diff --git a/bun.config.mjs b/bun.config.mjs deleted file mode 100644 index b4a900d..0000000 --- a/bun.config.mjs +++ /dev/null @@ -1,45 +0,0 @@ -// @ts-check -// https://bun.sh/docs/bundler -// @ts-ignore -import { resolvePath } from '@kevisual/use-config/env'; -import pkg from './package.json'; -import { execSync } from 'node:child_process'; - -// bun run src/index.ts -- -await Bun.build({ - target: 'node', - format: 'esm', - entrypoints: [resolvePath('./src/provider/index.ts')], - outdir: resolvePath('./dist'), - naming: { - entry: 'ai-provider.js', - }, - - define: { - ENVISION_VERSION: JSON.stringify(pkg.version), - IS_BROWSER: JSON.stringify(false), - }, - env: 'ENVISION_*', -}); - -const cmd = 'dts -i src/provider/index.ts -o ai-provider.d.ts'; -execSync(cmd, { stdio: 'inherit' }); -execSync('cp dist/ai-provider.d.ts dist/ai-provider-browser.d.ts', { stdio: 'inherit' }); - -// bun run src/index.ts -- -await Bun.build({ - target: 'browser', - format: 'esm', - entrypoints: [resolvePath('./src/provider/index.ts')], - outdir: resolvePath('./dist'), - naming: { - entry: 'ai-provider-browser.js', - }, - - define: { - ENVISION_VERSION: JSON.stringify(pkg.version), - IS_BROWSER: JSON.stringify(true), - }, - env: 'ENVISION_*', -}); - diff --git a/bun.config.ts b/bun.config.ts new file mode 100644 index 0000000..022f6bb --- /dev/null +++ b/bun.config.ts @@ -0,0 +1,11 @@ +import { buildWithBun } from '@kevisual/code-builder'; + +await buildWithBun({ naming: 'ai-provider', entry: './src/provider/index.ts', target: 'node', dts: true, clean: true }); + +await buildWithBun({ naming: 'ai-provider-browser', entry: './src/provider/index.ts', target: 'browser', dts: true }); + +await buildWithBun({ + naming: 'agent', entry: './src/agent/index.ts', target: 'browser', dts: true, + external: ['ai', '@kevisual/js-filter', 'zod'] +}); + diff --git a/package.json b/package.json index 4b5a1c8..bb29c8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/ai", - "version": "0.0.26", + "version": "0.0.27", "description": "AI Center Services", "main": "index.js", "basename": "/root/ai-center-services", @@ -14,8 +14,8 @@ "types" ], "scripts": { - "build": "npm run clean && bun bun.config.mjs", - "dev": "bun run --watch bun.config.mjs", + "build": "npm run clean && bun bun.config.ts", + "dev": "bun run --watch bun.config.ts", "clean": "rm -rf dist", "pub": "envision pack -p -u" }, @@ -26,7 +26,7 @@ ], "author": "abearxiong (https://www.xiongxiao.me)", "license": "MIT", - "packageManager": "pnpm@10.30.3", + "packageManager": "pnpm@10.32.0", "type": "module", "publishConfig": { "registry": "https://registry.npmjs.org/", @@ -36,34 +36,38 @@ ".": "./dist/ai-provider-browser.js", "./ai-provider": "./dist/ai-provider.js", "./browser": "./dist/ai-provider-browser.js", + "./agent": "./dist/agent.js", "./src/*": "./src/*" }, "devDependencies": { - "@kevisual/router": "0.0.84", + "@kevisual/code-builder": "^0.0.6", + "@kevisual/router": "0.1.0", "@kevisual/types": "^0.0.12", "@kevisual/use-config": "^1.0.30", "@types/bun": "^1.3.10", "@types/crypto-js": "^4.2.2", - "@types/formidable": "^3.4.7", - "@types/node": "^25.3.3", + "@types/formidable": "^3.5.0", + "@types/node": "^25.4.0", "cross-env": "^10.1.0", "crypto-js": "^4.2.0", "dayjs": "^1.11.19", "dotenv": "^17.3.1", "formidable": "^3.5.4", - "openai": "6.25.0", + "openai": "6.27.0", "pm2": "^6.0.14", "rimraf": "^6.1.3", "typescript": "^5.9.3", "vite": "^7.3.1" }, "dependencies": { + "@ai-sdk/anthropic": "^3.0.58", + "@ai-sdk/openai": "^3.0.41", + "@ai-sdk/openai-compatible": "^2.0.35", + "@kevisual/js-filter": "^0.0.6", "@kevisual/logger": "^0.0.4", - "@ai-sdk/anthropic": "^3.0.53", - "@ai-sdk/openai": "^3.0.39", - "@ai-sdk/openai-compatible": "^2.0.33", - "ai": "^6.0.108", "@kevisual/permission": "^0.0.4", - "@kevisual/query": "^0.0.52" + "@kevisual/query": "^0.0.53", + "ai": "^6.0.116", + "zod": "^4.3.6" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a34c34f..7384776 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,14 +9,17 @@ importers: .: dependencies: '@ai-sdk/anthropic': - specifier: ^3.0.53 - version: 3.0.53(zod@3.25.76) + specifier: ^3.0.58 + version: 3.0.58(zod@4.3.6) '@ai-sdk/openai': - specifier: ^3.0.39 - version: 3.0.39(zod@3.25.76) + specifier: ^3.0.41 + version: 3.0.41(zod@4.3.6) '@ai-sdk/openai-compatible': - specifier: ^2.0.33 - version: 2.0.33(zod@3.25.76) + specifier: ^2.0.35 + version: 2.0.35(zod@4.3.6) + '@kevisual/js-filter': + specifier: ^0.0.6 + version: 0.0.6 '@kevisual/logger': specifier: ^0.0.4 version: 0.0.4 @@ -24,15 +27,21 @@ importers: specifier: ^0.0.4 version: 0.0.4 '@kevisual/query': - specifier: ^0.0.52 - version: 0.0.52 + specifier: ^0.0.53 + version: 0.0.53 ai: - specifier: ^6.0.108 - version: 6.0.108(zod@3.25.76) + specifier: ^6.0.116 + version: 6.0.116(zod@4.3.6) + zod: + specifier: ^4.3.6 + version: 4.3.6 devDependencies: + '@kevisual/code-builder': + specifier: ^0.0.6 + version: 0.0.6 '@kevisual/router': - specifier: 0.0.84 - version: 0.0.84 + specifier: 0.1.0 + version: 0.1.0 '@kevisual/types': specifier: ^0.0.12 version: 0.0.12 @@ -46,11 +55,11 @@ importers: specifier: ^4.2.2 version: 4.2.2 '@types/formidable': - specifier: ^3.4.7 - version: 3.4.7 + specifier: ^3.5.0 + version: 3.5.0 '@types/node': - specifier: ^25.3.3 - version: 25.3.3 + specifier: ^25.4.0 + version: 25.4.0 cross-env: specifier: ^10.1.0 version: 10.1.0 @@ -67,8 +76,8 @@ importers: specifier: ^3.5.4 version: 3.5.4 openai: - specifier: 6.25.0 - version: 6.25.0(ws@8.18.3)(zod@3.25.76) + specifier: 6.27.0 + version: 6.27.0(ws@8.18.3)(zod@4.3.6) pm2: specifier: ^6.0.14 version: 6.0.14 @@ -80,36 +89,36 @@ importers: version: 5.9.3 vite: specifier: ^7.3.1 - version: 7.3.1(@types/node@25.3.3) + version: 7.3.1(@types/node@25.4.0) packages: - '@ai-sdk/anthropic@3.0.53': - resolution: {integrity: sha512-HVuVLUt4VtioGKV5gxRg7Wu2g0BvX3zzrAa51OHPG9sJlP+caPyZu3n4j4FHjZmg++8A9JHDCMWBQfHra3gtWg==} + '@ai-sdk/anthropic@3.0.58': + resolution: {integrity: sha512-/53SACgmVukO4bkms4dpxpRlYhW8Ct6QZRe6sj1Pi5H00hYhxIrqfiLbZBGxkdRvjsBQeP/4TVGsXgH5rQeb8Q==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/gateway@3.0.61': - resolution: {integrity: sha512-OT6SeORuOoqfABhntMJHmInblxE2DbBYvRTynVOGl6dCDDh0cNU1lJgknyDV698eQmfb6Um/94/rImgt0ZPjDA==} + '@ai-sdk/gateway@3.0.66': + resolution: {integrity: sha512-SIQ0YY0iMuv+07HLsZ+bB990zUJ6S4ujORAh+Jv1V2KGNn73qQKnGO0JBk+w+Res8YqOFSycwDoWcFlQrVxS4A==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/openai-compatible@2.0.33': - resolution: {integrity: sha512-HwptqeUS4vtDyjSSjmKCQExjoQMwPVq0C4pHH18i7c+3CQ0QN81HLvz3BdpULo0n/UtdQwTNISRqx3G5miPZhw==} + '@ai-sdk/openai-compatible@2.0.35': + resolution: {integrity: sha512-g3wA57IAQFb+3j4YuFndgkUdXyRETZVvbfAWM+UX7bZSxA3xjes0v3XKgIdKdekPtDGsh4ZX2byHD0gJIMPfiA==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/openai@3.0.39': - resolution: {integrity: sha512-EZrs4L6kMkPQhpodagpEvqLSryOIK99WgblN0IsVHr1xhajWizQOZ0XMa7c5JpSYgIjV6u8GCpGV6hS3Mk2Bug==} + '@ai-sdk/openai@3.0.41': + resolution: {integrity: sha512-IZ42A+FO+vuEQCVNqlnAPYQnnUpUfdJIwn1BEDOBywiEHa23fw7PahxVtlX9zm3/zMvTW4JKPzWyvAgDu+SQ2A==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@4.0.17': - resolution: {integrity: sha512-oyCeFINTYK0B8ZGUBiQc05G5vytPlKSmTTtm19xfJuUgoi8zkvvRcoPQci4mSnyfpPn2XSFFDfsALG8uGcapfg==} + '@ai-sdk/provider-utils@4.0.19': + resolution: {integrity: sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -277,6 +286,13 @@ packages: cpu: [x64] os: [win32] + '@kevisual/code-builder@0.0.6': + resolution: {integrity: sha512-0aqATB31/yw4k4s5/xKnfr4DKbUnx8e3Z3BmKbiXTrc+CqWiWTdlGe9bKI9dZ2Df+xNp6g11W4xM2NICNyyCCw==} + hasBin: true + + '@kevisual/js-filter@0.0.6': + resolution: {integrity: sha512-FcbOsmS1inhwrfgXMM/XLFTGTHUxBCss32JEMYdEFWQDYCar5rN8cxD1W8FuKDTVRlpA+zBpQ/BE6XT4UaeljA==} + '@kevisual/load@0.0.6': resolution: {integrity: sha512-+3YTFehRcZ1haGel5DKYMUwmi5i6f2psyaPZlfkKU/cOXgkpwoG9/BEqPCnPjicKqqnksEpixVRkyHJ+5bjLVA==} @@ -286,11 +302,11 @@ packages: '@kevisual/permission@0.0.4': resolution: {integrity: sha512-zwBYPnT/z21W4q2wkklJrxvoYBYWG/+a3iXFDKqXQAnDOcxm/SU1f1N6FQb9KxGKl36/fclVlhxlxqszvKCenQ==} - '@kevisual/query@0.0.52': - resolution: {integrity: sha512-m1UbyDTIxtfAQXM+EqhXA4ytE2V8rV8mXTZVBwzfW9O6+gtvAcRY7K1YYxfewTSXLVh9nwvfHe0KQ8MDL5ukyw==} + '@kevisual/query@0.0.53': + resolution: {integrity: sha512-PAhpCLBr0emz0lGNlTVHMbJiC5wrtGLbInPddRzgKE35fiyNt+SWSsUWABiD0DeNrLN/OxWyAFobt880Z/e5MQ==} - '@kevisual/router@0.0.84': - resolution: {integrity: sha512-l/TUFuqTJegB/S3FZQRBMUoz0Spvg8EzV3C/kBi/VO9KKCzjqZDVvhZJJbTQh9879CBY6vUy1ajo9WcLYnwbNA==} + '@kevisual/router@0.1.0': + resolution: {integrity: sha512-7NHoKP36uWkTDp/hxeUBMtawma91BrOAwG/caOrVsO8tM3wjqhlmCt0sIvLBM+snVJkmylROQR0WGaygd3JqYw==} '@kevisual/types@0.0.12': resolution: {integrity: sha512-zJXH2dosir3jVrQ6QG4i0+iLQeT9gJ3H+cKXs8ReWboxBSYzUZO78XssVeVrFPsJ33iaAqo4q3DWbSS1dWGn7Q==} @@ -466,11 +482,11 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/formidable@3.4.7': - resolution: {integrity: sha512-EN2atJPHCiD5LBqgX0cUjL4n1XA84MpUVwrXDC8en4K8TFIaPB7zC/Im1EbTMC9biUnMdfhaVRmUKzN4n6pJ/g==} + '@types/formidable@3.5.0': + resolution: {integrity: sha512-fHChKoKkxUy/n7uCHHWTMQ8yA7/raxz1+K2B7edHTIQhwBHX9TfRnCX0ohmuR77ezEFgMapUuSksk0MA7nQCrA==} - '@types/node@25.3.3': - resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==} + '@types/node@25.4.0': + resolution: {integrity: sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==} '@vercel/oidc@3.1.0': resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} @@ -480,8 +496,8 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - ai@6.0.108: - resolution: {integrity: sha512-h2xwwU9lE+tdLyII/uFcjcrw+7ciWj2S68GrwQsebjHPSfnvxwrn+sjIl+tBt419yA9rYznWXtQvHJxM1wEAAQ==} + ai@6.0.116: + resolution: {integrity: sha512-7yM+cTmyRLeNIXwt4Vj+mrrJgVQ9RMIW5WO0ydoLoYkewIvsMcvUmqS4j2RJTUXaF1HphwmSKUMQ/HypNRGOmA==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -650,8 +666,8 @@ packages: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} - es-toolkit@1.45.0: - resolution: {integrity: sha512-RArCX+Zea16+R1jg4mH223Z8p/ivbJjIkU3oC6ld2bdUfmDxiCkFYSi9zLOR2anucWJUeH4Djnzgd0im0nD3dw==} + es-toolkit@1.45.1: + resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} esbuild@0.27.2: resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} @@ -883,8 +899,8 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - openai@6.25.0: - resolution: {integrity: sha512-mEh6VZ2ds2AGGokWARo18aPISI1OhlgdEIC1ewhkZr8pSIT31dec0ecr9Nhxx0JlybyOgoAT1sWeKtwPZzJyww==} + openai@6.27.0: + resolution: {integrity: sha512-osTKySlrdYrLYTt0zjhY8yp0JUBmWDCN+Q+QxsV4xMQnnoVFpylgKGgxwN8sSdTNw0G4y+WUXs4eCMWpyDNWZQ==} hasBin: true peerDependencies: ws: ^8.18.0 @@ -1190,42 +1206,42 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} snapshots: - '@ai-sdk/anthropic@3.0.53(zod@3.25.76)': + '@ai-sdk/anthropic@3.0.58(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.17(zod@3.25.76) - zod: 3.25.76 + '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6) + zod: 4.3.6 - '@ai-sdk/gateway@3.0.61(zod@3.25.76)': + '@ai-sdk/gateway@3.0.66(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.17(zod@3.25.76) + '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6) '@vercel/oidc': 3.1.0 - zod: 3.25.76 + zod: 4.3.6 - '@ai-sdk/openai-compatible@2.0.33(zod@3.25.76)': + '@ai-sdk/openai-compatible@2.0.35(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.17(zod@3.25.76) - zod: 3.25.76 + '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6) + zod: 4.3.6 - '@ai-sdk/openai@3.0.39(zod@3.25.76)': + '@ai-sdk/openai@3.0.41(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.17(zod@3.25.76) - zod: 3.25.76 + '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6) + zod: 4.3.6 - '@ai-sdk/provider-utils@4.0.17(zod@3.25.76)': + '@ai-sdk/provider-utils@4.0.19(zod@4.3.6)': dependencies: '@ai-sdk/provider': 3.0.8 '@standard-schema/spec': 1.1.0 eventsource-parser: 3.0.6 - zod: 3.25.76 + zod: 4.3.6 '@ai-sdk/provider@3.0.8': dependencies: @@ -1311,6 +1327,10 @@ snapshots: '@esbuild/win32-x64@0.27.2': optional: true + '@kevisual/code-builder@0.0.6': {} + + '@kevisual/js-filter@0.0.6': {} + '@kevisual/load@0.0.6': dependencies: eventemitter3: 5.0.1 @@ -1319,11 +1339,11 @@ snapshots: '@kevisual/permission@0.0.4': {} - '@kevisual/query@0.0.52': {} + '@kevisual/query@0.0.53': {} - '@kevisual/router@0.0.84': + '@kevisual/router@0.1.0': dependencies: - es-toolkit: 1.45.0 + es-toolkit: 1.45.1 '@kevisual/types@0.0.12': {} @@ -1470,11 +1490,11 @@ snapshots: '@types/estree@1.0.8': {} - '@types/formidable@3.4.7': + '@types/formidable@3.5.0': dependencies: - '@types/node': 25.3.3 + '@types/node': 25.4.0 - '@types/node@25.3.3': + '@types/node@25.4.0': dependencies: undici-types: 7.18.2 @@ -1482,13 +1502,13 @@ snapshots: agent-base@7.1.4: {} - ai@6.0.108(zod@3.25.76): + ai@6.0.116(zod@4.3.6): dependencies: - '@ai-sdk/gateway': 3.0.61(zod@3.25.76) + '@ai-sdk/gateway': 3.0.66(zod@4.3.6) '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.17(zod@3.25.76) + '@ai-sdk/provider-utils': 4.0.19(zod@4.3.6) '@opentelemetry/api': 1.9.0 - zod: 3.25.76 + zod: 4.3.6 amp-message@0.1.2: dependencies: @@ -1543,7 +1563,7 @@ snapshots: bun-types@1.3.10: dependencies: - '@types/node': 25.3.3 + '@types/node': 25.4.0 chalk@3.0.0: dependencies: @@ -1630,7 +1650,7 @@ snapshots: dependencies: ansi-colors: 4.1.3 - es-toolkit@1.45.0: {} + es-toolkit@1.45.1: {} esbuild@0.27.2: optionalDependencies: @@ -1851,10 +1871,10 @@ snapshots: dependencies: wrappy: 1.0.2 - openai@6.25.0(ws@8.18.3)(zod@3.25.76): + openai@6.27.0(ws@8.18.3)(zod@4.3.6): optionalDependencies: ws: 8.18.3 - zod: 3.25.76 + zod: 4.3.6 pac-proxy-agent@7.2.0: dependencies: @@ -2140,7 +2160,7 @@ snapshots: undici-types@7.18.2: {} - vite@7.3.1(@types/node@25.3.3): + vite@7.3.1(@types/node@25.4.0): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.3) @@ -2149,7 +2169,7 @@ snapshots: rollup: 4.53.3 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.3.3 + '@types/node': 25.4.0 fsevents: 2.3.3 vizion@2.2.1: @@ -2172,4 +2192,4 @@ snapshots: yallist@4.0.0: {} - zod@3.25.76: {} + zod@4.3.6: {} diff --git a/src/agent/index.ts b/src/agent/index.ts new file mode 100644 index 0000000..29ca909 --- /dev/null +++ b/src/agent/index.ts @@ -0,0 +1,65 @@ +import { type QueryRouterServer, type App, type RouteInfo } from '@kevisual/router' +import { generateText, tool, type ModelMessage, type LanguageModel, type GenerateTextResult } from 'ai'; +import z from 'zod'; +import { filter } from '@kevisual/js-filter' +export const createTool = async (app: QueryRouterServer | App, message: { path: string, key: string, token?: string }) => { + const route = app.findRoute({ path: message.path, key: message.key }); + if (!route) { + console.error(`未找到路径 ${message.path} 和 key ${message.key} 的路由`); + return null; + } + const _tool = tool({ + description: route?.metadata?.summary || route?.description || '无描述', + inputSchema: z.object({ + ...route.metadata?.args + }), // 这里可以根据实际需要定义输入参数的 schema + execute: async (args: any) => { + const res = await app.run({ path: message.path, key: message.key, payload: args, token: message.token }); + return res; + } + }); + return _tool; +} + +export const createTools = async (opts: { app: QueryRouterServer | App, token?: string }) => { + const { app, token } = opts; + const tools: Record = {}; + for (const route of app.routes) { + const id = route.id!; + const _tool = await createTool(app, { path: route.path!, key: route.key!, token }); + if (_tool && id) { + tools[id] = _tool; + } + } + return tools; +} +type Route = Partial +type AgentResult = { + result: GenerateTextResult, any>, + messages: ModelMessage[], +} +export const reCallAgent = async (opts: { messages?: ModelMessage[], tools?: Record, languageModel: LanguageModel }): Promise => { + const { messages = [], tools = {}, languageModel } = opts; + const result = await generateText({ + model: languageModel, + messages, + tools, + }); + const step = result.steps[0]!; + if (step.finishReason === 'tool-calls') { + messages.push(...result.response.messages); + return reCallAgent({ messages, tools, languageModel }); + } + return { result, messages }; +} +export const runAgent = async (opts: { app: QueryRouterServer | App, messages?: ModelMessage[], routes?: Route[], query?: string, languageModel: LanguageModel, token: string }) => { + const { app, languageModel } = opts; + let messages = opts.messages || []; + + let routes = opts?.routes || app.routes; + if (opts.query) { + routes = filter(routes, opts.query); + }; + const tools = await createTools({ app, token: opts.token }); + return await reCallAgent({ messages, tools, languageModel }); +}