@openclaw/ai 2026.9.33 → 2026.9.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{anthropic-a0uD7NUz.mjs → anthropic-BL3z3SiB.mjs} +2 -2
- package/dist/{anthropic-payload-policy-BVcxWtQD.d.mts → anthropic-payload-policy-CFbalbbU.d.mts} +3 -3
- package/dist/{anthropic-stream-reducer-Cis7c1sm.mjs → anthropic-stream-reducer-XCL_L8KJ.mjs} +1 -1
- package/dist/{api-registry-pGjnPg1z.d.mts → api-registry-BLbq15N5.d.mts} +2 -2
- package/dist/{azure-openai-responses-CqWvI8x6.mjs → azure-openai-responses-DYSS_bLh.mjs} +3 -3
- package/dist/diagnostics.d.mts +4 -4
- package/dist/env-api-keys-BR0MUYYD.d.mts +17 -0
- package/dist/event-stream-B0vjWzHd.d.mts +1 -0
- package/dist/{event-stream-DOPFYVqs.d.mts → event-stream-CiaHxSK0.d.mts} +1 -1
- package/dist/event-stream.d.mts +2 -2
- package/dist/{google-BfYNxKpG.mjs → google-D9zpPelZ.mjs} +1 -1
- package/dist/{google-interactions-BJNj0ugu.mjs → google-interactions-Br_n4tZB.mjs} +14 -11
- package/dist/{google-messages-C4ZiLG1P.mjs → google-messages-pvt0rKfN.mjs} +3 -1
- package/dist/{google-shared-6u4WCDyl.mjs → google-shared-DPeR7LLA.mjs} +9 -14
- package/dist/{google-vertex-CX1QaTs3.mjs → google-vertex-D4Qde9Qq.mjs} +1 -1
- package/dist/{host-COwfRiSL.d.mts → host-BhpDO5Sy.d.mts} +3 -3
- package/dist/{index-DHeFfpcz.d.mts → index-Iw8l620S.d.mts} +3 -3
- package/dist/index.d.mts +6 -6
- package/dist/internal/anthropic.d.mts +5 -5
- package/dist/internal/anthropic.mjs +2 -2
- package/dist/internal/env-api-keys.d.mts +2 -0
- package/dist/internal/env-api-keys.mjs +2 -0
- package/dist/internal/google-model-family.d.mts +2 -0
- package/dist/internal/google-model-family.mjs +6 -2
- 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.d.mts +9 -9
- package/dist/internal/openai.mjs +6 -6
- package/dist/internal/runtime.d.mts +8 -23
- package/dist/internal/shared.d.mts +3 -3
- package/dist/internal/tool-schema.mjs +1 -1
- package/dist/{openai-chatgpt-responses-L0Jc-0DF.mjs → openai-chatgpt-responses-Crt3yb4D.mjs} +59 -50
- package/dist/{openai-completions-gyTpI3xG.mjs → openai-completions-BwcqZo-Y.mjs} +4 -4
- package/dist/{openai-completions-compat-D1q02qdx.mjs → openai-completions-compat-BuszNIRF.mjs} +5 -1
- package/dist/{openai-completions-compat-CqWP1fn5.d.mts → openai-completions-compat-WTcM-PUc.d.mts} +4 -3
- package/dist/{openai-completions-stream-BrsoGafc.mjs → openai-completions-stream-D--YONza.mjs} +14 -11
- package/dist/{openai-prompt-cache-DHxMpeRz.mjs → openai-prompt-cache-BcwCks0h.mjs} +1 -1
- package/dist/{openai-prompt-cache-YTmJ_iMS.d.mts → openai-prompt-cache-CuY5QDIc.d.mts} +2 -2
- package/dist/{openai-provider-client-D1gd0dfR.mjs → openai-provider-client-Co1u7I3J.mjs} +1 -1
- package/dist/{openai-responses-DluFZzn_.mjs → openai-responses-C7B8_pLG.mjs} +5 -5
- package/dist/{openai-responses-compaction-replay-CQHR2isp.d.mts → openai-responses-compaction-replay-DiGjwK4d.d.mts} +4 -4
- package/dist/{openai-responses-contracts-C2H8pffb.d.mts → openai-responses-contracts-CYScOS7J.d.mts} +4 -4
- package/dist/{openai-responses-prompt-observer-internal-C5WB2Kxf.mjs → openai-responses-prompt-observer-internal-CGhqoBH1.mjs} +6 -6
- package/dist/{openai-responses-shared-BpGnmnV8.mjs → openai-responses-shared-DLz_xgps.mjs} +504 -12
- package/dist/{openai-responses-terminal-usage-D0WZQlIF.d.mts → openai-responses-terminal-usage-CLzeNWqW.d.mts} +2 -2
- package/dist/{openai-tool-schema-vsl-cE-n.mjs → openai-tool-schema-DSAxYnHW.mjs} +18 -1
- package/dist/{openai-transport-params-C4eZAXf2.mjs → openai-transport-params-DzSQTRdN.mjs} +17 -5
- package/dist/{provider-options-yDbWMoEr.d.mts → provider-options-CFiaIG4K.d.mts} +2 -2
- package/dist/{provider-types-CHsKHBBD.d.mts → provider-types-Bx_6hBmK.d.mts} +3 -3
- package/dist/provider-types.d.mts +5 -5
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +9 -9
- package/dist/{transport-stream-shared-CYLM2HEK.d.mts → transport-stream-shared-B_REuIea.d.mts} +4 -4
- package/dist/{transport-utils-CnxX8hPj.mjs → transport-utils-B11GlmDO.mjs} +5 -1
- package/dist/transports.d.mts +15 -13
- package/dist/transports.mjs +18 -503
- package/dist/{types-CLLR3eB4.d.mts → types-B89w6ly2.d.mts} +11 -0
- package/dist/types-DbmNRKvK.d.mts +1 -0
- package/dist/types.d.mts +5 -5
- package/dist/{validation-Cat2wQsc.d.mts → validation-DblQWSRA.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/package.json +6 -1
- package/dist/event-stream-CMQfX_yr.d.mts +0 -1
- package/dist/types-CoL-LJ7j.d.mts +0 -1
|
@@ -6,20 +6,21 @@ import { a as normalizeOptionalString, o as normalizeStringifiedOptionalString,
|
|
|
6
6
|
import { d as supportsOpenAITemperature } from "./openai-reasoning-effort-C_0p3psG.mjs";
|
|
7
7
|
import { o as truncateUtf16Safe, s as stableStringify } from "./provider-error-CwT_j2v0.mjs";
|
|
8
8
|
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-CJaB6g8J.mjs";
|
|
9
|
-
import { o as redactSensitiveText } from "./transport-utils-
|
|
10
|
-
import { i as resolveOpenAICompletionsCompat } from "./openai-completions-compat-
|
|
9
|
+
import { o as redactSensitiveText } from "./transport-utils-B11GlmDO.mjs";
|
|
10
|
+
import { i as resolveOpenAICompletionsCompat } from "./openai-completions-compat-BuszNIRF.mjs";
|
|
11
11
|
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-Dt7VrJFd.mjs";
|
|
12
|
-
import { C as stripSystemPromptCacheBoundary, D as sortPromptCacheToolsByName, d as describeToolResultMediaPlaceholder, m as extractToolResultText, s as prepareModelRequestBody } from "./simple-options-B9u6-CF3.mjs";
|
|
13
|
-
import {
|
|
12
|
+
import { C as stripSystemPromptCacheBoundary, D as sortPromptCacheToolsByName, d as describeToolResultMediaPlaceholder, m as extractToolResultText, r as clampMaxTokensToModel, s as prepareModelRequestBody } from "./simple-options-B9u6-CF3.mjs";
|
|
13
|
+
import { M as sha256Hex, S as detachPartialSnapshot, d as prepareOpenAITools, h as resolveOpenAIRequestReasoning, j as redactIdentifier, u as resolveOpenAIStrictToolFlagWithDiagnostics, w as log, y as createOpenAIProviderAcceptanceHook } from "./openai-transport-params-DzSQTRdN.mjs";
|
|
14
14
|
import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-BwVRJUQZ.mjs";
|
|
15
15
|
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
16
16
|
import { t as transformProviderMessages } from "./provider-transcript-transform-Cg-36VSt.mjs";
|
|
17
17
|
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-B9o0S4SZ.mjs";
|
|
18
|
-
import { a as resolveOpenAIProjectedToolsStrictToolFlag, f as withPreparedToolSchemaNormalization, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-
|
|
19
|
-
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-CLxnqS9p.mjs";
|
|
18
|
+
import { a as resolveOpenAIProjectedToolsStrictToolFlag, f as withPreparedToolSchemaNormalization, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-DSAxYnHW.mjs";
|
|
19
|
+
import { a as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, c as OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE, d as OpenAIResponsesWebSocketSafeRetryError, f as RESPONSE_FAILED_NO_DETAILS_MESSAGE, l as OpenAIResponsesWebSocketPostDispatchError, m as parseOpenAIResponsesWebSocketServerError, o as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, p as isPreviousResponseRejection, s as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY, u as OpenAIResponsesWebSocketPreDispatchError } from "./openai-responses-contracts-CLxnqS9p.mjs";
|
|
20
20
|
import { n as isOpenAIResponsesCompactionOutput, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-CYGCjAQz.mjs";
|
|
21
21
|
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
22
22
|
import { randomUUID } from "node:crypto";
|
|
23
|
+
import { ResponsesWS } from "openai/resources/responses/ws.js";
|
|
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. */
|
|
25
26
|
function resolveReplayableResponsesMessageId(params) {
|
|
@@ -649,6 +650,492 @@ function createResponsesInputReplay(model) {
|
|
|
649
650
|
};
|
|
650
651
|
}
|
|
651
652
|
//#endregion
|
|
653
|
+
//#region packages/ai/src/transports/openai-responses-steering.ts
|
|
654
|
+
function cloneWireRequest(request) {
|
|
655
|
+
const serialized = JSON.stringify(request);
|
|
656
|
+
return JSON.parse(serialized);
|
|
657
|
+
}
|
|
658
|
+
async function projectResponsesSteeringInput(request, project) {
|
|
659
|
+
const { input: activeInput, ...activeSettings } = cloneWireRequest(request);
|
|
660
|
+
if (!Array.isArray(activeInput)) return [];
|
|
661
|
+
const { input, ...settings } = cloneWireRequest(await project());
|
|
662
|
+
if (!Array.isArray(input) || stableStringify(settings) !== stableStringify(activeSettings) || stableStringify(input.slice(0, activeInput.length)) !== stableStringify(activeInput)) return [];
|
|
663
|
+
const projected = input.slice(activeInput.length);
|
|
664
|
+
return projected.every((item) => isRecord(item) && item.role === "user") ? projected : [];
|
|
665
|
+
}
|
|
666
|
+
/** One response owns admission; accepted input stays on this connection until continuation. */
|
|
667
|
+
function createResponsesSteering(params) {
|
|
668
|
+
let responseId;
|
|
669
|
+
let sealed = false;
|
|
670
|
+
let unsubscribe;
|
|
671
|
+
const pending = [];
|
|
672
|
+
const accepted = /* @__PURE__ */ new Map();
|
|
673
|
+
const acknowledged = /* @__PURE__ */ new Set();
|
|
674
|
+
const seal = () => {
|
|
675
|
+
sealed = true;
|
|
676
|
+
const cleanup = unsubscribe;
|
|
677
|
+
unsubscribe = void 0;
|
|
678
|
+
cleanup?.();
|
|
679
|
+
};
|
|
680
|
+
return {
|
|
681
|
+
get responseId() {
|
|
682
|
+
return responseId;
|
|
683
|
+
},
|
|
684
|
+
get pending() {
|
|
685
|
+
return pending.length > 0;
|
|
686
|
+
},
|
|
687
|
+
get acceptedInput() {
|
|
688
|
+
return [...accepted.values()].flat();
|
|
689
|
+
},
|
|
690
|
+
seal,
|
|
691
|
+
close(error) {
|
|
692
|
+
seal();
|
|
693
|
+
for (const submission of pending.splice(0)) submission.reject(error);
|
|
694
|
+
},
|
|
695
|
+
handle(event) {
|
|
696
|
+
if (!isRecord(event)) return false;
|
|
697
|
+
if (event.type === "response.created" && !responseId && !sealed) {
|
|
698
|
+
const response = isRecord(event.response) ? event.response : void 0;
|
|
699
|
+
if (typeof response?.id !== "string" || !response.id.trim()) throw new Error("Responses steering requires a response identity");
|
|
700
|
+
const activeResponseId = response.id;
|
|
701
|
+
responseId = activeResponseId;
|
|
702
|
+
const cleanup = params.onActiveResponse({
|
|
703
|
+
needsContinuation: params.needsContinuation,
|
|
704
|
+
steer(messages) {
|
|
705
|
+
if (sealed || messages.length === 0) return Promise.resolve(false);
|
|
706
|
+
params.assertActive();
|
|
707
|
+
const converted = params.toInput(messages);
|
|
708
|
+
const submit = (input) => {
|
|
709
|
+
if (sealed || input.length === 0) return Promise.resolve(false);
|
|
710
|
+
params.assertActive();
|
|
711
|
+
return new Promise((resolve, reject) => {
|
|
712
|
+
pending.push({
|
|
713
|
+
input,
|
|
714
|
+
resolve,
|
|
715
|
+
reject
|
|
716
|
+
});
|
|
717
|
+
params.send({
|
|
718
|
+
type: "response.steer",
|
|
719
|
+
previous_response_id: activeResponseId,
|
|
720
|
+
input
|
|
721
|
+
});
|
|
722
|
+
});
|
|
723
|
+
};
|
|
724
|
+
return Array.isArray(converted) ? submit(converted) : converted.then(submit);
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
if (sealed) cleanup?.();
|
|
728
|
+
else unsubscribe = cleanup;
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
if (event.type !== "response.steer.accepted" && event.type !== "response.steer.failed" && event.type !== "response.steer.pending") return false;
|
|
732
|
+
const steer = isRecord(event.steer) ? event.steer : void 0;
|
|
733
|
+
if (!responseId || steer?.previous_response_id !== responseId) throw new Error("Responses steering acknowledgement has an unexpected identity");
|
|
734
|
+
if (event.type === "response.steer.failed" && steer.id === void 0) {
|
|
735
|
+
const index = pending.findIndex((submission) => stableStringify(submission.input) === stableStringify(steer.input));
|
|
736
|
+
const submission = pending[index];
|
|
737
|
+
if (!submission) throw new Error("Responses steering acknowledgement has no pending submission");
|
|
738
|
+
pending.splice(index, 1);
|
|
739
|
+
submission.resolve(false);
|
|
740
|
+
return true;
|
|
741
|
+
}
|
|
742
|
+
if (typeof steer.id !== "string" || !steer.id.trim()) throw new Error("Responses steering acknowledgement has an unexpected identity");
|
|
743
|
+
if (event.type === "response.steer.pending") {
|
|
744
|
+
if (!accepted.has(steer.id)) throw new Error("Responses steering pending event has no accepted submission");
|
|
745
|
+
return true;
|
|
746
|
+
}
|
|
747
|
+
if (event.type === "response.steer.failed" && accepted.has(steer.id)) throw new Error("OpenAI could not apply accepted steering; the queued message remains in the conversation");
|
|
748
|
+
if (acknowledged.has(steer.id)) throw new Error("Responses steering acknowledgement was already applied");
|
|
749
|
+
const submission = pending.shift();
|
|
750
|
+
if (!submission) throw new Error("Responses steering acknowledgement has no pending submission");
|
|
751
|
+
acknowledged.add(steer.id);
|
|
752
|
+
if (event.type === "response.steer.accepted") {
|
|
753
|
+
accepted.set(steer.id, submission.input);
|
|
754
|
+
submission.resolve(true);
|
|
755
|
+
} else submission.resolve(false);
|
|
756
|
+
return true;
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
/** Accepted steering is prepended by the server, so never repeat it in response.create. */
|
|
761
|
+
function omitAcceptedSteering(input, accepted) {
|
|
762
|
+
const remaining = [...input];
|
|
763
|
+
for (const message of accepted) {
|
|
764
|
+
const index = remaining.findIndex((item) => stableStringify(item) === stableStringify(message));
|
|
765
|
+
if (index < 0) throw new Error("Responses steering continuation no longer contains the accepted user input");
|
|
766
|
+
remaining.splice(index, 1);
|
|
767
|
+
}
|
|
768
|
+
return remaining;
|
|
769
|
+
}
|
|
770
|
+
//#endregion
|
|
771
|
+
//#region packages/ai/src/transports/openai-responses-websocket.ts
|
|
772
|
+
const SESSION_WEBSOCKET_CACHE_TTL_MS = 3e5;
|
|
773
|
+
const SESSION_WEBSOCKET_MAX_AGE_MS = 33e5;
|
|
774
|
+
const WEBSOCKET_OPEN_STATE = 1;
|
|
775
|
+
const websocketSessionCache = /* @__PURE__ */ new Map();
|
|
776
|
+
const degradedWebSocketConnections = /* @__PURE__ */ new Map();
|
|
777
|
+
function isOfficialOpenAIResponsesBaseUrl(baseUrl) {
|
|
778
|
+
if (!baseUrl) return false;
|
|
779
|
+
try {
|
|
780
|
+
const url = new URL(baseUrl);
|
|
781
|
+
return url.origin === "https://api.openai.com" && url.username === "" && url.password === "" && url.search === "" && url.hash === "" && url.pathname.replace(/\/+$/, "") === "/v1";
|
|
782
|
+
} catch {
|
|
783
|
+
return false;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
function supportsNativeOpenAIResponsesEndpoint(params) {
|
|
787
|
+
return params.provider.trim().toLowerCase() === "openai" && params.api === "openai-responses" && isOfficialOpenAIResponsesBaseUrl(params.baseUrl);
|
|
788
|
+
}
|
|
789
|
+
function closeWebSocketSilently(socket, reason = "done") {
|
|
790
|
+
try {
|
|
791
|
+
socket.close({
|
|
792
|
+
code: 1e3,
|
|
793
|
+
reason
|
|
794
|
+
});
|
|
795
|
+
} catch {}
|
|
796
|
+
}
|
|
797
|
+
function invalidateOwnedWebSocketSession(cacheKey, entry, reason = "done") {
|
|
798
|
+
if (entry.idleTimer) {
|
|
799
|
+
clearTimeout(entry.idleTimer);
|
|
800
|
+
entry.idleTimer = void 0;
|
|
801
|
+
}
|
|
802
|
+
closeWebSocketSilently(entry.socket, reason);
|
|
803
|
+
entry.steeringContinuation?.steering.close(/* @__PURE__ */ new Error("Responses steering connection closed"));
|
|
804
|
+
entry.steeringContinuation?.iterator.return?.().catch(() => void 0);
|
|
805
|
+
entry.steeringContinuation = void 0;
|
|
806
|
+
if (websocketSessionCache.get(cacheKey) === entry) websocketSessionCache.delete(cacheKey);
|
|
807
|
+
}
|
|
808
|
+
function scheduleSessionWebSocketExpiry(cacheKey, entry) {
|
|
809
|
+
if (entry.idleTimer) clearTimeout(entry.idleTimer);
|
|
810
|
+
entry.idleTimer = setTimeout(() => {
|
|
811
|
+
if (entry.busy) return;
|
|
812
|
+
invalidateOwnedWebSocketSession(cacheKey, entry, "idle_timeout");
|
|
813
|
+
}, SESSION_WEBSOCKET_CACHE_TTL_MS);
|
|
814
|
+
entry.idleTimer.unref?.();
|
|
815
|
+
}
|
|
816
|
+
function prepareWebSocketConnection(client, headers) {
|
|
817
|
+
if (!isOfficialOpenAIResponsesBaseUrl(client.baseURL)) throw new Error("OpenAI Responses WebSocket requires the official API endpoint");
|
|
818
|
+
if (typeof client.apiKey !== "string" || client.apiKey.length === 0) throw new Error("OpenAI Responses WebSocket requires an API key");
|
|
819
|
+
const resolvedApiKey = getAiTransportHost().resolveSecretSentinel(client.apiKey);
|
|
820
|
+
const resolvedHeaders = { ...resolveAiTransportHeaderSentinels(headers) };
|
|
821
|
+
for (const key of Object.keys(resolvedHeaders)) {
|
|
822
|
+
const normalizedKey = key.toLowerCase();
|
|
823
|
+
if (normalizedKey === "authorization" || normalizedKey === "traceparent") delete resolvedHeaders[key];
|
|
824
|
+
}
|
|
825
|
+
if (!resolvedApiKey) throw new Error("OpenAI Responses WebSocket requires a resolved API key");
|
|
826
|
+
return {
|
|
827
|
+
client: client.withOptions({ apiKey: resolvedApiKey }),
|
|
828
|
+
headers: resolvedHeaders,
|
|
829
|
+
identity: sha256Hex(JSON.stringify([
|
|
830
|
+
resolvedApiKey,
|
|
831
|
+
client.baseURL,
|
|
832
|
+
Object.entries(resolvedHeaders).toSorted(([a], [b]) => a.localeCompare(b))
|
|
833
|
+
]))
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
function createWebSocket(connection, onError) {
|
|
837
|
+
const socket = new ResponsesWS(connection.client, {
|
|
838
|
+
headers: connection.headers,
|
|
839
|
+
maxQueueSize: 1
|
|
840
|
+
});
|
|
841
|
+
socket.on("error", () => onError(socket));
|
|
842
|
+
return socket;
|
|
843
|
+
}
|
|
844
|
+
function createTransientWebSocketLease(connection) {
|
|
845
|
+
const socket = createWebSocket(connection, (failedSocket) => closeWebSocketSilently(failedSocket, "transport_error"));
|
|
846
|
+
return {
|
|
847
|
+
socket,
|
|
848
|
+
iterator: socket.stream(),
|
|
849
|
+
reusedConnection: false,
|
|
850
|
+
release: () => closeWebSocketSilently(socket)
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function createCachedWebSocketLease(cacheKey, entry, reusedConnection) {
|
|
854
|
+
entry.busy = true;
|
|
855
|
+
const steeringContinuation = entry.steeringContinuation;
|
|
856
|
+
entry.steeringContinuation = void 0;
|
|
857
|
+
return {
|
|
858
|
+
socket: entry.socket,
|
|
859
|
+
iterator: steeringContinuation?.iterator ?? entry.socket.stream(),
|
|
860
|
+
entry,
|
|
861
|
+
reusedConnection,
|
|
862
|
+
steeringContinuation,
|
|
863
|
+
release: ({ keep } = {}) => {
|
|
864
|
+
if (!keep || entry.socket.socket.readyState !== WEBSOCKET_OPEN_STATE) {
|
|
865
|
+
invalidateOwnedWebSocketSession(cacheKey, entry);
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
entry.busy = false;
|
|
869
|
+
scheduleSessionWebSocketExpiry(cacheKey, entry);
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
function acquireWebSocket(params, connection) {
|
|
874
|
+
if (!(params.mode !== "websocket" && Boolean(params.sessionId)) || !params.sessionId) return createTransientWebSocketLease(connection);
|
|
875
|
+
const cacheKey = `${params.sessionId}\0${connection.identity}`;
|
|
876
|
+
const cached = websocketSessionCache.get(cacheKey);
|
|
877
|
+
if (cached) {
|
|
878
|
+
if (cached.idleTimer) {
|
|
879
|
+
clearTimeout(cached.idleTimer);
|
|
880
|
+
cached.idleTimer = void 0;
|
|
881
|
+
}
|
|
882
|
+
if (cached.busy) return createTransientWebSocketLease(connection);
|
|
883
|
+
const expired = Date.now() - cached.createdAt >= SESSION_WEBSOCKET_MAX_AGE_MS;
|
|
884
|
+
if (!expired && cached.socket.socket.readyState === WEBSOCKET_OPEN_STATE) return createCachedWebSocketLease(cacheKey, cached, true);
|
|
885
|
+
invalidateOwnedWebSocketSession(cacheKey, cached, expired ? "connection_age_limit" : "done");
|
|
886
|
+
}
|
|
887
|
+
const entry = {
|
|
888
|
+
socket: createWebSocket(connection, (failedSocket) => {
|
|
889
|
+
const failedEntry = websocketSessionCache.get(cacheKey);
|
|
890
|
+
if (failedEntry?.socket === failedSocket) invalidateOwnedWebSocketSession(cacheKey, failedEntry, "transport_error");
|
|
891
|
+
else closeWebSocketSilently(failedSocket, "transport_error");
|
|
892
|
+
}),
|
|
893
|
+
sessionId: params.sessionId,
|
|
894
|
+
busy: true,
|
|
895
|
+
createdAt: Date.now()
|
|
896
|
+
};
|
|
897
|
+
websocketSessionCache.set(cacheKey, entry);
|
|
898
|
+
return createCachedWebSocketLease(cacheKey, entry, false);
|
|
899
|
+
}
|
|
900
|
+
function sanitizeWebSocketRequest(request) {
|
|
901
|
+
const { stream: _stream, background: _background, ...websocketRequest } = request;
|
|
902
|
+
return websocketRequest;
|
|
903
|
+
}
|
|
904
|
+
async function nextWebSocketMessage(iterator, signal) {
|
|
905
|
+
if (!signal) return iterator.next();
|
|
906
|
+
if (signal.aborted) throw transportAbortError(signal);
|
|
907
|
+
let onAbort;
|
|
908
|
+
try {
|
|
909
|
+
return await Promise.race([iterator.next(), new Promise((_resolve, reject) => {
|
|
910
|
+
onAbort = () => reject(transportAbortError(signal));
|
|
911
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
912
|
+
})]);
|
|
913
|
+
} finally {
|
|
914
|
+
if (onAbort) signal.removeEventListener("abort", onAbort);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
function readServerEvent(message) {
|
|
918
|
+
if (message.type === "message") return message.message;
|
|
919
|
+
if (message.type === "error") throw parseOpenAIResponsesWebSocketServerError(message.error) ?? new Error("OpenAI Responses WebSocket transport failed", { cause: message.error });
|
|
920
|
+
if (message.type === "close") throw new Error(`OpenAI Responses WebSocket closed before completion (code ${message.code})`);
|
|
921
|
+
}
|
|
922
|
+
function createOpenAIResponsesWebSocketStream(params) {
|
|
923
|
+
const connection = prepareWebSocketConnection(params.client, params.headers);
|
|
924
|
+
let fullRequest = sanitizeWebSocketRequest(params.request);
|
|
925
|
+
const requestModel = typeof fullRequest.model === "string" ? fullRequest.model : "";
|
|
926
|
+
const degradationKey = `${params.sessionId ?? ""}\0${connection.identity}\0${requestModel}`;
|
|
927
|
+
const degraded = degradedWebSocketConnections.get(degradationKey);
|
|
928
|
+
if (degraded && degraded.retryAt > Date.now()) throw new OpenAIResponsesWebSocketPreDispatchError(/* @__PURE__ */ new Error("OpenAI Responses WebSocket is cooling down after a transport failure"));
|
|
929
|
+
degradedWebSocketConnections.delete(degradationKey);
|
|
930
|
+
const markDegraded = () => {
|
|
931
|
+
const cooldownMs = params.degradeCooldownMs;
|
|
932
|
+
if (cooldownMs === void 0 || !Number.isFinite(cooldownMs) || cooldownMs <= 0) return;
|
|
933
|
+
degradedWebSocketConnections.set(degradationKey, {
|
|
934
|
+
sessionId: params.sessionId,
|
|
935
|
+
retryAt: Date.now() + cooldownMs
|
|
936
|
+
});
|
|
937
|
+
};
|
|
938
|
+
let lease;
|
|
939
|
+
try {
|
|
940
|
+
lease = acquireWebSocket(params, connection);
|
|
941
|
+
} catch (error) {
|
|
942
|
+
markDegraded();
|
|
943
|
+
throw new OpenAIResponsesWebSocketPreDispatchError(error);
|
|
944
|
+
}
|
|
945
|
+
let prepared;
|
|
946
|
+
let previousContinuation;
|
|
947
|
+
const resumedSteering = lease.steeringContinuation;
|
|
948
|
+
const steeringMode = resumedSteering ? resumedSteering.requiresInput ? "required-input" : "automatic" : void 0;
|
|
949
|
+
try {
|
|
950
|
+
const continuation = previousContinuation = lease.entry?.continuation;
|
|
951
|
+
if (continuation && lease.entry) {
|
|
952
|
+
lease.entry.continuation = void 0;
|
|
953
|
+
prepared = resolveResponsesContinuationRequest(continuation, fullRequest, steeringMode);
|
|
954
|
+
} else {
|
|
955
|
+
fullRequest = params.restoreRequest?.(fullRequest) ?? fullRequest;
|
|
956
|
+
prepared = {
|
|
957
|
+
request: fullRequest,
|
|
958
|
+
continuationStatus: lease.entry ? "no_previous_response" : "socket_not_cached"
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
} catch (error) {
|
|
962
|
+
lease.iterator.return?.().catch(() => void 0);
|
|
963
|
+
lease.release({ keep: false });
|
|
964
|
+
throw error;
|
|
965
|
+
}
|
|
966
|
+
let streamStarted = false;
|
|
967
|
+
let terminalResponse;
|
|
968
|
+
let terminalReceived = false;
|
|
969
|
+
let released = false;
|
|
970
|
+
let retainIterator = false;
|
|
971
|
+
let deferredInput = false;
|
|
972
|
+
let inputReplay;
|
|
973
|
+
if (resumedSteering) try {
|
|
974
|
+
if (prepared.continuationStatus !== "continued" || !prepared.request.previous_response_id) throw new Error("Responses steering continuation changed its request or history");
|
|
975
|
+
const input = omitAcceptedSteering(prepared.request.input ?? [], resumedSteering.acceptedInput);
|
|
976
|
+
if (!resumedSteering.requiresInput && (stableStringify(fullRequest.instructions) !== stableStringify(resumedSteering.instructions) || stableStringify(fullRequest.tools) !== stableStringify(resumedSteering.tools))) throw new Error("Responses automatic steering continuation cannot change instructions or tools");
|
|
977
|
+
const baseline = prepared.fullRequest ?? fullRequest;
|
|
978
|
+
const priorLength = (baseline.input?.length ?? 0) - (prepared.request.input?.length ?? 0);
|
|
979
|
+
const fingerprints = input.map(responsesInputFingerprint);
|
|
980
|
+
if (fingerprints.length > 0) inputReplay = {
|
|
981
|
+
afterResponseId: prepared.request.previous_response_id,
|
|
982
|
+
before: resumedSteering.requiresInput ? fingerprints : [],
|
|
983
|
+
after: resumedSteering.requiresInput ? [] : fingerprints
|
|
984
|
+
};
|
|
985
|
+
const delivered = resumedSteering.requiresInput ? input : [];
|
|
986
|
+
prepared.fullRequest = {
|
|
987
|
+
...baseline,
|
|
988
|
+
input: [
|
|
989
|
+
...(baseline.input ?? []).slice(0, priorLength),
|
|
990
|
+
...resumedSteering.acceptedInput,
|
|
991
|
+
...delivered
|
|
992
|
+
]
|
|
993
|
+
};
|
|
994
|
+
prepared.request = {
|
|
995
|
+
...prepared.request,
|
|
996
|
+
input: delivered
|
|
997
|
+
};
|
|
998
|
+
deferredInput = !resumedSteering.requiresInput && input.length > 0;
|
|
999
|
+
} catch (error) {
|
|
1000
|
+
lease.iterator.return?.().catch(() => void 0);
|
|
1001
|
+
lease.release({ keep: false });
|
|
1002
|
+
throw new OpenAIResponsesWebSocketPostDispatchError(error);
|
|
1003
|
+
}
|
|
1004
|
+
const steering = lease.entry && params.onActiveResponse && params.steeringInput ? createResponsesSteering({
|
|
1005
|
+
onActiveResponse: params.onActiveResponse,
|
|
1006
|
+
toInput: params.steeringInput,
|
|
1007
|
+
send: (event) => lease.socket.sendRaw(JSON.stringify(event)),
|
|
1008
|
+
needsContinuation: () => deferredInput,
|
|
1009
|
+
assertActive: () => {
|
|
1010
|
+
if (released || terminalReceived || params.signal?.aborted) throw new Error("Responses steering is no longer active");
|
|
1011
|
+
}
|
|
1012
|
+
}) : void 0;
|
|
1013
|
+
const finish = ({ keep = true } = {}) => {
|
|
1014
|
+
if (released) return;
|
|
1015
|
+
released = true;
|
|
1016
|
+
if (keep && lease.entry && terminalResponse) lease.entry.continuation = recordResponsesContinuationState(previousContinuation, prepared.fullRequest ?? fullRequest, terminalResponse, previousContinuation?.lastResponseId === prepared.request.previous_response_id);
|
|
1017
|
+
lease.release({ keep });
|
|
1018
|
+
};
|
|
1019
|
+
return {
|
|
1020
|
+
stream: { async *[Symbol.asyncIterator]() {
|
|
1021
|
+
if (streamStarted) throw new Error("OpenAI Responses WebSocket stream can only be consumed once");
|
|
1022
|
+
streamStarted = true;
|
|
1023
|
+
const iterator = lease.iterator;
|
|
1024
|
+
let requestDispatched = false;
|
|
1025
|
+
try {
|
|
1026
|
+
if (params.signal?.aborted) throw transportAbortError(params.signal);
|
|
1027
|
+
if (resumedSteering) {
|
|
1028
|
+
requestDispatched = true;
|
|
1029
|
+
if (resumedSteering.requiresInput) lease.socket.send({
|
|
1030
|
+
...prepared.request,
|
|
1031
|
+
type: "response.create"
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
for (;;) {
|
|
1035
|
+
const buffered = resumedSteering?.buffered.shift();
|
|
1036
|
+
const next = buffered ? {
|
|
1037
|
+
value: buffered,
|
|
1038
|
+
done: false
|
|
1039
|
+
} : await nextWebSocketMessage(iterator, params.signal);
|
|
1040
|
+
if (next.done) throw new Error("OpenAI Responses WebSocket closed before a terminal response event");
|
|
1041
|
+
if (next.value.type === "open") {
|
|
1042
|
+
if (!requestDispatched) {
|
|
1043
|
+
requestDispatched = true;
|
|
1044
|
+
lease.socket.send({
|
|
1045
|
+
...prepared.request,
|
|
1046
|
+
type: "response.create"
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
const event = readServerEvent(next.value);
|
|
1052
|
+
if (!event) continue;
|
|
1053
|
+
if (isRecord(event) && typeof event.type === "string" && event.type.startsWith("response.steer.")) {
|
|
1054
|
+
if ((isRecord(event.steer) && event.steer.previous_response_id === steering?.responseId ? steering : resumedSteering?.steering ?? steering)?.handle(event)) continue;
|
|
1055
|
+
}
|
|
1056
|
+
steering?.handle(event);
|
|
1057
|
+
if (event.type === "response.completed") terminalResponse = event.response;
|
|
1058
|
+
terminalReceived = event.type === "response.completed" || event.type === "response.incomplete" || event.type === "response.failed";
|
|
1059
|
+
if (terminalReceived) {
|
|
1060
|
+
steering?.seal();
|
|
1061
|
+
if (event.type === "response.failed") steering?.close(/* @__PURE__ */ new Error("Responses failed before steering could be applied"));
|
|
1062
|
+
const continuationBuffer = [];
|
|
1063
|
+
for (;;) {
|
|
1064
|
+
if (!steering?.pending) break;
|
|
1065
|
+
const acknowledgement = await nextWebSocketMessage(iterator, params.signal);
|
|
1066
|
+
if (acknowledgement.done) throw new Error("Responses closed before acknowledging steering");
|
|
1067
|
+
const acknowledgedEvent = readServerEvent(acknowledgement.value);
|
|
1068
|
+
if (!steering.handle(acknowledgedEvent)) continuationBuffer.push(acknowledgement.value);
|
|
1069
|
+
}
|
|
1070
|
+
const acceptedInput = steering?.acceptedInput ?? [];
|
|
1071
|
+
const isSteered = event.type === "response.incomplete" && isRecord(event.response.incomplete_details) && event.response.incomplete_details.reason === "steered";
|
|
1072
|
+
if (lease.entry && steering && acceptedInput.length > 0 && (event.type === "response.completed" || isSteered)) {
|
|
1073
|
+
if (event.type === "response.incomplete") terminalResponse = event.response;
|
|
1074
|
+
lease.entry.steeringContinuation = {
|
|
1075
|
+
iterator,
|
|
1076
|
+
buffered: continuationBuffer,
|
|
1077
|
+
acceptedInput,
|
|
1078
|
+
requiresInput: (terminalResponse?.output ?? []).some((item) => (item.type === "function_call" || item.type === "custom_tool_call") && !(isRecord(item) && item.async === true) || item.type === "mcp_approval_request"),
|
|
1079
|
+
steering,
|
|
1080
|
+
instructions: fullRequest.instructions,
|
|
1081
|
+
tools: fullRequest.tools
|
|
1082
|
+
};
|
|
1083
|
+
retainIterator = true;
|
|
1084
|
+
if (isSteered) {
|
|
1085
|
+
yield {
|
|
1086
|
+
...event,
|
|
1087
|
+
type: "response.completed",
|
|
1088
|
+
response: {
|
|
1089
|
+
...event.response,
|
|
1090
|
+
status: "completed",
|
|
1091
|
+
incomplete_details: null
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
yield event;
|
|
1099
|
+
if (terminalReceived) {
|
|
1100
|
+
degradedWebSocketConnections.delete(degradationKey);
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
const steeringDispatched = Boolean(steering?.pending || steering?.acceptedInput.length || resumedSteering);
|
|
1106
|
+
steering?.close(error instanceof Error ? error : /* @__PURE__ */ new Error("Responses steering failed"));
|
|
1107
|
+
if (lease.entry) lease.entry.continuation = void 0;
|
|
1108
|
+
const safeRetry = error instanceof OpenAIResponsesWebSocketSafeRetryError && !steeringDispatched;
|
|
1109
|
+
if (!params.callerSignal?.aborted && !safeRetry) markDegraded();
|
|
1110
|
+
if (!requestDispatched && !params.signal?.aborted) throw new OpenAIResponsesWebSocketPreDispatchError(error);
|
|
1111
|
+
if (!requestDispatched || params.callerSignal?.aborted || safeRetry) throw error;
|
|
1112
|
+
throw new OpenAIResponsesWebSocketPostDispatchError(error);
|
|
1113
|
+
} finally {
|
|
1114
|
+
steering?.seal();
|
|
1115
|
+
if (!retainIterator) {
|
|
1116
|
+
steering?.close(/* @__PURE__ */ new Error("Responses stream ended before steering was confirmed"));
|
|
1117
|
+
await iterator.return?.().catch(() => void 0);
|
|
1118
|
+
}
|
|
1119
|
+
if (!terminalReceived) finish({ keep: false });
|
|
1120
|
+
}
|
|
1121
|
+
} },
|
|
1122
|
+
request: prepared.request,
|
|
1123
|
+
fullRequest: prepared.fullRequest ?? fullRequest,
|
|
1124
|
+
reusedConnection: lease.reusedConnection,
|
|
1125
|
+
continuationStatus: prepared.continuationStatus,
|
|
1126
|
+
inputReplay,
|
|
1127
|
+
finish
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
function closeOpenAIResponsesWebSocketSessions(sessionId) {
|
|
1131
|
+
for (const [cacheKey, entry] of websocketSessionCache) {
|
|
1132
|
+
if (sessionId && entry.sessionId !== sessionId) continue;
|
|
1133
|
+
invalidateOwnedWebSocketSession(cacheKey, entry, "session_cleanup");
|
|
1134
|
+
}
|
|
1135
|
+
for (const [key, entry] of degradedWebSocketConnections) if (!sessionId || entry.sessionId === sessionId) degradedWebSocketConnections.delete(key);
|
|
1136
|
+
}
|
|
1137
|
+
registerSessionResourceCleanup(closeOpenAIResponsesWebSocketSessions);
|
|
1138
|
+
//#endregion
|
|
652
1139
|
//#region packages/ai/src/transports/openai-responses-replay-messages-internal.ts
|
|
653
1140
|
function stripEncryptedReasoningContentFields(value) {
|
|
654
1141
|
if (!value || typeof value !== "object") return {
|
|
@@ -803,6 +1290,9 @@ function buildResponsesInputMessage(role, content, source) {
|
|
|
803
1290
|
...identity ? { [responsesInputSource]: identity } : {}
|
|
804
1291
|
};
|
|
805
1292
|
}
|
|
1293
|
+
function resolveResponsesInstructionRole(model) {
|
|
1294
|
+
return model.reasoning && model.compat?.supportsDeveloperRole !== false ? "developer" : "system";
|
|
1295
|
+
}
|
|
806
1296
|
function convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, conversionStyle) {
|
|
807
1297
|
const messages = [];
|
|
808
1298
|
const providerStyle = conversionStyle === "provider";
|
|
@@ -851,7 +1341,7 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
851
1341
|
preserveUnframedToolResults: replayPlan.preserveUnframedToolResults
|
|
852
1342
|
});
|
|
853
1343
|
const transformedMessages = orderResponsesAsyncToolResults(transformMessages(replayPlan.messages));
|
|
854
|
-
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model
|
|
1344
|
+
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(resolveResponsesInstructionRole(model), [{
|
|
855
1345
|
type: "input_text",
|
|
856
1346
|
text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt))
|
|
857
1347
|
}]));
|
|
@@ -873,13 +1363,15 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
873
1363
|
}
|
|
874
1364
|
let msgIndex = 0;
|
|
875
1365
|
const appendAssistant = createResponsesInputReplay(model);
|
|
1366
|
+
const inHistorySystemUpdates = supportsNativeOpenAIResponsesEndpoint(model);
|
|
876
1367
|
for (const msg of replayMessages) {
|
|
877
1368
|
if (!("role" in msg)) {
|
|
878
1369
|
messages.push(msg);
|
|
879
1370
|
continue;
|
|
880
1371
|
}
|
|
881
1372
|
if (msg.role === "user") {
|
|
882
|
-
|
|
1373
|
+
const role = msg.runtimeContextCarrier === true && inHistorySystemUpdates ? resolveResponsesInstructionRole(model) : "user";
|
|
1374
|
+
if (typeof msg.content === "string") messages.push(buildResponsesInputMessage(role, [{
|
|
883
1375
|
type: "input_text",
|
|
884
1376
|
text: sanitizeTransportPayloadText(msg.content)
|
|
885
1377
|
}], msg));
|
|
@@ -892,7 +1384,7 @@ function convertResponsesMessagesWithStyle(model, context, allowedToolCallProvid
|
|
|
892
1384
|
detail: "auto",
|
|
893
1385
|
image_url: `data:${item.mimeType};base64,${item.data}`
|
|
894
1386
|
}).filter((item) => providerStyle || model.input.includes("image") || item.type !== "input_image");
|
|
895
|
-
if (content.length > 0) messages.push(buildResponsesInputMessage(
|
|
1387
|
+
if (content.length > 0) messages.push(buildResponsesInputMessage(role, content, msg));
|
|
896
1388
|
else if (providerStyle) continue;
|
|
897
1389
|
}
|
|
898
1390
|
} else if (msg.role === "assistant") {
|
|
@@ -1704,7 +2196,7 @@ function createResponsesOutputTracker(params) {
|
|
|
1704
2196
|
trackStream(sink) {
|
|
1705
2197
|
return { push(event) {
|
|
1706
2198
|
visibleTextEmitted ||= event.type === "text_delta" && event.delta.length > 0 || event.type === "text_end" && event.content.length > 0;
|
|
1707
|
-
sink.push(event);
|
|
2199
|
+
sink.push(detachPartialSnapshot(event));
|
|
1708
2200
|
} };
|
|
1709
2201
|
},
|
|
1710
2202
|
observeEvent(event) {
|
|
@@ -2565,7 +3057,7 @@ function applyResponsesServiceTierPricing(usage, serviceTier, model) {
|
|
|
2565
3057
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
2566
3058
|
}
|
|
2567
3059
|
function applyCommonResponsesParams(params, model, context, options, config) {
|
|
2568
|
-
if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
|
|
3060
|
+
if (options?.maxTokens) params.max_output_tokens = clampMaxTokensToModel(model, Math.max(options.maxTokens, 16));
|
|
2569
3061
|
if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
|
|
2570
3062
|
if (context.tools) {
|
|
2571
3063
|
const tools = convertResponsesToolPayload(context.tools, { model });
|
|
@@ -2686,4 +3178,4 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
2686
3178
|
}
|
|
2687
3179
|
}
|
|
2688
3180
|
//#endregion
|
|
2689
|
-
export { OPENAI_RESPONSES_FUNCTION_CALL_ITEM_ID_RE as $, recordResponsesContextUsage as A,
|
|
3181
|
+
export { OPENAI_RESPONSES_FUNCTION_CALL_ITEM_ID_RE as $, recordResponsesContextUsage as A, claimOpenAIResponsesHttpContinuation as B, resolveAzureOpenAIApiVersion as C, safeDebugValue as D, logResponsesFailedNoDetails as E, convertResponsesMessages as F, supportsResponsesReasoningUpdate as G, responsesContinuationRequestFingerprint as H, createOpenAIResponsesWebSocketStream as I, captureOpenAIResponsesCompaction as J, CompactionReplayRefreshRequiredError as K, supportsNativeOpenAIResponsesEndpoint as L, bindResponsesInputMessage as M, buildResponsesInputMessage as N, summarizeOpenAITransportError as O, convertProviderResponsesMessages as P, OPENAI_RESPONSES_CALL_ID_RE as Q, projectResponsesSteeringInput as R, isInvalidEncryptedContentError as S, ResponsesStreamFailure as T, isConfigurationUpdate as U, responsesContinuationPrefixFingerprint as V, replayResponsesReasoningUpdates as W, resolveNewestOpenAIResponsesCompactionReplay as X, isOpenAIResponsesReplayContext 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, buildOpenAIResponsesReasoningReplayMetadata 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, recordResponsesInputReplay as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { K as StopReason, a as AssistantMessage, ot as Usage } from "./types-
|
|
2
|
-
import "./types-
|
|
1
|
+
import { K as StopReason, a as AssistantMessage, ot as Usage } from "./types-B89w6ly2.mjs";
|
|
2
|
+
import "./types-DbmNRKvK.mjs";
|
|
3
3
|
import OpenAI from "openai";
|
|
4
4
|
//#region packages/ai/src/providers/openai-responses-terminal-usage.d.ts
|
|
5
5
|
/** A known output ceiling can resume sampling after admitted tools have settled. */
|
|
@@ -982,6 +982,21 @@ function normalizeOpenAIStrictCompatSchemaRecursive(schema, promoteEmptyObject =
|
|
|
982
982
|
function normalizeOpenAIStrictCompatSchema(schema) {
|
|
983
983
|
return normalizeOpenAIStrictCompatSchemaRecursive(schema, true);
|
|
984
984
|
}
|
|
985
|
+
/**
|
|
986
|
+
* Returns whether a regex pattern contains a lookahead or lookbehind group.
|
|
987
|
+
* Escaped parentheses, character classes, and named groups are not lookarounds.
|
|
988
|
+
*/
|
|
989
|
+
function hasRegexLookaround(pattern) {
|
|
990
|
+
let inCharacterClass = false;
|
|
991
|
+
for (let index = 0; index < pattern.length; index += 1) {
|
|
992
|
+
const char = pattern[index];
|
|
993
|
+
if (char === "\\") index += 1;
|
|
994
|
+
else if (inCharacterClass) inCharacterClass = char !== "]";
|
|
995
|
+
else if (char === "[") inCharacterClass = true;
|
|
996
|
+
else if (char === "(" && /^\?<?[=!]/.test(pattern.slice(index + 1, index + 4))) return true;
|
|
997
|
+
}
|
|
998
|
+
return false;
|
|
999
|
+
}
|
|
985
1000
|
/** Finds schema paths that violate OpenAI strict tool-schema requirements. */
|
|
986
1001
|
function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
987
1002
|
if (Array.isArray(schema)) {
|
|
@@ -997,6 +1012,7 @@ function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
|
997
1012
|
"allOf"
|
|
998
1013
|
]) if (key in record) violations.push(`${path}.${key}`);
|
|
999
1014
|
if (Array.isArray(record.type)) violations.push(`${path}.type`);
|
|
1015
|
+
if (typeof record.pattern === "string" && hasRegexLookaround(record.pattern)) violations.push(`${path}.pattern`);
|
|
1000
1016
|
const properties = isRecord(record.properties) ? record.properties : void 0;
|
|
1001
1017
|
if (record.type === "object") {
|
|
1002
1018
|
if (record.additionalProperties !== false) violations.push(`${path}.additionalProperties`);
|
|
@@ -1082,7 +1098,8 @@ function normalizeOpenAIStrictToolParameters(schema, strict, modelCompat) {
|
|
|
1082
1098
|
}
|
|
1083
1099
|
/** Returns whether a schema already satisfies OpenAI strict tool-schema constraints. */
|
|
1084
1100
|
function isStrictOpenAIJsonSchemaCompatible(schema) {
|
|
1085
|
-
|
|
1101
|
+
const normalized = normalizeStrictOpenAIJsonSchema(schema);
|
|
1102
|
+
return isStrictOpenAIJsonSchemaCompatibleRecursive(normalized) && findOpenAIStrictSchemaViolations(normalized, "parameters").length === 0;
|
|
1086
1103
|
}
|
|
1087
1104
|
/** Returns strict-schema diagnostics for an already materialized OpenAI tool projection. */
|
|
1088
1105
|
function findOpenAIStrictToolProjectionDiagnostics(projection) {
|