@openclaw/ai 2026.7.2-beta.1 → 2026.7.2-beta.3

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.
Files changed (34) hide show
  1. package/dist/{anthropic-Cvm71xlk.mjs → anthropic-D7SyZQ5v.mjs} +58 -39
  2. package/dist/{api-registry-Byvoz8Ha.d.mts → api-registry-DXBIXISf.d.mts} +1 -1
  3. package/dist/{azure-openai-responses-b4lfJxYS.mjs → azure-openai-responses-BkZgyZ3I.mjs} +5 -4
  4. package/dist/{event-stream-uQspnL8S.d.mts → event-stream-BPemFrFW.d.mts} +1 -1
  5. package/dist/event-stream.d.mts +1 -1
  6. package/dist/{google-C7PoDjpW.mjs → google-C_biGbV7.mjs} +2 -2
  7. package/dist/{google-shared-C7ohrmOI.mjs → google-shared-BK-NoHl8.mjs} +5 -4
  8. package/dist/{google-vertex-L_ABazIA.mjs → google-vertex-CvdzF1U7.mjs} +2 -2
  9. package/dist/index.d.mts +4 -4
  10. package/dist/internal/anthropic.d.mts +8 -2
  11. package/dist/internal/anthropic.mjs +3 -3
  12. package/dist/internal/openai.d.mts +27 -2
  13. package/dist/internal/openai.mjs +5 -5
  14. package/dist/internal/runtime.d.mts +2 -2
  15. package/dist/internal/runtime.mjs +3 -2
  16. package/dist/internal/shared.d.mts +13 -2
  17. package/dist/internal/shared.mjs +2 -2
  18. package/dist/{mistral-D-39Trax.mjs → mistral-BdrQmDWp.mjs} +25 -9
  19. package/dist/{model-utils-Q1LSRIdo.mjs → model-utils-1GiZ2_rr.mjs} +3 -1
  20. package/dist/{openai-chatgpt-responses-DCA0K85L.mjs → openai-chatgpt-responses-DP63Qt01.mjs} +11 -9
  21. package/dist/{openai-completions-B2jr3vtJ.mjs → openai-completions-zLDfebnN.mjs} +42 -21
  22. package/dist/{openai-responses-DTpD8YVy.mjs → openai-responses-ClspWt4I.mjs} +3 -3
  23. package/dist/{openai-responses-shared-B9mtGvXq.mjs → openai-responses-shared-CwnGU0KW.mjs} +412 -284
  24. package/dist/{openai-tool-projection-cTLC4F65.mjs → openai-tool-projection-WHf2nuOI.mjs} +1 -1
  25. package/dist/provider-error-LMfTEkfO.mjs +40 -0
  26. package/dist/providers.d.mts +1 -1
  27. package/dist/providers.mjs +8 -8
  28. package/dist/{transform-messages-DNWpwvXA.mjs → transform-messages-eb6lxDLB.mjs} +18 -3
  29. package/dist/{types-Cx2zJtyz.d.mts → types-CYORveZ7.d.mts} +6 -0
  30. package/dist/types.d.mts +3 -3
  31. package/dist/{validation-Cej7htKc.d.mts → validation-BX8euiDv.d.mts} +1 -1
  32. package/dist/validation.d.mts +1 -1
  33. package/npm-shrinkwrap.json +2 -2
  34. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
2
- import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-Q1LSRIdo.mjs";
2
+ import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-1GiZ2_rr.mjs";
3
3
  import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
4
4
  import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
5
5
  import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
6
- import { T as normalizeOptionalString, i as extractToolResultText, l as isRecord, n as describeToolResultMediaPlaceholder, t as transformMessages, w as normalizeLowercaseStringOrEmpty, x as stripSystemPromptCacheBoundary } from "./transform-messages-DNWpwvXA.mjs";
6
+ import { D as normalizeLowercaseStringOrEmpty, O as normalizeOptionalString, f as isRecord, i as extractToolResultText, n as describeToolResultMediaPlaceholder, o as isImageWithMediaPayload, t as transformMessages, w as stripSystemPromptCacheBoundary } from "./transform-messages-eb6lxDLB.mjs";
7
7
  import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-RjWszj8c.mjs";
8
- import { t as projectOpenAITools } from "./openai-tool-projection-cTLC4F65.mjs";
8
+ import { t as projectOpenAITools } from "./openai-tool-projection-WHf2nuOI.mjs";
9
9
  import { t as shortHash } from "./hash-CHgqbJmD.mjs";
10
10
  import { createHash, randomUUID } from "node:crypto";
11
11
  //#region packages/normalization-core/src/string-normalization.ts
@@ -1076,6 +1076,82 @@ function resolveResponsesMessageSnapshotCollapse(params) {
1076
1076
  return { kind: "keep" };
1077
1077
  }
1078
1078
  //#endregion
