Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/goofy-llamas-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@openai/agents-extensions': minor
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intentionally minor; also when we release this, we will update the documents too (currently we're asking users to use zod@3)

'@openai/agents-realtime': minor
'@openai/agents-openai': minor
'@openai/agents-core': minor
'@openai/agents': minor
---

feat: #561 support both zod3 and zod4
2 changes: 1 addition & 1 deletion integration-tests/deno.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('Deno', () => {
await execa`deno install`;
}, 60000);

test('should be able to run', async () => {
test('should be able to run', { timeout: 60000 }, async () => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated improvement

const { stdout } = await execa`deno --allow-net --allow-env main.ts`;
expect(stdout).toContain('[RESPONSE]Hello there![/RESPONSE]');
});
Expand Down
32 changes: 32 additions & 0 deletions integration-tests/node-zod3.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, test, expect, beforeAll } from 'vitest';
import { execa as execaBase } from 'execa';

const execa = execaBase({
cwd: './integration-tests/node-zod3',
env: {
...process.env,
NODE_OPTIONS: '',
TS_NODE_PROJECT: '',
TS_NODE_COMPILER_OPTIONS: '',
},
});

describe('Node.js', () => {
beforeAll(async () => {
// remove lock file to avoid errors
console.log('[node] Removing node_modules');
await execa`rm -rf node_modules`;
console.log('[node] Installing dependencies');
await execa`npm install`;
}, 60000);

test('should be able to run using CommonJS', async () => {
const { stdout } = await execa`npm run start:cjs`;
expect(stdout).toContain('[RESPONSE]Hello there![/RESPONSE]');
});

test('should be able to run using ESM', async () => {
const { stdout } = await execa`npm run start:esm`;
expect(stdout).toContain('[RESPONSE]Hello there![/RESPONSE]');
});
});
2 changes: 2 additions & 0 deletions integration-tests/node-zod3/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@openai:registry=http://localhost:4873
package-lock=false
37 changes: 37 additions & 0 deletions integration-tests/node-zod3/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// @ts-check

const {
Agent,
run,
tool,
setTraceProcessors,
ConsoleSpanExporter,
BatchTraceProcessor,
} = require('@openai/agents');

const { z } = require('zod');

setTraceProcessors([new BatchTraceProcessor(new ConsoleSpanExporter())]);

const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
return `The weather in ${input.city} is sunny`;
},
});

const agent = new Agent({
name: 'Test Agent',
instructions:
'You will always only respond with "Hello there!". Not more not less.',
tools: [getWeatherTool],
});

async function main() {
const result = await run(agent, 'Hey there!');
console.log(`[RESPONSE]${result.finalOutput}[/RESPONSE]`);
}

main().catch(console.error);
33 changes: 33 additions & 0 deletions integration-tests/node-zod3/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// @ts-check

import { z } from 'zod';

import {
Agent,
run,
tool,
setTraceProcessors,
ConsoleSpanExporter,
BatchTraceProcessor,
} from '@openai/agents';

setTraceProcessors([new BatchTraceProcessor(new ConsoleSpanExporter())]);

const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
return `The weather in ${input.city} is sunny`;
},
});

const agent = new Agent({
name: 'Test Agent',
instructions:
'You will always only respond with "Hello there!". Not more not less.',
tools: [getWeatherTool],
});

const result = await run(agent, 'What is the weather in San Francisco?');
console.log(`[RESPONSE]${result.finalOutput}[/RESPONSE]`);
13 changes: 13 additions & 0 deletions integration-tests/node-zod3/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"private": true,
"type": "commonjs",
"scripts": {
"start:cjs": "node --no-experimental-require-module index.cjs",
"start:esm": "node --no-experimental-require-module index.mjs"
},
"dependencies": {
"@openai/agents": "latest",
"typescript": "^5.9.3",
"zod": "^3.25.40"
}
}
32 changes: 32 additions & 0 deletions integration-tests/node-zod4.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, test, expect, beforeAll } from 'vitest';
import { execa as execaBase } from 'execa';

const execa = execaBase({
cwd: './integration-tests/node-zod4',
env: {
...process.env,
NODE_OPTIONS: '',
TS_NODE_PROJECT: '',
TS_NODE_COMPILER_OPTIONS: '',
},
});

describe('Node.js', () => {
beforeAll(async () => {
// remove lock file to avoid errors
console.log('[node] Removing node_modules');
await execa`rm -rf node_modules`;
console.log('[node] Installing dependencies');
await execa`npm install`;
}, 60000);

test('should be able to run using CommonJS', async () => {
const { stdout } = await execa`npm run start:cjs`;
expect(stdout).toContain('[RESPONSE]Hello there![/RESPONSE]');
});

test('should be able to run using ESM', async () => {
const { stdout } = await execa`npm run start:esm`;
expect(stdout).toContain('[RESPONSE]Hello there![/RESPONSE]');
});
});
2 changes: 2 additions & 0 deletions integration-tests/node-zod4/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@openai:registry=http://localhost:4873
package-lock=false
37 changes: 37 additions & 0 deletions integration-tests/node-zod4/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// @ts-check

