@ai-sdk/openai 4.0.24 → 4.0.25

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @ai-sdk/openai
2
2
 
3
+ ## 4.0.25
4
+
5
+ ### Patch Changes
6
+
7
+ - beaecb3: fix(provider/openai): resolve responses doStream at response.in_progress instead of first output token
8
+
9
+ The early-stream-error peek treated `response.in_progress` as an unknown chunk, so `doStream` did not resolve until the first output item arrived — delaying stream availability (and downstream TTFB for proxies/gateways) by the model's full time-to-first-token. `response.in_progress` is now modeled in the chunk schema and marks the request as accepted: the peek keeps watching for error frames for a short grace window (50ms) so quota/rate-limit errors flushed alongside `response.in_progress` still throw as retryable `APICallError`s, while healthy streams become available right after upstream acknowledges the request.
10
+
11
+ - b192878: feat: add experimental_toolCaller routing to generateText for code mode
12
+ - Updated dependencies [d8210b6]
13
+ - Updated dependencies [b192878]
14
+ - @ai-sdk/provider-utils@5.0.16
15
+
3
16
  ## 4.0.24
4
17
 
5
18
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -311,6 +311,14 @@ declare const openaiResponsesChunkSchema: _ai_sdk_provider_utils.LazySchema<{
311
311
  model: string;
312
312
  service_tier?: string | null | undefined;
313
313
  };
314
+ } | {
315
+ type: "response.in_progress";
316
+ response: {
317
+ id: string;
318
+ created_at: number;
319
+ model: string;
320
+ service_tier?: string | null | undefined;
321
+ };
314
322
  } | {
315
323
  type: "response.output_item.added";
316
324
  output_index: number;
@@ -1300,13 +1308,13 @@ declare const openaiTools: {
1300
1308
  * Programmatic Tool Calling lets OpenAI Responses models write and execute
1301
1309
  * JavaScript that orchestrates eligible tools.
1302
1310
  */
1303
- programmaticToolCalling: () => _ai_sdk_provider_utils.ProviderExecutedTool<{
1311
+ programmaticToolCalling: () => _ai_sdk_provider_utils.Experimental_ToolCallerTool<_ai_sdk_provider_utils.ProviderExecutedTool<{
1304
1312
  code: string;
1305
1313
  fingerprint: string;
1306
1314
  }, {
1307
1315
  result: string;
1308
1316
  status: "completed" | "incomplete";
1309
- }, {}>;
1317
+ }, {}>>;
1310
1318
  /**
1311
1319
  * Tool search allows the model to dynamically search for and load deferred
1312
1320
  * tools into the model's context as needed. This helps reduce overall token
package/dist/index.js CHANGED
@@ -83,15 +83,28 @@ async function throwIfOpenAIStreamErrorBeforeOutput({
83
83
  stream,
84
84
  getError,
85
85
  isOutputChunk,
86
+ isAcceptedChunk,
87
+ acceptedGraceMs = 50,
86
88
  url,
87
89
  requestBodyValues,
88
90
  responseHeaders
89
91
  }) {
90
92
  const [streamForEarlyError, streamForConsumer] = stream.tee();
91
93
  const reader = streamForEarlyError.getReader();
94
+ let drainAfterError = false;
92
95
  try {
96
+ let accepted = false;
93
97
  while (true) {
94
- const result = await reader.read();
98
+ let result;
99
+ if (accepted) {
100
+ const raced = await raceWithTimeout(reader.read(), acceptedGraceMs);
101
+ if (raced.timedOut) {
102
+ return streamForConsumer;
103
+ }
104
+ result = raced.value;
105
+ } else {
106
+ result = await reader.read();
107
+ }
95
108
  if (result.done) {
96
109
  return streamForConsumer;
97
110
  }
@@ -101,7 +114,10 @@ async function throwIfOpenAIStreamErrorBeforeOutput({
101
114
  }
102
115
  const errorFrame = getError(chunk.value);
103
116
  if (errorFrame != null) {
104
- streamForConsumer.cancel().catch(() => {
117
+ drainAfterError = true;
118
+ drainReader(reader).catch(() => {
119
+ });
120
+ drainReader(streamForConsumer.getReader()).catch(() => {
105
121
  });
106
122
  throw createOpenAIStreamError({
107
123
  frame: errorFrame,
@@ -113,13 +129,46 @@ async function throwIfOpenAIStreamErrorBeforeOutput({
113
129
  if (isOutputChunk(chunk.value)) {
114
130
  return streamForConsumer;
115
131
  }
132
+ if (!accepted && (isAcceptedChunk == null ? void 0 : isAcceptedChunk(chunk.value)) === true) {
133
+ accepted = true;
134
+ }
116
135
  }
117
136
  } finally {
118
- reader.cancel().catch(() => {
119
- });
137
+ if (!drainAfterError) {
138
+ reader.cancel().catch(() => {
139
+ });
140
+ reader.releaseLock();
141
+ }
142
+ }
143
+ }
144
+ async function drainReader(reader) {
145
+ try {
146
+ while (!(await reader.read()).done) {
147
+ }
148
+ } catch (e) {
149
+ } finally {
120
150
  reader.releaseLock();
121
151
  }
122
152
  }
153
+ async function raceWithTimeout(promise, timeoutMs) {
154
+ let timer;
155
+ const wrapped = promise.then((value) => ({ timedOut: false, value }));
156
+ try {
157
+ const raced = await Promise.race([
158
+ wrapped,
159
+ new Promise((resolve) => {
160
+ timer = setTimeout(() => resolve({ timedOut: true }), timeoutMs);
161
+ })
162
+ ]);
163
+ if (raced.timedOut) {
164
+ wrapped.catch(() => {
165
+ });
166
+ }
167
+ return raced;
168
+ } finally {
169
+ clearTimeout(timer);
170
+ }
171
+ }
123
172
  function createOpenAIStreamError({
124
173
  frame,
125
174
  url,
@@ -3114,6 +3163,7 @@ var mcp = (args) => mcpToolFactory(args);
3114
3163
  // src/tool/programmatic-tool-calling.ts
3115
3164
  import {
3116
3165
  createProviderExecutedToolFactory as createProviderExecutedToolFactory7,
3166
+ experimental_toolCaller,
3117
3167
  lazySchema as lazySchema23,
3118
3168
  zodSchema as zodSchema23
3119
3169
  } from "@ai-sdk/provider-utils";
@@ -3140,7 +3190,25 @@ var programmaticToolCallingFactory = createProviderExecutedToolFactory7({
3140
3190
  outputSchema: programmaticToolCallingOutputSchema,
3141
3191
  supportsDeferredResults: true
3142
3192
  });
3143
- var programmaticToolCalling = () => programmaticToolCallingFactory({});
3193
+ var programmaticToolCalling = () => experimental_toolCaller(programmaticToolCallingFactory({}), {
3194
+ type: "provider",
3195
+ prepareProviderOptions: (providerOptions) => {
3196
+ var _a;
3197
+ const openaiOptions = providerOptions == null ? void 0 : providerOptions.openai;
3198
+ return {
3199
+ ...providerOptions,
3200
+ openai: {
3201
+ ...openaiOptions,
3202
+ allowedCallers: [
3203
+ .../* @__PURE__ */ new Set([
3204
+ ...(_a = openaiOptions == null ? void 0 : openaiOptions.allowedCallers) != null ? _a : [],
3205
+ "programmatic"
3206
+ ])
3207
+ ]
3208
+ }
3209
+ };
3210
+ }
3211
+ });
3144
3212
 
