@ai-sdk/open-responses 2.0.0-beta.4 → 2.0.0-beta.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,6 @@
1
- import { JSONSchema7 } from '@ai-sdk/provider';
2
- import { lazySchema } from '@ai-sdk/provider-utils';
1
+ import type { JSONSchema7 } from '@ai-sdk/provider';
2
+ import { lazySchema, zodSchema } from '@ai-sdk/provider-utils';
3
3
  import { z } from 'zod/v4';
4
- import { zodSchema } from '@ai-sdk/provider-utils';
5
4
 
6
5
  export const openResponsesErrorSchema = lazySchema(() =>
7
6
  zodSchema(
@@ -1,9 +1,10 @@
1
- import { FetchFunction } from '@ai-sdk/provider-utils';
1
+ import type { FetchFunction } from '@ai-sdk/provider-utils';
2
2
 
3
3
  export type OpenResponsesConfig = {
4
4
  provider: string;
5
+ providerOptionsName: string;
5
6
  url: string;
6
- headers: () => Record<string, string | undefined>;
7
+ headers?: () => Record<string, string | undefined>;
7
8
  fetch?: FetchFunction;
8
9
  generateId: () => string;
9
10
  };
@@ -0,0 +1,22 @@
1
+ import {
2
+ lazySchema,
3
+ zodSchema,
4
+ type InferSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod/v4';
7
+
8
+ export const openResponsesLanguageModelOptions = lazySchema(() =>
9
+ zodSchema(
10
+ z.object({
11
+ /**
12
+ * Controls reasoning summary output from the model.
13
+ * Valid values: 'concise', 'detailed', 'auto'.
14
+ */
15
+ reasoningSummary: z.enum(['concise', 'detailed', 'auto']).nullish(),
16
+ }),
17
+ ),
18
+ );
19
+
20
+ export type OpenResponsesLanguageModelOptions = InferSchema<
21
+ typeof openResponsesLanguageModelOptions
22
+ >;
@@ -1,4 +1,4 @@
1
- import {
1
+ import type {
2
2
  LanguageModelV4,
3
3
  LanguageModelV4CallOptions,
4
4
  LanguageModelV4Content,
@@ -14,22 +14,29 @@ import {
14
14
  createEventSourceResponseHandler,
15
15
  createJsonErrorResponseHandler,
16
16
  createJsonResponseHandler,
17
+ isCustomReasoning,
17
18
  jsonSchema,
18
- ParseResult,
19
+ mapReasoningToProviderEffort,
20
+ parseProviderOptions,
19
21
  postJsonToApi,
22
+ serializeModelOptions,
23
+ WORKFLOW_SERIALIZE,
24
+ WORKFLOW_DESERIALIZE,
25
+ type ParseResult,
20
26
  } from '@ai-sdk/provider-utils';
21
27
  import { z } from 'zod/v4';
22
28
  import { convertToOpenResponsesInput } from './convert-to-open-responses-input';
23
29
  import {
24
- FunctionToolParam,
25
- OpenResponsesRequestBody,
26
- OpenResponsesResponseBody,
27
- OpenResponsesChunk,
28
30
  openResponsesErrorSchema,
29
- ToolChoiceParam,
31
+ type FunctionToolParam,
32
+ type OpenResponsesRequestBody,
33
+ type OpenResponsesResponseBody,
34
+ type OpenResponsesChunk,
35
+ type ToolChoiceParam,
30
36
  } from './open-responses-api';
31
37
  import { mapOpenResponsesFinishReason } from './map-open-responses-finish-reason';
32
- import { OpenResponsesConfig } from './open-responses-config';
38
+ import type { OpenResponsesConfig } from './open-responses-config';
39
+ import { openResponsesLanguageModelOptions } from './open-responses-language-model-options';
33
40
 
34
41
  export class OpenResponsesLanguageModel implements LanguageModelV4 {
35
42
  readonly specificationVersion = 'v4';
@@ -38,6 +45,20 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
38
45
 
39
46
  private readonly config: OpenResponsesConfig;
40
47
 
48
+ static [WORKFLOW_SERIALIZE](model: OpenResponsesLanguageModel) {
49
+ return serializeModelOptions({
50
+ modelId: model.modelId,
51
+ config: model.config,
52
+ });
53
+ }
54
+
55
+ static [WORKFLOW_DESERIALIZE](options: {
56
+ modelId: string;
57
+ config: OpenResponsesConfig;
58
+ }) {
59
+ return new OpenResponsesLanguageModel(options.modelId, options.config);
60
+ }
61
+
41
62
  constructor(modelId: string, config: OpenResponsesConfig) {
42
63
  this.modelId = modelId;
43
64
  this.config = config;
@@ -60,6 +81,7 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
60
81
  presencePenalty,
61
82
  frequencyPenalty,
62
83
  seed,
84
+ reasoning,
63
85
  prompt,
64
86
  providerOptions,
65
87
  tools,
@@ -127,6 +149,28 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
127
149
  }
128
150
  : undefined;
129
151
 
152
+ const openResponsesOptions = await parseProviderOptions({
153
+ provider: this.config.providerOptionsName,
154
+ providerOptions,
155
+ schema: openResponsesLanguageModelOptions,
156
+ });
157
+
158
+ const resolvedReasoningEffort = isCustomReasoning(reasoning)
159
+ ? reasoning === 'none'
160
+ ? 'none'
161
+ : mapReasoningToProviderEffort({
162
+ reasoning,
163
+ effortMap: {
164
+ minimal: 'low',
165
+ low: 'low',
166
+ medium: 'medium',
167
+ high: 'high',
168
+ xhigh: 'xhigh',
169
+ },
170
+ warnings,
171
+ })
172
+ : undefined;
173
+
130
174
  return {
131
175
  body: {
132
176
  model: this.modelId,
@@ -137,6 +181,18 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
137
181
  top_p: topP,
138
182
  presence_penalty: presencePenalty,
139
183
  frequency_penalty: frequencyPenalty,
184
+ reasoning:
185
+ resolvedReasoningEffort != null ||
186
+ openResponsesOptions?.reasoningSummary != null
187
+ ? {
188
+ ...(resolvedReasoningEffort != null && {
189
+ effort: resolvedReasoningEffort,
190
+ }),
191
+ ...(openResponsesOptions?.reasoningSummary != null && {
192
+ summary: openResponsesOptions.reasoningSummary,
193
+ }),
194
+ }
195
+ : undefined,
140
196
  tools: functionTools?.length ? functionTools : undefined,
141
197
  tool_choice: convertedToolChoice,
142
198
  ...(textFormat != null && { text: { format: textFormat } }),
@@ -156,7 +212,7 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
156
212
  rawValue: rawResponse,
157
213
  } = await postJsonToApi({
158
214
  url: this.config.url,
159
- headers: combineHeaders(this.config.headers(), options.headers),
215
+ headers: combineHeaders(this.config.headers?.(), options.headers),
160
216
  body,
161
217
  failedResponseHandler: createJsonErrorResponseHandler({
162
218
  errorSchema: openResponsesErrorSchema,
@@ -261,7 +317,7 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
261
317
 
262
318
  const { responseHeaders, value: response } = await postJsonToApi({
263
319
  url: this.config.url,
264
- headers: combineHeaders(this.config.headers(), options.headers),
320
+ headers: combineHeaders(this.config.headers?.(), options.headers),
265
321
  body: {
266
322
  ...body,
267
323
  stream: true,
@@ -270,7 +326,6 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
270
326
  errorSchema: openResponsesErrorSchema,
271
327
  errorToMessage: error => error.error.message,
272
328
  }),
273
- // TODO consider validation
274
329
  successfulResponseHandler: createEventSourceResponseHandler(z.any()),
275
330
  abortSignal: options.abortSignal,
276
331
  fetch: this.config.fetch,
@@ -324,10 +379,10 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
324
379
  unified: 'other',
325
380
  raw: undefined,
326
381
  };
327
- const toolCallsByItemId: Record<
382
+ const toolCallsByItemId = new Map<
328
383
  string,
329
384
  { toolName?: string; toolCallId?: string; arguments?: string }
330
- > = {};
385
+ >();
331
386
 
332
387
  return {
333
388
  stream: response.pipeThrough(
@@ -359,41 +414,43 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
359
414
  chunk.type === 'response.output_item.added' &&
360
415
  chunk.item.type === 'function_call'
361
416
  ) {
362
- toolCallsByItemId[chunk.item.id] = {
417
+ toolCallsByItemId.set(chunk.item.id, {
363
418
  toolName: chunk.item.name,
364
419
  toolCallId: chunk.item.call_id,
365
420
  arguments: chunk.item.arguments,
366
- };
421
+ });
367
422
  } else if (
368
- (chunk as { type: string }).type ===
369
- 'response.function_call_arguments.delta'
423
+ chunk.type === 'response.function_call_arguments.delta'
370
424
  ) {
371
- const functionCallChunk = chunk as {
372
- item_id: string;
373
- delta: string;
374
- };
375
- const toolCall =
376
- toolCallsByItemId[functionCallChunk.item_id] ??
377
- (toolCallsByItemId[functionCallChunk.item_id] = {});
425
+ const functionCallChunk = chunk;
426
+ const toolCall = toolCallsByItemId.get(functionCallChunk.item_id);
427
+
428
+ if (toolCall == null) {
429
+ toolCallsByItemId.set(functionCallChunk.item_id, {
430
+ arguments: functionCallChunk.delta,
431
+ });
432
+ return;
433
+ }
434
+
378
435
  toolCall.arguments =
379
436
  (toolCall.arguments ?? '') + functionCallChunk.delta;
380
- } else if (
381
- (chunk as { type: string }).type ===
382
- 'response.function_call_arguments.done'
383
- ) {
384
- const functionCallChunk = chunk as {
385
- item_id: string;
386
- arguments: string;
387
- };
388
- const toolCall =
389
- toolCallsByItemId[functionCallChunk.item_id] ??
390
- (toolCallsByItemId[functionCallChunk.item_id] = {});
437
+ } else if (chunk.type === 'response.function_call_arguments.done') {
438
+ const functionCallChunk = chunk;
439
+ const toolCall = toolCallsByItemId.get(functionCallChunk.item_id);
440
+
441
+ if (toolCall == null) {
442
+ toolCallsByItemId.set(functionCallChunk.item_id, {
443
+ arguments: functionCallChunk.arguments,
444
+ });
445
+ return;
446
+ }
447
+
391
448
  toolCall.arguments = functionCallChunk.arguments;
392
449
  } else if (
393
450
  chunk.type === 'response.output_item.done' &&
394
451
  chunk.item.type === 'function_call'
395
452
  ) {
396
- const toolCall = toolCallsByItemId[chunk.item.id];
453
+ const toolCall = toolCallsByItemId.get(chunk.item.id);
397
454
  const toolName = toolCall?.toolName ?? chunk.item.name;
398
455
  const toolCallId = toolCall?.toolCallId ?? chunk.item.call_id;
399
456
  const input = toolCall?.arguments ?? chunk.item.arguments ?? '';
@@ -406,7 +463,7 @@ export class OpenResponsesLanguageModel implements LanguageModelV4 {
406
463
  });
407
464
  hasToolCalls = true;
408
465
 
409
- delete toolCallsByItemId[chunk.item.id];
466
+ toolCallsByItemId.delete(chunk.item.id);
410
467
  }
411
468
 
412
469
  // Reasoning events (note: response.reasoning_text.delta is an LM Studio extension, not in official spec)
package/dist/index.d.mts DELETED
@@ -1,34 +0,0 @@
1
- import { ProviderV4, LanguageModelV4 } from '@ai-sdk/provider';
2
- import { FetchFunction } from '@ai-sdk/provider-utils';
3
-
4
- declare const VERSION: string;
5
-
6
- interface OpenResponsesProvider extends ProviderV4 {
7
- (modelId: string): LanguageModelV4;
8
- }
9
- interface OpenResponsesProviderSettings {
10
- /**
11
- * URL for the Open Responses API POST endpoint.
12
- */
13
- url: string;
14
- /**
15
- * Provider name. Used as key for provider options and metadata.
16
- */
17
- name: string;
18
- /**
19
- * API key for authenticating requests.
20
- */
21
- apiKey?: string;
22
- /**
23
- * Custom headers to include in the requests.
24
- */
25
- headers?: Record<string, string>;
26
- /**
27
- * Custom fetch implementation. You can use it as a middleware to intercept requests,
28
- * or to provide a custom fetch implementation for e.g. testing.
29
- */
30
- fetch?: FetchFunction;
31
- }
32
- declare function createOpenResponses(options: OpenResponsesProviderSettings): OpenResponsesProvider;
33
-
34
- export { VERSION, createOpenResponses };