@ai-sdk/openai 3.0.137 → 3.0.138

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/dist/index.mjs CHANGED
@@ -655,10 +655,13 @@ function getResponseMetadata({
655
655
  }
656
656
 
657
657
  // src/chat/map-openai-finish-reason.ts
658
- function mapOpenAIFinishReason(finishReason) {
658
+ function mapOpenAIFinishReason({
659
+ finishReason,
660
+ hasRefusal = false
661
+ }) {
659
662
  switch (finishReason) {
660
663
  case "stop":
661
- return "stop";
664
+ return hasRefusal ? "content-filter" : "stop";
662
665
  case "length":
663
666
  return "length";
664
667
  case "content_filter":
@@ -688,6 +691,8 @@ var openaiChatResponseSchema = lazySchema2(
688
691
  message: z2.object({
689
692
  role: z2.literal("assistant").nullish(),
690
693
  content: z2.string().nullish(),
694
+ // set instead of `content` when the model refuses to answer:
695
+ refusal: z2.string().nullish(),
691
696
  audio: z2.object({
692
697
  transcript: z2.string().nullish()
693
698
  }).nullish(),
@@ -726,6 +731,20 @@ var openaiChatResponseSchema = lazySchema2(
726
731
  })
727
732
  )
728
733
  })
734
+ ).nullish(),
735
+ // logprobs of the refusal tokens (set instead of `content` when
736
+ // the model refuses to answer):
737
+ refusal: z2.array(
738
+ z2.object({
739
+ token: z2.string(),
740
+ logprob: z2.number(),
741
+ top_logprobs: z2.array(
742
+ z2.object({
743
+ token: z2.string(),
744
+ logprob: z2.number()
745
+ })
746
+ )
747
+ })
729
748
  ).nullish()
730
749
  }).nullish(),
731
750
  finish_reason: z2.string().nullish()
@@ -760,6 +779,8 @@ var openaiChatChunkSchema = lazySchema2(
760
779
  delta: z2.object({
761
780
  role: z2.enum(["assistant"]).nullish(),
762
781
  content: z2.string().nullish(),
782
+ // set instead of `content` when the model refuses to answer:
783
+ refusal: z2.string().nullish(),
763
784
  tool_calls: z2.array(
764
785
  z2.object({
765
786
  index: z2.number(),
@@ -795,6 +816,20 @@ var openaiChatChunkSchema = lazySchema2(
795
816
  })
796
817
  )
797
818
  })
819
+ ).nullish(),
820
+ // logprobs of the refusal tokens (set instead of `content` when
821
+ // the model refuses to answer):
822
+ refusal: z2.array(
823
+ z2.object({
824
+ token: z2.string(),
825
+ logprob: z2.number(),
826
+ top_logprobs: z2.array(
827
+ z2.object({
828
+ token: z2.string(),
829
+ logprob: z2.number()
830
+ })
831
+ )
832
+ })
798
833
  ).nullish()
799
834
  }).nullish(),
800
835
  finish_reason: z2.string().nullish(),
@@ -1236,7 +1271,7 @@ var OpenAIChatLanguageModel = class {
1236
1271
  };
1237
1272
  }