3145
3213
  // src/openai-tools.ts
3146
3214
  var openaiTools = {
@@ -4870,6 +4938,15 @@ var openaiResponsesChunkSchema = lazySchema24(
4870
4938
  service_tier: z26.string().nullish()
4871
4939
  })
4872
4940
  }),
4941
+ z26.object({
4942
+ type: z26.literal("response.in_progress"),
4943
+ response: z26.object({
4944
+ id: z26.string(),
4945
+ created_at: z26.number(),
4946
+ model: z26.string(),
4947
+ service_tier: z26.string().nullish()
4948
+ })
4949
+ }),
4873
4950
  z26.object({
4874
4951
  type: z26.literal("response.output_item.added"),
4875
4952
  output_index: z26.number(),
@@ -7275,6 +7352,7 @@ var OpenAIResponsesLanguageModel = class _OpenAIResponsesLanguageModel {
7275
7352
  stream: response,
7276
7353
  getError: (chunk) => isErrorChunk(chunk) || isResponseFailedChunk(chunk) && chunk.response.error != null ? chunk : void 0,
7277
7354
  isOutputChunk: isResponseOutputChunk,
7355
+ isAcceptedChunk: isResponseInProgressChunk,
7278
7356
  url,
7279
7357
  requestBodyValues: body,
7280
7358
  responseHeaders
@@ -8316,8 +8394,11 @@ function isResponseAnnotationAddedChunk(chunk) {
8316
8394
  function isErrorChunk(chunk) {
8317
8395
  return chunk.type === "error";
8318
8396
  }
8397
+ function isResponseInProgressChunk(chunk) {
8398
+ return chunk.type === "response.in_progress";
8399
+ }
8319
8400
  function isResponseOutputChunk(chunk) {
8320
- return !(chunk.type === "response.created" || chunk.type === "response.failed" || chunk.type === "error" || chunk.type === "unknown_chunk");
8401
+ return !(chunk.type === "response.created" || chunk.type === "response.in_progress" || chunk.type === "response.failed" || chunk.type === "error" || chunk.type === "unknown_chunk");
8321
8402
  }
8322
8403
  function mapWebSearchOutput(action) {
8323
8404
  var _a;
@@ -9422,7 +9503,7 @@ var OpenAISkills = class {
9422
9503
  };
9423
9504
 
9424
9505
  // src/version.ts
9425
- var VERSION = true ? "4.0.24" : "0.0.0-test";
9506
+ var VERSION = true ? "4.0.25" : "0.0.0-test";
9426
9507
 
9427
9508
  // src/openai-provider.ts
9428
9509
  function createOpenAI(options = {}) {