diff --git a/package-lock.json b/package-lock.json index 5a138f0d48..75c4f7b55a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3367,9 +3367,9 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.9", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", - "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", + "version": "1.19.14", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", "license": "MIT", "optional": true, "engines": { @@ -5011,9 +5011,9 @@ "license": "MIT" }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.26.0.tgz", - "integrity": "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg==", + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", + "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", "license": "MIT", "optional": true, "dependencies": { @@ -5052,9 +5052,9 @@ } }, "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", "optional": true, "dependencies": { @@ -5363,35 +5363,35 @@ } }, "node_modules/@openai/agents": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@openai/agents/-/agents-0.3.9.tgz", - "integrity": "sha512-YaKnqv0M6bCVvn47pThkFfyHz8xWJ+0Ll9ZnhvwJZ5gyPX0UxHIUeUs9SMG9BSvNuJNJHlc5uvfUDGYAmKJClw==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@openai/agents/-/agents-0.10.1.tgz", + "integrity": "sha512-RBpU0THlBYydrr9d9rD8B9QO5kP+A/rHkgjf3QJttRHbaSWMO0uCit6hpnGR8mrMwzFeDM834thrlJB0LFybiA==", "license": "MIT", "dependencies": { - "@openai/agents-core": "0.3.9", - "@openai/agents-openai": "0.3.9", - "@openai/agents-realtime": "0.3.9", + "@openai/agents-core": "0.10.1", + "@openai/agents-openai": "0.10.1", + "@openai/agents-realtime": "0.10.1", "debug": "^4.4.0", - "openai": "^6" + "openai": "^6.26.0" }, "peerDependencies": { - "zod": "^3.25.40 || ^4.0" + "zod": "^4.0.0" } }, "node_modules/@openai/agents-core": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@openai/agents-core/-/agents-core-0.3.9.tgz", - "integrity": "sha512-6Fr/VkA3lMaTT9EV2+OsmkMX9Yx+/PeWtlmaWNKDRG8D15IWuK13NOC9eFklTsa7otbuwbw/Xmjes+h4Z+CwSQ==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@openai/agents-core/-/agents-core-0.10.1.tgz", + "integrity": "sha512-NTagyB1XpbG3N/3yKa9DK7W0C6yBZOjXBMUxCWq9reNGVuBKzMIL/RCufYKslukaEH31QpjEKF4K9f7cvqNh1Q==", "license": "MIT", "dependencies": { "debug": "^4.4.0", - "openai": "^6" + "openai": "^6.26.0" }, "optionalDependencies": { - "@modelcontextprotocol/sdk": "^1.25.2" + "@modelcontextprotocol/sdk": "^1.26.0" }, "peerDependencies": { - "zod": "^3.25.40 || ^4.0" + "zod": "^4.0.0" }, "peerDependenciesMeta": { "zod": { @@ -5400,32 +5400,32 @@ } }, "node_modules/@openai/agents-openai": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@openai/agents-openai/-/agents-openai-0.3.9.tgz", - "integrity": "sha512-duXUt0xU6K/+c7ae4m8BrJIUzZal6Pzln8V0frnJfNyfYO4SvHMV4qwPRzVDvv/ANj4DQXWI2L1JdPxKJeSHkw==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@openai/agents-openai/-/agents-openai-0.10.1.tgz", + "integrity": "sha512-uw0dpYBwT15fnPxzMQ8ms6fD4DiL1M437J2MbQmNrS6c6Z5XZX6RMUQtuh1fMVsSyqbobs1kZSBCXYjsH1ck2A==", "license": "MIT", "dependencies": { - "@openai/agents-core": "0.3.9", + "@openai/agents-core": "0.10.1", "debug": "^4.4.0", - "openai": "^6" + "openai": "^6.26.0" }, "peerDependencies": { - "zod": "^3.25.40 || ^4.0" + "zod": "^4.0.0" } }, "node_modules/@openai/agents-realtime": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@openai/agents-realtime/-/agents-realtime-0.3.9.tgz", - "integrity": "sha512-51zHO/zao/LHv70gseU1otTvXyS81tuVaewHlUBiNMXvqSZNkYViiO69hpXMoTYn5c3gCjUrXPxxI+NlHUtaHg==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@openai/agents-realtime/-/agents-realtime-0.10.1.tgz", + "integrity": "sha512-Fv8QPwBLp/GZ/QtppP3yRUC0oUVs1ThcpqEpuI2GLFxGLzHWoOAGk3aLFQfWqTtE+ymrnE1FW2pOHBYgYSkToA==", "license": "MIT", "dependencies": { - "@openai/agents-core": "0.3.9", + "@openai/agents-core": "0.10.1", "@types/ws": "^8.18.1", "debug": "^4.4.0", "ws": "^8.18.1" }, "peerDependencies": { - "zod": "^3.25.40 || ^4.0" + "zod": "^4.0.0" } }, "node_modules/@parcel/watcher": { @@ -9033,9 +9033,9 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", "optional": true, "dependencies": { @@ -10592,9 +10592,9 @@ "license": "MIT" }, "node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", "license": "MIT", "optional": true, "engines": { @@ -12707,9 +12707,9 @@ } }, "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.8.tgz", + "integrity": "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==", "license": "MIT", "optional": true, "engines": { @@ -12941,13 +12941,13 @@ } }, "node_modules/express-rate-limit": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", - "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.1.tgz", + "integrity": "sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ==", "license": "MIT", "optional": true, "dependencies": { - "ip-address": "10.0.1" + "ip-address": "^10.2.0" }, "engines": { "node": ">= 16" @@ -14025,9 +14025,9 @@ "license": "MIT" }, "node_modules/hono": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.9.tgz", - "integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==", + "version": "4.12.18", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz", + "integrity": "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==", "license": "MIT", "optional": true, "engines": { @@ -14593,9 +14593,9 @@ "license": "Apache-2.0" }, "node_modules/ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "license": "MIT", "optional": true, "engines": { @@ -16474,9 +16474,9 @@ } }, "node_modules/jose": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", - "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", + "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", "license": "MIT", "optional": true, "funding": { @@ -18194,9 +18194,9 @@ } }, "node_modules/openai": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.22.0.tgz", - "integrity": "sha512-7Yvy17F33Bi9RutWbsaYt5hJEEJ/krRPOrwan+f9aCPuMat1WVsb2VNSII5W1EksKT6fF69TG/xj4XzodK3JZw==", + "version": "6.36.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.36.0.tgz", + "integrity": "sha512-Has2YbIusMq9wQEierFsgf9c783dy1y9arX459LmphNacEkkM5yxi2RIyXP0LmkOroQyW19iTwALHL8Yf26UKA==", "license": "Apache-2.0", "bin": { "openai": "bin/cli" @@ -19858,9 +19858,9 @@ } }, "node_modules/router/node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", "license": "MIT", "optional": true, "funding": { @@ -23570,21 +23570,22 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", "license": "ISC", + "optional": true, "peerDependencies": { - "zod": "^3.25 || ^4" + "zod": "^3.25.28 || ^4" } }, "packages/botonic-cli": { @@ -23901,12 +23902,11 @@ "version": "0.48.0", "dependencies": { "@botonic/core": "^0.48.0", - "@openai/agents": "^0.3.9", + "@openai/agents": "^0.10.1", "axios": "^1.15.2", - "openai": "^6.0.0", + "openai": "^6.36.0", "uuid": "^10.0.0", - "zod": "3.25.76", - "zod-to-json-schema": "^3.25.1" + "zod": "^4.3.6" }, "devDependencies": { "@types/uuid": "^10.0.0" diff --git a/packages/botonic-plugin-ai-agents/package.json b/packages/botonic-plugin-ai-agents/package.json index be5b390bc7..b6ece44902 100644 --- a/packages/botonic-plugin-ai-agents/package.json +++ b/packages/botonic-plugin-ai-agents/package.json @@ -15,12 +15,11 @@ }, "dependencies": { "@botonic/core": "^0.48.0", - "@openai/agents": "^0.3.9", + "@openai/agents": "^0.10.1", "axios": "^1.15.2", - "openai": "^6.0.0", + "openai": "^6.36.0", "uuid": "^10.0.0", - "zod": "3.25.76", - "zod-to-json-schema": "^3.25.1" + "zod": "^4.3.6" }, "devDependencies": { "@types/uuid": "^10.0.0" diff --git a/packages/botonic-plugin-ai-agents/src/bot-config-tools.ts b/packages/botonic-plugin-ai-agents/src/bot-config-tools.ts index 56d1b21f94..bde16a2475 100644 --- a/packages/botonic-plugin-ai-agents/src/bot-config-tools.ts +++ b/packages/botonic-plugin-ai-agents/src/bot-config-tools.ts @@ -1,5 +1,5 @@ import type { ToolConfigJSON } from '@botonic/core' -import { zodToJsonSchema } from 'zod-to-json-schema' +import { z } from 'zod' import type { CustomTool } from './types' @@ -13,9 +13,8 @@ export function getToolsForBotConfig( return customTools.map(tool => ({ name: tool.name, description: tool.description, - // Cast to avoid TS "Type instantiation is excessively deep" with zodToJsonSchema + ZodSchema - schema: zodToJsonSchema(tool.schema as never, { - $refStrategy: 'none', + schema: z.toJSONSchema(tool.schema, { + target: 'draft-07', }) as ToolConfigJSON['schema'], })) } diff --git a/packages/botonic-plugin-ai-agents/src/types.ts b/packages/botonic-plugin-ai-agents/src/types.ts index ac7a0b09e2..a9be427be9 100644 --- a/packages/botonic-plugin-ai-agents/src/types.ts +++ b/packages/botonic-plugin-ai-agents/src/types.ts @@ -14,7 +14,7 @@ import type { RunContext as OpenAIRunContext, Tool as OpenAITool, } from '@openai/agents' -import type { ZodSchema } from 'zod' +import type { ZodType } from 'zod' import type { OutputSchema } from './structured-output' @@ -44,7 +44,7 @@ export interface CustomTool< > { name: string description: string - schema: ZodSchema + schema: ZodType func: ( input?: any, runContext?: RunContext diff --git a/packages/botonic-plugin-ai-agents/tests/bot-config-tools.test.ts b/packages/botonic-plugin-ai-agents/tests/bot-config-tools.test.ts new file mode 100644 index 0000000000..eb4f5a5a60 --- /dev/null +++ b/packages/botonic-plugin-ai-agents/tests/bot-config-tools.test.ts @@ -0,0 +1,75 @@ +import { z } from 'zod' + +import { getToolsForBotConfig } from '../src/bot-config-tools' +import type { CustomTool } from '../src/types' + +describe('getToolsForBotConfig', () => { + it('should convert custom tool schemas to JSON Schema', () => { + const customTools: CustomTool[] = [ + { + name: 'schedule_meeting', + description: 'Schedule a meeting with a contact.', + schema: z + .object({ + contactEmail: z.string().email().describe('Contact email address'), + durationMinutes: z + .number() + .int() + .positive() + .describe('Meeting duration in minutes'), + notes: z.string().optional().describe('Optional meeting notes'), + }) + .describe('Meeting scheduling input'), + func: async () => undefined, + }, + ] + + expect(getToolsForBotConfig(customTools)).toEqual([ + { + name: 'schedule_meeting', + description: 'Schedule a meeting with a contact.', + schema: { + $schema: 'http://json-schema.org/draft-07/schema#', + additionalProperties: false, + description: 'Meeting scheduling input', + properties: { + contactEmail: { + description: 'Contact email address', + format: 'email', + pattern: + "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + type: 'string', + }, + durationMinutes: { + description: 'Meeting duration in minutes', + exclusiveMinimum: 0, + maximum: 9007199254740991, + type: 'integer', + }, + notes: { + description: 'Optional meeting notes', + type: 'string', + }, + }, + required: ['contactEmail', 'durationMinutes'], + type: 'object', + }, + }, + ]) + }) + + it('should fail when a custom tool schema cannot be represented as JSON Schema', () => { + const customTools: CustomTool[] = [ + { + name: 'invalid_tool', + description: 'Uses an unrepresentable schema.', + schema: z.object({ + value: z.string().transform(value => value.length), + }), + func: async () => undefined, + }, + ] + + expect(() => getToolsForBotConfig(customTools)).toThrow() + }) +})