mirror of
https://github.com/geoffsee/open-gsio.git
synced 2025-09-08 22:56:46 +00:00
Enable tool-based message generation in chat-stream-provider
and add BasicValueTool
and WeatherTool
.
Updated dependencies to latest versions in `bun.lock`. Modified development script in `package.json` to include watch mode.
This commit is contained in:

committed by
Geoff Seemueller

parent
de968bcfbd
commit
06b6a68b9b
18
bun.lock
18
bun.lock
@@ -66,7 +66,7 @@
|
|||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
"react-streaming": "^0.3.44",
|
"react-streaming": "^0.4.2",
|
||||||
"react-textarea-autosize": "^8.5.5",
|
"react-textarea-autosize": "^8.5.5",
|
||||||
"shiki": "^1.24.0",
|
"shiki": "^1.24.0",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.7.2",
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
"bun": "^1.2.17",
|
"bun": "^1.2.17",
|
||||||
"bun-sqlite-key-value": "^1.13.1",
|
"bun-sqlite-key-value": "^1.13.1",
|
||||||
"chokidar": "^4.0.1",
|
"chokidar": "^4.0.1",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^17.0.0",
|
||||||
"itty-router": "^5.0.18",
|
"itty-router": "^5.0.18",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^24.0.0",
|
||||||
"mobx": "^6.13.5",
|
"mobx": "^6.13.5",
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
"@vitest/ui": "^3.1.4",
|
"@vitest/ui": "^3.1.4",
|
||||||
"bun-sqlite-key-value": "^1.13.1",
|
"bun-sqlite-key-value": "^1.13.1",
|
||||||
"chokidar": "^4.0.1",
|
"chokidar": "^4.0.1",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^17.0.0",
|
||||||
"itty-router": "^5.0.18",
|
"itty-router": "^5.0.18",
|
||||||
"jsdom": "^24.0.0",
|
"jsdom": "^24.0.0",
|
||||||
"mobx": "^6.13.5",
|
"mobx": "^6.13.5",
|
||||||
@@ -994,7 +994,7 @@
|
|||||||
|
|
||||||
"dompurify": ["dompurify@3.2.5", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ=="],
|
"dompurify": ["dompurify@3.2.5", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ=="],
|
||||||
|
|
||||||
"dotenv": ["dotenv@16.5.0", "", {}, "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg=="],
|
"dotenv": ["dotenv@17.0.1", "", {}, "sha512-GLjkduuAL7IMJg/ZnOPm9AnWKJ82mSE2tzXLaJ/6hD6DhwGfZaXG77oB8qbReyiczNxnbxQKyh0OE5mXq0bAHA=="],
|
||||||
|
|
||||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||||
|
|
||||||
@@ -1566,7 +1566,7 @@
|
|||||||
|
|
||||||
"react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
|
"react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
|
||||||
|
|
||||||
"react-streaming": ["react-streaming@0.3.50", "", { "dependencies": { "@brillout/import": "^0.2.3", "@brillout/json-serializer": "^0.5.1", "@brillout/picocolors": "^1.0.11", "isbot-fast": "1.2.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-BRjWzY83dtnjgFUCYM0H2J3iRuYruE++/AidXmjxRclTsz1O/zBdUVgjAO2uKb05y/zybskcKjmK/5xyMc1MSg=="],
|
"react-streaming": ["react-streaming@0.4.2", "", { "dependencies": { "@brillout/import": "^0.2.3", "@brillout/json-serializer": "^0.5.1", "@brillout/picocolors": "^1.0.11", "isbot-fast": "1.2.0" }, "peerDependencies": { "react": ">=19", "react-dom": ">=19" } }, "sha512-b192E9E0TnE9wWdc8uZg00MMY36btQmFV25cDOGcWQwl5qF8vzNcQPVJwWkljLOec5qIJWumH9cvEvAL1JlAGg=="],
|
||||||
|
|
||||||
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
|
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
|
||||||
|
|
||||||
@@ -2146,6 +2146,10 @@
|
|||||||
|
|
||||||
"@open-gsio/client/vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
|
"@open-gsio/client/vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
|
||||||
|
|
||||||
|
"@open-gsio/coordinators/@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||||
|
|
||||||
|
"@open-gsio/scripts/@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||||
|
|
||||||
"@open-gsio/server/vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
|
"@open-gsio/server/vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
|
||||||
|
|
||||||
"@open-gsio/services/vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
|
"@open-gsio/services/vite": ["vite@7.0.0", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", "picomatch": "^4.0.2", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g=="],
|
||||||
@@ -2450,6 +2454,10 @@
|
|||||||
|
|
||||||
"@open-gsio/client/vite/rollup": ["rollup@4.44.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.44.0", "@rollup/rollup-android-arm64": "4.44.0", "@rollup/rollup-darwin-arm64": "4.44.0", "@rollup/rollup-darwin-x64": "4.44.0", "@rollup/rollup-freebsd-arm64": "4.44.0", "@rollup/rollup-freebsd-x64": "4.44.0", "@rollup/rollup-linux-arm-gnueabihf": "4.44.0", "@rollup/rollup-linux-arm-musleabihf": "4.44.0", "@rollup/rollup-linux-arm64-gnu": "4.44.0", "@rollup/rollup-linux-arm64-musl": "4.44.0", "@rollup/rollup-linux-loongarch64-gnu": "4.44.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-musl": "4.44.0", "@rollup/rollup-linux-s390x-gnu": "4.44.0", "@rollup/rollup-linux-x64-gnu": "4.44.0", "@rollup/rollup-linux-x64-musl": "4.44.0", "@rollup/rollup-win32-arm64-msvc": "4.44.0", "@rollup/rollup-win32-ia32-msvc": "4.44.0", "@rollup/rollup-win32-x64-msvc": "4.44.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA=="],
|
"@open-gsio/client/vite/rollup": ["rollup@4.44.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.44.0", "@rollup/rollup-android-arm64": "4.44.0", "@rollup/rollup-darwin-arm64": "4.44.0", "@rollup/rollup-darwin-x64": "4.44.0", "@rollup/rollup-freebsd-arm64": "4.44.0", "@rollup/rollup-freebsd-x64": "4.44.0", "@rollup/rollup-linux-arm-gnueabihf": "4.44.0", "@rollup/rollup-linux-arm-musleabihf": "4.44.0", "@rollup/rollup-linux-arm64-gnu": "4.44.0", "@rollup/rollup-linux-arm64-musl": "4.44.0", "@rollup/rollup-linux-loongarch64-gnu": "4.44.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-musl": "4.44.0", "@rollup/rollup-linux-s390x-gnu": "4.44.0", "@rollup/rollup-linux-x64-gnu": "4.44.0", "@rollup/rollup-linux-x64-musl": "4.44.0", "@rollup/rollup-win32-arm64-msvc": "4.44.0", "@rollup/rollup-win32-ia32-msvc": "4.44.0", "@rollup/rollup-win32-x64-msvc": "4.44.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA=="],
|
||||||
|
|
||||||
|
"@open-gsio/coordinators/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||||
|
|
||||||
|
"@open-gsio/scripts/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||||
|
|
||||||
"@open-gsio/server/vite/fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="],
|
"@open-gsio/server/vite/fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="],
|
||||||
|
|
||||||
"@open-gsio/server/vite/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
"@open-gsio/server/vite/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||||
|
@@ -2,6 +2,7 @@ import { Schema } from '@open-gsio/schema';
|
|||||||
import type { Instance } from 'mobx-state-tree';
|
import type { Instance } from 'mobx-state-tree';
|
||||||
import { OpenAI } from 'openai';
|
import { OpenAI } from 'openai';
|
||||||
|
|
||||||
|
import type Message from '../../../schema/src/models/Message.ts';
|
||||||
import { AssistantSdk } from '../assistant-sdk';
|
import { AssistantSdk } from '../assistant-sdk';
|
||||||
import { ProviderRepository } from '../providers/_ProviderRepository.ts';
|
import { ProviderRepository } from '../providers/_ProviderRepository.ts';
|
||||||
import type {
|
import type {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { OpenAI } from 'openai';
|
import { OpenAI } from 'openai';
|
||||||
|
|
||||||
import ChatSdk from '../chat-sdk/chat-sdk.ts';
|
import ChatSdk from '../chat-sdk/chat-sdk.ts';
|
||||||
|
import { BasicValueTool, WeatherTool } from '../tools/basic.ts';
|
||||||
import type { GenericEnv } from '../types';
|
import type { GenericEnv } from '../types';
|
||||||
|
|
||||||
export interface CommonProviderParams {
|
export interface CommonProviderParams {
|
||||||
@@ -35,12 +36,270 @@ export abstract class BaseChatProvider implements ChatStreamProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const client = this.getOpenAIClient(param);
|
const client = this.getOpenAIClient(param);
|
||||||
const streamParams = this.getStreamParams(param, safeMessages);
|
|
||||||
const stream = await client.chat.completions.create(streamParams);
|
|
||||||
|
|
||||||
for await (const chunk of stream as unknown as AsyncIterable<any>) {
|
// const tools = [WeatherTool];
|
||||||
const shouldBreak = await this.processChunk(chunk, dataCallback);
|
const tools = [
|
||||||
if (shouldBreak) break;
|
{
|
||||||
|
type: 'function',
|
||||||
|
function: {
|
||||||
|
name: 'getCurrentTemperature',
|
||||||
|
description: 'Get the current temperature for a specific location',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
location: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'The city and state, e.g., San Francisco, CA',
|
||||||
|
},
|
||||||
|
unit: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['Celsius', 'Fahrenheit'],
|
||||||
|
description: "The temperature unit to use. Infer this from the user's location.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['location', 'unit'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const getCurrentTemp = (location: string) => {
|
||||||
|
return '20C';
|
||||||
|
};
|
||||||
|
|
||||||
|
const callFunction = async (name, args) => {
|
||||||
|
if (name === 'getCurrentTemperature') {
|
||||||
|
return getCurrentTemp(args.location);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main conversation loop - handle tool calls properly
|
||||||
|
let conversationComplete = false;
|
||||||
|
let toolCallIterations = 0;
|
||||||
|
const maxToolCallIterations = 5; // Prevent infinite loops
|
||||||
|
let toolsExecuted = false; // Track if we've executed tools
|
||||||
|
|
||||||
|
while (!conversationComplete && toolCallIterations < maxToolCallIterations) {
|
||||||
|
const streamParams = this.getStreamParams(param, safeMessages);
|
||||||
|
// Only provide tools on the first call, after that force text response
|
||||||
|
const currentTools = toolsExecuted ? undefined : tools;
|
||||||
|
const stream = await client.chat.completions.create({ ...streamParams, tools: currentTools });
|
||||||
|
|
||||||
|
let assistantMessage = '';
|
||||||
|
const toolCalls: any[] = [];
|
||||||
|
|
||||||
|
for await (const chunk of stream as unknown as AsyncIterable<any>) {
|
||||||
|
console.log('chunk', chunk);
|
||||||
|
|
||||||
|
// Handle tool calls
|
||||||
|
if (chunk.choices[0]?.delta?.tool_calls) {
|
||||||
|
const deltaToolCalls = chunk.choices[0].delta.tool_calls;
|
||||||
|
|
||||||
|
for (const deltaToolCall of deltaToolCalls) {
|
||||||
|
if (deltaToolCall.index !== undefined) {
|
||||||
|
// Initialize or get existing tool call
|
||||||
|
if (!toolCalls[deltaToolCall.index]) {
|
||||||
|
toolCalls[deltaToolCall.index] = {
|
||||||
|
id: deltaToolCall.id || '',
|
||||||
|
type: deltaToolCall.type || 'function',
|
||||||
|
function: {
|
||||||
|
name: deltaToolCall.function?.name || '',
|
||||||
|
arguments: deltaToolCall.function?.arguments || '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Append to existing tool call
|
||||||
|
if (deltaToolCall.function?.arguments) {
|
||||||
|
toolCalls[deltaToolCall.index].function.arguments +=
|
||||||
|
deltaToolCall.function.arguments;
|
||||||
|
}
|
||||||
|
if (deltaToolCall.function?.name) {
|
||||||
|
toolCalls[deltaToolCall.index].function.name += deltaToolCall.function.name;
|
||||||
|
}
|
||||||
|
if (deltaToolCall.id) {
|
||||||
|
toolCalls[deltaToolCall.index].id += deltaToolCall.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle regular content
|
||||||
|
if (chunk.choices[0]?.delta?.content) {
|
||||||
|
assistantMessage += chunk.choices[0].delta.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if stream is finished
|
||||||
|
if (chunk.choices[0]?.finish_reason) {
|
||||||
|
if (chunk.choices[0].finish_reason === 'tool_calls' && toolCalls.length > 0) {
|
||||||
|
// Increment tool call iterations counter
|
||||||
|
toolCallIterations++;
|
||||||
|
console.log(`Tool call iteration ${toolCallIterations}/${maxToolCallIterations}`);
|
||||||
|
|
||||||
|
// Execute tool calls and add results to conversation
|
||||||
|
console.log('Executing tool calls:', toolCalls);
|
||||||
|
|
||||||
|
// Send feedback to user about tool invocation
|
||||||
|
dataCallback({
|
||||||
|
type: 'chat',
|
||||||
|
data: {
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
delta: {
|
||||||
|
content: `\n\n🔧 Invoking ${toolCalls.length} tool${toolCalls.length > 1 ? 's' : ''}...\n`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add assistant message with tool calls to conversation
|
||||||
|
safeMessages.push({
|
||||||
|
role: 'assistant',
|
||||||
|
content: assistantMessage || null,
|
||||||
|
tool_calls: toolCalls,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute each tool call and add results
|
||||||
|
for (const toolCall of toolCalls) {
|
||||||
|
if (toolCall.type === 'function') {
|
||||||
|
const name = toolCall.function.name;
|
||||||
|
console.log(`Calling function: ${name}`);
|
||||||
|
|
||||||
|
// Send feedback about specific tool being called
|
||||||
|
dataCallback({
|
||||||
|
type: 'chat',
|
||||||
|
data: {
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
delta: {
|
||||||
|
content: `📞 Calling ${name}...`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const args = JSON.parse(toolCall.function.arguments);
|
||||||
|
console.log(`Function arguments:`, args);
|
||||||
|
|
||||||
|
const result = await callFunction(name, args);
|
||||||
|
console.log(`Function result:`, result);
|
||||||
|
|
||||||
|
// Send feedback about tool completion
|
||||||
|
dataCallback({
|
||||||
|
type: 'chat',
|
||||||
|
data: {
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
delta: {
|
||||||
|
content: ` ✅\n`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add tool result to conversation
|
||||||
|
safeMessages.push({
|
||||||
|
role: 'tool',
|
||||||
|
tool_call_id: toolCall.id,
|
||||||
|
content: result?.toString() || '',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error executing tool ${name}:`, error);
|
||||||
|
|
||||||
|
// Send feedback about tool error
|
||||||
|
dataCallback({
|
||||||
|
type: 'chat',
|
||||||
|
data: {
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
delta: {
|
||||||
|
content: ` ❌ Error\n`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
safeMessages.push({
|
||||||
|
role: 'tool',
|
||||||
|
tool_call_id: toolCall.id,
|
||||||
|
content: `Error: ${error.message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark that tools have been executed to prevent repeated calls
|
||||||
|
toolsExecuted = true;
|
||||||
|
|
||||||
|
// Send feedback that tool execution is complete
|
||||||
|
dataCallback({
|
||||||
|
type: 'chat',
|
||||||
|
data: {
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
delta: {
|
||||||
|
content: `\n🎯 Tool execution complete. Generating response...\n\n`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Continue conversation with tool results
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Regular completion - send final response
|
||||||
|
conversationComplete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process chunk normally for non-tool-call responses
|
||||||
|
if (!chunk.choices[0]?.delta?.tool_calls) {
|
||||||
|
console.log('after-tool-call-chunk', chunk);
|
||||||
|
const shouldBreak = await this.processChunk(chunk, dataCallback);
|
||||||
|
if (shouldBreak) {
|
||||||
|
conversationComplete = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle case where we hit maximum tool call iterations
|
||||||
|
if (toolCallIterations >= maxToolCallIterations && !conversationComplete) {
|
||||||
|
console.log('Maximum tool call iterations reached, forcing completion');
|
||||||
|
|
||||||
|
// Send a message indicating we've hit the limit and provide available information
|
||||||
|
dataCallback({
|
||||||
|
type: 'chat',
|
||||||
|
data: {
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
delta: {
|
||||||
|
content:
|
||||||
|
'\n\n⚠️ Maximum tool execution limit reached. Based on the available information, I can provide the following response:\n\n',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make one final call without tools to get a response based on the tool results
|
||||||
|
const finalStreamParams = this.getStreamParams(param, safeMessages);
|
||||||
|
const finalStream = await client.chat.completions.create({
|
||||||
|
...finalStreamParams,
|
||||||
|
tools: undefined, // Remove tools to force a text response
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const chunk of finalStream as unknown as AsyncIterable<any>) {
|
||||||
|
const shouldBreak = await this.processChunk(chunk, dataCallback);
|
||||||
|
if (shouldBreak) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
41
packages/ai/src/tools/basic.ts
Normal file
41
packages/ai/src/tools/basic.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// tools/basicValue.ts
|
||||||
|
export interface BasicValueResult {
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BasicValueTool = {
|
||||||
|
name: 'basicValue',
|
||||||
|
type: 'function',
|
||||||
|
description: 'Returns a basic value (timestamp-based) for testing',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {},
|
||||||
|
required: [],
|
||||||
|
},
|
||||||
|
function: async (): Promise<BasicValueResult> => {
|
||||||
|
// generate something obviously basic
|
||||||
|
const basic = `tool-called-${Date.now()}`;
|
||||||
|
console.log('[BasicValueTool] returning:', basic);
|
||||||
|
return { value: basic };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export const WeatherTool = {
|
||||||
|
name: 'get_weather',
|
||||||
|
type: 'function',
|
||||||
|
description: 'Get current temperature for a given location.',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
location: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'City and country e.g. Bogotá, Colombia',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['location'],
|
||||||
|
additionalProperties: false,
|
||||||
|
},
|
||||||
|
function: async (params: { location: string }) => {
|
||||||
|
console.log('[WeatherTool] Getting weather for:', params.location);
|
||||||
|
return { temperature: '25°C' };
|
||||||
|
},
|
||||||
|
};
|
@@ -2,7 +2,7 @@
|
|||||||
"name": "@open-gsio/server",
|
"name": "@open-gsio/server",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun src/server/server.ts",
|
"dev": "bun --watch src/server/server.ts",
|
||||||
"build": "bun ./src/server/build.ts"
|
"build": "bun ./src/server/build.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
Reference in New Issue
Block a user