@openclaw/ai 2026.9.1-beta.1 → 2026.9.2
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/{anthropic-DI4PZKKB.mjs → anthropic-BDdqdVLK.mjs} +222 -216
- package/dist/{anthropic-compaction-replay-nhKaCXu6.mjs → anthropic-compaction-replay-DB2FGLQc.mjs} +160 -68
- package/dist/{anthropic-payload-policy-B_0n0enE.d.mts → anthropic-payload-policy-d46X2pR0.d.mts} +28 -4
- package/dist/{api-registry-CTd8NzcD.d.mts → api-registry-DWtPjzyn.d.mts} +2 -2
- package/dist/{azure-openai-responses-D8dI0ekg.mjs → azure-openai-responses-C5bZRfAP.mjs} +12 -9
- package/dist/{number-coercion-H9qHik3g.mjs → base64-CEFBpSkN.mjs} +73 -1
- package/dist/{diagnostics-COpOtRwq.mjs → diagnostics-CPeq9F7y.mjs} +5 -1
- package/dist/diagnostics-DfFyKeX_.mjs +136 -0
- package/dist/{diagnostics-BaTA9eVl.d.mts → diagnostics-DnPnOui6.d.mts} +5 -1
- package/dist/diagnostics.d.mts +8 -3
- package/dist/diagnostics.mjs +4 -3
- package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-bktO00EJ.mjs} +2 -15
- package/dist/{event-stream-uSMZJ3FA.mjs → event-stream-BgDvQeum.mjs} +3 -9
- package/dist/{event-stream-LiXePESD.d.mts → event-stream-BhT5T1Ay.d.mts} +1 -1
- package/dist/event-stream-zctLx0yr.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-Od-LLdVK.mjs → google-4qeuE8iX.mjs} +9 -7
- package/dist/{google-shared-Bgr9lFPw.mjs → google-shared-CWeG8RIl.mjs} +27 -23
- package/dist/{google-vertex-aerRSXc4.mjs → google-vertex-O9BcnB6X.mjs} +8 -6
- package/dist/{host-D51fmkH6.mjs → host-CEvLw30U.mjs} +54 -9
- package/dist/{host-DsbPMFU6.d.mts → host-DjzGmdZ2.d.mts} +3 -3
- package/dist/index-FnHM2FcI.d.mts +117 -0
- package/dist/index.d.mts +10 -11
- package/dist/index.mjs +6 -6
- package/dist/internal/anthropic.d.mts +59 -55
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
- package/dist/internal/openai-responses-payload-policy.mjs +2 -3
- package/dist/internal/openai.d.mts +66 -64
- package/dist/internal/openai.mjs +10 -10
- package/dist/internal/retry-after.d.mts +2 -3
- package/dist/internal/runtime.d.mts +43 -43
- package/dist/internal/runtime.mjs +10 -8
- package/dist/internal/shared.d.mts +25 -25
- package/dist/internal/shared.mjs +95 -4
- package/dist/{mistral-EiHdymeb.mjs → mistral-Tb6oalqH.mjs} +30 -23
- package/dist/{openai-chatgpt-responses-DHpF9o1e.mjs → openai-chatgpt-responses-yUXjPNfu.mjs} +76 -137
- package/dist/{openai-completions-EFPiUGfS.mjs → openai-completions-BIUV3RDT.mjs} +26 -22
- package/dist/{openai-completions-compat-BefmHT26.d.mts → openai-completions-compat-CpjYUArk.d.mts} +5 -5
- package/dist/{openai-completions-stream-DUlGwRMz.mjs → openai-completions-stream-BsrBe3Gg.mjs} +103 -96
- package/dist/openai-prompt-cache-CGnVB74a.mjs +21 -0
- package/dist/openai-prompt-cache-CNoIfHYC.d.mts +16 -0
- package/dist/{openai-responses-BogP8OjX.mjs → openai-responses-CCL41ALM.mjs} +15 -14
- package/dist/openai-responses-compaction-window-BMVHFOtq.mjs +697 -0
- package/dist/{openai-responses-contracts-Dvj_UtPy.d.mts → openai-responses-contracts-rF5DDRNS.d.mts} +23 -6
- package/dist/{openai-responses-payload-policy-CNGFT9zr.d.mts → openai-responses-payload-policy-rLRPsSmB.d.mts} +1 -0
- package/dist/{openai-responses-prompt-observer-internal-Cd4hJG-S.mjs → openai-responses-prompt-observer-internal-D0bhBfgL.mjs} +4 -18
- package/dist/{openai-responses-shared-DJThc6jW.mjs → openai-responses-shared-Bmma_3Qc.mjs} +438 -309
- package/dist/{openai-tool-schema-ho-hIkQf.mjs → openai-tool-schema-_pTAJqKF.mjs} +30 -40
- package/dist/{provider-error-DDOs_Bz0.mjs → provider-error-9TraxGvt.mjs} +20 -92
- package/dist/{provider-options-MdMBLzlU.d.mts → provider-options-Bcc_p-TU.d.mts} +26 -6
- package/dist/provider-replay-context-BuSUaAk5.mjs +21 -0
- package/dist/{provider-transcript-transform-C01bQ5a3.mjs → provider-transcript-transform-BaMbI1hr.mjs} +1 -1
- package/dist/provider-types.d.mts +19 -20
- package/dist/providers.d.mts +6 -6
- package/dist/providers.mjs +11 -11
- package/dist/{reasoning-tag-text-partitioner-5ygO2rZc.mjs → reasoning-tag-text-partitioner-DLCNXki6.mjs} +158 -94
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{sanitize-unicode-DCkltN94.mjs → sanitize-unicode-D6xUvZaS.mjs} +2 -8
- package/dist/{simple-options-CFj7x3J4.mjs → simple-options-BjHCCh4v.mjs} +42 -6
- package/dist/{src-Bu3FiFAG.mjs → src-2qBGKg8O.mjs} +83 -2
- package/dist/{stream-first-event-timeout-MK28puvq.mjs → stream-first-event-timeout-DcNjoFQE.mjs} +1 -1
- package/dist/{tool-schema-json-projection-qvTEs5Am.mjs → tool-schema-json-projection-mJhXDcyz.mjs} +21 -31
- package/dist/{transport-stream-shared-ljShVIZB.mjs → transport-stream-shared-CZqMhfIw.mjs} +19 -6
- package/dist/{transport-stream-shared-rvaCyFYt.d.mts → transport-stream-shared-xnaqxmbP.d.mts} +5 -5
- package/dist/{transport-utils-LJ1_rbi-.mjs → transport-utils-7il795_9.mjs} +5 -8
- package/dist/transports.d.mts +121 -85
- package/dist/transports.mjs +747 -464
- package/dist/types-3Lnm-QSJ.d.mts +1 -0
- package/dist/{types-DhLoJbFm.d.mts → types-CJ1-Ht7A.d.mts} +55 -19
- package/dist/types.d.mts +7 -7
- package/dist/types.mjs +5 -5
- package/dist/{validation-Dk7q7NMN.d.mts → validation-AKZBDGQd.d.mts} +1 -1
- package/dist/{validation-B61OhAio.mjs → validation-CJZtym2g.mjs} +7 -5
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +5 -5
- package/dist/anthropic-BECQCNdF.d.mts +0 -98
- package/dist/event-stream-BKp4fOt_.d.mts +0 -1
- package/dist/index-Qbej8io0.d.mts +0 -3
- package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
- package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
- package/dist/openai-responses-contracts-QUY12X0B.mjs +0 -233
- package/dist/openai-responses-payload-policy-D8EdimYe.mjs +0 -204
- package/dist/provider-options-AvldWZt8.mjs +0 -21
- package/dist/tls-certificate-errors-DXSpluKI.mjs +0 -93
- package/dist/types-GiAjXatj.d.mts +0 -1
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { c as normalizeLowercaseStringOrEmpty, d as normalizeOptionalString, o as isRecord, t as truncateUtf16Safe } from "./utf16-slice-qz3nsy87.mjs";
|
|
2
|
-
import { i as clampThinkingLevel, r as calculateCost } from "./sanitize-unicode-
|
|
3
|
-
import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, n as getAiTransportHost } from "./host-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { c as transformTransportMessages } from "./tool-schema-json-projection-
|
|
8
|
-
import { d as redactSensitiveText, u as redactIdentifier } from "./transport-utils-
|
|
9
|
-
import { _ as transportAbortError, g as sanitizeTransportPayloadText, h as sanitizeNonEmptyTransportPayloadText, m as parseTerminalToolCallArguments, y as withProviderResponseHook } from "./transport-stream-shared-
|
|
2
|
+
import { i as clampThinkingLevel, r as calculateCost } from "./sanitize-unicode-D6xUvZaS.mjs";
|
|
3
|
+
import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, n as getAiTransportHost } from "./host-CEvLw30U.mjs";
|
|
4
|
+
import { i as stableStringify } from "./provider-error-9TraxGvt.mjs";
|
|
5
|
+
import { r as asFiniteNumber } from "./base64-CEFBpSkN.mjs";
|
|
6
|
+
import { d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName } from "./simple-options-BjHCCh4v.mjs";
|
|
7
|
+
import { c as transformTransportMessages } from "./tool-schema-json-projection-mJhXDcyz.mjs";
|
|
8
|
+
import { d as redactSensitiveText, p as sha256Hex, u as redactIdentifier } from "./transport-utils-7il795_9.mjs";
|
|
9
|
+
import { _ as transportAbortError, c as finalizeTransportStream, g as sanitizeTransportPayloadText, h as sanitizeNonEmptyTransportPayloadText, m as parseTerminalToolCallArguments, o as failTransportStream, y as withProviderResponseHook } from "./transport-stream-shared-CZqMhfIw.mjs";
|
|
10
10
|
import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-BuAJEbdW.mjs";
|
|
11
11
|
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
12
12
|
import { t as shortHash } from "./hash-CHgqbJmD.mjs";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { t as
|
|
16
|
-
import {
|
|
13
|
+
import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-BuSUaAk5.mjs";
|
|
14
|
+
import { C as createOpenAIProviderAcceptanceHook, E as log, S as createModelStreamCooperativeScheduler, a as resolveOpenAIProjectedToolsStrictToolFlag, r as normalizeOpenAIStrictToolParameters, t as findOpenAIStrictToolProjectionDiagnostics, v as projectOpenAITools } from "./openai-tool-schema-_pTAJqKF.mjs";
|
|
15
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-DcNjoFQE.mjs";
|
|
16
|
+
import { t as transformProviderMessages } from "./provider-transcript-transform-BaMbI1hr.mjs";
|
|
17
|
+
import { D as resolveOpenAIModelReasoningEfforts, O as resolveOpenAIReasoningEffortForModel, b as RESPONSE_FAILED_NO_DETAILS_MESSAGE, g as OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE, h as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY, j as supportsOpenAITemperature, m as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, n as isOpenAIResponsesCompactionOutput, p as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-BMVHFOtq.mjs";
|
|
17
18
|
import { createHash, randomUUID } from "node:crypto";
|
|
18
19
|
//#region packages/ai/src/transports/model-transport-debug.ts
|
|
19
20
|
/**
|
|
@@ -67,19 +68,8 @@ function resolveReplayableResponsesMessageId(params) {
|
|
|
67
68
|
//#region packages/ai/src/transports/openai-responses-compaction-replay.ts
|
|
68
69
|
const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE = "openai-responses-compaction-suppression";
|
|
69
70
|
const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA = "rejected";
|
|
70
|
-
function hashOptionalReplayContextValue(value) {
|
|
71
|
-
const normalized = value?.trim();
|
|
72
|
-
return normalized ? shortHash(normalized) : void 0;
|
|
73
|
-
}
|
|
74
71
|
function buildOpenAIResponsesReplayContext(model, options) {
|
|
75
|
-
return
|
|
76
|
-
provider: model.provider,
|
|
77
|
-
api: model.api,
|
|
78
|
-
model: model.id,
|
|
79
|
-
baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
|
|
80
|
-
sessionHash: hashOptionalReplayContextValue(options?.sessionId),
|
|
81
|
-
authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
|
|
82
|
-
};
|
|
72
|
+
return buildProviderReplayContext(model, options);
|
|
83
73
|
}
|
|
84
74
|
function isOpenAIResponsesReplayContext(value) {
|
|
85
75
|
if (!isRecord(value)) return false;
|
|
@@ -94,10 +84,7 @@ function isOpenAIResponsesCompactionState(state) {
|
|
|
94
84
|
function readOpenAIResponsesCompactionReplayState(value) {
|
|
95
85
|
return isRecord(value) && isOpenAIResponsesReplayContext(value) && isOpenAIResponsesCompactionState(value) ? value : void 0;
|
|
96
86
|
}
|
|
97
|
-
function
|
|
98
|
-
return state.provider === context.provider && state.api === context.api && state.model === context.model && state.baseUrlHash === context.baseUrlHash && state.sessionHash === context.sessionHash && state.authProfileHash === context.authProfileHash;
|
|
99
|
-
}
|
|
100
|
-
function captureOpenAIResponsesCompaction(output, item, boundary, model, captureMetadata) {
|
|
87
|
+
function captureOpenAIResponsesCompaction(output, item, boundary, model, captureMetadata, compactedOutput) {
|
|
101
88
|
const metadata = captureMetadata ?? buildOpenAIResponsesReasoningReplayMetadata(model);
|
|
102
89
|
if (!item.encrypted_content) return;
|
|
103
90
|
if (!metadata?.baseUrlHash) {
|
|
@@ -106,19 +93,28 @@ function captureOpenAIResponsesCompaction(output, item, boundary, model, capture
|
|
|
106
93
|
}
|
|
107
94
|
const currentReplay = readOpenAIResponsesCompactionReplayState(output.providerReplay);
|
|
108
95
|
if (typeof boundary === "number" && currentReplay?.type === "openai-responses-compaction" && (currentReplay.replayIndex ?? -1) > boundary) return;
|
|
109
|
-
|
|
96
|
+
if (compactedOutput && !isOpenAIResponsesCompactionOutput(compactedOutput, model)) throw new Error("Responses compact endpoint checkpoint is invalid");
|
|
97
|
+
const replay = {
|
|
110
98
|
v: 1,
|
|
111
|
-
|
|
99
|
+
...boundary === "retained-users" ? { type: OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE } : {
|
|
100
|
+
type: OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE,
|
|
101
|
+
replayIndex: boundary
|
|
102
|
+
},
|
|
112
103
|
...item.id ? { id: item.id } : {},
|
|
113
104
|
data: item.encrypted_content,
|
|
114
|
-
...typeof boundary === "number" ? { replayIndex: boundary } : {},
|
|
115
105
|
provider: metadata.provider,
|
|
116
106
|
api: metadata.api,
|
|
117
107
|
model: metadata.model,
|
|
118
108
|
baseUrlHash: metadata.baseUrlHash,
|
|
119
109
|
...metadata.sessionHash ? { sessionHash: metadata.sessionHash } : {},
|
|
120
|
-
...metadata.authProfileHash ? { authProfileHash: metadata.authProfileHash } : {}
|
|
110
|
+
...metadata.authProfileHash ? { authProfileHash: metadata.authProfileHash } : {},
|
|
111
|
+
...compactedOutput ? { compactedWindow: {
|
|
112
|
+
state: "ready",
|
|
113
|
+
output: JSON.stringify(compactedOutput)
|
|
114
|
+
} } : {}
|
|
121
115
|
};
|
|
116
|
+
if (compactedOutput && !readOpenAIResponsesCompactionWindow(replay, model)) throw new Error("Responses compact endpoint checkpoint is invalid or exceeds 16 MiB");
|
|
117
|
+
output.providerReplay = replay;
|
|
122
118
|
}
|
|
123
119
|
function suppressOpenAIResponsesCompaction(output, model, options, rejectedCheckpoint) {
|
|
124
120
|
const context = buildOpenAIResponsesReplayContext(model, options);
|
|
@@ -159,14 +155,29 @@ function resolveNewestOpenAIResponsesCompactionReplay(messages, model, options)
|
|
|
159
155
|
if (message?.role !== "assistant") continue;
|
|
160
156
|
const replay = readOpenAIResponsesCompactionReplayState(message.providerReplay);
|
|
161
157
|
if (replay?.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) {
|
|
162
|
-
if (
|
|
158
|
+
if (providerReplayContextMatches(replay, context)) return;
|
|
163
159
|
continue;
|
|
164
160
|
}
|
|
165
161
|
if (replay?.type !== "openai-responses-compaction" && replay?.type !== "openai-responses-retained-compaction") {
|
|
166
162
|
if (message.providerReplay?.type === "openai-responses-compaction" || message.providerReplay?.type === "openai-responses-retained-compaction") return;
|
|
167
163
|
continue;
|
|
168
164
|
}
|
|
169
|
-
if (!
|
|
165
|
+
if (!providerReplayContextMatches(replay, context)) return;
|
|
166
|
+
if (replay.compactedWindow !== void 0 || replay.type === "openai-responses-retained-compaction") {
|
|
167
|
+
const output = readOpenAIResponsesCompactionWindow(replay, model);
|
|
168
|
+
const item = output?.at(-1);
|
|
169
|
+
if (!output || item?.type !== "compaction") return {
|
|
170
|
+
owner: message,
|
|
171
|
+
mode: "refresh-required"
|
|
172
|
+
};
|
|
173
|
+
return {
|
|
174
|
+
owner: message,
|
|
175
|
+
mode: "complete-window",
|
|
176
|
+
output,
|
|
177
|
+
item,
|
|
178
|
+
replayIndex: replay.type === "openai-responses-retained-compaction" ? message.content.length : replay.replayIndex ?? 0
|
|
179
|
+
};
|
|
180
|
+
}
|
|
170
181
|
return {
|
|
171
182
|
owner: message,
|
|
172
183
|
item: {
|
|
@@ -174,13 +185,17 @@ function resolveNewestOpenAIResponsesCompactionReplay(messages, model, options)
|
|
|
174
185
|
...isSafeResponsesReplayItemId(replay.id) ? { id: replay.id } : {},
|
|
175
186
|
encrypted_content: replay.data
|
|
176
187
|
},
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
replayIndex: replay.replayIndex ?? 0
|
|
180
|
-
}
|
|
188
|
+
mode: "compacted-prefix",
|
|
189
|
+
replayIndex: replay.replayIndex ?? 0
|
|
181
190
|
};
|
|
182
191
|
}
|
|
183
192
|
}
|
|
193
|
+
var CompactionReplayRefreshRequiredError = class extends Error {
|
|
194
|
+
constructor() {
|
|
195
|
+
super("Provider compaction checkpoint needs rebuilding. Run /compact to rebuild from saved conversation history.");
|
|
196
|
+
this.name = "CompactionReplayRefreshRequiredError";
|
|
197
|
+
}
|
|
198
|
+
};
|
|
184
199
|
function buildOpenAIResponsesCompactionReplayPlan(messages, model, options) {
|
|
185
200
|
if (options?.mode === "full-history") return {
|
|
186
201
|
messages,
|
|
@@ -191,22 +206,14 @@ function buildOpenAIResponsesCompactionReplayPlan(messages, model, options) {
|
|
|
191
206
|
messages,
|
|
192
207
|
preserveUnframedToolResults: false
|
|
193
208
|
};
|
|
209
|
+
if (compaction.mode === "refresh-required") throw new CompactionReplayRefreshRequiredError();
|
|
194
210
|
const ownerIndex = messages.indexOf(compaction.owner);
|
|
195
|
-
const collectRetainedUserMessages = (prefix) => {
|
|
196
|
-
const previous = resolveNewestOpenAIResponsesCompactionReplay(prefix, model, options);
|
|
197
|
-
if (!previous) return prefix.filter((message) => message.role === "user");
|
|
198
|
-
const previousOwnerIndex = prefix.indexOf(previous.owner);
|
|
199
|
-
const laterUsers = prefix.slice(previousOwnerIndex + 1).filter((message) => message.role === "user");
|
|
200
|
-
return previous.mode === "retained-users" ? [...collectRetainedUserMessages(prefix.slice(0, previousOwnerIndex)), ...laterUsers] : laterUsers;
|
|
201
|
-
};
|
|
202
|
-
const retainedMessages = compaction.mode === "retained-users" ? collectRetainedUserMessages(messages.slice(0, ownerIndex)) : void 0;
|
|
203
211
|
return {
|
|
204
212
|
messages: [{
|
|
205
213
|
...compaction.owner,
|
|
206
|
-
content: compaction.
|
|
214
|
+
content: compaction.owner.content.slice(compaction.replayIndex)
|
|
207
215
|
}, ...messages.slice(ownerIndex + 1)],
|
|
208
|
-
...
|
|
209
|
-
compaction: compaction.item,
|
|
216
|
+
...compaction.mode === "complete-window" ? { compactedWindow: compaction.output } : { compaction: compaction.item },
|
|
210
217
|
preserveUnframedToolResults: true
|
|
211
218
|
};
|
|
212
219
|
}
|
|
@@ -218,6 +225,63 @@ function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
|
|
|
218
225
|
};
|
|
219
226
|
}
|
|
220
227
|
//#endregion
|
|
228
|
+
//#region packages/ai/src/transports/openai-responses-input-replay.ts
|
|
229
|
+
function recordResponsesInputReplay(message, replay) {
|
|
230
|
+
if (replay) Object.assign(message, { openclawResponsesInputReplay: replay });
|
|
231
|
+
}
|
|
232
|
+
function readResponsesInputReplay(message) {
|
|
233
|
+
const replay = "openclawResponsesInputReplay" in message ? message.openclawResponsesInputReplay : void 0;
|
|
234
|
+
if (isRecord(replay) && typeof replay.afterResponseId === "string" && Array.isArray(replay.before) && replay.before.every((item) => typeof item === "string") && Array.isArray(replay.after) && replay.after.every((item) => typeof item === "string")) return {
|
|
235
|
+
afterResponseId: replay.afterResponseId,
|
|
236
|
+
before: replay.before,
|
|
237
|
+
after: replay.after
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function responsesInputFingerprint(item) {
|
|
241
|
+
if (isRecord(item) && (item.type === "function_call_output" || item.type === "custom_tool_call_output") && typeof item.call_id === "string") return sha256Hex(stableStringify({
|
|
242
|
+
type: item.type,
|
|
243
|
+
call_id: item.call_id
|
|
244
|
+
}));
|
|
245
|
+
return sha256Hex(stableStringify(item));
|
|
246
|
+
}
|
|
247
|
+
/** Reconstruct delivery order without rewriting durable local completion events. */
|
|
248
|
+
function createResponsesInputReplay(model) {
|
|
249
|
+
const starts = /* @__PURE__ */ new Map();
|
|
250
|
+
const ends = /* @__PURE__ */ new Map();
|
|
251
|
+
const fingerprints = /* @__PURE__ */ new Map();
|
|
252
|
+
const fingerprint = (item) => {
|
|
253
|
+
const value = fingerprints.get(item) ?? responsesInputFingerprint(item);
|
|
254
|
+
fingerprints.set(item, value);
|
|
255
|
+
return value;
|
|
256
|
+
};
|
|
257
|
+
return (input, output, message) => {
|
|
258
|
+
const key = message.turnId || message.responseId;
|
|
259
|
+
const start = (key ? starts.get(key) : void 0) ?? output[0];
|
|
260
|
+
if (key && start) starts.set(key, start);
|
|
261
|
+
input.push(...output);
|
|
262
|
+
let end = input.at(-1);
|
|
263
|
+
const replay = readResponsesInputReplay(message);
|
|
264
|
+
const parent = replay ? ends.get(replay.afterResponseId) : void 0;
|
|
265
|
+
if (replay && parent && message.provider === model.provider && message.api === model.api && message.model === model.id) {
|
|
266
|
+
const take = (keys) => {
|
|
267
|
+
const moved = [];
|
|
268
|
+
for (const inputKey of keys.toReversed()) {
|
|
269
|
+
const boundary = input.indexOf(parent);
|
|
270
|
+
const index = input.findLastIndex((item, position) => position > boundary && fingerprint(item) === inputKey);
|
|
271
|
+
if (index > boundary) moved.unshift(...input.splice(index, 1));
|
|
272
|
+
}
|
|
273
|
+
return moved;
|
|
274
|
+
};
|
|
275
|
+
const before = take(replay.before);
|
|
276
|
+
const after = take(replay.after);
|
|
277
|
+
input.splice(start ? input.indexOf(start) : input.length, 0, ...before);
|
|
278
|
+
end = input.at(-1);
|
|
279
|
+
input.push(...after);
|
|
280
|
+
}
|
|
281
|
+
if (message.responseId && end) ends.set(message.responseId, end);
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
//#endregion
|
|
221
285
|
//#region packages/ai/src/transports/openai-responses-replay-messages-internal.ts
|
|
222
286
|
function stripEncryptedReasoningContentFields(value) {
|
|
223
287
|
if (!value || typeof value !== "object") return {
|
|
@@ -287,7 +351,7 @@ function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetada
|
|
|
287
351
|
const { [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: rawMetadata, ...rest } = record;
|
|
288
352
|
if (!("encrypted_content" in rest)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
|
|
289
353
|
const metadata = blockMetadata !== void 0 ? blockMetadata ?? void 0 : isOpenAIResponsesReasoningReplayMetadata(rawMetadata) ? rawMetadata : void 0;
|
|
290
|
-
if (blockMetadata === void 0 && !hasRawMetadata && options?.preserveUnattributedEncryptedContent === true || metadata &&
|
|
354
|
+
if (blockMetadata === void 0 && !hasRawMetadata && options?.preserveUnattributedEncryptedContent === true || metadata && providerReplayContextMatches(metadata, context)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
|
|
291
355
|
return normalizeOpenAIResponsesReasoningReplayItem(stripEncryptedReasoningContentFields(rest).value);
|
|
292
356
|
}
|
|
293
357
|
function normalizeResponsesReplayItemId(id, prefix) {
|
|
@@ -302,6 +366,41 @@ function encodeTextSignatureV1(id, phase) {
|
|
|
302
366
|
...phase ? { phase } : {}
|
|
303
367
|
});
|
|
304
368
|
}
|
|
369
|
+
function orderResponsesAsyncToolResults(source) {
|
|
370
|
+
const turnKey = (message) => {
|
|
371
|
+
const id = message.turnId || message.responseId;
|
|
372
|
+
return id ? `${message.provider}:${message.api}:${message.model}:${id}` : void 0;
|
|
373
|
+
};
|
|
374
|
+
const lastAssistant = /* @__PURE__ */ new Map();
|
|
375
|
+
for (const [index, message] of source.entries()) if (message.role === "assistant") {
|
|
376
|
+
const key = turnKey(message);
|
|
377
|
+
if (key) lastAssistant.set(key, index);
|
|
378
|
+
}
|
|
379
|
+
const owners = /* @__PURE__ */ new Map();
|
|
380
|
+
const pending = /* @__PURE__ */ new Map();
|
|
381
|
+
const ordered = [];
|
|
382
|
+
for (const [index, message] of source.entries()) {
|
|
383
|
+
if (message.role === "assistant") {
|
|
384
|
+
const key = turnKey(message);
|
|
385
|
+
if (key) {
|
|
386
|
+
for (const block of message.content) if (block.type === "toolCall" && block.async) owners.set(block.id, key);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
const owner = message.role === "toolResult" ? owners.get(message.toolCallId) : void 0;
|
|
390
|
+
const lastIndex = owner ? lastAssistant.get(owner) : void 0;
|
|
391
|
+
if (lastIndex !== void 0 && lastIndex > index) {
|
|
392
|
+
const results = pending.get(lastIndex) ?? [];
|
|
393
|
+
results.push(message);
|
|
394
|
+
pending.set(lastIndex, results);
|
|
395
|
+
} else ordered.push(message);
|
|
396
|
+
const results = pending.get(index);
|
|
397
|
+
if (results) {
|
|
398
|
+
ordered.push(...results);
|
|
399
|
+
pending.delete(index);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return ordered;
|
|
403
|
+
}
|
|
305
404
|
function parseOpenAIResponsesTextSignature(signature) {
|
|
306
405
|
if (!signature) return;
|
|
307
406
|
if (signature.startsWith("{")) try {
|
|
@@ -397,40 +496,52 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
397
496
|
normalizeSameModelToolCallIds: shouldNormalizeSameModelToolCallIds,
|
|
398
497
|
preserveUnframedToolResults: replayPlan.preserveUnframedToolResults
|
|
399
498
|
});
|
|
400
|
-
const transformedMessages = transformMessages(replayPlan.messages);
|
|
401
|
-
|
|
402
|
-
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && (providerStyle ? model.compat?.supportsDeveloperRole !== false : options?.supportsDeveloperRole !== false) ? "developer" : "system", [{
|
|
499
|
+
const transformedMessages = orderResponsesAsyncToolResults(transformMessages(replayPlan.messages));
|
|
500
|
+
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && model.compat?.supportsDeveloperRole !== false ? "developer" : "system", [{
|
|
403
501
|
type: "input_text",
|
|
404
502
|
text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt))
|
|
405
503
|
}]));
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
504
|
+
if (replayPlan.compactedWindow) messages.push(...replayPlan.compactedWindow);
|
|
505
|
+
let replayMessages = replayPlan.compaction ? [replayPlan.compaction, ...transformedMessages] : transformedMessages;
|
|
506
|
+
const isCarrier = (message) => "role" in message && message.role === "user" && message.runtimeContextCarrier === true;
|
|
507
|
+
if (replayMessages.some(isCarrier)) {
|
|
508
|
+
const anchored = [];
|
|
509
|
+
let insertionIndex = replayPlan.compactedWindow ? 0 : void 0;
|
|
510
|
+
for (const message of replayMessages) {
|
|
511
|
+
if (isCarrier(message) && insertionIndex !== void 0) {
|
|
512
|
+
anchored.splice(insertionIndex++, 0, message);
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
anchored.push(message);
|
|
516
|
+
if (!isCarrier(message) && ("role" in message ? message.role === "user" : message.type === "compaction")) insertionIndex = anchored.length;
|
|
517
|
+
}
|
|
518
|
+
replayMessages = anchored;
|
|
519
|
+
}
|
|
411
520
|
let msgIndex = 0;
|
|
521
|
+
const appendAssistant = createResponsesInputReplay(model);
|
|
412
522
|
for (const msg of replayMessages) {
|
|
413
523
|
if (!("role" in msg)) {
|
|
414
524
|
messages.push(msg);
|
|
415
525
|
continue;
|
|
416
526
|
}
|
|
417
|
-
if (msg.role === "user")
|
|
418
|
-
|
|
419
|
-
text: sanitizeTransportPayloadText(msg.content)
|
|
420
|
-
}]));
|
|
421
|
-
else {
|
|
422
|
-
const content = msg.content.map((item) => item.type === "text" ? {
|
|
527
|
+
if (msg.role === "user") {
|
|
528
|
+
if (typeof msg.content === "string") messages.push(buildResponsesInputMessage("user", [{
|
|
423
529
|
type: "input_text",
|
|
424
|
-
text: sanitizeTransportPayloadText(
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
530
|
+
text: sanitizeTransportPayloadText(msg.content)
|
|
531
|
+
}]));
|
|
532
|
+
else {
|
|
533
|
+
const content = msg.content.map((item) => item.type === "text" ? {
|
|
534
|
+
type: "input_text",
|
|
535
|
+
text: sanitizeTransportPayloadText(item.text)
|
|
536
|
+
} : {
|
|
537
|
+
type: "input_image",
|
|
538
|
+
detail: "auto",
|
|
539
|
+
image_url: `data:${item.mimeType};base64,${item.data}`
|
|
540
|
+
}).filter((item) => providerStyle || model.input.includes("image") || item.type !== "input_image");
|
|
541
|
+
if (content.length > 0) messages.push(buildResponsesInputMessage("user", content));
|
|
542
|
+
else if (providerStyle) continue;
|
|
543
|
+
}
|
|
544
|
+
} else if (msg.role === "assistant") {
|
|
434
545
|
const output = [];
|
|
435
546
|
let textFallbackOrdinal = 0;
|
|
436
547
|
let previousReplayItemWasReasoning = false;
|
|
@@ -485,12 +596,18 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
485
596
|
...itemId ? { id: itemId } : {},
|
|
486
597
|
call_id: callId,
|
|
487
598
|
name: block.name,
|
|
599
|
+
...block.async ? { async: true } : {},
|
|
488
600
|
arguments: providerStyle ? JSON.stringify(block.arguments) : typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
|
|
489
601
|
});
|
|
490
602
|
previousReplayItemWasReasoning = false;
|
|
491
603
|
}
|
|
492
|
-
|
|
493
|
-
|
|
604
|
+
while (true) {
|
|
605
|
+
const last = output.at(-1);
|
|
606
|
+
if (last?.type !== "reasoning" || !last.id?.startsWith("rs_") || typeof last.encrypted_content === "string" && last.encrypted_content.length > 0) break;
|
|
607
|
+
output.pop();
|
|
608
|
+
}
|
|
609
|
+
appendAssistant(messages, output, msg);
|
|
610
|
+
if (output.length === 0 && providerStyle) continue;
|
|
494
611
|
} else if (msg.role === "toolResult") {
|
|
495
612
|
const textResult = extractToolResultText(msg.content);
|
|
496
613
|
const sanitizedTextResult = sanitizeTransportPayloadText(textResult);
|
|
@@ -592,84 +709,83 @@ async function resolveNextResponsesEncryptedContentAttempt(attempt, error, optio
|
|
|
592
709
|
};
|
|
593
710
|
}
|
|
594
711
|
async function createResponsesStreamWithEncryptedContentRetry(params) {
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
712
|
+
const send = async (initialAttempt) => {
|
|
713
|
+
let attempt = initialAttempt;
|
|
714
|
+
for (;;) {
|
|
715
|
+
params.observePrompt?.(attempt.request, {
|
|
716
|
+
egress: "responses-sdk",
|
|
717
|
+
payloadVariant: attempt.kind
|
|
718
|
+
});
|
|
719
|
+
try {
|
|
720
|
+
const { data, response } = await params.client.responses.create(attempt.request, params.requestOptions).withResponse();
|
|
721
|
+
commitResponsesEncryptedContentAttempt(attempt, (checkpoint) => {
|
|
722
|
+
if (checkpoint) params.onCompactionRejected?.(checkpoint);
|
|
723
|
+
});
|
|
724
|
+
if (!isAsyncIterable(data)) throw new Error("OpenAI Responses streaming request returned a non-stream response");
|
|
725
|
+
return {
|
|
726
|
+
stream: data,
|
|
727
|
+
response,
|
|
728
|
+
attempt
|
|
729
|
+
};
|
|
730
|
+
} catch (error) {
|
|
731
|
+
let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
|
|
732
|
+
if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && error.code === "previous_response_not_found") {
|
|
733
|
+
const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
|
|
734
|
+
delete request.previous_response_id;
|
|
735
|
+
nextAttempt = {
|
|
736
|
+
kind: "continuation-rejected",
|
|
737
|
+
request
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
if (!nextAttempt) throw error;
|
|
741
|
+
const retryDescription = nextAttempt.kind === "reasoning-stripped" ? "without encrypted reasoning content" : nextAttempt.kind === "compaction-stripped" ? "without encrypted compaction content" : "full history after rejected previous_response_id";
|
|
742
|
+
log.warn(`[responses] retrying ${retryDescription} provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
|
|
743
|
+
attempt = nextAttempt;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
606
746
|
};
|
|
607
|
-
|
|
747
|
+
const result = await send({
|
|
608
748
|
kind: params.initialAttemptKind ?? "initial",
|
|
609
749
|
request: params.request,
|
|
610
750
|
...params.initialRejectedCompaction ? { rejectedCompaction: params.initialRejectedCompaction } : {}
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
const message = typeof failure.message === "string" ? failure.message : "";
|
|
630
|
-
throw Object.assign(new Error(message), {
|
|
631
|
-
code: failure.code,
|
|
632
|
-
status: failure.status
|
|
633
|
-
});
|
|
634
|
-
}
|
|
751
|
+
});
|
|
752
|
+
return {
|
|
753
|
+
...result,
|
|
754
|
+
stream: { async *[Symbol.asyncIterator]() {
|
|
755
|
+
let current = result;
|
|
756
|
+
for (;;) {
|
|
757
|
+
let rejectedEvent;
|
|
758
|
+
try {
|
|
759
|
+
for await (const event of params.wrapStream?.(current) ?? current.stream) {
|
|
760
|
+
if (isRecord(event)) {
|
|
761
|
+
const failure = event.type === "response.failed" && isRecord(event.response) ? event.response.error : event.type === "error" ? event.error ?? event : void 0;
|
|
762
|
+
if (isRecord(failure) && params.canRetryStream?.() === true && isInvalidEncryptedContentError(failure)) {
|
|
763
|
+
rejectedEvent = event;
|
|
764
|
+
const message = typeof failure.message === "string" ? failure.message : "";
|
|
765
|
+
throw Object.assign(new Error(message), {
|
|
766
|
+
code: failure.code,
|
|
767
|
+
status: failure.status
|
|
768
|
+
});
|
|
635
769
|
}
|
|
636
|
-
yield event;
|
|
637
770
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
771
|
+
yield event;
|
|
772
|
+
}
|
|
773
|
+
return;
|
|
774
|
+
} catch (error) {
|
|
775
|
+
const nextAttempt = params.canRetryStream?.() === true && !params.requestOptions?.signal?.aborted ? await resolveNextResponsesEncryptedContentAttempt(current.attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest }) : void 0;
|
|
776
|
+
if (!nextAttempt) {
|
|
777
|
+
if (rejectedEvent !== void 0) {
|
|
778
|
+
yield rejectedEvent;
|
|
779
|
+
return;
|
|
646
780
|
}
|
|
647
|
-
|
|
648
|
-
yield* (await createResponsesStreamWithEncryptedContentRetry({
|
|
649
|
-
...params,
|
|
650
|
-
request: nextAttempt.request,
|
|
651
|
-
initialAttemptKind: nextAttempt.kind,
|
|
652
|
-
initialRejectedCompaction: nextAttempt.rejectedCompaction
|
|
653
|
-
})).stream;
|
|
781
|
+
throw error;
|
|
654
782
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
|
|
659
|
-
if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && error.code === "previous_response_not_found") {
|
|
660
|
-
const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
|
|
661
|
-
delete request.previous_response_id;
|
|
662
|
-
nextAttempt = {
|
|
663
|
-
kind: "continuation-rejected",
|
|
664
|
-
request
|
|
665
|
-
};
|
|
783
|
+
log.warn(`[responses] retrying streamed encrypted content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
|
|
784
|
+
current = await send(nextAttempt);
|
|
785
|
+
}
|
|
666
786
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
log.warn(`[responses] retrying ${retryDescription} provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
|
|
670
|
-
attempt = nextAttempt;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
787
|
+
} }
|
|
788
|
+
};
|
|
673
789
|
}
|
|
674
790
|
function resolveAzureOpenAIApiVersion(env = process.env) {
|
|
675
791
|
return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
|
|
@@ -725,14 +841,14 @@ function createResponsesToolCallTracker() {
|
|
|
725
841
|
state.callId ??= identity.callId;
|
|
726
842
|
return state;
|
|
727
843
|
};
|
|
728
|
-
const resolveCompatible = (candidates, identity) => {
|
|
844
|
+
const resolveCompatible = (candidates, identity, allowUnmatchedIdentity) => {
|
|
729
845
|
const uniqueCandidates = [...new Set(candidates)];
|
|
730
|
-
if (!identity.itemId && !identity.callId) return uniqueCandidates.length === 1 ? uniqueCandidates.at(0) : void 0;
|
|
846
|
+
if (!identity.itemId && !identity.callId) return allowUnmatchedIdentity && uniqueCandidates.length === 1 ? uniqueCandidates.at(0) : void 0;
|
|
731
847
|
const compatible = uniqueCandidates.filter((state) => !identitiesConflict(state, identity));
|
|
732
848
|
const matches = compatible.filter((state) => sharesIdentity(state, identity));
|
|
733
849
|
const matched = matches.length === 1 ? matches.at(0) : void 0;
|
|
734
850
|
if (matched) return adoptIdentity(matched, identity);
|
|
735
|
-
const soleCompatible = uniqueCandidates.length === 1 && compatible.length === 1 && matches.length === 0 ? compatible.at(0) : void 0;
|
|
851
|
+
const soleCompatible = allowUnmatchedIdentity && uniqueCandidates.length === 1 && compatible.length === 1 && matches.length === 0 ? compatible.at(0) : void 0;
|
|
736
852
|
return soleCompatible ? adoptIdentity(soleCompatible, identity) : void 0;
|
|
737
853
|
};
|
|
738
854
|
return {
|
|
@@ -743,9 +859,10 @@ function createResponsesToolCallTracker() {
|
|
|
743
859
|
return;
|
|
744
860
|
}
|
|
745
861
|
if (indexedCalls.has(outputIndex)) throw new Error(`Responses stream reused active tool-call output index ${outputIndex}`);
|
|
862
|
+
state.outputIndex = outputIndex;
|
|
746
863
|
indexedCalls.set(outputIndex, state);
|
|
747
864
|
},
|
|
748
|
-
resolve(event, identity = readEventIdentity(event)) {
|
|
865
|
+
resolve(event, identity = readEventIdentity(event), allowUnmatchedIdentity = true) {
|
|
749
866
|
const outputIndex = readOutputIndex(event);
|
|
750
867
|
if (outputIndex !== void 0) {
|
|
751
868
|
const indexed = indexedCalls.get(outputIndex);
|
|
@@ -753,14 +870,15 @@ function createResponsesToolCallTracker() {
|
|
|
753
870
|
if (indexed.callId && identity.callId && indexed.callId !== identity.callId) return;
|
|
754
871
|
return adoptIdentity(indexed, identity);
|
|
755
872
|
}
|
|
756
|
-
const unindexed = resolveCompatible(unindexedCalls, identity);
|
|
873
|
+
const unindexed = resolveCompatible(unindexedCalls, identity, allowUnmatchedIdentity);
|
|
757
874
|
if (unindexed) {
|
|
758
875
|
unindexedCalls.delete(unindexed);
|
|
876
|
+
unindexed.outputIndex = outputIndex;
|
|
759
877
|
indexedCalls.set(outputIndex, unindexed);
|
|
760
878
|
}
|
|
761
879
|
return unindexed;
|
|
762
880
|
}
|
|
763
|
-
return resolveCompatible([...indexedCalls.values(), ...unindexedCalls], identity);
|
|
881
|
+
return resolveCompatible([...indexedCalls.values(), ...unindexedCalls], identity, allowUnmatchedIdentity);
|
|
764
882
|
},
|
|
765
883
|
forget(toolCall) {
|
|
766
884
|
for (const [outputIndex, tracked] of indexedCalls) if (tracked === toolCall) indexedCalls.delete(outputIndex);
|
|
@@ -771,6 +889,10 @@ function createResponsesToolCallTracker() {
|
|
|
771
889
|
},
|
|
772
890
|
hasActive() {
|
|
773
891
|
return indexedCalls.size > 0 || unindexedCalls.size > 0;
|
|
892
|
+
},
|
|
893
|
+
hasExactlyActive(expected) {
|
|
894
|
+
const active = /* @__PURE__ */ new Set([...indexedCalls.values(), ...unindexedCalls]);
|
|
895
|
+
return active.size === expected.length && expected.every((state) => active.has(state));
|
|
774
896
|
}
|
|
775
897
|
};
|
|
776
898
|
}
|
|
@@ -896,9 +1018,10 @@ const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
|
|
|
896
1018
|
function readResponseFailedString(record, key) {
|
|
897
1019
|
return stringifyUnknown(record?.[key]);
|
|
898
1020
|
}
|
|
899
|
-
function buildResponsesFailedEventSummary(message, responseId, observation) {
|
|
1021
|
+
function buildResponsesFailedEventSummary(message, responseId, code, observation) {
|
|
900
1022
|
const summary = { message };
|
|
901
1023
|
if (responseId) summary.responseId = responseId;
|
|
1024
|
+
if (code) summary.code = code;
|
|
902
1025
|
if (observation) summary.observation = observation;
|
|
903
1026
|
return summary;
|
|
904
1027
|
}
|
|
@@ -1017,11 +1140,11 @@ function normalizeResponsesFailedEvent(event, model) {
|
|
|
1017
1140
|
if (error) {
|
|
1018
1141
|
const code = readResponseFailedString(error, "code").trim();
|
|
1019
1142
|
const message = readResponseFailedString(error, "message").trim();
|
|
1020
|
-
if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
|
|
1143
|
+
if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId, code || void 0);
|
|
1021
1144
|
}
|
|
1022
1145
|
const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
|
|
1023
1146
|
if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
|
|
1024
|
-
return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
|
|
1147
|
+
return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, void 0, buildResponsesFailedNoDetailsObservation(event, model, response));
|
|
1025
1148
|
}
|
|
1026
1149
|
var ResponsesStreamFailure = class extends Error {
|
|
1027
1150
|
constructor(failure, response) {
|
|
@@ -1029,6 +1152,7 @@ var ResponsesStreamFailure = class extends Error {
|
|
|
1029
1152
|
this.name = "ResponsesStreamFailure";
|
|
1030
1153
|
this.responseId = failure.responseId;
|
|
1031
1154
|
this.response = response;
|
|
1155
|
+
this.code = failure.code;
|
|
1032
1156
|
this.observation = failure.observation;
|
|
1033
1157
|
}
|
|
1034
1158
|
};
|
|
@@ -1123,7 +1247,8 @@ function createResponsesOutputTracker() {
|
|
|
1123
1247
|
const outputs = /* @__PURE__ */ new Map();
|
|
1124
1248
|
const identity = (item) => {
|
|
1125
1249
|
if ((item.type === "reasoning" || item.type === "message") && item.id) return `${item.type}:${item.id}`;
|
|
1126
|
-
|
|
1250
|
+
const callId = item.call_id ?? item.id;
|
|
1251
|
+
return item.type === "function_call" && callId ? `function_call:${callId}` : void 0;
|
|
1127
1252
|
};
|
|
1128
1253
|
const get = (item, outputIndex) => {
|
|
1129
1254
|
const key = identity(item);
|
|
@@ -1210,8 +1335,11 @@ function createResponsesOutputSlotTracker() {
|
|
|
1210
1335
|
* package and managed transports from drifting on token buckets, service-tier pricing, or future
|
|
1211
1336
|
* terminal-event semantics.
|
|
1212
1337
|
*/
|
|
1338
|
+
function readReportedCount(value) {
|
|
1339
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
1340
|
+
}
|
|
1213
1341
|
function readCount(value) {
|
|
1214
|
-
return
|
|
1342
|
+
return readReportedCount(value) ?? 0;
|
|
1215
1343
|
}
|
|
1216
1344
|
/**
|
|
1217
1345
|
* Split a terminal usage payload into the priced buckets.
|
|
@@ -1229,12 +1357,21 @@ function mapResponsesTerminalUsage(usage) {
|
|
|
1229
1357
|
const input = Math.max(0, readCount(usage.input_tokens) - cacheRead - cacheWrite);
|
|
1230
1358
|
const output = readCount(usage.output_tokens);
|
|
1231
1359
|
const bucketTotal = input + output + cacheRead + cacheWrite;
|
|
1360
|
+
const totalTokens = Math.max(bucketTotal, readCount(usage.total_tokens));
|
|
1361
|
+
const reportedInput = readReportedCount(usage.input_tokens);
|
|
1362
|
+
const reportedOutput = readReportedCount(usage.output_tokens);
|
|
1363
|
+
const reportedTotal = readReportedCount(usage.total_tokens);
|
|
1232
1364
|
return {
|
|
1233
1365
|
input,
|
|
1234
1366
|
output,
|
|
1235
1367
|
cacheRead,
|
|
1236
1368
|
cacheWrite,
|
|
1237
|
-
|
|
1369
|
+
contextUsage: reportedInput !== void 0 && (reportedOutput !== void 0 || reportedTotal !== void 0 && reportedTotal >= reportedInput) && cacheRead + cacheWrite <= reportedInput ? {
|
|
1370
|
+
state: "available",
|
|
1371
|
+
promptTokens: reportedInput,
|
|
1372
|
+
totalTokens: Math.max(totalTokens, reportedInput + (reportedOutput ?? 0))
|
|
1373
|
+
} : { state: "unavailable" },
|
|
1374
|
+
totalTokens
|
|
1238
1375
|
};
|
|
1239
1376
|
}
|
|
1240
1377
|
/** Reasoning tokens are reported by the agent path only; the package path does not track them. */
|
|
@@ -1392,30 +1529,34 @@ function createResponsesTerminalController(params) {
|
|
|
1392
1529
|
});
|
|
1393
1530
|
return index;
|
|
1394
1531
|
};
|
|
1395
|
-
const
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1532
|
+
const emitToolCallCompletion = (item, outputIndex, started, validated) => {
|
|
1533
|
+
const completed = {
|
|
1534
|
+
id: resolveResponsesToolCallId(item, started?.block.id),
|
|
1535
|
+
...validated
|
|
1536
|
+
};
|
|
1537
|
+
const toolCall = started ? Object.assign(started.block, completed) : {
|
|
1398
1538
|
type: "toolCall",
|
|
1399
|
-
|
|
1400
|
-
name: validated.name,
|
|
1401
|
-
arguments: validated.arguments
|
|
1539
|
+
...completed
|
|
1402
1540
|
};
|
|
1403
|
-
|
|
1404
|
-
const contentIndex = blocks.length
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1541
|
+
delete toolCall.partialJson;
|
|
1542
|
+
const contentIndex = started?.contentIndex ?? blocks.length;
|
|
1543
|
+
if (!started) {
|
|
1544
|
+
blocks.push(toolCall);
|
|
1545
|
+
stream.push({
|
|
1546
|
+
type: "toolcall_start",
|
|
1547
|
+
contentIndex,
|
|
1548
|
+
partial: output
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
params.outputs.set(item, contentIndex, outputIndex, true);
|
|
1410
1552
|
stream.push({
|
|
1411
1553
|
type: "toolcall_end",
|
|
1412
1554
|
contentIndex,
|
|
1413
1555
|
toolCall,
|
|
1414
1556
|
partial: output
|
|
1415
1557
|
});
|
|
1416
|
-
return contentIndex;
|
|
1417
1558
|
};
|
|
1418
|
-
const recoverTerminalOutput = (items,
|
|
1559
|
+
const recoverTerminalOutput = (items, completeToolCall) => {
|
|
1419
1560
|
let hasCompletedLaterOutput = false;
|
|
1420
1561
|
for (const [outputIndex, item] of [...items.entries()].toReversed()) {
|
|
1421
1562
|
const tracked = params.outputs.get(item, outputIndex);
|
|
@@ -1428,9 +1569,8 @@ function createResponsesTerminalController(params) {
|
|
|
1428
1569
|
hasCompletedLaterOutput = true;
|
|
1429
1570
|
continue;
|
|
1430
1571
|
}
|
|
1431
|
-
if (item.type === "function_call" && !
|
|
1572
|
+
if (item.type === "function_call" && !completeToolCall) continue;
|
|
1432
1573
|
if (hasCompletedLaterOutput) throw new Error("Responses stream omitted an output item before completed output");
|
|
1433
|
-
if (item.type === "function_call") resolveCompletedResponsesToolCall(item);
|
|
1434
1574
|
}
|
|
1435
1575
|
for (const [terminalIndex, item] of items.entries()) if (item.type === "message") {
|
|
1436
1576
|
const tracked = params.outputs.get(item, terminalIndex);
|
|
@@ -1451,9 +1591,9 @@ function createResponsesTerminalController(params) {
|
|
|
1451
1591
|
}
|
|
1452
1592
|
}
|
|
1453
1593
|
captureOpenAIResponsesCompaction(output, item, replayIndex, model, options?.reasoningReplayMetadata);
|
|
1454
|
-
} else if (
|
|
1455
|
-
if (params.outputs.get(item, terminalIndex)) continue;
|
|
1456
|
-
|
|
1594
|
+
} else if (completeToolCall && item.type === "function_call") {
|
|
1595
|
+
if (params.outputs.get(item, terminalIndex)?.completed) continue;
|
|
1596
|
+
completeToolCall(terminalIndex);
|
|
1457
1597
|
}
|
|
1458
1598
|
}
|
|
1459
1599
|
};
|
|
@@ -1480,7 +1620,6 @@ function createResponsesTerminalController(params) {
|
|
|
1480
1620
|
}
|
|
1481
1621
|
};
|
|
1482
1622
|
const finalizeResponse = (response, terminalEventType) => {
|
|
1483
|
-
params.markFinalized();
|
|
1484
1623
|
backfillReasoning(response.output ?? []);
|
|
1485
1624
|
finalizeTerminalFacts(response);
|
|
1486
1625
|
const terminal = resolveResponsesTerminalStopReason({
|
|
@@ -1495,7 +1634,8 @@ function createResponsesTerminalController(params) {
|
|
|
1495
1634
|
return {
|
|
1496
1635
|
finalizeResponse,
|
|
1497
1636
|
finalizeFailedResponse: finalizeTerminalFacts,
|
|
1498
|
-
recoverTerminalOutput
|
|
1637
|
+
recoverTerminalOutput,
|
|
1638
|
+
emitToolCallCompletion
|
|
1499
1639
|
};
|
|
1500
1640
|
}
|
|
1501
1641
|
//#endregion
|
|
@@ -1505,6 +1645,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1505
1645
|
const outputSlots = createResponsesOutputSlotTracker();
|
|
1506
1646
|
const outputs = createResponsesOutputTracker();
|
|
1507
1647
|
let terminalResponse;
|
|
1648
|
+
let incompleteToolCall;
|
|
1508
1649
|
let lastTextBlock = null;
|
|
1509
1650
|
const blocks = output.content;
|
|
1510
1651
|
const compactionTracker = createCompactionTracker(output, model, options);
|
|
@@ -1594,7 +1735,27 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1594
1735
|
const materializeDeferredTextSlots = (except) => {
|
|
1595
1736
|
for (const slot of outputSlots.values()) if (slot !== except && slot.type === "text") materializeDeferredTextSlot(slot);
|
|
1596
1737
|
};
|
|
1597
|
-
const
|
|
1738
|
+
const appendThinkingDelta = (slot, delta) => {
|
|
1739
|
+
slot.block.thinking += delta;
|
|
1740
|
+
stream.push({
|
|
1741
|
+
type: "thinking_delta",
|
|
1742
|
+
contentIndex: slot.contentIndex,
|
|
1743
|
+
delta,
|
|
1744
|
+
partial: output
|
|
1745
|
+
});
|
|
1746
|
+
};
|
|
1747
|
+
const projectTextDelta = (slot, delta) => {
|
|
1748
|
+
if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, delta, materializeDeferredTextSlot);
|
|
1749
|
+
else if (slot.block && slot.contentIndex !== void 0) {
|
|
1750
|
+
slot.block.text += delta;
|
|
1751
|
+
stream.push({
|
|
1752
|
+
type: "text_delta",
|
|
1753
|
+
contentIndex: slot.contentIndex,
|
|
1754
|
+
delta
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
const terminal = createResponsesTerminalController({
|
|
1598
1759
|
output,
|
|
1599
1760
|
stream,
|
|
1600
1761
|
model,
|
|
@@ -1603,9 +1764,52 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1603
1764
|
getLastTextBlock: () => lastTextBlock,
|
|
1604
1765
|
setLastTextBlock: (block) => {
|
|
1605
1766
|
lastTextBlock = block;
|
|
1606
|
-
}
|
|
1607
|
-
markFinalized: () => void 0
|
|
1767
|
+
}
|
|
1608
1768
|
});
|
|
1769
|
+
const finalizeToolCall = (item, outputIndex, streamingToolCall, validated) => {
|
|
1770
|
+
const identity = {
|
|
1771
|
+
type: item.type,
|
|
1772
|
+
id: item.id || streamingToolCall?.itemId,
|
|
1773
|
+
call_id: item.call_id || streamingToolCall?.callId
|
|
1774
|
+
};
|
|
1775
|
+
const finalOutputIndex = outputIndex ?? streamingToolCall?.outputIndex;
|
|
1776
|
+
if (finalOutputIndex === void 0 && !identity.id && !identity.call_id) {
|
|
1777
|
+
if (!streamingToolCall) throw new Error("Responses stream completed tool call without an output identity");
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
if (streamingToolCall) {
|
|
1781
|
+
streamingToolCalls.forget(streamingToolCall);
|
|
1782
|
+
for (const slot of outputSlots.values()) if (slot.type === "toolCall" && slot.toolCall === streamingToolCall) outputSlots.forget(slot);
|
|
1783
|
+
}
|
|
1784
|
+
terminal.emitToolCallCompletion(identity, finalOutputIndex, streamingToolCall, {
|
|
1785
|
+
...validated,
|
|
1786
|
+
...options?.asyncToolExecution && isRecord(item) && item.async === true ? { async: true } : {}
|
|
1787
|
+
});
|
|
1788
|
+
};
|
|
1789
|
+
const prepareTerminalToolCalls = (items) => {
|
|
1790
|
+
const prepared = /* @__PURE__ */ new Map();
|
|
1791
|
+
const recovered = [];
|
|
1792
|
+
const callIds = /* @__PURE__ */ new Set();
|
|
1793
|
+
const allowUnmatchedIdentity = items.filter((item, index) => item.type === "function_call" && !outputs.get(item, index)?.completed).length === 1;
|
|
1794
|
+
for (const [outputIndex, item] of items.entries()) {
|
|
1795
|
+
const tracked = outputs.get(item, outputIndex);
|
|
1796
|
+
if (item.type !== "function_call") continue;
|
|
1797
|
+
if (item.call_id && callIds.has(item.call_id)) throw new Error("Responses stream repeated a terminal tool-call identity");
|
|
1798
|
+
if (item.call_id) callIds.add(item.call_id);
|
|
1799
|
+
if (tracked?.completed) continue;
|
|
1800
|
+
const state = streamingToolCalls.resolve({ output_index: outputIndex }, readResponsesToolCallItemIdentity(item), allowUnmatchedIdentity);
|
|
1801
|
+
if (tracked && !state) throw new Error("Responses stream completed with unresolved tool calls");
|
|
1802
|
+
const validated = resolveCompletedResponsesToolCall(item, { name: state?.block.name });
|
|
1803
|
+
if (state) recovered.push(state);
|
|
1804
|
+
prepared.set(outputIndex, () => finalizeToolCall(item, outputIndex, state, validated));
|
|
1805
|
+
}
|
|
1806
|
+
if (!streamingToolCalls.hasExactlyActive(recovered)) throw new Error("Responses stream completed with unresolved tool calls");
|
|
1807
|
+
return (outputIndex) => {
|
|
1808
|
+
const complete = prepared.get(outputIndex);
|
|
1809
|
+
if (!complete) throw new Error("Responses stream completed with unresolved tool calls");
|
|
1810
|
+
complete();
|
|
1811
|
+
};
|
|
1812
|
+
};
|
|
1609
1813
|
const guardedStream = adaptResponsesStream(withFirstStreamEventTimeout(openaiStream, {
|
|
1610
1814
|
provider: model.provider,
|
|
1611
1815
|
api: model.api,
|
|
@@ -1619,6 +1823,8 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1619
1823
|
try {
|
|
1620
1824
|
for await (const event of guardedStream) {
|
|
1621
1825
|
notifyLlmRequestActivity(options?.signal);
|
|
1826
|
+
if (event.type === "response.output_item.done" && event.item.type === "function_call" && event.item.status === "incomplete") incompleteToolCall ??= event.item;
|
|
1827
|
+
if (incompleteToolCall && event.type !== "response.completed" && event.type !== "response.incomplete" && event.type !== "response.failed" && event.type !== "error") continue;
|
|
1622
1828
|
if (event.type === "response.created") output.responseId = event.response.id;
|
|
1623
1829
|
else if (event.type === "response.output_item.added") {
|
|
1624
1830
|
materializeDeferredTextSlots();
|
|
@@ -1666,38 +1872,20 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1666
1872
|
slot.item.summary = slot.item.summary || [];
|
|
1667
1873
|
const lastPart = slot.item.summary[slot.item.summary.length - 1];
|
|
1668
1874
|
if (!lastPart) continue;
|
|
1669
|
-
slot.block.thinking += event.delta;
|
|
1670
1875
|
lastPart.text += event.delta;
|
|
1671
|
-
|
|
1672
|
-
type: "thinking_delta",
|
|
1673
|
-
contentIndex: slot.contentIndex,
|
|
1674
|
-
delta: event.delta,
|
|
1675
|
-
partial: output
|
|
1676
|
-
});
|
|
1876
|
+
appendThinkingDelta(slot, event.delta);
|
|
1677
1877
|
} else if (event.type === "response.reasoning_summary_part.done") {
|
|
1678
1878
|
const slot = outputSlots.resolve(event, "thinking");
|
|
1679
1879
|
if (!slot) continue;
|
|
1680
1880
|
slot.item.summary = slot.item.summary || [];
|
|
1681
1881
|
const lastPart = slot.item.summary[slot.item.summary.length - 1];
|
|
1682
1882
|
if (!lastPart) continue;
|
|
1683
|
-
slot.block.thinking += "\n\n";
|
|
1684
1883
|
lastPart.text += "\n\n";
|
|
1685
|
-
|
|
1686
|
-
type: "thinking_delta",
|
|
1687
|
-
contentIndex: slot.contentIndex,
|
|
1688
|
-
delta: "\n\n",
|
|
1689
|
-
partial: output
|
|
1690
|
-
});
|
|
1884
|
+
appendThinkingDelta(slot, "\n\n");
|
|
1691
1885
|
} else if (event.type === "response.reasoning_text.delta") {
|
|
1692
1886
|
const slot = outputSlots.resolve(event, "thinking");
|
|
1693
1887
|
if (!slot) continue;
|
|
1694
|
-
slot
|
|
1695
|
-
stream.push({
|
|
1696
|
-
type: "thinking_delta",
|
|
1697
|
-
contentIndex: slot.contentIndex,
|
|
1698
|
-
delta: event.delta,
|
|
1699
|
-
partial: output
|
|
1700
|
-
});
|
|
1888
|
+
appendThinkingDelta(slot, event.delta);
|
|
1701
1889
|
} else if (event.type === "response.content_part.added") {
|
|
1702
1890
|
const slot = outputSlots.resolve(event, "text");
|
|
1703
1891
|
if (!slot) continue;
|
|
@@ -1717,15 +1905,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1717
1905
|
slot.item.content.push(lastPart);
|
|
1718
1906
|
}
|
|
1719
1907
|
lastPart.text += event.delta;
|
|
1720
|
-
|
|
1721
|
-
else if (slot.block && slot.contentIndex !== void 0) {
|
|
1722
|
-
slot.block.text += event.delta;
|
|
1723
|
-
stream.push({
|
|
1724
|
-
type: "text_delta",
|
|
1725
|
-
contentIndex: slot.contentIndex,
|
|
1726
|
-
delta: event.delta
|
|
1727
|
-
});
|
|
1728
|
-
}
|
|
1908
|
+
projectTextDelta(slot, event.delta);
|
|
1729
1909
|
} else if (isAzureResponsesTextDeltaEvent(event)) {
|
|
1730
1910
|
const slot = outputSlots.resolve(event, "text");
|
|
1731
1911
|
if (!slot) continue;
|
|
@@ -1739,15 +1919,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1739
1919
|
slot.item.content.push(lastPart);
|
|
1740
1920
|
}
|
|
1741
1921
|
lastPart.text += event.delta;
|
|
1742
|
-
|
|
1743
|
-
else if (slot.block && slot.contentIndex !== void 0) {
|
|
1744
|
-
slot.block.text += event.delta;
|
|
1745
|
-
stream.push({
|
|
1746
|
-
type: "text_delta",
|
|
1747
|
-
contentIndex: slot.contentIndex,
|
|
1748
|
-
delta: event.delta
|
|
1749
|
-
});
|
|
1750
|
-
}
|
|
1922
|
+
projectTextDelta(slot, event.delta);
|
|
1751
1923
|
} else if (event.type === "response.refusal.delta") {
|
|
1752
1924
|
const slot = outputSlots.resolve(event, "text");
|
|
1753
1925
|
if (!slot) continue;
|
|
@@ -1761,15 +1933,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1761
1933
|
slot.item.content.push(lastPart);
|
|
1762
1934
|
}
|
|
1763
1935
|
lastPart.refusal += event.delta;
|
|
1764
|
-
|
|
1765
|
-
else if (slot.block && slot.contentIndex !== void 0) {
|
|
1766
|
-
slot.block.text += event.delta;
|
|
1767
|
-
stream.push({
|
|
1768
|
-
type: "text_delta",
|
|
1769
|
-
contentIndex: slot.contentIndex,
|
|
1770
|
-
delta: event.delta
|
|
1771
|
-
});
|
|
1772
|
-
}
|
|
1936
|
+
projectTextDelta(slot, event.delta);
|
|
1773
1937
|
} else if (event.type === "response.function_call_arguments.delta") {
|
|
1774
1938
|
const toolCall = streamingToolCalls.resolve(event);
|
|
1775
1939
|
if (toolCall) {
|
|
@@ -1881,64 +2045,36 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1881
2045
|
}
|
|
1882
2046
|
outputSlots.forget(outputSlot);
|
|
1883
2047
|
} else if (item.type === "function_call") {
|
|
2048
|
+
if (outputs.get(item, readResponsesOutputIndex(event))?.completed) continue;
|
|
1884
2049
|
const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
|
|
1885
2050
|
if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
|
|
1886
|
-
const streamedArguments = streamingToolCall?.block.partialJson ?? "";
|
|
1887
2051
|
const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
|
|
1888
2052
|
if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
|
|
1889
|
-
const finalArguments = completedArguments !== void 0 && (completedArguments.length > 0 || !streamedArguments) ? completedArguments : streamedArguments;
|
|
1890
2053
|
const validated = resolveCompletedResponsesToolCall(item, {
|
|
1891
2054
|
name: streamingToolCall?.block.name,
|
|
1892
|
-
arguments:
|
|
2055
|
+
arguments: completedArguments || streamingToolCall?.block.partialJson || ""
|
|
1893
2056
|
});
|
|
1894
|
-
|
|
1895
|
-
let contentIndex;
|
|
1896
|
-
if (streamingToolCall) {
|
|
1897
|
-
const block = streamingToolCall.block;
|
|
1898
|
-
block.id = resolveResponsesToolCallId(item, block.id);
|
|
1899
|
-
block.name = validated.name;
|
|
1900
|
-
block.arguments = validated.arguments;
|
|
1901
|
-
delete block.partialJson;
|
|
1902
|
-
toolCall = block;
|
|
1903
|
-
contentIndex = streamingToolCall.contentIndex;
|
|
1904
|
-
} else {
|
|
1905
|
-
toolCall = {
|
|
1906
|
-
type: "toolCall",
|
|
1907
|
-
id: resolveResponsesToolCallId(item),
|
|
1908
|
-
name: validated.name,
|
|
1909
|
-
arguments: validated.arguments
|
|
1910
|
-
};
|
|
1911
|
-
blocks.push(toolCall);
|
|
1912
|
-
contentIndex = blocks.length - 1;
|
|
1913
|
-
stream.push({
|
|
1914
|
-
type: "toolcall_start",
|
|
1915
|
-
contentIndex,
|
|
1916
|
-
partial: output
|
|
1917
|
-
});
|
|
1918
|
-
}
|
|
1919
|
-
if (streamingToolCall) {
|
|
1920
|
-
streamingToolCalls.forget(streamingToolCall);
|
|
1921
|
-
for (const slot of outputSlots.values()) if (slot.type === "toolCall" && slot.toolCall === streamingToolCall) outputSlots.forget(slot);
|
|
1922
|
-
}
|
|
1923
|
-
stream.push({
|
|
1924
|
-
type: "toolcall_end",
|
|
1925
|
-
contentIndex,
|
|
1926
|
-
toolCall,
|
|
1927
|
-
partial: output
|
|
1928
|
-
});
|
|
1929
|
-
outputs.set(item, contentIndex, readResponsesOutputIndex(event), true);
|
|
2057
|
+
finalizeToolCall(item, readResponsesOutputIndex(event), streamingToolCall, validated);
|
|
1930
2058
|
}
|
|
1931
2059
|
} else if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
2060
|
+
terminal.finalizeResponse(event.response, event.type);
|
|
2061
|
+
if (incompleteToolCall) {
|
|
2062
|
+
if (output.errorMessage) throw new Error(output.errorMessage);
|
|
2063
|
+
resolveCompletedResponsesToolCall(incompleteToolCall);
|
|
2064
|
+
}
|
|
2065
|
+
if (event.type === "response.incomplete" && streamingToolCalls.hasActive()) throw new Error(output.errorMessage ?? "Responses stream completed with unresolved tool calls");
|
|
2066
|
+
if (event.type === "response.completed" || output.stopReason === "length") {
|
|
2067
|
+
const items = event.response.output ?? [];
|
|
2068
|
+
const completeToolCall = event.type === "response.completed" ? prepareTerminalToolCalls(items) : void 0;
|
|
2069
|
+
terminal.recoverTerminalOutput(items, completeToolCall);
|
|
2070
|
+
}
|
|
1935
2071
|
terminalResponse = event.type === "response.completed" ? event.response : null;
|
|
1936
2072
|
if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) output.stopReason = "toolUse";
|
|
1937
2073
|
break;
|
|
1938
2074
|
} else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
|
|
1939
2075
|
else if (event.type === "response.failed") {
|
|
1940
2076
|
const failure = normalizeResponsesFailedEvent(isRecord(event) ? event : {}, model);
|
|
1941
|
-
finalizeFailedResponse(event.response, failure.responseId);
|
|
2077
|
+
terminal.finalizeFailedResponse(event.response, failure.responseId);
|
|
1942
2078
|
throw new ResponsesStreamFailure(failure, event.response);
|
|
1943
2079
|
}
|
|
1944
2080
|
}
|
|
@@ -2019,9 +2155,6 @@ function shouldLogStrictToolDowngradeDiagnostic(diagnostics, model) {
|
|
|
2019
2155
|
}
|
|
2020
2156
|
//#endregion
|
|
2021
2157
|
//#region packages/ai/src/providers/openai-responses-shared.ts
|
|
2022
|
-
function isResponsesReasoningEffort(effort) {
|
|
2023
|
-
return effort === "minimal" || effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max";
|
|
2024
|
-
}
|
|
2025
2158
|
function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
|
|
2026
2159
|
return convertProviderResponsesMessages(model, context, allowedToolCallProviders, options);
|
|
2027
2160
|
}
|
|
@@ -2038,17 +2171,17 @@ function applyResponsesServiceTierPricing(usage, serviceTier, model) {
|
|
|
2038
2171
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
2039
2172
|
}
|
|
2040
2173
|
function resolveResponsesReasoningEffort(model, reasoning) {
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2174
|
+
if (!reasoning) return;
|
|
2175
|
+
const clampedReasoning = model.reasoning && model.thinkingLevelMap?.[reasoning] === void 0 && resolveOpenAIModelReasoningEfforts(model)?.includes(reasoning) ? reasoning : clampThinkingLevel(model, reasoning);
|
|
2176
|
+
return clampedReasoning === "off" ? void 0 : clampedReasoning;
|
|
2177
|
+
}
|
|
2178
|
+
function resolveResponsesRequestReasoningEffort(model, reasoning) {
|
|
2179
|
+
const mapped = model.thinkingLevelMap?.[reasoning === "none" ? "off" : reasoning];
|
|
2180
|
+
if (mapped !== void 0) return mapped ?? void 0;
|
|
2181
|
+
return resolveOpenAIModelReasoningEfforts(model) === void 0 ? reasoning === "off" ? "none" : reasoning : resolveOpenAIReasoningEffortForModel({
|
|
2182
|
+
model,
|
|
2183
|
+
effort: reasoning
|
|
2184
|
+
});
|
|
2052
2185
|
}
|
|
2053
2186
|
function applyCommonResponsesParams(params, model, context, options, config) {
|
|
2054
2187
|
if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
|
|
@@ -2058,19 +2191,20 @@ function applyCommonResponsesParams(params, model, context, options, config) {
|
|
|
2058
2191
|
if (converted.tools.length > 0) params.tools = converted.tools;
|
|
2059
2192
|
}
|
|
2060
2193
|
if (!model.reasoning) return;
|
|
2194
|
+
const requestedEffort = options?.reasoningEffort ?? (options?.reasoningSummary ? "medium" : config?.setDefaultReasoningOff ?? true ? "off" : void 0);
|
|
2195
|
+
const effort = requestedEffort === void 0 ? void 0 : resolveResponsesRequestReasoningEffort(model, requestedEffort);
|
|
2196
|
+
if (effort === void 0) return;
|
|
2197
|
+
params.reasoning = { effort };
|
|
2061
2198
|
if (options?.reasoningEffort || options?.reasoningSummary) {
|
|
2062
|
-
params.reasoning =
|
|
2063
|
-
effort: options?.reasoningEffort ? model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort : "medium",
|
|
2064
|
-
summary: options?.reasoningSummary || "auto"
|
|
2065
|
-
};
|
|
2199
|
+
params.reasoning.summary = options?.reasoningSummary || "auto";
|
|
2066
2200
|
params.include = ["reasoning.encrypted_content"];
|
|
2067
|
-
}
|
|
2201
|
+
}
|
|
2068
2202
|
}
|
|
2069
2203
|
function buildResponsesRequestOptions(options) {
|
|
2070
2204
|
return {
|
|
2071
2205
|
...options?.signal ? { signal: options.signal } : {},
|
|
2072
2206
|
...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
|
|
2073
|
-
maxRetries:
|
|
2207
|
+
maxRetries: 0
|
|
2074
2208
|
};
|
|
2075
2209
|
}
|
|
2076
2210
|
function cleanStreamingScratchBuffers(output) {
|
|
@@ -2137,27 +2271,22 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2137
2271
|
authProfileId: options?.authProfileId
|
|
2138
2272
|
})
|
|
2139
2273
|
});
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
reason: output.stopReason,
|
|
2145
|
-
message: output
|
|
2274
|
+
finalizeTransportStream({
|
|
2275
|
+
stream,
|
|
2276
|
+
output,
|
|
2277
|
+
signal: options?.signal
|
|
2146
2278
|
});
|
|
2147
|
-
stream.end();
|
|
2148
2279
|
} catch (error) {
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
error: output
|
|
2280
|
+
failTransportStream({
|
|
2281
|
+
stream,
|
|
2282
|
+
output,
|
|
2283
|
+
signal: options?.signal,
|
|
2284
|
+
error,
|
|
2285
|
+
cleanup: () => cleanStreamingScratchBuffers(output)
|
|
2156
2286
|
});
|
|
2157
|
-
stream.end();
|
|
2158
2287
|
} finally {
|
|
2159
2288
|
firstEventAbort?.dispose();
|
|
2160
2289
|
}
|
|
2161
2290
|
}
|
|
2162
2291
|
//#endregion
|
|
2163
|
-
export {
|
|
2292
|
+
export { resolveModelPayloadDebugMode as $, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as A, resolveNextResponsesEncryptedContentAttempt as B, summarizeResponsesPayload as C, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as D, readResponsesToolCallItemIdentity as E, resolveResponsesMessageSnapshotCollapse as F, responsesInputFingerprint as G, convertResponsesMessages$1 as H, commitResponsesEncryptedContentAttempt as I, captureOpenAIResponsesCompaction as J, CompactionReplayRefreshRequiredError as K, createResponsesStreamWithEncryptedContentRetry as L, isAzureResponsesTextDeltaEventType as M, isResponsesTextContentPartType as N, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as O, isResponsesTextDeltaEventType as P, emitModelTransportDebug as Q, isInvalidEncryptedContentError as R, summarizeResponsesFailedNoDetailsObservation as S, createResponsesToolCallTracker as T, createOpenAIResponsesAssistantOutput as U, buildResponsesInputMessage as V, recordResponsesInputReplay as W, suppressOpenAIResponsesCompaction as X, resolveNewestOpenAIResponsesCompactionReplay as Y, resolveReplayableResponsesMessageId as Z, normalizeResponsesFailedEvent as _, resolveResponsesReasoningEffort as a, stringifyRedactedPayload as b, convertResponsesToolPayload as c, readResponsesReasoningTokens as d, resolveModelSseDebugMode as et, resolveResponsesTerminalStopReason as f, logResponsesFailedNoDetails as g, buildResponsesFailedNoDetailsObservation as h, createResponsesAssistantOutput as i, isAzureResponsesTextDeltaEvent as j, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as k, processResponsesStream as l, ResponsesStreamFailure as m, applyResponsesServiceTierPricing as n, resolveResponsesRequestReasoningEffort as o, observeResponsesStream as p, buildOpenAIResponsesReasoningReplayMetadata as q, convertResponsesMessages as r, runResponsesStreamLifecycle as s, applyCommonResponsesParams as t, mapResponsesTerminalUsage as u, safeDebugValue as v, summarizeResponsesTools as w, summarizeOpenAITransportError as x, stringifyRedactedEvent as y, resolveAzureOpenAIApiVersion as z };
|