1238
1273
  async doGenerate(options) {
1239
- var _a2, _b, _c, _d, _e, _f, _g, _h;
1274
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
1240
1275
  const { args: body, warnings } = await this.getArgs(options);
1241
1276
  const {
1242
1277
  responseHeaders,
@@ -1268,6 +1303,11 @@ var OpenAIChatLanguageModel = class {
1268
1303
  if (text != null && text.length > 0) {
1269
1304
  content.push({ type: "text", text });
1270
1305
  }
1306
+ const refusal = choice.message.refusal;
1307
+ const hasRefusal = refusal != null && refusal.length > 0;
1308
+ if (hasRefusal) {
1309
+ content.push({ type: "text", text: refusal });
1310
+ }
1271
1311
  for (const toolCall of (_b = choice.message.tool_calls) != null ? _b : []) {
1272
1312
  content.push({
1273
1313
  type: "tool-call",
@@ -1294,14 +1334,22 @@ var OpenAIChatLanguageModel = class {
1294
1334
  if ((completionTokenDetails == null ? void 0 : completionTokenDetails.rejected_prediction_tokens) != null) {
1295
1335
  providerMetadata.openai.rejectedPredictionTokens = completionTokenDetails == null ? void 0 : completionTokenDetails.rejected_prediction_tokens;
1296
1336
  }
1297
- if (((_g = choice.logprobs) == null ? void 0 : _g.content) != null) {
1298
- providerMetadata.openai.logprobs = choice.logprobs.content;
1337
+ const contentLogprobs = (_g = choice.logprobs) == null ? void 0 : _g.content;
1338
+ const refusalLogprobs = (_h = choice.logprobs) == null ? void 0 : _h.refusal;
1339
+ if (contentLogprobs != null || refusalLogprobs != null) {
1340
+ providerMetadata.openai.logprobs = [
1341
+ ...contentLogprobs != null ? contentLogprobs : [],
1342
+ ...refusalLogprobs != null ? refusalLogprobs : []
1343
+ ];
1299
1344
  }
1300
1345
  return {
1301
1346
  content,
1302
1347
  finishReason: {
1303
- unified: mapOpenAIFinishReason(choice.finish_reason),
1304
- raw: (_h = choice.finish_reason) != null ? _h : void 0
1348
+ unified: mapOpenAIFinishReason({
1349
+ finishReason: choice.finish_reason,
1350
+ hasRefusal
1351
+ }),
1352
+ raw: (_i = choice.finish_reason) != null ? _i : void 0
1305
1353
  },
1306
1354
  usage: convertOpenAIChatUsage(response.usage),
1307
1355
  request: { body },
@@ -1354,6 +1402,10 @@ var OpenAIChatLanguageModel = class {
1354
1402
  let usage = void 0;
1355
1403
  let metadataExtracted = false;
1356
1404
  let isActiveText = false;
1405
+ let hasRefusal = false;
1406
+ let rawFinishReason = void 0;
1407
+ let hasLogprobs = false;
1408
+ const streamedLogprobs = [];
1357
1409
  const providerMetadata = { openai: {} };
1358
1410
  const result = {
1359
1411
  stream: checkedResponse.pipeThrough(
@@ -1366,18 +1418,20 @@ var OpenAIChatLanguageModel = class {
1366
1418
  controller.enqueue({ type: "stream-start", warnings });
1367
1419
  },
1368
1420
  transform(chunk, controller) {
1369
- var _a2, _b, _c, _d, _e;
1421
+ var _a2, _b, _c, _d;
1370
1422
  if (options.includeRawChunks) {
1371
1423
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
1372
1424
  }
1373
1425
  if (!chunk.success) {
1374
1426
  finishReason = { unified: "error", raw: void 0 };
1427
+ rawFinishReason = void 0;
1375
1428
  controller.enqueue({ type: "error", error: chunk.error });
1376
1429
  return;
1377
1430
  }
1378
1431
  const value = chunk.value;
1379
1432
  if ("error" in value) {
1380
1433
  finishReason = { unified: "error", raw: void 0 };
1434
+ rawFinishReason = void 0;
1381
1435
  controller.enqueue({ type: "error", error: value.error });
1382
1436
  return;
1383
1437
  }
@@ -1402,19 +1456,35 @@ var OpenAIChatLanguageModel = class {
1402
1456
  }
1403
1457
  const choice = value.choices[0];
1404
1458
  if ((choice == null ? void 0 : choice.finish_reason) != null) {
1405
- finishReason = {
1406
- unified: mapOpenAIFinishReason(choice.finish_reason),
1407
- raw: choice.finish_reason
1408
- };
1459
+ rawFinishReason = choice.finish_reason;
1409
1460
  }
1410
- if (((_e = choice == null ? void 0 : choice.logprobs) == null ? void 0 : _e.content) != null) {
1411
- providerMetadata.openai.logprobs = choice.logprobs.content;
1461
+ if ((choice == null ? void 0 : choice.logprobs) != null) {
1462
+ const contentLogprobs = choice.logprobs.content;
1463
+ const refusalLogprobs = choice.logprobs.refusal;
1464
+ if (contentLogprobs != null || refusalLogprobs != null) {
1465
+ hasLogprobs = true;
1466
+ streamedLogprobs.push(
1467
+ ...contentLogprobs != null ? contentLogprobs : [],
1468
+ ...refusalLogprobs != null ? refusalLogprobs : []
1469
+ );
1470
+ }
1412
1471
  }
1413
1472
  if ((choice == null ? void 0 : choice.delta) == null) {
1414
1473
  return;
1415
1474
  }
1416
1475
  const delta = choice.delta;
1417
- if (delta.content != null) {
1476
+ const textDeltas = [];
1477
+ if (delta.content != null && delta.content.length > 0) {
1478
+ textDeltas.push(delta.content);
1479
+ }
1480
+ if (delta.refusal != null && delta.refusal.length > 0) {
1481
+ hasRefusal = true;
1482
+ textDeltas.push(delta.refusal);
1483
+ }
1484
+ if (textDeltas.length === 0 && delta.content === "") {
1485
+ textDeltas.push(delta.content);
1486
+ }
1487
+ for (const textDelta of textDeltas) {
1418
1488
  if (!isActiveText) {
1419
1489
  controller.enqueue({ type: "text-start", id: "0" });
1420
1490
  isActiveText = true;
@@ -1422,7 +1492,7 @@ var OpenAIChatLanguageModel = class {
1422
1492
  controller.enqueue({
1423
1493
  type: "text-delta",
1424
1494
  id: "0",
1425
- delta: delta.content
1495
+ delta: textDelta
1426
1496
  });
1427
1497
  }
1428
1498
  if (delta.tool_calls != null) {
@@ -1447,6 +1517,18 @@ var OpenAIChatLanguageModel = class {
1447
1517
  controller.enqueue({ type: "text-end", id: "0" });
1448
1518
  }
1449
1519
  toolCallTracker.flush();
1520
+ if (rawFinishReason != null) {
1521
+ finishReason = {
1522
+ unified: mapOpenAIFinishReason({
1523
+ finishReason: rawFinishReason,
1524
+ hasRefusal
1525
+ }),
1526
+ raw: rawFinishReason
1527
+ };
1528
+ }
1529
+ if (hasLogprobs) {
1530
+ providerMetadata.openai.logprobs = streamedLogprobs;
1531
+ }
1450
1532
  controller.enqueue({
1451
1533
  type: "finish",
1452
1534
  finishReason,
@@ -1468,7 +1550,7 @@ function isOpenAIChatOutputChunk(chunk) {
1468
1550
  }
1469
1551
  return chunk.choices.some((choice) => {
1470
1552
  const delta = choice.delta;
1471
- return (delta == null ? void 0 : delta.content) != null && delta.content.length > 0 || (delta == null ? void 0 : delta.tool_calls) != null && delta.tool_calls.length > 0 || (delta == null ? void 0 : delta.annotations) != null && delta.annotations.length > 0;
1553
+ return (delta == null ? void 0 : delta.content) != null && delta.content.length > 0 || (delta == null ? void 0 : delta.refusal) != null && delta.refusal.length > 0 || (delta == null ? void 0 : delta.tool_calls) != null && delta.tool_calls.length > 0 || (delta == null ? void 0 : delta.annotations) != null && delta.annotations.length > 0;
1472
1554
  });
1473
1555
  }
1474
1556
 
@@ -4711,12 +4793,14 @@ var openaiResponsesReasoningProviderOptionsSchema = lazySchema22(
4711
4793
  // src/responses/map-openai-responses-finish-reason.ts
4712
4794
  function mapOpenAIResponseFinishReason({
4713
4795
  finishReason,
4714
- hasFunctionCall
4796
+ hasFunctionCall,
4797
+ hasRefusal = false
4715
4798
  }) {
4716
4799
  switch (finishReason) {
4717
4800
  case void 0:
4718
4801
  case null:
4719
- return hasFunctionCall ? "tool-calls" : "stop";
4802
+ if (hasFunctionCall) return "tool-calls";
4803
+ return hasRefusal ? "content-filter" : "stop";
4720
4804
  case "max_output_tokens":
4721
4805
  return "length";
4722
4806
  case "content_filter":
@@ -4826,6 +4910,8 @@ var openaiResponsesModeledChunkTypes = /* @__PURE__ */ new Set([
4826
4910
  "response.output_item.done",
4827
4911
  "response.output_text.annotation.added",
4828
4912
  "response.output_text.delta",
4913
+ "response.refusal.delta",
4914
+ "response.refusal.done",
4829
4915
  "response.reasoning_summary_part.added",
4830
4916
  "response.reasoning_summary_part.done",
4831
4917
  "response.reasoning_summary_text.delta"
@@ -4882,6 +4968,20 @@ var openaiResponsesChunkSchema = lazySchema23(
4882
4968
  })
4883
4969
  ).nullish()
4884
4970
  }),
4971
+ z23.object({
4972
+ type: z23.literal("response.refusal.delta"),
4973
+ item_id: z23.string(),
4974
+ output_index: z23.number().nullish(),
4975
+ content_index: z23.number().nullish(),
4976
+ delta: z23.string()
4977
+ }),
4978
+ z23.object({
4979
+ type: z23.literal("response.refusal.done"),
4980
+ item_id: z23.string(),
4981
+ output_index: z23.number().nullish(),
4982
+ content_index: z23.number().nullish(),
4983
+ refusal: z23.string()
4984
+ }),
4885
4985
  z23.object({
4886
4986
  type: z23.enum(["response.completed", "response.incomplete"]),
4887
4987
  response: z23.object({
@@ -5407,53 +5507,60 @@ var openaiResponsesResponseSchema = lazySchema23(
5407
5507
  role: z23.literal("assistant"),
5408
5508
  id: z23.string(),
5409
5509
  phase: z23.enum(["commentary", "final_answer"]).nullish(),
5510
+ // the API returns either text or a refusal as content parts:
5410
5511
  content: z23.array(
5411
- z23.object({
5412
- type: z23.literal("output_text"),
5413
- text: z23.string(),
5414
- logprobs: z23.array(
5415
- z23.object({
5416
- token: z23.string(),
5417
- logprob: z23.number(),
5418
- top_logprobs: z23.array(
5419
- z23.object({
5420
- token: z23.string(),
5421
- logprob: z23.number()
5422
- })
5423
- )
5424
- })
5425
- ).nullish(),
5426
- annotations: z23.array(
5427
- z23.discriminatedUnion("type", [
5428
- z23.object({
5429
- type: z23.literal("url_citation"),
5430
- start_index: z23.number(),
5431
- end_index: z23.number(),
5432
- url: z23.string(),
5433
- title: z23.string()
5434
- }),
5435
- z23.object({
5436
- type: z23.literal("file_citation"),
5437
- file_id: z23.string(),
5438
- filename: z23.string(),
5439
- index: z23.number()
5440
- }),
5441
- z23.object({
5442
- type: z23.literal("container_file_citation"),
5443
- container_id: z23.string(),
5444
- file_id: z23.string(),
5445
- filename: z23.string(),
5446
- start_index: z23.number(),
5447
- end_index: z23.number()
5448
- }),
5512
+ z23.discriminatedUnion("type", [
5513
+ z23.object({
5514
+ type: z23.literal("output_text"),
5515
+ text: z23.string(),
5516
+ logprobs: z23.array(
5449
5517
  z23.object({
5450
- type: z23.literal("file_path"),
5451
- file_id: z23.string(),
5452
- index: z23.number()
5518
+ token: z23.string(),
5519
+ logprob: z23.number(),
5520
+ top_logprobs: z23.array(
5521
+ z23.object({
5522
+ token: z23.string(),
5523
+ logprob: z23.number()
5524
+ })
5525
+ )
5453
5526
  })
5454
- ])
5455
- )
5456
- })
5527
+ ).nullish(),
5528
+ annotations: z23.array(
5529
+ z23.discriminatedUnion("type", [
5530
+ z23.object({
5531
+ type: z23.literal("url_citation"),
5532
+ start_index: z23.number(),
5533
+ end_index: z23.number(),
5534
+ url: z23.string(),
5535
+ title: z23.string()
5536
+ }),
5537
+ z23.object({
5538
+ type: z23.literal("file_citation"),
5539
+ file_id: z23.string(),
5540
+ filename: z23.string(),
5541
+ index: z23.number()
5542
+ }),
5543
+ z23.object({
5544
+ type: z23.literal("container_file_citation"),
5545
+ container_id: z23.string(),
5546
+ file_id: z23.string(),
5547
+ filename: z23.string(),
5548
+ start_index: z23.number(),
5549
+ end_index: z23.number()
5550
+ }),
5551
+ z23.object({
5552
+ type: z23.literal("file_path"),
5553
+ file_id: z23.string(),
5554
+ index: z23.number()
5555
+ })
5556
+ ])
5557
+ )
5558
+ }),
5559
+ z23.object({
5560
+ type: z23.literal("refusal"),
5561
+ refusal: z23.string()
5562
+ })
5563
+ ])
5457
5564
  )
5458
5565
  }),
5459
5566
  z23.object({
@@ -6590,6 +6697,7 @@ var OpenAIResponsesLanguageModel = class {
6590
6697
  )) != null ? _b : [];
6591
6698
  let hasFunctionCall = false;
6592
6699
  const hostedToolSearchCallIds = [];
6700
+ let hasRefusal = false;
6593
6701
  for (const part of response.output) {
6594
6702
  switch (part.type) {
6595
6703
  case "reasoning": {
@@ -6723,6 +6831,20 @@ var OpenAIResponsesLanguageModel = class {
6723
6831
  }
6724
6832
  case "message": {
6725
6833
  for (const contentPart of part.content) {
6834
+ if (contentPart.type === "refusal") {
6835
+ hasRefusal = true;
6836
+ content.push({
6837
+ type: "text",
6838
+ text: contentPart.refusal,
6839
+ providerMetadata: {
6840
+ [providerOptionsName]: {
6841
+ itemId: part.id,
6842
+ ...part.phase != null && { phase: part.phase }
6843
+ }
6844
+ }
6845
+ });
6846
+ continue;
6847
+ }
6726
6848
  if (((_h = (_g = options.providerOptions) == null ? void 0 : _g[providerOptionsName]) == null ? void 0 : _h.logprobs) && contentPart.logprobs) {
6727
6849
  logprobs.push(contentPart.logprobs);
6728
6850
  }
@@ -7022,7 +7144,8 @@ var OpenAIResponsesLanguageModel = class {
7022
7144
  finishReason: {
7023
7145
  unified: mapOpenAIResponseFinishReason({
7024
7146
  finishReason: (_C = response.incomplete_details) == null ? void 0 : _C.reason,
7025
- hasFunctionCall
7147
+ hasFunctionCall,
7148
+ hasRefusal
7026
7149
  }),
7027
7150
  raw: (_E = (_D = response.incomplete_details) == null ? void 0 : _D.reason) != null ? _E : void 0
7028
7151
  },
@@ -7093,6 +7216,7 @@ var OpenAIResponsesLanguageModel = class {
7093
7216
  const ongoingAnnotations = [];
7094
7217
  let activeMessagePhase;
7095
7218
  let hasFunctionCall = false;
7219
+ let hasRefusal = false;
7096
7220
  const activeReasoning = {};
7097
7221
  let serviceTier;
7098
7222
  let reasoningContext;
@@ -7866,6 +7990,15 @@ var OpenAIResponsesLanguageModel = class {
7866
7990
  if (((_u = (_t = options.providerOptions) == null ? void 0 : _t[providerOptionsName]) == null ? void 0 : _u.logprobs) && value.logprobs) {
7867
7991
  logprobs.push(value.logprobs);
7868
7992
  }
7993
+ } else if (isRefusalDeltaChunk(value)) {
7994
+ hasRefusal = true;
7995
+ controller.enqueue({
7996
+ type: "text-delta",
7997
+ id: value.item_id,
7998
+ delta: value.delta
7999
+ });
8000
+ } else if (isRefusalDoneChunk(value)) {
8001
+ hasRefusal = true;
7869
8002
  } else if (value.type === "response.reasoning_summary_part.added") {
7870
8003
  if (value.summary_index > 0) {
7871
8004
  const activeReasoningPart = activeReasoning[value.item_id];
@@ -7928,7 +8061,8 @@ var OpenAIResponsesLanguageModel = class {
7928
8061
  finishReason = {
7929
8062
  unified: mapOpenAIResponseFinishReason({
7930
8063
  finishReason: (_x = value.response.incomplete_details) == null ? void 0 : _x.reason,
7931
- hasFunctionCall
8064
+ hasFunctionCall,
8065
+ hasRefusal
7932
8066
  }),
7933
8067
  raw: (_z = (_y = value.response.incomplete_details) == null ? void 0 : _y.reason) != null ? _z : void 0
7934
8068
  };
@@ -8082,6 +8216,12 @@ var OpenAIResponsesLanguageModel = class {
8082
8216
  function isTextDeltaChunk(chunk) {
8083
8217
  return chunk.type === "response.output_text.delta";
8084
8218
  }
8219
+ function isRefusalDeltaChunk(chunk) {
8220
+ return chunk.type === "response.refusal.delta";
8221
+ }
8222
+ function isRefusalDoneChunk(chunk) {
8223
+ return chunk.type === "response.refusal.done";
8224
+ }
8085
8225
  function isOpenAIChatCompletionChunk(value) {
8086
8226
  const chunk = asRecord2(value);
8087
8227
  return chunk != null && Array.isArray(chunk.choices) && typeof chunk.type !== "string";
@@ -8579,7 +8719,7 @@ var OpenAITranscriptionModel = class {
8579
8719
  };
8580
8720
 
8581
8721
  // src/version.ts
8582
- var VERSION = true ? "3.0.137" : "0.0.0-test";
8722
+ var VERSION = true ? "3.0.138" : "0.0.0-test";
8583
8723
 
8584
8724
  // src/openai-provider.ts
8585
8725
  function createOpenAI(options = {}) {