@openclaw/ai 2026.8.1-beta.1 → 2026.8.1-beta.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/dist/{anthropic-CE-7SkF6.mjs → anthropic-B8KwTtlb.mjs} +62 -37
- package/dist/{anthropic-SrGtwsJu.d.mts → anthropic-BECQCNdF.d.mts} +0 -2
- package/dist/{src-QkygScBs.mjs → anthropic-BQXQudmA.mjs} +0 -2
- package/dist/{anthropic-usage-Ma4iX6uG.mjs → anthropic-compaction-replay-4Zx7-aCr.mjs} +225 -103
- package/dist/anthropic-payload-policy-CSx7MoKH.d.mts +50 -0
- package/dist/{api-registry-EpJoVwM1.d.mts → api-registry-DFxSnFqG.d.mts} +1 -1
- package/dist/{azure-openai-responses-Cc_kasye.mjs → azure-openai-responses-Aa4mVcYG.mjs} +23 -29
- package/dist/diagnostics.d.mts +24 -1
- package/dist/diagnostics.mjs +2 -1
- package/dist/event-stream-BVVgDSdq.d.mts +1 -0
- package/dist/{event-stream-DRmDMRHH.d.mts → event-stream-D91-ohD_.d.mts} +3 -1
- package/dist/{event-stream-CEV9t6da.mjs → event-stream-uSMZJ3FA.mjs} +16 -3
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-shared-Cq2UKx1l.mjs → google-shared-M1dl64nz.mjs} +17 -19
- package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
- package/dist/{google-vertex-CusxWzvE.mjs → google-vertex-DCJHM_a5.mjs} +5 -4
- package/dist/{google-CGQu21aw.mjs → google-yDRnipeq.mjs} +4 -4
- package/dist/host-DF_yxOsA.mjs +477 -0
- package/dist/{host-Dn4_SZI2.d.mts → host-DJq_FGcz.d.mts} +13 -8
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -5
- package/dist/internal/anthropic.d.mts +21 -7
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
- package/dist/internal/openai-responses-payload-policy.mjs +3 -0
- package/dist/internal/openai.d.mts +6 -6
- package/dist/internal/openai.mjs +9 -7
- package/dist/internal/runtime.d.mts +19 -5
- package/dist/internal/runtime.mjs +85 -72
- package/dist/internal/shared.d.mts +17 -8
- package/dist/internal/shared.mjs +4 -5
- package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
- package/dist/{mistral-Dx6VzNjf.mjs → mistral-D6hRXI7A.mjs} +67 -72
- package/dist/{number-coercion-1Miyb5MO.mjs → number-coercion-H9qHik3g.mjs} +7 -2
- package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
- package/dist/{openai-chatgpt-responses-SC9m0FSf.mjs → openai-chatgpt-responses-C339VIfT.mjs} +235 -146
- package/dist/{openai-completions-BaIpl93j.mjs → openai-completions-D88orSJ9.mjs} +88 -67
- package/dist/openai-completions-compat-B0KTleXp.d.mts +43 -0
- package/dist/{openai-responses-Bdx3V_Yu.mjs → openai-responses-BXEcr-Tp.mjs} +17 -24
- package/dist/openai-responses-contracts-CD75pQ0m.d.mts +68 -0
- package/dist/openai-responses-contracts-DvILoqBk.mjs +247 -0
- package/dist/openai-responses-payload-policy-BDo8CQsx.mjs +208 -0
- package/dist/openai-responses-payload-policy-CNGFT9zr.d.mts +41 -0
- package/dist/{openai-responses-prompt-observer-internal-DDZPxRfr.mjs → openai-responses-prompt-observer-internal-BG-1AsBI.mjs} +2 -3
- package/dist/{openai-responses-stream-internal-Bl8YyVtF.mjs → openai-responses-shared-Cvt5MgEm.mjs} +1287 -1039
- package/dist/{openai-reasoning-compat-DKebnIBL.mjs → openai-stop-reason-9OONKyAm.mjs} +222 -180
- package/dist/{openai-transport-shared-Cipt7egQ.mjs → openai-tool-projection-CHGLt03m.mjs} +239 -128
- package/dist/provider-error-C8mBRJDl.mjs +424 -0
- package/dist/provider-error-CzNw4BWX.d.mts +12 -0
- package/dist/provider-options-AvldWZt8.mjs +21 -0
- package/dist/{provider-options-C5kYML7i.d.mts → provider-options-Cc5ZQ6Aa.d.mts} +19 -3
- package/dist/provider-transcript-transform--gtf0ZbR.mjs +32 -0
- package/dist/provider-types.d.mts +31 -0
- package/dist/provider-types.mjs +8 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +17 -19
- package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-5ygO2rZc.mjs} +17 -8
- package/dist/record-coerce-DdXsgUd_.mjs +23 -0
- package/dist/{model-utils-Dau5dlgm.mjs → sanitize-unicode-BP7HLLZn.mjs} +28 -2
- package/dist/session-resources-CkR4WWy1.mjs +21 -0
- package/dist/simple-options-oqsXB6U3.mjs +450 -0
- package/dist/src-D2H6yKkH.mjs +2 -0
- package/dist/{stream-first-event-timeout-BIBomOGq.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{tool-schema-json-projection-B1b-XCn5.mjs → tool-schema-json-projection-FEr-jOoZ.mjs} +20 -13
- package/dist/transport-utils-Bv0FHkd0.mjs +138 -0
- package/dist/transports.d.mts +199 -209
- package/dist/transports.mjs +1842 -1364
- package/dist/types-BDdaOVi2.mjs +6 -0
- package/dist/{types-CH7ReIcU.d.mts → types-DTAP49HF.d.mts} +35 -2
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +6 -4
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
- package/dist/{validation-CcPcuEbR.d.mts → validation-DYNNrU9u.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +15 -1
- package/dist/host-Bl7Kgddo.mjs +0 -407
- package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
- package/dist/openai-responses-contracts-BBKBfAqR.d.mts +0 -116
- package/dist/openai-responses-shared-CCyMvg7M.mjs +0 -403
- package/dist/provider-error-DI0Ts28U.mjs +0 -47
- package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
- package/dist/tool-result-text-Dvkp2Dus.mjs +0 -274
- package/dist/transform-messages-DfjpNXNQ.mjs +0 -2
- package/dist/transport-stream-shared-CPNv7A3r.mjs +0 -297
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as sanitizeSurrogates } from "./sanitize-unicode-
|
|
3
|
-
import { a as
|
|
4
|
-
import {
|
|
1
|
+
import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
|
|
2
|
+
import { t as sanitizeSurrogates } from "./sanitize-unicode-BP7HLLZn.mjs";
|
|
3
|
+
import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload } from "./host-DF_yxOsA.mjs";
|
|
4
|
+
import { a as isRecord, r as asOptionalObjectRecord } from "./record-coerce-DdXsgUd_.mjs";
|
|
5
|
+
import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
|
|
6
|
+
import { d as finalizeTerminalToolCallArguments, j as stripSystemPromptCacheBoundary } from "./simple-options-oqsXB6U3.mjs";
|
|
7
|
+
import { o as resolveProviderRequestCapabilities } from "./tool-schema-json-projection-FEr-jOoZ.mjs";
|
|
8
|
+
import { u as measureUtf8AppendBytes } from "./openai-tool-projection-CHGLt03m.mjs";
|
|
9
|
+
import { t as transformProviderMessages } from "./provider-transcript-transform--gtf0ZbR.mjs";
|
|
5
10
|
import { randomUUID } from "node:crypto";
|
|
6
11
|
//#region packages/ai/src/utils/assistant-text-phase.ts
|
|
12
|
+
const EMPTY_ASSISTANT_TEXT_BLOCK_SET = /* @__PURE__ */ new Set();
|
|
7
13
|
function isAssistantTextPhaseBlock(block) {
|
|
8
14
|
if (!block || typeof block !== "object") return false;
|
|
9
15
|
const record = block;
|
|
@@ -16,20 +22,36 @@ function encodeAssistantTextSignatureV1(id, phase) {
|
|
|
16
22
|
...phase ? { phase } : {}
|
|
17
23
|
});
|
|
18
24
|
}
|
|
19
|
-
|
|
20
|
-
function tagPendingCommentaryText(content) {
|
|
25
|
+
function tagUnphasedText(content, phase, idPrefix) {
|
|
21
26
|
const textBlocks = content.filter(isAssistantTextPhaseBlock);
|
|
22
|
-
let
|
|
27
|
+
let phaseIndex = textBlocks.filter((block) => block.textSignature !== void 0).length;
|
|
23
28
|
const tagged = /* @__PURE__ */ new Map();
|
|
24
29
|
for (const block of textBlocks) {
|
|
25
30
|
if (block.text.trim().length === 0 || block.textSignature !== void 0) continue;
|
|
26
|
-
const signature = encodeAssistantTextSignatureV1(
|
|
31
|
+
const signature = encodeAssistantTextSignatureV1(`${idPrefix}-${phaseIndex}`, phase);
|
|
27
32
|
block.textSignature = signature;
|
|
28
33
|
tagged.set(block, signature);
|
|
29
|
-
|
|
34
|
+
phaseIndex += 1;
|
|
30
35
|
}
|
|
31
36
|
return tagged;
|
|
32
37
|
}
|
|
38
|
+
/** Tags unphased narration before a tool-call event becomes consumer-visible. */
|
|
39
|
+
function tagPendingCommentaryText(content) {
|
|
40
|
+
return tagUnphasedText(content, "commentary", "commentary");
|
|
41
|
+
}
|
|
42
|
+
/** Records the confirmed final-answer boundary after reasoning resumes. */
|
|
43
|
+
function tagInterruptedTextPhases(content, interruptedText, preservedVisibleText = EMPTY_ASSISTANT_TEXT_BLOCK_SET) {
|
|
44
|
+
const interruptedTextIndex = content.indexOf(interruptedText);
|
|
45
|
+
if (interruptedTextIndex === -1) return;
|
|
46
|
+
const finalAnswerIndex = content.findIndex((block, index) => index > interruptedTextIndex && isAssistantTextPhaseBlock(block) && block.text.trim().length > 0);
|
|
47
|
+
if (finalAnswerIndex === -1) return;
|
|
48
|
+
tagUnphasedText(content.slice(0, finalAnswerIndex).filter((block) => !preservedVisibleText.has(block)), "commentary", "commentary");
|
|
49
|
+
tagUnphasedText(content.filter((block, index) => index >= finalAnswerIndex || preservedVisibleText.has(block)), "final_answer", "final-answer");
|
|
50
|
+
}
|
|
51
|
+
/** Prevents unresolved completion text from becoming a fallback answer after stream failure. */
|
|
52
|
+
function tagUnresolvedTextAsCommentary(message) {
|
|
53
|
+
if (message.openclawDelivery?.textPhaseRequiresTerminal) tagUnphasedText(message.content, "commentary", "commentary");
|
|
54
|
+
}
|
|
33
55
|
/** Rolls back only the exact provisional signatures created by this transport turn. */
|
|
34
56
|
function clearPendingCommentaryText(tags) {
|
|
35
57
|
for (const [block, signature] of tags) if (block.textSignature === signature) delete block.textSignature;
|
|
@@ -122,8 +144,8 @@ function resolveOpenAICompletionsCompatDefaultsFromCapabilities(input) {
|
|
|
122
144
|
return resolveOpenAICompletionsCompatDefaults(input);
|
|
123
145
|
}
|
|
124
146
|
/** Detects endpoint capabilities and defaults for an OpenAI-completions model. */
|
|
125
|
-
function detectOpenAICompletionsCompat(model, resolveCapabilities
|
|
126
|
-
const capabilities = resolveCapabilities({
|
|
147
|
+
function detectOpenAICompletionsCompat(model, resolveCapabilities) {
|
|
148
|
+
const capabilities = (resolveCapabilities ?? ((input) => resolveProviderRequestCapabilities(input, model)))({
|
|
127
149
|
provider: model.provider,
|
|
128
150
|
api: "openai-completions",
|
|
129
151
|
baseUrl: model.baseUrl,
|
|
@@ -148,7 +170,7 @@ function resolveSessionAffinity(model, detectedFormat) {
|
|
|
148
170
|
return "openai";
|
|
149
171
|
}
|
|
150
172
|
/** Applies explicit model overrides once on top of the canonical transport defaults. */
|
|
151
|
-
function resolveOpenAICompletionsCompat(model, resolveCapabilities
|
|
173
|
+
function resolveOpenAICompletionsCompat(model, resolveCapabilities) {
|
|
152
174
|
const { defaults } = detectOpenAICompletionsCompat(model, resolveCapabilities);
|
|
153
175
|
const configured = model.compat;
|
|
154
176
|
return {
|
|
@@ -175,7 +197,160 @@ function resolveOpenAICompletionsCompat(model, resolveCapabilities = resolveProv
|
|
|
175
197
|
requiresNonEmptyUserOrAssistantMessage: defaults.requiresNonEmptyUserOrAssistantMessage
|
|
176
198
|
};
|
|
177
199
|
}
|
|
178
|
-
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region packages/ai/src/providers/openai-completions-tool-calls.ts
|
|
202
|
+
const MAX_BUFFERED_TOOL_CALL_ARGUMENT_BYTES = 256e3;
|
|
203
|
+
const MAX_BUFFERED_LEGACY_FOLLOWING_DELTA_BYTES = 256e3;
|
|
204
|
+
const MAX_BUFFERED_LEGACY_FOLLOWING_DELTAS = 1024;
|
|
205
|
+
/** Normalize the SDK's legacy single-function lane into its modern tool-call shape. */
|
|
206
|
+
function createOpenAICompletionsToolCallDeltaNormalizer() {
|
|
207
|
+
let sawModernToolCall = false;
|
|
208
|
+
let pendingLegacyArgumentBytes = 0;
|
|
209
|
+
let pendingFollowingDeltaBytes = 0;
|
|
210
|
+
let pendingLegacyToolCall;
|
|
211
|
+
const modernArguments = /* @__PURE__ */ new Map();
|
|
212
|
+
const pendingFollowingDeltas = [];
|
|
213
|
+
const takePendingFollowingDeltas = () => {
|
|
214
|
+
pendingFollowingDeltaBytes = 0;
|
|
215
|
+
return pendingFollowingDeltas.splice(0).map((delta) => ({
|
|
216
|
+
delta,
|
|
217
|
+
toolCalls: []
|
|
218
|
+
}));
|
|
219
|
+
};
|
|
220
|
+
const bufferFollowingDelta = (delta) => {
|
|
221
|
+
const nextDeltaBytes = Buffer.byteLength(JSON.stringify(delta), "utf8");
|
|
222
|
+
if (pendingFollowingDeltaBytes + nextDeltaBytes > MAX_BUFFERED_LEGACY_FOLLOWING_DELTA_BYTES || pendingFollowingDeltas.length >= MAX_BUFFERED_LEGACY_FOLLOWING_DELTAS) throw new Error("Exceeded legacy tool-call content buffer limit");
|
|
223
|
+
pendingFollowingDeltaBytes += nextDeltaBytes;
|
|
224
|
+
pendingFollowingDeltas.push(delta);
|
|
225
|
+
};
|
|
226
|
+
const withoutToolCalls = (delta) => {
|
|
227
|
+
const ordinaryDelta = { ...delta };
|
|
228
|
+
delete ordinaryDelta.function_call;
|
|
229
|
+
delete ordinaryDelta.tool_calls;
|
|
230
|
+
return ordinaryDelta;
|
|
231
|
+
};
|
|
232
|
+
const hasObservableContent = (value) => {
|
|
233
|
+
if (typeof value === "string") return value.length > 0;
|
|
234
|
+
if (Array.isArray(value)) return value.some(hasObservableContent);
|
|
235
|
+
if (isRecord(value)) return Object.entries(value).some(([field, nestedValue]) => field !== "type" && field !== "id" && field !== "index" && hasObservableContent(nestedValue));
|
|
236
|
+
return false;
|
|
237
|
+
};
|
|
238
|
+
const hasOrdinaryContent = (delta) => Object.entries(delta).some(([field, value]) => field !== "role" && hasObservableContent(value));
|
|
239
|
+
return (delta, finishReason) => {
|
|
240
|
+
const ordinaryDelta = withoutToolCalls(delta);
|
|
241
|
+
if (delta.tool_calls && delta.tool_calls.length > 0) {
|
|
242
|
+
for (const toolCall of delta.tool_calls) {
|
|
243
|
+
const index = typeof toolCall.index === "number" ? toolCall.index : void 0;
|
|
244
|
+
const state = (index === void 0 ? void 0 : modernArguments.get(index)) ?? (toolCall.id ? modernArguments.get(toolCall.id) : void 0) ?? {
|
|
245
|
+
bytes: 0,
|
|
246
|
+
pendingHighSurrogate: false
|
|
247
|
+
};
|
|
248
|
+
if (index !== void 0) modernArguments.set(index, state);
|
|
249
|
+
if (toolCall.id) modernArguments.set(toolCall.id, state);
|
|
250
|
+
const argumentDelta = toolCall.function?.arguments ?? "";
|
|
251
|
+
const append = measureUtf8AppendBytes(state.pendingHighSurrogate, argumentDelta);
|
|
252
|
+
state.bytes += append.bytes;
|
|
253
|
+
if (state.bytes > MAX_BUFFERED_TOOL_CALL_ARGUMENT_BYTES) throw new Error("Exceeded tool-call argument buffer limit");
|
|
254
|
+
state.pendingHighSurrogate = append.endsWithHighSurrogate;
|
|
255
|
+
}
|
|
256
|
+
const precedingDeltas = takePendingFollowingDeltas();
|
|
257
|
+
sawModernToolCall = true;
|
|
258
|
+
pendingLegacyArgumentBytes = 0;
|
|
259
|
+
pendingLegacyToolCall = void 0;
|
|
260
|
+
return [...precedingDeltas, {
|
|
261
|
+
delta: ordinaryDelta,
|
|
262
|
+
toolCalls: delta.tool_calls
|
|
263
|
+
}];
|
|
264
|
+
}
|
|
265
|
+
const functionCall = delta.function_call;
|
|
266
|
+
if (sawModernToolCall) return [{
|
|
267
|
+
delta: ordinaryDelta,
|
|
268
|
+
toolCalls: []
|
|
269
|
+
}];
|
|
270
|
+
const hadPendingLegacyCall = pendingLegacyToolCall !== void 0;
|
|
271
|
+
const leadingDeltas = [];
|
|
272
|
+
if (hasOrdinaryContent(ordinaryDelta)) if (hadPendingLegacyCall) bufferFollowingDelta(ordinaryDelta);
|
|
273
|
+
else leadingDeltas.push({
|
|
274
|
+
delta: ordinaryDelta,
|
|
275
|
+
toolCalls: []
|
|
276
|
+
});
|
|
277
|
+
if (functionCall && (functionCall.name || functionCall.arguments)) {
|
|
278
|
+
const nextFunctionName = pendingLegacyToolCall?.function?.name ? void 0 : functionCall.name;
|
|
279
|
+
const nextArgumentBytes = Buffer.byteLength(functionCall.arguments ?? "", "utf8") + Buffer.byteLength(nextFunctionName ?? "", "utf8");
|
|
280
|
+
if (pendingLegacyArgumentBytes + nextArgumentBytes > MAX_BUFFERED_TOOL_CALL_ARGUMENT_BYTES) throw new Error("Exceeded tool-call argument buffer limit");
|
|
281
|
+
pendingLegacyArgumentBytes += nextArgumentBytes;
|
|
282
|
+
pendingLegacyToolCall ??= {
|
|
283
|
+
index: 0,
|
|
284
|
+
id: `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`,
|
|
285
|
+
type: "function",
|
|
286
|
+
function: {}
|
|
287
|
+
};
|
|
288
|
+
const pendingFunction = pendingLegacyToolCall.function ??= {};
|
|
289
|
+
if (nextFunctionName) pendingFunction.name = nextFunctionName;
|
|
290
|
+
if (functionCall.arguments) pendingFunction.arguments = (pendingFunction.arguments ?? "") + functionCall.arguments;
|
|
291
|
+
}
|
|
292
|
+
if (!pendingLegacyToolCall) return leadingDeltas.length > 0 ? leadingDeltas : [{
|
|
293
|
+
delta: ordinaryDelta,
|
|
294
|
+
toolCalls: []
|
|
295
|
+
}];
|
|
296
|
+
if (finishReason === "function_call") {
|
|
297
|
+
const confirmedLegacyToolCall = pendingLegacyToolCall;
|
|
298
|
+
pendingLegacyToolCall = void 0;
|
|
299
|
+
pendingLegacyArgumentBytes = 0;
|
|
300
|
+
return [
|
|
301
|
+
...leadingDeltas,
|
|
302
|
+
{
|
|
303
|
+
delta: {},
|
|
304
|
+
toolCalls: [confirmedLegacyToolCall]
|
|
305
|
+
},
|
|
306
|
+
...takePendingFollowingDeltas()
|
|
307
|
+
];
|
|
308
|
+
}
|
|
309
|
+
if (finishReason) {
|
|
310
|
+
pendingLegacyArgumentBytes = 0;
|
|
311
|
+
pendingLegacyToolCall = void 0;
|
|
312
|
+
return [...leadingDeltas, ...takePendingFollowingDeltas()];
|
|
313
|
+
}
|
|
314
|
+
return leadingDeltas;
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/** Publish only executable calls; streaming scratch state never belongs in replay. */
|
|
318
|
+
function finalizeOpenAICompletionsToolCalls(output, options = {}) {
|
|
319
|
+
const isToolCall = (block) => block.type === "toolCall";
|
|
320
|
+
const hasToolCalls = output.content.some(isToolCall);
|
|
321
|
+
if (output.stopReason === "toolUse" && !hasToolCalls) output.stopReason = "stop";
|
|
322
|
+
if (output.stopReason === "stop" && hasToolCalls && options.allowSilentToolCallPromotion !== false && !output.content.some((block) => {
|
|
323
|
+
const candidate = block;
|
|
324
|
+
return candidate.type === "text" && typeof candidate.text === "string" && candidate.text.trim().length > 0;
|
|
325
|
+
})) output.stopReason = "toolUse";
|
|
326
|
+
if (output.stopReason !== "toolUse") {
|
|
327
|
+
if (hasToolCalls) output.content = output.content.filter((block) => !isToolCall(block));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const toolCalls = output.content.filter(isToolCall);
|
|
331
|
+
const rejectToolCalls = () => {
|
|
332
|
+
output.stopReason = "error";
|
|
333
|
+
output.errorMessage = "Provider returned an incomplete or malformed tool call";
|
|
334
|
+
output.content = output.content.filter((candidate) => !isToolCall(candidate));
|
|
335
|
+
};
|
|
336
|
+
if (toolCalls.some((call) => typeof call.name !== "string" || call.name.trim().length === 0 || typeof call.partialArgs !== "string" || call.partialArgs.trim().length === 0)) {
|
|
337
|
+
rejectToolCalls();
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
try {
|
|
341
|
+
finalizeTerminalToolCallArguments(toolCalls, (call) => call.partialArgs);
|
|
342
|
+
} catch {
|
|
343
|
+
rejectToolCalls();
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
for (let contentIndex = 0; contentIndex < output.content.length; contentIndex += 1) {
|
|
347
|
+
const block = output.content[contentIndex];
|
|
348
|
+
if (!block || !isToolCall(block)) continue;
|
|
349
|
+
delete block.partialArgs;
|
|
350
|
+
delete block.streamIndex;
|
|
351
|
+
options.onConfirmedToolCall?.(block, contentIndex);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
179
354
|
//#endregion
|
|
180
355
|
//#region packages/ai/src/openai-completions-messages.ts
|
|
181
356
|
const EMPTY_TOOL_RESULT_TEXT = "(no output)";
|
|
@@ -192,6 +367,10 @@ function sanitizeToolResultText(text, fallback) {
|
|
|
192
367
|
const sanitized = sanitizeSurrogates(text);
|
|
193
368
|
return sanitized.trim().length > 0 ? sanitized : fallback;
|
|
194
369
|
}
|
|
370
|
+
/** Whether replayed messages require a tools marker for proxy compatibility. */
|
|
371
|
+
function hasToolCallHistory(messages) {
|
|
372
|
+
return messages.some((message) => message.role === "toolResult" || message.role === "assistant" && Array.isArray(message.content) && message.content.some((block) => block.type === "toolCall"));
|
|
373
|
+
}
|
|
195
374
|
/** Convert a normalized transcript to OpenAI Chat Completions messages. */
|
|
196
375
|
function convertMessages(model, context, compat, options = {}) {
|
|
197
376
|
const params = [];
|
|
@@ -200,7 +379,7 @@ function convertMessages(model, context, compat, options = {}) {
|
|
|
200
379
|
if (model.provider === "openai") return id.length > 40 ? truncateUtf16Safe(id, 40) : id;
|
|
201
380
|
return id;
|
|
202
381
|
};
|
|
203
|
-
const transformedMessages =
|
|
382
|
+
const transformedMessages = transformProviderMessages(context.messages, model, (id) => normalizeToolCallId(id));
|
|
204
383
|
if (context.systemPrompt) {
|
|
205
384
|
const role = model.reasoning && compat.supportsDeveloperRole ? "developer" : "system";
|
|
206
385
|
const systemPrompt = options.preserveSystemPromptCacheBoundary ? context.systemPrompt : stripSystemPromptCacheBoundary(context.systemPrompt);
|
|
@@ -232,6 +411,10 @@ function convertMessages(model, context, compat, options = {}) {
|
|
|
232
411
|
type: "text",
|
|
233
412
|
text: sanitizeSurrogates(item.text)
|
|
234
413
|
};
|
|
414
|
+
if (item.type === "video") return {
|
|
415
|
+
type: "video_url",
|
|
416
|
+
video_url: { url: `data:${item.mimeType};base64,${item.data}` }
|
|
417
|
+
};
|
|
235
418
|
return {
|
|
236
419
|
type: "image_url",
|
|
237
420
|
image_url: { url: `data:${item.mimeType};base64,${item.data}` }
|
|
@@ -339,144 +522,31 @@ function convertMessages(model, context, compat, options = {}) {
|
|
|
339
522
|
return params;
|
|
340
523
|
}
|
|
341
524
|
//#endregion
|
|
342
|
-
//#region packages/ai/src/
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const takePendingFollowingDeltas = () => {
|
|
354
|
-
pendingFollowingDeltaBytes = 0;
|
|
355
|
-
return pendingFollowingDeltas.splice(0).map((delta) => ({
|
|
356
|
-
delta,
|
|
357
|
-
toolCalls: []
|
|
358
|
-
}));
|
|
359
|
-
};
|
|
360
|
-
const bufferFollowingDelta = (delta) => {
|
|
361
|
-
const nextDeltaBytes = Buffer.byteLength(JSON.stringify(delta), "utf8");
|
|
362
|
-
if (pendingFollowingDeltaBytes + nextDeltaBytes > MAX_BUFFERED_LEGACY_FOLLOWING_DELTA_BYTES || pendingFollowingDeltas.length >= MAX_BUFFERED_LEGACY_FOLLOWING_DELTAS) throw new Error("Exceeded legacy tool-call content buffer limit");
|
|
363
|
-
pendingFollowingDeltaBytes += nextDeltaBytes;
|
|
364
|
-
pendingFollowingDeltas.push(delta);
|
|
365
|
-
};
|
|
366
|
-
const withoutToolCalls = (delta) => {
|
|
367
|
-
const ordinaryDelta = { ...delta };
|
|
368
|
-
delete ordinaryDelta.function_call;
|
|
369
|
-
delete ordinaryDelta.tool_calls;
|
|
370
|
-
return ordinaryDelta;
|
|
371
|
-
};
|
|
372
|
-
const hasObservableContent = (value) => {
|
|
373
|
-
if (typeof value === "string") return value.length > 0;
|
|
374
|
-
if (Array.isArray(value)) return value.some(hasObservableContent);
|
|
375
|
-
if (isRecord(value)) return Object.entries(value).some(([field, nestedValue]) => field !== "type" && field !== "id" && field !== "index" && hasObservableContent(nestedValue));
|
|
376
|
-
return false;
|
|
377
|
-
};
|
|
378
|
-
const hasOrdinaryContent = (delta) => Object.entries(delta).some(([field, value]) => field !== "role" && hasObservableContent(value));
|
|
379
|
-
return (delta, finishReason) => {
|
|
380
|
-
const ordinaryDelta = withoutToolCalls(delta);
|
|
381
|
-
if (delta.tool_calls && delta.tool_calls.length > 0) {
|
|
382
|
-
const precedingDeltas = takePendingFollowingDeltas();
|
|
383
|
-
sawModernToolCall = true;
|
|
384
|
-
pendingLegacyArgumentBytes = 0;
|
|
385
|
-
pendingLegacyToolCall = void 0;
|
|
386
|
-
return [...precedingDeltas, {
|
|
387
|
-
delta: ordinaryDelta,
|
|
388
|
-
toolCalls: delta.tool_calls
|
|
389
|
-
}];
|
|
390
|
-
}
|
|
391
|
-
const functionCall = delta.function_call;
|
|
392
|
-
if (sawModernToolCall) return [{
|
|
393
|
-
delta: ordinaryDelta,
|
|
394
|
-
toolCalls: []
|
|
395
|
-
}];
|
|
396
|
-
const hadPendingLegacyCall = pendingLegacyToolCall !== void 0;
|
|
397
|
-
const leadingDeltas = [];
|
|
398
|
-
if (hasOrdinaryContent(ordinaryDelta)) if (hadPendingLegacyCall) bufferFollowingDelta(ordinaryDelta);
|
|
399
|
-
else leadingDeltas.push({
|
|
400
|
-
delta: ordinaryDelta,
|
|
401
|
-
toolCalls: []
|
|
402
|
-
});
|
|
403
|
-
if (functionCall && (functionCall.name || functionCall.arguments)) {
|
|
404
|
-
const nextFunctionName = pendingLegacyToolCall?.function?.name ? void 0 : functionCall.name;
|
|
405
|
-
const nextArgumentBytes = Buffer.byteLength(functionCall.arguments ?? "", "utf8") + Buffer.byteLength(nextFunctionName ?? "", "utf8");
|
|
406
|
-
if (pendingLegacyArgumentBytes + nextArgumentBytes > MAX_BUFFERED_LEGACY_TOOL_CALL_ARGUMENT_BYTES) throw new Error("Exceeded tool-call argument buffer limit");
|
|
407
|
-
pendingLegacyArgumentBytes += nextArgumentBytes;
|
|
408
|
-
pendingLegacyToolCall ??= {
|
|
409
|
-
index: 0,
|
|
410
|
-
id: `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`,
|
|
411
|
-
type: "function",
|
|
412
|
-
function: {}
|
|
413
|
-
};
|
|
414
|
-
const pendingFunction = pendingLegacyToolCall.function ??= {};
|
|
415
|
-
if (nextFunctionName) pendingFunction.name = nextFunctionName;
|
|
416
|
-
if (functionCall.arguments) pendingFunction.arguments = (pendingFunction.arguments ?? "") + functionCall.arguments;
|
|
417
|
-
}
|
|
418
|
-
if (!pendingLegacyToolCall) return leadingDeltas.length > 0 ? leadingDeltas : [{
|
|
419
|
-
delta: ordinaryDelta,
|
|
420
|
-
toolCalls: []
|
|
421
|
-
}];
|
|
422
|
-
if (finishReason === "function_call") {
|
|
423
|
-
const confirmedLegacyToolCall = pendingLegacyToolCall;
|
|
424
|
-
pendingLegacyToolCall = void 0;
|
|
425
|
-
pendingLegacyArgumentBytes = 0;
|
|
426
|
-
return [
|
|
427
|
-
...leadingDeltas,
|
|
428
|
-
{
|
|
429
|
-
delta: {},
|
|
430
|
-
toolCalls: [confirmedLegacyToolCall]
|
|
431
|
-
},
|
|
432
|
-
...takePendingFollowingDeltas()
|
|
433
|
-
];
|
|
434
|
-
}
|
|
435
|
-
if (finishReason) {
|
|
436
|
-
pendingLegacyArgumentBytes = 0;
|
|
437
|
-
pendingLegacyToolCall = void 0;
|
|
438
|
-
return [...leadingDeltas, ...takePendingFollowingDeltas()];
|
|
439
|
-
}
|
|
440
|
-
return leadingDeltas;
|
|
441
|
-
};
|
|
525
|
+
//#region packages/ai/src/transports/openai-reasoning-compat.ts
|
|
526
|
+
/**
|
|
527
|
+
* OpenAI reasoning-effort compatibility helpers.
|
|
528
|
+
*
|
|
529
|
+
* Keeps provider metadata and built-in model exceptions on one path before request payloads are built.
|
|
530
|
+
*/
|
|
531
|
+
const OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.1-codex-mini"]);
|
|
532
|
+
function readCompatReasoningEffortMap(compat) {
|
|
533
|
+
const rawMap = asOptionalObjectRecord(asOptionalObjectRecord(compat)?.reasoningEffortMap);
|
|
534
|
+
if (!rawMap) return {};
|
|
535
|
+
return Object.fromEntries(Object.entries(rawMap).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
|
|
442
536
|
}
|
|
443
|
-
/**
|
|
444
|
-
function
|
|
445
|
-
const
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
for (const block of output.content) {
|
|
457
|
-
if (!isToolCall(block)) continue;
|
|
458
|
-
const toolCall = block;
|
|
459
|
-
let completeArguments;
|
|
460
|
-
try {
|
|
461
|
-
completeArguments = typeof toolCall.partialArgs === "string" && toolCall.partialArgs.trim().length > 0 ? JSON.parse(toolCall.partialArgs) : void 0;
|
|
462
|
-
} catch {
|
|
463
|
-
completeArguments = void 0;
|
|
464
|
-
}
|
|
465
|
-
if (typeof toolCall.name !== "string" || toolCall.name.trim().length === 0 || !isRecord(completeArguments)) {
|
|
466
|
-
output.stopReason = "error";
|
|
467
|
-
output.errorMessage = "Provider returned an incomplete or malformed tool call";
|
|
468
|
-
output.content = output.content.filter((candidate) => !isToolCall(candidate));
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
toolCall.arguments = completeArguments;
|
|
472
|
-
}
|
|
473
|
-
for (let contentIndex = 0; contentIndex < output.content.length; contentIndex += 1) {
|
|
474
|
-
const block = output.content[contentIndex];
|
|
475
|
-
if (!block || !isToolCall(block)) continue;
|
|
476
|
-
delete block.partialArgs;
|
|
477
|
-
delete block.streamIndex;
|
|
478
|
-
options.onConfirmedToolCall?.(block, contentIndex);
|
|
479
|
-
}
|
|
537
|
+
/** Resolves the reasoning effort remap for an OpenAI-compatible model. */
|
|
538
|
+
function resolveOpenAIReasoningEffortMap(model, fallbackMap = {}) {
|
|
539
|
+
const provider = normalizeLowercaseStringOrEmpty(model.provider ?? "");
|
|
540
|
+
const id = normalizeLowercaseStringOrEmpty(model.id ?? "");
|
|
541
|
+
const builtinMap = provider === "openai" && OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS.has(id) ? {
|
|
542
|
+
minimal: "medium",
|
|
543
|
+
low: "medium"
|
|
544
|
+
} : {};
|
|
545
|
+
return {
|
|
546
|
+
...fallbackMap,
|
|
547
|
+
...builtinMap,
|
|
548
|
+
...readCompatReasoningEffortMap(model.compat)
|
|
549
|
+
};
|
|
480
550
|
}
|
|
481
551
|
//#endregion
|
|
482
552
|
//#region packages/ai/src/providers/openai-stop-reason.ts
|
|
@@ -506,32 +576,4 @@ function mapOpenAIStopReason(reason, options) {
|
|
|
506
576
|
};
|
|
507
577
|
}
|
|
508
578
|
//#endregion
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* OpenAI reasoning-effort compatibility helpers.
|
|
512
|
-
*
|
|
513
|
-
* Keeps provider metadata and built-in model exceptions on one path before request payloads are built.
|
|
514
|
-
*/
|
|
515
|
-
const OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.1-codex-mini"]);
|
|
516
|
-
function readCompatReasoningEffortMap(compat) {
|
|
517
|
-
if (!compat || typeof compat !== "object") return {};
|
|
518
|
-
const rawMap = compat.reasoningEffortMap;
|
|
519
|
-
if (!rawMap || typeof rawMap !== "object") return {};
|
|
520
|
-
return Object.fromEntries(Object.entries(rawMap).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
|
|
521
|
-
}
|
|
522
|
-
/** Resolves the reasoning effort remap for an OpenAI-compatible model. */
|
|
523
|
-
function resolveOpenAIReasoningEffortMap(model, fallbackMap = {}) {
|
|
524
|
-
const provider = normalizeLowercaseStringOrEmpty(model.provider ?? "");
|
|
525
|
-
const id = normalizeLowercaseStringOrEmpty(model.id ?? "");
|
|
526
|
-
const builtinMap = provider === "openai" && OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS.has(id) ? {
|
|
527
|
-
minimal: "medium",
|
|
528
|
-
low: "medium"
|
|
529
|
-
} : {};
|
|
530
|
-
return {
|
|
531
|
-
...fallbackMap,
|
|
532
|
-
...builtinMap,
|
|
533
|
-
...readCompatReasoningEffortMap(model.compat)
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
//#endregion
|
|
537
|
-
export { convertMessages as a, resolveOpenAICompletionsResponseFormat as c, rememberPendingCommentaryTags as d, tagPendingCommentaryText as f, finalizeOpenAICompletionsToolCalls as i, shouldOmitOllamaCompatResponseFormat as l, mapOpenAIStopReason as n, detectOpenAICompletionsCompat as o, createOpenAICompletionsToolCallDeltaNormalizer as r, resolveOpenAICompletionsCompat as s, resolveOpenAIReasoningEffortMap as t, clearPendingCommentaryText as u };
|
|
579
|
+
export { createOpenAICompletionsToolCallDeltaNormalizer as a, resolveOpenAICompletionsCompat as c, clearPendingCommentaryText as d, rememberPendingCommentaryTags as f, tagUnresolvedTextAsCommentary as h, hasToolCallHistory as i, resolveOpenAICompletionsResponseFormat as l, tagPendingCommentaryText as m, resolveOpenAIReasoningEffortMap as n, finalizeOpenAICompletionsToolCalls as o, tagInterruptedTextPhases as p, convertMessages as r, detectOpenAICompletionsCompat as s, mapOpenAIStopReason as t, shouldOmitOllamaCompatResponseFormat as u };
|