@openclaw/ai 2026.10.1-beta.2 → 2026.10.5-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 +6 -0
- package/dist/{anthropic-CZv6XFER.mjs → anthropic-BAHKgWam.mjs} +30 -59
- package/dist/{anthropic-payload-policy-BhCcgNdm.d.mts → anthropic-payload-policy-DGblkHL5.d.mts} +19 -16
- package/dist/{anthropic-stream-reducer-BQ1tjd7x.mjs → anthropic-stream-reducer-g6w1YVii.mjs} +197 -285
- package/dist/{api-registry-DpU0Rj-I.d.mts → api-registry-BhXXYdRA.d.mts} +2 -2
- package/dist/assistant-message-events-CHMJgbhs.mjs +18 -0
- package/dist/{assistant-output-OLm-Oln0.mjs → assistant-output-CUEeSotf.mjs} +2 -2
- package/dist/{assistant-text-phase-Bl1aDCB7.mjs → assistant-text-phase-BrV8KdFO.mjs} +7 -6
- package/dist/{azure-openai-responses-DH7bd3QT.mjs → azure-openai-responses-C7qBuR23.mjs} +8 -9
- package/dist/{credential-redaction-BKv49aiv.d.mts → credential-redaction-BHxruEH6.d.mts} +3 -1
- package/dist/{diagnostics-Caj-4RBA.mjs → diagnostics-tQasYct1.mjs} +10 -3
- package/dist/diagnostics.d.mts +7 -7
- package/dist/diagnostics.mjs +3 -3
- package/dist/{env-api-keys-CyX4VKGO.mjs → env-api-keys-CrxwdylR.mjs} +24 -35
- package/dist/event-stream-6UNs-AhN.d.mts +1 -0
- package/dist/{event-stream-DrRM_90c.d.mts → event-stream-BcqWLo_u.d.mts} +1 -1
- package/dist/{event-stream-C5AbCAaZ.mjs → event-stream-X2gmsUWv.mjs} +5 -8
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/google-Boz2QcpK.mjs +20 -0
- package/dist/{google-interactions-wrnE6MLw.mjs → google-interactions-tjAb1mc5.mjs} +52 -84
- package/dist/{google-messages-BwPPycw6.mjs → google-messages-C-RZzloH.mjs} +25 -35
- package/dist/google-provider-stream-CMImyxbX.mjs +58 -0
- package/dist/{google-shared-Eql1OMPU.mjs → google-shared-OyAtMTZv.mjs} +6 -15
- package/dist/google-vertex-hCxTJea7.mjs +40 -0
- package/dist/{host-BinBeGcQ.d.mts → host-CTDz7LXD.d.mts} +6 -3
- package/dist/{host-DCW52iHe.mjs → host-JWXZWa-c.mjs} +12 -8
- package/dist/{host-policy-B3jc4Rpn.mjs → host-policy-q4Azym9F.mjs} +1 -1
- package/dist/{index-a8e_oKnu.d.mts → index-BYDvopUB.d.mts} +27 -6
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -6
- package/dist/internal/anthropic.d.mts +6 -6
- package/dist/internal/anthropic.mjs +5 -5
- 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 +8 -1
- package/dist/internal/openai-responses-payload-policy.mjs +3 -3
- package/dist/internal/openai.d.mts +9 -9
- package/dist/internal/openai.mjs +9 -11
- package/dist/internal/runtime.d.mts +14 -11
- package/dist/internal/runtime.mjs +10 -13
- package/dist/internal/shared.d.mts +5 -5
- package/dist/internal/shared.mjs +6 -7
- package/dist/internal/tool-schema.mjs +2 -2
- package/dist/{llm-request-activity-D8f_oxHj.mjs → llm-request-activity-CfMuh5cC.mjs} +2 -2
- package/dist/{mistral-DSt4vQAO.mjs → mistral-DUveP4hF.mjs} +71 -146
- package/dist/{model-transport-url-C5f59L3Y.d.mts → model-transport-url-BrsjjdjR.d.mts} +5 -1
- package/dist/{number-coercion-V8-BhME4.mjs → number-coercion-C3hztWoY.mjs} +5 -4
- package/dist/{openai-chatgpt-responses-BC2x0Oqx.mjs → openai-chatgpt-responses-OCwckGhY.mjs} +173 -242
- package/dist/{openai-completions-DNyHnXKg.mjs → openai-completions-DOltBUe9.mjs} +7 -6
- package/dist/{openai-completions-compat-BYdYpXhU.d.mts → openai-completions-compat-i-nLZxFy.d.mts} +10 -11
- package/dist/{openai-completions-compat-BdmlhD4u.mjs → openai-completions-compat-pg1q4uNG.mjs} +10 -6
- package/dist/openai-completions-transport-OMrn7gnZ.mjs +3319 -0
- package/dist/{openai-prompt-cache-I8YQTzf8.mjs → openai-prompt-cache-Cr2xKVrS.mjs} +1 -1
- package/dist/{openai-prompt-cache-45-AH_xv.d.mts → openai-prompt-cache-DIPMrMFy.d.mts} +2 -2
- package/dist/{openai-responses-uZ5oWSp7.mjs → openai-responses-BSBJUA19.mjs} +9 -10
- package/dist/{openai-responses-compaction-replay-BClApUIf.d.mts → openai-responses-compaction-replay-B2FE4Nw8.d.mts} +4 -4
- package/dist/{openai-responses-contracts-Br5IIw_h.d.mts → openai-responses-contracts-DKqMJ1Ct.d.mts} +9 -4
- package/dist/{openai-responses-contracts-BKu8O7l4.mjs → openai-responses-contracts-DlKMMTxK.mjs} +26 -6
- package/dist/{openai-responses-compaction-window-m878aVpU.mjs → openai-responses-endpoint-CinGh4VZ.mjs} +14 -4
- package/dist/{openai-responses-prompt-observer-internal-CCg7B6l4.mjs → openai-responses-request-lifecycle-D2IFiI0-.mjs} +39 -4
- package/dist/{openai-responses-shared-C7oVyjED.mjs → openai-responses-shared-DVGhq5xF.mjs} +1036 -327
- package/dist/{openai-responses-terminal-usage-DgImcyJu.d.mts → openai-responses-terminal-usage-BygjiAdi.d.mts} +2 -2
- package/dist/{openai-tool-schema-DYNePiF8.mjs → openai-tool-schema-DDPXsvJP.mjs} +236 -399
- package/dist/{positive-integer-CwLi8LUL.mjs → positive-integer-CqWjqSi9.mjs} +1 -1
- package/dist/{provider-error-DQBE1bUQ.mjs → provider-error-CF9GWCs2.mjs} +5 -3
- package/dist/{provider-options-D5ABCV_l.d.mts → provider-options-CVrXZBtA.d.mts} +3 -2
- package/dist/{provider-transport-turn-state-_M2kLdUE.mjs → provider-transport-turn-state-LuCaTsSO.mjs} +2 -2
- package/dist/{provider-types-F8Mqc9Ma.d.mts → provider-types-CHtRx0dI.d.mts} +3 -3
- package/dist/provider-types.d.mts +6 -6
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +12 -12
- package/dist/{reasoning-tag-text-partitioner-Ju9VpUGl.mjs → reasoning-tag-text-partitioner-0-Rsezog.mjs} +13 -12
- package/dist/{required-api-key-D4kn3252.mjs → required-api-key-CFJvcFy_.mjs} +1 -1
- package/dist/{simple-options-BkKTXxhp.mjs → simple-options-BARFAzk9.mjs} +9 -11
- package/dist/{src-B0NIt2UK.mjs → src-C_wfIUmV.mjs} +35 -10
- package/dist/{stream-DSdzKsDK.mjs → stream-DwrETW0_.mjs} +12 -21
- package/dist/{stream-first-event-timeout-D9ZmL_s9.mjs → stream-first-event-timeout-Dc42hKv6.mjs} +8 -21
- package/dist/{streaming-byte-guard-CC-HMn_u.mjs → streaming-byte-guard-DBXr1XYn.mjs} +16 -1
- package/dist/{string-normalization-PN10hf6d.mjs → string-normalization-I3ux50s9.mjs} +1 -1
- package/dist/{text-signature-MLwfi6fq.mjs → text-signature-B_MB6U_9.mjs} +32 -5
- package/dist/{tool-schema-json-projection-Ct8SeBeJ.mjs → tool-schema-json-projection-B8sG1I9v.mjs} +29 -23
- package/dist/{transport-stream-shared-BcAKh2XH.d.mts → transport-stream-shared-BmpzDtdQ.d.mts} +4 -4
- package/dist/{transport-stream-shared-CxXXz_Dd.mjs → transport-stream-shared-DH08b7Il.mjs} +31 -20
- package/dist/transports.d.mts +33 -22
- package/dist/transports.mjs +73 -1234
- package/dist/{types-DvzmWW8J.d.mts → types-Bd2T86VJ.d.mts} +5 -23
- package/dist/types-Kdfw_04V.d.mts +1 -0
- package/dist/types.d.mts +6 -6
- package/dist/types.mjs +5 -4
- package/dist/{validation-B3lQt_VE.d.mts → validation-DdGB1yy3.d.mts} +1 -1
- package/dist/{validation-DbqlIfDn.mjs → validation-opC2pjk9.mjs} +2 -3
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +4 -4
- package/dist/event-stream-DqDQWqiy.d.mts +0 -1
- package/dist/google-1WLOtb8w.mjs +0 -54
- package/dist/google-vertex-0LrlRoO3.mjs +0 -88
- package/dist/openai-completions-transport-DWM2mQDB.mjs +0 -2081
- package/dist/openai-responses-request-lifecycle-Fsag-IGZ.mjs +0 -36
- package/dist/openai-transport-params-JFsnIyto.mjs +0 -735
- package/dist/openai-web-search-tools-Cfu0uLyN.mjs +0 -14
- package/dist/provider-replay-context-C7Bmi84a.mjs +0 -25
- package/dist/types-BuiEBM3u.d.mts +0 -1
|
@@ -1,735 +0,0 @@
|
|
|
1
|
-
import { o as isRecord, r as asOptionalObjectRecord } from "./record-coerce-CNDovvft.mjs";
|
|
2
|
-
import { a as normalizeOptionalString, n as normalizeLowercaseStringOrEmpty } from "./string-coerce-CtgOVOSv.mjs";
|
|
3
|
-
import { D as applyProviderReportedUsageCost, E as headersToRecord, O as calculateCost, k as clampThinkingLevel, r as getAiTransportHost } from "./host-DCW52iHe.mjs";
|
|
4
|
-
import { A as resolveOpenAIThinkingApi, C as resolveOpenAIReasoningEffortForModel, E as supportsOpenAIReasoningEffort, O as MODEL_CATALOG_THINKING_LEVELS, S as resolveOpenAIModelReasoningEfforts, i as OPENAI_RESPONSES_APIS, w as resolveOpenAIReasoningEffortMapping, x as normalizeOpenAIReasoningEffort } from "./openai-responses-contracts-BKu8O7l4.mjs";
|
|
5
|
-
import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-I8YQTzf8.mjs";
|
|
6
|
-
import { i as isCodeModeModelVisibleToolName } from "./text-signature-MLwfi6fq.mjs";
|
|
7
|
-
import { i as resolveOpenAICompletionsCompat, o as usesNativeOpenAICodexResponsesBackend } from "./openai-completions-compat-BdmlhD4u.mjs";
|
|
8
|
-
import { r as resolveModelRequestTimeoutMs } from "./host-policy-B3jc4Rpn.mjs";
|
|
9
|
-
import { m as notifyProviderHttpResponse } from "./transport-stream-shared-CxXXz_Dd.mjs";
|
|
10
|
-
import { n as projectRuntimeToolInputSchema, t as prepareRuntimeToolInputSchema } from "./tool-schema-json-projection-Ct8SeBeJ.mjs";
|
|
11
|
-
import { n as resolveOpencodeSessionHeaders } from "./session-affinity-DA4WHv1h.mjs";
|
|
12
|
-
import { a as resolveOpenAIProjectedToolsStrictToolFlag, t as findOpenAIStrictToolProjectionDiagnostics } from "./openai-tool-schema-DYNePiF8.mjs";
|
|
13
|
-
import { hash } from "node:crypto";
|
|
14
|
-
//#region packages/normalization-core/src/node-crypto.ts
|
|
15
|
-
function sha256Hex(input) {
|
|
16
|
-
return hash("sha256", input, "hex");
|
|
17
|
-
}
|
|
18
|
-
function sha256HexPrefixCore(input, length) {
|
|
19
|
-
return sha256Hex(input).slice(0, length);
|
|
20
|
-
}
|
|
21
|
-
/** Redacts an identifier to a stable hash label, or "-" for missing values. */
|
|
22
|
-
function redactIdentifier(value, opts) {
|
|
23
|
-
const trimmed = normalizeOptionalString(value);
|
|
24
|
-
if (!trimmed) return "-";
|
|
25
|
-
const len = opts?.len ?? 12;
|
|
26
|
-
return `sha256:${sha256HexPrefixCore(trimmed, Number.isFinite(len) ? Math.max(1, Math.floor(len)) : 12)}`;
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region packages/ai/src/transports/openai-transport-shared.ts
|
|
30
|
-
const OPENAI_RESPONSE_MODEL_HEADER_NAMES = /* @__PURE__ */ new Set(["openai-model", "x-openai-model"]);
|
|
31
|
-
const OPENAI_RESPONSE_MODEL_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
32
|
-
"response.created",
|
|
33
|
-
"response.in_progress",
|
|
34
|
-
"response.completed",
|
|
35
|
-
"response.done",
|
|
36
|
-
"response.incomplete",
|
|
37
|
-
"response.failed"
|
|
38
|
-
]);
|
|
39
|
-
const OPENAI_DATED_MODEL_SUFFIX = /-(?:\d{8}|\d{4}-\d{2}-\d{2})$/;
|
|
40
|
-
const GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP = "skip_thought_signature_validator";
|
|
41
|
-
const log = {
|
|
42
|
-
debug(message, data) {
|
|
43
|
-
getAiTransportHost().logDebug("openai-transport", () => ({
|
|
44
|
-
message,
|
|
45
|
-
data
|
|
46
|
-
}));
|
|
47
|
-
},
|
|
48
|
-
info(message, data) {
|
|
49
|
-
getAiTransportHost().logInfo("openai-transport", message, data);
|
|
50
|
-
},
|
|
51
|
-
warn(message, data) {
|
|
52
|
-
getAiTransportHost().logWarn("openai-transport", message, data);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
const OPENAI_RESPONSE_MODEL_CONFLICT = "Conflicting OpenAI response model attestations";
|
|
56
|
-
function splitOpenAIResponseModelHeader(value) {
|
|
57
|
-
return value ? value.split(",").map((part) => part.trim()).filter(Boolean) : [];
|
|
58
|
-
}
|
|
59
|
-
function readOpenAIResponseModelHeaders(headers) {
|
|
60
|
-
return [...OPENAI_RESPONSE_MODEL_HEADER_NAMES].flatMap((name) => splitOpenAIResponseModelHeader(headers.get(name)));
|
|
61
|
-
}
|
|
62
|
-
function readOpenAIResponseModelHeaderRecord(headers) {
|
|
63
|
-
if (!isRecord(headers)) return [];
|
|
64
|
-
return Object.entries(headers).filter(([name]) => OPENAI_RESPONSE_MODEL_HEADER_NAMES.has(name.toLowerCase())).flatMap(([, value]) => typeof value === "string" ? splitOpenAIResponseModelHeader(value) : []);
|
|
65
|
-
}
|
|
66
|
-
function readOpenAIResponseModelEvent(event) {
|
|
67
|
-
if (!isRecord(event)) return [];
|
|
68
|
-
const response = isRecord(event.response) ? event.response : void 0;
|
|
69
|
-
return [
|
|
70
|
-
...OPENAI_RESPONSE_MODEL_EVENT_TYPES.has(String(event.type)) && typeof response?.model === "string" && response.model.trim() ? [response.model.trim()] : [],
|
|
71
|
-
...readOpenAIResponseModelHeaderRecord(response?.headers),
|
|
72
|
-
...readOpenAIResponseModelHeaderRecord(event.headers)
|
|
73
|
-
];
|
|
74
|
-
}
|
|
75
|
-
function reconcileOpenAIResponseModels(current, observed) {
|
|
76
|
-
if (!current || current === observed) return observed;
|
|
77
|
-
const currentBase = current.replace(OPENAI_DATED_MODEL_SUFFIX, "");
|
|
78
|
-
const observedBase = observed.replace(OPENAI_DATED_MODEL_SUFFIX, "");
|
|
79
|
-
if (currentBase !== observedBase) return;
|
|
80
|
-
if (currentBase === current && observedBase !== observed) return observed;
|
|
81
|
-
if (observedBase === observed && currentBase !== current) return current;
|
|
82
|
-
}
|
|
83
|
-
function createResponseModelTracker(enabled = true) {
|
|
84
|
-
let responseModel;
|
|
85
|
-
const observe = (models) => {
|
|
86
|
-
for (const model of models) {
|
|
87
|
-
const reconciled = reconcileOpenAIResponseModels(responseModel, model);
|
|
88
|
-
if (!reconciled) throw new Error(OPENAI_RESPONSE_MODEL_CONFLICT);
|
|
89
|
-
responseModel = reconciled;
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
const begin = (headers) => {
|
|
93
|
-
responseModel = void 0;
|
|
94
|
-
if (enabled && headers) observe(readOpenAIResponseModelHeaders(headers));
|
|
95
|
-
};
|
|
96
|
-
const observeEvent = (event) => {
|
|
97
|
-
if (enabled) observe(readOpenAIResponseModelEvent(event));
|
|
98
|
-
return responseModel;
|
|
99
|
-
};
|
|
100
|
-
const resolve = () => responseModel;
|
|
101
|
-
return {
|
|
102
|
-
begin,
|
|
103
|
-
observeEvent,
|
|
104
|
-
resolve,
|
|
105
|
-
track(response, stream) {
|
|
106
|
-
if (!enabled) return stream;
|
|
107
|
-
return (async function* () {
|
|
108
|
-
begin(response?.headers);
|
|
109
|
-
for await (const event of stream) {
|
|
110
|
-
observeEvent(event);
|
|
111
|
-
yield event;
|
|
112
|
-
}
|
|
113
|
-
})();
|
|
114
|
-
},
|
|
115
|
-
terminalOptions: enabled ? { resolveResponseModel: resolve } : {}
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
function resolveOpenAIClientBaseUrl(model, baseUrl = model.baseUrl) {
|
|
119
|
-
if (baseUrl?.trim()) return baseUrl;
|
|
120
|
-
if (model.provider.trim().toLowerCase() === "openai") return;
|
|
121
|
-
throw new Error(`Provider "${model.provider}" requires an explicit base URL before using an OpenAI-compatible API. Reload provider metadata or configure an endpoint.`);
|
|
122
|
-
}
|
|
123
|
-
const EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH = createOpenAICompletionsReasoningBatch();
|
|
124
|
-
const OPENAI_COMPLETIONS_REASONING_FIELDS = [
|
|
125
|
-
"reasoning_content",
|
|
126
|
-
"reasoning",
|
|
127
|
-
"reasoning_text"
|
|
128
|
-
];
|
|
129
|
-
function appendOpenAICompletionsReasoningDelta(batch, next) {
|
|
130
|
-
if (next.kind === "thinking") batch.hasThinking = true;
|
|
131
|
-
else batch.hasVisibleText = true;
|
|
132
|
-
const previous = batch.deltas[batch.deltas.length - 1];
|
|
133
|
-
if (!previous || previous.kind !== next.kind || next.kind === "thinking" && previous.kind === "thinking" && previous.signature !== next.signature) {
|
|
134
|
-
batch.deltas.push(next);
|
|
135
|
-
if (next.kind === "thinking") batch.mirroredThinking.push(next.text);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
previous.text += next.text;
|
|
139
|
-
if (next.kind === "thinking") batch.mirroredThinking[batch.mirroredThinking.length - 1] += next.text;
|
|
140
|
-
}
|
|
141
|
-
function createOpenAICompletionsReasoningBatch() {
|
|
142
|
-
return {
|
|
143
|
-
deltas: [],
|
|
144
|
-
mirroredThinking: [],
|
|
145
|
-
hasThinking: false,
|
|
146
|
-
hasVisibleText: false
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
function readOpenAICompletionsReasoningBatch(delta, visibleReasoningDetailTypes) {
|
|
150
|
-
let batch;
|
|
151
|
-
const reasoningDetails = delta.reasoning_details;
|
|
152
|
-
let usedReasoningThinkingDetails = false;
|
|
153
|
-
if (Array.isArray(reasoningDetails)) for (const item of reasoningDetails) {
|
|
154
|
-
if (!isRecord(item)) continue;
|
|
155
|
-
const detail = item;
|
|
156
|
-
if (typeof detail.text !== "string" || !detail.text) continue;
|
|
157
|
-
if (detail.type === "reasoning.text") {
|
|
158
|
-
usedReasoningThinkingDetails = true;
|
|
159
|
-
batch ??= createOpenAICompletionsReasoningBatch();
|
|
160
|
-
appendOpenAICompletionsReasoningDelta(batch, {
|
|
161
|
-
kind: "thinking",
|
|
162
|
-
signature: "reasoning_details",
|
|
163
|
-
text: detail.text
|
|
164
|
-
});
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
if (typeof detail.type === "string" && visibleReasoningDetailTypes.has(detail.type)) {
|
|
168
|
-
batch ??= createOpenAICompletionsReasoningBatch();
|
|
169
|
-
appendOpenAICompletionsReasoningDelta(batch, {
|
|
170
|
-
kind: "text",
|
|
171
|
-
text: detail.text,
|
|
172
|
-
source: "reasoning_detail"
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (!usedReasoningThinkingDetails) for (const field of OPENAI_COMPLETIONS_REASONING_FIELDS) {
|
|
177
|
-
const value = delta[field];
|
|
178
|
-
if (typeof value === "string" && value.length > 0) {
|
|
179
|
-
batch ??= createOpenAICompletionsReasoningBatch();
|
|
180
|
-
appendOpenAICompletionsReasoningDelta(batch, {
|
|
181
|
-
kind: "thinking",
|
|
182
|
-
signature: field,
|
|
183
|
-
text: value
|
|
184
|
-
});
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return batch ?? EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH;
|
|
189
|
-
}
|
|
190
|
-
function parseOpenAICompletionsUsage(rawUsage, model, options) {
|
|
191
|
-
const cacheRead = rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.prompt_cache_hit_tokens ?? 0;
|
|
192
|
-
const cacheWrite = rawUsage.prompt_tokens_details?.cache_write_tokens ?? rawUsage.prompt_tokens_details?.cache_creation_input_tokens ?? rawUsage.cache_creation_input_tokens ?? 0;
|
|
193
|
-
const input = Math.max(0, (rawUsage.prompt_tokens || 0) - cacheRead - cacheWrite);
|
|
194
|
-
const output = rawUsage.completion_tokens || 0;
|
|
195
|
-
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
|
|
196
|
-
const hasCoherentContext = [
|
|
197
|
-
rawUsage.prompt_tokens,
|
|
198
|
-
rawUsage.completion_tokens,
|
|
199
|
-
rawUsage.total_tokens,
|
|
200
|
-
cacheRead,
|
|
201
|
-
cacheWrite
|
|
202
|
-
].every((value) => typeof value === "number" && Number.isFinite(value) && value >= 0) && rawUsage.prompt_tokens >= cacheRead + cacheWrite && rawUsage.total_tokens >= rawUsage.prompt_tokens + rawUsage.completion_tokens;
|
|
203
|
-
const usage = {
|
|
204
|
-
input,
|
|
205
|
-
output,
|
|
206
|
-
cacheRead,
|
|
207
|
-
cacheWrite,
|
|
208
|
-
...options?.includeReasoningTokens !== false && typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? { reasoningTokens } : {},
|
|
209
|
-
contextUsage: hasCoherentContext ? {
|
|
210
|
-
state: "available",
|
|
211
|
-
promptTokens: rawUsage.prompt_tokens,
|
|
212
|
-
totalTokens: Math.max(input + output + cacheRead + cacheWrite, rawUsage.total_tokens)
|
|
213
|
-
} : { state: "unavailable" },
|
|
214
|
-
totalTokens: input + output + cacheRead + cacheWrite,
|
|
215
|
-
cost: {
|
|
216
|
-
input: 0,
|
|
217
|
-
output: 0,
|
|
218
|
-
cacheRead: 0,
|
|
219
|
-
cacheWrite: 0,
|
|
220
|
-
total: 0
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
calculateCost(model, usage);
|
|
224
|
-
applyProviderReportedUsageCost(usage, rawUsage.cost);
|
|
225
|
-
return usage;
|
|
226
|
-
}
|
|
227
|
-
function createOpenAIResponseHook(onResponse, response, model) {
|
|
228
|
-
return onResponse ? () => onResponse({
|
|
229
|
-
status: response.status,
|
|
230
|
-
headers: headersToRecord(response.headers)
|
|
231
|
-
}, model) : void 0;
|
|
232
|
-
}
|
|
233
|
-
function createOpenAIProviderAcceptanceHook(options, response, model) {
|
|
234
|
-
return () => notifyProviderHttpResponse({
|
|
235
|
-
options,
|
|
236
|
-
response,
|
|
237
|
-
model
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
/** Measure one UTF-8 append without double-counting a surrogate pair split across chunks. */
|
|
241
|
-
function measureUtf8AppendBytes(bufferEndsWithHighSurrogate, chunk) {
|
|
242
|
-
let bytes = Buffer.byteLength(chunk, "utf8");
|
|
243
|
-
if (!chunk) return {
|
|
244
|
-
bytes,
|
|
245
|
-
endsWithHighSurrogate: bufferEndsWithHighSurrogate
|
|
246
|
-
};
|
|
247
|
-
const nextCodeUnit = chunk.charCodeAt(0);
|
|
248
|
-
if (bufferEndsWithHighSurrogate && nextCodeUnit >= 56320 && nextCodeUnit <= 57343) bytes -= 2;
|
|
249
|
-
const finalCodeUnit = chunk.charCodeAt(chunk.length - 1);
|
|
250
|
-
return {
|
|
251
|
-
bytes,
|
|
252
|
-
endsWithHighSurrogate: finalCodeUnit >= 55296 && finalCodeUnit <= 56319
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
function resolvePromptCacheKey(options, cacheRetention) {
|
|
256
|
-
if (cacheRetention === "none") return;
|
|
257
|
-
return clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId);
|
|
258
|
-
}
|
|
259
|
-
function isOpenAICompletionsThinkingEnabled(effort) {
|
|
260
|
-
const normalized = effort.trim().toLowerCase();
|
|
261
|
-
return normalized !== "off" && normalized !== "none";
|
|
262
|
-
}
|
|
263
|
-
function readOpenAICompletionsContentDeltas(content, topLevelRefusal, mirroredThinking = []) {
|
|
264
|
-
let deltas = readOpenAICompletionsContentPartDeltas(content);
|
|
265
|
-
if (mirroredThinking.length > 0) {
|
|
266
|
-
const structuredThinking = deltas.filter((delta) => delta.kind === "thinking").map((delta) => delta.text);
|
|
267
|
-
const mirrorsCombinedThinking = structuredThinking.length > 1 && mirroredThinking.includes(structuredThinking.join(""));
|
|
268
|
-
deltas = deltas.filter((delta) => delta.kind !== "thinking" || !mirrorsCombinedThinking && !mirroredThinking.includes(delta.text));
|
|
269
|
-
}
|
|
270
|
-
if (typeof topLevelRefusal !== "string" || !topLevelRefusal) return deltas;
|
|
271
|
-
const structuredRefusals = deltas.filter((delta) => delta.kind === "text" && delta.source === "refusal").map((delta) => delta.text);
|
|
272
|
-
if (structuredRefusals.some((refusal) => refusal === topLevelRefusal) || structuredRefusals.length > 1 && structuredRefusals.join("") === topLevelRefusal) return deltas;
|
|
273
|
-
return [...deltas, {
|
|
274
|
-
kind: "text",
|
|
275
|
-
text: topLevelRefusal,
|
|
276
|
-
source: "refusal"
|
|
277
|
-
}];
|
|
278
|
-
}
|
|
279
|
-
function readOpenAICompletionsContentPartDeltas(content) {
|
|
280
|
-
if (typeof content === "string") return content ? [{
|
|
281
|
-
kind: "text",
|
|
282
|
-
text: content
|
|
283
|
-
}] : [];
|
|
284
|
-
if (Array.isArray(content)) return content.flatMap(readOpenAICompletionsContentPartDeltas);
|
|
285
|
-
if (!content || typeof content !== "object") return [];
|
|
286
|
-
const record = content;
|
|
287
|
-
const type = typeof record.type === "string" ? record.type.toLowerCase() : "";
|
|
288
|
-
const extractText = (value) => {
|
|
289
|
-
if (typeof value === "string") return value;
|
|
290
|
-
if (Array.isArray(value)) return value.map(extractText).join("");
|
|
291
|
-
if (value && typeof value === "object") {
|
|
292
|
-
const nested = value;
|
|
293
|
-
return extractText(nested.text ?? nested.content ?? nested.thinking ?? nested.refusal);
|
|
294
|
-
}
|
|
295
|
-
return "";
|
|
296
|
-
};
|
|
297
|
-
const text = extractText(record.text ?? record.content ?? record.thinking ?? record.refusal);
|
|
298
|
-
if (!text) return [];
|
|
299
|
-
if (type.includes("thinking") || type.includes("reasoning")) return [{
|
|
300
|
-
kind: "thinking",
|
|
301
|
-
text
|
|
302
|
-
}];
|
|
303
|
-
if (type === "refusal") return [{
|
|
304
|
-
kind: "text",
|
|
305
|
-
text,
|
|
306
|
-
source: "refusal"
|
|
307
|
-
}];
|
|
308
|
-
if (["text", "output_text"].includes(type) || type.endsWith(".output_text")) return [{
|
|
309
|
-
kind: "text",
|
|
310
|
-
text
|
|
311
|
-
}];
|
|
312
|
-
return [];
|
|
313
|
-
}
|
|
314
|
-
//#endregion
|
|
315
|
-
//#region packages/ai/src/transports/openai-reasoning-compat.ts
|
|
316
|
-
/** Explicit model reasoning-effort compatibility metadata. */
|
|
317
|
-
function readCompatReasoningEffortMap(compat) {
|
|
318
|
-
const rawMap = asOptionalObjectRecord(asOptionalObjectRecord(compat)?.reasoningEffortMap);
|
|
319
|
-
if (!rawMap) return {};
|
|
320
|
-
return Object.fromEntries(Object.entries(rawMap).filter((entry) => typeof entry[1] === "string"));
|
|
321
|
-
}
|
|
322
|
-
/** Resolves the reasoning effort remap for an OpenAI-compatible model. */
|
|
323
|
-
function resolveOpenAIReasoningEffortMap(model, fallbackMap = {}) {
|
|
324
|
-
return {
|
|
325
|
-
...fallbackMap,
|
|
326
|
-
...readCompatReasoningEffortMap(model.compat)
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
//#endregion
|
|
330
|
-
//#region packages/ai/src/providers/openai-request-reasoning.ts
|
|
331
|
-
/** Preserve explicit off until the selected route maps it to its native value. */
|
|
332
|
-
function resolveOpenAISimpleReasoningEffort(model, reasoning) {
|
|
333
|
-
return reasoning === void 0 ? void 0 : clampThinkingLevel(model, reasoning);
|
|
334
|
-
}
|
|
335
|
-
function resolveOpenAIRequestReasoning(model, reasoning) {
|
|
336
|
-
const requested = normalizeOpenAIReasoningEffort(reasoning ?? "off");
|
|
337
|
-
const modelLevel = MODEL_CATALOG_THINKING_LEVELS.find((candidate) => candidate === requested);
|
|
338
|
-
const modelMapped = modelLevel ? model.thinkingLevelMap?.[modelLevel] : void 0;
|
|
339
|
-
const mapped = modelMapped === null ? null : resolveOpenAIReasoningEffortMapping(requested, resolveOpenAIReasoningEffortMap(model)) ?? modelMapped;
|
|
340
|
-
const intent = mapped !== void 0 ? mapped?.trim() : reasoning === void 0 ? void 0 : requested;
|
|
341
|
-
const normalizedIntent = normalizeOpenAIReasoningEffort(intent ?? "off");
|
|
342
|
-
const supported = resolveOpenAIModelReasoningEfforts(model);
|
|
343
|
-
const effort = !model.reasoning || supported?.length === 0 || intent === void 0 ? void 0 : supported === void 0 ? mapped !== void 0 ? intent : requested === "off" ? "none" : requested : resolveOpenAIReasoningEffortForModel({
|
|
344
|
-
model,
|
|
345
|
-
effort: requested,
|
|
346
|
-
fallbackMap: { [requested]: intent }
|
|
347
|
-
});
|
|
348
|
-
return {
|
|
349
|
-
effort: effort === "none" && resolveOpenAIThinkingApi(model.api) === "openai-chatgpt-responses" && !supportsOpenAIReasoningEffort(model.id === "gpt-6-sol" || model.id === "gpt-6-luna" ? model : { compat: model.compat }, "none") ? void 0 : effort,
|
|
350
|
-
thinkingEnabled: intent === void 0 ? void 0 : model.reasoning && normalizedIntent !== "off" && normalizedIntent !== "none"
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
//#endregion
|
|
354
|
-
//#region packages/ai/src/providers/openai-tool-projection.ts
|
|
355
|
-
function unreadableToolDiagnostic(toolIndex) {
|
|
356
|
-
return {
|
|
357
|
-
toolIndex,
|
|
358
|
-
violations: [`tool[${toolIndex}] is unreadable`]
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
/** Snapshots direct/custom tool descriptors before OpenAI payload construction. */
|
|
362
|
-
function projectOpenAITools(tools) {
|
|
363
|
-
return projectOpenAIToolDescriptors(tools);
|
|
364
|
-
}
|
|
365
|
-
/** Package-private facts are consumed before the projection or payload can escape. */
|
|
366
|
-
function prepareOpenAITools(tools) {
|
|
367
|
-
const schemas = /* @__PURE__ */ new Map();
|
|
368
|
-
return {
|
|
369
|
-
projection: projectOpenAIToolDescriptors(tools, schemas),
|
|
370
|
-
schemas
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
function projectOpenAIToolDescriptors(tools, schemas) {
|
|
374
|
-
let inputToolCount;
|
|
375
|
-
try {
|
|
376
|
-
inputToolCount = tools.length;
|
|
377
|
-
} catch {
|
|
378
|
-
return {
|
|
379
|
-
inputToolCount: 0,
|
|
380
|
-
tools: [],
|
|
381
|
-
diagnostics: [unreadableToolDiagnostic(0)]
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
const projectedTools = [];
|
|
385
|
-
const diagnostics = [];
|
|
386
|
-
for (let toolIndex = 0; toolIndex < inputToolCount; toolIndex += 1) {
|
|
387
|
-
let tool;
|
|
388
|
-
try {
|
|
389
|
-
const candidate = tools[toolIndex];
|
|
390
|
-
if (!candidate) {
|
|
391
|
-
diagnostics.push(unreadableToolDiagnostic(toolIndex));
|
|
392
|
-
continue;
|
|
393
|
-
}
|
|
394
|
-
tool = candidate;
|
|
395
|
-
} catch {
|
|
396
|
-
diagnostics.push(unreadableToolDiagnostic(toolIndex));
|
|
397
|
-
continue;
|
|
398
|
-
}
|
|
399
|
-
let name;
|
|
400
|
-
try {
|
|
401
|
-
name = tool.name;
|
|
402
|
-
} catch {
|
|
403
|
-
diagnostics.push({
|
|
404
|
-
toolIndex,
|
|
405
|
-
violations: [`tool[${toolIndex}].name is unreadable`]
|
|
406
|
-
});
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
if (typeof name !== "string" || !name) {
|
|
410
|
-
diagnostics.push({
|
|
411
|
-
toolIndex,
|
|
412
|
-
violations: [`tool[${toolIndex}].name is empty`]
|
|
413
|
-
});
|
|
414
|
-
continue;
|
|
415
|
-
}
|
|
416
|
-
let parameters;
|
|
417
|
-
try {
|
|
418
|
-
parameters = tool.parameters;
|
|
419
|
-
} catch {
|
|
420
|
-
diagnostics.push({
|
|
421
|
-
toolIndex,
|
|
422
|
-
toolName: name,
|
|
423
|
-
violations: [`${name}.parameters is unreadable`]
|
|
424
|
-
});
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
const prepared = schemas ? prepareRuntimeToolInputSchema(parameters ?? {}, `${name}.parameters`) : void 0;
|
|
428
|
-
const schemaProjection = prepared?.projection ?? projectRuntimeToolInputSchema(parameters ?? {}, `${name}.parameters`);
|
|
429
|
-
if (!isRecord(schemaProjection.schema) || schemaProjection.violations.length > 0) {
|
|
430
|
-
diagnostics.push({
|
|
431
|
-
toolIndex,
|
|
432
|
-
toolName: name,
|
|
433
|
-
violations: schemaProjection.violations.length > 0 ? schemaProjection.violations : [`${name}.parameters must be a JSON object schema`]
|
|
434
|
-
});
|
|
435
|
-
continue;
|
|
436
|
-
}
|
|
437
|
-
if (prepared?.normalization) schemas?.set(schemaProjection.schema, prepared.normalization);
|
|
438
|
-
let descriptionValue;
|
|
439
|
-
try {
|
|
440
|
-
descriptionValue = tool.description;
|
|
441
|
-
} catch {}
|
|
442
|
-
const description = typeof descriptionValue === "string" ? descriptionValue : void 0;
|
|
443
|
-
projectedTools.push({
|
|
444
|
-
toolIndex,
|
|
445
|
-
name,
|
|
446
|
-
...description !== void 0 ? { description } : {},
|
|
447
|
-
parameters: schemaProjection.schema
|
|
448
|
-
});
|
|
449
|
-
}
|
|
450
|
-
return {
|
|
451
|
-
inputToolCount,
|
|
452
|
-
tools: projectedTools,
|
|
453
|
-
diagnostics
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
function reconcileToolChoice(choice, projection, responses) {
|
|
457
|
-
const label = responses ? "OpenAI Responses" : "OpenAI Chat Completions";
|
|
458
|
-
if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
|
|
459
|
-
if (choice === "required") {
|
|
460
|
-
if (projection.tools.length === 0) throw new Error(`${label} tool_choice requires a tool, but no tools survived schema conversion`);
|
|
461
|
-
return choice;
|
|
462
|
-
}
|
|
463
|
-
if (choice === "none" || !isRecord(choice)) return choice;
|
|
464
|
-
const choiceType = choice.type;
|
|
465
|
-
if (!responses && choiceType === "custom") throw new Error("OpenAI Chat Completions custom tool_choice is unsupported because this adapter emits function tools only");
|
|
466
|
-
if (choiceType === "function") {
|
|
467
|
-
const functionChoice = responses ? choice : choice.function;
|
|
468
|
-
const functionName = isRecord(functionChoice) ? functionChoice.name : void 0;
|
|
469
|
-
if (typeof functionName !== "string") return choice;
|
|
470
|
-
if (!projection.tools.some((tool) => tool.name === functionName)) throw new Error(`${label} tool_choice requested unavailable tool "${functionName}" after schema conversion`);
|
|
471
|
-
return responses ? {
|
|
472
|
-
type: "function",
|
|
473
|
-
name: functionName
|
|
474
|
-
} : {
|
|
475
|
-
type: "function",
|
|
476
|
-
function: { name: functionName }
|
|
477
|
-
};
|
|
478
|
-
}
|
|
479
|
-
if (choiceType !== "allowed_tools") return choice;
|
|
480
|
-
const allowedConfig = responses ? choice : choice.allowed_tools;
|
|
481
|
-
if (!isRecord(allowedConfig)) return choice;
|
|
482
|
-
const { mode, tools } = allowedConfig;
|
|
483
|
-
if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
|
|
484
|
-
const responseTools = [];
|
|
485
|
-
const completionTools = [];
|
|
486
|
-
for (const tool of tools) {
|
|
487
|
-
if (!isRecord(tool) || tool.type !== "function") {
|
|
488
|
-
if (responses) responseTools.push(tool);
|
|
489
|
-
continue;
|
|
490
|
-
}
|
|
491
|
-
const functionChoice = responses ? tool : tool.function;
|
|
492
|
-
const functionName = isRecord(functionChoice) ? functionChoice.name : void 0;
|
|
493
|
-
if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) {
|
|
494
|
-
if (responses) responseTools.push({
|
|
495
|
-
type: "function",
|
|
496
|
-
name: functionName
|
|
497
|
-
});
|
|
498
|
-
else completionTools.push({
|
|
499
|
-
type: "function",
|
|
500
|
-
function: { name: functionName }
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
if (responseTools.length === 0 && completionTools.length === 0) {
|
|
505
|
-
if (mode === "auto") return "none";
|
|
506
|
-
throw new Error(`${label} tool_choice requires a tool, but no allowed tools survived schema conversion`);
|
|
507
|
-
}
|
|
508
|
-
return responses ? {
|
|
509
|
-
type: "allowed_tools",
|
|
510
|
-
mode,
|
|
511
|
-
tools: responseTools
|
|
512
|
-
} : {
|
|
513
|
-
type: "allowed_tools",
|
|
514
|
-
allowed_tools: {
|
|
515
|
-
mode,
|
|
516
|
-
tools: completionTools
|
|
517
|
-
}
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
/** Keeps Responses tool choices aligned with surviving function schemas. */
|
|
521
|
-
function reconcileOpenAIResponsesToolChoice(choice, projection) {
|
|
522
|
-
return reconcileToolChoice(choice, projection, true);
|
|
523
|
-
}
|
|
524
|
-
/** Keeps Chat Completions tool choices aligned with surviving function schemas. */
|
|
525
|
-
function reconcileOpenAICompletionsToolChoice(choice, projection) {
|
|
526
|
-
return reconcileToolChoice(choice, projection, false);
|
|
527
|
-
}
|
|
528
|
-
//#endregion
|
|
529
|
-
//#region packages/ai/src/transports/openai-transport-params.ts
|
|
530
|
-
const MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 256;
|
|
531
|
-
const loggedOpenAIStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
|
|
532
|
-
const OPENAI_COMPLETIONS_APIS = /* @__PURE__ */ new Set(["openai-completions", "openclaw-openai-completions-transport"]);
|
|
533
|
-
function readToolPayloadField(record, field) {
|
|
534
|
-
try {
|
|
535
|
-
return Object.hasOwn(record, field) ? record[field] : void 0;
|
|
536
|
-
} catch {
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
function readCodeModePayloadToolName(tool) {
|
|
541
|
-
if (!isRecord(tool)) return;
|
|
542
|
-
const name = readToolPayloadField(tool, "name");
|
|
543
|
-
if (typeof name === "string") return name;
|
|
544
|
-
const fn = readToolPayloadField(tool, "function");
|
|
545
|
-
if (!isRecord(fn)) return;
|
|
546
|
-
const fnName = readToolPayloadField(fn, "name");
|
|
547
|
-
return typeof fnName === "string" ? fnName : void 0;
|
|
548
|
-
}
|
|
549
|
-
function readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes) {
|
|
550
|
-
if (!isRecord(tool)) return;
|
|
551
|
-
const type = readToolPayloadField(tool, "type");
|
|
552
|
-
if (typeof type === "string" && allowedHostedToolTypes?.has(type)) {
|
|
553
|
-
try {
|
|
554
|
-
if (Object.hasOwn(tool, "name") || Object.hasOwn(tool, "function") || Object.hasOwn(tool, "functionDeclarations") || Object.hasOwn(tool, "function_declarations")) return false;
|
|
555
|
-
} catch {
|
|
556
|
-
return false;
|
|
557
|
-
}
|
|
558
|
-
return `hosted:${type}`;
|
|
559
|
-
}
|
|
560
|
-
const name = readCodeModePayloadToolName(tool);
|
|
561
|
-
return typeof name === "string" && isCodeModeModelVisibleToolName(name, visibleToolNames) ? `client:${name}` : void 0;
|
|
562
|
-
}
|
|
563
|
-
function readCodeModePayloadToolIdentities(payload) {
|
|
564
|
-
if (!isRecord(payload)) return [];
|
|
565
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
566
|
-
if (!Array.isArray(tools)) return [];
|
|
567
|
-
return tools.flatMap((tool) => {
|
|
568
|
-
if (!isRecord(tool)) return [];
|
|
569
|
-
const identities = [];
|
|
570
|
-
const name = readCodeModePayloadToolName(tool);
|
|
571
|
-
if (name) identities.push(`client:${name}`);
|
|
572
|
-
for (const key of ["functionDeclarations", "function_declarations"]) {
|
|
573
|
-
const declarations = readToolPayloadField(tool, key);
|
|
574
|
-
if (!Array.isArray(declarations)) continue;
|
|
575
|
-
for (const declaration of declarations) {
|
|
576
|
-
const declarationName = readCodeModePayloadToolName(declaration);
|
|
577
|
-
if (declarationName) identities.push(`client:${declarationName}`);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
const type = readToolPayloadField(tool, "type");
|
|
581
|
-
if (typeof type === "string" && type !== "function") identities.push(`hosted:${type}`);
|
|
582
|
-
return identities;
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
function filterCodeModePayloadTools(payload, visibleToolNames, allowedHostedToolTypes, observer) {
|
|
586
|
-
if (!isRecord(payload)) return;
|
|
587
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
588
|
-
if (!Array.isArray(tools)) return;
|
|
589
|
-
const beforeToolIdentities = observer ? readCodeModePayloadToolIdentities(payload) : void 0;
|
|
590
|
-
payload.tools = tools.flatMap((tool) => {
|
|
591
|
-
const identity = readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes);
|
|
592
|
-
if (identity) return [tool];
|
|
593
|
-
if (identity === false) return [];
|
|
594
|
-
if (!isRecord(tool)) return [];
|
|
595
|
-
const filteredGroups = {};
|
|
596
|
-
for (const key of ["functionDeclarations", "function_declarations"]) {
|
|
597
|
-
const declarations = readToolPayloadField(tool, key);
|
|
598
|
-
if (!Array.isArray(declarations)) continue;
|
|
599
|
-
const filtered = declarations.filter((declaration) => {
|
|
600
|
-
const declarationName = readCodeModePayloadToolName(declaration);
|
|
601
|
-
return typeof declarationName === "string" && isCodeModeModelVisibleToolName(declarationName, visibleToolNames);
|
|
602
|
-
});
|
|
603
|
-
if (filtered.length > 0) filteredGroups[key] = filtered;
|
|
604
|
-
}
|
|
605
|
-
return Object.keys(filteredGroups).length > 0 ? [filteredGroups] : [];
|
|
606
|
-
});
|
|
607
|
-
if (beforeToolIdentities) observer?.({
|
|
608
|
-
beforeToolIdentities,
|
|
609
|
-
afterToolIdentities: readCodeModePayloadToolIdentities(payload)
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
function resolveCodeModeResponsesVisibleToolNames(context) {
|
|
613
|
-
return new Set((context.tools ?? []).map(readCodeModePayloadToolName).filter((name) => typeof name === "string"));
|
|
614
|
-
}
|
|
615
|
-
function enforceCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes, observer) {
|
|
616
|
-
if (!isRecord(payload)) return;
|
|
617
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
618
|
-
if (!Array.isArray(tools)) return;
|
|
619
|
-
const beforeToolIdentities = observer ? readCodeModePayloadToolIdentities(payload) : void 0;
|
|
620
|
-
payload.tools = tools.filter((tool) => Boolean(readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes)));
|
|
621
|
-
if (beforeToolIdentities) observer?.({
|
|
622
|
-
beforeToolIdentities,
|
|
623
|
-
afterToolIdentities: readCodeModePayloadToolIdentities(payload)
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
function assertCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes) {
|
|
627
|
-
const tools = isRecord(payload) ? readToolPayloadField(payload, "tools") : void 0;
|
|
628
|
-
if (!Array.isArray(tools)) throw new Error("Code mode payload tool surface violation: expected exec,wait; got no tools");
|
|
629
|
-
const identities = tools.map((tool) => readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes));
|
|
630
|
-
const names = identities.flatMap((identity) => typeof identity === "string" && identity.startsWith("client:") ? [identity.slice(7)] : []).toSorted((left, right) => left.localeCompare(right));
|
|
631
|
-
if (names.length >= 2 && identities.every((identity) => typeof identity === "string") && new Set(identities).size === identities.length && names.includes("exec") && names.includes("wait")) return;
|
|
632
|
-
throw new Error(`Code mode payload tool surface violation: expected exec,wait plus direct-only tools; got ${names.length > 0 ? names.join(",") : "none"}`);
|
|
633
|
-
}
|
|
634
|
-
function resolveOpenAIStrictToolFlagWithDiagnostics(projection, strictSetting, context) {
|
|
635
|
-
const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
|
|
636
|
-
if (strictSetting === true && strict === false) getAiTransportHost().logDebug("openai-transport", () => {
|
|
637
|
-
const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
|
|
638
|
-
const key = sha256Hex(JSON.stringify({
|
|
639
|
-
transport: context.transport,
|
|
640
|
-
provider: context.model.provider ?? null,
|
|
641
|
-
model: context.model.id ?? null,
|
|
642
|
-
diagnostics: diagnostics.map((entry) => ({
|
|
643
|
-
toolIndex: entry.toolIndex,
|
|
644
|
-
toolName: entry.toolName ?? null,
|
|
645
|
-
violations: entry.violations
|
|
646
|
-
}))
|
|
647
|
-
}));
|
|
648
|
-
if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.has(key)) return null;
|
|
649
|
-
if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.size >= MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedOpenAIStrictToolDowngradeDiagnosticKeys.clear();
|
|
650
|
-
loggedOpenAIStrictToolDowngradeDiagnosticKeys.add(key);
|
|
651
|
-
const sample = diagnostics.slice(0, 5).map((entry) => ({
|
|
652
|
-
tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
|
|
653
|
-
violations: entry.violations.slice(0, 8)
|
|
654
|
-
}));
|
|
655
|
-
return {
|
|
656
|
-
message: `OpenAI ${context.transport} tool schema strict mode downgraded to strict=false for ${context.model.provider ?? "unknown"}/${context.model.id ?? "unknown"} because ${diagnostics.length} tool schema(s) are not strict-compatible`,
|
|
657
|
-
data: {
|
|
658
|
-
transport: context.transport,
|
|
659
|
-
provider: context.model.provider,
|
|
660
|
-
model: context.model.id,
|
|
661
|
-
incompatibleToolCount: diagnostics.length,
|
|
662
|
-
sample
|
|
663
|
-
}
|
|
664
|
-
};
|
|
665
|
-
});
|
|
666
|
-
return strict;
|
|
667
|
-
}
|
|
668
|
-
function buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId, cacheRetention) {
|
|
669
|
-
const providerHeaders = { ...model.headers };
|
|
670
|
-
if (model.provider === "github-copilot") Object.assign(providerHeaders, getAiTransportHost().buildCopilotDynamicHeaders(context.messages));
|
|
671
|
-
if (OPENAI_COMPLETIONS_APIS.has(model.api) && sessionId && cacheRetention !== "none") {
|
|
672
|
-
const { sessionAffinity } = resolveOpenAICompletionsCompat(model);
|
|
673
|
-
if (sessionAffinity !== "none") {
|
|
674
|
-
const affinityValue = clampOpenAIPromptCacheKey(sessionId) ?? sessionId;
|
|
675
|
-
const affinityHeaders = sessionAffinity === "openrouter" ? ["x-session-id"] : [
|
|
676
|
-
"session_id",
|
|
677
|
-
"x-client-request-id",
|
|
678
|
-
"x-session-affinity"
|
|
679
|
-
];
|
|
680
|
-
const configuredHeaders = new Set(Object.keys(providerHeaders).map((key) => key.toLowerCase()));
|
|
681
|
-
for (const name of affinityHeaders) if (!configuredHeaders.has(name)) providerHeaders[name] = affinityValue;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
const callerHeaders = {
|
|
685
|
-
...optionHeaders,
|
|
686
|
-
...turnHeaders
|
|
687
|
-
};
|
|
688
|
-
const resolvedHeaders = getAiTransportHost().resolveProviderRequestHeaders({
|
|
689
|
-
provider: model.provider,
|
|
690
|
-
api: model.api,
|
|
691
|
-
baseUrl: model.baseUrl,
|
|
692
|
-
providerHeaders,
|
|
693
|
-
callerHeaders: Object.keys(callerHeaders).length > 0 ? callerHeaders : void 0,
|
|
694
|
-
precedence: "caller-wins",
|
|
695
|
-
model
|
|
696
|
-
}) ?? {};
|
|
697
|
-
const sendSessionIdHeader = (OPENAI_RESPONSES_APIS.has(model.api) && model.compat && "sendSessionIdHeader" in model.compat ? model.compat?.sendSessionIdHeader : void 0) ?? usesNativeOpenAICodexResponsesBackend(model);
|
|
698
|
-
if (sessionId && cacheRetention !== "none" && sendSessionIdHeader && !Object.keys(resolvedHeaders).some((key) => normalizeLowercaseStringOrEmpty(key) === "session_id")) resolvedHeaders.session_id = clampOpenAIPromptCacheKey(sessionId) ?? sessionId;
|
|
699
|
-
return resolveOpencodeSessionHeaders(model, {
|
|
700
|
-
sessionId,
|
|
701
|
-
headers: resolvedHeaders
|
|
702
|
-
}) ?? resolvedHeaders;
|
|
703
|
-
}
|
|
704
|
-
function buildOpenAISdkClientOptions(model) {
|
|
705
|
-
const timeout = resolveModelRequestTimeoutMs(model);
|
|
706
|
-
return {
|
|
707
|
-
...timeout === void 0 ? {} : { timeout },
|
|
708
|
-
maxRetries: 0
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
function buildOpenAISdkRequestOptions(model, signal, options) {
|
|
712
|
-
const timeout = resolveModelRequestTimeoutMs(model, options?.timeoutMs);
|
|
713
|
-
const headers = options?.stream === true && usesNativeOpenAICodexResponsesBackend(model) ? { Accept: "text/event-stream" } : void 0;
|
|
714
|
-
if (timeout === void 0 && !signal && !headers) return;
|
|
715
|
-
return {
|
|
716
|
-
...headers ? { headers } : {},
|
|
717
|
-
...signal ? { signal } : {},
|
|
718
|
-
...timeout !== void 0 ? { timeout } : {},
|
|
719
|
-
maxRetries: 0
|
|
720
|
-
};
|
|
721
|
-
}
|
|
722
|
-
function getCompat(model) {
|
|
723
|
-
const resolved = resolveOpenAICompletionsCompat(model);
|
|
724
|
-
const compat = model.compat ?? {};
|
|
725
|
-
return {
|
|
726
|
-
...resolved,
|
|
727
|
-
reasoningEffortMap: resolveOpenAIReasoningEffortMap(model, {}),
|
|
728
|
-
openRouterRouting: resolved.openRouterRouting ?? {},
|
|
729
|
-
vercelGatewayRouting: resolved.vercelGatewayRouting,
|
|
730
|
-
requiresStringContent: compat.requiresStringContent ?? false,
|
|
731
|
-
strictMessageKeys: compat.strictMessageKeys === true
|
|
732
|
-
};
|
|
733
|
-
}
|
|
734
|
-
//#endregion
|
|
735
|
-
export { redactIdentifier as A, log as C, readOpenAICompletionsReasoningBatch as D, readOpenAICompletionsContentDeltas as E, resolveOpenAIClientBaseUrl as O, isOpenAICompletionsThinkingEnabled as S, parseOpenAICompletionsUsage as T, resolveOpenAIReasoningEffortMap as _, enforceCodeModeResponsesToolSurface as a, createOpenAIResponseHook as b, readCodeModePayloadToolName as c, prepareOpenAITools as d, projectOpenAITools as f, resolveOpenAISimpleReasoningEffort as g, resolveOpenAIRequestReasoning as h, buildOpenAISdkRequestOptions as i, sha256Hex as j, resolvePromptCacheKey as k, resolveCodeModeResponsesVisibleToolNames as l, reconcileOpenAIResponsesToolChoice as m, buildOpenAIClientHeaders as n, filterCodeModePayloadTools as o, reconcileOpenAICompletionsToolChoice as p, buildOpenAISdkClientOptions as r, getCompat as s, assertCodeModeResponsesToolSurface as t, resolveOpenAIStrictToolFlagWithDiagnostics as u, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP as v, measureUtf8AppendBytes as w, createResponseModelTracker as x, createOpenAIProviderAcceptanceHook as y };
|