1079
+ //#region packages/ai/src/providers/openai-responses-tool-call-tracker.ts
1080
+ function readIdentityValue(value) {
1081
+ return (typeof value === "string" ? value.trim() : "") || void 0;
1082
+ }
1083
+ function readOutputIndex(event) {
1084
+ return typeof event.output_index === "number" && Number.isInteger(event.output_index) && event.output_index >= 0 ? event.output_index : void 0;
1085
+ }
1086
+ function readEventIdentity(event) {
1087
+ return { itemId: readIdentityValue(event.item_id) };
1088
+ }
1089
+ function readResponsesToolCallItemIdentity(item) {
1090
+ return {
1091
+ itemId: readIdentityValue(item.id),
1092
+ callId: readIdentityValue(item.call_id)
1093
+ };
1094
+ }
1095
+ function createResponsesToolCallTracker() {
1096
+ const indexedCalls = /* @__PURE__ */ new Map();
1097
+ const unindexedCalls = /* @__PURE__ */ new Set();
1098
+ const identitiesConflict = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId !== identity.itemId || state.callId && identity.callId && state.callId !== identity.callId);
1099
+ const sharesIdentity = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId === identity.itemId || state.callId && identity.callId && state.callId === identity.callId);
1100
+ const adoptIdentity = (state, identity) => {
1101
+ state.itemId ??= identity.itemId;
1102
+ state.callId ??= identity.callId;
1103
+ return state;
1104
+ };
1105
+ const resolveCompatible = (candidates, identity) => {
1106
+ const uniqueCandidates = [...new Set(candidates)];
1107
+ if (!identity.itemId && !identity.callId) return uniqueCandidates.length === 1 ? uniqueCandidates.at(0) : void 0;
1108
+ const compatible = uniqueCandidates.filter((state) => !identitiesConflict(state, identity));
1109
+ const matches = compatible.filter((state) => sharesIdentity(state, identity));
1110
+ const matched = matches.length === 1 ? matches.at(0) : void 0;
1111
+ if (matched) return adoptIdentity(matched, identity);
1112
+ const soleCompatible = uniqueCandidates.length === 1 && compatible.length === 1 && matches.length === 0 ? compatible.at(0) : void 0;
1113
+ return soleCompatible ? adoptIdentity(soleCompatible, identity) : void 0;
1114
+ };
1115
+ return {
1116
+ register(event, state) {
1117
+ const outputIndex = readOutputIndex(event);
1118
+ if (outputIndex === void 0) {
1119
+ unindexedCalls.add(state);
1120
+ return;
1121
+ }
1122
+ if (indexedCalls.has(outputIndex)) throw new Error(`Responses stream reused active tool-call output index ${outputIndex}`);
1123
+ indexedCalls.set(outputIndex, state);
1124
+ },
1125
+ resolve(event, identity = readEventIdentity(event)) {
1126
+ const outputIndex = readOutputIndex(event);
1127
+ if (outputIndex !== void 0) {
1128
+ const indexed = indexedCalls.get(outputIndex);
1129
+ if (indexed) {
1130
+ if (indexed.callId && identity.callId && indexed.callId !== identity.callId) return;
1131
+ return adoptIdentity(indexed, identity);
1132
+ }
1133
+ const unindexed = resolveCompatible(unindexedCalls, identity);
1134
+ if (unindexed) {
1135
+ unindexedCalls.delete(unindexed);
1136
+ indexedCalls.set(outputIndex, unindexed);
1137
+ }
1138
+ return unindexed;
1139
+ }
1140
+ return resolveCompatible([...indexedCalls.values(), ...unindexedCalls], identity);
1141
+ },
1142
+ forget(toolCall) {
1143
+ for (const [outputIndex, tracked] of indexedCalls) if (tracked === toolCall) indexedCalls.delete(outputIndex);
1144
+ unindexedCalls.delete(toolCall);
1145
+ },
1146
+ markArgumentsUnreliable() {
1147
+ for (const toolCall of /* @__PURE__ */ new Set([...indexedCalls.values(), ...unindexedCalls])) toolCall.argumentStreamReliable = false;
1148
+ },
1149
+ hasActive() {
1150
+ return indexedCalls.size > 0 || unindexedCalls.size > 0;
1151
+ }
1152
+ };
1153
+ }
1154
+ //#endregion
1079
1155
  //#region packages/ai/src/providers/openai-tool-schema.ts
1080
1156
  /**
1081
1157
  * OpenAI strict JSON-schema normalization for tool inventories and request payloads.
@@ -1386,7 +1462,8 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
1386
1462
  };
1387
1463
  const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
1388
1464
  if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) {
1389
- const role = model.reasoning ? "developer" : "system";
1465
+ const compat = model.compat;
1466
+ const role = model.reasoning && compat?.supportsDeveloperRole !== false ? "developer" : "system";
1390
1467
  messages.push({
1391
1468
  type: "message",
1392
1469
  role,
@@ -1484,7 +1561,7 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
1484
1561
  } else if (msg.role === "toolResult") {
1485
1562
  const textResult = extractToolResultText(msg.content);
1486
1563
  const sanitizedTextResult = sanitizeSurrogates(textResult);
1487
- const hasImages = msg.content.some((c) => c.type === "image");
1564
+ const hasImages = msg.content.some(isImageWithMediaPayload);
1488
1565
  const mediaPlaceholder = describeToolResultMediaPlaceholder(msg.content);
1489
1566
  const hasText = sanitizedTextResult.trim().length > 0;
1490
1567
  const [callId] = splitResponsesToolCallId(msg.toolCallId);
@@ -1499,7 +1576,7 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
1499
1576
  type: "input_text",
1500
1577
  text: mediaPlaceholder
1501
1578
  });
1502
- for (const block of msg.content) if (block.type === "image") contentParts.push({
1579
+ for (const block of msg.content) if (isImageWithMediaPayload(block)) contentParts.push({
1503
1580
  type: "input_image",
1504
1581
  detail: "auto",
1505
1582
  image_url: `data:${block.mimeType};base64,${block.data}`
@@ -1555,7 +1632,7 @@ function resolveResponsesReasoningEffort(model, reasoning) {
1555
1632
  return clampedReasoning;
1556
1633
  }
1557
1634
  function applyCommonResponsesParams(params, model, context, options, config) {
1558
- if (options?.maxTokens) params.max_output_tokens = options.maxTokens;
1635
+ if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
1559
1636
  if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
1560
1637
  if (context.tools) {
1561
1638
  const converted = convertResponsesToolPayload(context.tools, { model });
@@ -1574,7 +1651,7 @@ function buildResponsesRequestOptions(options) {
1574
1651
  return {
1575
1652
  ...options?.signal ? { signal: options.signal } : {},
1576
1653
  ...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
1577
- ...options?.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
1654
+ maxRetries: options?.maxRetries ?? 0
1578
1655
  };
1579
1656
  }
1580
1657
  function cleanStreamingScratchBuffers(output) {
@@ -1613,7 +1690,7 @@ async function runResponsesStreamLifecycle(params) {
1613
1690
  onFirstEventTimeout: params.processStreamOptions?.onFirstEventTimeout ?? onFirstEventTimeout
1614
1691
  } : void 0);
1615
1692
  if (options?.signal?.aborted) throw new Error("Request was aborted");
1616
- if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
1693
+ if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
1617
1694
  stream.push({
1618
1695
  type: "done",
1619
1696
  reason: output.stopReason,
@@ -1635,62 +1712,52 @@ async function runResponsesStreamLifecycle(params) {
1635
1712
  }
1636
1713
  }
1637
1714
  async function processResponsesStream(openaiStream, output, stream, model, options) {
1638
- let currentItem = null;
1639
- let currentBlock = null;
1640
- const toolCallsByOutputIndex = /* @__PURE__ */ new Map();
1641
- const unindexedToolCalls = /* @__PURE__ */ new Set();
1715
+ const streamingToolCalls = createResponsesToolCallTracker();
1716
+ const outputSlots = /* @__PURE__ */ new Map();
1717
+ const reasoningBlocksById = /* @__PURE__ */ new Map();
1718
+ let unindexedOutputSlot;
1719
+ let terminalResponseEvent;
1642
1720
  let lastTextBlock = null;
1643
- let pendingMessageText = null;
1644
1721
  const blocks = output.content;
1645
1722
  const blockIndex = () => blocks.length - 1;
