@openclaw/ai 2026.8.1-beta.1 → 2026.8.1-beta.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-CE-7SkF6.mjs → anthropic-B6dLpq5L.mjs} +37 -22
- package/dist/{src-QkygScBs.mjs → anthropic-JsNA5KCu.mjs} +0 -1
- package/dist/{anthropic-usage-Ma4iX6uG.mjs → anthropic-compaction-replay-8lJNKXOE.mjs} +225 -102
- package/dist/anthropic-payload-policy-CiEuQS72.d.mts +49 -0
- package/dist/{api-registry-EpJoVwM1.d.mts → api-registry-k3zTz0cV.d.mts} +1 -1
- package/dist/{azure-openai-responses-Cc_kasye.mjs → azure-openai-responses-mxIOtUnn.mjs} +23 -29
- package/dist/diagnostics.d.mts +24 -1
- package/dist/diagnostics.mjs +2 -1
- package/dist/{event-stream-DRmDMRHH.d.mts → event-stream-BP6AWT8j.d.mts} +3 -1
- package/dist/{event-stream-CEV9t6da.mjs → event-stream-uSMZJ3FA.mjs} +16 -3
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-CGQu21aw.mjs → google-C7h2QzDX.mjs} +4 -4
- package/dist/{google-shared-Cq2UKx1l.mjs → google-shared-B0Qr9OR7.mjs} +9 -18
- package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
- package/dist/{google-vertex-CusxWzvE.mjs → google-vertex-Bhc3TjDl.mjs} +5 -4
- package/dist/{llm-request-activity-BjtkplhG.mjs → headers-DdOQtGuU.mjs} +9 -1
- package/dist/{host-Bl7Kgddo.mjs → host-DTqNc7ad.mjs} +227 -168
- package/dist/{host-Dn4_SZI2.d.mts → host-vWgMMhiJ.d.mts} +9 -4
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +7 -5
- package/dist/internal/anthropic.d.mts +13 -5
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
- package/dist/internal/openai-responses-payload-policy.mjs +3 -0
- package/dist/internal/openai.d.mts +6 -6
- package/dist/internal/openai.mjs +8 -7
- package/dist/internal/runtime.d.mts +17 -5
- package/dist/internal/runtime.mjs +85 -73
- package/dist/internal/shared.d.mts +1 -6
- package/dist/internal/shared.mjs +3 -4
- package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
- package/dist/{mistral-Dx6VzNjf.mjs → mistral-CEWoQI_g.mjs} +26 -45
- package/dist/{number-coercion-1Miyb5MO.mjs → number-coercion-H9qHik3g.mjs} +7 -2
- package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
- package/dist/{openai-chatgpt-responses-SC9m0FSf.mjs → openai-chatgpt-responses-CrPmqERt.mjs} +225 -144
- package/dist/{openai-completions-BaIpl93j.mjs → openai-completions-BPnt4Sml.mjs} +28 -43
- package/dist/openai-completions-compat-Dt3dcawL.d.mts +43 -0
- package/dist/{openai-responses-Bdx3V_Yu.mjs → openai-responses-DhIKtOup.mjs} +17 -24
- package/dist/openai-responses-contracts-CyfIkQi5.mjs +253 -0
- package/dist/openai-responses-contracts-XpZJxrRG.d.mts +68 -0
- package/dist/openai-responses-payload-policy-BDxV-W0c.mjs +206 -0
- package/dist/openai-responses-payload-policy-BSs371VM.d.mts +40 -0
- package/dist/{openai-responses-prompt-observer-internal-DDZPxRfr.mjs → openai-responses-prompt-observer-internal-DgNTYnRY.mjs} +3 -3
- package/dist/{openai-responses-stream-internal-Bl8YyVtF.mjs → openai-responses-shared-DXIt3iY5.mjs} +1211 -908
- package/dist/{openai-reasoning-compat-DKebnIBL.mjs → openai-stop-reason-BkFkqqK0.mjs} +198 -172
- package/dist/{openai-transport-shared-Cipt7egQ.mjs → openai-tool-projection-CY04OcvQ.mjs} +151 -128
- package/dist/provider-error-BUwEnjXq.mjs +429 -0
- package/dist/provider-error-CzNw4BWX.d.mts +12 -0
- package/dist/{provider-options-C5kYML7i.d.mts → provider-options-B96RdNpH.d.mts} +9 -3
- package/dist/provider-transcript-transform-ePx-Bbfr.mjs +155 -0
- package/dist/provider-types.d.mts +31 -0
- package/dist/provider-types.mjs +8 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +17 -19
- package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-rnPwX2pg.mjs} +14 -8
- package/dist/record-coerce-DdXsgUd_.mjs +23 -0
- package/dist/{model-utils-Dau5dlgm.mjs → sanitize-unicode-BYqrYtC_.mjs} +28 -2
- package/dist/session-resources-CkR4WWy1.mjs +21 -0
- package/dist/simple-options-D58D5Kvw.mjs +117 -0
- package/dist/src-D2H6yKkH.mjs +2 -0
- package/dist/{stream-first-event-timeout-BIBomOGq.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{tool-schema-json-projection-B1b-XCn5.mjs → tool-schema-json-projection-q5d7QX5c.mjs} +5 -7
- package/dist/transport-utils-DJqkxbhC.mjs +138 -0
- package/dist/transports.d.mts +135 -178
- package/dist/transports.mjs +1732 -1294
- package/dist/types-BDdaOVi2.mjs +6 -0
- package/dist/{types-CH7ReIcU.d.mts → types-BHNrPS1l.d.mts} +19 -1
- package/dist/types.d.mts +4 -4
- package/dist/types.mjs +6 -4
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
- package/dist/{validation-CcPcuEbR.d.mts → validation-DT9SrFn3.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +15 -1
- package/dist/headers-B_e4-1J0.mjs +0 -9
- package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
- package/dist/openai-responses-contracts-BBKBfAqR.d.mts +0 -116
- package/dist/openai-responses-shared-CCyMvg7M.mjs +0 -403
- package/dist/provider-error-DI0Ts28U.mjs +0 -47
- package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
- package/dist/tool-result-text-Dvkp2Dus.mjs +0 -274
- package/dist/transform-messages-DfjpNXNQ.mjs +0 -2
- package/dist/transport-stream-shared-CPNv7A3r.mjs +0 -297
package/dist/{openai-responses-stream-internal-Bl8YyVtF.mjs → openai-responses-shared-DXIt3iY5.mjs}
RENAMED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { a as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { a as
|
|
1
|
+
import { a as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
|
|
2
|
+
import { i as clampThinkingLevel, r as calculateCost } from "./sanitize-unicode-BYqrYtC_.mjs";
|
|
3
|
+
import { a as describeToolResultMediaPlaceholder, l as isImageWithMediaPayload, n as getAiTransportHost, s as extractToolResultText } from "./host-DTqNc7ad.mjs";
|
|
4
|
+
import { a as isRecord, n as asNullableRecord } from "./record-coerce-DdXsgUd_.mjs";
|
|
5
|
+
import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
|
|
6
|
+
import { n as projectProviderError } from "./provider-error-BUwEnjXq.mjs";
|
|
7
|
+
import { t as asFiniteNumber } from "./number-coercion-H9qHik3g.mjs";
|
|
8
|
+
import { C as normalizeStringEntries, S as supportsOpenAITemperature, T as uniqueValues, a as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, f as RESPONSE_FAILED_NO_DETAILS_MESSAGE, o as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, s as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY, x as supportsOpenAIReasoningEffort, y as resolveOpenAIReasoningEffortForModel } from "./openai-responses-contracts-CyfIkQi5.mjs";
|
|
9
|
+
import { f as sortPromptCacheToolsByName, l as stripSystemPromptCacheBoundary } from "./simple-options-D58D5Kvw.mjs";
|
|
10
|
+
import { c as transformTransportMessages } from "./tool-schema-json-projection-q5d7QX5c.mjs";
|
|
11
|
+
import { n as parseStreamingJson } from "./json-parse-CDnesDM_.mjs";
|
|
12
|
+
import { n as notifyLlmRequestActivity } from "./headers-DdOQtGuU.mjs";
|
|
9
13
|
import { t as shortHash } from "./hash-CHgqbJmD.mjs";
|
|
10
|
-
import {
|
|
14
|
+
import { d as sanitizeTransportPayloadText, f as transportAbortError, p as withProviderResponseHook, t as transformProviderMessages, u as sanitizeNonEmptyTransportPayloadText } from "./provider-transcript-transform-ePx-Bbfr.mjs";
|
|
15
|
+
import { l as redactIdentifier, u as redactSensitiveText } from "./transport-utils-DJqkxbhC.mjs";
|
|
16
|
+
import { a as createModelStreamCooperativeScheduler, c as log, o as createOpenAIResponseHook, t as projectOpenAITools } from "./openai-tool-projection-CY04OcvQ.mjs";
|
|
17
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-MK28puvq.mjs";
|
|
18
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
11
19
|
//#region packages/ai/src/transports/json-unsafe-integers.ts
|
|
12
20
|
/**
|
|
13
21
|
* JSON parsing helpers that preserve integer literals larger than
|
|
@@ -92,37 +100,35 @@ function parseJsonPreservingUnsafeIntegers(input) {
|
|
|
92
100
|
}
|
|
93
101
|
/** Parses or accepts an object while preserving unsafe integer literals in string input. */
|
|
94
102
|
function parseJsonObjectPreservingUnsafeIntegers(value) {
|
|
95
|
-
if (typeof value === "string") {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
|
|
99
|
-
} catch {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
103
|
+
if (typeof value === "string") try {
|
|
104
|
+
return asNullableRecord(parseJsonPreservingUnsafeIntegers(value));
|
|
105
|
+
} catch {
|
|
102
106
|
return null;
|
|
103
107
|
}
|
|
104
|
-
|
|
105
|
-
return null;
|
|
108
|
+
return asNullableRecord(value);
|
|
106
109
|
}
|
|
107
110
|
//#endregion
|
|
108
111
|
//#region packages/ai/src/transports/model-transport-debug.ts
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Environment-driven debug controls for model transport logging.
|
|
114
|
+
*
|
|
115
|
+
* Model adapters share these helpers so payload, SSE, and transport diagnostics
|
|
116
|
+
* interpret OpenClaw debug environment variables consistently.
|
|
117
|
+
*/
|
|
112
118
|
function isTruthyEnv(value) {
|
|
113
|
-
const normalized =
|
|
119
|
+
const normalized = normalizeLowercaseStringOrEmpty(value);
|
|
114
120
|
return normalized.length > 0 && normalized !== "0" && normalized !== "false" && normalized !== "off" && normalized !== "no";
|
|
115
121
|
}
|
|
116
122
|
/** Resolves model payload debug verbosity from `OPENCLAW_DEBUG_MODEL_PAYLOAD`. */
|
|
117
123
|
function resolveModelPayloadDebugMode(env = process.env) {
|
|
118
|
-
const normalized =
|
|
124
|
+
const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_MODEL_PAYLOAD);
|
|
119
125
|
if (normalized === "tools" || normalized === "full-redacted") return normalized;
|
|
120
126
|
if (normalized === "summary") return "summary";
|
|
121
127
|
return "off";
|
|
122
128
|
}
|
|
123
129
|
/** Resolves SSE stream debug verbosity from `OPENCLAW_DEBUG_SSE`. */
|
|
124
130
|
function resolveModelSseDebugMode(env = process.env) {
|
|
125
|
-
const normalized =
|
|
131
|
+
const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_SSE);
|
|
126
132
|
if (normalized === "peek") return "peek";
|
|
127
133
|
if (normalized === "events" || isTruthyEnv(normalized)) return "events";
|
|
128
134
|
return "off";
|
|
@@ -143,173 +149,6 @@ function emitModelTransportDebug(log, message) {
|
|
|
143
149
|
log.debug(message);
|
|
144
150
|
}
|
|
145
151
|
//#endregion
|
|
146
|
-
//#region packages/normalization-core/src/string-normalization.ts
|
|
147
|
-
/** Coerces entries to strings, trims them, and drops empty results. */
|
|
148
|
-
function normalizeStringEntries(list) {
|
|
149
|
-
return (list ?? []).map((entry) => normalizeOptionalString(String(entry)) ?? "").filter(Boolean);
|
|
150
|
-
}
|
|
151
|
-
/** Returns first-seen unique values while preserving insertion order. */
|
|
152
|
-
function uniqueValues(values) {
|
|
153
|
-
return [...new Set(values)];
|
|
154
|
-
}
|
|
155
|
-
/** Returns first-seen unique strings while preserving insertion order. */
|
|
156
|
-
function uniqueStrings(values) {
|
|
157
|
-
return uniqueValues(values);
|
|
158
|
-
}
|
|
159
|
-
//#endregion
|
|
160
|
-
//#region packages/ai/src/providers/openai-reasoning-effort.ts
|
|
161
|
-
/**
|
|
162
|
-
* OpenAI-compatible reasoning-effort normalization. Different GPT families
|
|
163
|
-
* expose different accepted effort enums, so callers map requested values here
|
|
164
|
-
* before constructing provider payloads.
|
|
165
|
-
*/
|
|
166
|
-
const GPT_5_REASONING_EFFORTS = [
|
|
167
|
-
"minimal",
|
|
168
|
-
"low",
|
|
169
|
-
"medium",
|
|
170
|
-
"high"
|
|
171
|
-
];
|
|
172
|
-
const GPT_51_REASONING_EFFORTS = [
|
|
173
|
-
"none",
|
|
174
|
-
"low",
|
|
175
|
-
"medium",
|
|
176
|
-
"high"
|
|
177
|
-
];
|
|
178
|
-
const GPT_52_REASONING_EFFORTS = [
|
|
179
|
-
"none",
|
|
180
|
-
"low",
|
|
181
|
-
"medium",
|
|
182
|
-
"high",
|
|
183
|
-
"xhigh"
|
|
184
|
-
];
|
|
185
|
-
const GPT_56_REASONING_EFFORTS = [
|
|
186
|
-
"none",
|
|
187
|
-
"low",
|
|
188
|
-
"medium",
|
|
189
|
-
"high",
|
|
190
|
-
"xhigh",
|
|
191
|
-
"max"
|
|
192
|
-
];
|
|
193
|
-
const GPT_CODEX_REASONING_EFFORTS = [
|
|
194
|
-
"low",
|
|
195
|
-
"medium",
|
|
196
|
-
"high",
|
|
197
|
-
"xhigh"
|
|
198
|
-
];
|
|
199
|
-
const GPT_PRO_REASONING_EFFORTS = [
|
|
200
|
-
"medium",
|
|
201
|
-
"high",
|
|
202
|
-
"xhigh"
|
|
203
|
-
];
|
|
204
|
-
const GPT_5_PRO_REASONING_EFFORTS = ["high"];
|
|
205
|
-
const GPT_51_CODEX_MAX_REASONING_EFFORTS = [
|
|
206
|
-
"none",
|
|
207
|
-
"medium",
|
|
208
|
-
"high",
|
|
209
|
-
"xhigh"
|
|
210
|
-
];
|
|
211
|
-
const GPT_51_CODEX_MINI_REASONING_EFFORTS = ["medium"];
|
|
212
|
-
const GENERIC_REASONING_EFFORTS = [
|
|
213
|
-
"low",
|
|
214
|
-
"medium",
|
|
215
|
-
"high"
|
|
216
|
-
];
|
|
217
|
-
const CANONICAL_REASONING_EFFORTS = /* @__PURE__ */ new Set([
|
|
218
|
-
"none",
|
|
219
|
-
"minimal",
|
|
220
|
-
"low",
|
|
221
|
-
"medium",
|
|
222
|
-
"high",
|
|
223
|
-
"xhigh",
|
|
224
|
-
"max",
|
|
225
|
-
"off"
|
|
226
|
-
]);
|
|
227
|
-
function normalizeModelId(id) {
|
|
228
|
-
return normalizeLowercaseStringOrEmpty(id ?? "").replace(/-\d{4}-\d{2}-\d{2}$/u, "");
|
|
229
|
-
}
|
|
230
|
-
/** Return whether a model is the GPT-5.4 mini family. */
|
|
231
|
-
function isOpenAIGpt54MiniModel(model) {
|
|
232
|
-
const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
|
|
233
|
-
return /^gpt-5\.4-mini(?:-|$)/u.test(id);
|
|
234
|
-
}
|
|
235
|
-
/** Return whether a model is the GPT-5.5 family. */
|
|
236
|
-
function isOpenAIGpt55Model(model) {
|
|
237
|
-
const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
|
|
238
|
-
const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
|
|
239
|
-
return /^gpt-5\.5(?:-|$)/u.test(id) || /^gpt-5\.5(?:\s|\(|-|$)/u.test(name);
|
|
240
|
-
}
|
|
241
|
-
/** Return whether a model is the GPT-5.6 family. */
|
|
242
|
-
function isOpenAIGpt56Model(model) {
|
|
243
|
-
const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
|
|
244
|
-
const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
|
|
245
|
-
return /^gpt-5\.6(?:-|$)/u.test(id) || /^gpt-5\.6(?:\s|\(|-|$)/u.test(name);
|
|
246
|
-
}
|
|
247
|
-
/** Normalize user-facing reasoning effort names to API effort names. */
|
|
248
|
-
function normalizeOpenAIReasoningEffort(effort) {
|
|
249
|
-
const trimmed = effort.trim();
|
|
250
|
-
const folded = trimmed.toLowerCase();
|
|
251
|
-
return CANONICAL_REASONING_EFFORTS.has(folded) ? folded : trimmed;
|
|
252
|
-
}
|
|
253
|
-
function readCompatReasoningEfforts(compat) {
|
|
254
|
-
if (!compat || typeof compat !== "object") return;
|
|
255
|
-
if (compat.supportsReasoningEffort === false) return [];
|
|
256
|
-
const raw = compat.supportedReasoningEfforts;
|
|
257
|
-
if (!Array.isArray(raw)) return;
|
|
258
|
-
const supported = uniqueStrings(normalizeStringEntries(raw.filter((value) => typeof value === "string")));
|
|
259
|
-
return supported.length > 0 ? supported : void 0;
|
|
260
|
-
}
|
|
261
|
-
function isDisabledReasoningEffort(effort) {
|
|
262
|
-
return effort === "none" || effort === "off";
|
|
263
|
-
}
|
|
264
|
-
/** Resolve the reasoning efforts accepted by a specific OpenAI-compatible model. */
|
|
265
|
-
function resolveOpenAISupportedReasoningEfforts(model) {
|
|
266
|
-
const compatEfforts = readCompatReasoningEfforts(model.compat);
|
|
267
|
-
if (compatEfforts) return compatEfforts;
|
|
268
|
-
const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
|
|
269
|
-
if (/^gpt-5\.6(?:-|$)/u.test(id)) return GPT_56_REASONING_EFFORTS;
|
|
270
|
-
if (id === "gpt-5.1-codex-mini") return GPT_51_CODEX_MINI_REASONING_EFFORTS;
|
|
271
|
-
if (id === "gpt-5.1-codex-max") return GPT_51_CODEX_MAX_REASONING_EFFORTS;
|
|
272
|
-
if (/^gpt-5(?:\.\d+)?-codex(?:-|$)/u.test(id)) return GPT_CODEX_REASONING_EFFORTS;
|
|
273
|
-
if (id === "gpt-5-pro") return GPT_5_PRO_REASONING_EFFORTS;
|
|
274
|
-
if (/^gpt-5\.[2-9](?:\.\d+)?-pro(?:-|$)/u.test(id)) return GPT_PRO_REASONING_EFFORTS;
|
|
275
|
-
if (/^gpt-5\.[2-9](?:\.\d+)?(?:-|$)/u.test(id)) return GPT_52_REASONING_EFFORTS;
|
|
276
|
-
if (/^gpt-5\.1(?:-|$)/u.test(id)) return GPT_51_REASONING_EFFORTS;
|
|
277
|
-
if (/^gpt-5(?:-|$)/u.test(id)) return GPT_5_REASONING_EFFORTS;
|
|
278
|
-
return GENERIC_REASONING_EFFORTS;
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Return whether a model accepts the temperature parameter. The GPT-5.6
|
|
282
|
-
* family rejects it with a 400; catalog compat can override per model.
|
|
283
|
-
*/
|
|
284
|
-
function supportsOpenAITemperature(model) {
|
|
285
|
-
const compat = model.compat;
|
|
286
|
-
if (compat && typeof compat === "object") {
|
|
287
|
-
const declared = compat.supportsTemperature;
|
|
288
|
-
if (typeof declared === "boolean") return declared;
|
|
289
|
-
}
|
|
290
|
-
const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
|
|
291
|
-
return !/^gpt-5\.6(?:-|$)/u.test(id);
|
|
292
|
-
}
|
|
293
|
-
/** Return whether a model accepts a requested reasoning effort. */
|
|
294
|
-
function supportsOpenAIReasoningEffort(model, effort) {
|
|
295
|
-
return resolveOpenAISupportedReasoningEfforts(model).includes(normalizeOpenAIReasoningEffort(effort));
|
|
296
|
-
}
|
|
297
|
-
/** Resolve a requested reasoning effort to the closest value supported by the model. */
|
|
298
|
-
function resolveOpenAIReasoningEffortForModel(params) {
|
|
299
|
-
const requested = normalizeOpenAIReasoningEffort(params.effort);
|
|
300
|
-
const mapped = params.fallbackMap?.[requested] ?? (params.fallbackMap && CANONICAL_REASONING_EFFORTS.has(requested) ? Object.entries(params.fallbackMap).find(([effort]) => normalizeOpenAIReasoningEffort(effort) === requested)?.[1] : void 0);
|
|
301
|
-
const normalized = mapped === void 0 ? requested : mapped.trim();
|
|
302
|
-
const supported = resolveOpenAISupportedReasoningEfforts(params.model);
|
|
303
|
-
if (supported.includes(normalized)) return normalized;
|
|
304
|
-
if (requested === "off" && supported.includes("none")) return "none";
|
|
305
|
-
if (isDisabledReasoningEffort(requested) || isDisabledReasoningEffort(normalized)) return;
|
|
306
|
-
if (requested === "minimal" && supported.includes("low")) return "low";
|
|
307
|
-
if ((requested === "minimal" || requested === "low") && supported.includes("medium")) return "medium";
|
|
308
|
-
if (requested === "xhigh" && supported.includes("high")) return "high";
|
|
309
|
-
if (requested === "max" && supported.includes("xhigh")) return "xhigh";
|
|
310
|
-
return supported.find((effort) => !isDisabledReasoningEffort(normalizeOpenAIReasoningEffort(effort)));
|
|
311
|
-
}
|
|
312
|
-
//#endregion
|
|
313
152
|
//#region packages/ai/src/providers/clean-for-gemini.ts
|
|
314
153
|
const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
315
154
|
"patternProperties",
|
|
@@ -608,9 +447,6 @@ const SCHEMA_CHILD_KEYS = /* @__PURE__ */ new Set([
|
|
|
608
447
|
"unevaluatedItems",
|
|
609
448
|
"unevaluatedProperties"
|
|
610
449
|
]);
|
|
611
|
-
function isSchemaRecord(value) {
|
|
612
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
613
|
-
}
|
|
614
450
|
function cleanSchemaNode(node) {
|
|
615
451
|
if (Array.isArray(node)) {
|
|
616
452
|
let changed = false;
|
|
@@ -621,7 +457,7 @@ function cleanSchemaNode(node) {
|
|
|
621
457
|
});
|
|
622
458
|
return changed ? entries : node;
|
|
623
459
|
}
|
|
624
|
-
if (!
|
|
460
|
+
if (!isRecord(node)) return node;
|
|
625
461
|
let changed = false;
|
|
626
462
|
const cleaned = {};
|
|
627
463
|
for (const [key, value] of Object.entries(node)) {
|
|
@@ -634,7 +470,7 @@ function cleanSchemaNode(node) {
|
|
|
634
470
|
continue;
|
|
635
471
|
}
|
|
636
472
|
let next = value;
|
|
637
|
-
if (SCHEMA_MAP_KEYS$2.has(key) &&
|
|
473
|
+
if (SCHEMA_MAP_KEYS$2.has(key) && isRecord(value)) {
|
|
638
474
|
let mapChanged = false;
|
|
639
475
|
next = Object.fromEntries(Object.entries(value).map(([childKey, childValue]) => {
|
|
640
476
|
const cleanedChild = cleanSchemaNode(childValue);
|
|
@@ -653,10 +489,10 @@ function collectSchemaViolations(node, path, violations) {
|
|
|
653
489
|
node.forEach((entry, index) => collectSchemaViolations(entry, `${path}[${index}]`, violations));
|
|
654
490
|
return;
|
|
655
491
|
}
|
|
656
|
-
if (!
|
|
492
|
+
if (!isRecord(node)) return;
|
|
657
493
|
if ("pattern" in node) violations.push(`${path}.pattern`);
|
|
658
494
|
if (typeof node.maxLength === "number" && node.maxLength >= 2e3) violations.push(`${path}.maxLength`);
|
|
659
|
-
for (const [key, value] of Object.entries(node)) if (SCHEMA_MAP_KEYS$2.has(key) &&
|
|
495
|
+
for (const [key, value] of Object.entries(node)) if (SCHEMA_MAP_KEYS$2.has(key) && isRecord(value)) for (const [childKey, childValue] of Object.entries(value)) collectSchemaViolations(childValue, `${path}.${key}.${childKey}`, violations);
|
|
660
496
|
else if (SCHEMA_CHILD_KEYS.has(key)) collectSchemaViolations(value, `${path}.${key}`, violations);
|
|
661
497
|
}
|
|
662
498
|
/** Removes JSON Schema constraints that llama.cpp cannot compile into GBNF. */
|
|
@@ -1458,7 +1294,7 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
|
1458
1294
|
* Caches normalized object inputs by provider compatibility so repeated inventory builds preserve identity.
|
|
1459
1295
|
*/
|
|
1460
1296
|
const MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8;
|
|
1461
|
-
|
|
1297
|
+
const strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
|
|
1462
1298
|
function resolveToolSchemaModelCompat(compat) {
|
|
1463
1299
|
if (!compat) return;
|
|
1464
1300
|
const unsupportedToolSchemaKeywords = Array.isArray(compat.unsupportedToolSchemaKeywords) ? compat.unsupportedToolSchemaKeywords.filter((keyword) => typeof keyword === "string") : [];
|
|
@@ -1483,9 +1319,6 @@ function rememberStrictOpenAISchema(schema, key, value) {
|
|
|
1483
1319
|
}, ...entries.filter((entry) => entry.key !== key)].slice(0, MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA));
|
|
1484
1320
|
return value;
|
|
1485
1321
|
}
|
|
1486
|
-
function clearOpenAIToolSchemaCacheForTest() {
|
|
1487
|
-
strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
|
|
1488
|
-
}
|
|
1489
1322
|
/** Normalizes a tool parameter schema into the OpenAI strict JSON-schema subset. */
|
|
1490
1323
|
function normalizeStrictOpenAIJsonSchema(schema, modelCompat) {
|
|
1491
1324
|
const schemaInput = schema ?? {};
|
|
@@ -1584,308 +1417,148 @@ function resolveReplayableResponsesMessageId(params) {
|
|
|
1584
1417
|
if (!params.textSignatureId) return params.fallbackOrdinal === 0 ? params.fallbackId : `${params.fallbackId}_${params.fallbackOrdinal}`;
|
|
1585
1418
|
return params.previousReplayItemWasReasoning ? params.textSignatureId : void 0;
|
|
1586
1419
|
}
|
|
1587
|
-
const OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS = "Follow the user request.";
|
|
1588
|
-
const AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS = 3e4;
|
|
1589
|
-
const RESPONSE_FAILED_NO_DETAILS_MESSAGE = "Unknown error (no error details in response)";
|
|
1590
|
-
const OPENAI_RESPONSES_REASONING_REPLAY_META_KEY = "__openclaw_replay";
|
|
1591
|
-
const OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY = "openclawReasoningReplay";
|
|
1592
|
-
const PROMPT_OBSERVER = Symbol("openaiResponsesPromptObserver");
|
|
1593
|
-
const responsesPromptObserver = {
|
|
1594
|
-
set(options, observer) {
|
|
1595
|
-
Reflect.set(options, PROMPT_OBSERVER, observer);
|
|
1596
|
-
},
|
|
1597
|
-
get(options) {
|
|
1598
|
-
return Reflect.get(options, PROMPT_OBSERVER);
|
|
1599
|
-
},
|
|
1600
|
-
copy(source, target) {
|
|
1601
|
-
const observer = source && responsesPromptObserver.get(source);
|
|
1602
|
-
if (observer) responsesPromptObserver.set(target, observer);
|
|
1603
|
-
}
|
|
1604
|
-
};
|
|
1605
1420
|
//#endregion
|
|
1606
|
-
//#region packages/ai/src/transports/openai-responses-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
function getServiceTierCostMultiplier(serviceTier) {
|
|
1613
|
-
switch (serviceTier) {
|
|
1614
|
-
case "flex": return .5;
|
|
1615
|
-
case "priority": return 2;
|
|
1616
|
-
default: return 1;
|
|
1617
|
-
}
|
|
1421
|
+
//#region packages/ai/src/transports/openai-responses-compaction-replay.ts
|
|
1422
|
+
const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE = "openai-responses-compaction-suppression";
|
|
1423
|
+
const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA = "rejected";
|
|
1424
|
+
function hashOptionalReplayContextValue(value) {
|
|
1425
|
+
const normalized = value?.trim();
|
|
1426
|
+
return normalized ? shortHash(normalized) : void 0;
|
|
1618
1427
|
}
|
|
1619
|
-
function
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1428
|
+
function buildOpenAIResponsesReplayContext(model, options) {
|
|
1429
|
+
return {
|
|
1430
|
+
provider: model.provider,
|
|
1431
|
+
api: model.api,
|
|
1432
|
+
model: model.id,
|
|
1433
|
+
baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
|
|
1434
|
+
sessionHash: hashOptionalReplayContextValue(options?.sessionId),
|
|
1435
|
+
authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
|
|
1436
|
+
};
|
|
1627
1437
|
}
|
|
1628
|
-
function
|
|
1629
|
-
if (
|
|
1630
|
-
|
|
1631
|
-
if (value === null) return "null";
|
|
1632
|
-
if (value === void 0) return "undefined";
|
|
1633
|
-
return Array.isArray(value) ? "array" : typeof value;
|
|
1438
|
+
function isOpenAIResponsesReplayContext(value) {
|
|
1439
|
+
if (!isRecord(value)) return false;
|
|
1440
|
+
return typeof value.provider === "string" && typeof value.api === "string" && typeof value.model === "string" && (value.baseUrlHash === void 0 || typeof value.baseUrlHash === "string") && (value.sessionHash === void 0 || typeof value.sessionHash === "string") && (value.authProfileHash === void 0 || typeof value.authProfileHash === "string");
|
|
1634
1441
|
}
|
|
1635
|
-
function
|
|
1636
|
-
if (typeof
|
|
1637
|
-
|
|
1638
|
-
if (
|
|
1639
|
-
|
|
1640
|
-
let total = 0;
|
|
1641
|
-
if (typeof record.text === "string") total += record.text.length;
|
|
1642
|
-
if (typeof record.content === "string") total += record.content.length;
|
|
1643
|
-
else if (Array.isArray(record.content)) total += responseInputTextChars(record.content);
|
|
1644
|
-
return total;
|
|
1442
|
+
function readOpenAIResponsesCompactionReplayState(value) {
|
|
1443
|
+
if (!isOpenAIResponsesReplayContext(value) || typeof value.baseUrlHash !== "string" || value.v !== 1) return;
|
|
1444
|
+
const state = value;
|
|
1445
|
+
if (state.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) return state.data === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA ? state : void 0;
|
|
1446
|
+
return state.type === "openai-responses-compaction" && typeof state.data === "string" && state.data.length > 0 && (state.id === void 0 || typeof state.id === "string") && (state.replayIndex === void 0 || Number.isSafeInteger(state.replayIndex) && state.replayIndex >= 0) ? state : void 0;
|
|
1645
1447
|
}
|
|
1646
|
-
function
|
|
1647
|
-
|
|
1648
|
-
const roles = /* @__PURE__ */ new Set();
|
|
1649
|
-
for (const item of input) if (item && typeof item === "object") {
|
|
1650
|
-
const role = item.role;
|
|
1651
|
-
if (typeof role === "string" && role.trim()) roles.add(role.trim());
|
|
1652
|
-
}
|
|
1653
|
-
return [...roles].toSorted().join(",");
|
|
1448
|
+
function openAIResponsesReplayContextMatches(state, context) {
|
|
1449
|
+
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;
|
|
1654
1450
|
}
|
|
1655
|
-
function
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1451
|
+
function captureOpenAIResponsesCompaction(output, item, replayIndex, model, captureMetadata) {
|
|
1452
|
+
const metadata = captureMetadata ?? buildOpenAIResponsesReasoningReplayMetadata(model);
|
|
1453
|
+
if (!item.encrypted_content) return;
|
|
1454
|
+
if (!metadata?.baseUrlHash) {
|
|
1455
|
+
log.debug("[responses] skipping compaction capture: missing base URL hash");
|
|
1659
1456
|
return;
|
|
1660
1457
|
}
|
|
1458
|
+
const currentReplay = readOpenAIResponsesCompactionReplayState(output.providerReplay);
|
|
1459
|
+
if (currentReplay?.type === "openai-responses-compaction" && (currentReplay.replayIndex ?? -1) > (replayIndex ?? Number.MAX_SAFE_INTEGER)) return;
|
|
1460
|
+
output.providerReplay = {
|
|
1461
|
+
v: 1,
|
|
1462
|
+
type: OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE,
|
|
1463
|
+
...item.id ? { id: item.id } : {},
|
|
1464
|
+
data: item.encrypted_content,
|
|
1465
|
+
...replayIndex === void 0 ? {} : { replayIndex },
|
|
1466
|
+
provider: metadata.provider,
|
|
1467
|
+
api: metadata.api,
|
|
1468
|
+
model: metadata.model,
|
|
1469
|
+
baseUrlHash: metadata.baseUrlHash,
|
|
1470
|
+
...metadata.sessionHash ? { sessionHash: metadata.sessionHash } : {},
|
|
1471
|
+
...metadata.authProfileHash ? { authProfileHash: metadata.authProfileHash } : {}
|
|
1472
|
+
};
|
|
1661
1473
|
}
|
|
1662
|
-
function
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
return typeof type === "string" && type !== "function" ? type : "";
|
|
1674
|
-
}
|
|
1675
|
-
function summarizeResponsesTools(tools) {
|
|
1676
|
-
if (!Array.isArray(tools)) return "count=0";
|
|
1677
|
-
const names = tools.map(readResponsesToolDisplayName).filter(Boolean);
|
|
1678
|
-
const mode = resolveModelPayloadDebugMode();
|
|
1679
|
-
const maxNames = mode === "tools" || mode === "full-redacted" ? names.length : 12;
|
|
1680
|
-
const label = maxNames >= names.length ? "names" : "sample";
|
|
1681
|
-
const shown = names.slice(0, maxNames).join(",");
|
|
1682
|
-
return `count=${tools.length}${shown ? ` ${label}=${shown}` : ""}`;
|
|
1683
|
-
}
|
|
1684
|
-
function stringifyRedactedPayload(value) {
|
|
1685
|
-
try {
|
|
1686
|
-
const encoded = JSON.stringify(value);
|
|
1687
|
-
if (!encoded) return "<empty>";
|
|
1688
|
-
const redacted = redactSensitiveText(encoded, { mode: "tools" });
|
|
1689
|
-
return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
|
|
1690
|
-
} catch {
|
|
1691
|
-
return "<unserializable>";
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
function stringifyRedactedEvent(value) {
|
|
1695
|
-
const redacted = stringifyRedactedPayload(value);
|
|
1696
|
-
return redacted.length > 2e3 ? `${truncateUtf16Safe(redacted, 2e3)}…<truncated>` : redacted;
|
|
1697
|
-
}
|
|
1698
|
-
const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
|
|
1699
|
-
"error",
|
|
1700
|
-
"incomplete_details",
|
|
1701
|
-
"status_details",
|
|
1702
|
-
"failure_reason",
|
|
1703
|
-
"last_error",
|
|
1704
|
-
"provider_error",
|
|
1705
|
-
"error_details"
|
|
1706
|
-
];
|
|
1707
|
-
function readResponseFailedString(record, key) {
|
|
1708
|
-
return stringifyUnknown(record?.[key]);
|
|
1474
|
+
function suppressOpenAIResponsesCompaction(output, model, options, rejectedCheckpoint) {
|
|
1475
|
+
const context = buildOpenAIResponsesReplayContext(model, options);
|
|
1476
|
+
if (!context.baseUrlHash) return;
|
|
1477
|
+
output.providerReplay = {
|
|
1478
|
+
v: 1,
|
|
1479
|
+
type: OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE,
|
|
1480
|
+
data: OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA,
|
|
1481
|
+
...context,
|
|
1482
|
+
baseUrlHash: context.baseUrlHash
|
|
1483
|
+
};
|
|
1484
|
+
if (rejectedCheckpoint) options?.onCompactionRejected?.(rejectedCheckpoint);
|
|
1709
1485
|
}
|
|
1710
|
-
function
|
|
1711
|
-
const
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1486
|
+
function createCompactionTracker(output, model, options) {
|
|
1487
|
+
const replayIndexes = /* @__PURE__ */ new Map();
|
|
1488
|
+
return {
|
|
1489
|
+
added(item, replayIndex) {
|
|
1490
|
+
if (item.type === "compaction" && item.id) replayIndexes.set(item.id, replayIndex);
|
|
1491
|
+
},
|
|
1492
|
+
completed(item, fallbackReplayIndex) {
|
|
1493
|
+
if (item.type !== "compaction" || !item.encrypted_content) return;
|
|
1494
|
+
captureOpenAIResponsesCompaction(output, {
|
|
1495
|
+
type: "compaction",
|
|
1496
|
+
...item.id ? { id: item.id } : {},
|
|
1497
|
+
encrypted_content: item.encrypted_content
|
|
1498
|
+
}, (item.id ? replayIndexes.get(item.id) : void 0) ?? fallbackReplayIndex, model, options?.reasoningReplayMetadata);
|
|
1499
|
+
if (item.id) replayIndexes.delete(item.id);
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1715
1502
|
}
|
|
1716
|
-
function
|
|
1717
|
-
|
|
1718
|
-
return normalized === "requestid" || normalized === "xrequestid" || normalized === "providerrequestid" || normalized === "providerresponseid" || normalized === "litellmrequestid" || normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
|
|
1503
|
+
function isSafeResponsesReplayItemId(id) {
|
|
1504
|
+
return typeof id === "string" && id.length > 0 && id.length <= 64;
|
|
1719
1505
|
}
|
|
1720
|
-
function
|
|
1721
|
-
const
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
if (Array.isArray(value)) {
|
|
1730
|
-
for (const [index, item] of value.entries()) {
|
|
1731
|
-
if (index >= 8 || out.length >= 12) break;
|
|
1732
|
-
const itemString = typeof item === "string" || typeof item === "number" ? String(item).trim() : "";
|
|
1733
|
-
if (identifierKey && isResponseFailedIdentifierKey(identifierKey) && itemString) {
|
|
1734
|
-
out.push(`${path}[${index}]=${redactIdentifier(itemString, { len: 12 })}`);
|
|
1735
|
-
continue;
|
|
1736
|
-
}
|
|
1737
|
-
collectResponseFailedIdentifierHashes(item, {
|
|
1738
|
-
path: `${path}[${index}]`,
|
|
1739
|
-
depth: depth + 1,
|
|
1740
|
-
identifierKey,
|
|
1741
|
-
out,
|
|
1742
|
-
seen
|
|
1743
|
-
});
|
|
1506
|
+
function resolveNewestOpenAIResponsesCompactionReplay(messages, model, options) {
|
|
1507
|
+
const context = buildOpenAIResponsesReplayContext(model, options);
|
|
1508
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
1509
|
+
const message = messages[index];
|
|
1510
|
+
if (message?.role !== "assistant") continue;
|
|
1511
|
+
const replay = readOpenAIResponsesCompactionReplayState(message.providerReplay);
|
|
1512
|
+
if (replay?.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) {
|
|
1513
|
+
if (openAIResponsesReplayContextMatches(replay, context)) return;
|
|
1514
|
+
continue;
|
|
1744
1515
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
for (const [key, child] of Object.entries(value)) {
|
|
1748
|
-
if (out.length >= 12) break;
|
|
1749
|
-
const childPath = path ? `${path}.${key}` : key;
|
|
1750
|
-
const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
|
|
1751
|
-
if (isResponseFailedIdentifierKey(key) && childString) {
|
|
1752
|
-
out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
|
|
1516
|
+
if (replay?.type !== "openai-responses-compaction") {
|
|
1517
|
+
if (message.providerReplay?.type === "openai-responses-compaction") return;
|
|
1753
1518
|
continue;
|
|
1754
1519
|
}
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1520
|
+
if (!openAIResponsesReplayContextMatches(replay, context)) return;
|
|
1521
|
+
return {
|
|
1522
|
+
owner: message,
|
|
1523
|
+
item: {
|
|
1524
|
+
type: "compaction",
|
|
1525
|
+
...isSafeResponsesReplayItemId(replay.id) ? { id: replay.id } : {},
|
|
1526
|
+
encrypted_content: replay.data
|
|
1527
|
+
},
|
|
1528
|
+
replayIndex: replay.replayIndex ?? 0
|
|
1529
|
+
};
|
|
1762
1530
|
}
|
|
1763
|
-
return out;
|
|
1764
|
-
}
|
|
1765
|
-
function redactResponseFailedDiagnosticValue(value, opts = {}) {
|
|
1766
|
-
const key = opts.key ?? "";
|
|
1767
|
-
const depth = opts.depth ?? 0;
|
|
1768
|
-
if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
|
|
1769
|
-
if (depth > 6 || !value || typeof value !== "object") return value;
|
|
1770
|
-
const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
|
|
1771
|
-
if (seen.has(value)) return "<circular>";
|
|
1772
|
-
seen.add(value);
|
|
1773
|
-
if (Array.isArray(value)) return value.slice(0, 16).map((item) => redactResponseFailedDiagnosticValue(item, {
|
|
1774
|
-
key,
|
|
1775
|
-
depth: depth + 1,
|
|
1776
|
-
seen
|
|
1777
|
-
}));
|
|
1778
|
-
const out = {};
|
|
1779
|
-
for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
|
|
1780
|
-
key: childKey,
|
|
1781
|
-
depth: depth + 1,
|
|
1782
|
-
seen
|
|
1783
|
-
});
|
|
1784
|
-
return out;
|
|
1785
|
-
}
|
|
1786
|
-
function buildResponsesFailedFailureFields(response) {
|
|
1787
|
-
if (!response) return {};
|
|
1788
|
-
const fields = {};
|
|
1789
|
-
for (const key of RESPONSE_FAILED_FAILURE_FIELD_KEYS) if (response[key] !== void 0 && response[key] !== null) fields[key] = response[key];
|
|
1790
|
-
return fields;
|
|
1791
1531
|
}
|
|
1792
|
-
function
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
metadataKeys
|
|
1532
|
+
function buildOpenAIResponsesCompactionReplayPlan(messages, model, options) {
|
|
1533
|
+
if (options?.mode === "full-history") return {
|
|
1534
|
+
messages,
|
|
1535
|
+
preserveUnframedToolResults: false
|
|
1536
|
+
};
|
|
1537
|
+
const compaction = resolveNewestOpenAIResponsesCompactionReplay(messages, model, options);
|
|
1538
|
+
if (!compaction) return {
|
|
1539
|
+
messages,
|
|
1540
|
+
preserveUnframedToolResults: false
|
|
1802
1541
|
};
|
|
1542
|
+
const ownerIndex = messages.indexOf(compaction.owner);
|
|
1803
1543
|
return {
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
responseStatus: responsePreview.status,
|
|
1811
|
-
responseModel: responsePreview.model,
|
|
1812
|
-
responseObject: responsePreview.object,
|
|
1813
|
-
metadataKeys,
|
|
1814
|
-
requestIdHashes: collectResponseFailedIdentifierHashes(event),
|
|
1815
|
-
failureFieldsPreview: stringifyRedactedEvent(failureFields),
|
|
1816
|
-
responsePreview: stringifyRedactedEvent(responsePreview)
|
|
1544
|
+
messages: [{
|
|
1545
|
+
...compaction.owner,
|
|
1546
|
+
content: compaction.owner.content.slice(compaction.replayIndex)
|
|
1547
|
+
}, ...messages.slice(ownerIndex + 1)],
|
|
1548
|
+
compaction: compaction.item,
|
|
1549
|
+
preserveUnframedToolResults: true
|
|
1817
1550
|
};
|
|
1818
1551
|
}
|
|
1819
|
-
function
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
const response = isRecord(event.response) ? event.response : void 0;
|
|
1826
|
-
const responseId = readResponseFailedString(response, "id") || void 0;
|
|
1827
|
-
const error = isRecord(response?.error) ? response.error : void 0;
|
|
1828
|
-
if (error) {
|
|
1829
|
-
const code = readResponseFailedString(error, "code").trim();
|
|
1830
|
-
const message = readResponseFailedString(error, "message").trim();
|
|
1831
|
-
if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
|
|
1832
|
-
}
|
|
1833
|
-
const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
|
|
1834
|
-
if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
|
|
1835
|
-
return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
|
|
1836
|
-
}
|
|
1837
|
-
function logResponsesFailedNoDetails(observation) {
|
|
1838
|
-
log.warn(`[responses] response.failed missing error details provider=${observation.provider} api=${observation.api} model=${observation.transportModel} ` + summarizeResponsesFailedNoDetailsObservation(observation), observation);
|
|
1839
|
-
}
|
|
1840
|
-
function summarizeResponsesPayload(params) {
|
|
1841
|
-
if (!params || typeof params !== "object") return "payload=non-object";
|
|
1842
|
-
const record = params;
|
|
1843
|
-
const input = record.input;
|
|
1844
|
-
const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
|
|
1845
|
-
const text = record.text && typeof record.text === "object" ? record.text : void 0;
|
|
1846
|
-
const parts = [
|
|
1847
|
-
`fields=${Object.keys(record).toSorted().join(",")}`,
|
|
1848
|
-
`model=${safeDebugValue(record.model)}`,
|
|
1849
|
-
`stream=${safeDebugValue(record.stream)}`,
|
|
1850
|
-
`inputItems=${Array.isArray(input) ? input.length : typeof input}`,
|
|
1851
|
-
`inputRoles=${responseInputRoles(input) || "none"}`,
|
|
1852
|
-
`inputTextChars=${responseInputTextChars(input)}`,
|
|
1853
|
-
`tools=${summarizeResponsesTools(record.tools)}`,
|
|
1854
|
-
`reasoningEffort=${safeDebugValue(reasoning?.effort)}`,
|
|
1855
|
-
`reasoningSummary=${safeDebugValue(reasoning?.summary)}`,
|
|
1856
|
-
`textVerbosity=${safeDebugValue(text?.verbosity)}`,
|
|
1857
|
-
`serviceTier=${safeDebugValue(record.service_tier)}`,
|
|
1858
|
-
`store=${safeDebugValue(record.store)}`,
|
|
1859
|
-
`promptCacheKey=${record.prompt_cache_key === void 0 ? "absent" : "present"}`,
|
|
1860
|
-
`metadataKeys=${record.metadata && typeof record.metadata === "object" ? Object.keys(record.metadata).toSorted().join(",") : "none"}`
|
|
1861
|
-
];
|
|
1862
|
-
if (resolveModelPayloadDebugMode() === "full-redacted") parts.push(`payload=${stringifyRedactedPayload(record)}`);
|
|
1863
|
-
return parts.join(" ");
|
|
1864
|
-
}
|
|
1865
|
-
function summarizeOpenAITransportError(error) {
|
|
1866
|
-
if (!error || typeof error !== "object") return `type=${typeof error} message=${safeDebugValue(error)}`;
|
|
1867
|
-
const record = error;
|
|
1868
|
-
const cause = record.cause && typeof record.cause === "object" ? record.cause : void 0;
|
|
1869
|
-
return [
|
|
1870
|
-
`name=${safeDebugValue(record.name)}`,
|
|
1871
|
-
`status=${safeDebugValue(record.status)}`,
|
|
1872
|
-
`code=${safeDebugValue(record.code)}`,
|
|
1873
|
-
`type=${safeDebugValue(record.type)}`,
|
|
1874
|
-
`causeName=${safeDebugValue(cause?.name)}`,
|
|
1875
|
-
`causeCode=${safeDebugValue(cause?.code)}`,
|
|
1876
|
-
`message=${error instanceof Error ? error.message : safeDebugValue(error)}`
|
|
1877
|
-
].join(" ");
|
|
1552
|
+
function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
|
|
1553
|
+
return {
|
|
1554
|
+
v: 1,
|
|
1555
|
+
source: "openai-responses",
|
|
1556
|
+
...buildOpenAIResponsesReplayContext(model, options)
|
|
1557
|
+
};
|
|
1878
1558
|
}
|
|
1879
1559
|
//#endregion
|
|
1880
|
-
//#region packages/ai/src/transports/openai-responses-replay-internal.ts
|
|
1881
|
-
function
|
|
1882
|
-
if (!error || typeof error !== "object") return false;
|
|
1883
|
-
const record = error;
|
|
1884
|
-
if (record.code === "invalid_encrypted_content" || record.code === "thinking_signature_invalid") return true;
|
|
1885
|
-
const message = typeof record.message === "string" ? record.message : "";
|
|
1886
|
-
return message.includes("invalid_encrypted_content") || message.includes("thinking_signature_invalid") || record.status === 400 && message.toLowerCase().includes("could not decrypt the provided encrypted_content");
|
|
1887
|
-
}
|
|
1888
|
-
function stripEncryptedContentFields(value) {
|
|
1560
|
+
//#region packages/ai/src/transports/openai-responses-replay-messages-internal.ts
|
|
1561
|
+
function stripEncryptedReasoningContentFields(value) {
|
|
1889
1562
|
if (!value || typeof value !== "object") return {
|
|
1890
1563
|
value,
|
|
1891
1564
|
changed: false
|
|
@@ -1893,7 +1566,7 @@ function stripEncryptedContentFields(value) {
|
|
|
1893
1566
|
if (Array.isArray(value)) {
|
|
1894
1567
|
let changed = false;
|
|
1895
1568
|
const next = value.map((item) => {
|
|
1896
|
-
const stripped =
|
|
1569
|
+
const stripped = stripEncryptedReasoningContentFields(item);
|
|
1897
1570
|
changed ||= stripped.changed;
|
|
1898
1571
|
return stripped.value;
|
|
1899
1572
|
});
|
|
@@ -1905,14 +1578,19 @@ function stripEncryptedContentFields(value) {
|
|
|
1905
1578
|
changed: false
|
|
1906
1579
|
};
|
|
1907
1580
|
}
|
|
1581
|
+
const source = value;
|
|
1582
|
+
if (source.type === "compaction") return {
|
|
1583
|
+
value,
|
|
1584
|
+
changed: false
|
|
1585
|
+
};
|
|
1908
1586
|
let changed = false;
|
|
1909
1587
|
const next = {};
|
|
1910
|
-
for (const [key, child] of Object.entries(
|
|
1588
|
+
for (const [key, child] of Object.entries(source)) {
|
|
1911
1589
|
if (key === "encrypted_content") {
|
|
1912
1590
|
changed = true;
|
|
1913
1591
|
continue;
|
|
1914
1592
|
}
|
|
1915
|
-
const stripped =
|
|
1593
|
+
const stripped = stripEncryptedReasoningContentFields(child);
|
|
1916
1594
|
changed ||= stripped.changed;
|
|
1917
1595
|
next[key] = stripped.value;
|
|
1918
1596
|
}
|
|
@@ -1924,54 +1602,15 @@ function stripEncryptedContentFields(value) {
|
|
|
1924
1602
|
changed: false
|
|
1925
1603
|
};
|
|
1926
1604
|
}
|
|
1927
|
-
function stripResponsesRequestEncryptedContent(params) {
|
|
1928
|
-
const stripped = stripEncryptedContentFields(params.input);
|
|
1929
|
-
if (!stripped.changed) return params;
|
|
1930
|
-
return {
|
|
1931
|
-
...params,
|
|
1932
|
-
input: stripped.value
|
|
1933
|
-
};
|
|
1934
|
-
}
|
|
1935
|
-
function hashOptionalReplayContextValue(value) {
|
|
1936
|
-
const normalized = value?.trim();
|
|
1937
|
-
return normalized ? shortHash(normalized) : void 0;
|
|
1938
|
-
}
|
|
1939
|
-
function buildOpenAIResponsesReplayContext(model, options) {
|
|
1940
|
-
return {
|
|
1941
|
-
provider: model.provider,
|
|
1942
|
-
api: model.api,
|
|
1943
|
-
model: model.id,
|
|
1944
|
-
baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
|
|
1945
|
-
sessionHash: hashOptionalReplayContextValue(options?.sessionId),
|
|
1946
|
-
authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
|
|
1947
|
-
};
|
|
1948
|
-
}
|
|
1949
|
-
function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
|
|
1950
|
-
return {
|
|
1951
|
-
v: 1,
|
|
1952
|
-
source: "openai-responses",
|
|
1953
|
-
...buildOpenAIResponsesReplayContext(model, options)
|
|
1954
|
-
};
|
|
1955
|
-
}
|
|
1956
|
-
function tagOpenAIResponsesReasoningReplayItem(item, model, options) {
|
|
1957
|
-
if (!("encrypted_content" in item)) return item;
|
|
1958
|
-
return {
|
|
1959
|
-
...item,
|
|
1960
|
-
[OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: buildOpenAIResponsesReasoningReplayMetadata(model, options)
|
|
1961
|
-
};
|
|
1962
|
-
}
|
|
1963
1605
|
function isOpenAIResponsesReasoningReplayMetadata(value) {
|
|
1964
|
-
if (!value
|
|
1606
|
+
if (!isOpenAIResponsesReplayContext(value)) return false;
|
|
1965
1607
|
const record = value;
|
|
1966
|
-
return record.v === 1 && record.source === "openai-responses"
|
|
1967
|
-
}
|
|
1968
|
-
function encryptedReasoningReplayMetadataMatches(metadata, context) {
|
|
1969
|
-
if (!metadata) return false;
|
|
1970
|
-
return metadata.provider === context.provider && metadata.api === context.api && metadata.model === context.model && metadata.baseUrlHash === context.baseUrlHash && metadata.sessionHash === context.sessionHash && metadata.authProfileHash === context.authProfileHash;
|
|
1608
|
+
return record.v === 1 && record.source === "openai-responses";
|
|
1971
1609
|
}
|
|
1972
1610
|
function readOpenAIResponsesReasoningReplayBlockMetadata(block) {
|
|
1611
|
+
if (!Object.hasOwn(block, "openclawReasoningReplay")) return;
|
|
1973
1612
|
const value = block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY];
|
|
1974
|
-
return isOpenAIResponsesReasoningReplayMetadata(value) ? value :
|
|
1613
|
+
return isOpenAIResponsesReasoningReplayMetadata(value) ? value : null;
|
|
1975
1614
|
}
|
|
1976
1615
|
function normalizeOpenAIResponsesReasoningReplayItem(item) {
|
|
1977
1616
|
const record = item;
|
|
@@ -1981,49 +1620,20 @@ function normalizeOpenAIResponsesReasoningReplayItem(item) {
|
|
|
1981
1620
|
summary: []
|
|
1982
1621
|
};
|
|
1983
1622
|
}
|
|
1984
|
-
function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetadata) {
|
|
1985
|
-
const
|
|
1623
|
+
function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetadata, options) {
|
|
1624
|
+
const record = item;
|
|
1625
|
+
const hasRawMetadata = Object.hasOwn(record, OPENAI_RESPONSES_REASONING_REPLAY_META_KEY);
|
|
1626
|
+
const { [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: rawMetadata, ...rest } = record;
|
|
1986
1627
|
if (!("encrypted_content" in rest)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
|
|
1987
|
-
|
|
1988
|
-
return normalizeOpenAIResponsesReasoningReplayItem(
|
|
1989
|
-
|
|
1990
|
-
async function createResponsesStreamWithEncryptedContentRetry(params) {
|
|
1991
|
-
try {
|
|
1992
|
-
params.observePrompt?.(params.request, {
|
|
1993
|
-
egress: "responses-sdk",
|
|
1994
|
-
payloadVariant: "initial"
|
|
1995
|
-
});
|
|
1996
|
-
const { data, response } = await params.client.responses.create(params.request, params.requestOptions).withResponse();
|
|
1997
|
-
return {
|
|
1998
|
-
stream: data,
|
|
1999
|
-
response
|
|
2000
|
-
};
|
|
2001
|
-
} catch (error) {
|
|
2002
|
-
const retryRequest = stripResponsesRequestEncryptedContent(params.request);
|
|
2003
|
-
if (!isInvalidEncryptedContentError(error) || retryRequest === params.request) throw error;
|
|
2004
|
-
log.warn(`[responses] retrying without encrypted reasoning content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
|
|
2005
|
-
params.observePrompt?.(retryRequest, {
|
|
2006
|
-
egress: "responses-sdk",
|
|
2007
|
-
payloadVariant: "encrypted-content-retry"
|
|
2008
|
-
});
|
|
2009
|
-
const { data, response } = await params.client.responses.create(retryRequest, params.requestOptions).withResponse();
|
|
2010
|
-
return {
|
|
2011
|
-
stream: data,
|
|
2012
|
-
response
|
|
2013
|
-
};
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
function resolveAzureOpenAIApiVersion(env = process.env) {
|
|
2017
|
-
return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
|
|
1628
|
+
const metadata = blockMetadata !== void 0 ? blockMetadata ?? void 0 : isOpenAIResponsesReasoningReplayMetadata(rawMetadata) ? rawMetadata : void 0;
|
|
1629
|
+
if (blockMetadata === void 0 && !hasRawMetadata && options?.preserveUnattributedEncryptedContent === true || metadata && openAIResponsesReplayContextMatches(metadata, context)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
|
|
1630
|
+
return normalizeOpenAIResponsesReasoningReplayItem(stripEncryptedReasoningContentFields(rest).value);
|
|
2018
1631
|
}
|
|
2019
1632
|
function normalizeResponsesReplayItemId(id, prefix) {
|
|
2020
1633
|
if (!id) return;
|
|
2021
1634
|
if (id.length <= 64) return id;
|
|
2022
1635
|
return `${prefix}_${shortHash(id)}`;
|
|
2023
1636
|
}
|
|
2024
|
-
function isSafeResponsesReplayItemId(id) {
|
|
2025
|
-
return typeof id === "string" && id.length > 0 && id.length <= 64;
|
|
2026
|
-
}
|
|
2027
1637
|
function encodeTextSignatureV1(id, phase) {
|
|
2028
1638
|
return JSON.stringify({
|
|
2029
1639
|
v: 1,
|
|
@@ -2031,7 +1641,7 @@ function encodeTextSignatureV1(id, phase) {
|
|
|
2031
1641
|
...phase ? { phase } : {}
|
|
2032
1642
|
});
|
|
2033
1643
|
}
|
|
2034
|
-
function
|
|
1644
|
+
function parseOpenAIResponsesTextSignature(signature) {
|
|
2035
1645
|
if (!signature) return;
|
|
2036
1646
|
if (signature.startsWith("{")) try {
|
|
2037
1647
|
const parsed = JSON.parse(signature);
|
|
@@ -2054,8 +1664,34 @@ function buildResponsesInputMessage(role, content) {
|
|
|
2054
1664
|
content
|
|
2055
1665
|
};
|
|
2056
1666
|
}
|
|
2057
|
-
function
|
|
1667
|
+
function createOpenAIResponsesAssistantOutput(model, api = model.api) {
|
|
1668
|
+
return {
|
|
1669
|
+
role: "assistant",
|
|
1670
|
+
content: [],
|
|
1671
|
+
api,
|
|
1672
|
+
provider: model.provider,
|
|
1673
|
+
model: model.id,
|
|
1674
|
+
usage: {
|
|
1675
|
+
input: 0,
|
|
1676
|
+
output: 0,
|
|
1677
|
+
cacheRead: 0,
|
|
1678
|
+
cacheWrite: 0,
|
|
1679
|
+
totalTokens: 0,
|
|
1680
|
+
cost: {
|
|
1681
|
+
input: 0,
|
|
1682
|
+
output: 0,
|
|
1683
|
+
cacheRead: 0,
|
|
1684
|
+
cacheWrite: 0,
|
|
1685
|
+
total: 0
|
|
1686
|
+
}
|
|
1687
|
+
},
|
|
1688
|
+
stopReason: "stop",
|
|
1689
|
+
timestamp: Date.now()
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
function convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, conversionStyle) {
|
|
2058
1693
|
const messages = [];
|
|
1694
|
+
const providerStyle = conversionStyle === "provider";
|
|
2059
1695
|
const shouldReplayReasoningItems = options?.replayReasoningItems ?? true;
|
|
2060
1696
|
const shouldReplayResponsesItemIds = options?.replayResponsesItemIds ?? true;
|
|
2061
1697
|
const replayContext = buildOpenAIResponsesReplayContext(model, {
|
|
@@ -2063,7 +1699,10 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
|
|
|
2063
1699
|
authProfileId: options?.authProfileId
|
|
2064
1700
|
});
|
|
2065
1701
|
const shouldNormalizeSameModelToolCallIds = model.provider === "github-copilot";
|
|
2066
|
-
const sanitizeIdPart = (part) =>
|
|
1702
|
+
const sanitizeIdPart = (part) => {
|
|
1703
|
+
const sanitized = part.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1704
|
+
return providerStyle ? sanitized : sanitized.replace(/_+$/, "");
|
|
1705
|
+
};
|
|
2067
1706
|
const normalizeIdPart = (part) => {
|
|
2068
1707
|
const sanitized = sanitizeIdPart(part);
|
|
2069
1708
|
return (sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized).replace(/_+$/, "");
|
|
@@ -2084,15 +1723,24 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
|
|
|
2084
1723
|
const callId = id.slice(0, separatorIndex);
|
|
2085
1724
|
const itemId = id.slice(separatorIndex + 1);
|
|
2086
1725
|
const normalizedCallId = normalizeIdPart(callId);
|
|
2087
|
-
let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : model.provider === "github-copilot" ? buildSameProviderCopilotResponsesItemId(itemId) : normalizeIdPart(itemId);
|
|
1726
|
+
let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : model.provider === "github-copilot" ? providerStyle ? normalizeIdPart(itemId) : buildSameProviderCopilotResponsesItemId(itemId) : normalizeIdPart(itemId);
|
|
2088
1727
|
if (!normalizedItemId.startsWith("fc_")) normalizedItemId = normalizeIdPart(`fc_${normalizedItemId}`);
|
|
2089
1728
|
return `${normalizedCallId}|${normalizedItemId}`;
|
|
2090
1729
|
};
|
|
2091
|
-
const
|
|
2092
|
-
|
|
1730
|
+
const replayPlan = buildOpenAIResponsesCompactionReplayPlan(context.messages, model, {
|
|
1731
|
+
sessionId: options?.sessionId,
|
|
1732
|
+
authProfileId: options?.authProfileId,
|
|
1733
|
+
mode: options?.replayMode
|
|
1734
|
+
});
|
|
1735
|
+
const transformedMessages = providerStyle ? transformProviderMessages(replayPlan.messages, model, normalizeToolCallId) : transformTransportMessages(replayPlan.messages, model, normalizeToolCallId, {
|
|
1736
|
+
normalizeSameModelToolCallIds: shouldNormalizeSameModelToolCallIds,
|
|
1737
|
+
preserveUnframedToolResults: replayPlan.preserveUnframedToolResults
|
|
1738
|
+
});
|
|
1739
|
+
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && (providerStyle ? model.compat?.supportsDeveloperRole !== false : options?.supportsDeveloperRole !== false) ? "developer" : "system", [{
|
|
2093
1740
|
type: "input_text",
|
|
2094
1741
|
text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt))
|
|
2095
1742
|
}]));
|
|
1743
|
+
if (replayPlan.compaction) messages.push(replayPlan.compaction);
|
|
2096
1744
|
let msgIndex = 0;
|
|
2097
1745
|
for (const msg of transformedMessages) {
|
|
2098
1746
|
if (msg.role === "user") if (typeof msg.content === "string") messages.push(buildResponsesInputMessage("user", [{
|
|
@@ -2107,8 +1755,9 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
|
|
|
2107
1755
|
type: "input_image",
|
|
2108
1756
|
detail: "auto",
|
|
2109
1757
|
image_url: `data:${item.mimeType};base64,${item.data}`
|
|
2110
|
-
}).filter((item) => model.input.includes("image") || item.type !== "input_image");
|
|
1758
|
+
}).filter((item) => providerStyle || model.input.includes("image") || item.type !== "input_image");
|
|
2111
1759
|
if (content.length > 0) messages.push(buildResponsesInputMessage("user", content));
|
|
1760
|
+
else if (providerStyle) continue;
|
|
2112
1761
|
}
|
|
2113
1762
|
else if (msg.role === "assistant") {
|
|
2114
1763
|
const output = [];
|
|
@@ -2116,15 +1765,15 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
|
|
|
2116
1765
|
let previousReplayItemWasReasoning = false;
|
|
2117
1766
|
const isDifferentModel = msg.model !== model.id && msg.provider === model.provider && msg.api === model.api;
|
|
2118
1767
|
for (const block of msg.content) if (block.type === "thinking") {
|
|
2119
|
-
if (shouldReplayReasoningItems && block.thinkingSignature && block.thinkingSignature.startsWith("{")) {
|
|
2120
|
-
const replayableReasoningItem = prepareOpenAIResponsesReasoningItemForReplay(JSON.parse(block.thinkingSignature), replayContext, readOpenAIResponsesReasoningReplayBlockMetadata(block));
|
|
1768
|
+
if (shouldReplayReasoningItems && block.thinkingSignature && (providerStyle || block.thinkingSignature.startsWith("{"))) {
|
|
1769
|
+
const replayableReasoningItem = prepareOpenAIResponsesReasoningItemForReplay(JSON.parse(block.thinkingSignature), replayContext, readOpenAIResponsesReasoningReplayBlockMetadata(block), providerStyle ? { preserveUnattributedEncryptedContent: true } : void 0);
|
|
2121
1770
|
if (!shouldReplayResponsesItemIds) delete replayableReasoningItem.id;
|
|
2122
|
-
if (shouldReplayResponsesItemIds && model.provider === "github-copilot" && !isSafeResponsesReplayItemId(replayableReasoningItem.id)) continue;
|
|
1771
|
+
if (shouldReplayResponsesItemIds && !providerStyle && model.provider === "github-copilot" && !isSafeResponsesReplayItemId(replayableReasoningItem.id)) continue;
|
|
2123
1772
|
output.push(replayableReasoningItem);
|
|
2124
1773
|
previousReplayItemWasReasoning = true;
|
|
2125
1774
|
}
|
|
2126
1775
|
} else if (block.type === "text") {
|
|
2127
|
-
const textSignature =
|
|
1776
|
+
const textSignature = parseOpenAIResponsesTextSignature(block.textSignature);
|
|
2128
1777
|
let msgId = resolveReplayableResponsesMessageId({
|
|
2129
1778
|
replayResponsesItemIds: shouldReplayResponsesItemIds,
|
|
2130
1779
|
textSignatureId: textSignature?.id,
|
|
@@ -2158,11 +1807,12 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
|
|
|
2158
1807
|
...itemId ? { id: itemId } : {},
|
|
2159
1808
|
call_id: callId,
|
|
2160
1809
|
name: block.name,
|
|
2161
|
-
arguments: typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
|
|
1810
|
+
arguments: providerStyle ? JSON.stringify(block.arguments) : typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
|
|
2162
1811
|
});
|
|
2163
1812
|
previousReplayItemWasReasoning = false;
|
|
2164
1813
|
}
|
|
2165
1814
|
if (output.length > 0) messages.push(...output);
|
|
1815
|
+
else if (providerStyle) continue;
|
|
2166
1816
|
} else if (msg.role === "toolResult") {
|
|
2167
1817
|
const textResult = extractToolResultText(msg.content);
|
|
2168
1818
|
const sanitizedTextResult = sanitizeTransportPayloadText(textResult);
|
|
@@ -2191,6 +1841,119 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
|
|
|
2191
1841
|
}
|
|
2192
1842
|
return messages;
|
|
2193
1843
|
}
|
|
1844
|
+
function convertResponsesMessages$1(model, context, allowedToolCallProviders, options) {
|
|
1845
|
+
return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "transport");
|
|
1846
|
+
}
|
|
1847
|
+
function convertProviderResponsesMessages(model, context, allowedToolCallProviders, options) {
|
|
1848
|
+
return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "provider");
|
|
1849
|
+
}
|
|
1850
|
+
//#endregion
|
|
1851
|
+
//#region packages/ai/src/transports/openai-responses-replay-internal.ts
|
|
1852
|
+
function isInvalidEncryptedContentError(error) {
|
|
1853
|
+
if (!error || typeof error !== "object") return false;
|
|
1854
|
+
const record = error;
|
|
1855
|
+
if (record.code === "invalid_encrypted_content" || record.code === "thinking_signature_invalid") return true;
|
|
1856
|
+
const message = typeof record.message === "string" ? record.message : "";
|
|
1857
|
+
return message.includes("invalid_encrypted_content") || message.includes("thinking_signature_invalid") || record.status === 400 && message.toLowerCase().includes("could not decrypt the provided encrypted_content");
|
|
1858
|
+
}
|
|
1859
|
+
function isOrphanedFunctionCallOutputError(error) {
|
|
1860
|
+
if (!error || typeof error !== "object") return false;
|
|
1861
|
+
const record = error;
|
|
1862
|
+
const message = typeof record.message === "string" ? record.message : "";
|
|
1863
|
+
return /No tool call found for function call output with call_id [A-Za-z0-9_-]+/.test(message);
|
|
1864
|
+
}
|
|
1865
|
+
function commitResponsesEncryptedContentAttempt(attempt, commit) {
|
|
1866
|
+
if (attempt.kind === "compaction-stripped") commit(attempt.rejectedCompaction);
|
|
1867
|
+
}
|
|
1868
|
+
function stripResponsesRequestEncryptedReasoning(request) {
|
|
1869
|
+
const stripped = stripEncryptedReasoningContentFields(request.input);
|
|
1870
|
+
if (!stripped.changed) return request;
|
|
1871
|
+
return {
|
|
1872
|
+
...request,
|
|
1873
|
+
input: stripped.value
|
|
1874
|
+
};
|
|
1875
|
+
}
|
|
1876
|
+
function stripResponsesRequestCompaction(request) {
|
|
1877
|
+
if (!Array.isArray(request.input)) return request;
|
|
1878
|
+
const input = request.input.filter((item) => !(item !== null && typeof item === "object" && item.type === "compaction"));
|
|
1879
|
+
return input.length === request.input.length ? request : {
|
|
1880
|
+
...request,
|
|
1881
|
+
input
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
function readOpenAIResponsesCompactionRejection(request) {
|
|
1885
|
+
if (!Array.isArray(request.input)) return;
|
|
1886
|
+
const item = request.input.find((candidate) => candidate !== null && typeof candidate === "object" && candidate.type === "compaction" && typeof candidate.encrypted_content === "string");
|
|
1887
|
+
return item ? {
|
|
1888
|
+
data: item.encrypted_content,
|
|
1889
|
+
...typeof item.id === "string" ? { id: item.id } : {}
|
|
1890
|
+
} : void 0;
|
|
1891
|
+
}
|
|
1892
|
+
async function resolveNextResponsesEncryptedContentAttempt(attempt, error, options) {
|
|
1893
|
+
const orphanedFunctionOutput = isOrphanedFunctionCallOutputError(error);
|
|
1894
|
+
if (!isInvalidEncryptedContentError(error) && !orphanedFunctionOutput || attempt.kind === "compaction-stripped") return;
|
|
1895
|
+
if (!orphanedFunctionOutput && (attempt.kind === "initial" || attempt.kind === "continuation-rejected")) {
|
|
1896
|
+
const reasoningStripped = stripResponsesRequestEncryptedReasoning(attempt.request);
|
|
1897
|
+
if (reasoningStripped !== attempt.request) return {
|
|
1898
|
+
kind: "reasoning-stripped",
|
|
1899
|
+
request: reasoningStripped
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
const locallyStripped = stripResponsesRequestCompaction(attempt.request);
|
|
1903
|
+
if (locallyStripped === attempt.request) return;
|
|
1904
|
+
let compactionStripped = options?.buildFullHistoryRequest ? await options.buildFullHistoryRequest() : locallyStripped;
|
|
1905
|
+
compactionStripped = stripResponsesRequestCompaction(compactionStripped);
|
|
1906
|
+
if (attempt.kind === "reasoning-stripped") compactionStripped = stripResponsesRequestEncryptedReasoning(compactionStripped);
|
|
1907
|
+
return {
|
|
1908
|
+
kind: "compaction-stripped",
|
|
1909
|
+
request: compactionStripped,
|
|
1910
|
+
rejectedCompaction: readOpenAIResponsesCompactionRejection(attempt.request)
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
async function createResponsesStreamWithEncryptedContentRetry(params) {
|
|
1914
|
+
const sendAttempt = async (attempt) => {
|
|
1915
|
+
const { data, response } = await params.client.responses.create(attempt.request, params.requestOptions).withResponse();
|
|
1916
|
+
commitResponsesEncryptedContentAttempt(attempt, (checkpoint) => {
|
|
1917
|
+
if (checkpoint) params.onCompactionRejected?.(checkpoint);
|
|
1918
|
+
});
|
|
1919
|
+
return {
|
|
1920
|
+
stream: data,
|
|
1921
|
+
response,
|
|
1922
|
+
attempt
|
|
1923
|
+
};
|
|
1924
|
+
};
|
|
1925
|
+
let attempt = {
|
|
1926
|
+
kind: params.initialAttemptKind ?? "initial",
|
|
1927
|
+
request: params.request,
|
|
1928
|
+
...params.initialRejectedCompaction ? { rejectedCompaction: params.initialRejectedCompaction } : {}
|
|
1929
|
+
};
|
|
1930
|
+
while (true) {
|
|
1931
|
+
params.observePrompt?.(attempt.request, {
|
|
1932
|
+
egress: "responses-sdk",
|
|
1933
|
+
payloadVariant: attempt.kind
|
|
1934
|
+
});
|
|
1935
|
+
try {
|
|
1936
|
+
return await sendAttempt(attempt);
|
|
1937
|
+
} catch (error) {
|
|
1938
|
+
let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
|
|
1939
|
+
if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && error.code === "previous_response_not_found") {
|
|
1940
|
+
const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
|
|
1941
|
+
delete request.previous_response_id;
|
|
1942
|
+
nextAttempt = {
|
|
1943
|
+
kind: "continuation-rejected",
|
|
1944
|
+
request
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
if (!nextAttempt) throw error;
|
|
1948
|
+
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";
|
|
1949
|
+
log.warn(`[responses] retrying ${retryDescription} provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
|
|
1950
|
+
attempt = nextAttempt;
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
function resolveAzureOpenAIApiVersion(env = process.env) {
|
|
1955
|
+
return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
|
|
1956
|
+
}
|
|
2194
1957
|
//#endregion
|
|
2195
1958
|
//#region packages/ai/src/providers/openai-responses-stream-compat.ts
|
|
2196
1959
|
const OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE = "output_text";
|
|
@@ -2220,19 +1983,16 @@ function resolveResponsesMessageSnapshotCollapse(params) {
|
|
|
2220
1983
|
}
|
|
2221
1984
|
//#endregion
|
|
2222
1985
|
//#region packages/ai/src/providers/openai-responses-tool-call-tracker.ts
|
|
2223
|
-
function readIdentityValue(value) {
|
|
2224
|
-
return (typeof value === "string" ? value.trim() : "") || void 0;
|
|
2225
|
-
}
|
|
2226
1986
|
function readOutputIndex(event) {
|
|
2227
1987
|
return typeof event.output_index === "number" && Number.isInteger(event.output_index) && event.output_index >= 0 ? event.output_index : void 0;
|
|
2228
1988
|
}
|
|
2229
1989
|
function readEventIdentity(event) {
|
|
2230
|
-
return { itemId:
|
|
1990
|
+
return { itemId: normalizeOptionalString(event.item_id) };
|
|
2231
1991
|
}
|
|
2232
1992
|
function readResponsesToolCallItemIdentity(item) {
|
|
2233
1993
|
return {
|
|
2234
|
-
itemId:
|
|
2235
|
-
callId:
|
|
1994
|
+
itemId: normalizeOptionalString(item.id),
|
|
1995
|
+
callId: normalizeOptionalString(item.call_id)
|
|
2236
1996
|
};
|
|
2237
1997
|
}
|
|
2238
1998
|
function createResponsesToolCallTracker() {
|
|
@@ -2295,6 +2055,308 @@ function createResponsesToolCallTracker() {
|
|
|
2295
2055
|
};
|
|
2296
2056
|
}
|
|
2297
2057
|
//#endregion
|
|
2058
|
+
//#region packages/ai/src/transports/openai-responses-debug.ts
|
|
2059
|
+
function stringifyUnknown(value, fallback = "") {
|
|
2060
|
+
if (typeof value === "string") return value;
|
|
2061
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
2062
|
+
return fallback;
|
|
2063
|
+
}
|
|
2064
|
+
function safeDebugValue(value) {
|
|
2065
|
+
if (typeof value === "string") return value;
|
|
2066
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
2067
|
+
if (value === null) return "null";
|
|
2068
|
+
if (value === void 0) return "undefined";
|
|
2069
|
+
return Array.isArray(value) ? "array" : typeof value;
|
|
2070
|
+
}
|
|
2071
|
+
function responseInputTextChars(input) {
|
|
2072
|
+
if (typeof input === "string") return input.length;
|
|
2073
|
+
if (Array.isArray(input)) return input.reduce((total, item) => total + responseInputTextChars(item), 0);
|
|
2074
|
+
if (!input || typeof input !== "object") return 0;
|
|
2075
|
+
const record = input;
|
|
2076
|
+
let total = 0;
|
|
2077
|
+
if (typeof record.text === "string") total += record.text.length;
|
|
2078
|
+
if (typeof record.content === "string") total += record.content.length;
|
|
2079
|
+
else if (Array.isArray(record.content)) total += responseInputTextChars(record.content);
|
|
2080
|
+
return total;
|
|
2081
|
+
}
|
|
2082
|
+
function responseInputRoles(input) {
|
|
2083
|
+
if (!Array.isArray(input)) return "";
|
|
2084
|
+
const roles = /* @__PURE__ */ new Set();
|
|
2085
|
+
for (const item of input) if (item && typeof item === "object") {
|
|
2086
|
+
const role = item.role;
|
|
2087
|
+
if (typeof role === "string" && role.trim()) roles.add(role.trim());
|
|
2088
|
+
}
|
|
2089
|
+
return [...roles].toSorted().join(",");
|
|
2090
|
+
}
|
|
2091
|
+
function responseInputItemShape(input) {
|
|
2092
|
+
if (!Array.isArray(input)) return "none";
|
|
2093
|
+
return input.map((item) => {
|
|
2094
|
+
if (!isRecord(item) || typeof item.type !== "string") return "unknown";
|
|
2095
|
+
if (item.type === "message" && typeof item.role === "string") return `message:${item.role}`;
|
|
2096
|
+
return item.type;
|
|
2097
|
+
}).join(",") || "none";
|
|
2098
|
+
}
|
|
2099
|
+
function hashOpaqueResponsesValue(value) {
|
|
2100
|
+
return createHash("sha256").update(value).digest("hex");
|
|
2101
|
+
}
|
|
2102
|
+
function summarizeResponsesCompactionItems(input) {
|
|
2103
|
+
if (!Array.isArray(input)) return [
|
|
2104
|
+
"compactionItems=0",
|
|
2105
|
+
"compactionIdHashes=none",
|
|
2106
|
+
"compactionPayloadHashes=none",
|
|
2107
|
+
"compactionInputIndexes=none"
|
|
2108
|
+
];
|
|
2109
|
+
const compactions = input.flatMap((item, inputIndex) => {
|
|
2110
|
+
if (!isRecord(item) || item.type !== "compaction") return [];
|
|
2111
|
+
return [{
|
|
2112
|
+
idHash: typeof item.id === "string" ? hashOpaqueResponsesValue(item.id) : void 0,
|
|
2113
|
+
inputIndex,
|
|
2114
|
+
payloadHash: typeof item.encrypted_content === "string" ? hashOpaqueResponsesValue(item.encrypted_content) : void 0
|
|
2115
|
+
}];
|
|
2116
|
+
});
|
|
2117
|
+
return [
|
|
2118
|
+
`compactionItems=${compactions.length}`,
|
|
2119
|
+
`compactionIdHashes=${compactions.flatMap((item) => item.idHash ?? []).join(",") || "none"}`,
|
|
2120
|
+
`compactionPayloadHashes=${compactions.flatMap((item) => item.payloadHash ?? []).join(",") || "none"}`,
|
|
2121
|
+
`compactionInputIndexes=${compactions.map((item) => item.inputIndex).join(",") || "none"}`
|
|
2122
|
+
];
|
|
2123
|
+
}
|
|
2124
|
+
function readToolPayloadField(record, field) {
|
|
2125
|
+
try {
|
|
2126
|
+
return record[field];
|
|
2127
|
+
} catch {
|
|
2128
|
+
return;
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
function readResponsesToolDisplayName(tool) {
|
|
2132
|
+
if (!tool || typeof tool !== "object") return "";
|
|
2133
|
+
const record = tool;
|
|
2134
|
+
const name = readToolPayloadField(record, "name");
|
|
2135
|
+
if (typeof name === "string") return name;
|
|
2136
|
+
const fn = readToolPayloadField(record, "function");
|
|
2137
|
+
if (fn && typeof fn === "object") {
|
|
2138
|
+
const fnName = readToolPayloadField(fn, "name");
|
|
2139
|
+
if (typeof fnName === "string") return fnName;
|
|
2140
|
+
}
|
|
2141
|
+
const type = readToolPayloadField(record, "type");
|
|
2142
|
+
return typeof type === "string" && type !== "function" ? type : "";
|
|
2143
|
+
}
|
|
2144
|
+
function summarizeResponsesTools(tools) {
|
|
2145
|
+
if (!Array.isArray(tools)) return "count=0";
|
|
2146
|
+
const names = tools.map(readResponsesToolDisplayName).filter(Boolean);
|
|
2147
|
+
const mode = resolveModelPayloadDebugMode();
|
|
2148
|
+
const maxNames = mode === "tools" || mode === "full-redacted" ? names.length : 12;
|
|
2149
|
+
const label = maxNames >= names.length ? "names" : "sample";
|
|
2150
|
+
const shown = names.slice(0, maxNames).join(",");
|
|
2151
|
+
return `count=${tools.length}${shown ? ` ${label}=${shown}` : ""}`;
|
|
2152
|
+
}
|
|
2153
|
+
function stringifyRedactedPayload(value) {
|
|
2154
|
+
try {
|
|
2155
|
+
const encoded = JSON.stringify(value, (key, child) => key === "encrypted_content" ? "<opaque data omitted>" : child);
|
|
2156
|
+
if (!encoded) return "<empty>";
|
|
2157
|
+
const redacted = redactSensitiveText(encoded, { mode: "tools" });
|
|
2158
|
+
return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
|
|
2159
|
+
} catch {
|
|
2160
|
+
return "<unserializable>";
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
function stringifyRedactedEvent(value) {
|
|
2164
|
+
const redacted = stringifyRedactedPayload(value);
|
|
2165
|
+
return redacted.length > 2e3 ? `${truncateUtf16Safe(redacted, 2e3)}…<truncated>` : redacted;
|
|
2166
|
+
}
|
|
2167
|
+
const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
|
|
2168
|
+
"error",
|
|
2169
|
+
"incomplete_details",
|
|
2170
|
+
"status_details",
|
|
2171
|
+
"failure_reason",
|
|
2172
|
+
"last_error",
|
|
2173
|
+
"provider_error",
|
|
2174
|
+
"error_details"
|
|
2175
|
+
];
|
|
2176
|
+
function readResponseFailedString(record, key) {
|
|
2177
|
+
return stringifyUnknown(record?.[key]);
|
|
2178
|
+
}
|
|
2179
|
+
function buildResponsesFailedEventSummary(message, responseId, observation) {
|
|
2180
|
+
const summary = { message };
|
|
2181
|
+
if (responseId) summary.responseId = responseId;
|
|
2182
|
+
if (observation) summary.observation = observation;
|
|
2183
|
+
return summary;
|
|
2184
|
+
}
|
|
2185
|
+
function isResponseFailedIdentifierKey(key) {
|
|
2186
|
+
const normalized = key.replace(/[-_\s]/g, "").toLowerCase();
|
|
2187
|
+
return normalized === "requestid" || normalized === "xrequestid" || normalized === "providerrequestid" || normalized === "providerresponseid" || normalized === "litellmrequestid" || normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
|
|
2188
|
+
}
|
|
2189
|
+
function collectResponseFailedIdentifierHashes(value, opts = {}) {
|
|
2190
|
+
const path = opts.path ?? "";
|
|
2191
|
+
const depth = opts.depth ?? 0;
|
|
2192
|
+
const identifierKey = opts.identifierKey ?? "";
|
|
2193
|
+
const out = opts.out ?? [];
|
|
2194
|
+
const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
|
|
2195
|
+
if (out.length >= 12 || depth > 4 || !value || typeof value !== "object") return out;
|
|
2196
|
+
if (seen.has(value)) return out;
|
|
2197
|
+
seen.add(value);
|
|
2198
|
+
if (Array.isArray(value)) {
|
|
2199
|
+
for (const [index, item] of value.entries()) {
|
|
2200
|
+
if (index >= 8 || out.length >= 12) break;
|
|
2201
|
+
const itemString = typeof item === "string" || typeof item === "number" ? String(item).trim() : "";
|
|
2202
|
+
if (identifierKey && isResponseFailedIdentifierKey(identifierKey) && itemString) {
|
|
2203
|
+
out.push(`${path}[${index}]=${redactIdentifier(itemString, { len: 12 })}`);
|
|
2204
|
+
continue;
|
|
2205
|
+
}
|
|
2206
|
+
collectResponseFailedIdentifierHashes(item, {
|
|
2207
|
+
path: `${path}[${index}]`,
|
|
2208
|
+
depth: depth + 1,
|
|
2209
|
+
identifierKey,
|
|
2210
|
+
out,
|
|
2211
|
+
seen
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
2214
|
+
return out;
|
|
2215
|
+
}
|
|
2216
|
+
for (const [key, child] of Object.entries(value)) {
|
|
2217
|
+
if (out.length >= 12) break;
|
|
2218
|
+
const childPath = path ? `${path}.${key}` : key;
|
|
2219
|
+
const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
|
|
2220
|
+
if (isResponseFailedIdentifierKey(key) && childString) {
|
|
2221
|
+
out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
|
|
2222
|
+
continue;
|
|
2223
|
+
}
|
|
2224
|
+
collectResponseFailedIdentifierHashes(child, {
|
|
2225
|
+
path: childPath,
|
|
2226
|
+
depth: depth + 1,
|
|
2227
|
+
identifierKey: isResponseFailedIdentifierKey(key) ? key : void 0,
|
|
2228
|
+
out,
|
|
2229
|
+
seen
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
return out;
|
|
2233
|
+
}
|
|
2234
|
+
function redactResponseFailedDiagnosticValue(value, opts = {}) {
|
|
2235
|
+
const key = opts.key ?? "";
|
|
2236
|
+
const depth = opts.depth ?? 0;
|
|
2237
|
+
if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
|
|
2238
|
+
if (depth > 6 || !value || typeof value !== "object") return value;
|
|
2239
|
+
const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
|
|
2240
|
+
if (seen.has(value)) return "<circular>";
|
|
2241
|
+
seen.add(value);
|
|
2242
|
+
if (Array.isArray(value)) return value.slice(0, 16).map((item) => redactResponseFailedDiagnosticValue(item, {
|
|
2243
|
+
key,
|
|
2244
|
+
depth: depth + 1,
|
|
2245
|
+
seen
|
|
2246
|
+
}));
|
|
2247
|
+
const out = {};
|
|
2248
|
+
for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
|
|
2249
|
+
key: childKey,
|
|
2250
|
+
depth: depth + 1,
|
|
2251
|
+
seen
|
|
2252
|
+
});
|
|
2253
|
+
return out;
|
|
2254
|
+
}
|
|
2255
|
+
function buildResponsesFailedFailureFields(response) {
|
|
2256
|
+
if (!response) return {};
|
|
2257
|
+
const fields = {};
|
|
2258
|
+
for (const key of RESPONSE_FAILED_FAILURE_FIELD_KEYS) if (response[key] !== void 0 && response[key] !== null) fields[key] = response[key];
|
|
2259
|
+
return fields;
|
|
2260
|
+
}
|
|
2261
|
+
function buildResponsesFailedNoDetailsObservation(event, model, response = isRecord(event.response) ? event.response : void 0) {
|
|
2262
|
+
const failureFields = redactResponseFailedDiagnosticValue(buildResponsesFailedFailureFields(response));
|
|
2263
|
+
const metadataKeys = isRecord(response?.metadata) ? Object.keys(response.metadata).toSorted() : [];
|
|
2264
|
+
const responsePreview = {
|
|
2265
|
+
id: readResponseFailedString(response, "id"),
|
|
2266
|
+
status: readResponseFailedString(response, "status"),
|
|
2267
|
+
model: readResponseFailedString(response, "model"),
|
|
2268
|
+
object: readResponseFailedString(response, "object"),
|
|
2269
|
+
failureFields,
|
|
2270
|
+
metadataKeys
|
|
2271
|
+
};
|
|
2272
|
+
return {
|
|
2273
|
+
event: "openai_responses_response_failed_without_details",
|
|
2274
|
+
provider: model.provider,
|
|
2275
|
+
api: model.api,
|
|
2276
|
+
transportModel: model.id,
|
|
2277
|
+
providerRuntimeFailureKind: "no_error_details",
|
|
2278
|
+
responseId: responsePreview.id,
|
|
2279
|
+
responseStatus: responsePreview.status,
|
|
2280
|
+
responseModel: responsePreview.model,
|
|
2281
|
+
responseObject: responsePreview.object,
|
|
2282
|
+
metadataKeys,
|
|
2283
|
+
requestIdHashes: collectResponseFailedIdentifierHashes(event),
|
|
2284
|
+
failureFieldsPreview: stringifyRedactedEvent(failureFields),
|
|
2285
|
+
responsePreview: stringifyRedactedEvent(responsePreview)
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
function summarizeResponsesFailedNoDetailsObservation(observation) {
|
|
2289
|
+
const requestIds = observation.requestIdHashes.join(",");
|
|
2290
|
+
const metadataKeys = observation.metadataKeys.join(",");
|
|
2291
|
+
return `responseId=${safeDebugValue(observation.responseId || void 0)} responseStatus=${safeDebugValue(observation.responseStatus || void 0)} responseModel=${safeDebugValue(observation.responseModel || void 0)} requestIds=${requestIds || "none"} metadataKeys=${metadataKeys || "none"} failureFields=${observation.failureFieldsPreview}`;
|
|
2292
|
+
}
|
|
2293
|
+
function normalizeResponsesFailedEvent(event, model) {
|
|
2294
|
+
const response = isRecord(event.response) ? event.response : void 0;
|
|
2295
|
+
const responseId = readResponseFailedString(response, "id") || void 0;
|
|
2296
|
+
const error = isRecord(response?.error) ? response.error : void 0;
|
|
2297
|
+
if (error) {
|
|
2298
|
+
const code = readResponseFailedString(error, "code").trim();
|
|
2299
|
+
const message = readResponseFailedString(error, "message").trim();
|
|
2300
|
+
if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
|
|
2301
|
+
}
|
|
2302
|
+
const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
|
|
2303
|
+
if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
|
|
2304
|
+
return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
|
|
2305
|
+
}
|
|
2306
|
+
var ResponsesStreamFailure = class extends Error {
|
|
2307
|
+
constructor(failure, response) {
|
|
2308
|
+
super(failure.message);
|
|
2309
|
+
this.name = "ResponsesStreamFailure";
|
|
2310
|
+
this.responseId = failure.responseId;
|
|
2311
|
+
this.response = response;
|
|
2312
|
+
this.observation = failure.observation;
|
|
2313
|
+
}
|
|
2314
|
+
};
|
|
2315
|
+
function logResponsesFailedNoDetails(observation) {
|
|
2316
|
+
log.warn(`[responses] response.failed missing error details provider=${observation.provider} api=${observation.api} model=${observation.transportModel} ` + summarizeResponsesFailedNoDetailsObservation(observation), observation);
|
|
2317
|
+
}
|
|
2318
|
+
function summarizeResponsesPayload(params) {
|
|
2319
|
+
if (!params || typeof params !== "object") return "payload=non-object";
|
|
2320
|
+
const record = params;
|
|
2321
|
+
const input = record.input;
|
|
2322
|
+
const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
|
|
2323
|
+
const text = record.text && typeof record.text === "object" ? record.text : void 0;
|
|
2324
|
+
const parts = [
|
|
2325
|
+
`fields=${Object.keys(record).toSorted().join(",")}`,
|
|
2326
|
+
`model=${safeDebugValue(record.model)}`,
|
|
2327
|
+
`stream=${safeDebugValue(record.stream)}`,
|
|
2328
|
+
`inputItems=${Array.isArray(input) ? input.length : typeof input}`,
|
|
2329
|
+
`inputItemShape=${responseInputItemShape(input)}`,
|
|
2330
|
+
`inputRoles=${responseInputRoles(input) || "none"}`,
|
|
2331
|
+
`inputTextChars=${responseInputTextChars(input)}`,
|
|
2332
|
+
`tools=${summarizeResponsesTools(record.tools)}`,
|
|
2333
|
+
`reasoningEffort=${safeDebugValue(reasoning?.effort)}`,
|
|
2334
|
+
`reasoningSummary=${safeDebugValue(reasoning?.summary)}`,
|
|
2335
|
+
`textVerbosity=${safeDebugValue(text?.verbosity)}`,
|
|
2336
|
+
`serviceTier=${safeDebugValue(record.service_tier)}`,
|
|
2337
|
+
...summarizeResponsesCompactionItems(input),
|
|
2338
|
+
`store=${safeDebugValue(record.store)}`,
|
|
2339
|
+
`promptCacheKey=${record.prompt_cache_key === void 0 ? "absent" : "present"}`,
|
|
2340
|
+
`metadataKeys=${record.metadata && typeof record.metadata === "object" ? Object.keys(record.metadata).toSorted().join(",") : "none"}`
|
|
2341
|
+
];
|
|
2342
|
+
if (resolveModelPayloadDebugMode() === "full-redacted") parts.push(`payload=${stringifyRedactedPayload(record)}`);
|
|
2343
|
+
return parts.join(" ");
|
|
2344
|
+
}
|
|
2345
|
+
function summarizeOpenAITransportError(error) {
|
|
2346
|
+
if (!error || typeof error !== "object") return `type=${typeof error} message=${safeDebugValue(error)}`;
|
|
2347
|
+
const record = error;
|
|
2348
|
+
const cause = record.cause && typeof record.cause === "object" ? record.cause : void 0;
|
|
2349
|
+
return [
|
|
2350
|
+
`name=${safeDebugValue(record.name)}`,
|
|
2351
|
+
`status=${safeDebugValue(record.status)}`,
|
|
2352
|
+
`code=${safeDebugValue(record.code)}`,
|
|
2353
|
+
`type=${safeDebugValue(record.type)}`,
|
|
2354
|
+
`causeName=${safeDebugValue(cause?.name)}`,
|
|
2355
|
+
`causeCode=${safeDebugValue(cause?.code)}`,
|
|
2356
|
+
`message=${error instanceof Error ? error.message : safeDebugValue(error)}`
|
|
2357
|
+
].join(" ");
|
|
2358
|
+
}
|
|
2359
|
+
//#endregion
|
|
2298
2360
|
//#region packages/ai/src/transports/openai-responses-stream-observer-internal.ts
|
|
2299
2361
|
const STRING_DELTA_EVENTS = /* @__PURE__ */ new Set([
|
|
2300
2362
|
"response.function_call_arguments.delta",
|
|
@@ -2316,7 +2378,7 @@ async function* adaptResponsesStream(stream, signal) {
|
|
|
2316
2378
|
await scheduler.afterEvent();
|
|
2317
2379
|
}
|
|
2318
2380
|
}
|
|
2319
|
-
async function* observeResponsesStream(stream, model) {
|
|
2381
|
+
async function* observeResponsesStream(stream, model, requestStartedAt) {
|
|
2320
2382
|
const startedAt = Date.now();
|
|
2321
2383
|
const eventTypes = /* @__PURE__ */ new Map();
|
|
2322
2384
|
const debugMode = resolveModelSseDebugMode();
|
|
@@ -2326,7 +2388,7 @@ async function* observeResponsesStream(stream, model) {
|
|
|
2326
2388
|
const type = isRecord(event) && typeof event.type === "string" ? event.type : "unknown";
|
|
2327
2389
|
eventCount += 1;
|
|
2328
2390
|
eventTypes.set(type, (eventTypes.get(type) ?? 0) + 1);
|
|
2329
|
-
if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - startedAt} type=${type}`);
|
|
2391
|
+
if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - (requestStartedAt ?? startedAt)} headersToEventMs=${Date.now() - startedAt} type=${type}`);
|
|
2330
2392
|
if (debugMode === "peek" && eventCount <= 5) emitModelTransportDebug(log, `[responses] event_peek provider=${model.provider} api=${model.api} model=${model.id} index=${eventCount} type=${type} event=${stringifyRedactedEvent(event)}`);
|
|
2331
2393
|
yield event;
|
|
2332
2394
|
}
|
|
@@ -2337,6 +2399,23 @@ async function* observeResponsesStream(stream, model) {
|
|
|
2337
2399
|
}
|
|
2338
2400
|
//#endregion
|
|
2339
2401
|
//#region packages/ai/src/transports/openai-responses-stream-slots-internal.ts
|
|
2402
|
+
function createResponsesOutputContentIndex() {
|
|
2403
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
2404
|
+
const identity = (item) => {
|
|
2405
|
+
if ((item.type === "reasoning" || item.type === "message") && item.id) return `${item.type}:${item.id}`;
|
|
2406
|
+
return item.type === "function_call" ? `function_call:${item.call_id ?? item.id ?? ""}` : void 0;
|
|
2407
|
+
};
|
|
2408
|
+
return {
|
|
2409
|
+
get(item) {
|
|
2410
|
+
const key = identity(item);
|
|
2411
|
+
return key === void 0 ? void 0 : indexes.get(key);
|
|
2412
|
+
},
|
|
2413
|
+
set(item, contentIndex) {
|
|
2414
|
+
const key = identity(item);
|
|
2415
|
+
if (key !== void 0) indexes.set(key, contentIndex);
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
}
|
|
2340
2419
|
function appendResponsesPendingTextDelta(slot, delta, materialize) {
|
|
2341
2420
|
slot.pendingText = `${slot.pendingText ?? ""}${delta}`;
|
|
2342
2421
|
const priorText = slot.collapseCandidate?.block.text ?? "";
|
|
@@ -2385,6 +2464,14 @@ function createResponsesOutputSlotTracker() {
|
|
|
2385
2464
|
}
|
|
2386
2465
|
//#endregion
|
|
2387
2466
|
//#region packages/ai/src/providers/openai-responses-terminal-usage.ts
|
|
2467
|
+
/**
|
|
2468
|
+
* Canonical mapping for terminal OpenAI Responses events.
|
|
2469
|
+
*
|
|
2470
|
+
* `response.completed`, `response.incomplete`, and `response.failed` are terminal and can carry
|
|
2471
|
+
* usage, so every Responses path finalizes through the helpers here. Keeping one owner prevents
|
|
2472
|
+
* package and managed transports from drifting on token buckets, service-tier pricing, or future
|
|
2473
|
+
* terminal-event semantics.
|
|
2474
|
+
*/
|
|
2388
2475
|
function readCount(value) {
|
|
2389
2476
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
2390
2477
|
}
|
|
@@ -2414,8 +2501,7 @@ function mapResponsesTerminalUsage(usage) {
|
|
|
2414
2501
|
}
|
|
2415
2502
|
/** Reasoning tokens are reported by the agent path only; the package path does not track them. */
|
|
2416
2503
|
function readResponsesReasoningTokens(usage) {
|
|
2417
|
-
|
|
2418
|
-
return typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? reasoningTokens : void 0;
|
|
2504
|
+
return asFiniteNumber(usage?.output_tokens_details?.reasoning_tokens);
|
|
2419
2505
|
}
|
|
2420
2506
|
function mapResponsesTerminalStopReason(status) {
|
|
2421
2507
|
if (!status) return "stop";
|
|
@@ -2522,7 +2608,7 @@ function createResponsesTerminalController(params) {
|
|
|
2522
2608
|
content: text,
|
|
2523
2609
|
partial: output
|
|
2524
2610
|
});
|
|
2525
|
-
return;
|
|
2611
|
+
return started.index;
|
|
2526
2612
|
}
|
|
2527
2613
|
const previous = params.getLastTextBlock();
|
|
2528
2614
|
const collapse = resolveResponsesMessageSnapshotCollapse({
|
|
@@ -2542,7 +2628,7 @@ function createResponsesTerminalController(params) {
|
|
|
2542
2628
|
content: collapse.text,
|
|
2543
2629
|
partial: output
|
|
2544
2630
|
});
|
|
2545
|
-
return;
|
|
2631
|
+
return previous.index;
|
|
2546
2632
|
}
|
|
2547
2633
|
const block = {
|
|
2548
2634
|
type: "text",
|
|
@@ -2567,6 +2653,7 @@ function createResponsesTerminalController(params) {
|
|
|
2567
2653
|
content: text,
|
|
2568
2654
|
partial: output
|
|
2569
2655
|
});
|
|
2656
|
+
return index;
|
|
2570
2657
|
};
|
|
2571
2658
|
const appendToolCall = (item) => {
|
|
2572
2659
|
const validated = resolveCompletedResponsesToolCall(item);
|
|
@@ -2589,17 +2676,17 @@ function createResponsesTerminalController(params) {
|
|
|
2589
2676
|
toolCall,
|
|
2590
2677
|
partial: output
|
|
2591
2678
|
});
|
|
2679
|
+
return contentIndex;
|
|
2592
2680
|
};
|
|
2593
2681
|
const recoverTerminalOutput = (items, includeToolCalls) => {
|
|
2594
2682
|
let hasCompletedLaterOutput = false;
|
|
2595
2683
|
for (const item of items.toReversed()) {
|
|
2596
2684
|
if (item.type === "reasoning") {
|
|
2597
|
-
hasCompletedLaterOutput ||= params.
|
|
2685
|
+
hasCompletedLaterOutput ||= params.outputItemContentIndexes.get(item) !== void 0;
|
|
2598
2686
|
continue;
|
|
2599
2687
|
}
|
|
2600
2688
|
if (item.type !== "message" && item.type !== "function_call") continue;
|
|
2601
|
-
|
|
2602
|
-
if (params.completedOutputItemIdentities.has(identity) || item.type === "message" && params.startedTextBlocksByItemId.has(item.id)) {
|
|
2689
|
+
if (params.outputItemContentIndexes.get(item) !== void 0 || item.type === "message" && params.startedTextBlocksByItemId.has(item.id)) {
|
|
2603
2690
|
hasCompletedLaterOutput = true;
|
|
2604
2691
|
continue;
|
|
2605
2692
|
}
|
|
@@ -2607,25 +2694,32 @@ function createResponsesTerminalController(params) {
|
|
|
2607
2694
|
if (hasCompletedLaterOutput) throw new Error("Responses stream omitted an output item before completed output");
|
|
2608
2695
|
if (item.type === "function_call") resolveCompletedResponsesToolCall(item);
|
|
2609
2696
|
}
|
|
2610
|
-
for (const item of items) if (item.type === "message") {
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
params.completedOutputItemIdentities.add(identity);
|
|
2697
|
+
for (const [terminalIndex, item] of items.entries()) if (item.type === "message") {
|
|
2698
|
+
if (params.outputItemContentIndexes.get(item) !== void 0 && !params.startedTextBlocksByItemId.has(item.id)) continue;
|
|
2699
|
+
const appendedIndex = appendText(item);
|
|
2700
|
+
if (appendedIndex !== void 0) params.outputItemContentIndexes.set(item, appendedIndex);
|
|
2615
2701
|
} else {
|
|
2616
2702
|
params.setLastTextBlock(null);
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2703
|
+
const alreadyCapturedCompaction = item.type === "compaction" && output.providerReplay?.type === "openai-responses-compaction" && output.providerReplay.id === item.id && output.providerReplay.data === item.encrypted_content;
|
|
2704
|
+
if (item.type === "compaction" && !alreadyCapturedCompaction) {
|
|
2705
|
+
let replayIndex = blocks.length;
|
|
2706
|
+
for (const laterItem of items.slice(terminalIndex + 1)) {
|
|
2707
|
+
const laterContentIndex = params.outputItemContentIndexes.get(laterItem);
|
|
2708
|
+
if (laterContentIndex !== void 0) {
|
|
2709
|
+
replayIndex = laterContentIndex;
|
|
2710
|
+
break;
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
captureOpenAIResponsesCompaction(output, item, replayIndex, model, options?.reasoningReplayMetadata);
|
|
2714
|
+
} else if (includeToolCalls && item.type === "function_call") {
|
|
2715
|
+
if (params.outputItemContentIndexes.get(item) !== void 0) continue;
|
|
2716
|
+
params.outputItemContentIndexes.set(item, appendToolCall(item));
|
|
2622
2717
|
}
|
|
2623
2718
|
}
|
|
2624
2719
|
};
|
|
2625
|
-
const
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
output.responseId = response.id || output.responseId;
|
|
2720
|
+
const finalizeTerminalFacts = (response, responseId = response.id) => {
|
|
2721
|
+
output.responseId = responseId || output.responseId;
|
|
2722
|
+
output.responseModel = response.model?.trim() || void 0;
|
|
2629
2723
|
const usage = mapResponsesTerminalUsage(response.usage);
|
|
2630
2724
|
const reasoningTokens = readResponsesReasoningTokens(response.usage);
|
|
2631
2725
|
if (usage) output.usage = {
|
|
@@ -2644,6 +2738,11 @@ function createResponsesTerminalController(params) {
|
|
|
2644
2738
|
const tier = options.resolveServiceTier ? options.resolveServiceTier(response.service_tier, options.serviceTier) : response.service_tier ?? options.serviceTier;
|
|
2645
2739
|
options.applyServiceTierPricing(output.usage, tier);
|
|
2646
2740
|
}
|
|
2741
|
+
};
|
|
2742
|
+
const finalizeResponse = (response, terminalEventType) => {
|
|
2743
|
+
params.markFinalized();
|
|
2744
|
+
backfillReasoning(response.output ?? []);
|
|
2745
|
+
finalizeTerminalFacts(response);
|
|
2647
2746
|
const terminal = resolveResponsesTerminalStopReason({
|
|
2648
2747
|
status: response.status,
|
|
2649
2748
|
terminalEventType,
|
|
@@ -2655,30 +2754,22 @@ function createResponsesTerminalController(params) {
|
|
|
2655
2754
|
};
|
|
2656
2755
|
return {
|
|
2657
2756
|
finalizeResponse,
|
|
2757
|
+
finalizeFailedResponse: finalizeTerminalFacts,
|
|
2658
2758
|
recoverTerminalOutput
|
|
2659
2759
|
};
|
|
2660
2760
|
}
|
|
2661
2761
|
//#endregion
|
|
2662
2762
|
//#region packages/ai/src/transports/openai-responses-stream-internal.ts
|
|
2663
|
-
var ResponsesStreamFailure = class extends Error {
|
|
2664
|
-
constructor(failure, response) {
|
|
2665
|
-
super(failure.message);
|
|
2666
|
-
this.name = "ResponsesStreamFailure";
|
|
2667
|
-
this.responseId = failure.responseId;
|
|
2668
|
-
this.response = response;
|
|
2669
|
-
this.observation = failure.observation;
|
|
2670
|
-
}
|
|
2671
|
-
};
|
|
2672
2763
|
async function processResponsesStream(openaiStream, output, stream, model, options) {
|
|
2673
2764
|
const streamingToolCalls = createResponsesToolCallTracker();
|
|
2674
2765
|
const outputSlots = createResponsesOutputSlotTracker();
|
|
2675
2766
|
const reasoningBlocksById = /* @__PURE__ */ new Map();
|
|
2676
|
-
const
|
|
2767
|
+
const outputItemContentIndexes = createResponsesOutputContentIndex();
|
|
2677
2768
|
const startedTextBlocksByItemId = /* @__PURE__ */ new Map();
|
|
2678
|
-
let
|
|
2769
|
+
let terminalResponse;
|
|
2679
2770
|
let lastTextBlock = null;
|
|
2680
2771
|
const blocks = output.content;
|
|
2681
|
-
const
|
|
2772
|
+
const compactionTracker = createCompactionTracker(output, model, options);
|
|
2682
2773
|
const createOutputSlot = (event, item) => {
|
|
2683
2774
|
if (item.type === "reasoning") {
|
|
2684
2775
|
const block = {
|
|
@@ -2693,6 +2784,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2693
2784
|
};
|
|
2694
2785
|
blocks.push(block);
|
|
2695
2786
|
reasoningBlocksById.set(item.id, block);
|
|
2787
|
+
outputItemContentIndexes.set(item, slot.contentIndex);
|
|
2696
2788
|
outputSlots.register(event, slot);
|
|
2697
2789
|
stream.push({
|
|
2698
2790
|
type: "thinking_start",
|
|
@@ -2719,6 +2811,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2719
2811
|
};
|
|
2720
2812
|
if (block) {
|
|
2721
2813
|
blocks.push(block);
|
|
2814
|
+
outputItemContentIndexes.set(messageItem, slot.contentIndex ?? blocks.length - 1);
|
|
2722
2815
|
startedTextBlocksByItemId.set(messageItem.id, {
|
|
2723
2816
|
block,
|
|
2724
2817
|
index: slot.contentIndex ?? blocks.length - 1,
|
|
@@ -2751,7 +2844,8 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2751
2844
|
...slot.item.phase ? { textSignature: encodeTextSignatureV1(slot.item.id, slot.item.phase) } : {}
|
|
2752
2845
|
};
|
|
2753
2846
|
blocks.push(slot.block);
|
|
2754
|
-
slot.contentIndex =
|
|
2847
|
+
slot.contentIndex = blocks.length - 1;
|
|
2848
|
+
outputItemContentIndexes.set(slot.item, slot.contentIndex);
|
|
2755
2849
|
startedTextBlocksByItemId.set(slot.item.id, {
|
|
2756
2850
|
block: slot.block,
|
|
2757
2851
|
index: slot.contentIndex,
|
|
@@ -2774,21 +2868,19 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2774
2868
|
const materializeDeferredTextSlots = (except) => {
|
|
2775
2869
|
for (const slot of outputSlots.values()) if (slot !== except && slot.type === "text") materializeDeferredTextSlot(slot);
|
|
2776
2870
|
};
|
|
2777
|
-
const { finalizeResponse, recoverTerminalOutput } = createResponsesTerminalController({
|
|
2871
|
+
const { finalizeResponse, finalizeFailedResponse, recoverTerminalOutput } = createResponsesTerminalController({
|
|
2778
2872
|
output,
|
|
2779
2873
|
stream,
|
|
2780
2874
|
model,
|
|
2781
2875
|
options,
|
|
2782
2876
|
reasoningBlocksById,
|
|
2783
|
-
completedOutputItemIdentities,
|
|
2784
2877
|
startedTextBlocksByItemId,
|
|
2878
|
+
outputItemContentIndexes,
|
|
2785
2879
|
getLastTextBlock: () => lastTextBlock,
|
|
2786
2880
|
setLastTextBlock: (block) => {
|
|
2787
2881
|
lastTextBlock = block;
|
|
2788
2882
|
},
|
|
2789
|
-
markFinalized: () =>
|
|
2790
|
-
terminalResponseEvent = "finalized";
|
|
2791
|
-
}
|
|
2883
|
+
markFinalized: () => void 0
|
|
2792
2884
|
});
|
|
2793
2885
|
const guardedStream = adaptResponsesStream(withFirstStreamEventTimeout(openaiStream, {
|
|
2794
2886
|
provider: model.provider,
|
|
@@ -2801,327 +2893,538 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2801
2893
|
hint: "The provider may be stalled while parsing the tool payload; retry with a smaller tool surface or enable OPENCLAW_DEBUG_MODEL_PAYLOAD=tools to inspect exposed tools."
|
|
2802
2894
|
}), options?.signal);
|
|
2803
2895
|
try {
|
|
2804
|
-
for await (const event of guardedStream)
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
contentIndex
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
partial: output
|
|
2855
|
-
});
|
|
2856
|
-
} else if (event.type === "response.reasoning_summary_part.done") {
|
|
2857
|
-
const slot = outputSlots.resolve(event, "thinking");
|
|
2858
|
-
if (!slot) continue;
|
|
2859
|
-
slot.item.summary = slot.item.summary || [];
|
|
2860
|
-
const lastPart = slot.item.summary[slot.item.summary.length - 1];
|
|
2861
|
-
if (!lastPart) continue;
|
|
2862
|
-
slot.block.thinking += "\n\n";
|
|
2863
|
-
lastPart.text += "\n\n";
|
|
2864
|
-
stream.push({
|
|
2865
|
-
type: "thinking_delta",
|
|
2866
|
-
contentIndex: slot.contentIndex,
|
|
2867
|
-
delta: "\n\n",
|
|
2868
|
-
partial: output
|
|
2869
|
-
});
|
|
2870
|
-
} else if (event.type === "response.reasoning_text.delta") {
|
|
2871
|
-
const slot = outputSlots.resolve(event, "thinking");
|
|
2872
|
-
if (!slot) continue;
|
|
2873
|
-
slot.block.thinking += event.delta;
|
|
2874
|
-
stream.push({
|
|
2875
|
-
type: "thinking_delta",
|
|
2876
|
-
contentIndex: slot.contentIndex,
|
|
2877
|
-
delta: event.delta,
|
|
2878
|
-
partial: output
|
|
2879
|
-
});
|
|
2880
|
-
} else if (event.type === "response.content_part.added") {
|
|
2881
|
-
const slot = outputSlots.resolve(event, "text");
|
|
2882
|
-
if (!slot) continue;
|
|
2883
|
-
slot.item.content = slot.item.content || [];
|
|
2884
|
-
if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
|
|
2885
|
-
} else if (event.type === "response.output_text.delta") {
|
|
2886
|
-
const slot = outputSlots.resolve(event, "text");
|
|
2887
|
-
if (!slot) continue;
|
|
2888
|
-
slot.item.content ||= [];
|
|
2889
|
-
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2890
|
-
if (!isResponsesTextContentPartType(lastPart?.type)) {
|
|
2891
|
-
lastPart = {
|
|
2892
|
-
type: "output_text",
|
|
2893
|
-
text: "",
|
|
2894
|
-
annotations: []
|
|
2895
|
-
};
|
|
2896
|
-
slot.item.content.push(lastPart);
|
|
2897
|
-
}
|
|
2898
|
-
lastPart.text += event.delta;
|
|
2899
|
-
if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
|
|
2900
|
-
else if (slot.block && slot.contentIndex !== void 0) {
|
|
2901
|
-
slot.block.text += event.delta;
|
|
2896
|
+
for await (const event of guardedStream) {
|
|
2897
|
+
notifyLlmRequestActivity(options?.signal);
|
|
2898
|
+
if (event.type === "response.created") output.responseId = event.response.id;
|
|
2899
|
+
else if (event.type === "response.output_item.added") {
|
|
2900
|
+
materializeDeferredTextSlots();
|
|
2901
|
+
const item = event.item;
|
|
2902
|
+
compactionTracker.added(item, blocks.length);
|
|
2903
|
+
if (item.type !== "message") lastTextBlock = null;
|
|
2904
|
+
if (item.type === "reasoning" || item.type === "message") createOutputSlot(event, item);
|
|
2905
|
+
else if (item.type === "function_call") {
|
|
2906
|
+
const toolCallBlock = {
|
|
2907
|
+
type: "toolCall",
|
|
2908
|
+
id: resolveResponsesToolCallId(item),
|
|
2909
|
+
name: typeof item.name === "string" ? item.name.trim() : "",
|
|
2910
|
+
arguments: {},
|
|
2911
|
+
partialJson: item.arguments || ""
|
|
2912
|
+
};
|
|
2913
|
+
const contentIndex = output.content.length;
|
|
2914
|
+
const toolCallState = {
|
|
2915
|
+
block: toolCallBlock,
|
|
2916
|
+
contentIndex,
|
|
2917
|
+
argumentStreamReliable: true,
|
|
2918
|
+
...readResponsesToolCallItemIdentity(item)
|
|
2919
|
+
};
|
|
2920
|
+
streamingToolCalls.register(event, toolCallState);
|
|
2921
|
+
if (readResponsesOutputIndex(event) !== void 0) outputSlots.register(event, {
|
|
2922
|
+
type: "toolCall",
|
|
2923
|
+
toolCall: toolCallState
|
|
2924
|
+
});
|
|
2925
|
+
output.content.push(toolCallBlock);
|
|
2926
|
+
outputItemContentIndexes.set(item, contentIndex);
|
|
2927
|
+
stream.push({
|
|
2928
|
+
type: "toolcall_start",
|
|
2929
|
+
contentIndex,
|
|
2930
|
+
partial: output
|
|
2931
|
+
});
|
|
2932
|
+
}
|
|
2933
|
+
} else if (event.type === "response.reasoning_summary_part.added") {
|
|
2934
|
+
const slot = outputSlots.resolve(event, "thinking");
|
|
2935
|
+
if (!slot) continue;
|
|
2936
|
+
slot.item.summary = slot.item.summary || [];
|
|
2937
|
+
slot.item.summary.push(event.part);
|
|
2938
|
+
} else if (event.type === "response.reasoning_summary_text.delta") {
|
|
2939
|
+
const slot = outputSlots.resolve(event, "thinking");
|
|
2940
|
+
if (!slot) continue;
|
|
2941
|
+
slot.item.summary = slot.item.summary || [];
|
|
2942
|
+
const lastPart = slot.item.summary[slot.item.summary.length - 1];
|
|
2943
|
+
if (!lastPart) continue;
|
|
2944
|
+
slot.block.thinking += event.delta;
|
|
2945
|
+
lastPart.text += event.delta;
|
|
2902
2946
|
stream.push({
|
|
2903
|
-
type: "
|
|
2947
|
+
type: "thinking_delta",
|
|
2904
2948
|
contentIndex: slot.contentIndex,
|
|
2905
|
-
delta: event.delta
|
|
2949
|
+
delta: event.delta,
|
|
2950
|
+
partial: output
|
|
2906
2951
|
});
|
|
2907
|
-
}
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
lastPart
|
|
2915
|
-
type: "text",
|
|
2916
|
-
text: ""
|
|
2917
|
-
};
|
|
2918
|
-
slot.item.content.push(lastPart);
|
|
2919
|
-
}
|
|
2920
|
-
lastPart.text += event.delta;
|
|
2921
|
-
if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
|
|
2922
|
-
else if (slot.block && slot.contentIndex !== void 0) {
|
|
2923
|
-
slot.block.text += event.delta;
|
|
2952
|
+
} else if (event.type === "response.reasoning_summary_part.done") {
|
|
2953
|
+
const slot = outputSlots.resolve(event, "thinking");
|
|
2954
|
+
if (!slot) continue;
|
|
2955
|
+
slot.item.summary = slot.item.summary || [];
|
|
2956
|
+
const lastPart = slot.item.summary[slot.item.summary.length - 1];
|
|
2957
|
+
if (!lastPart) continue;
|
|
2958
|
+
slot.block.thinking += "\n\n";
|
|
2959
|
+
lastPart.text += "\n\n";
|
|
2924
2960
|
stream.push({
|
|
2925
|
-
type: "
|
|
2961
|
+
type: "thinking_delta",
|
|
2926
2962
|
contentIndex: slot.contentIndex,
|
|
2927
|
-
delta:
|
|
2963
|
+
delta: "\n\n",
|
|
2964
|
+
partial: output
|
|
2928
2965
|
});
|
|
2929
|
-
}
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
slot.item.content ||= [];
|
|
2934
|
-
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2935
|
-
if (lastPart?.type !== "refusal") {
|
|
2936
|
-
lastPart = {
|
|
2937
|
-
type: "refusal",
|
|
2938
|
-
refusal: ""
|
|
2939
|
-
};
|
|
2940
|
-
slot.item.content.push(lastPart);
|
|
2941
|
-
}
|
|
2942
|
-
lastPart.refusal += event.delta;
|
|
2943
|
-
if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
|
|
2944
|
-
else if (slot.block && slot.contentIndex !== void 0) {
|
|
2945
|
-
slot.block.text += event.delta;
|
|
2966
|
+
} else if (event.type === "response.reasoning_text.delta") {
|
|
2967
|
+
const slot = outputSlots.resolve(event, "thinking");
|
|
2968
|
+
if (!slot) continue;
|
|
2969
|
+
slot.block.thinking += event.delta;
|
|
2946
2970
|
stream.push({
|
|
2947
|
-
type: "
|
|
2971
|
+
type: "thinking_delta",
|
|
2948
2972
|
contentIndex: slot.contentIndex,
|
|
2949
|
-
delta: event.delta
|
|
2950
|
-
});
|
|
2951
|
-
}
|
|
2952
|
-
} else if (event.type === "response.function_call_arguments.delta") {
|
|
2953
|
-
const toolCall = streamingToolCalls.resolve(event);
|
|
2954
|
-
if (toolCall) {
|
|
2955
|
-
toolCall.block.partialJson += event.delta;
|
|
2956
|
-
toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
|
|
2957
|
-
stream.push({
|
|
2958
|
-
type: "toolcall_delta",
|
|
2959
|
-
contentIndex: toolCall.contentIndex,
|
|
2960
2973
|
delta: event.delta,
|
|
2961
2974
|
partial: output
|
|
2962
2975
|
});
|
|
2963
|
-
} else if (
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2976
|
+
} else if (event.type === "response.content_part.added") {
|
|
2977
|
+
const slot = outputSlots.resolve(event, "text");
|
|
2978
|
+
if (!slot) continue;
|
|
2979
|
+
slot.item.content = slot.item.content || [];
|
|
2980
|
+
if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
|
|
2981
|
+
} else if (event.type === "response.output_text.delta") {
|
|
2982
|
+
const slot = outputSlots.resolve(event, "text");
|
|
2983
|
+
if (!slot) continue;
|
|
2984
|
+
slot.item.content ||= [];
|
|
2985
|
+
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2986
|
+
if (!isResponsesTextContentPartType(lastPart?.type)) {
|
|
2987
|
+
lastPart = {
|
|
2988
|
+
type: "output_text",
|
|
2989
|
+
text: "",
|
|
2990
|
+
annotations: []
|
|
2991
|
+
};
|
|
2992
|
+
slot.item.content.push(lastPart);
|
|
2993
|
+
}
|
|
2994
|
+
lastPart.text += event.delta;
|
|
2995
|
+
if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
|
|
2996
|
+
else if (slot.block && slot.contentIndex !== void 0) {
|
|
2997
|
+
slot.block.text += event.delta;
|
|
2998
|
+
stream.push({
|
|
2999
|
+
type: "text_delta",
|
|
3000
|
+
contentIndex: slot.contentIndex,
|
|
3001
|
+
delta: event.delta
|
|
3002
|
+
});
|
|
3003
|
+
}
|
|
3004
|
+
} else if (isAzureResponsesTextDeltaEvent(event)) {
|
|
3005
|
+
const slot = outputSlots.resolve(event, "text");
|
|
3006
|
+
if (!slot) continue;
|
|
3007
|
+
slot.item.content = slot.item.content || [];
|
|
3008
|
+
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
3009
|
+
if (lastPart?.type !== "text") {
|
|
3010
|
+
lastPart = {
|
|
3011
|
+
type: "text",
|
|
3012
|
+
text: ""
|
|
3013
|
+
};
|
|
3014
|
+
slot.item.content.push(lastPart);
|
|
3015
|
+
}
|
|
3016
|
+
lastPart.text += event.delta;
|
|
3017
|
+
if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
|
|
3018
|
+
else if (slot.block && slot.contentIndex !== void 0) {
|
|
3019
|
+
slot.block.text += event.delta;
|
|
3020
|
+
stream.push({
|
|
3021
|
+
type: "text_delta",
|
|
3022
|
+
contentIndex: slot.contentIndex,
|
|
3023
|
+
delta: event.delta
|
|
3024
|
+
});
|
|
3025
|
+
}
|
|
3026
|
+
} else if (event.type === "response.refusal.delta") {
|
|
3027
|
+
const slot = outputSlots.resolve(event, "text");
|
|
3028
|
+
if (!slot) continue;
|
|
3029
|
+
slot.item.content ||= [];
|
|
3030
|
+
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
3031
|
+
if (lastPart?.type !== "refusal") {
|
|
3032
|
+
lastPart = {
|
|
3033
|
+
type: "refusal",
|
|
3034
|
+
refusal: ""
|
|
3035
|
+
};
|
|
3036
|
+
slot.item.content.push(lastPart);
|
|
3037
|
+
}
|
|
3038
|
+
lastPart.refusal += event.delta;
|
|
3039
|
+
if (slot.pendingText !== null) appendResponsesPendingTextDelta(slot, event.delta, materializeDeferredTextSlot);
|
|
3040
|
+
else if (slot.block && slot.contentIndex !== void 0) {
|
|
3041
|
+
slot.block.text += event.delta;
|
|
3042
|
+
stream.push({
|
|
3043
|
+
type: "text_delta",
|
|
3044
|
+
contentIndex: slot.contentIndex,
|
|
3045
|
+
delta: event.delta
|
|
3046
|
+
});
|
|
2973
3047
|
}
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
3048
|
+
} else if (event.type === "response.function_call_arguments.delta") {
|
|
3049
|
+
const toolCall = streamingToolCalls.resolve(event);
|
|
3050
|
+
if (toolCall) {
|
|
3051
|
+
toolCall.block.partialJson += event.delta;
|
|
3052
|
+
toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
|
|
3053
|
+
stream.push({
|
|
2977
3054
|
type: "toolcall_delta",
|
|
2978
3055
|
contentIndex: toolCall.contentIndex,
|
|
2979
|
-
delta,
|
|
3056
|
+
delta: event.delta,
|
|
2980
3057
|
partial: output
|
|
2981
3058
|
});
|
|
2982
|
-
}
|
|
2983
|
-
} else if (
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
} else if (
|
|
3004
|
-
const
|
|
3005
|
-
|
|
3006
|
-
const
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
|
|
3017
|
-
outputSlot.collapseCandidate.block.text = collapse.text;
|
|
3018
|
-
outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
|
|
3059
|
+
} else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
|
|
3060
|
+
} else if (event.type === "response.function_call_arguments.done") {
|
|
3061
|
+
const toolCall = streamingToolCalls.resolve(event);
|
|
3062
|
+
if (toolCall) {
|
|
3063
|
+
const previousPartialJson = toolCall.block.partialJson;
|
|
3064
|
+
const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
|
|
3065
|
+
if (doneArguments !== void 0 && (doneArguments.length > 0 || previousPartialJson === "")) {
|
|
3066
|
+
toolCall.block.partialJson = doneArguments;
|
|
3067
|
+
toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
|
|
3068
|
+
toolCall.argumentStreamReliable = true;
|
|
3069
|
+
}
|
|
3070
|
+
if (doneArguments?.startsWith(previousPartialJson)) {
|
|
3071
|
+
const delta = doneArguments.slice(previousPartialJson.length);
|
|
3072
|
+
if (delta.length > 0) stream.push({
|
|
3073
|
+
type: "toolcall_delta",
|
|
3074
|
+
contentIndex: toolCall.contentIndex,
|
|
3075
|
+
delta,
|
|
3076
|
+
partial: output
|
|
3077
|
+
});
|
|
3078
|
+
}
|
|
3079
|
+
} else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
|
|
3080
|
+
} else if (event.type === "response.output_item.done") {
|
|
3081
|
+
const item = event.item;
|
|
3082
|
+
if (item.type !== "message") lastTextBlock = null;
|
|
3083
|
+
const existingOutputSlot = resolveOutputItemSlot(event, item);
|
|
3084
|
+
materializeDeferredTextSlots(existingOutputSlot);
|
|
3085
|
+
const outputSlot = existingOutputSlot ?? getOrCreateOutputSlot(event, item);
|
|
3086
|
+
compactionTracker.completed(item, blocks.length);
|
|
3087
|
+
if (item.type === "reasoning" && outputSlot?.type === "thinking") {
|
|
3088
|
+
const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
|
|
3089
|
+
const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
|
|
3090
|
+
outputSlot.block.thinking = summaryText || contentText || outputSlot.block.thinking;
|
|
3091
|
+
outputSlot.block.thinkingSignature = JSON.stringify(item);
|
|
3092
|
+
if (item.encrypted_content && options?.reasoningReplayMetadata) outputSlot.block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY] = options.reasoningReplayMetadata;
|
|
3019
3093
|
stream.push({
|
|
3020
|
-
type: "
|
|
3021
|
-
contentIndex: outputSlot.
|
|
3022
|
-
content:
|
|
3094
|
+
type: "thinking_end",
|
|
3095
|
+
contentIndex: outputSlot.contentIndex,
|
|
3096
|
+
content: outputSlot.block.thinking,
|
|
3023
3097
|
partial: output
|
|
3024
3098
|
});
|
|
3025
|
-
|
|
3026
|
-
} else {
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3099
|
+
outputSlots.forget(outputSlot);
|
|
3100
|
+
} else if (item.type === "message" && outputSlot?.type === "text" && (outputSlot.block || outputSlot.pendingText !== null)) {
|
|
3101
|
+
const streamedText = outputSlot.pendingText ?? outputSlot.block?.text ?? "";
|
|
3102
|
+
const finalText = item.content == null ? streamedText : item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
|
|
3103
|
+
const phase = item.phase ?? void 0;
|
|
3104
|
+
const collapse = outputSlot.pendingText !== null ? resolveResponsesMessageSnapshotCollapse({
|
|
3105
|
+
prior: outputSlot.collapseCandidate && {
|
|
3106
|
+
text: outputSlot.collapseCandidate.block.text,
|
|
3107
|
+
phase: outputSlot.collapseCandidate.phase
|
|
3108
|
+
},
|
|
3109
|
+
nextText: finalText,
|
|
3110
|
+
nextPhase: phase
|
|
3111
|
+
}) : { kind: "keep" };
|
|
3112
|
+
outputSlot.pendingText = null;
|
|
3113
|
+
if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
|
|
3114
|
+
outputSlot.collapseCandidate.block.text = collapse.text;
|
|
3115
|
+
outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
|
|
3116
|
+
stream.push({
|
|
3117
|
+
type: "text_end",
|
|
3118
|
+
contentIndex: outputSlot.collapseCandidate.index,
|
|
3119
|
+
content: collapse.text,
|
|
3120
|
+
partial: output
|
|
3121
|
+
});
|
|
3122
|
+
lastTextBlock = outputSlot.collapseCandidate;
|
|
3123
|
+
outputItemContentIndexes.set(item, outputSlot.collapseCandidate.index);
|
|
3124
|
+
} else {
|
|
3125
|
+
if (!outputSlot.block) {
|
|
3126
|
+
outputSlot.block = {
|
|
3127
|
+
type: "text",
|
|
3128
|
+
text: "",
|
|
3129
|
+
...phase ? { textSignature: encodeTextSignatureV1(item.id, phase) } : {}
|
|
3130
|
+
};
|
|
3131
|
+
blocks.push(outputSlot.block);
|
|
3132
|
+
outputSlot.contentIndex = blocks.length - 1;
|
|
3133
|
+
stream.push({
|
|
3134
|
+
type: "text_start",
|
|
3135
|
+
contentIndex: outputSlot.contentIndex,
|
|
3136
|
+
partial: output
|
|
3137
|
+
});
|
|
3138
|
+
}
|
|
3139
|
+
outputSlot.block.text = finalText;
|
|
3140
|
+
outputSlot.block.textSignature = encodeTextSignatureV1(item.id, phase);
|
|
3141
|
+
const contentIndex = outputSlot.contentIndex;
|
|
3142
|
+
if (contentIndex === void 0) throw new Error("Responses stream finalized text without a content index");
|
|
3143
|
+
lastTextBlock = {
|
|
3144
|
+
block: outputSlot.block,
|
|
3145
|
+
index: contentIndex,
|
|
3146
|
+
phase
|
|
3032
3147
|
};
|
|
3033
|
-
|
|
3034
|
-
outputSlot.contentIndex = blockIndex();
|
|
3148
|
+
outputItemContentIndexes.set(item, contentIndex);
|
|
3035
3149
|
stream.push({
|
|
3036
|
-
type: "
|
|
3037
|
-
contentIndex
|
|
3150
|
+
type: "text_end",
|
|
3151
|
+
contentIndex,
|
|
3152
|
+
content: outputSlot.block.text,
|
|
3038
3153
|
partial: output
|
|
3039
3154
|
});
|
|
3040
3155
|
}
|
|
3041
|
-
outputSlot
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
content: outputSlot.block.text,
|
|
3054
|
-
partial: output
|
|
3156
|
+
outputSlots.forget(outputSlot);
|
|
3157
|
+
startedTextBlocksByItemId.delete(item.id);
|
|
3158
|
+
} else if (item.type === "function_call") {
|
|
3159
|
+
const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
|
|
3160
|
+
if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
|
|
3161
|
+
const streamedArguments = streamingToolCall?.block.partialJson ?? "";
|
|
3162
|
+
const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
|
|
3163
|
+
if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
|
|
3164
|
+
const finalArguments = completedArguments !== void 0 && (completedArguments.length > 0 || !streamedArguments) ? completedArguments : streamedArguments;
|
|
3165
|
+
const validated = resolveCompletedResponsesToolCall(item, {
|
|
3166
|
+
name: streamingToolCall?.block.name,
|
|
3167
|
+
arguments: finalArguments
|
|
3055
3168
|
});
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
type
|
|
3084
|
-
|
|
3085
|
-
name: validated.name,
|
|
3086
|
-
arguments: validated.arguments
|
|
3087
|
-
};
|
|
3088
|
-
blocks.push(toolCall);
|
|
3089
|
-
contentIndex = blockIndex();
|
|
3169
|
+
let toolCall;
|
|
3170
|
+
let contentIndex;
|
|
3171
|
+
if (streamingToolCall) {
|
|
3172
|
+
const block = streamingToolCall.block;
|
|
3173
|
+
block.id = resolveResponsesToolCallId(item, block.id);
|
|
3174
|
+
block.name = validated.name;
|
|
3175
|
+
block.arguments = validated.arguments;
|
|
3176
|
+
delete block.partialJson;
|
|
3177
|
+
toolCall = block;
|
|
3178
|
+
contentIndex = streamingToolCall.contentIndex;
|
|
3179
|
+
} else {
|
|
3180
|
+
toolCall = {
|
|
3181
|
+
type: "toolCall",
|
|
3182
|
+
id: resolveResponsesToolCallId(item),
|
|
3183
|
+
name: validated.name,
|
|
3184
|
+
arguments: validated.arguments
|
|
3185
|
+
};
|
|
3186
|
+
blocks.push(toolCall);
|
|
3187
|
+
contentIndex = blocks.length - 1;
|
|
3188
|
+
stream.push({
|
|
3189
|
+
type: "toolcall_start",
|
|
3190
|
+
contentIndex,
|
|
3191
|
+
partial: output
|
|
3192
|
+
});
|
|
3193
|
+
}
|
|
3194
|
+
if (streamingToolCall) {
|
|
3195
|
+
streamingToolCalls.forget(streamingToolCall);
|
|
3196
|
+
for (const slot of outputSlots.values()) if (slot.type === "toolCall" && slot.toolCall === streamingToolCall) outputSlots.forget(slot);
|
|
3197
|
+
}
|
|
3090
3198
|
stream.push({
|
|
3091
|
-
type: "
|
|
3199
|
+
type: "toolcall_end",
|
|
3092
3200
|
contentIndex,
|
|
3201
|
+
toolCall,
|
|
3093
3202
|
partial: output
|
|
3094
3203
|
});
|
|
3204
|
+
outputItemContentIndexes.set(item, contentIndex);
|
|
3095
3205
|
}
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3206
|
+
} else if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
3207
|
+
if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
|
|
3208
|
+
finalizeResponse(event.response, event.type);
|
|
3209
|
+
if (event.type === "response.completed" || output.stopReason === "length") recoverTerminalOutput(event.response.output ?? [], event.type === "response.completed");
|
|
3210
|
+
terminalResponse = event.type === "response.completed" ? event.response : null;
|
|
3211
|
+
if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) output.stopReason = "toolUse";
|
|
3212
|
+
break;
|
|
3213
|
+
} else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
|
|
3214
|
+
else if (event.type === "response.failed") {
|
|
3215
|
+
const failure = normalizeResponsesFailedEvent(event, model);
|
|
3216
|
+
finalizeFailedResponse(event.response, failure.responseId);
|
|
3217
|
+
throw new ResponsesStreamFailure(failure, event.response);
|
|
3107
3218
|
}
|
|
3108
|
-
} else if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
3109
|
-
if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
|
|
3110
|
-
finalizeResponse(event.response, event.type);
|
|
3111
|
-
if (event.type === "response.completed" || output.stopReason === "length") recoverTerminalOutput(event.response.output ?? [], event.type === "response.completed");
|
|
3112
|
-
if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) output.stopReason = "toolUse";
|
|
3113
|
-
break;
|
|
3114
|
-
} else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
|
|
3115
|
-
else if (event.type === "response.failed") {
|
|
3116
|
-
const failure = normalizeResponsesFailedEvent(event, model);
|
|
3117
|
-
if (failure.responseId) output.responseId = failure.responseId;
|
|
3118
|
-
throw new ResponsesStreamFailure(failure, event.response);
|
|
3119
3219
|
}
|
|
3220
|
+
if (options?.signal?.aborted) throw transportAbortError(options.signal);
|
|
3120
3221
|
if (streamingToolCalls.hasActive()) throw new Error("Responses stream ended with unresolved tool calls");
|
|
3121
|
-
if (
|
|
3222
|
+
if (terminalResponse === void 0) throw new Error("OpenAI Responses stream ended before a terminal response event");
|
|
3223
|
+
return terminalResponse ?? void 0;
|
|
3122
3224
|
} finally {
|
|
3123
3225
|
for (const block of output.content) delete block.partialJson;
|
|
3124
3226
|
}
|
|
3125
3227
|
}
|
|
3126
3228
|
//#endregion
|
|
3127
|
-
|
|
3229
|
+
//#region packages/ai/src/providers/openai-responses-tools.ts
|
|
3230
|
+
const LOG_SUBSYSTEM = "llm/openai-responses";
|
|
3231
|
+
const MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 64;
|
|
3232
|
+
const loggedStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
|
|
3233
|
+
/** Converts and returns the projection used to reconcile tool choices. */
|
|
3234
|
+
function convertResponsesToolPayload(tools, options) {
|
|
3235
|
+
const projection = projectOpenAITools(tools);
|
|
3236
|
+
const strict = resolveResponsesStrictToolFlag(projection, resolveResponsesStrictToolSetting(options), options?.model);
|
|
3237
|
+
return {
|
|
3238
|
+
projection,
|
|
3239
|
+
tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
|
|
3240
|
+
const result = {
|
|
3241
|
+
type: "function",
|
|
3242
|
+
name: tool.name,
|
|
3243
|
+
description: tool.description,
|
|
3244
|
+
parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, options?.model?.compat)
|
|
3245
|
+
};
|
|
3246
|
+
if (strict !== void 0) result.strict = strict;
|
|
3247
|
+
return result;
|
|
3248
|
+
})
|
|
3249
|
+
};
|
|
3250
|
+
}
|
|
3251
|
+
function resolveResponsesStrictToolSetting(options) {
|
|
3252
|
+
if (options?.strict !== void 0) return options.strict;
|
|
3253
|
+
if (options?.model) return getAiTransportHost().resolveOpenAIStrictToolSetting(options.model, {
|
|
3254
|
+
transport: "stream",
|
|
3255
|
+
supportsStrictMode: options.supportsStrictMode
|
|
3256
|
+
});
|
|
3257
|
+
return false;
|
|
3258
|
+
}
|
|
3259
|
+
function resolveResponsesStrictToolFlag(projection, strictSetting, model) {
|
|
3260
|
+
const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
|
|
3261
|
+
if (strictSetting === true && strict === false && model) getAiTransportHost().logDebug(LOG_SUBSYSTEM, () => {
|
|
3262
|
+
const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
|
|
3263
|
+
if (!shouldLogStrictToolDowngradeDiagnostic(diagnostics, model)) return null;
|
|
3264
|
+
const sample = diagnostics.slice(0, 5).map((entry) => ({
|
|
3265
|
+
tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
|
|
3266
|
+
violations: entry.violations.slice(0, 8)
|
|
3267
|
+
}));
|
|
3268
|
+
return {
|
|
3269
|
+
message: `OpenAI responses tool schema strict mode downgraded to strict=false for ${model.provider ?? "unknown"}/${model.id ?? "unknown"} because ${diagnostics.length} tool schema(s) are not strict-compatible`,
|
|
3270
|
+
data: {
|
|
3271
|
+
provider: model.provider,
|
|
3272
|
+
model: model.id,
|
|
3273
|
+
incompatibleToolCount: diagnostics.length,
|
|
3274
|
+
sample
|
|
3275
|
+
}
|
|
3276
|
+
};
|
|
3277
|
+
});
|
|
3278
|
+
return strict;
|
|
3279
|
+
}
|
|
3280
|
+
function shouldLogStrictToolDowngradeDiagnostic(diagnostics, model) {
|
|
3281
|
+
const key = createHash("sha256").update(JSON.stringify({
|
|
3282
|
+
provider: model.provider,
|
|
3283
|
+
model: model.id,
|
|
3284
|
+
diagnostics: diagnostics.map((entry) => ({
|
|
3285
|
+
toolIndex: entry.toolIndex,
|
|
3286
|
+
toolName: entry.toolName ?? null,
|
|
3287
|
+
violations: entry.violations
|
|
3288
|
+
}))
|
|
3289
|
+
})).digest("hex");
|
|
3290
|
+
if (loggedStrictToolDowngradeDiagnosticKeys.has(key)) return false;
|
|
3291
|
+
if (loggedStrictToolDowngradeDiagnosticKeys.size >= MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedStrictToolDowngradeDiagnosticKeys.clear();
|
|
3292
|
+
loggedStrictToolDowngradeDiagnosticKeys.add(key);
|
|
3293
|
+
return true;
|
|
3294
|
+
}
|
|
3295
|
+
//#endregion
|
|
3296
|
+
//#region packages/ai/src/providers/openai-responses-shared.ts
|
|
3297
|
+
function isResponsesReasoningEffort(effort) {
|
|
3298
|
+
return effort === "minimal" || effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max";
|
|
3299
|
+
}
|
|
3300
|
+
function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
|
|
3301
|
+
return convertProviderResponsesMessages(model, context, allowedToolCallProviders, options);
|
|
3302
|
+
}
|
|
3303
|
+
const createResponsesAssistantOutput = createOpenAIResponsesAssistantOutput;
|
|
3304
|
+
function applyResponsesServiceTierPricing(usage, serviceTier, model) {
|
|
3305
|
+
let multiplier = 1;
|
|
3306
|
+
if (serviceTier === "flex") multiplier = .5;
|
|
3307
|
+
else if (serviceTier === "priority") multiplier = model.id === "gpt-5.5" ? 2.5 : 2;
|
|
3308
|
+
if (multiplier === 1) return;
|
|
3309
|
+
usage.cost.input *= multiplier;
|
|
3310
|
+
usage.cost.output *= multiplier;
|
|
3311
|
+
usage.cost.cacheRead *= multiplier;
|
|
3312
|
+
usage.cost.cacheWrite *= multiplier;
|
|
3313
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
3314
|
+
}
|
|
3315
|
+
function resolveResponsesReasoningEffort(model, reasoning) {
|
|
3316
|
+
const clampedReasoning = reasoning ? clampThinkingLevel(model, reasoning) : void 0;
|
|
3317
|
+
if (!clampedReasoning || clampedReasoning === "off") return;
|
|
3318
|
+
if (clampedReasoning === "max") return supportsOpenAIReasoningEffort(model, "max") ? "max" : "xhigh";
|
|
3319
|
+
if (clampedReasoning === "minimal" && model.provider === "openai" && supportsOpenAIReasoningEffort(model, "max")) {
|
|
3320
|
+
const effort = resolveOpenAIReasoningEffortForModel({
|
|
3321
|
+
model,
|
|
3322
|
+
effort: "minimal"
|
|
3323
|
+
});
|
|
3324
|
+
return isResponsesReasoningEffort(effort) ? effort : void 0;
|
|
3325
|
+
}
|
|
3326
|
+
return clampedReasoning;
|
|
3327
|
+
}
|
|
3328
|
+
function applyCommonResponsesParams(params, model, context, options, config) {
|
|
3329
|
+
if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
|
|
3330
|
+
if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
|
|
3331
|
+
if (context.tools) {
|
|
3332
|
+
const converted = convertResponsesToolPayload(context.tools, { model });
|
|
3333
|
+
if (converted.tools.length > 0) params.tools = converted.tools;
|
|
3334
|
+
}
|
|
3335
|
+
if (!model.reasoning) return;
|
|
3336
|
+
if (options?.reasoningEffort || options?.reasoningSummary) {
|
|
3337
|
+
params.reasoning = {
|
|
3338
|
+
effort: options?.reasoningEffort ? model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort : "medium",
|
|
3339
|
+
summary: options?.reasoningSummary || "auto"
|
|
3340
|
+
};
|
|
3341
|
+
params.include = ["reasoning.encrypted_content"];
|
|
3342
|
+
} else if ((config?.setDefaultReasoningOff ?? true) && model.thinkingLevelMap?.off !== null) params.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
|
|
3343
|
+
}
|
|
3344
|
+
function buildResponsesRequestOptions(options) {
|
|
3345
|
+
return {
|
|
3346
|
+
...options?.signal ? { signal: options.signal } : {},
|
|
3347
|
+
...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
|
|
3348
|
+
maxRetries: options?.maxRetries ?? 0
|
|
3349
|
+
};
|
|
3350
|
+
}
|
|
3351
|
+
function cleanStreamingScratchBuffers(output) {
|
|
3352
|
+
for (const block of output.content) {
|
|
3353
|
+
delete block.index;
|
|
3354
|
+
delete block.partialJson;
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
async function runResponsesStreamLifecycle(params) {
|
|
3358
|
+
const { stream, output, options } = params;
|
|
3359
|
+
let firstEventAbort;
|
|
3360
|
+
try {
|
|
3361
|
+
const model = params.resolveRequestModel?.(params.model) ?? params.model;
|
|
3362
|
+
const client = params.createClient(model);
|
|
3363
|
+
const buildRequest = async (replayMode) => {
|
|
3364
|
+
let request = params.buildParams(model, replayMode);
|
|
3365
|
+
const nextRequest = await options?.onPayload?.(request, model);
|
|
3366
|
+
if (nextRequest !== void 0) request = nextRequest;
|
|
3367
|
+
return request;
|
|
3368
|
+
};
|
|
3369
|
+
const requestParams = await buildRequest("checkpoint");
|
|
3370
|
+
firstEventAbort = createFirstStreamEventAbortController(options?.signal);
|
|
3371
|
+
const { stream: openaiStream, response } = await createResponsesStreamWithEncryptedContentRetry({
|
|
3372
|
+
client,
|
|
3373
|
+
request: requestParams,
|
|
3374
|
+
requestOptions: {
|
|
3375
|
+
...buildResponsesRequestOptions(options),
|
|
3376
|
+
signal: firstEventAbort.signal
|
|
3377
|
+
},
|
|
3378
|
+
model,
|
|
3379
|
+
buildFullHistoryRequest: () => buildRequest("full-history"),
|
|
3380
|
+
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, options, checkpoint)
|
|
3381
|
+
});
|
|
3382
|
+
const hookedOpenAIStream = withProviderResponseHook({
|
|
3383
|
+
stream: openaiStream,
|
|
3384
|
+
signal: firstEventAbort.signal,
|
|
3385
|
+
abort: firstEventAbort.abort,
|
|
3386
|
+
hook: createOpenAIResponseHook(options?.onResponse, response, model),
|
|
3387
|
+
onReady: () => stream.push({
|
|
3388
|
+
type: "start",
|
|
3389
|
+
partial: output
|
|
3390
|
+
})
|
|
3391
|
+
});
|
|
3392
|
+
const firstEventTimeoutMs = getFirstStreamEventTimeoutMs(options);
|
|
3393
|
+
const onFirstEventTimeout = getFirstStreamEventTimeoutHandler(options);
|
|
3394
|
+
await processResponsesStream(hookedOpenAIStream, output, stream, model, {
|
|
3395
|
+
...params.processStreamOptions || firstEventTimeoutMs !== void 0 || onFirstEventTimeout !== void 0 ? {
|
|
3396
|
+
...params.processStreamOptions,
|
|
3397
|
+
firstEventTimeoutMs: params.processStreamOptions?.firstEventTimeoutMs ?? firstEventTimeoutMs,
|
|
3398
|
+
abortFirstEventStream: params.processStreamOptions?.abortFirstEventStream ?? firstEventAbort.abort,
|
|
3399
|
+
onFirstEventTimeout: params.processStreamOptions?.onFirstEventTimeout ?? onFirstEventTimeout,
|
|
3400
|
+
signal: params.processStreamOptions?.signal ?? options?.signal
|
|
3401
|
+
} : void 0,
|
|
3402
|
+
reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
|
|
3403
|
+
sessionId: options?.sessionId,
|
|
3404
|
+
authProfileId: options?.authProfileId
|
|
3405
|
+
})
|
|
3406
|
+
});
|
|
3407
|
+
if (options?.signal?.aborted) throw transportAbortError(options.signal);
|
|
3408
|
+
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
3409
|
+
stream.push({
|
|
3410
|
+
type: "done",
|
|
3411
|
+
reason: output.stopReason,
|
|
3412
|
+
message: output
|
|
3413
|
+
});
|
|
3414
|
+
stream.end();
|
|
3415
|
+
} catch (error) {
|
|
3416
|
+
cleanStreamingScratchBuffers(output);
|
|
3417
|
+
const terminal = projectProviderError(error, options?.signal);
|
|
3418
|
+
Object.assign(output, terminal);
|
|
3419
|
+
stream.push({
|
|
3420
|
+
type: "error",
|
|
3421
|
+
reason: terminal.stopReason,
|
|
3422
|
+
error: output
|
|
3423
|
+
});
|
|
3424
|
+
stream.end();
|
|
3425
|
+
} finally {
|
|
3426
|
+
firstEventAbort?.dispose();
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
//#endregion
|
|
3430
|
+
export { normalizeOpenAIStrictCompatSchema as $, isAzureResponsesTextDeltaEvent as A, buildResponsesInputMessage as B, summarizeResponsesTools as C, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as D, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as E, commitResponsesEncryptedContentAttempt as F, suppressOpenAIResponsesCompaction as G, createOpenAIResponsesAssistantOutput as H, createResponsesStreamWithEncryptedContentRetry as I, isStrictOpenAIJsonSchemaCompatible as J, resolveReplayableResponsesMessageId as K, isInvalidEncryptedContentError as L, isResponsesTextContentPartType as M, isResponsesTextDeltaEventType as N, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as O, resolveResponsesMessageSnapshotCollapse as P, findOpenAIStrictSchemaViolations as Q, resolveAzureOpenAIApiVersion as R, summarizeResponsesPayload as S, readResponsesToolCallItemIdentity as T, buildOpenAIResponsesReasoningReplayMetadata as U, convertResponsesMessages$1 as V, captureOpenAIResponsesCompaction as W, normalizeStrictOpenAIJsonSchema as X, normalizeOpenAIStrictToolParameters as Y, resolveOpenAIProjectedToolsStrictToolFlag as Z, safeDebugValue as _, resolveResponsesReasoningEffort as a, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as at, summarizeOpenAITransportError as b, processResponsesStream as c, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as ct, resolveResponsesTerminalStopReason as d, resolveModelPayloadDebugMode as dt, extractToolSchemaModelCompat as et, observeResponsesStream as f, resolveModelSseDebugMode as ft, normalizeResponsesFailedEvent as g, logResponsesFailedNoDetails as h, quoteUnsafeIntegerLiterals as ht, createResponsesAssistantOutput as i, stripUnsupportedSchemaKeywords as it, isAzureResponsesTextDeltaEventType as j, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as k, mapResponsesTerminalUsage as l, cleanSchemaForGemini as lt, buildResponsesFailedNoDetailsObservation as m, parseJsonPreservingUnsafeIntegers as mt, applyResponsesServiceTierPricing as n, resolveUnsupportedToolSchemaKeywords as nt, runResponsesStreamLifecycle as o, cleanSchemaForLlamacppGbnf as ot, ResponsesStreamFailure as p, parseJsonObjectPreservingUnsafeIntegers as pt, findOpenAIStrictToolProjectionDiagnostics as q, convertResponsesMessages as r, shouldOmitEmptyArrayItems as rt, convertResponsesToolPayload as s, findLlamacppGbnfSchemaViolations as st, applyCommonResponsesParams as t, normalizeToolParameterSchema as tt, readResponsesReasoningTokens as u, emitModelTransportDebug as ut, stringifyRedactedEvent as v, createResponsesToolCallTracker as w, summarizeResponsesFailedNoDetailsObservation as x, stringifyRedactedPayload as y, resolveNextResponsesEncryptedContentAttempt as z };
|