@openclaw/ai 2026.9.3 → 2026.9.5
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/README.md +1 -1
- package/dist/{anthropic-CZy5U0NY.mjs → anthropic-COtDvgtt.mjs} +16 -16
- package/dist/{anthropic-payload-policy-wuRCb6MH.d.mts → anthropic-payload-policy-5Erq1Nzy.d.mts} +3 -3
- package/dist/{anthropic-stream-reducer-B_yo_7pf.mjs → anthropic-stream-reducer-BvdYYWL8.mjs} +56 -47
- package/dist/{api-registry-CB1-1oQ2.d.mts → api-registry-Ba2Cv-ut.d.mts} +2 -2
- package/dist/{assistant-output-iqnlJCV2.mjs → assistant-output-BsEkB-vU.mjs} +1 -1
- package/dist/{azure-openai-responses-Crpa40QR.mjs → azure-openai-responses-YrgnD583.mjs} +6 -9
- package/dist/{base64-D-su8YVo.mjs → base64-BQOzsvUH.mjs} +4 -4
- package/dist/credential-redaction-BKv49aiv.d.mts +24 -0
- package/dist/{diagnostics-dV98PqIy.mjs → diagnostics-Dm4bisWG.mjs} +89 -2
- package/dist/diagnostics.d.mts +4 -23
- package/dist/diagnostics.mjs +3 -3
- package/dist/{event-stream-C1Z2piyk.d.mts → event-stream-CCoa-qSI.d.mts} +1 -1
- package/dist/event-stream-DmSCpi1T.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -2
- package/dist/expect-lbe3Hgrh.mjs +8 -0
- package/dist/{google-BDPriaVe.mjs → google-BuhpRO9r.mjs} +7 -10
- package/dist/{google-messages-CVn9eFpF.mjs → google-messages-CyWnYlh0.mjs} +3 -4
- package/dist/{google-shared-BedY23XS.mjs → google-shared-BT5ZeNer.mjs} +13 -13
- package/dist/{google-vertex-DMz8XQCn.mjs → google-vertex-C7EplRvt.mjs} +5 -8
- package/dist/{host-CWuF-sS3.mjs → host-B4MeUNBc.mjs} +145 -12
- package/dist/{host-DK3wmS3e.d.mts → host-FZ1RA_qD.d.mts} +7 -3
- package/dist/{host-policy-CAopLRKA.mjs → host-policy-DUnXSx0I.mjs} +1 -1
- package/dist/{index-CQ6LTHw8.d.mts → index-DaF2QbwS.d.mts} +5 -10
- package/dist/index.d.mts +7 -8
- package/dist/index.mjs +5 -5
- package/dist/internal/anthropic.d.mts +6 -7
- package/dist/internal/anthropic.mjs +4 -4
- package/dist/internal/openai-completions-compat.d.mts +2 -0
- package/dist/internal/openai-completions-compat.mjs +2 -0
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
- package/dist/internal/openai-responses-payload-policy.mjs +3 -2
- package/dist/internal/openai.d.mts +10 -53
- package/dist/internal/openai.mjs +11 -10
- package/dist/internal/runtime.d.mts +43 -10
- package/dist/internal/runtime.mjs +5 -11
- package/dist/internal/shared.d.mts +35 -5
- package/dist/internal/shared.mjs +4 -4
- package/dist/internal/tool-schema.d.mts +3 -3
- package/dist/internal/tool-schema.mjs +2 -2
- package/dist/{mistral--m-Jm6VZ.mjs → mistral-moA-mbwl.mjs} +9 -16
- package/dist/{openai-chatgpt-responses-nDZccFW-.mjs → openai-chatgpt-responses-DWID3EFO.mjs} +76 -33
- package/dist/{openai-completions-KuoZyx0d.mjs → openai-completions-DJ1Vm-CD.mjs} +12 -13
- package/dist/{openai-prompt-cache-BI0rkM-5.mjs → openai-completions-compat-CkwdxTZx.mjs} +5 -50
- package/dist/{openai-completions-compat-CXn3T1we.d.mts → openai-completions-compat-JE7gqxb9.d.mts} +4 -4
- package/dist/{openai-completions-stream-BQk3SkLD.mjs → openai-completions-stream-Bu98b0Hv.mjs} +128 -99
- package/dist/openai-prompt-cache-1wfaIszn.mjs +46 -0
- package/dist/{openai-prompt-cache-rrutvqxq.d.mts → openai-prompt-cache-CJ_xEevu.d.mts} +2 -2
- package/dist/{openai-provider-client-ha_WxTyj.mjs → openai-provider-client-DPo0Hmak.mjs} +2 -2
- package/dist/{openai-reasoning-effort-BK7FbcLT.mjs → openai-reasoning-effort-NlFZmfEu.mjs} +87 -19
- package/dist/{openai-responses-D99dOzKI.mjs → openai-responses-BejZzQCP.mjs} +9 -13
- package/dist/{openai-responses-compaction-window-D5jbzCi3.mjs → openai-responses-compaction-window-D6P5oZP5.mjs} +21 -140
- package/dist/openai-responses-contracts-DWrfMODE.mjs +81 -0
- package/dist/{openai-responses-contracts-B55afwRo.d.mts → openai-responses-contracts-Dflvrfa8.d.mts} +10 -39
- package/dist/{openai-responses-payload-policy-rLRPsSmB.d.mts → openai-responses-payload-policy-C7GsA1y0.d.mts} +5 -3
- package/dist/openai-responses-prompt-observer-internal-C15_-OwV.mjs +195 -0
- package/dist/{openai-responses-shared-ZyQEzS5i.mjs → openai-responses-shared-CwsziD_m.mjs} +390 -183
- package/dist/openai-responses-terminal-usage-Dl3J6zrf.d.mts +47 -0
- package/dist/{openai-tool-schema-CzjyYXun.mjs → openai-tool-schema-BO8rwyAD.mjs} +92 -68
- package/dist/{openai-transport-params-DNasp2fU.mjs → openai-transport-params-DQeuAvBl.mjs} +162 -51
- package/dist/positive-integer-DtjCkbue.mjs +8 -0
- package/dist/{provider-error-C6TbKiey.mjs → provider-error-DDqw9Qda.mjs} +140 -36
- package/dist/{provider-options-BXr9Ec83.d.mts → provider-options-DprLsWh9.d.mts} +9 -6
- package/dist/{provider-replay-context-BuSUaAk5.mjs → provider-replay-context-CnUSOwhr.mjs} +1 -1
- package/dist/{provider-transcript-transform-pPmUIwKt.mjs → provider-transcript-transform-BsRAhuWJ.mjs} +1 -1
- package/dist/provider-transport-turn-state-CkGToCD2.mjs +42 -0
- package/dist/{provider-types-CAV0Og3m.d.mts → provider-types-CAKRC7N5.d.mts} +3 -3
- package/dist/provider-types.d.mts +6 -7
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +10 -10
- package/dist/{reasoning-tag-text-partitioner-BQBi4B9d.mjs → reasoning-tag-text-partitioner-Dy9IO8Dc.mjs} +15 -14
- package/dist/{session-affinity-CCH7eYdB.mjs → session-affinity-Bcunsn4I.mjs} +5 -2
- package/dist/{simple-options-tcKOqnpF.mjs → simple-options-C6cFWj_f.mjs} +26 -5
- package/dist/{src-B2Q_6G8V.mjs → src-DeKjbE8I.mjs} +3 -6
- package/dist/{stream-first-event-timeout-2hfrquuz.mjs → stream-first-event-timeout-C9ZadkJW.mjs} +1 -1
- package/dist/{string-normalization-CmLIasuf.mjs → string-normalization-J9ZiLfGO.mjs} +13 -1
- package/dist/tool-schema-json-projection-CD9c_fK8.mjs +134 -0
- package/dist/{transport-stream-shared-DOxpGJ-H.d.mts → transport-stream-shared-BbUkFaHi.d.mts} +20 -36
- package/dist/{transport-stream-shared-Cu3ZPhNW.mjs → transport-stream-shared-D-6FQSHm.mjs} +223 -11
- package/dist/{transport-utils-CCooe-cr.mjs → transport-utils-1cyq5Y7x.mjs} +4 -7
- package/dist/transports.d.mts +51 -165
- package/dist/transports.mjs +172 -507
- package/dist/{types-Dy1q0CSu.d.mts → types-4_uVs5WH.d.mts} +49 -3
- package/dist/types-DkJfb4W3.d.mts +1 -0
- package/dist/types-LFWwv0cF.mjs +8 -0
- package/dist/types.d.mts +6 -7
- package/dist/types.mjs +4 -4
- package/dist/{validation-CaFUZN9B.d.mts → validation-Ctzu2DhF.d.mts} +1 -1
- package/dist/{validation-BDzVDnTs.mjs → validation-Dw7cb6BV.mjs} +1 -0
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +10 -5
- package/dist/diagnostics-DnPnOui6.d.mts +0 -29
- package/dist/event-stream-I_GlBsuZ.d.mts +0 -1
- package/dist/hash-CHgqbJmD.mjs +0 -16
- package/dist/json-parse-Dw_hnxsA.mjs +0 -146
- package/dist/openai-responses-prompt-observer-internal-tApyTLVu.mjs +0 -32
- package/dist/sanitize-unicode-Bb-v9meu.mjs +0 -83
- package/dist/tool-schema-json-projection-ClptDdAO.mjs +0 -82
- package/dist/types-BADKjDBI.d.mts +0 -1
- package/dist/types-BDdaOVi2.mjs +0 -6
|
@@ -1,26 +1,25 @@
|
|
|
1
|
+
import { t as appendAssistantMessageDiagnostic } from "./diagnostics-CPeq9F7y.mjs";
|
|
1
2
|
import { r as appendAssistantThinking } from "./event-stream-D8PARQfL.mjs";
|
|
2
3
|
import { a as normalizeOptionalString } from "./string-coerce-fsri9iCu.mjs";
|
|
3
|
-
import { i as clampThinkingLevel, r as calculateCost } from "./sanitize-unicode-Bb-v9meu.mjs";
|
|
4
|
-
import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, n as getAiTransportHost } from "./host-CWuF-sS3.mjs";
|
|
5
4
|
import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
|
|
5
|
+
import { u as supportsOpenAITemperature } from "./openai-reasoning-effort-NlFZmfEu.mjs";
|
|
6
|
+
import { _ as isImageWithMediaPayload, d as describeToolResultMediaPlaceholder, j as calculateCost, m as extractToolResultText, n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-B4MeUNBc.mjs";
|
|
6
7
|
import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import { a as resolveModelSseDebugMode, i as resolveModelPayloadDebugMode, r as emitModelTransportDebug } from "./diagnostics-
|
|
9
|
-
import {
|
|
10
|
-
import { s as
|
|
11
|
-
import {
|
|
12
|
-
import { d as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { t as shortHash } from "./hash-CHgqbJmD.mjs";
|
|
16
|
-
import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-BuSUaAk5.mjs";
|
|
17
|
-
import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-Dw_hnxsA.mjs";
|
|
8
|
+
import { o as stableStringify } from "./provider-error-DDqw9Qda.mjs";
|
|
9
|
+
import { a as resolveModelSseDebugMode, d as readResponsesReasoningTokens, f as resolveResponsesTerminalStopReason, i as resolveModelPayloadDebugMode, r as emitModelTransportDebug, u as mapResponsesTerminalUsage } from "./diagnostics-Dm4bisWG.mjs";
|
|
10
|
+
import { o as redactSensitiveText } from "./transport-utils-1cyq5Y7x.mjs";
|
|
11
|
+
import { s as transformTransportMessages } from "./host-policy-DUnXSx0I.mjs";
|
|
12
|
+
import { m as stripSystemPromptCacheBoundary, v as sortPromptCacheToolsByName } from "./simple-options-C6cFWj_f.mjs";
|
|
13
|
+
import { M as redactIdentifier, N as sha256Hex, b as createOpenAIProviderAcceptanceHook, d as prepareOpenAITools, h as resolveOpenAIRequestReasoning, u as resolveOpenAIStrictToolFlagWithDiagnostics, w as log, y as createModelStreamCooperativeScheduler } from "./openai-transport-params-DQeuAvBl.mjs";
|
|
14
|
+
import { E as parseStreamingJson, _ as sanitizeTransportPayloadText, b as withProviderResponseHook, g as sanitizeNonEmptyTransportPayloadText, h as parseTerminalToolCallArguments, k as shortHash, l as finalizeTransportStream, s as failTransportStream, t as IncompleteToolCallError, v as transportAbortError, w as createToolArgumentPreviewSchedule, x as parseJsonObjectPreservingUnsafeIntegers } from "./transport-stream-shared-D-6FQSHm.mjs";
|
|
15
|
+
import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-CnUSOwhr.mjs";
|
|
18
16
|
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
19
|
-
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-
|
|
20
|
-
import { t as transformProviderMessages } from "./provider-transcript-transform-
|
|
21
|
-
import { a as
|
|
22
|
-
import { a as
|
|
23
|
-
import {
|
|
17
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-C9ZadkJW.mjs";
|
|
18
|
+
import { t as transformProviderMessages } from "./provider-transcript-transform-BsRAhuWJ.mjs";
|
|
19
|
+
import { a as resolveOpenAIProjectedToolsStrictToolFlag, f as withPreparedToolSchemaNormalization, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-BO8rwyAD.mjs";
|
|
20
|
+
import { a as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, c as OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE, f as RESPONSE_FAILED_NO_DETAILS_MESSAGE, o as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, p as isPreviousResponseRejection, s as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY } from "./openai-responses-contracts-DWrfMODE.mjs";
|
|
21
|
+
import { n as isOpenAIResponsesCompactionOutput, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-D6P5oZP5.mjs";
|
|
22
|
+
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
24
23
|
import { createHash, randomUUID } from "node:crypto";
|
|
25
24
|
//#region packages/ai/src/transports/openai-responses-replay.ts
|
|
26
25
|
/** Resolves the assistant message id that can be replayed to OpenAI Responses. */
|
|
@@ -190,6 +189,199 @@ function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
|
|
|
190
189
|
};
|
|
191
190
|
}
|
|
192
191
|
//#endregion
|
|
192
|
+
//#region packages/ai/src/transports/openai-responses-reasoning-update.ts
|
|
193
|
+
function isConfigurationUpdate(value) {
|
|
194
|
+
return isRecord(value) && value.type === "configuration_update" && isRecord(value.reasoning) && typeof value.reasoning.effort === "string";
|
|
195
|
+
}
|
|
196
|
+
function isResponsesReasoningUpdateCompatible(request) {
|
|
197
|
+
const mode = isRecord(request.reasoning) ? request.reasoning.mode : void 0;
|
|
198
|
+
return request.model === "gpt-6-astra" && (mode === void 0 || mode === "standard") && (!isRecord(request.multi_agent) || request.multi_agent.enabled !== true) && request.truncation !== "auto" && (!Array.isArray(request.context_management) || !request.context_management.some((item) => isRecord(item) && item.type === "compaction"));
|
|
199
|
+
}
|
|
200
|
+
function supportsResponsesReasoningUpdate(request) {
|
|
201
|
+
return isResponsesReasoningUpdateCompatible(request) && isRecord(request.reasoning) && typeof request.reasoning.effort === "string";
|
|
202
|
+
}
|
|
203
|
+
function canReferenceResponsesReasoningHistory(previous, request) {
|
|
204
|
+
return !previous.input?.some(isConfigurationUpdate) || isResponsesReasoningUpdateCompatible(request);
|
|
205
|
+
}
|
|
206
|
+
/** Rehydrate input controls only provisionally; continuation must validate the full prefix. */
|
|
207
|
+
function replayResponsesReasoningUpdates(previous, request, previousOutputLength, steering) {
|
|
208
|
+
if (steering !== "required-input" && (!supportsResponsesReasoningUpdate(previous) || !supportsResponsesReasoningUpdate(request)) || !Array.isArray(previous.input) || !Array.isArray(request.input) || request.input.some(isConfigurationUpdate)) return request;
|
|
209
|
+
const input = [...request.input];
|
|
210
|
+
let activeEffort = isRecord(previous.reasoning) ? previous.reasoning.effort : void 0;
|
|
211
|
+
for (const [index, item] of previous.input.entries()) if (isConfigurationUpdate(item)) {
|
|
212
|
+
input.splice(index, 0, item);
|
|
213
|
+
activeEffort = item.reasoning.effort;
|
|
214
|
+
}
|
|
215
|
+
if (steering === "required-input") return input.length === request.input.length ? request : {
|
|
216
|
+
...request,
|
|
217
|
+
input
|
|
218
|
+
};
|
|
219
|
+
if (!isRecord(previous.reasoning) || !isRecord(request.reasoning) || typeof request.reasoning.effort !== "string") return request;
|
|
220
|
+
if (activeEffort !== request.reasoning.effort && steering !== "automatic") {
|
|
221
|
+
const baselineLength = previous.input.length + previousOutputLength;
|
|
222
|
+
const nextUser = input.findIndex((item, index) => index >= baselineLength && "role" in item && item.role === "user");
|
|
223
|
+
if (nextUser === -1) return request;
|
|
224
|
+
input.splice(nextUser, 0, {
|
|
225
|
+
type: "configuration_update",
|
|
226
|
+
reasoning: { effort: request.reasoning.effort }
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (input.length === request.input.length && activeEffort === request.reasoning.effort) return request;
|
|
230
|
+
return {
|
|
231
|
+
...request,
|
|
232
|
+
reasoning: {
|
|
233
|
+
...request.reasoning,
|
|
234
|
+
effort: previous.reasoning.effort
|
|
235
|
+
},
|
|
236
|
+
input
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region packages/ai/src/transports/openai-responses-continuation.ts
|
|
241
|
+
const HTTP_CONTINUATION_IDLE_TTL_MS = 3e5;
|
|
242
|
+
const TURN_HEADERS = /* @__PURE__ */ new Set([
|
|
243
|
+
"traceparent",
|
|
244
|
+
"x-openclaw-turn-id",
|
|
245
|
+
"x-openclaw-turn-attempt"
|
|
246
|
+
]);
|
|
247
|
+
function jsonValuesEqual(left, right) {
|
|
248
|
+
const leftJson = JSON.stringify(left);
|
|
249
|
+
const normalizedLeft = stableStringify(JSON.parse(leftJson));
|
|
250
|
+
const rightJson = JSON.stringify(right);
|
|
251
|
+
return leftJson === rightJson || normalizedLeft === stableStringify(JSON.parse(rightJson));
|
|
252
|
+
}
|
|
253
|
+
function requestWithoutInput(request) {
|
|
254
|
+
const { input: _input, previous_response_id: _previousResponseId, instructions: _instructions, tools: _tools, ...rest } = request;
|
|
255
|
+
if (!isRecord(rest.metadata)) return rest;
|
|
256
|
+
const metadata = Object.fromEntries(Object.entries(rest.metadata).filter(([key]) => key !== "openclaw_turn_id" && key !== "openclaw_turn_attempt"));
|
|
257
|
+
return {
|
|
258
|
+
...rest,
|
|
259
|
+
metadata
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function normalizeAssistantReplayInput(input, fromResponse = false) {
|
|
263
|
+
return input.map((item) => {
|
|
264
|
+
if (!isRecord(item)) return item;
|
|
265
|
+
if (item.type === "reasoning") return { type: "reasoning" };
|
|
266
|
+
if (item.type !== "function_call" && !(item.type === "message" && item.role === "assistant")) return item;
|
|
267
|
+
const { id: _id, status: _status, ...stableItem } = item;
|
|
268
|
+
if (fromResponse && item.type === "function_call") {
|
|
269
|
+
const args = parseJsonObjectPreservingUnsafeIntegers(stableItem.arguments);
|
|
270
|
+
stableItem.arguments = args ? JSON.stringify(args) : stableItem.arguments;
|
|
271
|
+
}
|
|
272
|
+
if (item.type === "message" && Array.isArray(stableItem.content)) stableItem.content = stableItem.content.map((part) => {
|
|
273
|
+
if (!isRecord(part) || part.type !== "output_text") return part;
|
|
274
|
+
const { annotations: _annotations, logprobs: _logprobs, ...stablePart } = part;
|
|
275
|
+
return stablePart;
|
|
276
|
+
});
|
|
277
|
+
return stableItem;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
function responsesContinuationRequestFingerprint(request) {
|
|
281
|
+
const serialized = JSON.stringify(requestWithoutInput(request));
|
|
282
|
+
return sha256Hex(stableStringify(JSON.parse(serialized)));
|
|
283
|
+
}
|
|
284
|
+
function responsesContinuationPrefixFingerprint(input, output = []) {
|
|
285
|
+
const serialized = JSON.stringify([...normalizeAssistantReplayInput(input), ...normalizeAssistantReplayInput(output, true)]);
|
|
286
|
+
return sha256Hex(stableStringify(JSON.parse(serialized)));
|
|
287
|
+
}
|
|
288
|
+
function resolveResponsesContinuationRequest(continuation, request, steering) {
|
|
289
|
+
if (!continuation) return {
|
|
290
|
+
request,
|
|
291
|
+
continuationStatus: "no_previous_response"
|
|
292
|
+
};
|
|
293
|
+
if (request.previous_response_id) return {
|
|
294
|
+
request,
|
|
295
|
+
continuationStatus: "explicit_previous_response_id"
|
|
296
|
+
};
|
|
297
|
+
if (!canReferenceResponsesReasoningHistory(continuation.lastRequest, request)) return {
|
|
298
|
+
request,
|
|
299
|
+
continuationStatus: "request_changed"
|
|
300
|
+
};
|
|
301
|
+
const prepared = replayResponsesReasoningUpdates(continuation.lastRequest, request, continuation.lastResponseItems.length, steering);
|
|
302
|
+
if (steering !== "required-input" && !jsonValuesEqual(requestWithoutInput(prepared), requestWithoutInput(continuation.lastRequest))) return {
|
|
303
|
+
request,
|
|
304
|
+
continuationStatus: "request_changed"
|
|
305
|
+
};
|
|
306
|
+
const currentInput = prepared.input ?? [];
|
|
307
|
+
const previousInput = continuation.lastRequest.input ?? [];
|
|
308
|
+
const baselineLength = previousInput.length + continuation.lastResponseItems.length;
|
|
309
|
+
if (currentInput.length < baselineLength) return {
|
|
310
|
+
request,
|
|
311
|
+
continuationStatus: "history_shorter"
|
|
312
|
+
};
|
|
313
|
+
if (!jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(0, previousInput.length)), normalizeAssistantReplayInput(previousInput)) || !jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(previousInput.length, baselineLength)), normalizeAssistantReplayInput(continuation.lastResponseItems, true))) return {
|
|
314
|
+
request,
|
|
315
|
+
continuationStatus: "history_changed"
|
|
316
|
+
};
|
|
317
|
+
return {
|
|
318
|
+
request: {
|
|
319
|
+
...prepared,
|
|
320
|
+
previous_response_id: continuation.lastResponseId,
|
|
321
|
+
input: currentInput.slice(baselineLength)
|
|
322
|
+
},
|
|
323
|
+
...prepared !== request ? { fullRequest: prepared } : {},
|
|
324
|
+
continuationStatus: "continued"
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
const httpContinuationEntries = /* @__PURE__ */ new Map();
|
|
328
|
+
function deleteHttpContinuationIfOwned(key, entry) {
|
|
329
|
+
if (httpContinuationEntries.get(key) === entry) httpContinuationEntries.delete(key);
|
|
330
|
+
}
|
|
331
|
+
function connectionIdentity(params) {
|
|
332
|
+
const headers = Object.entries(resolveAiTransportHeaderSentinels(params.headers) ?? {}).map(([name, value]) => [name.toLowerCase(), value]).filter(([name]) => !TURN_HEADERS.has(name)).toSorted(([a], [b]) => a.localeCompare(b));
|
|
333
|
+
return sha256Hex(JSON.stringify([
|
|
334
|
+
getAiTransportHost().resolveSecretSentinel(params.apiKey),
|
|
335
|
+
params.baseUrl,
|
|
336
|
+
headers
|
|
337
|
+
]));
|
|
338
|
+
}
|
|
339
|
+
function claimOpenAIResponsesHttpContinuation(params) {
|
|
340
|
+
const key = `${params.sessionId}\0${connectionIdentity(params)}`;
|
|
341
|
+
const previous = httpContinuationEntries.get(key);
|
|
342
|
+
if (previous?.kind === "claimed") return;
|
|
343
|
+
if (previous?.kind === "ready") clearTimeout(previous.idleTimer);
|
|
344
|
+
const claimed = {
|
|
345
|
+
kind: "claimed",
|
|
346
|
+
sessionId: params.sessionId
|
|
347
|
+
};
|
|
348
|
+
httpContinuationEntries.set(key, claimed);
|
|
349
|
+
try {
|
|
350
|
+
const request = previous?.kind === "ready" ? params.request : params.restoreRequest?.() ?? params.request;
|
|
351
|
+
const resolved = resolveResponsesContinuationRequest(previous?.kind === "ready" ? previous.state : void 0, request);
|
|
352
|
+
const fullRequest = resolved.fullRequest ?? request;
|
|
353
|
+
return {
|
|
354
|
+
request: params.request.store === false ? fullRequest : resolved.request,
|
|
355
|
+
fullRequest,
|
|
356
|
+
commit: (effectiveRequest, response) => {
|
|
357
|
+
if (httpContinuationEntries.get(key) !== claimed) return;
|
|
358
|
+
const ready = {
|
|
359
|
+
...claimed,
|
|
360
|
+
kind: "ready",
|
|
361
|
+
state: {
|
|
362
|
+
lastRequest: effectiveRequest,
|
|
363
|
+
lastResponseId: response.id,
|
|
364
|
+
lastResponseItems: response.output
|
|
365
|
+
},
|
|
366
|
+
idleTimer: setTimeout(() => deleteHttpContinuationIfOwned(key, ready), HTTP_CONTINUATION_IDLE_TTL_MS)
|
|
367
|
+
};
|
|
368
|
+
ready.idleTimer.unref?.();
|
|
369
|
+
httpContinuationEntries.set(key, ready);
|
|
370
|
+
},
|
|
371
|
+
release: () => deleteHttpContinuationIfOwned(key, claimed)
|
|
372
|
+
};
|
|
373
|
+
} catch (error) {
|
|
374
|
+
deleteHttpContinuationIfOwned(key, claimed);
|
|
375
|
+
throw error;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
registerSessionResourceCleanup((sessionId) => {
|
|
379
|
+
for (const [key, entry] of httpContinuationEntries) if (!sessionId || entry.sessionId === sessionId) {
|
|
380
|
+
if (entry.kind === "ready") clearTimeout(entry.idleTimer);
|
|
381
|
+
httpContinuationEntries.delete(key);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
//#endregion
|
|
193
385
|
//#region packages/ai/src/transports/openai-responses-input-replay.ts
|
|
194
386
|
function recordResponsesInputReplay(message, replay) {
|
|
195
387
|
if (replay) Object.assign(message, { openclawResponsesInputReplay: replay });
|
|
@@ -608,6 +800,83 @@ function convertProviderResponsesMessages(model, context, allowedToolCallProvide
|
|
|
608
800
|
return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "provider");
|
|
609
801
|
}
|
|
610
802
|
//#endregion
|
|
803
|
+
//#region packages/ai/src/transports/openai-responses-context-usage.ts
|
|
804
|
+
const TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set([
|
|
805
|
+
"openai",
|
|
806
|
+
"opencode",
|
|
807
|
+
"azure-openai-responses",
|
|
808
|
+
"github-copilot"
|
|
809
|
+
]);
|
|
810
|
+
function inputReplay(message) {
|
|
811
|
+
const value = "openclawResponsesInputReplay" in message ? message.openclawResponsesInputReplay : void 0;
|
|
812
|
+
return isRecord(value) ? value : void 0;
|
|
813
|
+
}
|
|
814
|
+
function contextFingerprint(input, output = []) {
|
|
815
|
+
const reasoning = [...input, ...output].flatMap((item) => {
|
|
816
|
+
if (!isRecord(item) || item.type !== "reasoning") return [];
|
|
817
|
+
const { id: _id, status: _status, ...content } = item;
|
|
818
|
+
return [content];
|
|
819
|
+
});
|
|
820
|
+
return sha256Hex(stableStringify({
|
|
821
|
+
prefix: responsesContinuationPrefixFingerprint(input, output),
|
|
822
|
+
reasoning
|
|
823
|
+
}));
|
|
824
|
+
}
|
|
825
|
+
/** Bind measured usage to the admitted replay prefix, without copying its content. */
|
|
826
|
+
function recordResponsesContextUsage(message, model, identity, request, output, projection) {
|
|
827
|
+
const usage = message.usage.contextUsage;
|
|
828
|
+
if (usage?.state !== "available" || !Number.isSafeInteger(usage.totalTokens) || usage.totalTokens <= 0 || message.stopReason === "error" || message.stopReason === "aborted" || message.providerReplay || request.previous_response_id || !Array.isArray(request.input) || !request.input.some((item) => isRecord(item) && item.type === "compaction") || !Array.isArray(output) || output.some((item) => isRecord(item) && item.type === "compaction")) return;
|
|
829
|
+
const replayOutput = (projection === "transport" ? convertResponsesMessages$1 : convertProviderResponsesMessages)(model, { messages: [message] }, TOOL_CALL_PROVIDERS, {
|
|
830
|
+
...identity,
|
|
831
|
+
includeSystemPrompt: false
|
|
832
|
+
}).filter((item) => item.type !== "function_call_output");
|
|
833
|
+
const firstInput = request.input[0];
|
|
834
|
+
const contextUsage = {
|
|
835
|
+
...buildProviderReplayContext(model, identity),
|
|
836
|
+
projection,
|
|
837
|
+
includeSystemPrompt: request.instructions === void 0 && firstInput?.type === "message" && (firstInput.role === "developer" || firstInput.role === "system"),
|
|
838
|
+
prefixHash: contextFingerprint(request.input, replayOutput),
|
|
839
|
+
prefixLength: request.input.length + replayOutput.length,
|
|
840
|
+
promptTokens: usage.promptTokens,
|
|
841
|
+
totalTokens: usage.totalTokens
|
|
842
|
+
};
|
|
843
|
+
Object.assign(message, { openclawResponsesInputReplay: {
|
|
844
|
+
...inputReplay(message),
|
|
845
|
+
contextUsage
|
|
846
|
+
} });
|
|
847
|
+
}
|
|
848
|
+
/** Only matching provider input may replace the conservative local pressure estimate. */
|
|
849
|
+
function resolveResponsesContextUsageBoundary(messages, model, identity, systemPrompt) {
|
|
850
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
851
|
+
const message = messages[index];
|
|
852
|
+
if (!message || !isAssistant(message)) continue;
|
|
853
|
+
const state = inputReplay(message)?.contextUsage;
|
|
854
|
+
const usage = message.usage.contextUsage;
|
|
855
|
+
if (!isRecord(state) || usage?.state !== "available") continue;
|
|
856
|
+
const { projection, prefixHash, prefixLength, promptTokens, totalTokens, includeSystemPrompt } = state;
|
|
857
|
+
if (!isOpenAIResponsesReplayContext(state) || !providerReplayContextMatches(state, buildProviderReplayContext(model, identity)) || message.provider !== model.provider || message.api !== model.api || message.model !== model.id || projection !== "transport" && projection !== "provider" || typeof prefixHash !== "string" || typeof prefixLength !== "number" || !Number.isSafeInteger(prefixLength) || prefixLength <= 0 || promptTokens !== usage.promptTokens || totalTokens !== usage.totalTokens || !Number.isSafeInteger(usage.totalTokens) || usage.totalTokens <= 0) return;
|
|
858
|
+
const input = (projection === "transport" ? convertResponsesMessages$1 : convertProviderResponsesMessages)(model, {
|
|
859
|
+
messages: messages.filter(isProviderMessage),
|
|
860
|
+
systemPrompt
|
|
861
|
+
}, TOOL_CALL_PROVIDERS, {
|
|
862
|
+
...identity,
|
|
863
|
+
includeSystemPrompt: includeSystemPrompt === true
|
|
864
|
+
});
|
|
865
|
+
if (input.length < prefixLength || contextFingerprint(input.slice(0, prefixLength)) !== prefixHash) return;
|
|
866
|
+
return {
|
|
867
|
+
index,
|
|
868
|
+
totalTokens: usage.totalTokens,
|
|
869
|
+
suffix: input.slice(prefixLength)
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
function isAssistant(message) {
|
|
874
|
+
return message.role === "assistant";
|
|
875
|
+
}
|
|
876
|
+
function isProviderMessage(message) {
|
|
877
|
+
return message.role === "user" || message.role === "assistant" || message.role === "toolResult";
|
|
878
|
+
}
|
|
879
|
+
//#endregion
|
|
611
880
|
//#region packages/ai/src/transports/openai-responses-replay-internal.ts
|
|
612
881
|
function isAsyncIterable(value) {
|
|
613
882
|
return (typeof value === "object" && value !== null || typeof value === "function") && Symbol.asyncIterator in value;
|
|
@@ -694,7 +963,7 @@ async function createResponsesStreamWithEncryptedContentRetry(params) {
|
|
|
694
963
|
};
|
|
695
964
|
} catch (error) {
|
|
696
965
|
let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
|
|
697
|
-
if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && error
|
|
966
|
+
if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && isPreviousResponseRejection(error)) {
|
|
698
967
|
const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
|
|
699
968
|
delete request.previous_response_id;
|
|
700
969
|
nextAttempt = {
|
|
@@ -714,43 +983,40 @@ async function createResponsesStreamWithEncryptedContentRetry(params) {
|
|
|
714
983
|
request: params.request,
|
|
715
984
|
...params.initialRejectedCompaction ? { rejectedCompaction: params.initialRejectedCompaction } : {}
|
|
716
985
|
});
|
|
717
|
-
return {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
let
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
if (isRecord(
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
status: failure.status
|
|
733
|
-
});
|
|
734
|
-
}
|
|
986
|
+
return { stream: { async *[Symbol.asyncIterator]() {
|
|
987
|
+
let current = result;
|
|
988
|
+
for (;;) {
|
|
989
|
+
let rejectedEvent;
|
|
990
|
+
try {
|
|
991
|
+
for await (const event of params.wrapStream?.(current) ?? current.stream) {
|
|
992
|
+
if (isRecord(event)) {
|
|
993
|
+
const failure = event.type === "response.failed" && isRecord(event.response) ? event.response.error : event.type === "error" ? event.error ?? event : void 0;
|
|
994
|
+
if (isRecord(failure) && params.canRetryStream?.() === true && isInvalidEncryptedContentError(failure)) {
|
|
995
|
+
rejectedEvent = event;
|
|
996
|
+
const message = typeof failure.message === "string" ? failure.message : "";
|
|
997
|
+
throw Object.assign(new Error(message), {
|
|
998
|
+
code: failure.code,
|
|
999
|
+
status: failure.status
|
|
1000
|
+
});
|
|
735
1001
|
}
|
|
736
|
-
yield event;
|
|
737
1002
|
}
|
|
738
|
-
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
1003
|
+
yield event;
|
|
1004
|
+
}
|
|
1005
|
+
return;
|
|
1006
|
+
} catch (error) {
|
|
1007
|
+
const nextAttempt = params.canRetryStream?.() === true && !params.requestOptions?.signal?.aborted ? await resolveNextResponsesEncryptedContentAttempt(current.attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest }) : void 0;
|
|
1008
|
+
if (!nextAttempt) {
|
|
1009
|
+
if (rejectedEvent !== void 0) {
|
|
1010
|
+
yield rejectedEvent;
|
|
1011
|
+
return;
|
|
747
1012
|
}
|
|
748
|
-
|
|
749
|
-
current = await send(nextAttempt);
|
|
1013
|
+
throw error;
|
|
750
1014
|
}
|
|
1015
|
+
log.warn(`[responses] retrying streamed encrypted content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
|
|
1016
|
+
current = await send(nextAttempt);
|
|
751
1017
|
}
|
|
752
|
-
}
|
|
753
|
-
};
|
|
1018
|
+
}
|
|
1019
|
+
} } };
|
|
754
1020
|
}
|
|
755
1021
|
function resolveAzureOpenAIApiVersion(env = process.env) {
|
|
756
1022
|
return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
|
|
@@ -1291,86 +1557,6 @@ function createResponsesOutputSlotTracker() {
|
|
|
1291
1557
|
};
|
|
1292
1558
|
}
|
|
1293
1559
|
//#endregion
|
|
1294
|
-
//#region packages/ai/src/providers/openai-responses-terminal-usage.ts
|
|
1295
|
-
/**
|
|
1296
|
-
* Canonical mapping for terminal OpenAI Responses events.
|
|
1297
|
-
*
|
|
1298
|
-
* `response.completed`, `response.incomplete`, and `response.failed` are terminal and can carry
|
|
1299
|
-
* usage, so every Responses path finalizes through the helpers here. Keeping one owner prevents
|
|
1300
|
-
* package and managed transports from drifting on token buckets, service-tier pricing, or future
|
|
1301
|
-
* terminal-event semantics.
|
|
1302
|
-
*/
|
|
1303
|
-
function readReportedCount(value) {
|
|
1304
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
1305
|
-
}
|
|
1306
|
-
function readCount(value) {
|
|
1307
|
-
return readReportedCount(value) ?? 0;
|
|
1308
|
-
}
|
|
1309
|
-
/**
|
|
1310
|
-
* Split a terminal usage payload into the priced buckets.
|
|
1311
|
-
*
|
|
1312
|
-
* OpenAI includes cache reads and writes in `input_tokens`, so both are subtracted out of the
|
|
1313
|
-
* billable input bucket. `total_tokens` comes from the payload, but never below the sum of the
|
|
1314
|
-
* split buckets: proxies routinely omit it (reporting 0 would understate the turn), and a payload
|
|
1315
|
-
* whose `cached_tokens` exceeds `input_tokens` clamps the input bucket, leaving the reported total
|
|
1316
|
-
* short of what the buckets actually price.
|
|
1317
|
-
*/
|
|
1318
|
-
function mapResponsesTerminalUsage(usage) {
|
|
1319
|
-
if (!usage) return;
|
|
1320
|
-
const cacheRead = readCount(usage.input_tokens_details?.cached_tokens);
|
|
1321
|
-
const cacheWrite = readCount(usage.input_tokens_details?.cache_write_tokens);
|
|
1322
|
-
const input = Math.max(0, readCount(usage.input_tokens) - cacheRead - cacheWrite);
|
|
1323
|
-
const output = readCount(usage.output_tokens);
|
|
1324
|
-
const bucketTotal = input + output + cacheRead + cacheWrite;
|
|
1325
|
-
const totalTokens = Math.max(bucketTotal, readCount(usage.total_tokens));
|
|
1326
|
-
const reportedInput = readReportedCount(usage.input_tokens);
|
|
1327
|
-
const reportedOutput = readReportedCount(usage.output_tokens);
|
|
1328
|
-
const reportedTotal = readReportedCount(usage.total_tokens);
|
|
1329
|
-
return {
|
|
1330
|
-
input,
|
|
1331
|
-
output,
|
|
1332
|
-
cacheRead,
|
|
1333
|
-
cacheWrite,
|
|
1334
|
-
contextUsage: reportedInput !== void 0 && (reportedOutput !== void 0 || reportedTotal !== void 0 && reportedTotal >= reportedInput) && cacheRead + cacheWrite <= reportedInput ? {
|
|
1335
|
-
state: "available",
|
|
1336
|
-
promptTokens: reportedInput,
|
|
1337
|
-
totalTokens: Math.max(totalTokens, reportedInput + (reportedOutput ?? 0))
|
|
1338
|
-
} : { state: "unavailable" },
|
|
1339
|
-
totalTokens
|
|
1340
|
-
};
|
|
1341
|
-
}
|
|
1342
|
-
/** Reasoning tokens are reported by the agent path only; the package path does not track them. */
|
|
1343
|
-
function readResponsesReasoningTokens(usage) {
|
|
1344
|
-
return asFiniteNumber(usage?.output_tokens_details?.reasoning_tokens);
|
|
1345
|
-
}
|
|
1346
|
-
function mapResponsesTerminalStopReason(status) {
|
|
1347
|
-
if (!status) return "stop";
|
|
1348
|
-
switch (status) {
|
|
1349
|
-
case "completed": return "stop";
|
|
1350
|
-
case "incomplete": return "length";
|
|
1351
|
-
case "failed":
|
|
1352
|
-
case "cancelled": return "error";
|
|
1353
|
-
case "in_progress":
|
|
1354
|
-
case "queued": return "stop";
|
|
1355
|
-
default: throw new Error(`Unhandled stop reason: ${String(status)}`);
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
/**
|
|
1359
|
-
* Resolve the terminal stop reason, including the two overrides every Responses path shares: a
|
|
1360
|
-
* content-filtered turn is a provider error rather than a truncated answer, and a turn that
|
|
1361
|
-
* produced tool calls reports `toolUse` instead of a plain stop.
|
|
1362
|
-
*/
|
|
1363
|
-
function resolveResponsesTerminalStopReason(params) {
|
|
1364
|
-
const status = params.status ?? (params.terminalEventType === "response.incomplete" ? "incomplete" : void 0);
|
|
1365
|
-
if (status === "incomplete" && params.incompleteReason === "content_filter") return {
|
|
1366
|
-
stopReason: "error",
|
|
1367
|
-
errorMessage: "Provider incomplete_reason: content_filter"
|
|
1368
|
-
};
|
|
1369
|
-
const stopReason = mapResponsesTerminalStopReason(status);
|
|
1370
|
-
if (stopReason === "stop" && params.hasToolCall) return { stopReason: "toolUse" };
|
|
1371
|
-
return { stopReason };
|
|
1372
|
-
}
|
|
1373
|
-
//#endregion
|
|
1374
1560
|
//#region packages/ai/src/transports/openai-responses-stream-terminal-internal.ts
|
|
1375
1561
|
function splitToolCallId(id) {
|
|
1376
1562
|
const separator = id.indexOf("|");
|
|
@@ -1387,7 +1573,7 @@ function resolveResponsesToolCallId(item, fallbackId) {
|
|
|
1387
1573
|
return resolvedItemId ? `${generated}|${resolvedItemId}` : generated;
|
|
1388
1574
|
}
|
|
1389
1575
|
function resolveCompletedResponsesToolCall(item, streamed) {
|
|
1390
|
-
if (item.status && item.status !== "completed") throw new
|
|
1576
|
+
if (item.status && item.status !== "completed") throw new IncompleteToolCallError("Responses stream completed with an incomplete terminal tool call");
|
|
1391
1577
|
const streamedName = streamed?.name?.trim() || void 0;
|
|
1392
1578
|
const completedName = typeof item.name === "string" ? item.name.trim() || void 0 : void 0;
|
|
1393
1579
|
if (streamedName && completedName && streamedName !== completedName) throw new Error(`Responses stream changed tool-call function name from ${streamedName} to ${completedName}`);
|
|
@@ -1564,7 +1750,7 @@ function createResponsesTerminalController(params) {
|
|
|
1564
1750
|
};
|
|
1565
1751
|
const finalizeTerminalFacts = (response, responseId = response.id) => {
|
|
1566
1752
|
output.responseId = responseId || output.responseId;
|
|
1567
|
-
output.responseModel = response.model?.trim() || void 0;
|
|
1753
|
+
output.responseModel = options?.resolveResponseModel ? options.resolveResponseModel()?.trim() || void 0 : response.model?.trim() || void 0;
|
|
1568
1754
|
const usage = mapResponsesTerminalUsage(response.usage);
|
|
1569
1755
|
const reasoningTokens = readResponsesReasoningTokens(response.usage);
|
|
1570
1756
|
if (usage) output.usage = {
|
|
@@ -1595,6 +1781,17 @@ function createResponsesTerminalController(params) {
|
|
|
1595
1781
|
});
|
|
1596
1782
|
output.stopReason = terminal.stopReason;
|
|
1597
1783
|
output.errorMessage = terminal.errorMessage;
|
|
1784
|
+
if (terminalEventType === "response.completed" && typeof response.end_turn === "boolean") output.endTurn = response.end_turn;
|
|
1785
|
+
const incompleteReason = response.incomplete_details?.reason;
|
|
1786
|
+
appendAssistantMessageDiagnostic(output, {
|
|
1787
|
+
type: "openai_responses_terminal",
|
|
1788
|
+
timestamp: Date.now(),
|
|
1789
|
+
details: {
|
|
1790
|
+
eventType: terminalEventType,
|
|
1791
|
+
...terminalEventType === "response.incomplete" ? { incompleteReason: incompleteReason === "max_output_tokens" || incompleteReason === "max_messages" || incompleteReason === "content_filter" || incompleteReason === "steered" ? incompleteReason : "unknown" } : {},
|
|
1792
|
+
endTurn: typeof response.end_turn === "boolean" ? response.end_turn : response.end_turn === void 0 ? "absent" : "invalid"
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1598
1795
|
};
|
|
1599
1796
|
return {
|
|
1600
1797
|
finalizeResponse,
|
|
@@ -1810,6 +2007,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1810
2007
|
block: toolCallBlock,
|
|
1811
2008
|
contentIndex,
|
|
1812
2009
|
argumentStreamReliable: true,
|
|
2010
|
+
argumentsStreamed: false,
|
|
1813
2011
|
previewSchedule: createToolArgumentPreviewSchedule(),
|
|
1814
2012
|
...readResponsesToolCallItemIdentity(item)
|
|
1815
2013
|
};
|
|
@@ -1903,6 +2101,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1903
2101
|
const toolCall = streamingToolCalls.resolve(event);
|
|
1904
2102
|
if (toolCall) {
|
|
1905
2103
|
toolCall.block.partialJson += event.delta;
|
|
2104
|
+
toolCall.argumentsStreamed = true;
|
|
1906
2105
|
if (toolCall.previewSchedule(toolCall.block.partialJson.length)) toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
|
|
1907
2106
|
stream.push({
|
|
1908
2107
|
type: "toolcall_delta",
|
|
@@ -1920,6 +2119,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1920
2119
|
toolCall.block.partialJson = doneArguments;
|
|
1921
2120
|
toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
|
|
1922
2121
|
toolCall.argumentStreamReliable = true;
|
|
2122
|
+
toolCall.argumentsStreamed = true;
|
|
1923
2123
|
}
|
|
1924
2124
|
if (doneArguments?.startsWith(previousPartialJson)) {
|
|
1925
2125
|
const delta = doneArguments.slice(previousPartialJson.length);
|
|
@@ -2015,9 +2215,11 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2015
2215
|
if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
|
|
2016
2216
|
const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
|
|
2017
2217
|
if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
|
|
2218
|
+
const streamedArguments = streamingToolCall?.block.partialJson || "";
|
|
2219
|
+
const preferredArguments = streamingToolCall?.argumentStreamReliable && streamingToolCall?.argumentsStreamed && streamedArguments.length > 0 && completedArguments !== void 0 && streamedArguments !== completedArguments && parseJsonObjectPreservingUnsafeIntegers(streamedArguments) !== null ? streamedArguments : completedArguments || streamedArguments;
|
|
2018
2220
|
const validated = resolveCompletedResponsesToolCall(item, {
|
|
2019
2221
|
name: streamingToolCall?.block.name,
|
|
2020
|
-
arguments:
|
|
2222
|
+
arguments: preferredArguments
|
|
2021
2223
|
});
|
|
2022
2224
|
finalizeToolCall(item, readResponsesOutputIndex(event), streamingToolCall, validated);
|
|
2023
2225
|
}
|
|
@@ -2027,7 +2229,10 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2027
2229
|
if (output.errorMessage) throw new Error(output.errorMessage);
|
|
2028
2230
|
resolveCompletedResponsesToolCall(incompleteToolCall);
|
|
2029
2231
|
}
|
|
2030
|
-
if (event.type === "response.incomplete" && streamingToolCalls.hasActive())
|
|
2232
|
+
if (event.type === "response.incomplete" && streamingToolCalls.hasActive()) {
|
|
2233
|
+
if (output.errorMessage) throw new Error(output.errorMessage);
|
|
2234
|
+
throw new IncompleteToolCallError("Responses stream completed with unresolved tool calls");
|
|
2235
|
+
}
|
|
2031
2236
|
if (event.type === "response.completed" || output.stopReason === "length") {
|
|
2032
2237
|
const items = event.response.output ?? [];
|
|
2033
2238
|
const completeToolCall = event.type === "response.completed" ? prepareTerminalToolCalls(items) : void 0;
|
|
@@ -2055,23 +2260,33 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2055
2260
|
//#region packages/ai/src/providers/openai-responses-tools.ts
|
|
2056
2261
|
/** Projects direct provider descriptors before resolving their strict policy. */
|
|
2057
2262
|
function convertResponsesToolPayload(tools, options) {
|
|
2058
|
-
return
|
|
2059
|
-
}
|
|
2060
|
-
/**
|
|
2061
|
-
function
|
|
2062
|
-
const
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2263
|
+
return convertPreparedResponsesTools(prepareOpenAITools(tools), resolveResponsesStrictToolSetting(options), options?.model);
|
|
2264
|
+
}
|
|
2265
|
+
/** The transport has already resolved policy before descriptor projection. */
|
|
2266
|
+
function prepareResponsesTools(tools, strictSetting, model) {
|
|
2267
|
+
const prepared = prepareOpenAITools(tools);
|
|
2268
|
+
return {
|
|
2269
|
+
projection: prepared.projection,
|
|
2270
|
+
tools: convertPreparedResponsesTools(prepared, strictSetting, model)
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
function convertPreparedResponsesTools(prepared, strictSetting, model) {
|
|
2274
|
+
const { projection, schemas } = prepared;
|
|
2275
|
+
return withPreparedToolSchemaNormalization(schemas, () => {
|
|
2276
|
+
const strict = model ? resolveOpenAIStrictToolFlagWithDiagnostics(projection, strictSetting, {
|
|
2277
|
+
transport: "responses",
|
|
2278
|
+
model
|
|
2279
|
+
}) : resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
|
|
2280
|
+
return sortPromptCacheToolsByName(projection.tools).map((tool) => {
|
|
2281
|
+
const result = {
|
|
2282
|
+
type: "function",
|
|
2283
|
+
name: tool.name,
|
|
2284
|
+
description: tool.description,
|
|
2285
|
+
parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model?.compat)
|
|
2286
|
+
};
|
|
2287
|
+
if (strict !== void 0) result.strict = strict;
|
|
2288
|
+
return result;
|
|
2289
|
+
});
|
|
2075
2290
|
});
|
|
2076
2291
|
}
|
|
2077
2292
|
function resolveResponsesStrictToolSetting(options) {
|
|
@@ -2099,19 +2314,6 @@ function applyResponsesServiceTierPricing(usage, serviceTier, model) {
|
|
|
2099
2314
|
usage.cost.cacheWrite *= multiplier;
|
|
2100
2315
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
2101
2316
|
}
|
|
2102
|
-
function resolveResponsesReasoningEffort(model, reasoning) {
|
|
2103
|
-
if (!reasoning) return;
|
|
2104
|
-
const clampedReasoning = model.reasoning && model.thinkingLevelMap?.[reasoning] === void 0 && resolveOpenAIModelReasoningEfforts(model)?.includes(reasoning) ? reasoning : clampThinkingLevel(model, reasoning);
|
|
2105
|
-
return clampedReasoning === "off" ? void 0 : clampedReasoning;
|
|
2106
|
-
}
|
|
2107
|
-
function resolveResponsesRequestReasoningEffort(model, reasoning) {
|
|
2108
|
-
const mapped = model.thinkingLevelMap?.[reasoning === "none" ? "off" : reasoning];
|
|
2109
|
-
if (mapped !== void 0) return mapped ?? void 0;
|
|
2110
|
-
return resolveOpenAIModelReasoningEfforts(model) === void 0 ? reasoning === "off" ? "none" : reasoning : resolveOpenAIReasoningEffortForModel({
|
|
2111
|
-
model,
|
|
2112
|
-
effort: reasoning
|
|
2113
|
-
});
|
|
2114
|
-
}
|
|
2115
2317
|
function applyCommonResponsesParams(params, model, context, options, config) {
|
|
2116
2318
|
if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
|
|
2117
2319
|
if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
|
|
@@ -2121,10 +2323,10 @@ function applyCommonResponsesParams(params, model, context, options, config) {
|
|
|
2121
2323
|
}
|
|
2122
2324
|
if (!model.reasoning) return;
|
|
2123
2325
|
const requestedEffort = options?.reasoningEffort ?? (options?.reasoningSummary ? "medium" : config?.setDefaultReasoningOff ?? true ? "off" : void 0);
|
|
2124
|
-
const effort = requestedEffort === void 0 ? void 0 :
|
|
2326
|
+
const effort = requestedEffort === void 0 ? void 0 : resolveOpenAIRequestReasoning(model, requestedEffort).effort;
|
|
2125
2327
|
if (effort === void 0) return;
|
|
2126
2328
|
params.reasoning = { effort };
|
|
2127
|
-
if (options?.reasoningEffort || options?.reasoningSummary) {
|
|
2329
|
+
if (effort !== "none" && (options?.reasoningEffort || options?.reasoningSummary)) {
|
|
2128
2330
|
params.reasoning.summary = options?.reasoningSummary || "auto";
|
|
2129
2331
|
params.include = ["reasoning.encrypted_content"];
|
|
2130
2332
|
}
|
|
@@ -2158,6 +2360,7 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2158
2360
|
const firstEvent = createFirstStreamEventAbortController(options?.signal);
|
|
2159
2361
|
firstEventAbort = firstEvent;
|
|
2160
2362
|
let started = false;
|
|
2363
|
+
let admittedRequest;
|
|
2161
2364
|
const { stream: hookedOpenAIStream } = await createResponsesStreamWithEncryptedContentRetry({
|
|
2162
2365
|
client,
|
|
2163
2366
|
request: requestParams,
|
|
@@ -2169,25 +2372,28 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2169
2372
|
buildFullHistoryRequest: () => buildRequest("full-history"),
|
|
2170
2373
|
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, options, checkpoint),
|
|
2171
2374
|
canRetryStream: () => output.content.length === 0,
|
|
2172
|
-
wrapStream: ({ stream: openaiStream, response }) =>
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2375
|
+
wrapStream: ({ stream: openaiStream, response, attempt }) => {
|
|
2376
|
+
admittedRequest = attempt.kind === "initial" ? attempt.request : void 0;
|
|
2377
|
+
return withProviderResponseHook({
|
|
2378
|
+
stream: openaiStream,
|
|
2379
|
+
signal: firstEvent.signal,
|
|
2380
|
+
abort: firstEvent.abort,
|
|
2381
|
+
hook: createOpenAIProviderAcceptanceHook(options, response, model),
|
|
2382
|
+
onReady: () => {
|
|
2383
|
+
if (!started) {
|
|
2384
|
+
started = true;
|
|
2385
|
+
stream.push({
|
|
2386
|
+
type: "start",
|
|
2387
|
+
partial: output
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2184
2390
|
}
|
|
2185
|
-
}
|
|
2186
|
-
}
|
|
2391
|
+
});
|
|
2392
|
+
}
|
|
2187
2393
|
});
|
|
2188
2394
|
const firstEventTimeoutMs = getFirstStreamEventTimeoutMs(options);
|
|
2189
2395
|
const onFirstEventTimeout = getFirstStreamEventTimeoutHandler(options);
|
|
2190
|
-
await processResponsesStream(hookedOpenAIStream, output, stream, model, {
|
|
2396
|
+
const terminal = await processResponsesStream(hookedOpenAIStream, output, stream, model, {
|
|
2191
2397
|
...params.processStreamOptions || firstEventTimeoutMs !== void 0 || onFirstEventTimeout !== void 0 ? {
|
|
2192
2398
|
...params.processStreamOptions,
|
|
2193
2399
|
firstEventTimeoutMs: params.processStreamOptions?.firstEventTimeoutMs ?? firstEventTimeoutMs,
|
|
@@ -2200,6 +2406,7 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2200
2406
|
authProfileId: options?.authProfileId
|
|
2201
2407
|
})
|
|
2202
2408
|
});
|
|
2409
|
+
if (terminal && admittedRequest && !options?.signal?.aborted) recordResponsesContextUsage(output, model, options, admittedRequest, terminal.output, "provider");
|
|
2203
2410
|
finalizeTransportStream({
|
|
2204
2411
|
stream,
|
|
2205
2412
|
output,
|
|
@@ -2218,4 +2425,4 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2218
2425
|
}
|
|
2219
2426
|
}
|
|
2220
2427
|
//#endregion
|
|
2221
|
-
export {
|
|
2428
|
+
export { resolveNextResponsesEncryptedContentAttempt as A, responsesContinuationPrefixFingerprint as B, isResponsesTextContentPartType as C, createResponsesStreamWithEncryptedContentRetry as D, commitResponsesEncryptedContentAttempt as E, createOpenAIResponsesAssistantOutput as F, CompactionReplayRefreshRequiredError as G, isConfigurationUpdate as H, recordResponsesInputReplay as I, isOpenAIResponsesReplayContext as J, buildOpenAIResponsesReasoningReplayMetadata as K, responsesInputFingerprint as L, resolveResponsesContextUsageBoundary as M, buildResponsesInputMessage as N, isInvalidEncryptedContentError as O, convertResponsesMessages$1 as P, claimOpenAIResponsesHttpContinuation as R, isAzureResponsesTextDeltaEventType as S, resolveResponsesMessageSnapshotCollapse as T, replayResponsesReasoningUpdates as U, responsesContinuationRequestFingerprint as V, supportsResponsesReasoningUpdate as W, suppressOpenAIResponsesCompaction as X, resolveNewestOpenAIResponsesCompactionReplay as Y, resolveReplayableResponsesMessageId as Z, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as _, runResponsesStreamLifecycle as a, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as b, processResponsesStream as c, logResponsesFailedNoDetails as d, safeDebugValue as f, readResponsesToolCallItemIdentity as g, createResponsesToolCallTracker as h, createResponsesAssistantOutput as i, recordResponsesContextUsage as j, resolveAzureOpenAIApiVersion as k, observeResponsesStream as l, summarizeResponsesPayload as m, applyResponsesServiceTierPricing as n, convertResponsesToolPayload as o, summarizeOpenAITransportError as p, captureOpenAIResponsesCompaction as q, convertResponsesMessages as r, prepareResponsesTools as s, applyCommonResponsesParams as t, ResponsesStreamFailure as u, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as v, isResponsesTextDeltaEventType as w, isAzureResponsesTextDeltaEvent as x, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as y, resolveResponsesContinuationRequest as z };
|