1646
- const readOutputIndex = (event) => typeof event.output_index === "number" && Number.isInteger(event.output_index) && event.output_index >= 0 ? event.output_index : void 0;
1647
- const readIdentityValue = (value) => {
1648
- return (typeof value === "string" ? value.trim() : "") || void 0;
1723
+ const readOutputIndex = (event) => {
1724
+ const outputIndex = event.output_index;
1725
+ return typeof outputIndex === "number" && Number.isInteger(outputIndex) && outputIndex >= 0 ? outputIndex : void 0;
1649
1726
  };
1650
- const readEventToolCallIdentity = (event) => ({ itemId: readIdentityValue(event.item_id) });
1651
- const readItemToolCallIdentity = (item) => ({
1652
- itemId: readIdentityValue(item.id),
1653
- callId: readIdentityValue(item.call_id)
1654
- });
1655
- const identitiesConflict = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId !== identity.itemId || state.callId && identity.callId && state.callId !== identity.callId);
1656
- const sharesIdentity = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId === identity.itemId || state.callId && identity.callId && state.callId === identity.callId);
1657
- const adoptToolCallIdentity = (state, identity) => {
1658
- state.itemId ??= identity.itemId;
1659
- state.callId ??= identity.callId;
1660
- return state;
1727
+ const registerOutputSlot = (event, slot) => {
1728
+ const outputIndex = readOutputIndex(event);
1729
+ if (outputIndex === void 0) {
1730
+ if (unindexedOutputSlot) throw new Error("Responses stream added overlapping unindexed output items");
1731
+ unindexedOutputSlot = slot;
1732
+ return;
1733
+ }
1734
+ if (outputSlots.has(outputIndex)) throw new Error(`Responses stream reused active output index ${outputIndex}`);
1735
+ outputSlots.set(outputIndex, slot);
1661
1736
  };
1662
- const resolveCompatibleToolCall = (candidates, identity) => {
1663
- const uniqueCandidates = [...new Set(candidates)];
1664
- if (!identity.itemId && !identity.callId) return uniqueCandidates.length === 1 ? uniqueCandidates.at(0) : void 0;
1665
- const compatible = uniqueCandidates.filter((state) => !identitiesConflict(state, identity));
1666
- const matches = compatible.filter((state) => sharesIdentity(state, identity));
1667
- const matched = matches.length === 1 ? matches.at(0) : void 0;
1668
- if (matched) return adoptToolCallIdentity(matched, identity);
1669
- const soleCompatible = uniqueCandidates.length === 1 && compatible.length === 1 && matches.length === 0 ? compatible.at(0) : void 0;
1670
- return soleCompatible ? adoptToolCallIdentity(soleCompatible, identity) : void 0;
1737
+ const resolveOutputSlot = (event, type) => {
1738
+ const outputIndex = readOutputIndex(event);
1739
+ let slot = outputIndex === void 0 ? unindexedOutputSlot : outputSlots.get(outputIndex);
1740
+ if (outputIndex === void 0 && !slot) {
1741
+ const matchingSlots = [...outputSlots.values()].filter((candidate) => candidate.type === type);
1742
+ slot = matchingSlots.length === 1 ? matchingSlots[0] : void 0;
1743
+ }
1744
+ return slot?.type === type ? slot : void 0;
1671
1745
  };
1672
- const resolveStreamingToolCall = (event, identity = readEventToolCallIdentity(event)) => {
1746
+ const forgetOutputSlot = (event, slot) => {
1673
1747
  const outputIndex = readOutputIndex(event);
1674
- if (outputIndex !== void 0) {
1675
- const indexed = toolCallsByOutputIndex.get(outputIndex);
1676
- if (indexed) return !identitiesConflict(indexed, identity) ? adoptToolCallIdentity(indexed, identity) : void 0;
1677
- const unindexed = resolveCompatibleToolCall(unindexedToolCalls, identity);
1678
- if (unindexed) {
1679
- unindexedToolCalls.delete(unindexed);
1680
- toolCallsByOutputIndex.set(outputIndex, unindexed);
1681
- }
1682
- return unindexed;
1748
+ if (outputIndex === void 0) {
1749
+ if (unindexedOutputSlot === slot) unindexedOutputSlot = void 0;
1750
+ else for (const [indexedOutput, indexedSlot] of outputSlots) if (indexedSlot === slot) outputSlots.delete(indexedOutput);
1751
+ return;
1683
1752
  }
1684
- return resolveCompatibleToolCall([...toolCallsByOutputIndex.values(), ...unindexedToolCalls], identity);
1753
+ if (outputSlots.get(outputIndex) === slot) outputSlots.delete(outputIndex);
1685
1754
  };
1686
- const forgetStreamingToolCall = (toolCall) => {
1687
- for (const [trackedIndex, tracked] of toolCallsByOutputIndex) if (tracked === toolCall) toolCallsByOutputIndex.delete(trackedIndex);
1688
- unindexedToolCalls.delete(toolCall);
1755
+ const forgetToolCallOutputSlot = (toolCall) => {
1756
+ for (const [outputIndex, slot] of outputSlots) if (slot.type === "toolCall" && slot.toolCall === toolCall) outputSlots.delete(outputIndex);
1689
1757
  };
1690
- const markActiveToolCallArgumentsUnreliable = () => {
1691
- for (const toolCall of /* @__PURE__ */ new Set([...toolCallsByOutputIndex.values(), ...unindexedToolCalls])) toolCall.argumentStreamReliable = false;
1758
+ const readIdentityValue = (value) => {
1759
+ return (typeof value === "string" ? value.trim() : "") || void 0;
1692
1760
  };
1693
- const hasActiveStreamingToolCall = () => toolCallsByOutputIndex.size > 0 || unindexedToolCalls.size > 0;
1694
1761
  const resolveCompletedToolCallName = (toolCall, value) => {
1695
1762
  const streamedName = readIdentityValue(toolCall?.block.name);
1696
1763
  const completedName = readIdentityValue(value);
@@ -1699,28 +1766,143 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1699
1766
  if (!name) throw new Error("Responses stream completed tool call without a function name");
1700
1767
  return name;
1701
1768
  };
1702
- const appendPendingMessageDelta = (delta) => {
1703
- pendingMessageText = `${pendingMessageText ?? ""}${delta}`;
1704
- const priorText = lastTextBlock?.block.text ?? "";
1705
- if (priorText.startsWith(pendingMessageText) || pendingMessageText.startsWith(priorText)) return;
1706
- currentBlock = {
1769
+ const createOutputSlot = (event, item) => {
1770
+ if (item.type === "reasoning") {
1771
+ const block = {
1772
+ type: "thinking",
1773
+ thinking: ""
1774
+ };
1775
+ const slot = {
1776
+ type: "thinking",
1777
+ item,
1778
+ block,
1779
+ contentIndex: blocks.length
1780
+ };
1781
+ blocks.push(block);
1782
+ registerOutputSlot(event, slot);
1783
+ stream.push({
1784
+ type: "thinking_start",
1785
+ contentIndex: slot.contentIndex,
1786
+ partial: output
1787
+ });
1788
+ return slot;
1789
+ }
1790
+ if (item.type === "message") {
1791
+ const messageItem = item;
1792
+ const collapseCandidate = lastTextBlock;
1793
+ const block = collapseCandidate ? null : {
1794
+ type: "text",
1795
+ text: "",
1796
+ ...messageItem.phase ? { textSignature: encodeTextSignatureV1(messageItem.id, messageItem.phase) } : {}
1797
+ };
1798
+ const slot = {
1799
+ type: "text",
1800
+ item: messageItem,
1801
+ block,
1802
+ contentIndex: block ? blocks.length : void 0,
1803
+ pendingText: collapseCandidate ? "" : null,
1804
+ collapseCandidate
1805
+ };
1806
+ if (block) blocks.push(block);
1807
+ registerOutputSlot(event, slot);
1808
+ if (slot.contentIndex !== void 0) stream.push({
1809
+ type: "text_start",
1810
+ contentIndex: slot.contentIndex,
1811
+ partial: output
1812
+ });
1813
+ return slot;
1814
+ }
1815
+ };
1816
+ const resolveOutputItemSlot = (event, item) => {
1817
+ if (item.type === "reasoning") return resolveOutputSlot(event, "thinking");
1818
+ if (item.type === "message") return resolveOutputSlot(event, "text");
1819
+ const outputIndex = readOutputIndex(event);
1820
+ return outputIndex === void 0 ? void 0 : outputSlots.get(outputIndex);
1821
+ };
1822
+ const getOrCreateOutputSlot = (event, item) => {
1823
+ return resolveOutputItemSlot(event, item) ?? createOutputSlot(event, item);
1824
+ };
1825
+ const materializeDeferredTextSlot = (slot) => {
1826
+ if (slot.block || slot.pendingText === null) return;
1827
+ const text = slot.pendingText;
1828
+ slot.block = {
1707
1829
  type: "text",
1708
- text: pendingMessageText,
1709
- ...currentItem?.type === "message" && currentItem.phase ? { textSignature: encodeTextSignatureV1(currentItem.id, currentItem.phase ?? void 0) } : {}
1830
+ text,
1831
+ ...slot.item.phase ? { textSignature: encodeTextSignatureV1(slot.item.id, slot.item.phase) } : {}
1710
1832
  };
1711
- blocks.push(currentBlock);
1833
+ blocks.push(slot.block);
1834
+ slot.contentIndex = blockIndex();
1712
1835
  stream.push({
1713
1836
  type: "text_start",
1714
- contentIndex: blockIndex(),
1837
+ contentIndex: slot.contentIndex,
1715
1838
  partial: output
1716
1839
  });
1717
- stream.push({
1840
+ if (text) stream.push({
1718
1841
  type: "text_delta",
1719
- contentIndex: blockIndex(),
1720
- delta: pendingMessageText,
1842
+ contentIndex: slot.contentIndex,
1843
+ delta: text,
1721
1844
  partial: output
1722
1845
  });
1723
- pendingMessageText = null;
1846
+ if (lastTextBlock === slot.collapseCandidate) lastTextBlock = null;
1847
+ slot.pendingText = null;
1848
+ slot.collapseCandidate = null;
1849
+ };
1850
+ const materializeDeferredTextSlots = (except) => {
1851
+ for (const slot of outputSlots.values()) if (slot !== except && slot.type === "text") materializeDeferredTextSlot(slot);
1852
+ if (unindexedOutputSlot !== except && unindexedOutputSlot?.type === "text") materializeDeferredTextSlot(unindexedOutputSlot);
1853
+ };
1854
+ const appendPendingMessageDelta = (slot, delta) => {
1855
+ slot.pendingText = `${slot.pendingText ?? ""}${delta}`;
1856
+ const priorText = slot.collapseCandidate?.block.text ?? "";
1857
+ if (priorText.startsWith(slot.pendingText) || slot.pendingText.startsWith(priorText)) return;
1858
+ materializeDeferredTextSlot(slot);
1859
+ };
1860
+ const backfillReasoningSignatures = (responseOutput) => {
1861
+ for (const item of responseOutput) {
1862
+ if (item.type !== "reasoning" || !item.encrypted_content) continue;
1863
+ const block = reasoningBlocksById.get(item.id);
1864
+ if (!block?.thinkingSignature) continue;
1865
+ const storedItem = JSON.parse(block.thinkingSignature);
1866
+ if (storedItem.encrypted_content) continue;
1867
+ block.thinkingSignature = JSON.stringify({
1868
+ ...storedItem,
1869
+ encrypted_content: item.encrypted_content
1870
+ });
1871
+ }
1872
+ };
1873
+ const finalizeResponse = (response) => {
1874
+ terminalResponseEvent = "finalized";
1875
+ backfillReasoningSignatures(response.output ?? []);
1876
+ if (response.id) output.responseId = response.id;
1877
+ if (response.usage) {
1878
+ const inputTokenDetails = response.usage.input_tokens_details;
1879
+ const cachedTokens = inputTokenDetails?.cached_tokens || 0;
1880
+ const cacheWriteTokens = inputTokenDetails?.cache_write_tokens || 0;
1881
+ output.usage = {
1882
+ input: Math.max(0, (response.usage.input_tokens || 0) - cachedTokens - cacheWriteTokens),
1883
+ output: response.usage.output_tokens || 0,
1884
+ cacheRead: cachedTokens,
1885
+ cacheWrite: cacheWriteTokens,
1886
+ totalTokens: response.usage.total_tokens || 0,
1887
+ cost: {
1888
+ input: 0,
1889
+ output: 0,
1890
+ cacheRead: 0,
1891
+ cacheWrite: 0,
1892
+ total: 0
1893
+ }
1894
+ };
1895
+ }
1896
+ calculateCost(model, output.usage);
1897
+ if (options?.applyServiceTierPricing) {
1898
+ const serviceTier = options.resolveServiceTier ? options.resolveServiceTier(response.service_tier, options.serviceTier) : response.service_tier ?? options.serviceTier;
1899
+ options.applyServiceTierPricing(output.usage, serviceTier);
1900
+ }
1901
+ if (response.status === "incomplete" && response.incomplete_details?.reason === "content_filter") {
1902
+ output.stopReason = "error";
1903
+ output.errorMessage = "Provider incomplete_reason: content_filter";
1904
+ } else output.stopReason = mapStopReason(response.status);
1905
+ if (output.content.some((block) => block.type === "toolCall") && output.stopReason === "stop") output.stopReason = "toolUse";
1724
1906
  };
1725
1907
  const guardedStream = withFirstStreamEventTimeout(openaiStream, {
1726
1908
  provider: model.provider,
@@ -1734,62 +1916,31 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1734
1916
  });
1735
1917
  for await (const event of guardedStream) if (event.type === "response.created") output.responseId = event.response.id;
1736
1918
  else if (event.type === "response.output_item.added") {
1919
+ materializeDeferredTextSlots();
1737
1920
  const item = event.item;
1738
- if (item.type !== "message") {
1739
- lastTextBlock = null;
1740
- pendingMessageText = null;
1741
- }
1742
- if (item.type === "reasoning") {
1743
- currentItem = item;
1744
- currentBlock = {
1745
- type: "thinking",
1746
- thinking: ""
1747
- };
1748
- output.content.push(currentBlock);
1749
- stream.push({
1750
- type: "thinking_start",
1751
- contentIndex: blockIndex(),
1752
- partial: output
1753
- });
1754
- } else if (item.type === "message") {
1755
- currentItem = item;
1756
- if (lastTextBlock) {
1757
- currentBlock = null;
1758
- pendingMessageText = "";
1759
- } else {
1760
- currentBlock = {
1761
- type: "text",
1762
- text: "",
1763
- ...item.phase ? { textSignature: encodeTextSignatureV1(item.id, item.phase) } : {}
1764
- };
1765
- output.content.push(currentBlock);
1766
- stream.push({
1767
- type: "text_start",
1768
- contentIndex: blockIndex(),
1769
- partial: output
1770
- });
1771
- }
1772
- } else if (item.type === "function_call") {
1773
- const outputIndex = readOutputIndex(event);
1774
- if (outputIndex !== void 0 && toolCallsByOutputIndex.has(outputIndex)) throw new Error(`Responses stream reused active tool-call output index ${outputIndex}`);
1775
- currentItem = item;
1776
- currentBlock = {
1921
+ if (item.type !== "message") lastTextBlock = null;
1922
+ if (item.type === "reasoning" || item.type === "message") createOutputSlot(event, item);
1923
+ else if (item.type === "function_call") {
1924
+ const toolCallBlock = {
1777
1925
  type: "toolCall",
1778
1926
  id: resolveResponsesToolCallId(item),
1779
1927
  name: readIdentityValue(item.name) ?? "",
1780
1928
  arguments: {},
1781
1929
  partialJson: item.arguments || ""
1782
1930
  };
1783
- output.content.push(currentBlock);
1784
- const contentIndex = blockIndex();
1931
+ const contentIndex = output.content.length;
1785
1932
  const toolCallState = {
1786
- block: currentBlock,
1933
+ block: toolCallBlock,
1787
1934
  contentIndex,
1788
1935
  argumentStreamReliable: true,
1789
- ...readItemToolCallIdentity(item)
1936
+ ...readResponsesToolCallItemIdentity(item)
1790
1937
  };
1791
- if (outputIndex !== void 0) toolCallsByOutputIndex.set(outputIndex, toolCallState);
1792
- else unindexedToolCalls.add(toolCallState);
1938
+ streamingToolCalls.register(event, toolCallState);
1939
+ if (readOutputIndex(event) !== void 0) registerOutputSlot(event, {
1940
+ type: "toolCall",
1941
+ toolCall: toolCallState
1942
+ });
1943
+ output.content.push(toolCallBlock);
1793
1944
  stream.push({
1794
1945
  type: "toolcall_start",
1795
1946
  contentIndex,
@@ -1797,116 +1948,110 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1797
1948
  });
1798
1949
  }
1799
1950
  } else if (event.type === "response.reasoning_summary_part.added") {
1800
- if (currentItem && currentItem.type === "reasoning") {
1801
- currentItem.summary = currentItem.summary || [];
1802
- currentItem.summary.push(event.part);
1803
- }
1951
+ const slot = resolveOutputSlot(event, "thinking");
1952
+ if (!slot) continue;
1953
+ slot.item.summary = slot.item.summary || [];
1954
+ slot.item.summary.push(event.part);
1804
1955
  } else if (event.type === "response.reasoning_summary_text.delta") {
1805
- if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
1806
- currentItem.summary = currentItem.summary || [];
1807
- const lastPart = currentItem.summary[currentItem.summary.length - 1];
1808
- if (lastPart) {
1809
- currentBlock.thinking += event.delta;
1810
- lastPart.text += event.delta;
1811
- stream.push({
1812
- type: "thinking_delta",
1813
- contentIndex: blockIndex(),
1814
- delta: event.delta,
1815
- partial: output
1816
- });
1817
- }
1818
- }
1956
+ const slot = resolveOutputSlot(event, "thinking");
1957
+ if (!slot) continue;
1958
+ slot.item.summary = slot.item.summary || [];
1959
+ const lastPart = slot.item.summary[slot.item.summary.length - 1];
1960
+ if (!lastPart) continue;
1961
+ slot.block.thinking += event.delta;
1962
+ lastPart.text += event.delta;
1963
+ stream.push({
1964
+ type: "thinking_delta",
1965
+ contentIndex: slot.contentIndex,
1966
+ delta: event.delta,
1967
+ partial: output
1968
+ });
1819
1969
  } else if (event.type === "response.reasoning_summary_part.done") {
1820
- if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
1821
- currentItem.summary = currentItem.summary || [];
1822
- const lastPart = currentItem.summary[currentItem.summary.length - 1];
1823
- if (lastPart) {
1824
- currentBlock.thinking += "\n\n";
1825
- lastPart.text += "\n\n";
1826
- stream.push({
1827
- type: "thinking_delta",
1828
- contentIndex: blockIndex(),
1829
- delta: "\n\n",
1830
- partial: output
1831
- });
1832
- }
1833
- }
1970
+ const slot = resolveOutputSlot(event, "thinking");
1971
+ if (!slot) continue;
1972
+ slot.item.summary = slot.item.summary || [];
1973
+ const lastPart = slot.item.summary[slot.item.summary.length - 1];
1974
+ if (!lastPart) continue;
1975
+ slot.block.thinking += "\n\n";
1976
+ lastPart.text += "\n\n";
1977
+ stream.push({
1978
+ type: "thinking_delta",
1979
+ contentIndex: slot.contentIndex,
1980
+ delta: "\n\n",
1981
+ partial: output
1982
+ });
1834
1983
  } else if (event.type === "response.reasoning_text.delta") {
1835
- if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
1836
- currentBlock.thinking += event.delta;
1984
+ const slot = resolveOutputSlot(event, "thinking");
1985
+ if (!slot) continue;
1986
+ slot.block.thinking += event.delta;
1987
+ stream.push({
1988
+ type: "thinking_delta",
1989
+ contentIndex: slot.contentIndex,
1990
+ delta: event.delta,
1991
+ partial: output
1992
+ });
1993
+ } else if (event.type === "response.content_part.added") {
1994
+ const slot = resolveOutputSlot(event, "text");
1995
+ if (!slot) continue;
1996
+ slot.item.content = slot.item.content || [];
1997
+ if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
1998
+ } else if (event.type === "response.output_text.delta") {
1999
+ const slot = resolveOutputSlot(event, "text");
2000
+ if (!slot?.item.content || slot.item.content.length === 0) continue;
2001
+ const lastPart = slot.item.content[slot.item.content.length - 1];
2002
+ if (!isResponsesTextContentPartType(lastPart?.type)) continue;
2003
+ lastPart.text += event.delta;
2004
+ if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
2005
+ else if (slot.block && slot.contentIndex !== void 0) {
2006
+ slot.block.text += event.delta;
1837
2007
  stream.push({
1838
- type: "thinking_delta",
1839
- contentIndex: blockIndex(),
2008
+ type: "text_delta",
2009
+ contentIndex: slot.contentIndex,
1840
2010
  delta: event.delta,
1841
2011
  partial: output
1842
2012
  });
1843
2013
  }
1844
- } else if (event.type === "response.content_part.added") {
1845
- if (currentItem?.type === "message") {
1846
- currentItem.content = currentItem.content || [];
1847
- if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") currentItem.content.push(event.part);
1848
- }
1849
- } else if (event.type === "response.output_text.delta") {
1850
- if (currentItem?.type === "message") {
1851
- if (!currentItem.content || currentItem.content.length === 0) continue;
1852
- const lastPart = currentItem.content[currentItem.content.length - 1];
1853
- if (isResponsesTextContentPartType(lastPart?.type)) {
1854
- lastPart.text += event.delta;
1855
- if (pendingMessageText !== null) appendPendingMessageDelta(event.delta);
1856
- else if (currentBlock?.type === "text") {
1857
- currentBlock.text += event.delta;
1858
- stream.push({
1859
- type: "text_delta",
1860
- contentIndex: blockIndex(),
1861
- delta: event.delta,
1862
- partial: output
1863
- });
1864
- }
1865
- }
1866
- }
1867
2014
  } else if (isAzureResponsesTextDeltaEvent(event)) {
1868
- if (currentItem?.type === "message") {
1869
- currentItem.content = currentItem.content || [];
1870
- let lastPart = currentItem.content[currentItem.content.length - 1];
1871
- if (lastPart?.type !== "text") {
1872
- lastPart = {
1873
- type: "text",
1874
- text: ""
1875
- };
1876
- currentItem.content.push(lastPart);
1877
- }
1878
- lastPart.text += event.delta;
1879
- if (pendingMessageText !== null) appendPendingMessageDelta(event.delta);
1880
- else if (currentBlock?.type === "text") {
1881
- currentBlock.text += event.delta;
1882
- stream.push({
1883
- type: "text_delta",
1884
- contentIndex: blockIndex(),
1885
- delta: event.delta,
1886
- partial: output
1887
- });
1888
- }
2015
+ const slot = resolveOutputSlot(event, "text");
2016
+ if (!slot) continue;
2017
+ slot.item.content = slot.item.content || [];
2018
+ let lastPart = slot.item.content[slot.item.content.length - 1];
2019
+ if (lastPart?.type !== "text") {
2020
+ lastPart = {
2021
+ type: "text",
2022
+ text: ""
2023
+ };
2024
+ slot.item.content.push(lastPart);
2025
+ }
2026
+ lastPart.text += event.delta;
2027
+ if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
2028
+ else if (slot.block && slot.contentIndex !== void 0) {
2029
+ slot.block.text += event.delta;
2030
+ stream.push({
2031
+ type: "text_delta",
2032
+ contentIndex: slot.contentIndex,
2033
+ delta: event.delta,
2034
+ partial: output
2035
+ });
1889
2036
  }
1890
2037
  } else if (event.type === "response.refusal.delta") {
1891
- if (currentItem?.type === "message") {
1892
- if (!currentItem.content || currentItem.content.length === 0) continue;
1893
- const lastPart = currentItem.content[currentItem.content.length - 1];
1894
- if (lastPart?.type === "refusal") {
1895
- lastPart.refusal += event.delta;
1896
- if (pendingMessageText !== null) appendPendingMessageDelta(event.delta);
1897
- else if (currentBlock?.type === "text") {
1898
- currentBlock.text += event.delta;
1899
- stream.push({
1900
- type: "text_delta",
1901
- contentIndex: blockIndex(),
1902
- delta: event.delta,
1903
- partial: output
1904
- });
1905
- }
1906
- }
2038
+ const slot = resolveOutputSlot(event, "text");
2039
+ if (!slot?.item.content || slot.item.content.length === 0) continue;
2040
+ const lastPart = slot.item.content[slot.item.content.length - 1];
2041
+ if (lastPart?.type !== "refusal") continue;
2042
+ lastPart.refusal += event.delta;
2043
+ if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
2044
+ else if (slot.block && slot.contentIndex !== void 0) {
2045
+ slot.block.text += event.delta;
2046
+ stream.push({
2047
+ type: "text_delta",
2048
+ contentIndex: slot.contentIndex,
2049
+ delta: event.delta,
2050
+ partial: output
2051
+ });
1907
2052
  }
1908
2053
  } else if (event.type === "response.function_call_arguments.delta") {
1909
- const toolCall = resolveStreamingToolCall(event);
2054
+ const toolCall = streamingToolCalls.resolve(event);
1910
2055
  if (toolCall) {
1911
2056
  toolCall.block.partialJson += event.delta;
1912
2057
  toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
@@ -1916,9 +2061,9 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1916
2061
  delta: event.delta,
1917
2062
  partial: output
1918
2063
  });
1919
- } else if (hasActiveStreamingToolCall()) markActiveToolCallArgumentsUnreliable();
2064
+ } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
1920
2065
  } else if (event.type === "response.function_call_arguments.done") {
1921
- const toolCall = resolveStreamingToolCall(event);
2066
+ const toolCall = streamingToolCalls.resolve(event);
1922
2067
  if (toolCall) {
1923
2068
  const previousPartialJson = toolCall.block.partialJson;
1924
2069
  const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
@@ -1936,78 +2081,84 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1936
2081
  partial: output
1937
2082
  });
1938
2083
  }
1939
- } else if (hasActiveStreamingToolCall()) markActiveToolCallArgumentsUnreliable();
2084
+ } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
1940
2085
  } else if (event.type === "response.output_item.done") {
1941
2086
  const item = event.item;
1942
- if (item.type !== "message") {
1943
- lastTextBlock = null;
1944
- pendingMessageText = null;
1945
- }
1946
- if (item.type === "reasoning" && currentBlock?.type === "thinking") {
2087
+ if (item.type !== "message") lastTextBlock = null;
2088
+ const existingOutputSlot = resolveOutputItemSlot(event, item);
2089
+ materializeDeferredTextSlots(existingOutputSlot);
2090
+ const outputSlot = existingOutputSlot ?? getOrCreateOutputSlot(event, item);
2091
+ if (item.type === "reasoning" && outputSlot?.type === "thinking") {
1947
2092
  const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
1948
2093
  const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
1949
- currentBlock.thinking = summaryText || contentText || currentBlock.thinking;
1950
- currentBlock.thinkingSignature = JSON.stringify(item);
2094
+ outputSlot.block.thinking = summaryText || contentText || outputSlot.block.thinking;
2095
+ outputSlot.block.thinkingSignature = JSON.stringify(item);
2096
+ if (typeof item.id === "string") reasoningBlocksById.set(item.id, outputSlot.block);
1951
2097
  stream.push({
1952
2098
  type: "thinking_end",
1953
- contentIndex: blockIndex(),
1954
- content: currentBlock.thinking,
2099
+ contentIndex: outputSlot.contentIndex,
2100
+ content: outputSlot.block.thinking,
1955
2101
  partial: output
1956
2102
  });
1957
- currentBlock = null;
1958
- } else if (item.type === "message" && (currentBlock?.type === "text" || pendingMessageText !== null)) {
1959
- const finalText = item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
2103
+ forgetOutputSlot(event, outputSlot);
2104
+ } else if (item.type === "message" && outputSlot?.type === "text" && (outputSlot.block || outputSlot.pendingText !== null)) {
2105
+ const streamedText = outputSlot.pendingText ?? outputSlot.block?.text ?? "";
2106
+ const finalText = item.content == null ? streamedText : item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
1960
2107
  const phase = item.phase ?? void 0;
1961
- const collapse = pendingMessageText !== null ? resolveResponsesMessageSnapshotCollapse({
1962
- prior: lastTextBlock && {
1963
- text: lastTextBlock.block.text,
1964
- phase: lastTextBlock.phase
2108
+ const collapse = outputSlot.pendingText !== null ? resolveResponsesMessageSnapshotCollapse({
2109
+ prior: outputSlot.collapseCandidate && {
2110
+ text: outputSlot.collapseCandidate.block.text,
2111
+ phase: outputSlot.collapseCandidate.phase
1965
2112
  },
1966
2113
  nextText: finalText,
1967
2114
  nextPhase: phase
1968
2115
  }) : { kind: "keep" };
1969
- pendingMessageText = null;
1970
- if (collapse.kind === "extend" && lastTextBlock) {
1971
- lastTextBlock.block.text = collapse.text;
1972
- lastTextBlock.block.textSignature = encodeTextSignatureV1(item.id, phase);
2116
+ outputSlot.pendingText = null;
2117
+ if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
2118
+ outputSlot.collapseCandidate.block.text = collapse.text;
2119
+ outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
1973
2120
  stream.push({
1974
2121
  type: "text_end",
1975
- contentIndex: lastTextBlock.index,
2122
+ contentIndex: outputSlot.collapseCandidate.index,
1976
2123
  content: collapse.text,
1977
2124
  partial: output
1978
2125
  });
2126
+ lastTextBlock = outputSlot.collapseCandidate;
1979
2127
  } else {
1980
- if (currentBlock?.type !== "text") {
1981
- currentBlock = {
2128
+ if (!outputSlot.block) {
2129
+ outputSlot.block = {
1982
2130
  type: "text",
1983
2131
  text: "",
1984
2132
  ...phase ? { textSignature: encodeTextSignatureV1(item.id, phase) } : {}
1985
2133
  };
1986
- blocks.push(currentBlock);
2134
+ blocks.push(outputSlot.block);
2135
+ outputSlot.contentIndex = blockIndex();
1987
2136
  stream.push({
1988
2137
  type: "text_start",
1989
- contentIndex: blockIndex(),
2138
+ contentIndex: outputSlot.contentIndex,
1990
2139
  partial: output
1991
2140
  });
1992
2141
  }
1993
- currentBlock.text = finalText;
1994
- currentBlock.textSignature = encodeTextSignatureV1(item.id, phase);
2142
+ outputSlot.block.text = finalText;
2143
+ outputSlot.block.textSignature = encodeTextSignatureV1(item.id, phase);
2144
+ const contentIndex = outputSlot.contentIndex;
2145
+ if (contentIndex === void 0) throw new Error("Responses stream finalized text without a content index");
1995
2146
  lastTextBlock = {
1996
- block: currentBlock,
1997
- index: blockIndex(),
2147
+ block: outputSlot.block,
2148
+ index: contentIndex,
1998
2149
  phase
1999
2150
  };
2000
2151
  stream.push({
2001
2152
  type: "text_end",
2002
- contentIndex: blockIndex(),
2003
- content: currentBlock.text,
2153
+ contentIndex,
2154
+ content: outputSlot.block.text,
2004
2155
  partial: output
2005
2156
  });
2006
2157
  }
2007
- currentBlock = null;
2158
+ forgetOutputSlot(event, outputSlot);
2008
2159
  } else if (item.type === "function_call") {
2009
- const streamingToolCall = resolveStreamingToolCall(event, readItemToolCallIdentity(item));
2010
- if (!streamingToolCall && hasActiveStreamingToolCall()) continue;
2160
+ const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
2161
+ if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
2011
2162
  const completedName = resolveCompletedToolCallName(streamingToolCall, item.name);
2012
2163
  const streamedArguments = streamingToolCall?.block.partialJson ?? "";
2013
2164
  const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
@@ -2038,10 +2189,9 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2038
2189
  partial: output
2039
2190
  });
2040
2191
  }
2041
- if (streamingToolCall) forgetStreamingToolCall(streamingToolCall);
2042
- if (currentBlock === toolCall) {
2043
- currentBlock = null;
2044
- currentItem = null;
2192
+ if (streamingToolCall) {
2193
+ streamingToolCalls.forget(streamingToolCall);
2194
+ forgetToolCallOutputSlot(streamingToolCall);
2045
2195
  }
2046
2196
  stream.push({
2047
2197
  type: "toolcall_end",
@@ -2050,44 +2200,22 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2050
2200
  partial: output
2051
2201
  });
2052
2202
  }
2053
- } else if (event.type === "response.completed") {
2054
- if (hasActiveStreamingToolCall()) throw new Error("Responses stream completed with unresolved tool calls");
2055
- const response = event.response;
2056
- if (response?.id) output.responseId = response.id;
2057
- if (response?.usage) {
2058
- const inputTokenDetails = response.usage.input_tokens_details;
2059
- const cachedTokens = inputTokenDetails?.cached_tokens || 0;
2060
- const cacheWriteTokens = inputTokenDetails?.cache_write_tokens || 0;
2061
- output.usage = {
2062
- input: Math.max(0, (response.usage.input_tokens || 0) - cachedTokens - cacheWriteTokens),
2063
- output: response.usage.output_tokens || 0,
2064
- cacheRead: cachedTokens,
2065
- cacheWrite: cacheWriteTokens,
2066
- totalTokens: response.usage.total_tokens || 0,
2067
- cost: {
2068
- input: 0,
2069
- output: 0,
2070
- cacheRead: 0,
2071
- cacheWrite: 0,
2072
- total: 0
2073
- }
2074
- };
2075
- }
2076
- calculateCost(model, output.usage);
2077
- if (options?.applyServiceTierPricing) {
2078
- const serviceTier = options.resolveServiceTier ? options.resolveServiceTier(response?.service_tier, options.serviceTier) : response?.service_tier ?? options.serviceTier;
2079
- options.applyServiceTierPricing(output.usage, serviceTier);
2080
- }
2081
- output.stopReason = mapStopReason(response?.status);
2082
- if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") output.stopReason = "toolUse";
2203
+ } else if (event.type === "response.completed" || event.type === "response.incomplete") {
2204
+ if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
2205
+ finalizeResponse(event.response);
2083
2206
  } else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
2084
2207
  else if (event.type === "response.failed") {
2085
2208
  const error = event.response?.error;
2086
2209
  const details = event.response?.incomplete_details;
2087
- const msg = error ? `${error.code || "unknown"}: ${error.message || "no message"}` : details?.reason ? `incomplete: ${details.reason}` : "Unknown error (no error details in response)";
2088
- throw new Error(msg);
2210
+ output.responseId = event.response.id;
2211
+ output.stopReason = "error";
2212
+ output.errorMessage = error ? `${error.code || "unknown"}: ${error.message || "no message"}` : details?.reason ? `incomplete: ${details.reason}` : "Unknown error (no error details in response)";
2213
+ terminalResponseEvent = "failed";
2214
+ break;
2089
2215
  }
2090
- if (hasActiveStreamingToolCall()) throw new Error("Responses stream ended with unresolved tool calls");
2216
+ if (terminalResponseEvent === "failed") return;
2217
+ if (streamingToolCalls.hasActive()) throw new Error("Responses stream ended with unresolved tool calls");
2218
+ if (!terminalResponseEvent) throw new Error("OpenAI Responses stream ended before a terminal response event");
2091
2219
  }
2092
2220
  function mapStopReason(status) {
2093
2221
  if (!status) return "stop";
@@ -2102,4 +2230,4 @@ function mapStopReason(status) {
2102
2230
  }
2103
2231
  }
2104
2232
  //#endregion
2105
- export { supportsOpenAITemperature as A, isOpenAIGpt54MiniModel as C, resolveOpenAIReasoningEffortForModel as D, normalizeOpenAIReasoningEffort as E, stripUnsupportedSchemaKeywords as F, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as I, cleanSchemaForGemini as L, normalizeToolParameterSchema as M, resolveUnsupportedToolSchemaKeywords as N, resolveOpenAISupportedReasoningEfforts as O, shouldOmitEmptyArrayItems as P, resolveResponsesMessageSnapshotCollapse as S, isOpenAIGpt56Model as T, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as _, resolveResponsesReasoningEffort as a, isResponsesTextContentPartType as b, clearOpenAIToolSchemaCacheForTest as c, normalizeOpenAIStrictToolParameters as d, normalizeStrictOpenAIJsonSchema as f, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as g, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as h, processResponsesStream as i, extractToolSchemaModelCompat as j, supportsOpenAIReasoningEffort as k, findOpenAIStrictToolProjectionDiagnostics as l, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as m, convertResponsesMessages as n, runResponsesStreamLifecycle as o, resolveOpenAIProjectedToolsStrictToolFlag as p, createResponsesAssistantOutput as r, convertResponsesToolPayload as s, applyCommonResponsesParams as t, isStrictOpenAIJsonSchemaCompatible as u, isAzureResponsesTextDeltaEvent as v, isOpenAIGpt55Model as w, isResponsesTextDeltaEventType as x, isAzureResponsesTextDeltaEventType as y };
2233
+ export { resolveOpenAISupportedReasoningEfforts as A, isResponsesTextDeltaEventType as C, isOpenAIGpt56Model as D, isOpenAIGpt55Model as E, resolveUnsupportedToolSchemaKeywords as F, shouldOmitEmptyArrayItems as I, stripUnsupportedSchemaKeywords as L, supportsOpenAITemperature as M, extractToolSchemaModelCompat as N, normalizeOpenAIReasoningEffort as O, normalizeToolParameterSchema as P, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as R, isResponsesTextContentPartType as S, isOpenAIGpt54MiniModel as T, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as _, resolveResponsesReasoningEffort as a, isAzureResponsesTextDeltaEvent as b, clearOpenAIToolSchemaCacheForTest as c, normalizeOpenAIStrictToolParameters as d, normalizeStrictOpenAIJsonSchema as f, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as g, readResponsesToolCallItemIdentity as h, processResponsesStream as i, supportsOpenAIReasoningEffort as j, resolveOpenAIReasoningEffortForModel as k, findOpenAIStrictToolProjectionDiagnostics as l, createResponsesToolCallTracker as m, convertResponsesMessages as n, runResponsesStreamLifecycle as o, resolveOpenAIProjectedToolsStrictToolFlag as p, createResponsesAssistantOutput as r, convertResponsesToolPayload as s, applyCommonResponsesParams as t, isStrictOpenAIJsonSchemaCompatible as u, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as v, resolveResponsesMessageSnapshotCollapse as w, isAzureResponsesTextDeltaEventType as x, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as y, cleanSchemaForGemini as z };