@openclaw/ai 2026.9.1 → 2026.9.3
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 +3 -2
- package/dist/anthropic-CZy5U0NY.mjs +376 -0
- package/dist/anthropic-payload-policy-wuRCb6MH.d.mts +85 -0
- package/dist/anthropic-stream-reducer-B_yo_7pf.mjs +1669 -0
- package/dist/{api-registry-Cs6HGNqY.d.mts → api-registry-CB1-1oQ2.d.mts} +2 -2
- package/dist/assistant-output-iqnlJCV2.mjs +16 -0
- package/dist/assistant-text-phase-C20rxWwP.mjs +55 -0
- package/dist/{azure-openai-responses-CN4Fy5zV.mjs → azure-openai-responses-Crpa40QR.mjs} +5 -5
- package/dist/{base64-CEFBpSkN.mjs → base64-D-su8YVo.mjs} +1 -27
- package/dist/{diagnostics-KhXK-QJI.mjs → diagnostics-dV98PqIy.mjs} +96 -21
- package/dist/diagnostics.d.mts +3 -1
- package/dist/diagnostics.mjs +3 -3
- package/dist/{event-stream-vK_7r3bj.d.mts → event-stream-C1Z2piyk.d.mts} +11 -3
- package/dist/{event-stream-uSMZJ3FA.mjs → event-stream-D8PARQfL.mjs} +48 -10
- package/dist/event-stream-I_GlBsuZ.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-B37TB3rB.mjs} +3 -10
- package/dist/github-copilot-request-facts-BTEBMeOv.mjs +16 -0
- package/dist/{google-CC-nrwXg.mjs → google-BDPriaVe.mjs} +10 -10
- package/dist/google-messages-CVn9eFpF.mjs +449 -0
- package/dist/google-shared-BedY23XS.mjs +185 -0
- package/dist/{google-vertex-DCr0pyzQ.mjs → google-vertex-DMz8XQCn.mjs} +7 -6
- package/dist/{host-BIaiBURL.mjs → host-CWuF-sS3.mjs} +84 -34
- package/dist/{host-BztR4tQj.d.mts → host-DK3wmS3e.d.mts} +3 -3
- package/dist/host-policy-CAopLRKA.mjs +37 -0
- package/dist/{index-AfaxKT8w.d.mts → index-CQ6LTHw8.d.mts} +11 -5
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +5 -5
- package/dist/internal/anthropic.d.mts +14 -11
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/google-model-family.d.mts +5 -0
- package/dist/internal/google-model-family.mjs +15 -0
- package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
- package/dist/internal/openai-responses-payload-policy.mjs +1 -1
- package/dist/internal/openai.d.mts +8 -103
- package/dist/internal/openai.mjs +10 -10
- package/dist/internal/retry-after.d.mts +2 -4
- package/dist/internal/retry-after.mjs +57 -8
- package/dist/internal/runtime.d.mts +7 -6
- package/dist/internal/runtime.mjs +8 -7
- package/dist/internal/shared.d.mts +14 -3
- package/dist/internal/shared.mjs +6 -4
- package/dist/internal/tool-schema.d.mts +63 -0
- package/dist/internal/tool-schema.mjs +3 -0
- package/dist/{json-parse-BuAJEbdW.mjs → json-parse-Dw_hnxsA.mjs} +1 -1
- package/dist/{mistral-B7etBd_H.mjs → mistral--m-Jm6VZ.mjs} +16 -38
- package/dist/model-transport-url-DKocrEsb.d.mts +28 -0
- package/dist/{openai-chatgpt-responses-BAJ4gq3i.mjs → openai-chatgpt-responses-nDZccFW-.mjs} +62 -54
- package/dist/openai-completions-KuoZyx0d.mjs +187 -0
- package/dist/{openai-completions-compat-4IjSBpr6.d.mts → openai-completions-compat-CXn3T1we.d.mts} +26 -4
- package/dist/{openai-completions-stream-DZjwK8vp.mjs → openai-completions-stream-BQk3SkLD.mjs} +621 -451
- package/dist/openai-prompt-cache-BI0rkM-5.mjs +220 -0
- package/dist/openai-prompt-cache-rrutvqxq.d.mts +16 -0
- package/dist/openai-provider-client-ha_WxTyj.mjs +24 -0
- package/dist/openai-reasoning-effort-BK7FbcLT.mjs +167 -0
- package/dist/{openai-responses-BEUlxfDu.mjs → openai-responses-D99dOzKI.mjs} +14 -32
- package/dist/{openai-responses-compaction-window-DO7yV7az.mjs → openai-responses-compaction-window-D5jbzCi3.mjs} +7 -159
- package/dist/{openai-responses-contracts-bPzSN_Ba.d.mts → openai-responses-contracts-B55afwRo.d.mts} +12 -4
- package/dist/{openai-responses-prompt-observer-internal-C7x4IK7r.mjs → openai-responses-prompt-observer-internal-tApyTLVu.mjs} +3 -3
- package/dist/{openai-responses-shared-DiAdpNAM.mjs → openai-responses-shared-ZyQEzS5i.mjs} +217 -212
- package/dist/openai-tool-projection-793cE3QX.d.mts +37 -0
- package/dist/{openai-tool-schema-BMiHFH36.mjs → openai-tool-schema-CzjyYXun.mjs} +53 -583
- package/dist/openai-tool-schema-ynZBgqW-.d.mts +38 -0
- package/dist/openai-transport-params-DNasp2fU.mjs +674 -0
- package/dist/{provider-error-B6EGq6gg.mjs → provider-error-C6TbKiey.mjs} +29 -13
- package/dist/{provider-options-CxFPtvh7.d.mts → provider-options-BXr9Ec83.d.mts} +19 -42
- package/dist/provider-replay-context-BuSUaAk5.mjs +21 -0
- package/dist/{provider-transcript-transform-WvJmFUAf.mjs → provider-transcript-transform-pPmUIwKt.mjs} +1 -1
- package/dist/provider-types-CAV0Og3m.d.mts +29 -0
- package/dist/provider-types.d.mts +6 -31
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +11 -11
- package/dist/{reasoning-tag-text-partitioner-C-4uedDb.mjs → reasoning-tag-text-partitioner-BQBi4B9d.mjs} +90 -35
- package/dist/record-coerce-DwRYMj3t.mjs +32 -0
- package/dist/retry-after-CdCURCVg.d.mts +15 -0
- package/dist/{sanitize-unicode-S6binQG-.mjs → sanitize-unicode-Bb-v9meu.mjs} +1 -1
- package/dist/session-affinity-CCH7eYdB.mjs +20 -0
- package/dist/{simple-options-0PLDyJ-d.mjs → simple-options-tcKOqnpF.mjs} +3 -3
- package/dist/{src-C8U7lkoa.mjs → src-B2Q_6G8V.mjs} +10 -2
- package/dist/{stream-first-event-timeout-DcNjoFQE.mjs → stream-first-event-timeout-2hfrquuz.mjs} +1 -1
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{string-normalization--fwJ4S2q.mjs → string-normalization-CmLIasuf.mjs} +1 -1
- package/dist/{tool-schema-json-projection-BtZiml7r.mjs → tool-schema-json-projection-ClptDdAO.mjs} +2 -38
- package/dist/{transport-stream-shared-CytPVLIg.mjs → transport-stream-shared-Cu3ZPhNW.mjs} +5 -5
- package/dist/{transport-stream-shared-BrvFTkoO.d.mts → transport-stream-shared-DOxpGJ-H.d.mts} +4 -4
- package/dist/transport-utils-CCooe-cr.mjs +121 -0
- package/dist/transports.d.mts +114 -41
- package/dist/transports.mjs +796 -1596
- package/dist/types-BADKjDBI.d.mts +1 -0
- package/dist/{types-DbrhszyQ.d.mts → types-Dy1q0CSu.d.mts} +101 -64
- package/dist/types.d.mts +6 -6
- package/dist/types.mjs +4 -4
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-CJZtym2g.mjs → validation-BDzVDnTs.mjs} +9 -1
- package/dist/{validation-BOwtcl9X.d.mts → validation-CaFUZN9B.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +14 -4
- package/dist/anthropic-compaction-replay-OMJZ0uyo.mjs +0 -838
- package/dist/anthropic-hk7F7ptG.mjs +0 -883
- package/dist/anthropic-payload-policy-DBT1itQ-.d.mts +0 -51
- package/dist/event-stream-DeDhbCc5.d.mts +0 -1
- package/dist/google-shared-CjPY0hZM.mjs +0 -634
- package/dist/google-thinking-level-C-V3tecN.mjs +0 -9
- package/dist/openai-completions-D0QZ0AyB.mjs +0 -403
- package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
- package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
- package/dist/transport-utils-CtuS1Upe.mjs +0 -138
- package/dist/types-B5EFUmXs.d.mts +0 -1
- package/dist/utf16-slice-qz3nsy87.mjs +0 -84
|
@@ -1,433 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { r as uniqueValues, t as normalizeStringEntries } from "./string-normalization--fwJ4S2q.mjs";
|
|
5
|
-
import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
|
|
6
|
-
import { t as projectRuntimeToolInputSchema } from "./tool-schema-json-projection-BtZiml7r.mjs";
|
|
7
|
-
import { C as headersToRecord, _ as transportAbortError, f as notifyProviderHttpResponse } from "./transport-stream-shared-CytPVLIg.mjs";
|
|
8
|
-
//#region packages/ai/src/transports/openai-transport-shared.ts
|
|
9
|
-
/** Shared options, usage shape, cache identity, ordering, and stream scheduling for OpenAI APIs. */
|
|
10
|
-
const MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS = 12;
|
|
11
|
-
const MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS = 64;
|
|
12
|
-
const GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP = "skip_thought_signature_validator";
|
|
13
|
-
const log = {
|
|
14
|
-
debug(message, data) {
|
|
15
|
-
getAiTransportHost().logDebug("openai-transport", () => ({
|
|
16
|
-
message,
|
|
17
|
-
data
|
|
18
|
-
}));
|
|
19
|
-
},
|
|
20
|
-
info(message, data) {
|
|
21
|
-
getAiTransportHost().logInfo("openai-transport", message, data);
|
|
22
|
-
},
|
|
23
|
-
warn(message, data) {
|
|
24
|
-
getAiTransportHost().logWarn("openai-transport", message, data);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
function resolveOpenAIClientBaseUrl(model, baseUrl = model.baseUrl) {
|
|
28
|
-
if (baseUrl?.trim()) return baseUrl;
|
|
29
|
-
if (model.provider.trim().toLowerCase() === "openai") return;
|
|
30
|
-
throw new Error(`Provider "${model.provider}" requires an explicit base URL before using an OpenAI-compatible API. Reload provider metadata or configure an endpoint.`);
|
|
31
|
-
}
|
|
32
|
-
const EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH = {
|
|
33
|
-
deltas: [],
|
|
34
|
-
mirroredThinking: [],
|
|
35
|
-
hasThinking: false,
|
|
36
|
-
hasVisibleText: false
|
|
37
|
-
};
|
|
38
|
-
const OPENAI_COMPLETIONS_REASONING_FIELDS = [
|
|
39
|
-
"reasoning_content",
|
|
40
|
-
"reasoning",
|
|
41
|
-
"reasoning_text"
|
|
42
|
-
];
|
|
43
|
-
function appendOpenAICompletionsReasoningDelta(batch, next) {
|
|
44
|
-
if (next.kind === "thinking") batch.hasThinking = true;
|
|
45
|
-
else batch.hasVisibleText = true;
|
|
46
|
-
const previous = batch.deltas[batch.deltas.length - 1];
|
|
47
|
-
if (!previous || previous.kind !== next.kind) {
|
|
48
|
-
batch.deltas.push(next);
|
|
49
|
-
if (next.kind === "thinking") batch.mirroredThinking.push(next.text);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (next.kind === "thinking" && previous.kind === "thinking") {
|
|
53
|
-
if (previous.signature !== next.signature) {
|
|
54
|
-
batch.deltas.push(next);
|
|
55
|
-
batch.mirroredThinking.push(next.text);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
previous.text += next.text;
|
|
59
|
-
batch.mirroredThinking[batch.mirroredThinking.length - 1] += next.text;
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
previous.text += next.text;
|
|
63
|
-
}
|
|
64
|
-
function createOpenAICompletionsReasoningBatch() {
|
|
65
|
-
return {
|
|
66
|
-
deltas: [],
|
|
67
|
-
mirroredThinking: [],
|
|
68
|
-
hasThinking: false,
|
|
69
|
-
hasVisibleText: false
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function readOpenAICompletionsReasoningBatch(delta, visibleReasoningDetailTypes) {
|
|
73
|
-
let batch;
|
|
74
|
-
const reasoningDetails = delta.reasoning_details;
|
|
75
|
-
let usedReasoningThinkingDetails = false;
|
|
76
|
-
if (Array.isArray(reasoningDetails)) for (const item of reasoningDetails) {
|
|
77
|
-
if (!isRecord(item)) continue;
|
|
78
|
-
const detail = item;
|
|
79
|
-
if (typeof detail.text !== "string" || !detail.text) continue;
|
|
80
|
-
if (detail.type === "reasoning.text") {
|
|
81
|
-
usedReasoningThinkingDetails = true;
|
|
82
|
-
batch ??= createOpenAICompletionsReasoningBatch();
|
|
83
|
-
appendOpenAICompletionsReasoningDelta(batch, {
|
|
84
|
-
kind: "thinking",
|
|
85
|
-
signature: "reasoning_details",
|
|
86
|
-
text: detail.text
|
|
87
|
-
});
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (typeof detail.type === "string" && visibleReasoningDetailTypes.has(detail.type)) {
|
|
91
|
-
batch ??= createOpenAICompletionsReasoningBatch();
|
|
92
|
-
appendOpenAICompletionsReasoningDelta(batch, {
|
|
93
|
-
kind: "text",
|
|
94
|
-
text: detail.text,
|
|
95
|
-
source: "reasoning_detail"
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (!usedReasoningThinkingDetails) for (const field of OPENAI_COMPLETIONS_REASONING_FIELDS) {
|
|
100
|
-
const value = delta[field];
|
|
101
|
-
if (typeof value === "string" && value.length > 0) {
|
|
102
|
-
batch ??= createOpenAICompletionsReasoningBatch();
|
|
103
|
-
appendOpenAICompletionsReasoningDelta(batch, {
|
|
104
|
-
kind: "thinking",
|
|
105
|
-
signature: field,
|
|
106
|
-
text: value
|
|
107
|
-
});
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return batch ?? EMPTY_OPENAI_COMPLETIONS_REASONING_BATCH;
|
|
112
|
-
}
|
|
113
|
-
function parseOpenAICompletionsUsage(rawUsage, model, options) {
|
|
114
|
-
const cacheRead = rawUsage.prompt_tokens_details?.cached_tokens ?? rawUsage.prompt_cache_hit_tokens ?? 0;
|
|
115
|
-
const cacheWrite = rawUsage.prompt_tokens_details?.cache_write_tokens ?? rawUsage.prompt_tokens_details?.cache_creation_input_tokens ?? 0;
|
|
116
|
-
const input = Math.max(0, (rawUsage.prompt_tokens || 0) - cacheRead - cacheWrite);
|
|
117
|
-
const output = rawUsage.completion_tokens || 0;
|
|
118
|
-
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
|
|
119
|
-
const usage = {
|
|
120
|
-
input,
|
|
121
|
-
output,
|
|
122
|
-
cacheRead,
|
|
123
|
-
cacheWrite,
|
|
124
|
-
...options?.includeReasoningTokens !== false && typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? { reasoningTokens } : {},
|
|
125
|
-
totalTokens: input + output + cacheRead + cacheWrite,
|
|
126
|
-
cost: {
|
|
127
|
-
input: 0,
|
|
128
|
-
output: 0,
|
|
129
|
-
cacheRead: 0,
|
|
130
|
-
cacheWrite: 0,
|
|
131
|
-
total: 0
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
calculateCost(model, usage);
|
|
135
|
-
applyProviderReportedUsageCost(usage, rawUsage.cost);
|
|
136
|
-
return usage;
|
|
137
|
-
}
|
|
138
|
-
function createOpenAIResponseHook(onResponse, response, model) {
|
|
139
|
-
return onResponse ? () => onResponse({
|
|
140
|
-
status: response.status,
|
|
141
|
-
headers: headersToRecord(response.headers)
|
|
142
|
-
}, model) : void 0;
|
|
143
|
-
}
|
|
144
|
-
function createOpenAIProviderAcceptanceHook(options, response, model) {
|
|
145
|
-
return () => notifyProviderHttpResponse({
|
|
146
|
-
options,
|
|
147
|
-
response,
|
|
148
|
-
model
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
function throwIfModelStreamAborted(signal) {
|
|
152
|
-
if (signal?.aborted) throw transportAbortError(signal);
|
|
153
|
-
}
|
|
154
|
-
/** Measure one UTF-8 append without double-counting a surrogate pair split across chunks. */
|
|
155
|
-
function measureUtf8AppendBytes(bufferEndsWithHighSurrogate, chunk) {
|
|
156
|
-
let bytes = Buffer.byteLength(chunk, "utf8");
|
|
157
|
-
if (!chunk) return {
|
|
158
|
-
bytes,
|
|
159
|
-
endsWithHighSurrogate: bufferEndsWithHighSurrogate
|
|
160
|
-
};
|
|
161
|
-
const nextCodeUnit = chunk.charCodeAt(0);
|
|
162
|
-
if (bufferEndsWithHighSurrogate && nextCodeUnit >= 56320 && nextCodeUnit <= 57343) bytes -= 2;
|
|
163
|
-
const finalCodeUnit = chunk.charCodeAt(chunk.length - 1);
|
|
164
|
-
return {
|
|
165
|
-
bytes,
|
|
166
|
-
endsWithHighSurrogate: finalCodeUnit >= 55296 && finalCodeUnit <= 56319
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
function createModelStreamCooperativeScheduler(signal) {
|
|
170
|
-
let lastYieldedAt = Date.now();
|
|
171
|
-
let eventsSinceYield = 0;
|
|
172
|
-
return { async afterEvent() {
|
|
173
|
-
throwIfModelStreamAborted(signal);
|
|
174
|
-
eventsSinceYield += 1;
|
|
175
|
-
const now = Date.now();
|
|
176
|
-
if (eventsSinceYield < MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS && now - lastYieldedAt < MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS) return;
|
|
177
|
-
eventsSinceYield = 0;
|
|
178
|
-
lastYieldedAt = now;
|
|
179
|
-
await new Promise((resolve) => {
|
|
180
|
-
setTimeout(resolve, 0);
|
|
181
|
-
});
|
|
182
|
-
throwIfModelStreamAborted(signal);
|
|
183
|
-
} };
|
|
184
|
-
}
|
|
185
|
-
function resolvePromptCacheKey(options, cacheRetention) {
|
|
186
|
-
if (cacheRetention === "none") return;
|
|
187
|
-
return clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId);
|
|
188
|
-
}
|
|
189
|
-
function isOpenAICompletionsThinkingEnabled(effort) {
|
|
190
|
-
const normalized = effort.trim().toLowerCase();
|
|
191
|
-
return normalized !== "off" && normalized !== "none";
|
|
192
|
-
}
|
|
193
|
-
function readOpenAICompletionsContentDeltas(content, topLevelRefusal, mirroredThinking = []) {
|
|
194
|
-
let deltas = readOpenAICompletionsContentPartDeltas(content);
|
|
195
|
-
if (mirroredThinking.length > 0) {
|
|
196
|
-
const structuredThinking = deltas.filter((delta) => delta.kind === "thinking").map((delta) => delta.text);
|
|
197
|
-
const mirrorsCombinedThinking = structuredThinking.length > 1 && mirroredThinking.includes(structuredThinking.join(""));
|
|
198
|
-
deltas = deltas.filter((delta) => delta.kind !== "thinking" || !mirrorsCombinedThinking && !mirroredThinking.includes(delta.text));
|
|
199
|
-
}
|
|
200
|
-
if (typeof topLevelRefusal !== "string" || !topLevelRefusal) return deltas;
|
|
201
|
-
const structuredRefusals = deltas.filter((delta) => delta.kind === "text" && delta.source === "refusal").map((delta) => delta.text);
|
|
202
|
-
if (structuredRefusals.some((refusal) => refusal === topLevelRefusal) || structuredRefusals.length > 1 && structuredRefusals.join("") === topLevelRefusal) return deltas;
|
|
203
|
-
return [...deltas, {
|
|
204
|
-
kind: "text",
|
|
205
|
-
text: topLevelRefusal,
|
|
206
|
-
source: "refusal"
|
|
207
|
-
}];
|
|
208
|
-
}
|
|
209
|
-
function readOpenAICompletionsContentPartDeltas(content) {
|
|
210
|
-
if (typeof content === "string") return content ? [{
|
|
211
|
-
kind: "text",
|
|
212
|
-
text: content
|
|
213
|
-
}] : [];
|
|
214
|
-
if (Array.isArray(content)) return content.flatMap(readOpenAICompletionsContentPartDeltas);
|
|
215
|
-
if (!content || typeof content !== "object") return [];
|
|
216
|
-
const record = content;
|
|
217
|
-
const type = typeof record.type === "string" ? record.type.toLowerCase() : "";
|
|
218
|
-
const extractText = (value) => {
|
|
219
|
-
if (typeof value === "string") return value;
|
|
220
|
-
if (Array.isArray(value)) return value.map(extractText).join("");
|
|
221
|
-
if (value && typeof value === "object") {
|
|
222
|
-
const nested = value;
|
|
223
|
-
return extractText(nested.text ?? nested.content ?? nested.thinking ?? nested.refusal);
|
|
224
|
-
}
|
|
225
|
-
return "";
|
|
226
|
-
};
|
|
227
|
-
const text = extractText(record.text ?? record.content ?? record.thinking ?? record.refusal);
|
|
228
|
-
if (!text) return [];
|
|
229
|
-
if (type.includes("thinking") || type.includes("reasoning")) return [{
|
|
230
|
-
kind: "thinking",
|
|
231
|
-
text
|
|
232
|
-
}];
|
|
233
|
-
if (type === "refusal") return [{
|
|
234
|
-
kind: "text",
|
|
235
|
-
text,
|
|
236
|
-
source: "refusal"
|
|
237
|
-
}];
|
|
238
|
-
if (["text", "output_text"].includes(type) || type.endsWith(".output_text")) return [{
|
|
239
|
-
kind: "text",
|
|
240
|
-
text
|
|
241
|
-
}];
|
|
242
|
-
return [];
|
|
243
|
-
}
|
|
244
|
-
//#endregion
|
|
245
|
-
//#region packages/ai/src/providers/openai-tool-projection.ts
|
|
246
|
-
function unreadableToolDiagnostic(toolIndex) {
|
|
247
|
-
return {
|
|
248
|
-
toolIndex,
|
|
249
|
-
violations: [`tool[${toolIndex}] is unreadable`]
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
/** Snapshots direct/custom tool descriptors before OpenAI payload construction. */
|
|
253
|
-
function projectOpenAITools(tools) {
|
|
254
|
-
let inputToolCount;
|
|
255
|
-
try {
|
|
256
|
-
inputToolCount = tools.length;
|
|
257
|
-
} catch {
|
|
258
|
-
return {
|
|
259
|
-
inputToolCount: 0,
|
|
260
|
-
tools: [],
|
|
261
|
-
diagnostics: [unreadableToolDiagnostic(0)]
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
const projectedTools = [];
|
|
265
|
-
const diagnostics = [];
|
|
266
|
-
for (let toolIndex = 0; toolIndex < inputToolCount; toolIndex += 1) {
|
|
267
|
-
let tool;
|
|
268
|
-
try {
|
|
269
|
-
const candidate = tools[toolIndex];
|
|
270
|
-
if (!candidate) {
|
|
271
|
-
diagnostics.push(unreadableToolDiagnostic(toolIndex));
|
|
272
|
-
continue;
|
|
273
|
-
}
|
|
274
|
-
tool = candidate;
|
|
275
|
-
} catch {
|
|
276
|
-
diagnostics.push(unreadableToolDiagnostic(toolIndex));
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
let name;
|
|
280
|
-
try {
|
|
281
|
-
name = tool.name;
|
|
282
|
-
} catch {
|
|
283
|
-
diagnostics.push({
|
|
284
|
-
toolIndex,
|
|
285
|
-
violations: [`tool[${toolIndex}].name is unreadable`]
|
|
286
|
-
});
|
|
287
|
-
continue;
|
|
288
|
-
}
|
|
289
|
-
if (typeof name !== "string" || !name) {
|
|
290
|
-
diagnostics.push({
|
|
291
|
-
toolIndex,
|
|
292
|
-
violations: [`tool[${toolIndex}].name is empty`]
|
|
293
|
-
});
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
let parameters;
|
|
297
|
-
try {
|
|
298
|
-
parameters = tool.parameters;
|
|
299
|
-
} catch {
|
|
300
|
-
diagnostics.push({
|
|
301
|
-
toolIndex,
|
|
302
|
-
toolName: name,
|
|
303
|
-
violations: [`${name}.parameters is unreadable`]
|
|
304
|
-
});
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
const schemaProjection = projectRuntimeToolInputSchema(parameters ?? {}, `${name}.parameters`);
|
|
308
|
-
if (!isRecord(schemaProjection.schema) || schemaProjection.violations.length > 0) {
|
|
309
|
-
diagnostics.push({
|
|
310
|
-
toolIndex,
|
|
311
|
-
toolName: name,
|
|
312
|
-
violations: schemaProjection.violations.length > 0 ? schemaProjection.violations : [`${name}.parameters must be a JSON object schema`]
|
|
313
|
-
});
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
let descriptionValue;
|
|
317
|
-
try {
|
|
318
|
-
descriptionValue = tool.description;
|
|
319
|
-
} catch {}
|
|
320
|
-
const description = typeof descriptionValue === "string" ? descriptionValue : void 0;
|
|
321
|
-
projectedTools.push({
|
|
322
|
-
toolIndex,
|
|
323
|
-
name,
|
|
324
|
-
...description !== void 0 ? { description } : {},
|
|
325
|
-
parameters: schemaProjection.schema
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
return {
|
|
329
|
-
inputToolCount,
|
|
330
|
-
tools: projectedTools,
|
|
331
|
-
diagnostics
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
function requireProjectedFunction(name, projection, choiceLabel) {
|
|
335
|
-
if (!projection.tools.some((tool) => tool.name === name)) throw new Error(`${choiceLabel} requested unavailable tool "${name}" after schema conversion`);
|
|
336
|
-
}
|
|
337
|
-
/** Keeps Responses tool choices aligned with surviving function schemas. */
|
|
338
|
-
function reconcileOpenAIResponsesToolChoice(choice, projection) {
|
|
339
|
-
if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
|
|
340
|
-
if (choice === "required") {
|
|
341
|
-
if (projection.tools.length === 0) throw new Error("OpenAI Responses tool_choice requires a tool, but no tools survived schema conversion");
|
|
342
|
-
return choice;
|
|
343
|
-
}
|
|
344
|
-
if (choice === "none" || !isRecord(choice)) return choice;
|
|
345
|
-
const choiceType = choice.type;
|
|
346
|
-
if (choiceType === "function") {
|
|
347
|
-
const functionName = choice.name;
|
|
348
|
-
if (typeof functionName !== "string") return choice;
|
|
349
|
-
requireProjectedFunction(functionName, projection, "OpenAI Responses tool_choice");
|
|
350
|
-
return {
|
|
351
|
-
type: "function",
|
|
352
|
-
name: functionName
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
if (choiceType !== "allowed_tools") return choice;
|
|
356
|
-
const mode = choice.mode;
|
|
357
|
-
const tools = choice.tools;
|
|
358
|
-
if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
|
|
359
|
-
const normalizedAllowedTools = [];
|
|
360
|
-
for (const tool of tools) {
|
|
361
|
-
if (!isRecord(tool) || tool.type !== "function") {
|
|
362
|
-
normalizedAllowedTools.push(tool);
|
|
363
|
-
continue;
|
|
364
|
-
}
|
|
365
|
-
const functionName = tool.name;
|
|
366
|
-
if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
|
|
367
|
-
type: "function",
|
|
368
|
-
name: functionName
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
if (normalizedAllowedTools.length === 0) {
|
|
372
|
-
if (mode === "auto") return "none";
|
|
373
|
-
throw new Error("OpenAI Responses tool_choice requires a tool, but no allowed tools survived schema conversion");
|
|
374
|
-
}
|
|
375
|
-
return {
|
|
376
|
-
type: "allowed_tools",
|
|
377
|
-
mode,
|
|
378
|
-
tools: normalizedAllowedTools
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
/** Keeps Chat Completions tool choices aligned with surviving function schemas. */
|
|
382
|
-
function reconcileOpenAICompletionsToolChoice(choice, projection) {
|
|
383
|
-
if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
|
|
384
|
-
if (choice === "required") {
|
|
385
|
-
if (projection.tools.length === 0) throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no tools survived schema conversion");
|
|
386
|
-
return choice;
|
|
387
|
-
}
|
|
388
|
-
if (choice === "none" || !isRecord(choice)) return choice;
|
|
389
|
-
const choiceType = choice.type;
|
|
390
|
-
if (choiceType === "custom") throw new Error("OpenAI Chat Completions custom tool_choice is unsupported because this adapter emits function tools only");
|
|
391
|
-
if (choiceType === "function") {
|
|
392
|
-
const functionChoice = choice.function;
|
|
393
|
-
if (!isRecord(functionChoice)) return choice;
|
|
394
|
-
const functionName = functionChoice.name;
|
|
395
|
-
if (typeof functionName !== "string") return choice;
|
|
396
|
-
requireProjectedFunction(functionName, projection, "OpenAI Chat Completions tool_choice");
|
|
397
|
-
return {
|
|
398
|
-
type: "function",
|
|
399
|
-
function: { name: functionName }
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
if (choiceType !== "allowed_tools") return choice;
|
|
403
|
-
const allowedConfig = choice.allowed_tools;
|
|
404
|
-
if (!isRecord(allowedConfig)) return choice;
|
|
405
|
-
const mode = allowedConfig.mode;
|
|
406
|
-
const tools = allowedConfig.tools;
|
|
407
|
-
if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
|
|
408
|
-
const normalizedAllowedTools = [];
|
|
409
|
-
for (const tool of tools) {
|
|
410
|
-
if (!isRecord(tool) || tool.type !== "function") continue;
|
|
411
|
-
const functionChoice = tool.function;
|
|
412
|
-
const functionName = isRecord(functionChoice) ? functionChoice.name : void 0;
|
|
413
|
-
if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
|
|
414
|
-
type: "function",
|
|
415
|
-
function: { name: functionName }
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
if (normalizedAllowedTools.length === 0) {
|
|
419
|
-
if (mode === "auto") return "none";
|
|
420
|
-
throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no allowed tools survived schema conversion");
|
|
421
|
-
}
|
|
422
|
-
return {
|
|
423
|
-
type: "allowed_tools",
|
|
424
|
-
allowed_tools: {
|
|
425
|
-
mode,
|
|
426
|
-
tools: normalizedAllowedTools
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
//#endregion
|
|
1
|
+
import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
|
|
2
|
+
import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
|
|
3
|
+
import { r as uniqueValues, t as normalizeStringEntries } from "./string-normalization-CmLIasuf.mjs";
|
|
431
4
|
//#region packages/ai/src/providers/clean-for-gemini.ts
|
|
432
5
|
const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
433
6
|
"patternProperties",
|
|
@@ -969,136 +542,46 @@ function isTypedObjectSchemaMissingValidProperties(schemaRecord, conditionalKey)
|
|
|
969
542
|
function isTrulyEmptySchema(schemaRecord) {
|
|
970
543
|
return Object.keys(schemaRecord).length === 0;
|
|
971
544
|
}
|
|
972
|
-
function
|
|
973
|
-
if (!isRecord(schema)) return schema;
|
|
974
|
-
let changed = false;
|
|
975
|
-
const nextSchema = { ...schema };
|
|
976
|
-
if (nextSchema.type === "array" && nextSchema.items === void 0) {
|
|
977
|
-
nextSchema.items = {};
|
|
978
|
-
changed = true;
|
|
979
|
-
}
|
|
980
|
-
const normalizeSchemaValue = (key) => {
|
|
981
|
-
if (!(key in nextSchema)) return;
|
|
982
|
-
const value = nextSchema[key];
|
|
983
|
-
if (Array.isArray(value)) {
|
|
984
|
-
const normalized = value.map(normalizeArraySchemasMissingItems);
|
|
985
|
-
if (normalized.some((entry, index) => entry !== value[index])) {
|
|
986
|
-
nextSchema[key] = normalized;
|
|
987
|
-
changed = true;
|
|
988
|
-
}
|
|
989
|
-
return;
|
|
990
|
-
}
|
|
991
|
-
const normalized = normalizeArraySchemasMissingItems(value);
|
|
992
|
-
if (normalized !== value) {
|
|
993
|
-
nextSchema[key] = normalized;
|
|
994
|
-
changed = true;
|
|
995
|
-
}
|
|
996
|
-
};
|
|
997
|
-
for (const key of [
|
|
998
|
-
"items",
|
|
999
|
-
"contains",
|
|
1000
|
-
"additionalProperties",
|
|
1001
|
-
"propertyNames",
|
|
1002
|
-
"not",
|
|
1003
|
-
"if",
|
|
1004
|
-
"then",
|
|
1005
|
-
"else"
|
|
1006
|
-
]) normalizeSchemaValue(key);
|
|
1007
|
-
for (const key of [
|
|
1008
|
-
"anyOf",
|
|
1009
|
-
"oneOf",
|
|
1010
|
-
"allOf",
|
|
1011
|
-
"prefixItems"
|
|
1012
|
-
]) normalizeSchemaValue(key);
|
|
1013
|
-
for (const key of [
|
|
1014
|
-
"properties",
|
|
1015
|
-
"patternProperties",
|
|
1016
|
-
"dependentSchemas",
|
|
1017
|
-
"$defs",
|
|
1018
|
-
"definitions"
|
|
1019
|
-
]) {
|
|
1020
|
-
const value = nextSchema[key];
|
|
1021
|
-
if (!isRecord(value)) continue;
|
|
1022
|
-
let entriesChanged = false;
|
|
1023
|
-
const normalizedEntries = Object.entries(value).map(([entryKey, entryValue]) => {
|
|
1024
|
-
const normalizedEntryValue = normalizeArraySchemasMissingItems(entryValue);
|
|
1025
|
-
if (normalizedEntryValue !== entryValue) entriesChanged = true;
|
|
1026
|
-
return [entryKey, normalizedEntryValue];
|
|
1027
|
-
});
|
|
1028
|
-
if (entriesChanged) {
|
|
1029
|
-
nextSchema[key] = Object.fromEntries(normalizedEntries);
|
|
1030
|
-
changed = true;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
return changed ? nextSchema : schema;
|
|
1034
|
-
}
|
|
1035
|
-
function schemaAllowsArrayType(schema) {
|
|
1036
|
-
const type = schema.type;
|
|
1037
|
-
return type === "array" || Array.isArray(type) && type.includes("array");
|
|
1038
|
-
}
|
|
1039
|
-
const ARRAY_ITEMS_SCHEMA_OBJECT_KEYS = /* @__PURE__ */ new Set([
|
|
1040
|
-
"additionalProperties",
|
|
1041
|
-
"contains",
|
|
1042
|
-
"else",
|
|
1043
|
-
"if",
|
|
1044
|
-
"items",
|
|
1045
|
-
"not",
|
|
1046
|
-
"propertyNames",
|
|
1047
|
-
"then"
|
|
1048
|
-
]);
|
|
1049
|
-
const ARRAY_ITEMS_SCHEMA_ARRAY_KEYS = /* @__PURE__ */ new Set([
|
|
1050
|
-
"allOf",
|
|
1051
|
-
"anyOf",
|
|
1052
|
-
"oneOf",
|
|
1053
|
-
"prefixItems"
|
|
1054
|
-
]);
|
|
1055
|
-
const ARRAY_ITEMS_SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
1056
|
-
"$defs",
|
|
1057
|
-
"definitions",
|
|
1058
|
-
"dependentSchemas",
|
|
1059
|
-
"patternProperties",
|
|
1060
|
-
"properties"
|
|
1061
|
-
]);
|
|
1062
|
-
function stripEmptyArrayItemsFromArraySchemas(schema) {
|
|
545
|
+
function normalizeArraySchemaItems(schema, mode) {
|
|
1063
546
|
if (Array.isArray(schema)) {
|
|
1064
|
-
|
|
1065
|
-
const entries = schema.map((entry) =>
|
|
1066
|
-
|
|
1067
|
-
changed ||= next !== entry;
|
|
1068
|
-
return next;
|
|
1069
|
-
});
|
|
1070
|
-
return changed ? entries : schema;
|
|
547
|
+
if (mode === "add") return schema;
|
|
548
|
+
const entries = schema.map((entry) => normalizeArraySchemaItems(entry, "omit"));
|
|
549
|
+
return entries.some((entry, index) => entry !== schema[index]) ? entries : schema;
|
|
1071
550
|
}
|
|
1072
551
|
if (!isRecord(schema)) return schema;
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
552
|
+
const missingItems = mode !== "omit" && schema.type === "array" && schema.items === void 0;
|
|
553
|
+
let changed = missingItems;
|
|
554
|
+
const normalized = { ...schema };
|
|
555
|
+
if (missingItems) {
|
|
556
|
+
if (mode === "add") normalized.items = {};
|
|
557
|
+
else delete normalized.items;
|
|
558
|
+
}
|
|
559
|
+
const allowsArray = schema.type === "array" || Array.isArray(schema.type) && schema.type.includes("array");
|
|
560
|
+
const normalizeValue = (value, valueMode) => {
|
|
561
|
+
if (!Array.isArray(value)) return normalizeArraySchemaItems(value, valueMode);
|
|
562
|
+
const entries = value.map((entry) => normalizeArraySchemaItems(entry, valueMode));
|
|
563
|
+
return entries.some((entry, index) => entry !== value[index]) ? entries : value;
|
|
564
|
+
};
|
|
565
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
566
|
+
if (mode !== "add" && key === "items" && allowsArray && isRecord(value) && isTrulyEmptySchema(value)) {
|
|
567
|
+
delete normalized.items;
|
|
1076
568
|
changed = true;
|
|
1077
|
-
|
|
1078
|
-
}
|
|
1079
|
-
if (ARRAY_ITEMS_SCHEMA_OBJECT_KEYS.has(key)) {
|
|
1080
|
-
const next = stripEmptyArrayItemsFromArraySchemas(value);
|
|
1081
|
-
changed ||= next !== value;
|
|
1082
|
-
return [[key, next]];
|
|
569
|
+
continue;
|
|
1083
570
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
571
|
+
let next = value;
|
|
572
|
+
if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
|
|
573
|
+
const entries = Object.entries(value).map(([entryKey, entry]) => [entryKey, normalizeArraySchemaItems(entry, mode)]);
|
|
574
|
+
if (entries.some(([entryKey, entry]) => entry !== value[entryKey])) next = Object.fromEntries(entries);
|
|
575
|
+
} else if (SCHEMA_OBJECT_KEYS.has(key) || SCHEMA_ARRAY_KEYS.has(key)) {
|
|
576
|
+
const valueMode = SCHEMA_OBJECT_KEYS.has(key) || Array.isArray(value) ? mode : "add";
|
|
577
|
+
if (valueMode === mode || mode !== "omit") next = normalizeValue(value, valueMode);
|
|
1088
578
|
}
|
|
1089
|
-
if (
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
const entryNext = stripEmptyArrayItemsFromArraySchemas(entryValue);
|
|
1093
|
-
mapChanged ||= entryNext !== entryValue;
|
|
1094
|
-
return [entryKey, entryNext];
|
|
1095
|
-
}));
|
|
1096
|
-
changed ||= mapChanged;
|
|
1097
|
-
return [[key, mapChanged ? next : value]];
|
|
579
|
+
if (next !== value) {
|
|
580
|
+
setOwnSchemaProperty(normalized, key, next);
|
|
581
|
+
changed = true;
|
|
1098
582
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
return changed ? Object.fromEntries(entries) : schema;
|
|
583
|
+
}
|
|
584
|
+
return changed ? normalized : schema;
|
|
1102
585
|
}
|
|
1103
586
|
function copySchemaMeta(from, to) {
|
|
1104
587
|
for (const key of [
|
|
@@ -1328,7 +811,7 @@ function normalizeOpenApiSchemaKeywords(schema) {
|
|
|
1328
811
|
changed ||= next.some((entry, index) => entry !== value[index]);
|
|
1329
812
|
continue;
|
|
1330
813
|
}
|
|
1331
|
-
normalized
|
|
814
|
+
setOwnSchemaProperty(normalized, key, value);
|
|
1332
815
|
}
|
|
1333
816
|
if (nullable) {
|
|
1334
817
|
if (hasOpenApiComposition(normalized)) return wrapNullableComposedSchema(normalized);
|
|
@@ -1353,8 +836,7 @@ function normalizeToolParameterSchemaUncached(schema, options) {
|
|
|
1353
836
|
const omitEmptyArrayItems = shouldOmitEmptyArrayItems(options?.modelCompat);
|
|
1354
837
|
const isLlamacppGbnfProfile = normalizedToolSchemaProfile === "llamacpp";
|
|
1355
838
|
function applyProviderCleaning(s) {
|
|
1356
|
-
|
|
1357
|
-
let arrayItemsCompatibleSchema = omitEmptyArrayItems ? stripEmptyArrayItemsFromArraySchemas(normalizedSchema) : normalizedSchema;
|
|
839
|
+
let arrayItemsCompatibleSchema = normalizeArraySchemaItems(s, omitEmptyArrayItems ? "normalize" : "add");
|
|
1358
840
|
if (isLlamacppGbnfProfile) arrayItemsCompatibleSchema = cleanSchemaForLlamacppGbnf(arrayItemsCompatibleSchema);
|
|
1359
841
|
if (isGeminiProvider && !isAnthropicProvider) {
|
|
1360
842
|
const geminiCompatibleSchema = cleanSchemaForGemini(arrayItemsCompatibleSchema);
|
|
@@ -1392,13 +874,7 @@ function normalizeToolParameterSchemaUncached(schema, options) {
|
|
|
1392
874
|
const props = entry.properties;
|
|
1393
875
|
if (!props || typeof props !== "object") continue;
|
|
1394
876
|
objectVariants += 1;
|
|
1395
|
-
for (const [key, value] of Object.entries(props))
|
|
1396
|
-
if (!(key in mergedProperties)) {
|
|
1397
|
-
mergedProperties[key] = value;
|
|
1398
|
-
continue;
|
|
1399
|
-
}
|
|
1400
|
-
mergedProperties[key] = mergePropertySchemas(mergedProperties[key], value);
|
|
1401
|
-
}
|
|
877
|
+
for (const [key, value] of Object.entries(props)) setOwnSchemaProperty(mergedProperties, key, mergePropertySchemas(Object.hasOwn(mergedProperties, key) ? mergedProperties[key] : void 0, value));
|
|
1402
878
|
const required = Array.isArray(entry.required) ? entry.required : [];
|
|
1403
879
|
for (const key of required) {
|
|
1404
880
|
if (typeof key !== "string") continue;
|
|
@@ -1463,12 +939,11 @@ const OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS = /* @__PURE__ */ new Set([
|
|
|
1463
939
|
function normalizeOpenAIStrictCompatSchemaMap(schema) {
|
|
1464
940
|
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return schema;
|
|
1465
941
|
let changed = false;
|
|
1466
|
-
const normalized = {
|
|
1467
|
-
for (const [key, value] of Object.entries(schema)) {
|
|
942
|
+
const normalized = Object.fromEntries(Object.entries(schema).map(([key, value]) => {
|
|
1468
943
|
const next = normalizeOpenAIStrictCompatSchemaRecursive(value, { promoteEmptyObject: false });
|
|
1469
|
-
normalized[key] = next;
|
|
1470
944
|
changed ||= next !== value;
|
|
1471
|
-
|
|
945
|
+
return [key, next];
|
|
946
|
+
}));
|
|
1472
947
|
return changed ? normalized : schema;
|
|
1473
948
|
}
|
|
1474
949
|
function normalizeOpenAIStrictCompatSchemaRecursive(schema, options) {
|
|
@@ -1485,21 +960,17 @@ function normalizeOpenAIStrictCompatSchemaRecursive(schema, options) {
|
|
|
1485
960
|
const record = schema;
|
|
1486
961
|
let changed = false;
|
|
1487
962
|
let hadNullType = false;
|
|
1488
|
-
const
|
|
1489
|
-
|
|
1490
|
-
|
|
963
|
+
const entries = Object.entries(record).flatMap(([key, value]) => {
|
|
964
|
+
if (value === null && (OPENAI_NULLABLE_ANNOTATION_KEYS.has(key) || key === "type")) {
|
|
965
|
+
hadNullType ||= key === "type";
|
|
1491
966
|
changed = true;
|
|
1492
|
-
|
|
1493
|
-
}
|
|
1494
|
-
if (value === null && key === "type") {
|
|
1495
|
-
hadNullType = true;
|
|
1496
|
-
changed = true;
|
|
1497
|
-
continue;
|
|
967
|
+
return [];
|
|
1498
968
|
}
|
|
1499
969
|
const next = OPENAI_STRICT_COMPAT_SCHEMA_MAP_KEYS.has(key) ? normalizeOpenAIStrictCompatSchemaMap(value) : OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS.has(key) ? normalizeOpenAIStrictCompatSchemaRecursive(value, { promoteEmptyObject: false }) : value;
|
|
1500
|
-
normalized[key] = next;
|
|
1501
970
|
changed ||= next !== value;
|
|
1502
|
-
|
|
971
|
+
return [[key, next]];
|
|
972
|
+
});
|
|
973
|
+
const normalized = Object.fromEntries(entries);
|
|
1503
974
|
if (Object.keys(normalized).length === 0) {
|
|
1504
975
|
if (!options.promoteEmptyObject) return schema;
|
|
1505
976
|
return {
|
|
@@ -1625,12 +1096,11 @@ function normalizeStrictOpenAIJsonSchemaRecursive(schema, depth) {
|
|
|
1625
1096
|
if (!schema || typeof schema !== "object") return schema;
|
|
1626
1097
|
const record = schema;
|
|
1627
1098
|
let changed = false;
|
|
1628
|
-
const normalized = {
|
|
1629
|
-
for (const [key, value] of Object.entries(record)) {
|
|
1099
|
+
const normalized = Object.fromEntries(Object.entries(record).map(([key, value]) => {
|
|
1630
1100
|
const next = normalizeStrictOpenAIJsonSchemaRecursive(value, key === "properties" ? depth : depth + 1);
|
|
1631
|
-
normalized[key] = next;
|
|
1632
1101
|
changed ||= next !== value;
|
|
1633
|
-
|
|
1102
|
+
return [key, next];
|
|
1103
|
+
}));
|
|
1634
1104
|
if (normalized.type === "object") {
|
|
1635
1105
|
const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : void 0;
|
|
1636
1106
|
if (properties && Object.keys(properties).length === 0 && !Array.isArray(normalized.required)) {
|
|
@@ -1694,4 +1164,4 @@ function resolveOpenAIProjectedToolsStrictToolFlag(projection, strict) {
|
|
|
1694
1164
|
return projection.tools.every((tool) => isStrictOpenAIJsonSchemaCompatible(tool.parameters));
|
|
1695
1165
|
}
|
|
1696
1166
|
//#endregion
|
|
1697
|
-
export {
|
|
1167
|
+
export { cleanSchemaForGemini as _, resolveOpenAIProjectedToolsStrictToolFlag as a, extractToolSchemaModelCompat as c, shouldOmitEmptyArrayItems as d, stripUnsupportedSchemaKeywords as f, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as g, findLlamacppGbnfSchemaViolations as h, normalizeStrictOpenAIJsonSchema as i, normalizeToolParameterSchema as l, cleanSchemaForLlamacppGbnf as m, isStrictOpenAIJsonSchemaCompatible as n, findOpenAIStrictSchemaViolations as o, LLAMACPP_GBNF_MAX_REPETITION_THRESHOLD as p, normalizeOpenAIStrictToolParameters as r, normalizeOpenAIStrictCompatSchema as s, findOpenAIStrictToolProjectionDiagnostics as t, resolveUnsupportedToolSchemaKeywords as u };
|