diff --git a/package.json b/package.json index 231ce64..32ff017 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "@codemirror/lang-markdown": "^6.3.2", "@codemirror/merge": "^6.10.0", "@electric-sql/pglite": "0.2.14", + "@google/genai": "^1.2.0", "@google/generative-ai": "^0.21.0", "@langchain/core": "^0.3.26", "@lexical/clipboard": "^0.17.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 984ddcb..ba568cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@electric-sql/pglite': specifier: 0.2.14 version: 0.2.14 + '@google/genai': + specifier: ^1.2.0 + version: 1.2.0(@modelcontextprotocol/sdk@1.12.0) '@google/generative-ai': specifier: ^0.21.0 version: 0.21.0 @@ -561,8 +564,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.25.3': - resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} + '@esbuild/aix-ppc64@0.25.5': + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -585,8 +588,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.25.3': - resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} + '@esbuild/android-arm64@0.25.5': + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -609,8 +612,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.25.3': - resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} + '@esbuild/android-arm@0.25.5': + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -633,8 +636,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.25.3': - resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} + '@esbuild/android-x64@0.25.5': + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -657,8 +660,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.25.3': - resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} + '@esbuild/darwin-arm64@0.25.5': + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -681,8 +684,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.25.3': - resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} + '@esbuild/darwin-x64@0.25.5': + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -705,8 +708,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.25.3': - resolution: {integrity: sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==} + '@esbuild/freebsd-arm64@0.25.5': + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -729,8 +732,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.3': - resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} + '@esbuild/freebsd-x64@0.25.5': + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -753,8 +756,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.25.3': - resolution: {integrity: sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==} + '@esbuild/linux-arm64@0.25.5': + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -777,8 +780,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.25.3': - resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} + '@esbuild/linux-arm@0.25.5': + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -801,8 +804,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.25.3': - resolution: {integrity: sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==} + '@esbuild/linux-ia32@0.25.5': + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -825,8 +828,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.25.3': - resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} + '@esbuild/linux-loong64@0.25.5': + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -849,8 +852,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.25.3': - resolution: {integrity: sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==} + '@esbuild/linux-mips64el@0.25.5': + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -873,8 +876,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.25.3': - resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} + '@esbuild/linux-ppc64@0.25.5': + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -897,8 +900,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.25.3': - resolution: {integrity: sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==} + '@esbuild/linux-riscv64@0.25.5': + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -921,8 +924,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.25.3': - resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} + '@esbuild/linux-s390x@0.25.5': + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -945,14 +948,14 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.25.3': - resolution: {integrity: sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==} + '@esbuild/linux-x64@0.25.5': + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.3': - resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} + '@esbuild/netbsd-arm64@0.25.5': + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -975,14 +978,14 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.3': - resolution: {integrity: sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==} + '@esbuild/netbsd-x64@0.25.5': + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.3': - resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} + '@esbuild/openbsd-arm64@0.25.5': + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -1005,8 +1008,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.3': - resolution: {integrity: sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==} + '@esbuild/openbsd-x64@0.25.5': + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -1029,8 +1032,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.25.3': - resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} + '@esbuild/sunos-x64@0.25.5': + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -1053,8 +1056,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.25.3': - resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} + '@esbuild/win32-arm64@0.25.5': + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -1077,8 +1080,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.25.3': - resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} + '@esbuild/win32-ia32@0.25.5': + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -1101,8 +1104,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.25.3': - resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} + '@esbuild/win32-x64@0.25.5': + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1140,6 +1143,12 @@ packages: '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + '@google/genai@1.2.0': + resolution: {integrity: sha512-jAYhzG7UrLJxeQr5cfL87O4AcyEu+E7AA7MJDYPrDWI3Hl25EAdx5mA4AuNfSXZO31LnSyrIkEzkmJOAdlPKOA==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.11.0 + '@google/generative-ai@0.21.0': resolution: {integrity: sha512-7XhUbtnlkSEZK15kN3t+tzIMxsbKm/dSkKBFalj+20NvPKe1kBY7mR2P7vuijEn+f06z5+A8bVGKO0v39cr6Wg==} engines: {node: '>=18.0.0'} @@ -1407,6 +1416,10 @@ packages: '@marijn/find-cluster-break@1.0.2': resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + '@modelcontextprotocol/sdk@1.12.0': + resolution: {integrity: sha512-m//7RlINx1F3sz3KqwY1WWzVgTcYX52HYk4bJ1hkBXV3zccAEth+jRvG8DBRrdaQuRsPAJOx2MH3zaHNCKL7Zg==} + engines: {node: '>=18'} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -2665,6 +2678,10 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} @@ -2686,6 +2703,10 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} + agent-base@7.1.3: + resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} + engines: {node: '>= 14'} + agentkeepalive@4.6.0: resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} engines: {node: '>= 8.0.0'} @@ -2820,6 +2841,13 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + bignumber.js@9.3.0: + resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==} + + body-parser@2.2.0: + resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + engines: {node: '>=18'} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -2842,6 +2870,9 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -2852,6 +2883,10 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + cacheable@1.8.8: resolution: {integrity: sha512-OE1/jlarWxROUIpd0qGBSKFLkNsotY8pt4GeiVErUYh/NUeTNrT+SBksUgllQv4m6a0W/VZsLuiHb88maavqEw==} @@ -2969,12 +3004,32 @@ packages: console-table-printer@2.12.1: resolution: {integrity: sha512-wKGOQRRvdnd89pCeH96e2Fn4wkbenSP6LMHfjfyNLMbGuHEFbMqQNuxXqd0oXG9caIOQ1FTvc5Uijp9/4jujnQ==} + content-disposition@1.0.0: + resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -3092,6 +3147,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -3250,6 +3309,12 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -3265,6 +3330,10 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + entities@1.0.0: resolution: {integrity: sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==} @@ -3340,8 +3409,8 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.25.3: - resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==} + esbuild@0.25.5: + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} engines: {node: '>=18'} hasBin: true @@ -3349,6 +3418,9 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@2.0.0: resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} engines: {node: '>=8'} @@ -3486,6 +3558,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -3493,6 +3569,14 @@ packages: eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + eventsource-parser@3.0.2: + resolution: {integrity: sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -3508,6 +3592,16 @@ packages: exponential-backoff@3.1.2: resolution: {integrity: sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==} + express-rate-limit@7.5.0: + resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==} + engines: {node: '>= 16'} + peerDependencies: + express: ^4.11 || 5 || ^5.0.0-beta.1 + + express@5.1.0: + resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + engines: {node: '>= 18'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -3554,6 +3648,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@2.1.0: + resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} + engines: {node: '>= 0.8'} + find-cache-dir@3.3.2: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} engines: {node: '>=8'} @@ -3604,6 +3702,14 @@ packages: resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} engines: {node: '>= 12.20'} + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -3629,6 +3735,14 @@ packages: fuzzysort@3.1.0: resolution: {integrity: sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==} + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -3708,6 +3822,14 @@ packages: engines: {node: '>=0.6.0'} hasBin: true + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} + engines: {node: '>=14'} + + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -3721,6 +3843,10 @@ packages: groq-sdk@0.7.0: resolution: {integrity: sha512-OgPqrRtti5MjEVclR8sgBHrhSkTLdFCmi47yrEF29uJZaiCkX3s7bXpnMhq8Lwoe1f4AwgC0qGOeHXpeSgu5lg==} + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + handlebars@4.7.8: resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} engines: {node: '>=0.4.7'} @@ -3809,6 +3935,10 @@ packages: htmlparser2@3.7.3: resolution: {integrity: sha512-XdyuCBH3/tTuRTCMFolbj5stKZek8FK7KVXm+aHYivHmXVo18jINvc2jR5zgFkp//z2KWl5vppTJ4DWhltYruA==} + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} @@ -3817,6 +3947,10 @@ packages: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -3872,6 +4006,10 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} @@ -3982,6 +4120,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -4236,6 +4377,9 @@ packages: engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -4268,6 +4412,12 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.0: + resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -4498,10 +4648,18 @@ packages: mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + meow@13.2.0: resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -4601,10 +4759,18 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -4645,6 +4811,10 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -4719,6 +4889,10 @@ packages: '@codemirror/state': ^6.0.0 '@codemirror/view': ^6.0.0 + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -4806,6 +4980,10 @@ packages: parse5@7.2.1: resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -4821,6 +4999,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -4839,6 +5021,10 @@ packages: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} + pkce-challenge@5.0.0: + resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} + engines: {node: '>=16.20.0'} + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -4908,6 +5094,10 @@ packages: property-information@7.0.0: resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==} + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -4921,6 +5111,10 @@ packages: pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -4940,6 +5134,14 @@ packages: '@types/react-dom': optional: true + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@3.0.0: + resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} + engines: {node: '>= 0.8'} + react-contenteditable@3.3.7: resolution: {integrity: sha512-GA9NbC0DkDdpN3iGvib/OMHWTJzDX2cfkgy5Tt98JJAbA3kLnyrNbBIpsSpPpq7T8d3scD39DHP+j8mAM7BIfQ==} peerDependencies: @@ -5091,6 +5293,10 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -5098,6 +5304,9 @@ packages: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -5125,6 +5334,14 @@ packages: engines: {node: '>=10'} hasBin: true + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + engines: {node: '>= 18'} + + serve-static@2.2.0: + resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} + engines: {node: '>= 18'} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -5137,6 +5354,9 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -5212,6 +5432,10 @@ packages: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -5320,6 +5544,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + tough-cookie@4.1.4: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} @@ -5398,6 +5626,10 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -5453,6 +5685,10 @@ packages: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + update-browserslist-db@1.1.2: resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} hasBin: true @@ -5500,10 +5736,18 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + v8-to-istanbul@9.3.0: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + vfile-location@5.0.3: resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} @@ -6044,7 +6288,7 @@ snapshots: '@esbuild/aix-ppc64@0.19.12': optional: true - '@esbuild/aix-ppc64@0.25.3': + '@esbuild/aix-ppc64@0.25.5': optional: true '@esbuild/android-arm64@0.17.3': @@ -6056,7 +6300,7 @@ snapshots: '@esbuild/android-arm64@0.19.12': optional: true - '@esbuild/android-arm64@0.25.3': + '@esbuild/android-arm64@0.25.5': optional: true '@esbuild/android-arm@0.17.3': @@ -6068,7 +6312,7 @@ snapshots: '@esbuild/android-arm@0.19.12': optional: true - '@esbuild/android-arm@0.25.3': + '@esbuild/android-arm@0.25.5': optional: true '@esbuild/android-x64@0.17.3': @@ -6080,7 +6324,7 @@ snapshots: '@esbuild/android-x64@0.19.12': optional: true - '@esbuild/android-x64@0.25.3': + '@esbuild/android-x64@0.25.5': optional: true '@esbuild/darwin-arm64@0.17.3': @@ -6092,7 +6336,7 @@ snapshots: '@esbuild/darwin-arm64@0.19.12': optional: true - '@esbuild/darwin-arm64@0.25.3': + '@esbuild/darwin-arm64@0.25.5': optional: true '@esbuild/darwin-x64@0.17.3': @@ -6104,7 +6348,7 @@ snapshots: '@esbuild/darwin-x64@0.19.12': optional: true - '@esbuild/darwin-x64@0.25.3': + '@esbuild/darwin-x64@0.25.5': optional: true '@esbuild/freebsd-arm64@0.17.3': @@ -6116,7 +6360,7 @@ snapshots: '@esbuild/freebsd-arm64@0.19.12': optional: true - '@esbuild/freebsd-arm64@0.25.3': + '@esbuild/freebsd-arm64@0.25.5': optional: true '@esbuild/freebsd-x64@0.17.3': @@ -6128,7 +6372,7 @@ snapshots: '@esbuild/freebsd-x64@0.19.12': optional: true - '@esbuild/freebsd-x64@0.25.3': + '@esbuild/freebsd-x64@0.25.5': optional: true '@esbuild/linux-arm64@0.17.3': @@ -6140,7 +6384,7 @@ snapshots: '@esbuild/linux-arm64@0.19.12': optional: true - '@esbuild/linux-arm64@0.25.3': + '@esbuild/linux-arm64@0.25.5': optional: true '@esbuild/linux-arm@0.17.3': @@ -6152,7 +6396,7 @@ snapshots: '@esbuild/linux-arm@0.19.12': optional: true - '@esbuild/linux-arm@0.25.3': + '@esbuild/linux-arm@0.25.5': optional: true '@esbuild/linux-ia32@0.17.3': @@ -6164,7 +6408,7 @@ snapshots: '@esbuild/linux-ia32@0.19.12': optional: true - '@esbuild/linux-ia32@0.25.3': + '@esbuild/linux-ia32@0.25.5': optional: true '@esbuild/linux-loong64@0.17.3': @@ -6176,7 +6420,7 @@ snapshots: '@esbuild/linux-loong64@0.19.12': optional: true - '@esbuild/linux-loong64@0.25.3': + '@esbuild/linux-loong64@0.25.5': optional: true '@esbuild/linux-mips64el@0.17.3': @@ -6188,7 +6432,7 @@ snapshots: '@esbuild/linux-mips64el@0.19.12': optional: true - '@esbuild/linux-mips64el@0.25.3': + '@esbuild/linux-mips64el@0.25.5': optional: true '@esbuild/linux-ppc64@0.17.3': @@ -6200,7 +6444,7 @@ snapshots: '@esbuild/linux-ppc64@0.19.12': optional: true - '@esbuild/linux-ppc64@0.25.3': + '@esbuild/linux-ppc64@0.25.5': optional: true '@esbuild/linux-riscv64@0.17.3': @@ -6212,7 +6456,7 @@ snapshots: '@esbuild/linux-riscv64@0.19.12': optional: true - '@esbuild/linux-riscv64@0.25.3': + '@esbuild/linux-riscv64@0.25.5': optional: true '@esbuild/linux-s390x@0.17.3': @@ -6224,7 +6468,7 @@ snapshots: '@esbuild/linux-s390x@0.19.12': optional: true - '@esbuild/linux-s390x@0.25.3': + '@esbuild/linux-s390x@0.25.5': optional: true '@esbuild/linux-x64@0.17.3': @@ -6236,10 +6480,10 @@ snapshots: '@esbuild/linux-x64@0.19.12': optional: true - '@esbuild/linux-x64@0.25.3': + '@esbuild/linux-x64@0.25.5': optional: true - '@esbuild/netbsd-arm64@0.25.3': + '@esbuild/netbsd-arm64@0.25.5': optional: true '@esbuild/netbsd-x64@0.17.3': @@ -6251,10 +6495,10 @@ snapshots: '@esbuild/netbsd-x64@0.19.12': optional: true - '@esbuild/netbsd-x64@0.25.3': + '@esbuild/netbsd-x64@0.25.5': optional: true - '@esbuild/openbsd-arm64@0.25.3': + '@esbuild/openbsd-arm64@0.25.5': optional: true '@esbuild/openbsd-x64@0.17.3': @@ -6266,7 +6510,7 @@ snapshots: '@esbuild/openbsd-x64@0.19.12': optional: true - '@esbuild/openbsd-x64@0.25.3': + '@esbuild/openbsd-x64@0.25.5': optional: true '@esbuild/sunos-x64@0.17.3': @@ -6278,7 +6522,7 @@ snapshots: '@esbuild/sunos-x64@0.19.12': optional: true - '@esbuild/sunos-x64@0.25.3': + '@esbuild/sunos-x64@0.25.5': optional: true '@esbuild/win32-arm64@0.17.3': @@ -6290,7 +6534,7 @@ snapshots: '@esbuild/win32-arm64@0.19.12': optional: true - '@esbuild/win32-arm64@0.25.3': + '@esbuild/win32-arm64@0.25.5': optional: true '@esbuild/win32-ia32@0.17.3': @@ -6302,7 +6546,7 @@ snapshots: '@esbuild/win32-ia32@0.19.12': optional: true - '@esbuild/win32-ia32@0.25.3': + '@esbuild/win32-ia32@0.25.5': optional: true '@esbuild/win32-x64@0.17.3': @@ -6314,7 +6558,7 @@ snapshots: '@esbuild/win32-x64@0.19.12': optional: true - '@esbuild/win32-x64@0.25.3': + '@esbuild/win32-x64@0.25.5': optional: true '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)': @@ -6357,6 +6601,19 @@ snapshots: '@floating-ui/utils@0.2.9': {} + '@google/genai@1.2.0(@modelcontextprotocol/sdk@1.12.0)': + dependencies: + '@modelcontextprotocol/sdk': 1.12.0 + google-auth-library: 9.15.1 + ws: 8.18.0 + zod: 3.24.2 + zod-to-json-schema: 3.24.1(zod@3.24.2) + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + '@google/generative-ai@0.21.0': {} '@humanwhocodes/config-array@0.13.0': @@ -6847,6 +7104,22 @@ snapshots: '@marijn/find-cluster-break@1.0.2': {} + '@modelcontextprotocol/sdk@1.12.0': + dependencies: + ajv: 6.12.6 + content-type: 1.0.5 + cors: 2.8.5 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + express: 5.1.0 + express-rate-limit: 7.5.0(express@5.1.0) + pkce-challenge: 5.0.0 + raw-body: 3.0.0 + zod: 3.24.2 + zod-to-json-schema: 3.24.1(zod@3.24.2) + transitivePeerDependencies: + - supports-color + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -8209,6 +8482,11 @@ snapshots: dependencies: event-target-shim: 5.0.1 + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + acorn-globals@7.0.1: dependencies: acorn: 8.14.0 @@ -8230,6 +8508,8 @@ snapshots: transitivePeerDependencies: - supports-color + agent-base@7.1.3: {} + agentkeepalive@4.6.0: dependencies: humanize-ms: 1.2.1 @@ -8424,6 +8704,22 @@ snapshots: base64-js@1.5.1: {} + bignumber.js@9.3.0: {} + + body-parser@2.2.0: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.0 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 3.0.0 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -8452,6 +8748,8 @@ snapshots: dependencies: node-int64: 0.4.0 + buffer-equal-constant-time@1.0.1: {} + buffer-from@1.1.2: {} buffer@6.0.3: @@ -8461,6 +8759,8 @@ snapshots: builtin-modules@3.3.0: {} + bytes@3.1.2: {} + cacheable@1.8.8: dependencies: hookified: 1.7.1 @@ -8562,11 +8862,26 @@ snapshots: dependencies: simple-wcswidth: 1.0.1 + content-disposition@1.0.0: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + convert-source-map@2.0.0: {} + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + core-util-is@1.0.3: optional: true + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + cosmiconfig@9.0.0(typescript@4.9.5): dependencies: env-paths: 2.2.1 @@ -8678,6 +8993,8 @@ snapshots: delayed-stream@1.0.0: {} + depd@2.0.0: {} + dequal@2.0.3: {} detect-newline@3.1.0: {} @@ -8761,6 +9078,12 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + ejs@3.1.10: dependencies: jake: 10.9.2 @@ -8771,6 +9094,8 @@ snapshots: emoji-regex@8.0.0: {} + encodeurl@2.0.0: {} + entities@1.0.0: optional: true @@ -8888,7 +9213,7 @@ snapshots: esbuild-plugin-inline-worker@0.1.1: dependencies: - esbuild: 0.25.3 + esbuild: 0.25.5 find-cache-dir: 3.3.2 esbuild-register@3.6.0(esbuild@0.19.12): @@ -8974,36 +9299,38 @@ snapshots: '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 - esbuild@0.25.3: + esbuild@0.25.5: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.3 - '@esbuild/android-arm': 0.25.3 - '@esbuild/android-arm64': 0.25.3 - '@esbuild/android-x64': 0.25.3 - '@esbuild/darwin-arm64': 0.25.3 - '@esbuild/darwin-x64': 0.25.3 - '@esbuild/freebsd-arm64': 0.25.3 - '@esbuild/freebsd-x64': 0.25.3 - '@esbuild/linux-arm': 0.25.3 - '@esbuild/linux-arm64': 0.25.3 - '@esbuild/linux-ia32': 0.25.3 - '@esbuild/linux-loong64': 0.25.3 - '@esbuild/linux-mips64el': 0.25.3 - '@esbuild/linux-ppc64': 0.25.3 - '@esbuild/linux-riscv64': 0.25.3 - '@esbuild/linux-s390x': 0.25.3 - '@esbuild/linux-x64': 0.25.3 - '@esbuild/netbsd-arm64': 0.25.3 - '@esbuild/netbsd-x64': 0.25.3 - '@esbuild/openbsd-arm64': 0.25.3 - '@esbuild/openbsd-x64': 0.25.3 - '@esbuild/sunos-x64': 0.25.3 - '@esbuild/win32-arm64': 0.25.3 - '@esbuild/win32-ia32': 0.25.3 - '@esbuild/win32-x64': 0.25.3 + '@esbuild/aix-ppc64': 0.25.5 + '@esbuild/android-arm': 0.25.5 + '@esbuild/android-arm64': 0.25.5 + '@esbuild/android-x64': 0.25.5 + '@esbuild/darwin-arm64': 0.25.5 + '@esbuild/darwin-x64': 0.25.5 + '@esbuild/freebsd-arm64': 0.25.5 + '@esbuild/freebsd-x64': 0.25.5 + '@esbuild/linux-arm': 0.25.5 + '@esbuild/linux-arm64': 0.25.5 + '@esbuild/linux-ia32': 0.25.5 + '@esbuild/linux-loong64': 0.25.5 + '@esbuild/linux-mips64el': 0.25.5 + '@esbuild/linux-ppc64': 0.25.5 + '@esbuild/linux-riscv64': 0.25.5 + '@esbuild/linux-s390x': 0.25.5 + '@esbuild/linux-x64': 0.25.5 + '@esbuild/netbsd-arm64': 0.25.5 + '@esbuild/netbsd-x64': 0.25.5 + '@esbuild/openbsd-arm64': 0.25.5 + '@esbuild/openbsd-x64': 0.25.5 + '@esbuild/sunos-x64': 0.25.5 + '@esbuild/win32-arm64': 0.25.5 + '@esbuild/win32-ia32': 0.25.5 + '@esbuild/win32-x64': 0.25.5 escalade@3.2.0: {} + escape-html@1.0.3: {} + escape-string-regexp@2.0.0: {} escape-string-regexp@4.0.0: {} @@ -9194,10 +9521,18 @@ snapshots: esutils@2.0.3: {} + etag@1.8.1: {} + event-target-shim@5.0.1: {} eventemitter3@4.0.7: {} + eventsource-parser@3.0.2: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.0.2 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -9222,6 +9557,42 @@ snapshots: exponential-backoff@3.1.2: {} + express-rate-limit@7.5.0(express@5.1.0): + dependencies: + express: 5.1.0 + + express@5.1.0: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.0 + content-disposition: 1.0.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.0 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.0 + serve-static: 2.2.0 + statuses: 2.0.1 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + extend@3.0.2: {} fast-deep-equal@3.1.3: {} @@ -9270,6 +9641,17 @@ snapshots: dependencies: to-regex-range: 5.0.1 + finalhandler@2.1.0: + dependencies: + debug: 4.4.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + find-cache-dir@3.3.2: dependencies: commondir: 1.0.1 @@ -9322,6 +9704,10 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 4.0.0-beta.3 + forwarded@0.2.0: {} + + fresh@2.0.0: {} + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -9344,6 +9730,26 @@ snapshots: fuzzysort@3.1.0: {} + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@6.1.1: + dependencies: + gaxios: 6.7.1 + google-logging-utils: 0.0.2 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} @@ -9435,6 +9841,20 @@ snapshots: dependencies: minimist: 1.2.8 + google-auth-library@9.15.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.1 + gtoken: 7.1.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + google-logging-utils@0.0.2: {} + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -9453,6 +9873,14 @@ snapshots: transitivePeerDependencies: - encoding + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + handlebars@4.7.8: dependencies: minimist: 1.2.8 @@ -9594,6 +10022,14 @@ snapshots: readable-stream: 1.1.14 optional: true + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + http-proxy-agent@5.0.0: dependencies: '@tootallnate/once': 2.0.0 @@ -9609,6 +10045,13 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} humanize-ms@1.2.1: @@ -9656,6 +10099,8 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 + ipaddr.js@1.9.1: {} + is-alphabetical@1.0.4: {} is-alphabetical@2.0.1: {} @@ -9758,6 +10203,8 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} + is-regex@1.2.1: dependencies: call-bound: 1.0.3 @@ -10240,6 +10687,10 @@ snapshots: jsesc@3.1.0: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.0 + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} @@ -10265,6 +10716,17 @@ snapshots: object.assign: 4.1.7 object.values: 1.2.1 + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.0: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -10553,8 +11015,12 @@ snapshots: mdn-data@2.12.2: {} + media-typer@1.1.0: {} + meow@13.2.0: {} + merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -10757,10 +11223,16 @@ snapshots: mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + mimic-fn@2.1.0: {} minimatch@10.0.1: @@ -10791,6 +11263,8 @@ snapshots: natural-compare@1.4.0: {} + negotiator@1.0.0: {} + neo-async@2.6.2: {} neverthrow@6.2.2: {} @@ -10861,6 +11335,10 @@ snapshots: '@types/codemirror': 5.60.8 moment: 2.29.4 + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -10973,6 +11451,8 @@ snapshots: dependencies: entities: 4.5.0 + parseurl@1.3.3: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -10981,6 +11461,8 @@ snapshots: path-parse@1.0.7: {} + path-to-regexp@8.2.0: {} + path-type@4.0.0: {} path@0.12.7: @@ -10994,6 +11476,8 @@ snapshots: pirates@4.0.6: {} + pkce-challenge@5.0.0: {} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -11054,6 +11538,11 @@ snapshots: property-information@7.0.0: {} + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} psl@1.15.0: @@ -11064,6 +11553,10 @@ snapshots: pure-rand@6.1.0: {} + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + querystringify@2.2.0: {} queue-microtask@1.2.3: {} @@ -11130,6 +11623,15 @@ snapshots: '@types/react': 18.3.18 '@types/react-dom': 18.3.5(@types/react@18.3.18) + range-parser@1.2.1: {} + + raw-body@3.0.0: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + react-contenteditable@3.3.7(react@18.3.1): dependencies: fast-deep-equal: 3.1.3 @@ -11323,6 +11825,16 @@ snapshots: dependencies: glob: 7.2.3 + router@2.2.0: + dependencies: + debug: 4.4.0 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.2.0 + transitivePeerDependencies: + - supports-color + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -11335,6 +11847,8 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 + safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -11360,6 +11874,31 @@ snapshots: semver@7.7.1: {} + send@1.2.0: + dependencies: + debug: 4.4.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.0 + mime-types: 3.0.1 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.0: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.0 + transitivePeerDependencies: + - supports-color + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -11382,6 +11921,8 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.1 + setprototypeof@1.2.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -11464,6 +12005,8 @@ snapshots: dependencies: escape-string-regexp: 2.0.0 + statuses@2.0.1: {} + string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -11632,6 +12175,8 @@ snapshots: dependencies: is-number: 7.0.0 + toidentifier@1.0.1: {} + tough-cookie@4.1.4: dependencies: psl: 1.15.0 @@ -11699,6 +12244,12 @@ snapshots: type-fest@0.21.3: {} + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.1 + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.3 @@ -11781,6 +12332,8 @@ snapshots: universalify@0.2.0: {} + unpipe@1.0.0: {} + update-browserslist-db@1.1.2(browserslist@4.24.4): dependencies: browserslist: 4.24.4 @@ -11823,12 +12376,16 @@ snapshots: uuid@10.0.0: {} + uuid@9.0.1: {} + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.25 '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 + vary@1.1.2: {} + vfile-location@5.0.3: dependencies: '@types/unist': 3.0.3 diff --git a/src/constants.ts b/src/constants.ts index 85c2210..9d53df3 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -33,7 +33,7 @@ export const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1' export const GROK_BASE_URL = 'https://api.x.ai/v1' export const SILICONFLOW_BASE_URL = 'https://api.siliconflow.cn/v1' export const ALIBABA_QWEN_BASE_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1' -export const INFIO_BASE_URL = 'https://api.infio.com/api/raw_message' +export const INFIO_BASE_URL = 'https://api.infio.app' export const JINA_BASE_URL = 'https://r.jina.ai' export const SERPER_BASE_URL = 'https://serpapi.com/search' // Pricing in dollars per million tokens diff --git a/src/core/llm/gemini.ts b/src/core/llm/gemini.ts index 3103694..d51611b 100644 --- a/src/core/llm/gemini.ts +++ b/src/core/llm/gemini.ts @@ -1,11 +1,11 @@ import { Content, - EnhancedGenerateContentResponse, - GenerateContentResult, - GenerateContentStreamResult, - GoogleGenerativeAI, + GoogleGenAI, Part, -} from '@google/generative-ai' + type GenerateContentConfig, + type GenerateContentParameters, + type GenerateContentResponse, +} from "@google/genai" import { LLMModel } from '../../types/llm/model' import { @@ -18,6 +18,12 @@ import { LLMResponseNonStreaming, LLMResponseStreaming, } from '../../types/llm/response' +import { + GeminiModelId, + ModelInfo, + geminiDefaultModelId, + geminiModels +} from "../../utils/api" import { parseImageDataUrl } from '../../utils/image' import { BaseLLMProvider } from './base' @@ -34,12 +40,41 @@ import { * issues are resolved. */ export class GeminiProvider implements BaseLLMProvider { - private client: GoogleGenerativeAI + private client: GoogleGenAI private apiKey: string + private baseUrl: string - constructor(apiKey: string) { + constructor(apiKey: string, baseUrl?: string) { this.apiKey = apiKey - this.client = new GoogleGenerativeAI(apiKey) + this.baseUrl = baseUrl + this.client = new GoogleGenAI({ apiKey }) + } + + getModel(modelId: string) { + let id = modelId + let info: ModelInfo = geminiModels[id as GeminiModelId] + + if (id?.endsWith(":thinking")) { + id = id.slice(0, -":thinking".length) + + if (geminiModels[id as GeminiModelId]) { + info = geminiModels[id as GeminiModelId] + + return { + id, + info, + thinkingConfig: undefined, + maxOutputTokens: info.maxTokens ?? undefined, + } + } + } + + if (!info) { + id = geminiDefaultModelId + info = geminiModels[geminiDefaultModelId] + } + + return { id, info } } async generateResponse( @@ -53,6 +88,8 @@ export class GeminiProvider implements BaseLLMProvider { ) } + const { id: modelName, thinkingConfig, maxOutputTokens, info } = this.getModel(model.modelId) + const systemMessages = request.messages.filter((m) => m.role === 'system') const systemInstruction: string | undefined = systemMessages.length > 0 @@ -60,30 +97,26 @@ export class GeminiProvider implements BaseLLMProvider { : undefined try { - const model = this.client.getGenerativeModel({ - model: request.model, - generationConfig: { - maxOutputTokens: request.max_tokens, - temperature: request.temperature, - topP: request.top_p, - presencePenalty: request.presence_penalty, - frequencyPenalty: request.frequency_penalty, - }, - systemInstruction: systemInstruction, - }) - const result = await model.generateContent( - { - systemInstruction: systemInstruction, - contents: request.messages - .map((message) => GeminiProvider.parseRequestMessage(message)) - .filter((m): m is Content => m !== null), - }, - { - signal: options?.signal, - }, - ) + const config: GenerateContentConfig = { + systemInstruction, + httpOptions: this.baseUrl ? { baseUrl: this.baseUrl } : undefined, + thinkingConfig, + maxOutputTokens: maxOutputTokens ?? request.max_tokens, + temperature: request.temperature ?? 0, + topP: request.top_p ?? 1, + presencePenalty: request.presence_penalty ?? 0, + frequencyPenalty: request.frequency_penalty ?? 0, + } + const params: GenerateContentParameters = { + model: modelName, + contents: request.messages + .map((message) => GeminiProvider.parseRequestMessage(message)) + .filter((m): m is Content => m !== null), + config, + } + const result = await this.client.models.generateContent(params) const messageId = crypto.randomUUID() // Gemini does not return a message id return GeminiProvider.parseNonStreamingResponse( result, @@ -115,6 +148,7 @@ export class GeminiProvider implements BaseLLMProvider { `Gemini API key is missing. Please set it in settings menu.`, ) } + const { id: modelName, thinkingConfig, maxOutputTokens, info } = this.getModel(model.modelId) const systemMessages = request.messages.filter((m) => m.role === 'system') const systemInstruction: string | undefined = @@ -123,30 +157,25 @@ export class GeminiProvider implements BaseLLMProvider { : undefined try { - const model = this.client.getGenerativeModel({ - model: request.model, - generationConfig: { - maxOutputTokens: request.max_tokens, - temperature: request.temperature, - topP: request.top_p, - presencePenalty: request.presence_penalty, - frequencyPenalty: request.frequency_penalty, - }, - systemInstruction: systemInstruction, - }) - - const stream = await model.generateContentStream( - { - systemInstruction: systemInstruction, - contents: request.messages - .map((message) => GeminiProvider.parseRequestMessage(message)) - .filter((m): m is Content => m !== null), - }, - { - signal: options?.signal, - }, - ) + const config: GenerateContentConfig = { + systemInstruction, + httpOptions: this.baseUrl ? { baseUrl: this.baseUrl } : undefined, + thinkingConfig, + maxOutputTokens: maxOutputTokens ?? request.max_tokens, + temperature: request.temperature ?? 0, + topP: request.top_p ?? 1, + presencePenalty: request.presence_penalty ?? 0, + frequencyPenalty: request.frequency_penalty ?? 0, + } + const params: GenerateContentParameters = { + model: modelName, + contents: request.messages + .map((message) => GeminiProvider.parseRequestMessage(message)) + .filter((m): m is Content => m !== null), + config, + } + const stream = await this.client.models.generateContentStream(params) const messageId = crypto.randomUUID() // Gemini does not return a message id return this.streamResponseGenerator(stream, request.model, messageId) } catch (error) { @@ -165,11 +194,11 @@ export class GeminiProvider implements BaseLLMProvider { } private async *streamResponseGenerator( - stream: GenerateContentStreamResult, + stream: AsyncGenerator, model: string, messageId: string, ): AsyncIterable { - for await (const chunk of stream.stream) { + for await (const chunk of stream) { yield GeminiProvider.parseStreamingResponseChunk(chunk, model, messageId) } } @@ -215,7 +244,7 @@ export class GeminiProvider implements BaseLLMProvider { } static parseNonStreamingResponse( - response: GenerateContentResult, + response: GenerateContentResponse, model: string, messageId: string, ): LLMResponseNonStreaming { @@ -224,9 +253,9 @@ export class GeminiProvider implements BaseLLMProvider { choices: [ { finish_reason: - response.response.candidates?.[0]?.finishReason ?? null, + response.candidates?.[0]?.finishReason ?? null, message: { - content: response.response.text(), + content: response.candidates?.[0]?.content?.parts?.[0]?.text ?? '', role: 'assistant', }, }, @@ -234,29 +263,32 @@ export class GeminiProvider implements BaseLLMProvider { created: Date.now(), model: model, object: 'chat.completion', - usage: response.response.usageMetadata + usage: response.usageMetadata ? { - prompt_tokens: response.response.usageMetadata.promptTokenCount, + prompt_tokens: response.usageMetadata.promptTokenCount, completion_tokens: - response.response.usageMetadata.candidatesTokenCount, - total_tokens: response.response.usageMetadata.totalTokenCount, + response.usageMetadata.candidatesTokenCount, + total_tokens: response.usageMetadata.totalTokenCount, } : undefined, } } static parseStreamingResponseChunk( - chunk: EnhancedGenerateContentResponse, + chunk: GenerateContentResponse, model: string, messageId: string, ): LLMResponseStreaming { + const firstCandidate = chunk.candidates?.[0] + const textContent = firstCandidate?.content?.parts?.[0]?.text || '' + return { id: messageId, choices: [ { - finish_reason: chunk.candidates?.[0]?.finishReason ?? null, + finish_reason: firstCandidate?.finishReason ?? null, delta: { - content: chunk.text(), + content: textContent, }, }, ], diff --git a/src/core/llm/infio.ts b/src/core/llm/infio.ts deleted file mode 100644 index 328eae1..0000000 --- a/src/core/llm/infio.ts +++ /dev/null @@ -1,251 +0,0 @@ -import OpenAI from 'openai' -import { - ChatCompletion, - ChatCompletionChunk, -} from 'openai/resources/chat/completions' - -import { INFIO_BASE_URL } from '../../constants' -import { LLMModel } from '../../types/llm/model' -import { - LLMRequestNonStreaming, - LLMRequestStreaming, - RequestMessage -} from '../../types/llm/request' -import { - LLMResponseNonStreaming, - LLMResponseStreaming, -} from '../../types/llm/response' - -import { BaseLLMProvider } from './base' -import { - LLMAPIKeyInvalidException, - LLMAPIKeyNotSetException, -} from './exception' - -export type RangeFilter = { - gte?: number; - lte?: number; -} - -export type ChunkFilter = { - field: string; - match_all?: string[]; - range?: RangeFilter; -} - -/** - * Interface for making requests to the Infio API - */ -export type InfioRequest = { - /** Required: The content of the user message to attach to the topic and then generate an assistant message in response to */ - messages: RequestMessage[]; - // /** Required: The ID of the topic to attach the message to */ - // topic_id: string; - /** Optional: URLs to include */ - links?: string[]; - /** Optional: Files to include */ - files?: string[]; - /** Optional: Whether to highlight results in chunk_html. Default is true */ - highlight_results?: boolean; - /** Optional: Delimiters for highlighting citations. Default is [".", "!", "?", "\n", "\t", ","] */ - highlight_delimiters?: string[]; - /** Optional: Search type - "semantic", "fulltext", or "hybrid". Default is "hybrid" */ - search_type?: string; - /** Optional: Filters for chunk filtering */ - filters?: ChunkFilter; - /** Optional: Whether to use web search API. Default is false */ - use_web_search?: boolean; - /** Optional: LLM model to use */ - llm_model?: string; - /** Optional: Force source */ - force_source?: string; - /** Optional: Whether completion should come before chunks in stream. Default is false */ - completion_first?: boolean; - /** Optional: Whether to stream the response. Default is true */ - stream_response?: boolean; - /** Optional: Sampling temperature between 0 and 2. Default is 0.5 */ - temperature?: number; - /** Optional: Frequency penalty between -2.0 and 2.0. Default is 0.7 */ - frequency_penalty?: number; - /** Optional: Presence penalty between -2.0 and 2.0. Default is 0.7 */ - presence_penalty?: number; - /** Optional: Maximum tokens to generate */ - max_tokens?: number; - /** Optional: Stop tokens (up to 4 sequences) */ - stop_tokens?: string[]; -} - -export class InfioProvider implements BaseLLMProvider { - // private adapter: OpenAIMessageAdapter - // private client: OpenAI - private apiKey: string - private baseUrl: string - - constructor(apiKey: string) { - // this.client = new OpenAI({ apiKey, dangerouslyAllowBrowser: true }) - // this.adapter = new OpenAIMessageAdapter() - this.apiKey = apiKey - this.baseUrl = INFIO_BASE_URL - } - - async generateResponse( - model: LLMModel, - request: LLMRequestNonStreaming, - // options?: LLMOptions, - ): Promise { - if (!this.apiKey) { - throw new LLMAPIKeyNotSetException( - 'OpenAI API key is missing. Please set it in settings menu.', - ) - } - try { - const req: InfioRequest = { - messages: request.messages, - stream_response: false, - temperature: request.temperature, - frequency_penalty: request.frequency_penalty, - presence_penalty: request.presence_penalty, - max_tokens: request.max_tokens, - } - const req_options = { - method: 'POST', - headers: { - Authorization: this.apiKey, - "TR-Dataset": "74aaec22-0cf0-4cba-80a5-ae5c0518344e", - 'Content-Type': 'application/json' - }, - body: JSON.stringify(req) - }; - - const response = await fetch(this.baseUrl, req_options); - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - const data = await response.json() as ChatCompletion; - return InfioProvider.parseNonStreamingResponse(data); - } catch (error) { - if (error instanceof OpenAI.AuthenticationError) { - throw new LLMAPIKeyInvalidException( - 'OpenAI API key is invalid. Please update it in settings menu.', - ) - } - throw error - } - } - - async streamResponse( - model: LLMModel, - request: LLMRequestStreaming, - ): Promise> { - if (!this.apiKey) { - throw new LLMAPIKeyNotSetException( - 'OpenAI API key is missing. Please set it in settings menu.', - ) - } - - try { - const req: InfioRequest = { - llm_model: request.model, - messages: request.messages, - stream_response: true, - temperature: request.temperature, - frequency_penalty: request.frequency_penalty, - presence_penalty: request.presence_penalty, - max_tokens: request.max_tokens, - } - const req_options = { - method: 'POST', - headers: { - Authorization: this.apiKey, - "TR-Dataset": "74aaec22-0cf0-4cba-80a5-ae5c0518344e", - "Content-Type": "application/json" - }, - body: JSON.stringify(req) - }; - - const response = await fetch(this.baseUrl, req_options); - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - if (!response.body) { - throw new Error('Response body is null'); - } - - const reader = response.body.getReader(); - const decoder = new TextDecoder(); - - return { - [Symbol.asyncIterator]: async function* () { - try { - while (true) { - const { done, value } = await reader.read(); - if (done) break; - - const chunk = decoder.decode(value); - const lines = chunk.split('\n').filter(line => line.trim()); - - for (const line of lines) { - if (line.startsWith('data: ')) { - const jsonData = JSON.parse(line.slice(6)) as ChatCompletionChunk; - if (!jsonData || typeof jsonData !== 'object' || !('choices' in jsonData)) { - throw new Error('Invalid chunk format received'); - } - yield InfioProvider.parseStreamingResponseChunk(jsonData); - } - } - } - } finally { - reader.releaseLock(); - } - } - }; - } catch (error) { - if (error instanceof OpenAI.AuthenticationError) { - throw new LLMAPIKeyInvalidException( - 'OpenAI API key is invalid. Please update it in settings menu.', - ) - } - throw error - } - } - - static parseNonStreamingResponse( - response: ChatCompletion, - ): LLMResponseNonStreaming { - return { - id: response.id, - choices: response.choices.map((choice) => ({ - finish_reason: choice.finish_reason, - message: { - content: choice.message.content, - role: choice.message.role, - }, - })), - created: response.created, - model: response.model, - object: 'chat.completion', - system_fingerprint: response.system_fingerprint, - usage: response.usage, - } - } - - static parseStreamingResponseChunk( - chunk: ChatCompletionChunk, - ): LLMResponseStreaming { - return { - id: chunk.id, - choices: chunk.choices.map((choice) => ({ - finish_reason: choice.finish_reason ?? null, - delta: { - content: choice.delta.content ?? null, - role: choice.delta.role, - }, - })), - created: chunk.created, - model: chunk.model, - object: 'chat.completion.chunk', - system_fingerprint: chunk.system_fingerprint, - usage: chunk.usage ?? undefined, - } - } -} diff --git a/src/core/llm/manager.ts b/src/core/llm/manager.ts index bdaac2d..a9ed5b6 100644 --- a/src/core/llm/manager.ts +++ b/src/core/llm/manager.ts @@ -1,4 +1,4 @@ -import { ALIBABA_QWEN_BASE_URL, DEEPSEEK_BASE_URL, GROK_BASE_URL, OPENROUTER_BASE_URL, SILICONFLOW_BASE_URL } from '../../constants' +import { ALIBABA_QWEN_BASE_URL, DEEPSEEK_BASE_URL, GROK_BASE_URL, INFIO_BASE_URL, OPENROUTER_BASE_URL, SILICONFLOW_BASE_URL } from '../../constants' import { ApiProvider, LLMModel } from '../../types/llm/model' import { LLMOptions, @@ -14,7 +14,6 @@ import { InfioSettings } from '../../types/settings' import { AnthropicProvider } from './anthropic' import { GeminiProvider } from './gemini' import { GroqProvider } from './groq' -import { InfioProvider } from './infio' import { OllamaProvider } from './ollama' import { OpenAIAuthenticatedProvider } from './openai' import { OpenAICompatibleProvider } from './openai-compatible' @@ -40,7 +39,7 @@ class LLMManager implements LLMManagerInterface { private googleProvider: GeminiProvider private groqProvider: GroqProvider private grokProvider: OpenAICompatibleProvider - private infioProvider: InfioProvider + private infioProvider: OpenAICompatibleProvider private openrouterProvider: OpenAICompatibleProvider private siliconflowProvider: OpenAICompatibleProvider private alibabaQwenProvider: OpenAICompatibleProvider @@ -49,7 +48,10 @@ class LLMManager implements LLMManagerInterface { private isInfioEnabled: boolean constructor(settings: InfioSettings) { - this.infioProvider = new InfioProvider(settings.infioProvider.apiKey) + this.infioProvider = new OpenAICompatibleProvider( + settings.infioProvider.apiKey, + INFIO_BASE_URL + ) this.openrouterProvider = new OpenAICompatibleProvider( settings.openrouterProvider.apiKey, settings.openrouterProvider.baseUrl && settings.openrouterProvider.useCustomUrl ? @@ -93,14 +95,14 @@ class LLMManager implements LLMManagerInterface { request: LLMRequestNonStreaming, options?: LLMOptions, ): Promise { - if (this.isInfioEnabled) { - return await this.infioProvider.generateResponse( - model, - request, - ) - } - // use custom provider + console.log("model", model) switch (model.provider) { + case ApiProvider.Infio: + return await this.infioProvider.generateResponse( + model, + request, + options, + ) case ApiProvider.OpenRouter: return await this.openrouterProvider.generateResponse( model, @@ -169,11 +171,9 @@ class LLMManager implements LLMManagerInterface { request: LLMRequestStreaming, options?: LLMOptions, ): Promise> { - if (this.isInfioEnabled) { - return await this.infioProvider.streamResponse(model, request) - } - // use custom provider switch (model.provider) { + case ApiProvider.Infio: + return await this.infioProvider.streamResponse(model, request, options) case ApiProvider.OpenRouter: return await this.openrouterProvider.streamResponse(model, request, options) case ApiProvider.SiliconFlow: diff --git a/src/settings/components/ModelProviderSettings.tsx b/src/settings/components/ModelProviderSettings.tsx index 6c61393..e53c540 100644 --- a/src/settings/components/ModelProviderSettings.tsx +++ b/src/settings/components/ModelProviderSettings.tsx @@ -171,6 +171,7 @@ const CustomProviderSettings: React.FC = ({ plugin,
= ({ plugin,
= ({ plugin,
void; }; @@ -157,6 +159,7 @@ export const ComboBoxComponent: React.FC = ({ name, provider, modelId, + settings = null, isEmbedding = false, updateModel, }) => { @@ -177,7 +180,7 @@ export const ComboBoxComponent: React.FC = ({ const fetchModelIds = async () => { const ids = isEmbedding ? GetEmbeddingProviderModelIds(modelProvider) - : await GetProviderModelIds(modelProvider); + : await GetProviderModelIds(modelProvider, settings); setModelIds(ids); }; diff --git a/src/utils/api.ts b/src/utils/api.ts index 5ba504c..c3f33b1 100644 --- a/src/utils/api.ts +++ b/src/utils/api.ts @@ -1,5 +1,6 @@ -import { OPENROUTER_BASE_URL } from '../constants' +import { INFIO_BASE_URL, OPENROUTER_BASE_URL } from '../constants' import { ApiProvider } from '../types/llm/model' +import { InfioSettings } from '../types/settings' export interface ModelInfo { maxTokens?: number @@ -14,6 +15,15 @@ export interface ModelInfo { description?: string reasoningEffort?: string, thinking?: boolean + maxThinkingTokens?: number + supportsReasoningBudget?: boolean + requiredReasoningBudget?: boolean + tiers?: readonly { + readonly contextWindow: number, + readonly inputPrice: number, + readonly outputPrice: number, + readonly cacheReadsPrice: number, + }[] } export interface EmbeddingModelInfo { @@ -21,89 +31,13 @@ export interface EmbeddingModelInfo { description?: string } -// Infio -// https://infio.app/pricing -export type InfioModelId = keyof typeof infioModels -export const infioDefaultModelId: InfioModelId = "deepseek-chat" -export const infioModels = { - "deepseek-chat": { - maxTokens: 8_000, - contextWindow: 64_000, - supportsImages: false, - supportsPromptCache: true, // supports context caching, but not in the way anthropic does it (deepseek reports input tokens and reads/writes in the same usage report) FIXME: we need to show users cache stats how deepseek does it - inputPrice: 0, // technically there is no input price, it's all either a cache hit or miss (ApiOptions will not show this) - outputPrice: 0.28, - cacheWritesPrice: 0.14, - cacheReadsPrice: 0.014, - }, - "deepseek-reasoner": { - maxTokens: 8_000, - contextWindow: 64_000, - supportsImages: false, - supportsPromptCache: true, // supports context caching, but not in the way anthropic does it (deepseek reports input tokens and reads/writes in the same usage report) FIXME: we need to show users cache stats how deepseek does it - inputPrice: 0, // technically there is no input price, it's all either a cache hit or miss (ApiOptions will not show this) - outputPrice: 2.19, - cacheWritesPrice: 0.55, - cacheReadsPrice: 0.14, - }, - "o3-mini": { - maxTokens: 100_000, - contextWindow: 200_000, - supportsImages: false, - supportsPromptCache: false, - inputPrice: 1.1, - outputPrice: 4.4, - }, - // don't support tool use yet - o1: { - maxTokens: 100_000, - contextWindow: 200_000, - supportsImages: true, - supportsPromptCache: false, - inputPrice: 15, - outputPrice: 60, - }, - "o1-preview": { - maxTokens: 32_768, - contextWindow: 128_000, - supportsImages: true, - supportsPromptCache: false, - inputPrice: 15, - outputPrice: 60, - }, - "o1-mini": { - maxTokens: 65_536, - contextWindow: 128_000, - supportsImages: true, - supportsPromptCache: false, - inputPrice: 1.1, - outputPrice: 4.4, - }, - "gpt-4o": { - maxTokens: 4_096, - contextWindow: 128_000, - supportsImages: true, - supportsPromptCache: false, - inputPrice: 2.5, - outputPrice: 10, - }, - "gpt-4o-mini": { - maxTokens: 16_384, - contextWindow: 128_000, - supportsImages: true, - supportsPromptCache: false, - inputPrice: 0.15, - outputPrice: 0.6, - }, -} as const satisfies Record - // Anthropic // https://docs.anthropic.com/en/docs/about-claude/models export type AnthropicModelId = keyof typeof anthropicModels -export const anthropicDefaultModelId: AnthropicModelId = "claude-3-7-sonnet-20250219" +export const anthropicDefaultModelId: AnthropicModelId = "claude-sonnet-4-20250514" export const anthropicModels = { - "claude-3-7-sonnet-20250219:thinking": { - maxTokens: 128_000, + "claude-sonnet-4-20250514": { + maxTokens: 64_000, // Overridden to 8k if `enableReasoningEffort` is false. contextWindow: 200_000, supportsImages: true, supportsComputerUse: true, @@ -112,10 +46,35 @@ export const anthropicModels = { outputPrice: 15.0, // $15 per million output tokens cacheWritesPrice: 3.75, // $3.75 per million tokens cacheReadsPrice: 0.3, // $0.30 per million tokens - thinking: true, + supportsReasoningBudget: true, + }, + "claude-opus-4-20250514": { + maxTokens: 32_000, // Overridden to 8k if `enableReasoningEffort` is false. + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 15.0, // $15 per million input tokens + outputPrice: 75.0, // $75 per million output tokens + cacheWritesPrice: 18.75, // $18.75 per million tokens + cacheReadsPrice: 1.5, // $1.50 per million tokens + supportsReasoningBudget: true, + }, + "claude-3-7-sonnet-20250219:thinking": { + maxTokens: 128_000, // Unlocked by passing `beta` flag to the model. Otherwise, it's 64k. + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 3.0, // $3 per million input tokens + outputPrice: 15.0, // $15 per million output tokens + cacheWritesPrice: 3.75, // $3.75 per million tokens + cacheReadsPrice: 0.3, // $0.30 per million tokens + supportsReasoningBudget: true, + requiredReasoningBudget: true, }, "claude-3-7-sonnet-20250219": { - maxTokens: 8192, + maxTokens: 8192, // Since we already have a `:thinking` virtual model we aren't setting `supportsReasoningBudget: true` here. contextWindow: 200_000, supportsImages: true, supportsComputerUse: true, @@ -124,7 +83,6 @@ export const anthropicModels = { outputPrice: 15.0, // $15 per million output tokens cacheWritesPrice: 3.75, // $3.75 per million tokens cacheReadsPrice: 0.3, // $0.30 per million tokens - thinking: false, }, "claude-3-5-sonnet-20241022": { maxTokens: 8192, @@ -167,10 +125,71 @@ export const anthropicModels = { cacheWritesPrice: 0.3, cacheReadsPrice: 0.03, }, -} as const satisfies Record +} as const satisfies Record // as const assertion makes the object + +// Infio +export const infioDefaultModelId = "deepseek/deepseek-v3" // will always exist +export const infioDefaultModelInfo: ModelInfo = { + maxTokens: 8192, + contextWindow: 65_536, + supportsImages: false, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 0.272, + outputPrice: 1.088, + cacheWritesPrice: 0.14, + cacheReadsPrice: 0.014, +} +let infioModelsCache: Record | null = null; + +async function fetchInfioModels(apiKey?: string): Promise> { + if (infioModelsCache) { + return infioModelsCache; + } + + try { + const headers: Record = { + 'Content-Type': 'application/json' + }; + + // 添加Authorization请求头,使用Bearer格式,如果有API密钥的话 + if (apiKey) { + headers['Authorization'] = `Bearer ${apiKey}`; + } + + const response = await fetch(INFIO_BASE_URL + "/model_group/info", { + method: 'GET', + headers: headers + }); + const data = await response.json(); + const models: Record = {}; + if (data?.data) { + for (const model of data.data) { + models[model.model_group] = { + maxTokens: model.max_output_tokens, + contextWindow: model.max_input_tokens, + supportsImages: false, + supportsPromptCache: false, + inputPrice: model.input_cost_per_token ? model.input_cost_per_token * 1000000 : 0, + outputPrice: model.output_cost_per_token ? model.output_cost_per_token * 1000000 : 0, + }; + } + } + + infioModelsCache = models; + return models; + } catch (error) { + console.error('Failed to fetch Infio models:', error); + // 如果出错,返回默认模型 + return { + [infioDefaultModelId]: infioDefaultModelInfo + }; + } +} + // OpenRouter // https://openrouter.ai/models?order=newest&supported_parameters=tools -export const openRouterDefaultModelId = "anthropic/claude-3.5-sonnet" // will always exist in openRouterModels +export const openRouterDefaultModelId = "anthropic/claude-sonnet-4" // will always exist in openRouterModels export const openRouterDefaultModelInfo: ModelInfo = { maxTokens: 8192, contextWindow: 200_000, @@ -222,8 +241,31 @@ async function fetchOpenRouterModels(): Promise> { // Gemini // https://ai.google.dev/gemini-api/docs/models/gemini export type GeminiModelId = keyof typeof geminiModels -export const geminiDefaultModelId: GeminiModelId = "gemini-2.5-flash-preview-04-17" +export const geminiDefaultModelId: GeminiModelId = "gemini-2.5-flash-preview-05-20" export const geminiModels = { + "gemini-2.5-flash-preview-05-20:thinking": { + maxTokens: 65_535, + contextWindow: 1_048_576, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.15, + outputPrice: 3.5, + cacheReadsPrice: 0.0375, + cacheWritesPrice: 1.0, + maxThinkingTokens: 24_576, + supportsReasoningBudget: true, + requiredReasoningBudget: true, + }, + "gemini-2.5-flash-preview-05-20": { + maxTokens: 65_535, + contextWindow: 1_048_576, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.15, + outputPrice: 0.6, + cacheReadsPrice: 0.0375, + cacheWritesPrice: 1.0, + }, "gemini-2.5-flash-preview-04-17:thinking": { maxTokens: 65_535, contextWindow: 1_048_576, @@ -231,8 +273,9 @@ export const geminiModels = { supportsPromptCache: false, inputPrice: 0.15, outputPrice: 3.5, - thinking: true, - // maxThinkingTokens: 24_576, + maxThinkingTokens: 24_576, + supportsReasoningBudget: true, + requiredReasoningBudget: true, }, "gemini-2.5-flash-preview-04-17": { maxTokens: 65_535, @@ -241,7 +284,6 @@ export const geminiModels = { supportsPromptCache: false, inputPrice: 0.15, outputPrice: 0.6, - thinking: false, }, "gemini-2.5-pro-exp-03-25": { maxTokens: 65_535, @@ -260,6 +302,44 @@ export const geminiModels = { outputPrice: 15, cacheReadsPrice: 0.625, cacheWritesPrice: 4.5, + tiers: [ + { + contextWindow: 200_000, + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.31, + }, + { + contextWindow: Infinity, + inputPrice: 2.5, + outputPrice: 15, + cacheReadsPrice: 0.625, + }, + ], + }, + "gemini-2.5-pro-preview-05-06": { + maxTokens: 65_535, + contextWindow: 1_048_576, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 2.5, // This is the pricing for prompts above 200k tokens. + outputPrice: 15, + cacheReadsPrice: 0.625, + cacheWritesPrice: 4.5, + tiers: [ + { + contextWindow: 200_000, + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.31, + }, + { + contextWindow: Infinity, + inputPrice: 2.5, + outputPrice: 15, + cacheReadsPrice: 0.625, + }, + ], }, "gemini-2.0-flash-001": { maxTokens: 8192, @@ -315,9 +395,25 @@ export const geminiModels = { maxTokens: 8192, contextWindow: 1_048_576, supportsImages: true, - supportsPromptCache: false, - inputPrice: 0, - outputPrice: 0, + supportsPromptCache: true, + inputPrice: 0.15, // This is the pricing for prompts above 128k tokens. + outputPrice: 0.6, + cacheReadsPrice: 0.0375, + cacheWritesPrice: 1.0, + tiers: [ + { + contextWindow: 128_000, + inputPrice: 0.075, + outputPrice: 0.3, + cacheReadsPrice: 0.01875, + }, + { + contextWindow: Infinity, + inputPrice: 0.15, + outputPrice: 0.6, + cacheReadsPrice: 0.0375, + }, + ], }, "gemini-1.5-flash-exp-0827": { maxTokens: 8192, @@ -360,6 +456,7 @@ export const geminiModels = { outputPrice: 0, }, } as const satisfies Record + export const geminiEmbeddingModels = { "text-embedding-004": { dimensions: 768, @@ -482,8 +579,8 @@ export const deepSeekModels = { contextWindow: 64_000, supportsImages: false, supportsPromptCache: true, // supports context caching, but not in the way anthropic does it (deepseek reports input tokens and reads/writes in the same usage report) FIXME: we need to show users cache stats how deepseek does it - inputPrice: 0, // technically there is no input price, it's all either a cache hit or miss (ApiOptions will not show this) - outputPrice: 0.28, + inputPrice: 0.272, // technically there is no input price, it's all either a cache hit or miss (ApiOptions will not show this) + outputPrice: 1.088, cacheWritesPrice: 0.14, cacheReadsPrice: 0.014, }, @@ -1505,10 +1602,46 @@ export const GetEmbeddingProviders = (): ApiProvider[] => { } // Get all models for a provider -export const GetProviderModels = async (provider: ApiProvider): Promise> => { +export const GetProviderModels = async (provider: ApiProvider, settings?: InfioSettings): Promise> => { switch (provider) { - case ApiProvider.Infio: - return infioModels + case ApiProvider.Infio: { + const apiKey = settings?.infioProvider?.apiKey + return await fetchInfioModels(apiKey) + } + case ApiProvider.OpenRouter: + return await fetchOpenRouterModels() + case ApiProvider.OpenAI: + return openAiNativeModels + case ApiProvider.AlibabaQwen: + return qwenModels + case ApiProvider.SiliconFlow: + return siliconFlowModels + case ApiProvider.Anthropic: + return anthropicModels + case ApiProvider.Deepseek: + return deepSeekModels + case ApiProvider.Google: + return geminiModels + case ApiProvider.Groq: + return groqModels + case ApiProvider.Grok: + return grokModels + case ApiProvider.Ollama: + return {} + case ApiProvider.OpenAICompatible: + return {} + default: + return {} + } +} + +// Get all models for a provider with settings (needed for providers that require API keys) +export const GetProviderModelsWithSettings = async (provider: ApiProvider, settings?: InfioSettings): Promise> => { + switch (provider) { + case ApiProvider.Infio: { + const apiKey = settings?.infioProvider?.apiKey + return await fetchInfioModels(apiKey) + } case ApiProvider.OpenRouter: return await fetchOpenRouterModels() case ApiProvider.OpenAI: @@ -1537,8 +1670,8 @@ export const GetProviderModels = async (provider: ApiProvider): Promise => { - const models = await GetProviderModels(provider) +export const GetProviderModelIds = async (provider: ApiProvider, settings?: InfioSettings): Promise => { + const models = await GetProviderModels(provider, settings) return Object.keys(models) }