const {
Agent,
run,
tool,
setTraceProcessors,
ConsoleSpanExporter,
BatchTraceProcessor,
} = require('@openai/agents');

const { z } = require('zod');

setTraceProcessors([new BatchTraceProcessor(new ConsoleSpanExporter())]);

const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
return `The weather in ${input.city} is sunny`;
},
});

const agent = new Agent({
name: 'Test Agent',
instructions:
'You will always only respond with "Hello there!". Not more not less.',
tools: [getWeatherTool],
});

async function main() {
const result = await run(agent, 'Hey there!');
console.log(`[RESPONSE]${result.finalOutput}[/RESPONSE]`);
}

main().catch(console.error);
33 changes: 33 additions & 0 deletions integration-tests/node-zod4/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// @ts-check

import { z } from 'zod';

import {
Agent,
run,
tool,
setTraceProcessors,
ConsoleSpanExporter,
BatchTraceProcessor,
} from '@openai/agents';

setTraceProcessors([new BatchTraceProcessor(new ConsoleSpanExporter())]);

const getWeatherTool = tool({
name: 'get_weather',
description: 'Get the weather for a given city',
parameters: z.object({ city: z.string() }),
execute: async (input) => {
return `The weather in ${input.city} is sunny`;
},
});

const agent = new Agent({
name: 'Test Agent',
instructions:
'You will always only respond with "Hello there!". Not more not less.',
tools: [getWeatherTool],
});

const result = await run(agent, 'What is the weather in San Francisco?');
console.log(`[RESPONSE]${result.finalOutput}[/RESPONSE]`);
13 changes: 13 additions & 0 deletions integration-tests/node-zod4/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"private": true,
"type": "commonjs",
"scripts": {
"start:cjs": "node --no-experimental-require-module index.cjs",
"start:esm": "node --no-experimental-require-module index.mjs"
},
"dependencies": {
"@openai/agents": "latest",
"typescript": "^5.9.3",
"zod": "^4"
}
}
1 change: 0 additions & 1 deletion integration-tests/node/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const {
ConsoleSpanExporter,
BatchTraceProcessor,
} = require('@openai/agents');
const { assert } = require('node:console');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unused


setTraceProcessors([new BatchTraceProcessor(new ConsoleSpanExporter())]);

Expand Down
2 changes: 1 addition & 1 deletion integration-tests/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
},
"dependencies": {
"@openai/agents": "latest",
"typescript": "^5.9.2"
"typescript": "^5.9.3"
}
}
24 changes: 24 additions & 0 deletions integration-tests/vite-react.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { describe, test, expect, beforeAll, afterAll } from 'vitest';
import { chromium } from 'playwright';
import { execa as execaBase, ResultPromise } from 'execa';
import { writeFile, unlink } from 'node:fs/promises';
import path from 'node:path';

const execa = execaBase({
cwd: './integration-tests/vite-react',
});

let server: ResultPromise;
const envPath = path.join(
process.cwd(),
'integration-tests',
'vite-react',
'.env',
);
let wroteEnvFile = false;

describe('Vite React', () => {
beforeAll(async () => {
Expand All @@ -16,10 +25,21 @@ describe('Vite React', () => {
await execa`rm -rf node_modules`;
console.log('[vite-react] Installing dependencies');
await execa`npm install`;

const apiKey = process.env.OPENAI_API_KEY;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated improvement; easier to run this test

if (!apiKey) {
throw new Error(
'OPENAI_API_KEY must be set to run the Vite React integration test.',
);
}
await writeFile(envPath, `VITE_OPENAI_API_KEY=${apiKey}\n`, 'utf8');
wroteEnvFile = true;

console.log('[vite-react] Building');
await execa`npm run build`;
console.log('[vite-react] Starting server');
server = execa`npm run preview -- --port 9999`;
server.catch(() => {});
await new Promise((resolve) => {
server.stdout?.on('data', (data) => {
if (data.toString().includes('http://localhost')) {
Expand All @@ -41,6 +61,7 @@ describe('Vite React', () => {
const root = await page.$('#root');
const span = await root?.waitForSelector('span[data-testid="response"]', {
state: 'attached',
timeout: 60000,
});
expect(await span?.textContent()).toBe('[RESPONSE]Hello there![/RESPONSE]');
await browser.close();
Expand All @@ -50,5 +71,8 @@ describe('Vite React', () => {
if (server) {
server.kill();
}
if (wroteEnvFile) {
await unlink(envPath).catch(() => {});
}
});
});
4 changes: 2 additions & 2 deletions packages/agents-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"debug": "^4.4.0"
},
"peerDependencies": {
"zod": "^3.25.40"
"zod": "^3.25.40 || ^4.0"
},
"peerDependenciesMeta": {
"zod": {
Expand Down Expand Up @@ -102,7 +102,7 @@
},
"devDependencies": {
"@types/debug": "^4.1.12",
"zod": "^3.25.40"
"zod": "^3.25.40 || ^4.0"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

align with underlying openai package

},
"files": [
"dist"
Expand Down
Loading