@openclaw/ai 2026.9.8 → 2026.10.1-beta.1
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 +4 -1
- package/dist/{anthropic-CTXJlfnS.mjs → anthropic-CZv6XFER.mjs} +52 -147
- package/dist/{anthropic-payload-policy-NIPVYXPq.d.mts → anthropic-payload-policy-BhCcgNdm.d.mts} +7 -4
- package/dist/{anthropic-stream-reducer-DrsBCsFY.mjs → anthropic-stream-reducer-BQ1tjd7x.mjs} +369 -233
- package/dist/{api-registry-D-nbmSqr.d.mts → api-registry-DpU0Rj-I.d.mts} +4 -4
- package/dist/{provider-transcript-transform-DjA5Fk2P.mjs → assistant-output-OLm-Oln0.mjs} +17 -17
- package/dist/{assistant-text-phase-C20rxWwP.mjs → assistant-text-phase-Bl1aDCB7.mjs} +2 -8
- package/dist/{azure-openai-responses-BBxv4QVI.mjs → azure-openai-responses-DH7bd3QT.mjs} +12 -17
- package/dist/{azure-openai-responses-client-compat-C7K7QfUE.mjs → azure-openai-responses-client-compat-D0dvJMbZ.mjs} +3 -10
- package/dist/{base64-C1PsYcRQ.mjs → base64-C8CdcsjU.mjs} +3 -45
- package/dist/cloudflare-5qSGvIUH.mjs +39 -0
- package/dist/{diagnostics-CJaB6g8J.mjs → diagnostics-Caj-4RBA.mjs} +19 -37
- package/dist/diagnostics.d.mts +4 -4
- package/dist/diagnostics.mjs +2 -2
- package/dist/{event-stream-vd9UnCAU.mjs → event-stream-C5AbCAaZ.mjs} +29 -1
- package/dist/event-stream-DqDQWqiy.d.mts +1 -0
- package/dist/{event-stream-DOPFYVqs.d.mts → event-stream-DrRM_90c.d.mts} +1 -1
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/{github-copilot-request-facts-BTEBMeOv.mjs → github-copilot-request-facts-DEE6gcB9.mjs} +3 -1
- package/dist/{google-B3HEK0Ag.mjs → google-1WLOtb8w.mjs} +12 -9
- package/dist/{google-interactions-vMlEfPAA.mjs → google-interactions-wrnE6MLw.mjs} +39 -49
- package/dist/{google-messages-Dz2dAnGo.mjs → google-messages-BwPPycw6.mjs} +11 -17
- package/dist/{google-shared-B58i3c8H.mjs → google-shared-Eql1OMPU.mjs} +5 -6
- package/dist/{google-vertex-DYFXzEbh.mjs → google-vertex-0LrlRoO3.mjs} +11 -11
- package/dist/{host-rxlNaBwm.d.mts → host-BinBeGcQ.d.mts} +12 -4
- package/dist/{host-DwBmNMCC.mjs → host-DCW52iHe.mjs} +57 -9
- package/dist/{host-policy-wK-ay_RK.mjs → host-policy-B3jc4Rpn.mjs} +9 -2
- package/dist/{index-D6KsSE74.d.mts → index-a8e_oKnu.d.mts} +7 -5
- package/dist/index.d.mts +23 -7
- package/dist/index.mjs +7 -7
- package/dist/internal/anthropic.d.mts +6 -6
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/google-model-family.mjs +1 -1
- package/dist/internal/openai-completions-compat.d.mts +1 -1
- package/dist/internal/openai-completions-compat.mjs +1 -1
- package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
- package/dist/internal/openai-responses-payload-policy.mjs +2 -2
- package/dist/internal/openai.d.mts +14 -10
- package/dist/internal/openai.mjs +12 -12
- package/dist/internal/runtime.d.mts +18 -9
- package/dist/internal/runtime.mjs +9 -9
- package/dist/internal/shared.d.mts +6 -4
- package/dist/internal/shared.mjs +6 -6
- package/dist/internal/tool-schema.mjs +1 -1
- package/dist/json-schema-Bp07Qui3.mjs +22 -0
- package/dist/{llm-request-activity-BjtkplhG.mjs → llm-request-activity-D8f_oxHj.mjs} +1 -2
- package/dist/{mistral-7wDWcjfF.mjs → mistral-DSt4vQAO.mjs} +18 -29
- package/dist/number-coercion-V8-BhME4.mjs +47 -0
- package/dist/{openai-chatgpt-responses-Bc7NZrQR.mjs → openai-chatgpt-responses-BC2x0Oqx.mjs} +215 -164
- package/dist/openai-completions-DNyHnXKg.mjs +25 -0
- package/dist/{openai-completions-compat-qJjmqQ71.d.mts → openai-completions-compat-BYdYpXhU.d.mts} +3 -3
- package/dist/{openai-completions-compat-BJf57ZxN.mjs → openai-completions-compat-BdmlhD4u.mjs} +30 -23
- package/dist/{openai-completions-stream-dju_5F3P.mjs → openai-completions-transport-DWM2mQDB.mjs} +389 -76
- package/dist/{openai-prompt-cache-CouErLh7.d.mts → openai-prompt-cache-45-AH_xv.d.mts} +2 -2
- package/dist/{openai-prompt-cache-BTMs80_O.mjs → openai-prompt-cache-I8YQTzf8.mjs} +1 -1
- package/dist/{openai-responses-compaction-replay-DiYn-gFM.d.mts → openai-responses-compaction-replay-BClApUIf.d.mts} +4 -4
- package/dist/{openai-responses-compaction-window-CYGCjAQz.mjs → openai-responses-compaction-window-m878aVpU.mjs} +25 -83
- package/dist/{openai-reasoning-effort-C_0p3psG.mjs → openai-responses-contracts-BKu8O7l4.mjs} +103 -4
- package/dist/{openai-responses-contracts-D1iZ0njF.d.mts → openai-responses-contracts-Br5IIw_h.d.mts} +16 -5
- package/dist/openai-responses-prompt-observer-internal-CCg7B6l4.mjs +32 -0
- package/dist/{openai-responses-shared-CIEHiKx7.mjs → openai-responses-shared-C7oVyjED.mjs} +297 -312
- package/dist/{openai-responses-terminal-usage-BE7lf7nW.d.mts → openai-responses-terminal-usage-DgImcyJu.d.mts} +2 -2
- package/dist/{openai-responses-DbPe3-Py.mjs → openai-responses-uZ5oWSp7.mjs} +12 -21
- package/dist/{openai-tool-schema-vsl-cE-n.mjs → openai-tool-schema-DYNePiF8.mjs} +66 -36
- package/dist/{openai-transport-params-DyFJ4cgR.mjs → openai-transport-params-JFsnIyto.mjs} +25 -30
- package/dist/openai-web-search-tools-Cfu0uLyN.mjs +14 -0
- package/dist/{positive-integer-CjN5OJbH.mjs → positive-integer-CwLi8LUL.mjs} +1 -1
- package/dist/{provider-error-CwT_j2v0.mjs → provider-error-DQBE1bUQ.mjs} +17 -28
- package/dist/{provider-options-Df7ov0K1.d.mts → provider-options-D5ABCV_l.d.mts} +2 -2
- package/dist/{provider-replay-context-Bs5aWE1d.mjs → provider-replay-context-C7Bmi84a.mjs} +6 -2
- package/dist/{provider-transport-turn-state-Dw7OtYUs.mjs → provider-transport-turn-state-_M2kLdUE.mjs} +25 -3
- package/dist/{provider-types-d4XnoZMd.d.mts → provider-types-F8Mqc9Ma.d.mts} +3 -3
- package/dist/provider-types.d.mts +6 -6
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +14 -26
- package/dist/{reasoning-tag-text-partitioner-B6FIIBt6.mjs → reasoning-tag-text-partitioner-Ju9VpUGl.mjs} +23 -37
- package/dist/required-api-key-D4kn3252.mjs +9 -0
- package/dist/sanitize-unicode-CjDG6jJx.d.mts +5 -0
- package/dist/{session-affinity-Bcunsn4I.mjs → session-affinity-DA4WHv1h.mjs} +2 -6
- package/dist/session-resources-D1wgDQ8C.mjs +40 -0
- package/dist/{simple-options-BkDPMuxw.mjs → simple-options-BkKTXxhp.mjs} +7 -11
- package/dist/{src-H4aXcFuX.mjs → src-B0NIt2UK.mjs} +7 -4
- package/dist/stream-DSdzKsDK.mjs +275 -0
- package/dist/{stream-first-event-timeout-B9o0S4SZ.mjs → stream-first-event-timeout-D9ZmL_s9.mjs} +3 -3
- package/dist/{string-coerce-fsri9iCu.mjs → string-coerce-CtgOVOSv.mjs} +5 -1
- package/dist/{string-normalization-J9ZiLfGO.mjs → string-normalization-PN10hf6d.mjs} +1 -1
- package/dist/{transport-utils-CqXzku3R.mjs → text-signature-MLwfi6fq.mjs} +18 -18
- package/dist/{transport-stream-shared-yYhXa4kX.d.mts → transport-stream-shared-BcAKh2XH.d.mts} +6 -19
- package/dist/{transport-stream-shared-BU5pwY6W.mjs → transport-stream-shared-CxXXz_Dd.mjs} +171 -56
- package/dist/transports.d.mts +22 -23
- package/dist/transports.mjs +251 -495
- package/dist/types-BuiEBM3u.d.mts +1 -0
- package/dist/types-CQc6JNG4.mjs +69 -0
- package/dist/{types-CLLR3eB4.d.mts → types-DvzmWW8J.d.mts} +58 -6
- package/dist/types.d.mts +6 -6
- package/dist/types.mjs +5 -5
- package/dist/usage-CJH5D6Ea.mjs +19 -0
- package/dist/{validation-Cat2wQsc.d.mts → validation-B3lQt_VE.d.mts} +1 -1
- package/dist/{validation-BFZc40Ig.mjs → validation-DbqlIfDn.mjs} +15 -30
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +4 -4
- package/dist/cache-retention-0x979a5V.mjs +0 -12
- package/dist/event-stream-CMQfX_yr.d.mts +0 -1
- package/dist/github-copilot-headers-B37TB3rB.mjs +0 -30
- package/dist/openai-completions-CHnwIV-W.mjs +0 -188
- package/dist/openai-provider-client-G8Otsq2Q.mjs +0 -24
- package/dist/openai-responses-contracts-CLxnqS9p.mjs +0 -81
- package/dist/openai-responses-prompt-observer-internal-BX3QTNSv.mjs +0 -198
- package/dist/sanitize-unicode-BZiVbGwK.d.mts +0 -24
- package/dist/session-resources-CkR4WWy1.mjs +0 -21
- package/dist/stream-DDsCBgd-.mjs +0 -68
- package/dist/types-CB-_vNyI.d.mts +0 -1
- package/dist/types-LFWwv0cF.mjs +0 -8
|
@@ -1,24 +1,25 @@
|
|
|
1
|
+
import "./src-B0NIt2UK.mjs";
|
|
2
|
+
import { _ as runtimeContextContentToText, f as hasRuntimeContextMarker, p as isRuntimeContextMessage } from "./types-CQc6JNG4.mjs";
|
|
1
3
|
import { o as readProviderRefusalReview, t as appendAssistantMessageDiagnostic } from "./diagnostics-DzrF1h4J.mjs";
|
|
2
|
-
import { r as appendAssistantThinking } from "./event-stream-
|
|
4
|
+
import { r as appendAssistantThinking } from "./event-stream-C5AbCAaZ.mjs";
|
|
3
5
|
import { o as isRecord } from "./record-coerce-CNDovvft.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { C as
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { t as
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import { a as
|
|
19
|
-
import { a as
|
|
20
|
-
import { n as isOpenAIResponsesCompactionOutput, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-
|
|
21
|
-
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
6
|
+
import { a as normalizeOptionalString, c as readStringValue, o as normalizeStringifiedOptionalString } from "./string-coerce-CtgOVOSv.mjs";
|
|
7
|
+
import { N as isImageWithMediaPayload, O as calculateCost, a as resolveAiTransportHeaderSentinels, r as getAiTransportHost } from "./host-DCW52iHe.mjs";
|
|
8
|
+
import { D as supportsOpenAITemperature, a as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, c as OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE, f as RESPONSE_FAILED_NO_DETAILS_MESSAGE, g as responsesServiceTierObserver, o as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, p as isPreviousResponseRejection, s as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY } from "./openai-responses-contracts-BKu8O7l4.mjs";
|
|
9
|
+
import { n as getSessionResourceOwnerId, r as registerSessionResourceCleanup } from "./session-resources-D1wgDQ8C.mjs";
|
|
10
|
+
import { o as truncateUtf16Safe, s as stableStringify } from "./provider-error-DQBE1bUQ.mjs";
|
|
11
|
+
import { a as resolveModelSseDebugMode, d as isResponsesProviderTool, g as resolveResponsesTerminalStopReason, h as readResponsesReasoningTokens, i as resolveModelPayloadDebugMode, l as ResponsesOutputIdentityError, m as mapResponsesTerminalUsage, r as emitModelTransportDebug, u as hasOnlyResponsesFunctionTools } from "./diagnostics-Caj-4RBA.mjs";
|
|
12
|
+
import { o as redactSensitiveText, t as encodeTextSignatureV1 } from "./text-signature-MLwfi6fq.mjs";
|
|
13
|
+
import { c as resolveOpenAIResponsesTextFormat, i as resolveOpenAICompletionsCompat } from "./openai-completions-compat-BdmlhD4u.mjs";
|
|
14
|
+
import { A as shortHash, C as parseJsonObjectPreservingUnsafeIntegers, E as createToolArgumentPreviewSchedule, O as parseStreamingJson, S as withProviderResponseHook, _ as sanitizeNonEmptyTransportPayloadText, b as transportAbortError, c as failTransportStream, d as iterateModelStream, g as parseTerminalToolCallArguments, t as IncompleteToolCallError, u as finalizeTransportStream, v as sanitizeTransportPayloadText } from "./transport-stream-shared-CxXXz_Dd.mjs";
|
|
15
|
+
import { C as stripSystemPromptCacheBoundary, D as sortPromptCacheToolsByName, d as describeToolResultMediaPlaceholder, m as extractToolResultText, s as prepareModelRequestBody } from "./simple-options-BkKTXxhp.mjs";
|
|
16
|
+
import { A as redactIdentifier, C as log, d as prepareOpenAITools, h as resolveOpenAIRequestReasoning, j as sha256Hex, u as resolveOpenAIStrictToolFlagWithDiagnostics, y as createOpenAIProviderAcceptanceHook } from "./openai-transport-params-JFsnIyto.mjs";
|
|
17
|
+
import { n as isProviderReplayContext, r as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-C7Bmi84a.mjs";
|
|
18
|
+
import { n as transformProviderMessages } from "./assistant-output-OLm-Oln0.mjs";
|
|
19
|
+
import { t as notifyLlmRequestActivity } from "./llm-request-activity-D8f_oxHj.mjs";
|
|
20
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-D9ZmL_s9.mjs";
|
|
21
|
+
import { a as resolveOpenAIProjectedToolsStrictToolFlag, f as withPreparedToolSchemaNormalization, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-DYNePiF8.mjs";
|
|
22
|
+
import { n as isOpenAIResponsesCompactionOutput, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-m878aVpU.mjs";
|
|
22
23
|
import { randomUUID } from "node:crypto";
|
|
23
24
|
//#region packages/ai/src/transports/openai-responses-replay.ts
|
|
24
25
|
/** Resolves the assistant message id that can be replayed to OpenAI Responses. */
|
|
@@ -90,10 +91,6 @@ function shouldNormalizeOpenAIResponsesToolCallId(id) {
|
|
|
90
91
|
//#region packages/ai/src/transports/openai-responses-compaction-replay.ts
|
|
91
92
|
const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE = "openai-responses-compaction-suppression";
|
|
92
93
|
const OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA = "rejected";
|
|
93
|
-
function isOpenAIResponsesReplayContext(value) {
|
|
94
|
-
if (!isRecord(value)) return false;
|
|
95
|
-
return typeof value.provider === "string" && typeof value.api === "string" && typeof value.model === "string" && (value.baseUrlHash === void 0 || typeof value.baseUrlHash === "string") && (value.sessionHash === void 0 || typeof value.sessionHash === "string") && (value.authProfileHash === void 0 || typeof value.authProfileHash === "string");
|
|
96
|
-
}
|
|
97
94
|
function isOpenAIResponsesCompactionState(state) {
|
|
98
95
|
if (typeof state.baseUrlHash !== "string" || state.v !== 1) return false;
|
|
99
96
|
if (state.type === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_TYPE) return state.data === OPENAI_RESPONSES_COMPACTION_SUPPRESSION_DATA;
|
|
@@ -101,7 +98,7 @@ function isOpenAIResponsesCompactionState(state) {
|
|
|
101
98
|
return state.type === "openai-responses-compaction" && typeof state.data === "string" && state.data.length > 0 && (state.id === void 0 || typeof state.id === "string") && (state.replayIndex === void 0 || typeof state.replayIndex === "number" && Number.isSafeInteger(state.replayIndex) && state.replayIndex >= 0);
|
|
102
99
|
}
|
|
103
100
|
function readOpenAIResponsesCompactionReplayState(value) {
|
|
104
|
-
return isRecord(value) &&
|
|
101
|
+
return isRecord(value) && isProviderReplayContext(value) && isOpenAIResponsesCompactionState(value) ? value : void 0;
|
|
105
102
|
}
|
|
106
103
|
function captureOpenAIResponsesCompaction(output, item, boundary, model, captureMetadata, compactedOutput) {
|
|
107
104
|
const metadata = captureMetadata ?? buildOpenAIResponsesReasoningReplayMetadata(model);
|
|
@@ -293,7 +290,9 @@ function replayResponsesReasoningUpdates(previous, request, previousOutputLength
|
|
|
293
290
|
}
|
|
294
291
|
//#endregion
|
|
295
292
|
//#region packages/ai/src/transports/openai-responses-continuation.ts
|
|
296
|
-
const HTTP_CONTINUATION_IDLE_TTL_MS =
|
|
293
|
+
const HTTP_CONTINUATION_IDLE_TTL_MS = 54e5;
|
|
294
|
+
const MAX_HTTP_CONTINUATION_READY_ENTRIES = 1e3;
|
|
295
|
+
const MAX_HTTP_CONTINUATION_RETAINED_BYTES = 67108864;
|
|
297
296
|
const TURN_HEADERS = /* @__PURE__ */ new Set([
|
|
298
297
|
"traceparent",
|
|
299
298
|
"x-openclaw-turn-id",
|
|
@@ -539,8 +538,27 @@ function resolveResponsesContinuationRequest(continuation, request, steering) {
|
|
|
539
538
|
};
|
|
540
539
|
}
|
|
541
540
|
const httpContinuationEntries = /* @__PURE__ */ new Map();
|
|
541
|
+
const readyHttpContinuationEntries = /* @__PURE__ */ new Map();
|
|
542
|
+
let httpContinuationRetainedBytes = 0;
|
|
542
543
|
function deleteHttpContinuationIfOwned(key, entry) {
|
|
543
|
-
if (httpContinuationEntries.get(key)
|
|
544
|
+
if (httpContinuationEntries.get(key) !== entry) return;
|
|
545
|
+
if (entry.kind === "ready") {
|
|
546
|
+
clearTimeout(entry.idleTimer);
|
|
547
|
+
httpContinuationRetainedBytes -= entry.retainedBytes;
|
|
548
|
+
readyHttpContinuationEntries.delete(key);
|
|
549
|
+
}
|
|
550
|
+
httpContinuationEntries.delete(key);
|
|
551
|
+
}
|
|
552
|
+
function evictReadyEntriesForCapacity(pendingBytes) {
|
|
553
|
+
for (;;) {
|
|
554
|
+
const overCapacity = readyHttpContinuationEntries.size >= MAX_HTTP_CONTINUATION_READY_ENTRIES;
|
|
555
|
+
const overBudget = httpContinuationRetainedBytes + pendingBytes > MAX_HTTP_CONTINUATION_RETAINED_BYTES;
|
|
556
|
+
if (!overCapacity && !overBudget) return;
|
|
557
|
+
const oldest = readyHttpContinuationEntries.entries().next();
|
|
558
|
+
if (oldest.done) return;
|
|
559
|
+
const [oldestKey, oldestEntry] = oldest.value;
|
|
560
|
+
deleteHttpContinuationIfOwned(oldestKey, oldestEntry);
|
|
561
|
+
}
|
|
544
562
|
}
|
|
545
563
|
function connectionIdentity(params) {
|
|
546
564
|
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));
|
|
@@ -551,13 +569,15 @@ function connectionIdentity(params) {
|
|
|
551
569
|
]));
|
|
552
570
|
}
|
|
553
571
|
function claimOpenAIResponsesHttpContinuation(params) {
|
|
554
|
-
const
|
|
572
|
+
const owner = getAiTransportHost();
|
|
573
|
+
const key = `${getSessionResourceOwnerId(owner)}\0${params.sessionId}\0${connectionIdentity(params)}`;
|
|
555
574
|
const previous = httpContinuationEntries.get(key);
|
|
556
575
|
if (previous?.kind === "claimed") return;
|
|
557
|
-
if (previous?.kind === "ready")
|
|
576
|
+
if (previous?.kind === "ready") deleteHttpContinuationIfOwned(key, previous);
|
|
558
577
|
const claimed = {
|
|
559
578
|
kind: "claimed",
|
|
560
|
-
sessionId: params.sessionId
|
|
579
|
+
sessionId: params.sessionId,
|
|
580
|
+
owner
|
|
561
581
|
};
|
|
562
582
|
httpContinuationEntries.set(key, claimed);
|
|
563
583
|
try {
|
|
@@ -569,14 +589,25 @@ function claimOpenAIResponsesHttpContinuation(params) {
|
|
|
569
589
|
fullRequest,
|
|
570
590
|
commit: (effectiveRequest, response, dispatchedPreviousResponseId) => {
|
|
571
591
|
if (httpContinuationEntries.get(key) !== claimed) return;
|
|
592
|
+
const state = recordResponsesContinuationState(previous?.kind === "ready" ? previous.state : void 0, effectiveRequest, response, previous?.kind === "ready" && dispatchedPreviousResponseId === previous.state.lastResponseId);
|
|
593
|
+
const retainedBytes = Buffer.byteLength(JSON.stringify(state), "utf8");
|
|
594
|
+
if (httpContinuationEntries.get(key) !== claimed) return;
|
|
595
|
+
if (retainedBytes > MAX_HTTP_CONTINUATION_RETAINED_BYTES) {
|
|
596
|
+
deleteHttpContinuationIfOwned(key, claimed);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
evictReadyEntriesForCapacity(retainedBytes);
|
|
572
600
|
const ready = {
|
|
573
601
|
...claimed,
|
|
574
602
|
kind: "ready",
|
|
575
|
-
state
|
|
576
|
-
idleTimer: setTimeout(() => deleteHttpContinuationIfOwned(key, ready), HTTP_CONTINUATION_IDLE_TTL_MS)
|
|
603
|
+
state,
|
|
604
|
+
idleTimer: setTimeout(() => deleteHttpContinuationIfOwned(key, ready), HTTP_CONTINUATION_IDLE_TTL_MS),
|
|
605
|
+
retainedBytes
|
|
577
606
|
};
|
|
578
607
|
ready.idleTimer.unref?.();
|
|
608
|
+
httpContinuationRetainedBytes += retainedBytes;
|
|
579
609
|
httpContinuationEntries.set(key, ready);
|
|
610
|
+
readyHttpContinuationEntries.set(key, ready);
|
|
580
611
|
},
|
|
581
612
|
release: () => deleteHttpContinuationIfOwned(key, claimed)
|
|
582
613
|
};
|
|
@@ -585,20 +616,21 @@ function claimOpenAIResponsesHttpContinuation(params) {
|
|
|
585
616
|
throw error;
|
|
586
617
|
}
|
|
587
618
|
}
|
|
588
|
-
registerSessionResourceCleanup((sessionId) => {
|
|
589
|
-
for (const [key, entry] of httpContinuationEntries) if (!sessionId || entry.sessionId === sessionId)
|
|
590
|
-
if (entry.kind === "ready") clearTimeout(entry.idleTimer);
|
|
591
|
-
httpContinuationEntries.delete(key);
|
|
592
|
-
}
|
|
619
|
+
registerSessionResourceCleanup((sessionId, owner) => {
|
|
620
|
+
for (const [key, entry] of httpContinuationEntries) if ((!owner || entry.owner === owner) && (!sessionId || entry.sessionId === sessionId)) deleteHttpContinuationIfOwned(key, entry);
|
|
593
621
|
});
|
|
594
622
|
//#endregion
|
|
595
623
|
//#region packages/ai/src/transports/openai-responses-input-replay.ts
|
|
596
624
|
function recordResponsesInputReplay(message, replay) {
|
|
597
625
|
if (replay) Object.assign(message, { openclawResponsesInputReplay: replay });
|
|
598
626
|
}
|
|
599
|
-
function
|
|
627
|
+
function readResponsesInputReplayState(message) {
|
|
600
628
|
const replay = "openclawResponsesInputReplay" in message ? message.openclawResponsesInputReplay : void 0;
|
|
601
|
-
|
|
629
|
+
return isRecord(replay) ? replay : void 0;
|
|
630
|
+
}
|
|
631
|
+
function readResponsesInputReplay(message) {
|
|
632
|
+
const replay = readResponsesInputReplayState(message);
|
|
633
|
+
if (replay && typeof replay.afterResponseId === "string" && Array.isArray(replay.before) && replay.before.every((item) => typeof item === "string") && Array.isArray(replay.after) && replay.after.every((item) => typeof item === "string")) return {
|
|
602
634
|
afterResponseId: replay.afterResponseId,
|
|
603
635
|
before: replay.before,
|
|
604
636
|
after: replay.after
|
|
@@ -650,6 +682,10 @@ function createResponsesInputReplay(model) {
|
|
|
650
682
|
}
|
|
651
683
|
//#endregion
|
|
652
684
|
//#region packages/ai/src/transports/openai-responses-replay-messages-internal.ts
|
|
685
|
+
function resolveResponsesInstructionRole(model) {
|
|
686
|
+
const supportsDeveloperRole = !isRecord(model.compat) || model.compat.supportsDeveloperRole !== false;
|
|
687
|
+
return model.reasoning && supportsDeveloperRole ? "developer" : "system";
|
|
688
|
+
}
|
|
653
689
|
function stripEncryptedReasoningContentFields(value) {
|
|
654
690
|
if (!value || typeof value !== "object") return {
|
|
655
691
|
value,
|
|
@@ -695,7 +731,7 @@ function stripEncryptedReasoningContentFields(value) {
|
|
|
695
731
|
};
|
|
696
732
|
}
|
|
697
733
|
function isOpenAIResponsesReasoningReplayMetadata(value) {
|
|
698
|
-
if (!
|
|
734
|
+
if (!isProviderReplayContext(value)) return false;
|
|
699
735
|
const record = value;
|
|
700
736
|
return record.v === 1 && record.source === "openai-responses";
|
|
701
737
|
}
|
|
@@ -726,13 +762,6 @@ function normalizeResponsesReplayItemId(id, prefix) {
|
|
|
726
762
|
if (id.length <= 64) return id;
|
|
727
763
|
return `${prefix}_${shortHash(id)}`;
|
|
728
764
|
}
|
|
729
|
-
function encodeTextSignatureV1(id, phase) {
|
|
730
|
-
return JSON.stringify({
|
|
731
|
-
v: 1,
|
|
732
|
-
id,
|
|
733
|
-
...phase ? { phase } : {}
|
|
734
|
-
});
|
|
735
|
-
}
|
|
736
765
|
function orderResponsesAsyncToolResults(source) {
|
|
737
766
|
const turnKey = (message) => {
|
|
738
767
|
const id = message.turnId || message.responseId;
|
|
@@ -821,18 +850,14 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
821
850
|
const sanitized = sanitizeIdPart(part);
|
|
822
851
|
return (sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized).replace(/_+$/, "");
|
|
823
852
|
};
|
|
824
|
-
const buildForeignResponsesItemId = (itemId) => {
|
|
825
|
-
const normalized = `fc_${shortHash(itemId)}`;
|
|
826
|
-
return normalized.length > 64 ? normalized.slice(0, 64) : normalized;
|
|
827
|
-
};
|
|
853
|
+
const buildForeignResponsesItemId = (itemId) => `fc_${shortHash(itemId)}`;
|
|
828
854
|
const buildSameProviderCopilotResponsesItemId = (itemId) => {
|
|
829
855
|
const sanitized = sanitizeIdPart(itemId);
|
|
830
856
|
const candidate = sanitized.startsWith("fc_") ? sanitized : `fc_${sanitized}`;
|
|
831
857
|
return candidate.length > 64 ? buildForeignResponsesItemId(itemId) : candidate;
|
|
832
858
|
};
|
|
833
859
|
const normalizeToolCallId = (id, _targetModel, source) => {
|
|
834
|
-
if (!allowedToolCallProviders.has(model.provider)) return normalizeIdPart(id);
|
|
835
|
-
if (!id.includes("|")) return normalizeIdPart(id);
|
|
860
|
+
if (!allowedToolCallProviders.has(model.provider) || !id.includes("|")) return normalizeIdPart(id);
|
|
836
861
|
const separatorIndex = id.indexOf("|");
|
|
837
862
|
const callId = id.slice(0, separatorIndex);
|
|
838
863
|
const itemId = id.slice(separatorIndex + 1);
|
|
@@ -851,13 +876,13 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
851
876
|
preserveUnframedToolResults: replayPlan.preserveUnframedToolResults
|
|
852
877
|
});
|
|
853
878
|
const transformedMessages = orderResponsesAsyncToolResults(transformMessages(replayPlan.messages));
|
|
854
|
-
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model
|
|
879
|
+
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(resolveResponsesInstructionRole(model), [{
|
|
855
880
|
type: "input_text",
|
|
856
881
|
text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt))
|
|
857
882
|
}]));
|
|
858
883
|
if (replayPlan.compactedWindow) messages.push(...replayPlan.compactedWindow);
|
|
859
884
|
let replayMessages = replayPlan.compaction ? [replayPlan.compaction, ...transformedMessages] : transformedMessages;
|
|
860
|
-
const isCarrier = (message) => "role" in message && message
|
|
885
|
+
const isCarrier = (message) => "role" in message && hasRuntimeContextMarker(message);
|
|
861
886
|
if (replayMessages.some(isCarrier)) {
|
|
862
887
|
const anchored = [];
|
|
863
888
|
let insertionIndex = replayPlan.compactedWindow ? 0 : void 0;
|
|
@@ -878,7 +903,11 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
878
903
|
messages.push(msg);
|
|
879
904
|
continue;
|
|
880
905
|
}
|
|
881
|
-
if (msg.
|
|
906
|
+
if (isRuntimeContextMessage(msg)) messages.push(buildResponsesInputMessage(resolveResponsesInstructionRole(model), [{
|
|
907
|
+
type: "input_text",
|
|
908
|
+
text: sanitizeTransportPayloadText(runtimeContextContentToText(msg.content))
|
|
909
|
+
}]));
|
|
910
|
+
else if (msg.role === "user") {
|
|
882
911
|
if (typeof msg.content === "string") messages.push(buildResponsesInputMessage("user", [{
|
|
883
912
|
type: "input_text",
|
|
884
913
|
text: sanitizeTransportPayloadText(msg.content)
|
|
@@ -1004,10 +1033,6 @@ const TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set([
|
|
|
1004
1033
|
"azure-openai-responses",
|
|
1005
1034
|
"github-copilot"
|
|
1006
1035
|
]);
|
|
1007
|
-
function inputReplay(message) {
|
|
1008
|
-
const value = "openclawResponsesInputReplay" in message ? message.openclawResponsesInputReplay : void 0;
|
|
1009
|
-
return isRecord(value) ? value : void 0;
|
|
1010
|
-
}
|
|
1011
1036
|
function contextFingerprint(input, output = []) {
|
|
1012
1037
|
const reasoning = [...input, ...output].flatMap((item) => {
|
|
1013
1038
|
if (!isRecord(item) || item.type !== "reasoning") return [];
|
|
@@ -1038,7 +1063,7 @@ function recordResponsesContextUsage(message, model, identity, request, output,
|
|
|
1038
1063
|
totalTokens: usage.totalTokens
|
|
1039
1064
|
};
|
|
1040
1065
|
Object.assign(message, { openclawResponsesInputReplay: {
|
|
1041
|
-
...
|
|
1066
|
+
...readResponsesInputReplayState(message),
|
|
1042
1067
|
contextUsage
|
|
1043
1068
|
} });
|
|
1044
1069
|
}
|
|
@@ -1047,11 +1072,11 @@ function resolveResponsesContextUsageBoundary(messages, model, identity, systemP
|
|
|
1047
1072
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
1048
1073
|
const message = messages[index];
|
|
1049
1074
|
if (!message || !isAssistant(message)) continue;
|
|
1050
|
-
const state =
|
|
1075
|
+
const state = readResponsesInputReplayState(message)?.contextUsage;
|
|
1051
1076
|
const usage = message.usage.contextUsage;
|
|
1052
1077
|
if (!isRecord(state) || usage?.state !== "available") continue;
|
|
1053
1078
|
const { projection, prefixHash, prefixLength, promptTokens, totalTokens, includeSystemPrompt } = state;
|
|
1054
|
-
if (!
|
|
1079
|
+
if (!isProviderReplayContext(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;
|
|
1055
1080
|
const input = (projection === "transport" ? convertResponsesMessages : convertProviderResponsesMessages)(model, {
|
|
1056
1081
|
messages: messages.filter(isProviderMessage),
|
|
1057
1082
|
systemPrompt
|
|
@@ -1081,10 +1106,7 @@ function stringifyUnknown(value, fallback = "") {
|
|
|
1081
1106
|
return fallback;
|
|
1082
1107
|
}
|
|
1083
1108
|
function safeDebugValue(value) {
|
|
1084
|
-
if (typeof value === "string") return value;
|
|
1085
|
-
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
1086
|
-
if (value === null) return "null";
|
|
1087
|
-
if (value === void 0) return "undefined";
|
|
1109
|
+
if (value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return String(value);
|
|
1088
1110
|
return Array.isArray(value) ? "array" : typeof value;
|
|
1089
1111
|
}
|
|
1090
1112
|
function responseInputTextChars(input) {
|
|
@@ -1116,13 +1138,7 @@ function responseInputItemShape(input) {
|
|
|
1116
1138
|
}).join(",") || "none";
|
|
1117
1139
|
}
|
|
1118
1140
|
function summarizeResponsesCompactionItems(input) {
|
|
1119
|
-
|
|
1120
|
-
"compactionItems=0",
|
|
1121
|
-
"compactionIdHashes=none",
|
|
1122
|
-
"compactionPayloadHashes=none",
|
|
1123
|
-
"compactionInputIndexes=none"
|
|
1124
|
-
];
|
|
1125
|
-
const compactions = input.flatMap((item, inputIndex) => {
|
|
1141
|
+
const compactions = (Array.isArray(input) ? input : []).flatMap((item, inputIndex) => {
|
|
1126
1142
|
if (!isRecord(item) || item.type !== "compaction") return [];
|
|
1127
1143
|
return [{
|
|
1128
1144
|
idHash: typeof item.id === "string" ? sha256Hex(item.id) : void 0,
|
|
@@ -1170,7 +1186,7 @@ function stringifyRedactedPayload(value) {
|
|
|
1170
1186
|
try {
|
|
1171
1187
|
const encoded = JSON.stringify(value, (key, child) => key === "encrypted_content" ? "<opaque data omitted>" : child);
|
|
1172
1188
|
if (!encoded) return "<empty>";
|
|
1173
|
-
const redacted = redactSensitiveText(encoded
|
|
1189
|
+
const redacted = redactSensitiveText(encoded);
|
|
1174
1190
|
return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
|
|
1175
1191
|
} catch {
|
|
1176
1192
|
return "<unserializable>";
|
|
@@ -1189,85 +1205,51 @@ const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
|
|
|
1189
1205
|
"provider_error",
|
|
1190
1206
|
"error_details"
|
|
1191
1207
|
];
|
|
1192
|
-
function readResponseFailedString(record, key) {
|
|
1193
|
-
return stringifyUnknown(record?.[key]);
|
|
1194
|
-
}
|
|
1195
1208
|
function buildResponsesFailedEventSummary(message, responseId, code, observation) {
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1209
|
+
return {
|
|
1210
|
+
message,
|
|
1211
|
+
...responseId ? { responseId } : {},
|
|
1212
|
+
...code ? { code } : {},
|
|
1213
|
+
...observation ? { observation } : {}
|
|
1214
|
+
};
|
|
1201
1215
|
}
|
|
1202
1216
|
function isResponseFailedIdentifierKey(key) {
|
|
1203
1217
|
const normalized = key.replace(/[-_\s]/g, "").toLowerCase();
|
|
1204
|
-
return normalized
|
|
1205
|
-
}
|
|
1206
|
-
function collectResponseFailedIdentifierHashes(
|
|
1207
|
-
const
|
|
1208
|
-
const
|
|
1209
|
-
const
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
const
|
|
1219
|
-
if (
|
|
1220
|
-
|
|
1221
|
-
continue;
|
|
1222
|
-
}
|
|
1223
|
-
collectResponseFailedIdentifierHashes(item, {
|
|
1224
|
-
path: `${path}[${index}]`,
|
|
1225
|
-
depth: depth + 1,
|
|
1226
|
-
identifierKey,
|
|
1227
|
-
out,
|
|
1228
|
-
seen
|
|
1229
|
-
});
|
|
1230
|
-
}
|
|
1231
|
-
return out;
|
|
1232
|
-
}
|
|
1233
|
-
for (const [key, child] of Object.entries(value)) {
|
|
1234
|
-
if (out.length >= 12) break;
|
|
1235
|
-
const childPath = path ? `${path}.${key}` : key;
|
|
1236
|
-
const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
|
|
1237
|
-
if (isResponseFailedIdentifierKey(key) && childString) {
|
|
1238
|
-
out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
|
|
1239
|
-
continue;
|
|
1218
|
+
return normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
|
|
1219
|
+
}
|
|
1220
|
+
function collectResponseFailedIdentifierHashes(input) {
|
|
1221
|
+
const out = [];
|
|
1222
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1223
|
+
const visit = (value, path, depth, identifierKey) => {
|
|
1224
|
+
if (out.length >= 12 || depth > 4 || !value || typeof value !== "object" || seen.has(value)) return;
|
|
1225
|
+
seen.add(value);
|
|
1226
|
+
const entries = Array.isArray(value) ? value.entries() : Object.entries(value);
|
|
1227
|
+
for (const [key, child] of entries) {
|
|
1228
|
+
if (out.length >= 12 || typeof key === "number" && key >= 8) break;
|
|
1229
|
+
const childPath = typeof key === "number" ? `${path}[${key}]` : path ? `${path}.${key}` : key;
|
|
1230
|
+
const childIdentifierKey = typeof key === "number" ? identifierKey : key;
|
|
1231
|
+
const isIdentifier = isResponseFailedIdentifierKey(childIdentifierKey);
|
|
1232
|
+
const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
|
|
1233
|
+
if (isIdentifier && childString) out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
|
|
1234
|
+
else visit(child, childPath, depth + 1, isIdentifier ? childIdentifierKey : "");
|
|
1240
1235
|
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
depth: depth + 1,
|
|
1244
|
-
identifierKey: isResponseFailedIdentifierKey(key) ? key : void 0,
|
|
1245
|
-
out,
|
|
1246
|
-
seen
|
|
1247
|
-
});
|
|
1248
|
-
}
|
|
1236
|
+
};
|
|
1237
|
+
visit(input, "", 0, "");
|
|
1249
1238
|
return out;
|
|
1250
1239
|
}
|
|
1251
|
-
function redactResponseFailedDiagnosticValue(
|
|
1252
|
-
const
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
const out = {};
|
|
1265
|
-
for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
|
|
1266
|
-
key: childKey,
|
|
1267
|
-
depth: depth + 1,
|
|
1268
|
-
seen
|
|
1269
|
-
});
|
|
1270
|
-
return out;
|
|
1240
|
+
function redactResponseFailedDiagnosticValue(input) {
|
|
1241
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
1242
|
+
const redact = (value, key, depth) => {
|
|
1243
|
+
if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
|
|
1244
|
+
if (depth > 6 || !value || typeof value !== "object") return value;
|
|
1245
|
+
if (seen.has(value)) return "<circular>";
|
|
1246
|
+
seen.add(value);
|
|
1247
|
+
if (Array.isArray(value)) return value.slice(0, 16).map((item) => redact(item, key, depth + 1));
|
|
1248
|
+
const out = {};
|
|
1249
|
+
for (const [childKey, child] of Object.entries(value)) out[childKey] = redact(child, childKey, depth + 1);
|
|
1250
|
+
return out;
|
|
1251
|
+
};
|
|
1252
|
+
return redact(input, "", 0);
|
|
1271
1253
|
}
|
|
1272
1254
|
function buildResponsesFailedFailureFields(response) {
|
|
1273
1255
|
if (!response) return {};
|
|
@@ -1279,10 +1261,10 @@ function buildResponsesFailedNoDetailsObservation(event, model, response = isRec
|
|
|
1279
1261
|
const failureFields = redactResponseFailedDiagnosticValue(buildResponsesFailedFailureFields(response));
|
|
1280
1262
|
const metadataKeys = isRecord(response?.metadata) ? Object.keys(response.metadata).toSorted() : [];
|
|
1281
1263
|
const responsePreview = {
|
|
1282
|
-
id:
|
|
1283
|
-
status:
|
|
1284
|
-
model:
|
|
1285
|
-
object:
|
|
1264
|
+
id: stringifyUnknown(response?.id),
|
|
1265
|
+
status: stringifyUnknown(response?.status),
|
|
1266
|
+
model: stringifyUnknown(response?.model),
|
|
1267
|
+
object: stringifyUnknown(response?.object),
|
|
1286
1268
|
failureFields,
|
|
1287
1269
|
metadataKeys
|
|
1288
1270
|
};
|
|
@@ -1309,14 +1291,14 @@ function summarizeResponsesFailedNoDetailsObservation(observation) {
|
|
|
1309
1291
|
}
|
|
1310
1292
|
function normalizeResponsesFailedEvent(event, model) {
|
|
1311
1293
|
const response = isRecord(event.response) ? event.response : void 0;
|
|
1312
|
-
const responseId =
|
|
1294
|
+
const responseId = stringifyUnknown(response?.id) || void 0;
|
|
1313
1295
|
const error = isRecord(response?.error) ? response.error : void 0;
|
|
1314
1296
|
if (error) {
|
|
1315
|
-
const code =
|
|
1316
|
-
const message =
|
|
1297
|
+
const code = stringifyUnknown(error.code).trim();
|
|
1298
|
+
const message = stringifyUnknown(error.message).trim();
|
|
1317
1299
|
if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId, code || void 0);
|
|
1318
1300
|
}
|
|
1319
|
-
const incompleteReason =
|
|
1301
|
+
const incompleteReason = stringifyUnknown((isRecord(response?.incomplete_details) ? response.incomplete_details : void 0)?.reason);
|
|
1320
1302
|
if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
|
|
1321
1303
|
return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, void 0, buildResponsesFailedNoDetailsObservation(event, model, response));
|
|
1322
1304
|
}
|
|
@@ -1556,123 +1538,6 @@ function resolveResponsesMessageSnapshotCollapse(params) {
|
|
|
1556
1538
|
return { kind: "keep" };
|
|
1557
1539
|
}
|
|
1558
1540
|
//#endregion
|
|
1559
|
-
//#region packages/ai/src/providers/openai-responses-tool-call-tracker.ts
|
|
1560
|
-
function readOutputIndex(event) {
|
|
1561
|
-
return typeof event.output_index === "number" && Number.isInteger(event.output_index) && event.output_index >= 0 ? event.output_index : void 0;
|
|
1562
|
-
}
|
|
1563
|
-
function readEventIdentity(event) {
|
|
1564
|
-
return { itemId: normalizeOptionalString(event.item_id) };
|
|
1565
|
-
}
|
|
1566
|
-
function readResponsesToolCallItemIdentity(item) {
|
|
1567
|
-
return {
|
|
1568
|
-
itemId: normalizeOptionalString(item.id),
|
|
1569
|
-
callId: normalizeOptionalString(item.call_id)
|
|
1570
|
-
};
|
|
1571
|
-
}
|
|
1572
|
-
function createResponsesToolCallTracker() {
|
|
1573
|
-
const indexedCalls = /* @__PURE__ */ new Map();
|
|
1574
|
-
const unindexedCalls = /* @__PURE__ */ new Set();
|
|
1575
|
-
const identitiesConflict = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId !== identity.itemId || state.callId && identity.callId && state.callId !== identity.callId);
|
|
1576
|
-
const sharesIdentity = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId === identity.itemId || state.callId && identity.callId && state.callId === identity.callId);
|
|
1577
|
-
const adoptIdentity = (state, identity) => {
|
|
1578
|
-
state.itemId ??= identity.itemId;
|
|
1579
|
-
state.callId ??= identity.callId;
|
|
1580
|
-
return state;
|
|
1581
|
-
};
|
|
1582
|
-
const resolveCompatible = (candidates, identity, allowUnmatchedIdentity) => {
|
|
1583
|
-
const uniqueCandidates = [...new Set(candidates)];
|
|
1584
|
-
if (!identity.itemId && !identity.callId) return allowUnmatchedIdentity && uniqueCandidates.length === 1 ? uniqueCandidates.at(0) : void 0;
|
|
1585
|
-
const compatible = uniqueCandidates.filter((state) => !identitiesConflict(state, identity));
|
|
1586
|
-
const matches = compatible.filter((state) => sharesIdentity(state, identity));
|
|
1587
|
-
const matched = matches.length === 1 ? matches.at(0) : void 0;
|
|
1588
|
-
if (matched) return adoptIdentity(matched, identity);
|
|
1589
|
-
const soleCompatible = allowUnmatchedIdentity && uniqueCandidates.length === 1 && compatible.length === 1 && matches.length === 0 ? compatible.at(0) : void 0;
|
|
1590
|
-
return soleCompatible ? adoptIdentity(soleCompatible, identity) : void 0;
|
|
1591
|
-
};
|
|
1592
|
-
return {
|
|
1593
|
-
register(event, state) {
|
|
1594
|
-
const outputIndex = readOutputIndex(event);
|
|
1595
|
-
if (outputIndex === void 0) {
|
|
1596
|
-
unindexedCalls.add(state);
|
|
1597
|
-
return;
|
|
1598
|
-
}
|
|
1599
|
-
if (indexedCalls.has(outputIndex)) throw new Error(`Responses stream reused active tool-call output index ${outputIndex}`);
|
|
1600
|
-
state.outputIndex = outputIndex;
|
|
1601
|
-
indexedCalls.set(outputIndex, state);
|
|
1602
|
-
},
|
|
1603
|
-
resolve(event, identity = readEventIdentity(event), allowUnmatchedIdentity = true) {
|
|
1604
|
-
const outputIndex = readOutputIndex(event);
|
|
1605
|
-
if (outputIndex !== void 0) {
|
|
1606
|
-
const indexed = indexedCalls.get(outputIndex);
|
|
1607
|
-
if (indexed) {
|
|
1608
|
-
if (indexed.callId && identity.callId && indexed.callId !== identity.callId) return;
|
|
1609
|
-
return adoptIdentity(indexed, identity);
|
|
1610
|
-
}
|
|
1611
|
-
const unindexed = resolveCompatible(unindexedCalls, identity, allowUnmatchedIdentity);
|
|
1612
|
-
if (unindexed) {
|
|
1613
|
-
unindexedCalls.delete(unindexed);
|
|
1614
|
-
unindexed.outputIndex = outputIndex;
|
|
1615
|
-
indexedCalls.set(outputIndex, unindexed);
|
|
1616
|
-
}
|
|
1617
|
-
return unindexed;
|
|
1618
|
-
}
|
|
1619
|
-
return resolveCompatible([...indexedCalls.values(), ...unindexedCalls], identity, allowUnmatchedIdentity);
|
|
1620
|
-
},
|
|
1621
|
-
forget(toolCall) {
|
|
1622
|
-
for (const [outputIndex, tracked] of indexedCalls) if (tracked === toolCall) indexedCalls.delete(outputIndex);
|
|
1623
|
-
unindexedCalls.delete(toolCall);
|
|
1624
|
-
},
|
|
1625
|
-
markArgumentsUnreliable() {
|
|
1626
|
-
for (const toolCall of /* @__PURE__ */ new Set([...indexedCalls.values(), ...unindexedCalls])) toolCall.argumentStreamReliable = false;
|
|
1627
|
-
},
|
|
1628
|
-
hasActive() {
|
|
1629
|
-
return indexedCalls.size > 0 || unindexedCalls.size > 0;
|
|
1630
|
-
},
|
|
1631
|
-
hasExactlyActive(expected) {
|
|
1632
|
-
const active = /* @__PURE__ */ new Set([...indexedCalls.values(), ...unindexedCalls]);
|
|
1633
|
-
return active.size === expected.length && expected.every((state) => active.has(state));
|
|
1634
|
-
}
|
|
1635
|
-
};
|
|
1636
|
-
}
|
|
1637
|
-
//#endregion
|
|
1638
|
-
//#region packages/ai/src/transports/openai-responses-stream-observer-internal.ts
|
|
1639
|
-
const STRING_DELTA_EVENTS = /* @__PURE__ */ new Set([
|
|
1640
|
-
"response.function_call_arguments.delta",
|
|
1641
|
-
"response.output_text.delta",
|
|
1642
|
-
"response.reasoning_summary_text.delta",
|
|
1643
|
-
"response.reasoning_text.delta",
|
|
1644
|
-
"response.refusal.delta",
|
|
1645
|
-
"response.text.delta"
|
|
1646
|
-
]);
|
|
1647
|
-
async function* adaptResponsesStream(stream, signal) {
|
|
1648
|
-
for await (const event of iterateModelStream(stream, signal)) {
|
|
1649
|
-
if (!isRecord(event) || typeof event.type !== "string") throw new Error("Responses stream delivered a malformed event without a string type");
|
|
1650
|
-
if (STRING_DELTA_EVENTS.has(event.type) && typeof event.delta !== "string") throw new Error(`Responses stream delivered malformed ${event.type} delta`);
|
|
1651
|
-
if ((event.type === "response.output_item.added" || event.type === "response.output_item.done") && !isRecord(event.item)) throw new Error(`Responses stream delivered malformed ${event.type} item`);
|
|
1652
|
-
if ((event.type === "response.created" || event.type === "response.completed" || event.type === "response.incomplete" || event.type === "response.failed") && !isRecord(event.response)) throw new Error(`Responses stream delivered malformed ${event.type} response`);
|
|
1653
|
-
yield event;
|
|
1654
|
-
}
|
|
1655
|
-
}
|
|
1656
|
-
async function* observeResponsesStream(stream, model, requestStartedAt) {
|
|
1657
|
-
const startedAt = Date.now();
|
|
1658
|
-
const eventTypes = /* @__PURE__ */ new Map();
|
|
1659
|
-
const debugMode = resolveModelSseDebugMode();
|
|
1660
|
-
let eventCount = 0;
|
|
1661
|
-
try {
|
|
1662
|
-
for await (const event of stream) {
|
|
1663
|
-
const type = isRecord(event) && typeof event.type === "string" ? event.type : "unknown";
|
|
1664
|
-
eventCount += 1;
|
|
1665
|
-
eventTypes.set(type, (eventTypes.get(type) ?? 0) + 1);
|
|
1666
|
-
if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - (requestStartedAt ?? startedAt)} headersToEventMs=${Date.now() - startedAt} type=${type}`);
|
|
1667
|
-
if (debugMode === "peek" && eventCount <= 5) emitModelTransportDebug(log, `[responses] event_peek provider=${model.provider} api=${model.api} model=${model.id} index=${eventCount} type=${type} event=${stringifyRedactedEvent(event)}`);
|
|
1668
|
-
yield event;
|
|
1669
|
-
}
|
|
1670
|
-
} finally {
|
|
1671
|
-
const types = [...eventTypes].map(([type, count]) => `${type}:${count}`).join(",");
|
|
1672
|
-
emitModelTransportDebug(log, `[responses] stream_done provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - startedAt} events=${eventCount} types=${types}`);
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
//#endregion
|
|
1676
1541
|
//#region packages/ai/src/transports/openai-responses-stream-slots-internal.ts
|
|
1677
1542
|
function createResponsesOutputTracker(params) {
|
|
1678
1543
|
const outputs = /* @__PURE__ */ new Map();
|
|
@@ -1794,6 +1659,121 @@ function createResponsesOutputSlotTracker() {
|
|
|
1794
1659
|
};
|
|
1795
1660
|
}
|
|
1796
1661
|
//#endregion
|
|
1662
|
+
//#region packages/ai/src/providers/openai-responses-tool-call-tracker.ts
|
|
1663
|
+
function readEventIdentity(event) {
|
|
1664
|
+
return { itemId: normalizeOptionalString(event.item_id) };
|
|
1665
|
+
}
|
|
1666
|
+
function readResponsesToolCallItemIdentity(item) {
|
|
1667
|
+
return {
|
|
1668
|
+
itemId: normalizeOptionalString(item.id),
|
|
1669
|
+
callId: normalizeOptionalString(item.call_id)
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
function createResponsesToolCallTracker() {
|
|
1673
|
+
const indexedCalls = /* @__PURE__ */ new Map();
|
|
1674
|
+
const unindexedCalls = /* @__PURE__ */ new Set();
|
|
1675
|
+
const identitiesConflict = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId !== identity.itemId || state.callId && identity.callId && state.callId !== identity.callId);
|
|
1676
|
+
const sharesIdentity = (state, identity) => Boolean(state.itemId && identity.itemId && state.itemId === identity.itemId || state.callId && identity.callId && state.callId === identity.callId);
|
|
1677
|
+
const adoptIdentity = (state, identity) => {
|
|
1678
|
+
state.itemId ??= identity.itemId;
|
|
1679
|
+
state.callId ??= identity.callId;
|
|
1680
|
+
return state;
|
|
1681
|
+
};
|
|
1682
|
+
const resolveCompatible = (candidates, identity, allowUnmatchedIdentity) => {
|
|
1683
|
+
const uniqueCandidates = [...new Set(candidates)];
|
|
1684
|
+
if (!identity.itemId && !identity.callId) return allowUnmatchedIdentity && uniqueCandidates.length === 1 ? uniqueCandidates.at(0) : void 0;
|
|
1685
|
+
const compatible = uniqueCandidates.filter((state) => !identitiesConflict(state, identity));
|
|
1686
|
+
const matches = compatible.filter((state) => sharesIdentity(state, identity));
|
|
1687
|
+
const matched = matches.length === 1 ? matches.at(0) : allowUnmatchedIdentity && uniqueCandidates.length === 1 ? compatible.at(0) : void 0;
|
|
1688
|
+
return matched ? adoptIdentity(matched, identity) : void 0;
|
|
1689
|
+
};
|
|
1690
|
+
return {
|
|
1691
|
+
register(event, state) {
|
|
1692
|
+
const outputIndex = readResponsesOutputIndex(event);
|
|
1693
|
+
if (outputIndex === void 0) {
|
|
1694
|
+
unindexedCalls.add(state);
|
|
1695
|
+
return;
|
|
1696
|
+
}
|
|
1697
|
+
if (indexedCalls.has(outputIndex)) throw new Error(`Responses stream reused active tool-call output index ${outputIndex}`);
|
|
1698
|
+
state.outputIndex = outputIndex;
|
|
1699
|
+
indexedCalls.set(outputIndex, state);
|
|
1700
|
+
},
|
|
1701
|
+
resolve(event, identity = readEventIdentity(event), allowUnmatchedIdentity = true) {
|
|
1702
|
+
const outputIndex = readResponsesOutputIndex(event);
|
|
1703
|
+
if (outputIndex !== void 0) {
|
|
1704
|
+
const indexed = indexedCalls.get(outputIndex);
|
|
1705
|
+
if (indexed) {
|
|
1706
|
+
if (indexed.callId && identity.callId && indexed.callId !== identity.callId) return;
|
|
1707
|
+
return adoptIdentity(indexed, identity);
|
|
1708
|
+
}
|
|
1709
|
+
const unindexed = resolveCompatible(unindexedCalls, identity, allowUnmatchedIdentity);
|
|
1710
|
+
if (unindexed) {
|
|
1711
|
+
unindexedCalls.delete(unindexed);
|
|
1712
|
+
unindexed.outputIndex = outputIndex;
|
|
1713
|
+
indexedCalls.set(outputIndex, unindexed);
|
|
1714
|
+
}
|
|
1715
|
+
return unindexed;
|
|
1716
|
+
}
|
|
1717
|
+
return resolveCompatible([...indexedCalls.values(), ...unindexedCalls], identity, allowUnmatchedIdentity);
|
|
1718
|
+
},
|
|
1719
|
+
forget(toolCall) {
|
|
1720
|
+
for (const [outputIndex, tracked] of indexedCalls) if (tracked === toolCall) indexedCalls.delete(outputIndex);
|
|
1721
|
+
unindexedCalls.delete(toolCall);
|
|
1722
|
+
},
|
|
1723
|
+
markArgumentsUnreliable() {
|
|
1724
|
+
for (const toolCall of /* @__PURE__ */ new Set([...indexedCalls.values(), ...unindexedCalls])) toolCall.argumentStreamReliable = false;
|
|
1725
|
+
},
|
|
1726
|
+
hasActive() {
|
|
1727
|
+
return indexedCalls.size > 0 || unindexedCalls.size > 0;
|
|
1728
|
+
},
|
|
1729
|
+
values() {
|
|
1730
|
+
return [.../* @__PURE__ */ new Set([...indexedCalls.values(), ...unindexedCalls])];
|
|
1731
|
+
},
|
|
1732
|
+
hasExactlyActive(expected) {
|
|
1733
|
+
const active = /* @__PURE__ */ new Set([...indexedCalls.values(), ...unindexedCalls]);
|
|
1734
|
+
return active.size === expected.length && expected.every((state) => active.has(state));
|
|
1735
|
+
}
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
//#endregion
|
|
1739
|
+
//#region packages/ai/src/transports/openai-responses-stream-observer-internal.ts
|
|
1740
|
+
const STRING_DELTA_EVENTS = /* @__PURE__ */ new Set([
|
|
1741
|
+
"response.function_call_arguments.delta",
|
|
1742
|
+
"response.output_text.delta",
|
|
1743
|
+
"response.reasoning_summary_text.delta",
|
|
1744
|
+
"response.reasoning_text.delta",
|
|
1745
|
+
"response.refusal.delta",
|
|
1746
|
+
"response.text.delta"
|
|
1747
|
+
]);
|
|
1748
|
+
async function* adaptResponsesStream(stream, signal) {
|
|
1749
|
+
for await (const event of iterateModelStream(stream, signal)) {
|
|
1750
|
+
if (!isRecord(event) || typeof event.type !== "string") throw new Error("Responses stream delivered a malformed event without a string type");
|
|
1751
|
+
if (STRING_DELTA_EVENTS.has(event.type) && typeof event.delta !== "string") throw new Error(`Responses stream delivered malformed ${event.type} delta`);
|
|
1752
|
+
if ((event.type === "response.output_item.added" || event.type === "response.output_item.done") && !isRecord(event.item)) throw new Error(`Responses stream delivered malformed ${event.type} item`);
|
|
1753
|
+
if ((event.type === "response.created" || event.type === "response.completed" || event.type === "response.incomplete" || event.type === "response.failed") && !isRecord(event.response)) throw new Error(`Responses stream delivered malformed ${event.type} response`);
|
|
1754
|
+
yield event;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
async function* observeResponsesStream(stream, model, requestStartedAt) {
|
|
1758
|
+
const startedAt = Date.now();
|
|
1759
|
+
const eventTypes = /* @__PURE__ */ new Map();
|
|
1760
|
+
const debugMode = resolveModelSseDebugMode();
|
|
1761
|
+
let eventCount = 0;
|
|
1762
|
+
try {
|
|
1763
|
+
for await (const event of stream) {
|
|
1764
|
+
const type = isRecord(event) && typeof event.type === "string" ? event.type : "unknown";
|
|
1765
|
+
eventCount += 1;
|
|
1766
|
+
eventTypes.set(type, (eventTypes.get(type) ?? 0) + 1);
|
|
1767
|
+
if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - (requestStartedAt ?? startedAt)} headersToEventMs=${Date.now() - startedAt} type=${type}`);
|
|
1768
|
+
if (debugMode === "peek" && eventCount <= 5) emitModelTransportDebug(log, `[responses] event_peek provider=${model.provider} api=${model.api} model=${model.id} index=${eventCount} type=${type} event=${stringifyRedactedEvent(event)}`);
|
|
1769
|
+
yield event;
|
|
1770
|
+
}
|
|
1771
|
+
} finally {
|
|
1772
|
+
const types = [...eventTypes].map(([type, count]) => `${type}:${count}`).join(",");
|
|
1773
|
+
emitModelTransportDebug(log, `[responses] stream_done provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - startedAt} events=${eventCount} types=${types}`);
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
//#endregion
|
|
1797
1777
|
//#region packages/ai/src/transports/openai-responses-stream-terminal-internal.ts
|
|
1798
1778
|
function splitToolCallId(id) {
|
|
1799
1779
|
const separator = id.indexOf("|");
|
|
@@ -1824,6 +1804,10 @@ function resolveCompletedResponsesToolCall(item, streamed) {
|
|
|
1824
1804
|
function createResponsesTerminalController(params) {
|
|
1825
1805
|
const { output, stream, model, options } = params;
|
|
1826
1806
|
const blocks = output.content;
|
|
1807
|
+
let rejectedToolCallId;
|
|
1808
|
+
const recordIncompleteToolCall = (event, item) => {
|
|
1809
|
+
rejectedToolCallId = params.toolCalls.resolve(event, readResponsesToolCallItemIdentity(item))?.block.id ?? (item.call_id ? resolveResponsesToolCallId(item) : void 0);
|
|
1810
|
+
};
|
|
1827
1811
|
const backfillReasoning = (items) => {
|
|
1828
1812
|
for (const [outputIndex, item] of items.entries()) {
|
|
1829
1813
|
if (item.type !== "reasoning" || !item.encrypted_content) continue;
|
|
@@ -1986,6 +1970,7 @@ function createResponsesTerminalController(params) {
|
|
|
1986
1970
|
}
|
|
1987
1971
|
};
|
|
1988
1972
|
const finalizeTerminalFacts = (response, responseId = response.id) => {
|
|
1973
|
+
options?.onServiceTier?.(response.service_tier);
|
|
1989
1974
|
output.responseId = responseId || output.responseId;
|
|
1990
1975
|
output.responseModel = options?.resolveResponseModel ? options.resolveResponseModel()?.trim() || void 0 : response.model?.trim() || void 0;
|
|
1991
1976
|
const usage = mapResponsesTerminalUsage(response.usage);
|
|
@@ -2007,7 +1992,7 @@ function createResponsesTerminalController(params) {
|
|
|
2007
1992
|
options.applyServiceTierPricing(output.usage, tier);
|
|
2008
1993
|
}
|
|
2009
1994
|
};
|
|
2010
|
-
const finalizeResponse = (response, terminalEventType) => {
|
|
1995
|
+
const finalizeResponse = (response, terminalEventType, hasRejectedToolCall) => {
|
|
2011
1996
|
backfillReasoning(response.output ?? []);
|
|
2012
1997
|
finalizeTerminalFacts(response);
|
|
2013
1998
|
const terminal = resolveResponsesTerminalStopReason({
|
|
@@ -2020,20 +2005,25 @@ function createResponsesTerminalController(params) {
|
|
|
2020
2005
|
output.errorMessage = terminal.errorMessage;
|
|
2021
2006
|
if (terminalEventType === "response.completed" && typeof response.end_turn === "boolean") output.endTurn = response.end_turn;
|
|
2022
2007
|
const incompleteReason = response.incomplete_details?.reason;
|
|
2008
|
+
const incompleteCall = response.output?.find((item) => item.type === "function_call" && item.status && item.status !== "completed");
|
|
2009
|
+
const incompleteToolCallId = rejectedToolCallId ?? (terminalEventType === "response.incomplete" && !hasRejectedToolCall ? params.toolCalls.values()[0]?.block.id : void 0) ?? (incompleteCall?.type === "function_call" && incompleteCall.call_id ? resolveResponsesToolCallId(incompleteCall) : void 0);
|
|
2023
2010
|
appendAssistantMessageDiagnostic(output, {
|
|
2024
2011
|
type: "openai_responses_terminal",
|
|
2025
2012
|
timestamp: Date.now(),
|
|
2026
2013
|
details: {
|
|
2027
2014
|
eventType: terminalEventType,
|
|
2028
2015
|
stopReason: terminal.stopReason,
|
|
2016
|
+
...incompleteToolCallId ? { incompleteToolCallId } : {},
|
|
2029
2017
|
...terminalEventType === "response.incomplete" ? { incompleteReason: incompleteReason === "max_output_tokens" || incompleteReason === "max_messages" || incompleteReason === "content_filter" || incompleteReason === "steered" ? incompleteReason : "unknown" } : {},
|
|
2030
2018
|
endTurn: typeof response.end_turn === "boolean" ? response.end_turn : response.end_turn === void 0 ? "absent" : "invalid"
|
|
2031
2019
|
}
|
|
2032
2020
|
});
|
|
2021
|
+
if (!hasRejectedToolCall && terminalEventType === "response.incomplete" && params.toolCalls.hasActive()) throw output.errorMessage ? new Error(output.errorMessage) : new IncompleteToolCallError("Responses stream completed with unresolved tool calls");
|
|
2033
2022
|
};
|
|
2034
2023
|
return {
|
|
2035
2024
|
finalizeResponse,
|
|
2036
2025
|
finalizeFailedResponse: finalizeTerminalFacts,
|
|
2026
|
+
recordIncompleteToolCall,
|
|
2037
2027
|
recoverTerminalOutput,
|
|
2038
2028
|
emitToolCallCompletion
|
|
2039
2029
|
};
|
|
@@ -2160,6 +2150,7 @@ async function processResponsesStream(openaiStream, output, sink, model, options
|
|
|
2160
2150
|
model,
|
|
2161
2151
|
options,
|
|
2162
2152
|
outputs,
|
|
2153
|
+
toolCalls: streamingToolCalls,
|
|
2163
2154
|
getLastTextBlock: () => lastTextBlock,
|
|
2164
2155
|
setLastTextBlock: (block) => {
|
|
2165
2156
|
lastTextBlock = block;
|
|
@@ -2226,6 +2217,7 @@ async function processResponsesStream(openaiStream, output, sink, model, options
|
|
|
2226
2217
|
if (event.type === "response.output_item.done" && event.item.type === "function_call" && event.item.status && event.item.status !== "completed" && !rejectedToolCall) try {
|
|
2227
2218
|
resolveCompletedResponsesToolCall(event.item);
|
|
2228
2219
|
} catch (error) {
|
|
2220
|
+
terminal.recordIncompleteToolCall(event, event.item);
|
|
2229
2221
|
rejectedToolCall = { error };
|
|
2230
2222
|
}
|
|
2231
2223
|
if (rejectedToolCall && event.type !== "response.completed" && event.type !== "response.incomplete" && event.type !== "response.failed" && event.type !== "error") continue;
|
|
@@ -2289,48 +2281,35 @@ async function processResponsesStream(openaiStream, output, sink, model, options
|
|
|
2289
2281
|
if (!slot) continue;
|
|
2290
2282
|
slot.item.content = slot.item.content || [];
|
|
2291
2283
|
if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
|
|
2292
|
-
} else if (event.type === "response.output_text.delta") {
|
|
2284
|
+
} else if (event.type === "response.output_text.delta" || isAzureResponsesTextDeltaEvent(event) || event.type === "response.refusal.delta") {
|
|
2293
2285
|
const slot = outputSlots.resolve(event, "text");
|
|
2294
2286
|
if (!slot) continue;
|
|
2295
2287
|
slot.item.content ||= [];
|
|
2296
2288
|
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2297
|
-
if (
|
|
2298
|
-
lastPart
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
projectTextDelta(slot, event.delta);
|
|
2321
|
-
} else if (event.type === "response.refusal.delta") {
|
|
2322
|
-
const slot = outputSlots.resolve(event, "text");
|
|
2323
|
-
if (!slot) continue;
|
|
2324
|
-
slot.item.content ||= [];
|
|
2325
|
-
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2326
|
-
if (lastPart?.type !== "refusal") {
|
|
2327
|
-
lastPart = {
|
|
2328
|
-
type: "refusal",
|
|
2329
|
-
refusal: ""
|
|
2330
|
-
};
|
|
2331
|
-
slot.item.content.push(lastPart);
|
|
2289
|
+
if (event.type === "response.refusal.delta") {
|
|
2290
|
+
if (lastPart?.type !== "refusal") {
|
|
2291
|
+
lastPart = {
|
|
2292
|
+
type: "refusal",
|
|
2293
|
+
refusal: ""
|
|
2294
|
+
};
|
|
2295
|
+
slot.item.content.push(lastPart);
|
|
2296
|
+
}
|
|
2297
|
+
lastPart.refusal += event.delta;
|
|
2298
|
+
} else {
|
|
2299
|
+
const azure = isAzureResponsesTextDeltaEvent(event);
|
|
2300
|
+
if (!isResponsesTextContentPartType(lastPart?.type) || azure && lastPart.type !== "text") {
|
|
2301
|
+
lastPart = azure ? {
|
|
2302
|
+
type: "text",
|
|
2303
|
+
text: ""
|
|
2304
|
+
} : {
|
|
2305
|
+
type: "output_text",
|
|
2306
|
+
text: "",
|
|
2307
|
+
annotations: []
|
|
2308
|
+
};
|
|
2309
|
+
slot.item.content.push(lastPart);
|
|
2310
|
+
}
|
|
2311
|
+
lastPart.text += event.delta;
|
|
2332
2312
|
}
|
|
2333
|
-
lastPart.refusal += event.delta;
|
|
2334
2313
|
projectTextDelta(slot, event.delta);
|
|
2335
2314
|
} else if (event.type === "response.function_call_arguments.delta") {
|
|
2336
2315
|
const toolCall = streamingToolCalls.resolve(event);
|
|
@@ -2465,9 +2444,8 @@ async function processResponsesStream(openaiStream, output, sink, model, options
|
|
|
2465
2444
|
finalizeToolCall(item, readResponsesOutputIndex(event), streamingToolCall, validated);
|
|
2466
2445
|
}
|
|
2467
2446
|
} else if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
2468
|
-
terminal.finalizeResponse(event.response, event.type);
|
|
2447
|
+
terminal.finalizeResponse(event.response, event.type, Boolean(rejectedToolCall));
|
|
2469
2448
|
if (rejectedToolCall) throw output.errorMessage ? new Error(output.errorMessage) : rejectedToolCall.error;
|
|
2470
|
-
if (event.type === "response.incomplete" && streamingToolCalls.hasActive()) throw output.errorMessage ? new Error(output.errorMessage) : new IncompleteToolCallError("Responses stream completed with unresolved tool calls");
|
|
2471
2449
|
if (event.type === "response.completed" || output.stopReason === "length") {
|
|
2472
2450
|
const items = event.response.output ?? [];
|
|
2473
2451
|
const completeToolCall = event.type === "response.completed" ? prepareTerminalToolCalls(items) : void 0;
|
|
@@ -2567,6 +2545,10 @@ function applyResponsesServiceTierPricing(usage, serviceTier, model) {
|
|
|
2567
2545
|
function applyCommonResponsesParams(params, model, context, options, config) {
|
|
2568
2546
|
if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
|
|
2569
2547
|
if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
|
|
2548
|
+
if (options?.responseFormat !== void 0) params.text = {
|
|
2549
|
+
...params.text,
|
|
2550
|
+
format: resolveOpenAIResponsesTextFormat(options.responseFormat)
|
|
2551
|
+
};
|
|
2570
2552
|
if (context.tools) {
|
|
2571
2553
|
const tools = convertResponsesToolPayload(context.tools, { model });
|
|
2572
2554
|
if (tools.length > 0) params.tools = tools;
|
|
@@ -2605,6 +2587,7 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2605
2587
|
firstEventAbort = firstEvent;
|
|
2606
2588
|
let started = false;
|
|
2607
2589
|
let admittedRequest;
|
|
2590
|
+
let requestedTier;
|
|
2608
2591
|
const { stream: hookedOpenAIStream } = await createResponsesStreamWithEncryptedContentRetry({
|
|
2609
2592
|
client,
|
|
2610
2593
|
request: requestParams,
|
|
@@ -2619,6 +2602,7 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2619
2602
|
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, options, checkpoint),
|
|
2620
2603
|
canRetryStream: () => output.content.length === 0,
|
|
2621
2604
|
wrapStream: ({ stream: openaiStream, response, attempt }) => {
|
|
2605
|
+
requestedTier = attempt.request.service_tier;
|
|
2622
2606
|
admittedRequest = attempt.kind === "initial" ? attempt.request : void 0;
|
|
2623
2607
|
return withProviderResponseHook({
|
|
2624
2608
|
stream: openaiStream,
|
|
@@ -2647,6 +2631,7 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2647
2631
|
onFirstEventTimeout: params.processStreamOptions?.onFirstEventTimeout ?? onFirstEventTimeout,
|
|
2648
2632
|
signal: params.processStreamOptions?.signal ?? options?.signal
|
|
2649
2633
|
} : void 0,
|
|
2634
|
+
onServiceTier: (responseTier) => responsesServiceTierObserver.observe(options, requestedTier, responseTier),
|
|
2650
2635
|
canRetryIdentityConflict: () => hasOnlyResponsesFunctionTools(admittedRequest),
|
|
2651
2636
|
reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
|
|
2652
2637
|
sessionId: options?.sessionId,
|
|
@@ -2686,4 +2671,4 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2686
2671
|
}
|
|
2687
2672
|
}
|
|
2688
2673
|
//#endregion
|
|
2689
|
-
export { OPENAI_RESPONSES_FUNCTION_CALL_ITEM_ID_RE as $, recordResponsesContextUsage as A,
|
|
2674
|
+
export { OPENAI_RESPONSES_FUNCTION_CALL_ITEM_ID_RE as $, recordResponsesContextUsage as A, recordResponsesContinuationState as B, resolveAzureOpenAIApiVersion as C, safeDebugValue as D, logResponsesFailedNoDetails as E, convertResponsesMessages as F, replayResponsesReasoningUpdates as G, responsesContinuationPrefixFingerprint as H, readResponsesInputReplayState as I, buildOpenAIResponsesReasoningReplayMetadata as J, supportsResponsesReasoningUpdate as K, recordResponsesInputReplay as L, bindResponsesInputMessage as M, buildResponsesInputMessage as N, summarizeOpenAITransportError as O, convertProviderResponsesMessages as P, OPENAI_RESPONSES_CALL_ID_RE as Q, responsesInputFingerprint as R, isInvalidEncryptedContentError as S, ResponsesStreamFailure as T, responsesContinuationRequestFingerprint as U, resolveResponsesContinuationRequest as V, isConfigurationUpdate as W, resolveNewestOpenAIResponsesCompactionReplay as X, captureOpenAIResponsesCompaction as Y, suppressOpenAIResponsesCompaction as Z, isResponsesTextContentPartType as _, prepareResponsesTools as a, commitResponsesEncryptedContentAttempt as b, observeResponsesStream as c, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as d, OPENAI_RESPONSES_ID_MAX_LENGTH as et, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as f, isAzureResponsesTextDeltaEventType as g, isAzureResponsesTextDeltaEvent as h, convertResponsesToolPayload as i, resolveReplayableResponsesMessageId as it, resolveResponsesContextUsageBoundary as j, summarizeResponsesPayload as k, createResponsesToolCallTracker as l, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as m, applyResponsesServiceTierPricing as n, shouldNormalizeOpenAIResponsesToolCallId as nt, readOpenAIMisalignmentReview as o, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as p, CompactionReplayRefreshRequiredError as q, runResponsesStreamLifecycle as r, splitOpenAIFunctionCallPairing as rt, processResponsesStream as s, applyCommonResponsesParams as t, normalizeOpenAIResponsesFunctionCallId as tt, readResponsesToolCallItemIdentity as u, isResponsesTextDeltaEventType as v, resolveNextResponsesEncryptedContentAttempt as w, createResponsesStreamWithEncryptedContentRetry as x, resolveResponsesMessageSnapshotCollapse as y, claimOpenAIResponsesHttpContinuation as z };
|