@openclaw/ai 2026.9.4 → 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-C4Qu4H0Z.mjs → anthropic-COtDvgtt.mjs} +10 -11
- package/dist/{anthropic-payload-policy-BZ8umAbk.d.mts → anthropic-payload-policy-5Erq1Nzy.d.mts} +3 -3
- package/dist/{anthropic-stream-reducer-CILWF7JD.mjs → anthropic-stream-reducer-BvdYYWL8.mjs} +47 -43
- package/dist/{api-registry-ByUwIR0e.d.mts → api-registry-Ba2Cv-ut.d.mts} +2 -2
- package/dist/{assistant-output-tLt4H-iQ.mjs → assistant-output-BsEkB-vU.mjs} +1 -1
- package/dist/{azure-openai-responses-BAlqlKKc.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-QuErwCIl.mjs → diagnostics-Dm4bisWG.mjs} +89 -2
- package/dist/diagnostics.d.mts +4 -23
- package/dist/diagnostics.mjs +3 -3
- package/dist/{event-stream-Bt5Y4Pav.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-DPBAOaOW.mjs → google-BuhpRO9r.mjs} +6 -9
- package/dist/{google-messages-6JkpHrhJ.mjs → google-messages-CyWnYlh0.mjs} +3 -3
- package/dist/{google-shared-BvBeW9aq.mjs → google-shared-BT5ZeNer.mjs} +13 -13
- package/dist/{google-vertex-k-TMCAYD.mjs → google-vertex-C7EplRvt.mjs} +5 -8
- package/dist/{host-B8YfDGd4.mjs → host-B4MeUNBc.mjs} +25 -27
- package/dist/{host-4atIX-2V.d.mts → host-FZ1RA_qD.d.mts} +5 -3
- package/dist/{host-policy-Zcg_cNz8.mjs → host-policy-DUnXSx0I.mjs} +1 -1
- package/dist/{index-DdD3qerf.d.mts → index-DaF2QbwS.d.mts} +4 -9
- package/dist/index.d.mts +6 -7
- package/dist/index.mjs +3 -4
- 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 +2 -2
- package/dist/internal/openai-responses-payload-policy.mjs +2 -2
- package/dist/internal/openai.d.mts +10 -53
- package/dist/internal/openai.mjs +11 -9
- package/dist/internal/runtime.d.mts +6 -8
- package/dist/internal/runtime.mjs +5 -9
- package/dist/internal/shared.d.mts +6 -5
- package/dist/internal/shared.mjs +4 -3
- package/dist/internal/tool-schema.d.mts +3 -3
- package/dist/internal/tool-schema.mjs +2 -2
- package/dist/{mistral-CxUZ1jUb.mjs → mistral-moA-mbwl.mjs} +9 -13
- package/dist/{openai-chatgpt-responses-CgO6kZfo.mjs → openai-chatgpt-responses-DWID3EFO.mjs} +73 -29
- package/dist/{openai-completions-yJuk7eis.mjs → openai-completions-DJ1Vm-CD.mjs} +11 -12
- package/dist/{openai-prompt-cache-Bds-n_9Q.mjs → openai-completions-compat-CkwdxTZx.mjs} +5 -50
- package/dist/{openai-completions-compat-eHgh5UPE.d.mts → openai-completions-compat-JE7gqxb9.d.mts} +4 -4
- package/dist/{openai-completions-stream-Da2vvl-S.mjs → openai-completions-stream-Bu98b0Hv.mjs} +94 -96
- package/dist/openai-prompt-cache-1wfaIszn.mjs +46 -0
- package/dist/{openai-prompt-cache-B4eYo2-I.d.mts → openai-prompt-cache-CJ_xEevu.d.mts} +2 -2
- package/dist/{openai-provider-client-S2gCrM2Z.mjs → openai-provider-client-DPo0Hmak.mjs} +2 -2
- package/dist/openai-reasoning-effort-NlFZmfEu.mjs +235 -0
- package/dist/{openai-responses-DaYwH05E.mjs → openai-responses-BejZzQCP.mjs} +8 -12
- package/dist/{openai-responses-compaction-window-CIhBAkkq.mjs → openai-responses-compaction-window-D6P5oZP5.mjs} +20 -62
- package/dist/openai-responses-contracts-DWrfMODE.mjs +81 -0
- package/dist/{openai-responses-contracts-BjBAqAg_.d.mts → openai-responses-contracts-Dflvrfa8.d.mts} +9 -5
- 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-B8RdBPCv.mjs → openai-responses-shared-CwsziD_m.mjs} +385 -178
- 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-9aPuV5YY.mjs → openai-transport-params-DQeuAvBl.mjs} +157 -47
- package/dist/{positive-integer-41zhOdcV.mjs → positive-integer-DtjCkbue.mjs} +1 -1
- package/dist/{provider-error-BA-v_tKd.mjs → provider-error-DDqw9Qda.mjs} +100 -38
- package/dist/{provider-options-Ceqv1OKk.d.mts → provider-options-DprLsWh9.d.mts} +9 -6
- package/dist/{provider-replay-context-CJ_YvcEW.mjs → provider-replay-context-CnUSOwhr.mjs} +1 -1
- package/dist/{provider-transcript-transform-V5YzU9zh.mjs → provider-transcript-transform-BsRAhuWJ.mjs} +1 -1
- package/dist/{provider-transport-turn-state-D5EXOFL2.mjs → provider-transport-turn-state-CkGToCD2.mjs} +1 -1
- package/dist/{provider-types-CVjKjsuq.d.mts → provider-types-CAKRC7N5.d.mts} +3 -3
- package/dist/provider-types.d.mts +5 -6
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +10 -10
- package/dist/{reasoning-tag-text-partitioner-BcR5pztD.mjs → reasoning-tag-text-partitioner-Dy9IO8Dc.mjs} +15 -7
- package/dist/{simple-options-BQbb4yQL.mjs → simple-options-C6cFWj_f.mjs} +5 -3
- package/dist/{usage-cost-BNWbbXav.mjs → src-DeKjbE8I.mjs} +3 -5
- 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-DNvmoWnv.d.mts → transport-stream-shared-BbUkFaHi.d.mts} +4 -4
- package/dist/{transport-stream-shared-zHll9BxO.mjs → transport-stream-shared-D-6FQSHm.mjs} +14 -14
- package/dist/{transport-utils-zrYjICLZ.mjs → transport-utils-1cyq5Y7x.mjs} +3 -3
- package/dist/transports.d.mts +26 -12
- package/dist/transports.mjs +130 -449
- package/dist/{types-Ntv5z2g2.d.mts → types-4_uVs5WH.d.mts} +47 -3
- package/dist/types-DkJfb4W3.d.mts +1 -0
- package/dist/types.d.mts +5 -6
- package/dist/types.mjs +2 -3
- package/dist/{validation-B0t_G2H6.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-C3WGFsum.d.mts +0 -1
- package/dist/openai-responses-contracts-DDOHA62Y.mjs +0 -245
- package/dist/openai-responses-prompt-observer-internal-f8J7wpsk.mjs +0 -32
- package/dist/src-DDmEryvj.mjs +0 -2
- package/dist/tool-schema-json-projection-ClptDdAO.mjs +0 -82
- package/dist/types-DlfwzH3T.d.mts +0 -1
|
@@ -1,23 +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 { M as clampThinkingLevel, _ as isImageWithMediaPayload, d as describeToolResultMediaPlaceholder, j as calculateCost, m as extractToolResultText, n as getAiTransportHost } from "./host-B8YfDGd4.mjs";
|
|
4
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";
|
|
5
7
|
import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import { a as resolveModelSseDebugMode, i as resolveModelPayloadDebugMode, r as emitModelTransportDebug } from "./diagnostics-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-CJ_YvcEW.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";
|
|
15
16
|
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
16
|
-
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-
|
|
17
|
-
import { t as transformProviderMessages } from "./provider-transcript-transform-
|
|
18
|
-
import {
|
|
19
|
-
import { a as
|
|
20
|
-
import { n as isOpenAIResponsesCompactionOutput, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-
|
|
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";
|
|
21
23
|
import { createHash, randomUUID } from "node:crypto";
|
|
22
24
|
//#region packages/ai/src/transports/openai-responses-replay.ts
|
|
23
25
|
/** Resolves the assistant message id that can be replayed to OpenAI Responses. */
|
|
@@ -187,6 +189,199 @@ function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
|
|
|
187
189
|
};
|
|
188
190
|
}
|
|
189
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
|
|
190
385
|
//#region packages/ai/src/transports/openai-responses-input-replay.ts
|
|
191
386
|
function recordResponsesInputReplay(message, replay) {
|
|
192
387
|
if (replay) Object.assign(message, { openclawResponsesInputReplay: replay });
|
|
@@ -605,6 +800,83 @@ function convertProviderResponsesMessages(model, context, allowedToolCallProvide
|
|
|
605
800
|
return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "provider");
|
|
606
801
|
}
|
|
607
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
|
|
608
880
|
//#region packages/ai/src/transports/openai-responses-replay-internal.ts
|
|
609
881
|
function isAsyncIterable(value) {
|
|
610
882
|
return (typeof value === "object" && value !== null || typeof value === "function") && Symbol.asyncIterator in value;
|
|
@@ -691,7 +963,7 @@ async function createResponsesStreamWithEncryptedContentRetry(params) {
|
|
|
691
963
|
};
|
|
692
964
|
} catch (error) {
|
|
693
965
|
let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
|
|
694
|
-
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)) {
|
|
695
967
|
const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
|
|
696
968
|
delete request.previous_response_id;
|
|
697
969
|
nextAttempt = {
|
|
@@ -711,43 +983,40 @@ async function createResponsesStreamWithEncryptedContentRetry(params) {
|
|
|
711
983
|
request: params.request,
|
|
712
984
|
...params.initialRejectedCompaction ? { rejectedCompaction: params.initialRejectedCompaction } : {}
|
|
713
985
|
});
|
|
714
|
-
return {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
let
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
if (isRecord(
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
status: failure.status
|
|
730
|
-
});
|
|
731
|
-
}
|
|
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
|
+
});
|
|
732
1001
|
}
|
|
733
|
-
yield event;
|
|
734
1002
|
}
|
|
735
|
-
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
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;
|
|
744
1012
|
}
|
|
745
|
-
|
|
746
|
-
current = await send(nextAttempt);
|
|
1013
|
+
throw error;
|
|
747
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);
|
|
748
1017
|
}
|
|
749
|
-
}
|
|
750
|
-
};
|
|
1018
|
+
}
|
|
1019
|
+
} } };
|
|
751
1020
|
}
|
|
752
1021
|
function resolveAzureOpenAIApiVersion(env = process.env) {
|
|
753
1022
|
return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
|
|
@@ -1288,86 +1557,6 @@ function createResponsesOutputSlotTracker() {
|
|
|
1288
1557
|
};
|
|
1289
1558
|
}
|
|
1290
1559
|
//#endregion
|
|
1291
|
-
//#region packages/ai/src/providers/openai-responses-terminal-usage.ts
|
|
1292
|
-
/**
|
|
1293
|
-
* Canonical mapping for terminal OpenAI Responses events.
|
|
1294
|
-
*
|
|
1295
|
-
* `response.completed`, `response.incomplete`, and `response.failed` are terminal and can carry
|
|
1296
|
-
* usage, so every Responses path finalizes through the helpers here. Keeping one owner prevents
|
|
1297
|
-
* package and managed transports from drifting on token buckets, service-tier pricing, or future
|
|
1298
|
-
* terminal-event semantics.
|
|
1299
|
-
*/
|
|
1300
|
-
function readReportedCount(value) {
|
|
1301
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
1302
|
-
}
|
|
1303
|
-
function readCount(value) {
|
|
1304
|
-
return readReportedCount(value) ?? 0;
|
|
1305
|
-
}
|
|
1306
|
-
/**
|
|
1307
|
-
* Split a terminal usage payload into the priced buckets.
|
|
1308
|
-
*
|
|
1309
|
-
* OpenAI includes cache reads and writes in `input_tokens`, so both are subtracted out of the
|
|
1310
|
-
* billable input bucket. `total_tokens` comes from the payload, but never below the sum of the
|
|
1311
|
-
* split buckets: proxies routinely omit it (reporting 0 would understate the turn), and a payload
|
|
1312
|
-
* whose `cached_tokens` exceeds `input_tokens` clamps the input bucket, leaving the reported total
|
|
1313
|
-
* short of what the buckets actually price.
|
|
1314
|
-
*/
|
|
1315
|
-
function mapResponsesTerminalUsage(usage) {
|
|
1316
|
-
if (!usage) return;
|
|
1317
|
-
const cacheRead = readCount(usage.input_tokens_details?.cached_tokens);
|
|
1318
|
-
const cacheWrite = readCount(usage.input_tokens_details?.cache_write_tokens);
|
|
1319
|
-
const input = Math.max(0, readCount(usage.input_tokens) - cacheRead - cacheWrite);
|
|
1320
|
-
const output = readCount(usage.output_tokens);
|
|
1321
|
-
const bucketTotal = input + output + cacheRead + cacheWrite;
|
|
1322
|
-
const totalTokens = Math.max(bucketTotal, readCount(usage.total_tokens));
|
|
1323
|
-
const reportedInput = readReportedCount(usage.input_tokens);
|
|
1324
|
-
const reportedOutput = readReportedCount(usage.output_tokens);
|
|
1325
|
-
const reportedTotal = readReportedCount(usage.total_tokens);
|
|
1326
|
-
return {
|
|
1327
|
-
input,
|
|
1328
|
-
output,
|
|
1329
|
-
cacheRead,
|
|
1330
|
-
cacheWrite,
|
|
1331
|
-
contextUsage: reportedInput !== void 0 && (reportedOutput !== void 0 || reportedTotal !== void 0 && reportedTotal >= reportedInput) && cacheRead + cacheWrite <= reportedInput ? {
|
|
1332
|
-
state: "available",
|
|
1333
|
-
promptTokens: reportedInput,
|
|
1334
|
-
totalTokens: Math.max(totalTokens, reportedInput + (reportedOutput ?? 0))
|
|
1335
|
-
} : { state: "unavailable" },
|
|
1336
|
-
totalTokens
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1339
|
-
/** Reasoning tokens are reported by the agent path only; the package path does not track them. */
|
|
1340
|
-
function readResponsesReasoningTokens(usage) {
|
|
1341
|
-
return asFiniteNumber(usage?.output_tokens_details?.reasoning_tokens);
|
|
1342
|
-
}
|
|
1343
|
-
function mapResponsesTerminalStopReason(status) {
|
|
1344
|
-
if (!status) return "stop";
|
|
1345
|
-
switch (status) {
|
|
1346
|
-
case "completed": return "stop";
|
|
1347
|
-
case "incomplete": return "length";
|
|
1348
|
-
case "failed":
|
|
1349
|
-
case "cancelled": return "error";
|
|
1350
|
-
case "in_progress":
|
|
1351
|
-
case "queued": return "stop";
|
|
1352
|
-
default: throw new Error(`Unhandled stop reason: ${String(status)}`);
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
/**
|
|
1356
|
-
* Resolve the terminal stop reason, including the two overrides every Responses path shares: a
|
|
1357
|
-
* content-filtered turn is a provider error rather than a truncated answer, and a turn that
|
|
1358
|
-
* produced tool calls reports `toolUse` instead of a plain stop.
|
|
1359
|
-
*/
|
|
1360
|
-
function resolveResponsesTerminalStopReason(params) {
|
|
1361
|
-
const status = params.status ?? (params.terminalEventType === "response.incomplete" ? "incomplete" : void 0);
|
|
1362
|
-
if (status === "incomplete" && params.incompleteReason === "content_filter") return {
|
|
1363
|
-
stopReason: "error",
|
|
1364
|
-
errorMessage: "Provider incomplete_reason: content_filter"
|
|
1365
|
-
};
|
|
1366
|
-
const stopReason = mapResponsesTerminalStopReason(status);
|
|
1367
|
-
if (stopReason === "stop" && params.hasToolCall) return { stopReason: "toolUse" };
|
|
1368
|
-
return { stopReason };
|
|
1369
|
-
}
|
|
1370
|
-
//#endregion
|
|
1371
1560
|
//#region packages/ai/src/transports/openai-responses-stream-terminal-internal.ts
|
|
1372
1561
|
function splitToolCallId(id) {
|
|
1373
1562
|
const separator = id.indexOf("|");
|
|
@@ -1561,7 +1750,7 @@ function createResponsesTerminalController(params) {
|
|
|
1561
1750
|
};
|
|
1562
1751
|
const finalizeTerminalFacts = (response, responseId = response.id) => {
|
|
1563
1752
|
output.responseId = responseId || output.responseId;
|
|
1564
|
-
output.responseModel = response.model?.trim() || void 0;
|
|
1753
|
+
output.responseModel = options?.resolveResponseModel ? options.resolveResponseModel()?.trim() || void 0 : response.model?.trim() || void 0;
|
|
1565
1754
|
const usage = mapResponsesTerminalUsage(response.usage);
|
|
1566
1755
|
const reasoningTokens = readResponsesReasoningTokens(response.usage);
|
|
1567
1756
|
if (usage) output.usage = {
|
|
@@ -1592,6 +1781,17 @@ function createResponsesTerminalController(params) {
|
|
|
1592
1781
|
});
|
|
1593
1782
|
output.stopReason = terminal.stopReason;
|
|
1594
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
|
+
});
|
|
1595
1795
|
};
|
|
1596
1796
|
return {
|
|
1597
1797
|
finalizeResponse,
|
|
@@ -1807,6 +2007,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1807
2007
|
block: toolCallBlock,
|
|
1808
2008
|
contentIndex,
|
|
1809
2009
|
argumentStreamReliable: true,
|
|
2010
|
+
argumentsStreamed: false,
|
|
1810
2011
|
previewSchedule: createToolArgumentPreviewSchedule(),
|
|
1811
2012
|
...readResponsesToolCallItemIdentity(item)
|
|
1812
2013
|
};
|
|
@@ -1900,6 +2101,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1900
2101
|
const toolCall = streamingToolCalls.resolve(event);
|
|
1901
2102
|
if (toolCall) {
|
|
1902
2103
|
toolCall.block.partialJson += event.delta;
|
|
2104
|
+
toolCall.argumentsStreamed = true;
|
|
1903
2105
|
if (toolCall.previewSchedule(toolCall.block.partialJson.length)) toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
|
|
1904
2106
|
stream.push({
|
|
1905
2107
|
type: "toolcall_delta",
|
|
@@ -1917,6 +2119,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1917
2119
|
toolCall.block.partialJson = doneArguments;
|
|
1918
2120
|
toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
|
|
1919
2121
|
toolCall.argumentStreamReliable = true;
|
|
2122
|
+
toolCall.argumentsStreamed = true;
|
|
1920
2123
|
}
|
|
1921
2124
|
if (doneArguments?.startsWith(previousPartialJson)) {
|
|
1922
2125
|
const delta = doneArguments.slice(previousPartialJson.length);
|
|
@@ -2012,9 +2215,11 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2012
2215
|
if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
|
|
2013
2216
|
const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
|
|
2014
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;
|
|
2015
2220
|
const validated = resolveCompletedResponsesToolCall(item, {
|
|
2016
2221
|
name: streamingToolCall?.block.name,
|
|
2017
|
-
arguments:
|
|
2222
|
+
arguments: preferredArguments
|
|
2018
2223
|
});
|
|
2019
2224
|
finalizeToolCall(item, readResponsesOutputIndex(event), streamingToolCall, validated);
|
|
2020
2225
|
}
|
|
@@ -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 };
|