From fbfe587ae21d96f3c986f7bd216cb25c7e81f7fd Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Sat, 25 Oct 2025 09:00:34 +0900 Subject: [PATCH] fix: ugprade openai package from v5 to v6 --- .changeset/heavy-crabs-start.md | 7 + packages/agents-core/package.json | 2 +- packages/agents-core/src/metadata.ts | 2 +- packages/agents-core/src/utils/tools.ts | 134 ++++++++++++++---- packages/agents-core/test/utils/tools.test.ts | 50 +++++++ packages/agents-openai/package.json | 2 +- packages/agents-openai/src/metadata.ts | 2 +- packages/agents/package.json | 2 +- packages/agents/src/metadata.ts | 2 +- pnpm-lock.yaml | 20 +-- 10 files changed, 183 insertions(+), 40 deletions(-) create mode 100644 .changeset/heavy-crabs-start.md diff --git a/.changeset/heavy-crabs-start.md b/.changeset/heavy-crabs-start.md new file mode 100644 index 00000000..34822bbb --- /dev/null +++ b/.changeset/heavy-crabs-start.md @@ -0,0 +1,7 @@ +--- +'@openai/agents-openai': patch +'@openai/agents-core': patch +'@openai/agents': patch +--- + +fix: ugprade openai package from v5 to v6 diff --git a/packages/agents-core/package.json b/packages/agents-core/package.json index 56cee090..d79df1a2 100644 --- a/packages/agents-core/package.json +++ b/packages/agents-core/package.json @@ -70,7 +70,7 @@ "@modelcontextprotocol/sdk": "^1.17.2" }, "dependencies": { - "openai": "^5.20.2", + "openai": "^6", "debug": "^4.4.0" }, "peerDependencies": { diff --git a/packages/agents-core/src/metadata.ts b/packages/agents-core/src/metadata.ts index 14ba4926..69184b8b 100644 --- a/packages/agents-core/src/metadata.ts +++ b/packages/agents-core/src/metadata.ts @@ -6,7 +6,7 @@ export const METADATA = { "version": "0.2.0", "versions": { "@openai/agents-core": "0.2.0", - "openai": "^5.20.2" + "openai": "^6" } }; diff --git a/packages/agents-core/src/utils/tools.ts b/packages/agents-core/src/utils/tools.ts index 5333bd86..b56ce971 100644 --- a/packages/agents-core/src/utils/tools.ts +++ b/packages/agents-core/src/utils/tools.ts @@ -11,6 +11,44 @@ import { import type { ZodObjectLike } from './zodCompat'; import { asZodType } from './zodCompat'; +// TypeScript struggles to infer the heavily generic types returned by the OpenAI +// helpers, so we provide minimal wrappers that sidestep the deep instantiation. +type MinimalParseableResponseTool = { + parameters: unknown; + $parseRaw: (input: string) => unknown; +}; + +type ZodResponsesFunctionOptions = { + name: string; + parameters: unknown; + function?: (...args: any[]) => unknown; + description?: string; +}; + +const zodResponsesFunctionCompat: ( + options: ZodResponsesFunctionOptions, +) => MinimalParseableResponseTool = zodResponsesFunction as unknown as ( + options: ZodResponsesFunctionOptions, +) => MinimalParseableResponseTool; + +type MinimalParseableTextFormat = { + type: 'json_schema'; + name: string; + strict?: boolean; + schema: unknown; +}; + +// The `.schema` payload is all we need, so a lightweight signature keeps the compiler happy. +const zodTextFormatCompat: ( + zodObject: unknown, + name: string, + props?: unknown, +) => MinimalParseableTextFormat = zodTextFormat as unknown as ( + zodObject: unknown, + name: string, + props?: unknown, +) => MinimalParseableTextFormat; + export type FunctionToolName = string & { __brand?: 'ToolName' } & { readonly __pattern?: '^[a-zA-Z0-9_]+$'; }; @@ -63,12 +101,37 @@ export function getSchemaAndParserFromInputType( const parser = (input: string) => JSON.parse(input); if (isZodObject(inputType)) { - const formattedFunction = zodResponsesFunction({ - name, - parameters: asZodType(inputType), - function: () => {}, // empty function here to satisfy the OpenAI helper - description: '', - }); + const useFallback = (originalError?: unknown) => { + const fallbackSchema = buildJsonSchemaFromZod(inputType); + if (fallbackSchema) { + return { + schema: fallbackSchema, + parser: (rawInput: string) => inputType.parse(JSON.parse(rawInput)), + }; + } + + const errorMessage = + originalError instanceof Error + ? ` Upstream helper error: ${originalError.message}` + : ''; + + throw new UserError( + `Unable to convert the provided Zod schema to JSON Schema. Ensure that the \`zod\` package is available at runtime or provide a JSON schema object instead.${errorMessage}`, + ); + }; + + let formattedFunction: MinimalParseableResponseTool; + try { + formattedFunction = zodResponsesFunctionCompat({ + name, + parameters: asZodType(inputType), + function: () => {}, // empty function here to satisfy the OpenAI helper + description: '', + }); + } catch (error) { + return useFallback(error); + } + if (hasJsonSchemaObjectShape(formattedFunction.parameters)) { return { schema: formattedFunction.parameters as JsonObjectSchema, @@ -76,18 +139,7 @@ export function getSchemaAndParserFromInputType( }; } - const fallbackSchema = buildJsonSchemaFromZod(inputType); - - if (fallbackSchema) { - return { - schema: fallbackSchema, - parser: (rawInput: string) => inputType.parse(JSON.parse(rawInput)), - }; - } - - throw new UserError( - 'Unable to convert the provided Zod schema to JSON Schema. Ensure that the `zod` package is available at runtime or provide a JSON schema object instead.', - ); + return useFallback(); } else if (typeof inputType === 'object' && inputType !== null) { return { schema: inputType, @@ -109,13 +161,47 @@ export function convertAgentOutputTypeToSerializable( } if (isZodObject(outputType)) { - const output = zodTextFormat(asZodType(outputType), 'output'); - return { - type: output.type, - name: output.name, - strict: output.strict || false, - schema: output.schema as JsonObjectSchema, + const useFallback = ( + existing?: MinimalParseableTextFormat, + originalError?: unknown, + ): JsonSchemaDefinition => { + const fallbackSchema = buildJsonSchemaFromZod(outputType); + if (fallbackSchema) { + return { + type: existing?.type ?? 'json_schema', + name: existing?.name ?? 'output', + strict: existing?.strict ?? false, + schema: fallbackSchema, + }; + } + + const errorMessage = + originalError instanceof Error + ? ` Upstream helper error: ${originalError.message}` + : ''; + + throw new UserError( + `Unable to convert the provided Zod schema to JSON Schema. Ensure that the \`zod\` package is available at runtime or provide a JSON schema object instead.${errorMessage}`, + ); }; + + let output: MinimalParseableTextFormat; + try { + output = zodTextFormatCompat(asZodType(outputType), 'output'); + } catch (error) { + return useFallback(undefined, error); + } + + if (hasJsonSchemaObjectShape(output.schema)) { + return { + type: output.type, + name: output.name, + strict: output.strict || false, + schema: output.schema as JsonObjectSchema, + }; + } + + return useFallback(output); } return outputType; diff --git a/packages/agents-core/test/utils/tools.test.ts b/packages/agents-core/test/utils/tools.test.ts index d539615f..f33f542a 100644 --- a/packages/agents-core/test/utils/tools.test.ts +++ b/packages/agents-core/test/utils/tools.test.ts @@ -2,6 +2,7 @@ import { describe, it, expect } from 'vitest'; import { toFunctionToolName, getSchemaAndParserFromInputType, + convertAgentOutputTypeToSerializable, } from '../../src/utils/tools'; import { z } from 'zod'; import { z as z4 } from 'zod/v4'; @@ -50,4 +51,53 @@ describe('utils/tools', () => { UserError, ); }); + + it('falls back to compat schema when the helper rejects optional fields', () => { + const zodSchema = z.object({ + required: z.string(), + optional: z.number().optional(), + }); + const res = getSchemaAndParserFromInputType( + zodSchema, + 'tool-with-optional', + ); + expect(res.schema).toEqual({ + type: 'object', + properties: { + required: { type: 'string' }, + optional: { type: 'number' }, + }, + required: ['required'], + additionalProperties: false, + $schema: 'http://json-schema.org/draft-07/schema#', + }); + expect(res.parser('{"required":"ok"}')).toEqual({ required: 'ok' }); + expect(res.parser('{"required":"ok","optional":2}')).toEqual({ + required: 'ok', + optional: 2, + }); + }); + + it('convertAgentOutputTypeToSerializable falls back when helper rejects optional fields', () => { + const zodSchema = z.object({ + required: z.string(), + optional: z.number().optional(), + }); + const res = convertAgentOutputTypeToSerializable(zodSchema); + expect(res).toEqual({ + type: 'json_schema', + name: 'output', + strict: false, + schema: { + type: 'object', + properties: { + required: { type: 'string' }, + optional: { type: 'number' }, + }, + required: ['required'], + additionalProperties: false, + $schema: 'http://json-schema.org/draft-07/schema#', + }, + }); + }); }); diff --git a/packages/agents-openai/package.json b/packages/agents-openai/package.json index bcaadc52..9f9d8484 100644 --- a/packages/agents-openai/package.json +++ b/packages/agents-openai/package.json @@ -17,7 +17,7 @@ "dependencies": { "@openai/agents-core": "workspace:*", "debug": "^4.4.0", - "openai": "^5.20.2" + "openai": "^6" }, "scripts": { "prebuild": "tsx ../../scripts/embedMeta.ts", diff --git a/packages/agents-openai/src/metadata.ts b/packages/agents-openai/src/metadata.ts index b8110b20..fedd0c2a 100644 --- a/packages/agents-openai/src/metadata.ts +++ b/packages/agents-openai/src/metadata.ts @@ -7,7 +7,7 @@ export const METADATA = { "versions": { "@openai/agents-openai": "0.2.0", "@openai/agents-core": "workspace:*", - "openai": "^5.20.2" + "openai": "^6" } }; diff --git a/packages/agents/package.json b/packages/agents/package.json index 3df4b256..0df8ce76 100644 --- a/packages/agents/package.json +++ b/packages/agents/package.json @@ -34,7 +34,7 @@ "@openai/agents-openai": "workspace:*", "@openai/agents-realtime": "workspace:*", "debug": "^4.4.0", - "openai": "^5.20.2" + "openai": "^6" }, "keywords": [ "openai", diff --git a/packages/agents/src/metadata.ts b/packages/agents/src/metadata.ts index 20453bc6..b6565927 100644 --- a/packages/agents/src/metadata.ts +++ b/packages/agents/src/metadata.ts @@ -9,7 +9,7 @@ export const METADATA = { "@openai/agents-core": "workspace:*", "@openai/agents-openai": "workspace:*", "@openai/agents-realtime": "workspace:*", - "openai": "^5.20.2" + "openai": "^6" } }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9381d022..ecf1ccb8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -416,8 +416,8 @@ importers: specifier: ^4.4.0 version: 4.4.3 openai: - specifier: ^5.20.2 - version: 5.23.2(ws@8.18.3)(zod@3.25.76) + specifier: ^6 + version: 6.7.0(ws@8.18.3)(zod@3.25.76) devDependencies: '@types/debug': specifier: ^4.1.12 @@ -432,8 +432,8 @@ importers: specifier: ^4.4.0 version: 4.4.3 openai: - specifier: ^5.20.2 - version: 5.23.2(ws@8.18.3)(zod@3.25.76) + specifier: ^6 + version: 6.7.0(ws@8.18.3)(zod@3.25.76) devDependencies: '@types/debug': specifier: ^4.1.12 @@ -483,8 +483,8 @@ importers: specifier: ^4.4.0 version: 4.4.3 openai: - specifier: ^5.20.2 - version: 5.23.2(ws@8.18.3)(zod@3.25.76) + specifier: ^6 + version: 6.7.0(ws@8.18.3)(zod@3.25.76) devDependencies: '@ai-sdk/provider': specifier: ^1.1.3 @@ -4188,12 +4188,12 @@ packages: oniguruma-to-es@4.3.3: resolution: {integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==} - openai@5.23.2: - resolution: {integrity: sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==} + openai@6.7.0: + resolution: {integrity: sha512-mgSQXa3O/UXTbA8qFzoa7aydbXBJR5dbLQXCRapAOtoNT+v69sLdKMZzgiakpqhclRnhPggPAXoniVGn2kMY2A==} hasBin: true peerDependencies: ws: ^8.18.0 - zod: ^3.23.8 + zod: ^3.25 || ^4.0 peerDependenciesMeta: ws: optional: true @@ -10028,7 +10028,7 @@ snapshots: regex: 6.0.1 regex-recursion: 6.0.2 - openai@5.23.2(ws@8.18.3)(zod@3.25.76): + openai@6.7.0(ws@8.18.3)(zod@3.25.76): optionalDependencies: ws: 8.18.3 zod: 3.25.76