Skip to content

Commit cdeb4e6

Browse files
committed
PR feedback
1 parent 5b52aa9 commit cdeb4e6

File tree

8 files changed

+42
-48
lines changed

8 files changed

+42
-48
lines changed

examples/tool-calls-beta-zod.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ async function main() {
1818
betaZodTool({
1919
name: 'getWeather',
2020
description: 'Get the weather at a specific location',
21-
inputSchema: z.object({
21+
parameters: z.object({
2222
location: z.string().describe('The city and state, e.g. San Francisco, CA'),
2323
}),
2424
run: ({ location }) => {
@@ -28,7 +28,7 @@ async function main() {
2828
betaZodTool({
2929
name: 'getTime',
3030
description: 'Get the current time in a specific timezone',
31-
inputSchema: z.object({
31+
parameters: z.object({
3232
timezone: z.string().describe('The timezone, e.g. America/Los_Angeles'),
3333
}),
3434
run: ({ timezone }) => {
@@ -38,7 +38,7 @@ async function main() {
3838
betaZodTool({
3939
name: 'getCurrencyExchangeRate',
4040
description: 'Get the exchange rate between two currencies',
41-
inputSchema: z.object({
41+
parameters: z.object({
4242
from_currency: z.string().describe('The currency to convert from, e.g. USD'),
4343
to_currency: z.string().describe('The currency to convert to, e.g. EUR'),
4444
}),

examples/tool-helpers-advanced-streaming.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ async function main() {
1818
betaZodTool({
1919
name: 'getWeather',
2020
description: 'Get the weather at a specific location',
21-
inputSchema: z.object({
21+
parameters: z.object({
2222
location: z.string().describe('The city and state, e.g. San Francisco, CA'),
2323
}),
2424
run: ({ location }) => {
@@ -28,7 +28,7 @@ async function main() {
2828
betaZodTool({
2929
name: 'getTime',
3030
description: 'Get the current time in a specific timezone',
31-
inputSchema: z.object({
31+
parameters: z.object({
3232
timezone: z.string().describe('The timezone, e.g. America/Los_Angeles'),
3333
}),
3434
run: ({ timezone }) => {
@@ -38,7 +38,7 @@ async function main() {
3838
betaZodTool({
3939
name: 'getCurrencyExchangeRate',
4040
description: 'Get the exchange rate between two currencies',
41-
inputSchema: z.object({
41+
parameters: z.object({
4242
from_currency: z.string().describe('The currency to convert from, e.g. USD'),
4343
to_currency: z.string().describe('The currency to convert to, e.g. EUR'),
4444
}),

examples/tool-helpers-advanced.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ async function main() {
1818
betaZodTool({
1919
name: 'getWeather',
2020
description: 'Get the weather at a specific location',
21-
inputSchema: z.object({
21+
parameters: z.object({
2222
location: z.string().describe('The city and state, e.g. San Francisco, CA'),
2323
}),
2424
run: ({ location }) => {

src/helpers/beta/zod.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import type { FunctionTool } from '../../resources/beta';
1111
*/
1212
export function betaZodTool<InputSchema extends ZodType>(options: {
1313
name: string;
14-
inputSchema: InputSchema;
14+
parameters: InputSchema;
1515
description: string;
1616
run: (args: zodInfer<InputSchema>) => Promisable<string | Array<FunctionTool>>; // TODO: I changed this but double check
1717
}): BetaRunnableTool<zodInfer<InputSchema>> {
18-
const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' });
18+
const jsonSchema = z.toJSONSchema(options.parameters, { reused: 'ref' });
1919

2020
if (jsonSchema.type !== 'object') {
2121
throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`);
@@ -35,6 +35,6 @@ export function betaZodTool<InputSchema extends ZodType>(options: {
3535
},
3636
},
3737
run: options.run,
38-
parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer<InputSchema>,
38+
parse: (args: unknown) => options.parameters.parse(args),
3939
};
4040
}

src/lib/beta/BetaToolRunner.ts

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ function promiseWithResolvers<T>(): {
3131
}
3232

3333
/**
34-
* A ToolRunner handles the automatic conversation loop between the assistant and tools.
34+
* A BetaToolRunner handles the automatic conversation loop between the assistant and tools.
3535
*
36-
* A ToolRunner is an async iterable that yields either BetaMessage or BetaMessageStream objects
37-
* depending on the streaming configuration.
36+
* A BetaToolRunner is an async iterable that yields either ChatCompletion or
37+
* ChatCompletionStream objects depending on the streaming configuration.
3838
*/
39-
export class BetaToolRunner<Stream extends boolean> {
39+
export class BetaToolRunner<Stream extends boolean>
40+
implements AsyncIterable<Stream extends true ? ChatCompletionStream : ChatCompletion>
41+
{
4042
/** Whether the async iterator has been consumed */
4143
#consumed = false;
4244
/** Whether parameters have been mutated since the last API call */
@@ -72,8 +74,7 @@ export class BetaToolRunner<Stream extends boolean> {
7274
params: BetaToolRunnerParams,
7375
options?: BetaToolRunnerRequestOptions,
7476
) {
75-
params.n ??= 1;
76-
if (params && params.n > 1) {
77+
if (params.n && params.n > 1) {
7778
throw new Error('BetaToolRunner does not support n > 1');
7879
}
7980

@@ -97,7 +98,7 @@ export class BetaToolRunner<Stream extends boolean> {
9798
async *[Symbol.asyncIterator](): AsyncIterator<
9899
Stream extends true ?
99100
ChatCompletionStream // TODO: for now!
100-
: ChatCompletion | undefined
101+
: ChatCompletion
101102
> {
102103
if (this.#consumed) {
103104
throw new OpenAIError('Cannot iterate over a consumed stream');
@@ -123,26 +124,21 @@ export class BetaToolRunner<Stream extends boolean> {
123124
this.#toolResponse = undefined;
124125
this.#iterationCount++;
125126

126-
const { ...params } = this.#state.params;
127-
const apiParams = { ...params };
128-
delete apiParams.max_iterations; // our own param
127+
const { max_iterations, ...params } = this.#state.params;
129128

130129
if (params.stream) {
131-
stream = this.client.beta.chat.completions.stream({ ...apiParams, stream: true }, this.#options);
130+
stream = this.client.chat.completions.stream({ ...params, stream: true }, this.#options);
132131
this.#message = stream.finalMessage();
133132

134133
// Make sure that this promise doesn't throw before we get the option to do something about it.
135134
// Error will be caught when we call await this.#message ultimately
136135
this.#message?.catch(() => {});
137136
yield stream as any;
138137
} else {
139-
this.#chatCompletion = this.client.beta.chat.completions.create(
138+
this.#chatCompletion = this.client.chat.completions.create(
140139
{
141-
...apiParams, // spread and explicit so we get better types
140+
...params, // spread and explicit so we get better types
142141
stream: false,
143-
tools: params.tools,
144-
messages: params.messages,
145-
model: params.model,
146142
},
147143
this.#options,
148144
);
@@ -155,15 +151,8 @@ export class BetaToolRunner<Stream extends boolean> {
155151

156152
const prevMessage = await this.#message;
157153

158-
if (!prevMessage) {
159-
throw new OpenAIError('ToolRunner concluded without a message from the server');
160-
}
161-
162154
if (!this.#mutated) {
163-
// TODO: what if it is empty?
164-
if (prevMessage) {
165-
this.#state.params.messages.push(prevMessage);
166-
}
155+
this.#state.params.messages.push(prevMessage);
167156
}
168157

169158
const toolMessages = await this.#generateToolResponse(prevMessage);
@@ -173,7 +162,6 @@ export class BetaToolRunner<Stream extends boolean> {
173162
}
174163
}
175164

176-
// TODO: make sure this is correct?
177165
if (!toolMessages && !this.#mutated) {
178166
break;
179167
}
@@ -206,21 +194,28 @@ export class BetaToolRunner<Stream extends boolean> {
206194
*
207195
* @example
208196
* // Direct parameter update
209-
* runner.setMessagesParams({
197+
* runner.setChatParams({
210198
* model: 'gpt-4o',
211199
* max_tokens: 500,
212200
* });
213201
*
214202
* @example
215203
* // Using a mutator function
216-
* runner.setMessagesParams((params) => ({
204+
* runner.setChatParams((params) => ({
217205
* ...params,
218206
* max_tokens: 100,
219207
* }));
208+
*
209+
* @example
210+
* // Appending a user message
211+
* runner.setChatParams((params) => ({
212+
* ...params,
213+
* messages: [...params.messages, { role: 'user', content: 'What colour is the sky?' }],
214+
* }));
220215
*/
221-
setMessagesParams(params: BetaToolRunnerParams): void;
222-
setMessagesParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void;
223-
setMessagesParams(
216+
setChatParams(params: BetaToolRunnerParams): void;
217+
setChatParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void;
218+
setChatParams(
224219
paramsOrMutator: BetaToolRunnerParams | ((prevParams: BetaToolRunnerParams) => BetaToolRunnerParams),
225220
) {
226221
if (typeof paramsOrMutator === 'function') {
@@ -343,7 +338,7 @@ export class BetaToolRunner<Stream extends boolean> {
343338
* );
344339
*/
345340
pushMessages(...messages: ChatCompletionMessageParam[]) {
346-
this.setMessagesParams((params) => ({
341+
this.setChatParams((params) => ({
347342
...params,
348343
messages: [...params.messages, ...messages],
349344
}));

src/resources/beta/chat.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import {
44
type BetaToolRunnerParams,
55
type BetaToolRunnerRequestOptions,
66
} from '../../lib/beta/BetaToolRunner';
7-
import { Chat as ChatResource } from '../../resources';
87

9-
export class BetaCompletions extends ChatResource.Completions {
8+
export class BetaCompletions extends APIResource {
109
toolRunner(
1110
body: BetaToolRunnerParams & { stream?: false },
1211
options?: BetaToolRunnerRequestOptions,

tests/lib/tools/ToolRunner.test.ts renamed to tests/lib/tools/BetaToolRunner.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ describe('ToolRunner', () => {
942942
});
943943

944944
// Update parameters before iteration
945-
runner.setMessagesParams({
945+
runner.setChatParams({
946946
messages: [{ role: 'user', content: 'Updated message' }],
947947
model: 'gpt-4o',
948948
max_tokens: 200,
@@ -981,7 +981,7 @@ describe('ToolRunner', () => {
981981
expect(toolResponse).toMatchObject([getWeatherToolResult('Paris')]);
982982

983983
// Update params to append a custom tool_use block to messages
984-
runner.setMessagesParams({
984+
runner.setChatParams({
985985
...runner.params,
986986
messages: [
987987
...runner.params.messages,

tests/lib/tools/ToolRunnerE2E.test.ts renamed to tests/lib/tools/BetaToolRunnerE2E.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ describe('toolRunner integration tests', () => {
104104
) {
105105
return betaZodTool({
106106
name: 'test_tool',
107-
inputSchema: z.object({ value: z.string() }),
107+
parameters: z.object({ value: z.string() }),
108108
description: 'A test tool',
109109
run: () => 'Tool result',
110110
...customConfig,
@@ -114,7 +114,7 @@ describe('toolRunner integration tests', () => {
114114
function createCounterTool() {
115115
return betaZodTool({
116116
name: 'test_tool',
117-
inputSchema: z.object({ count: z.number() }),
117+
parameters: z.object({ count: z.number() }),
118118
description: 'A test tool',
119119
run: (args) => `Called with ${args.count}`,
120120
});
@@ -259,7 +259,7 @@ describe('toolRunner integration tests', () => {
259259
});
260260

261261
// Update parameters
262-
runner.setMessagesParams({
262+
runner.setChatParams({
263263
model: 'gpt-4o',
264264
max_tokens: 500,
265265
messages: [{ role: 'user', content: 'Updated message' }],

0 commit comments

Comments
 (0)