@openclaw/ai 2026.7.2-beta.6 → 2026.7.33
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 +5 -6
- package/dist/{anthropic-CH4UUnZr.mjs → anthropic-BML72tLz.mjs} +468 -101
- package/dist/{api-registry-DlMgPR39.d.mts → api-registry-BXYnCOIR.d.mts} +2 -1
- package/dist/{azure-openai-responses-client-compat-C7K7QfUE.mjs → azure-openai-responses-client-compat-a_O_GVQV.mjs} +2 -23
- package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-kEN8II8I.mjs} +13 -11
- package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-CtMlqaQ4.mjs} +4 -5
- package/dist/{event-stream-YjaPW20U.d.mts → event-stream-0nZeBKl2.d.mts} +1 -1
- package/dist/{event-stream-D8n2uFee.mjs → event-stream-ReMmOTzX.mjs} +6 -14
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-BsH5cqGj.mjs} +12 -1
- package/dist/{google-CtSg0iTS.mjs → google-DTM4O3e9.mjs} +5 -5
- package/dist/{google-shared-DNBz5rcD.mjs → google-shared-BAP0BQVi.mjs} +22 -34
- package/dist/{google-vertex-31f1uS9L.mjs → google-vertex-D58MZHCQ.mjs} +19 -6
- package/dist/host-4t713IeR.mjs +37 -0
- package/dist/{anthropic-SrGtwsJu.d.mts → index-BoTnz8cv.d.mts} +1 -27
- package/dist/index.d.mts +50 -7
- package/dist/index.mjs +5 -5
- package/dist/internal/anthropic.d.mts +62 -22
- package/dist/internal/anthropic.mjs +4 -5
- package/dist/internal/openai.d.mts +82 -98
- package/dist/internal/openai.mjs +6 -8
- package/dist/internal/runtime.d.mts +34 -13
- package/dist/internal/runtime.mjs +14 -26
- package/dist/internal/shared.d.mts +9 -26
- package/dist/internal/shared.mjs +2 -6
- package/dist/{json-parse-BvXNt1-7.mjs → json-parse-DzNSIQBq.mjs} +6 -4
- package/dist/{llm-request-activity-BjtkplhG.mjs → llm-request-activity-CehVkZP-.mjs} +19 -1
- package/dist/{mistral-CWmpvWYh.mjs → mistral-CePVNdws.mjs} +39 -141
- package/dist/model-utils-DgmOla96.mjs +69 -0
- package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-BHqbcipc.mjs} +154 -101
- package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-9qYFVS7H.mjs} +295 -81
- package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-D6l9URyV.mjs} +8 -10
- package/dist/openai-responses-shared-L3PWZvkm.mjs +1949 -0
- package/dist/{openai-tool-projection-OhX64DoP.mjs → openai-tool-projection-BPlyXt8H.mjs} +12 -32
- package/dist/providers.d.mts +2 -3
- package/dist/providers.mjs +10 -11
- package/dist/reasoning-tag-text-partitioner-axhAdUwg.mjs +394 -0
- package/dist/{src-QkygScBs.mjs → src-CZ503MYJ.mjs} +5 -24
- package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-RjWszj8c.mjs} +22 -2
- package/dist/transform-messages-BhGF_fF4.mjs +507 -0
- package/dist/{types-bzp5k29J.d.mts → types-DRgdPqaZ.d.mts} +0 -19
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +4 -4
- package/dist/{validation-B-j7cOYp.d.mts → validation-BDMWOr8d.d.mts} +1 -1
- package/dist/{validation-DAa_yFOM.mjs → validation-FrchoOlv.mjs} +7 -2
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/npm-shrinkwrap.json +645 -0
- package/package.json +11 -36
- package/dist/anthropic-usage-DWU-x8MI.mjs +0 -459
- package/dist/cache-retention-0x979a5V.mjs +0 -12
- package/dist/deferred-event-buffer-DAvyP7qA.mjs +0 -19
- package/dist/error-coercion-DgxlWC0n.mjs +0 -15
- package/dist/host-B9GUmcra.d.mts +0 -173
- package/dist/host-Dog2WQiR.mjs +0 -369
- package/dist/index-BVVgDSdq.d.mts +0 -1
- package/dist/internal/retry-after.d.mts +0 -5
- package/dist/internal/retry-after.mjs +0 -101
- package/dist/number-coercion-DvG7SNMg.mjs +0 -129
- package/dist/openai-completions-compat-DBWjXoMZ.d.mts +0 -43
- package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
- package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
- package/dist/openai-reasoning-compat-YgeLncHw.mjs +0 -396
- package/dist/openai-responses-shared-pXl6Wd8S.mjs +0 -392
- package/dist/openai-responses-stream-internal-Cw5txaGW.mjs +0 -2964
- package/dist/prompt-cache-stability-Cwcjv_fx.d.mts +0 -13
- package/dist/provider-error-CAEvRjry.mjs +0 -47
- package/dist/provider-options-D8bB3z9b.d.mts +0 -144
- package/dist/reasoning-tag-text-partitioner-CGDyLWUR.mjs +0 -12209
- package/dist/simple-options-9lhRrN73.mjs +0 -50
- package/dist/stream-first-event-timeout-DvDeSucC.d.mts +0 -29
- package/dist/tls-certificate-errors-DXSpluKI.mjs +0 -93
- package/dist/tool-result-text-CTpIRbYd.mjs +0 -225
- package/dist/transform-messages-C8mBqZxF.mjs +0 -2
- package/dist/transport-stream-shared-D81p90xq.mjs +0 -297
- package/dist/transports.d.mts +0 -573
- package/dist/transports.mjs +0 -4110
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { E as Model, F as SimpleStreamOptions, H as ThinkingBudgets, T as Message, W as ThinkingLevel, i as AssistantMessage, n as Api, z as StreamOptions } from "../types-
|
|
1
|
+
import { E as Model, F as SimpleStreamOptions, H as ThinkingBudgets, T as Message, W as ThinkingLevel, i as AssistantMessage, n as Api, z as StreamOptions } from "../types-DRgdPqaZ.mjs";
|
|
2
2
|
import { t as sanitizeSurrogates } from "../sanitize-unicode-BZiVbGwK.mjs";
|
|
3
|
-
import { n as normalizeStructuredPromptSection, r as sortPromptCacheToolsByName, t as normalizePromptCapabilityIds } from "../prompt-cache-stability-Cwcjv_fx.mjs";
|
|
4
3
|
|
|
5
4
|
//#region packages/ai/src/providers/simple-options.d.ts
|
|
6
5
|
type FirstEventStreamOptions = {
|
|
@@ -8,9 +7,6 @@ type FirstEventStreamOptions = {
|
|
|
8
7
|
onFirstEventTimeout?: (reason: Error) => void;
|
|
9
8
|
};
|
|
10
9
|
declare function buildBaseOptions(model: Model, options?: SimpleStreamOptions, apiKey?: string): StreamOptions & FirstEventStreamOptions;
|
|
11
|
-
declare function clampMaxTokensToModel(model: Model, requestedMaxTokens: number): number;
|
|
12
|
-
declare function clampMaxTokensToModel(model: Model, requestedMaxTokens: number | undefined): number | undefined;
|
|
13
|
-
declare function clampReasoning(effort: ThinkingLevel): Exclude<ThinkingLevel, "xhigh">;
|
|
14
10
|
declare function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, "xhigh"> | undefined;
|
|
15
11
|
declare function adjustMaxTokensForThinking(baseMaxTokens: number | undefined, modelMaxTokens: number, reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): {
|
|
16
12
|
maxTokens: number;
|
|
@@ -18,20 +14,11 @@ declare function adjustMaxTokensForThinking(baseMaxTokens: number | undefined, m
|
|
|
18
14
|
};
|
|
19
15
|
//#endregion
|
|
20
16
|
//#region packages/ai/src/providers/tool-result-text.d.ts
|
|
21
|
-
/** Media metadata alone is not an attachment; provider emitters need inline bytes. */
|
|
22
|
-
declare function hasMediaPayload(block: unknown): block is Record<string, unknown> & {
|
|
23
|
-
data: string;
|
|
24
|
-
};
|
|
25
|
-
/** Image metadata alone is not an attachment; provider emitters need inline bytes. */
|
|
26
|
-
declare function isImageWithMediaPayload<T>(block: T): block is T & {
|
|
27
|
-
type: "image";
|
|
28
|
-
data: string;
|
|
29
|
-
};
|
|
30
17
|
declare function describeToolResultMediaPlaceholder(blocks: readonly unknown[]): string | undefined;
|
|
31
18
|
declare function extractToolResultBlockText(block: unknown): string | undefined;
|
|
32
19
|
declare function extractToolResultText(blocks: readonly unknown[]): string;
|
|
33
20
|
//#endregion
|
|
34
|
-
//#region packages/ai/src/
|
|
21
|
+
//#region packages/ai/src/providers/transform-messages.d.ts
|
|
35
22
|
/**
|
|
36
23
|
* Normalize tool call ID for cross-provider compatibility.
|
|
37
24
|
* OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
|
|
@@ -39,6 +26,12 @@ declare function extractToolResultText(blocks: readonly unknown[]): string;
|
|
|
39
26
|
*/
|
|
40
27
|
declare function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>, normalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string): Message[];
|
|
41
28
|
//#endregion
|
|
29
|
+
//#region packages/ai/src/utils/prompt-cache-stability.d.ts
|
|
30
|
+
/** Normalize structured prompt text before hashing or snapshot comparison. */
|
|
31
|
+
declare function normalizeStructuredPromptSection(text: string): string;
|
|
32
|
+
/** Normalize, de-dupe, and sort capability ids for stable prompt payloads. */
|
|
33
|
+
declare function normalizePromptCapabilityIds(capabilities: ReadonlyArray<string>): string[];
|
|
34
|
+
//#endregion
|
|
42
35
|
//#region packages/ai/src/utils/system-prompt-cache-boundary.d.ts
|
|
43
36
|
declare const SYSTEM_PROMPT_CACHE_BOUNDARY = "\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n";
|
|
44
37
|
declare function stripSystemPromptCacheBoundary(text: string): string;
|
|
@@ -52,14 +45,4 @@ declare function prependSystemPromptAdditionAfterCacheBoundary(params: {
|
|
|
52
45
|
systemPromptAddition?: string;
|
|
53
46
|
}): string;
|
|
54
47
|
//#endregion
|
|
55
|
-
|
|
56
|
-
type TlsCertificateErrorKind = "certificate_invalid" | "hostname_mismatch";
|
|
57
|
-
type TlsCertificateErrorDetails = {
|
|
58
|
-
kind: TlsCertificateErrorKind;
|
|
59
|
-
code?: string;
|
|
60
|
-
message: string;
|
|
61
|
-
};
|
|
62
|
-
/** Classify deterministic Node/OpenSSL certificate validation failures. */
|
|
63
|
-
declare function inspectTlsCertificateError(error: unknown): TlsCertificateErrorDetails | null;
|
|
64
|
-
//#endregion
|
|
65
|
-
export { SYSTEM_PROMPT_CACHE_BOUNDARY, TlsCertificateErrorDetails, TlsCertificateErrorKind, adjustMaxTokensForThinking, buildBaseOptions, clampMaxTokensToModel, clampReasoning, describeToolResultMediaPlaceholder, ensureSystemPromptCacheBoundary, extractToolResultBlockText, extractToolResultText, hasMediaPayload, inspectTlsCertificateError, isImageWithMediaPayload, normalizePromptCapabilityIds, normalizeStructuredPromptSection, prependSystemPromptAdditionAfterCacheBoundary, sanitizeSurrogates, sortPromptCacheToolsByName, splitSystemPromptCacheBoundary, stripSystemPromptCacheBoundary, transformMessages };
|
|
48
|
+
export { SYSTEM_PROMPT_CACHE_BOUNDARY, adjustMaxTokensForThinking, buildBaseOptions, clampReasoning, describeToolResultMediaPlaceholder, ensureSystemPromptCacheBoundary, extractToolResultBlockText, extractToolResultText, normalizePromptCapabilityIds, normalizeStructuredPromptSection, prependSystemPromptAdditionAfterCacheBoundary, sanitizeSurrogates, splitSystemPromptCacheBoundary, stripSystemPromptCacheBoundary, transformMessages };
|
package/dist/internal/shared.mjs
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { i as transformMessages } from "../host-Dog2WQiR.mjs";
|
|
2
1
|
import { t as sanitizeSurrogates } from "../sanitize-unicode-DT5o51ur.mjs";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import "../transform-messages-C8mBqZxF.mjs";
|
|
6
|
-
import { t as inspectTlsCertificateError } from "../tls-certificate-errors-DXSpluKI.mjs";
|
|
7
|
-
export { SYSTEM_PROMPT_CACHE_BOUNDARY, adjustMaxTokensForThinking, buildBaseOptions, clampMaxTokensToModel, clampReasoning, describeToolResultMediaPlaceholder, ensureSystemPromptCacheBoundary, extractToolResultBlockText, extractToolResultText, hasMediaPayload, inspectTlsCertificateError, isImageWithMediaPayload, normalizePromptCapabilityIds, normalizeStructuredPromptSection, prependSystemPromptAdditionAfterCacheBoundary, sanitizeSurrogates, sortPromptCacheToolsByName, splitSystemPromptCacheBoundary, stripSystemPromptCacheBoundary, transformMessages };
|
|
2
|
+
import { S as normalizeStructuredPromptSection, _ as ensureSystemPromptCacheBoundary, a as adjustMaxTokensForThinking, b as stripSystemPromptCacheBoundary, g as SYSTEM_PROMPT_CACHE_BOUNDARY, i as extractToolResultText, n as describeToolResultMediaPlaceholder, o as buildBaseOptions, r as extractToolResultBlockText, s as clampReasoning, t as transformMessages, v as prependSystemPromptAdditionAfterCacheBoundary, x as normalizePromptCapabilityIds, y as splitSystemPromptCacheBoundary } from "../transform-messages-BhGF_fF4.mjs";
|
|
3
|
+
export { SYSTEM_PROMPT_CACHE_BOUNDARY, adjustMaxTokensForThinking, buildBaseOptions, clampReasoning, describeToolResultMediaPlaceholder, ensureSystemPromptCacheBoundary, extractToolResultBlockText, extractToolResultText, normalizePromptCapabilityIds, normalizeStructuredPromptSection, prependSystemPromptAdditionAfterCacheBoundary, sanitizeSurrogates, splitSystemPromptCacheBoundary, stripSystemPromptCacheBoundary, transformMessages };
|
|
@@ -42,7 +42,7 @@ function repairJson(json) {
|
|
|
42
42
|
let inString = false;
|
|
43
43
|
let stringValuePrefix = "";
|
|
44
44
|
for (let index = 0; index < json.length; index++) {
|
|
45
|
-
const char = json
|
|
45
|
+
const char = json[index];
|
|
46
46
|
if (!inString) {
|
|
47
47
|
repaired += char;
|
|
48
48
|
if (char === "\"") {
|
|
@@ -58,8 +58,8 @@ function repairJson(json) {
|
|
|
58
58
|
continue;
|
|
59
59
|
}
|
|
60
60
|
if (char === "\\") {
|
|
61
|
-
const nextChar = json
|
|
62
|
-
if (
|
|
61
|
+
const nextChar = json[index + 1];
|
|
62
|
+
if (nextChar === void 0) {
|
|
63
63
|
repaired += "\\\\";
|
|
64
64
|
continue;
|
|
65
65
|
}
|
|
@@ -96,7 +96,9 @@ function repairJson(json) {
|
|
|
96
96
|
return repaired;
|
|
97
97
|
}
|
|
98
98
|
function parseJsonWithRepair(json) {
|
|
99
|
-
|
|
99
|
+
const repairedJson = repairJson(json);
|
|
100
|
+
if (repairedJson !== json) return JSON.parse(repairedJson);
|
|
101
|
+
return JSON.parse(json);
|
|
100
102
|
}
|
|
101
103
|
function looksLikeWindowsPathPrefix(prefix) {
|
|
102
104
|
const tail = prefix.slice(-160);
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
//#region packages/ai/src/utils/deferred-event-buffer.ts
|
|
2
|
+
function createDeferredEventBuffer(sink, onBufferedEvent) {
|
|
3
|
+
let events = [];
|
|
4
|
+
return {
|
|
5
|
+
push(event) {
|
|
6
|
+
events.push(event);
|
|
7
|
+
onBufferedEvent?.();
|
|
8
|
+
},
|
|
9
|
+
flush() {
|
|
10
|
+
for (const event of events) sink.push(event);
|
|
11
|
+
events = [];
|
|
12
|
+
},
|
|
13
|
+
discard() {
|
|
14
|
+
events = [];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
1
19
|
//#region packages/ai/src/utils/llm-request-activity.ts
|
|
2
20
|
const requestActivityListeners = /* @__PURE__ */ new WeakMap();
|
|
3
21
|
function notifyLlmRequestActivity(signal) {
|
|
@@ -14,4 +32,4 @@ function onLlmRequestActivity(signal, listener) {
|
|
|
14
32
|
};
|
|
15
33
|
}
|
|
16
34
|
//#endregion
|
|
17
|
-
export { onLlmRequestActivity as n, notifyLlmRequestActivity as t };
|
|
35
|
+
export { onLlmRequestActivity as n, createDeferredEventBuffer as r, notifyLlmRequestActivity as t };
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import { n as getEnvApiKey } from "./env-api-keys-
|
|
2
|
-
import { t as AssistantMessageEventStream } from "./event-stream-
|
|
3
|
-
import {
|
|
1
|
+
import { n as getEnvApiKey } from "./env-api-keys-CtMlqaQ4.mjs";
|
|
2
|
+
import { t as AssistantMessageEventStream } from "./event-stream-ReMmOTzX.mjs";
|
|
3
|
+
import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
|
|
4
|
+
import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-DgmOla96.mjs";
|
|
5
|
+
import { n as parseStreamingJson } from "./json-parse-DzNSIQBq.mjs";
|
|
4
6
|
import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import { c as calculateCost, l as clampThinkingLevel } from "./number-coercion-DvG7SNMg.mjs";
|
|
7
|
-
import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
|
|
8
|
-
import { d as transportAbortError } from "./transport-stream-shared-D81p90xq.mjs";
|
|
7
|
+
import { b as stripSystemPromptCacheBoundary, i as extractToolResultText, n as describeToolResultMediaPlaceholder, o as buildBaseOptions, t as transformMessages } from "./transform-messages-BhGF_fF4.mjs";
|
|
9
8
|
import { t as shortHash } from "./hash-CHgqbJmD.mjs";
|
|
10
|
-
import { n as buildBaseOptions, r as clampMaxTokensToModel } from "./simple-options-9lhRrN73.mjs";
|
|
11
|
-
import "./transform-messages-C8mBqZxF.mjs";
|
|
12
9
|
import { t as createSseByteGuard } from "./streaming-byte-guard-BrbkbwUu.mjs";
|
|
13
|
-
import { randomUUID } from "node:crypto";
|
|
14
10
|
import { HTTPClient, Mistral } from "@mistralai/mistralai";
|
|
15
11
|
//#region packages/ai/src/providers/mistral.ts
|
|
16
12
|
const MISTRAL_TOOL_CALL_ID_LENGTH = 9;
|
|
@@ -74,21 +70,13 @@ const streamMistral = (model, context, options) => {
|
|
|
74
70
|
let payload = buildChatPayload(model, context, transformMessages(context.messages, model, (id) => normalizeMistralToolCallId(id)), options);
|
|
75
71
|
const nextPayload = await options?.onPayload?.(payload, model);
|
|
76
72
|
if (nextPayload !== void 0) payload = nextPayload;
|
|
77
|
-
const
|
|
78
|
-
...model.headers,
|
|
79
|
-
...options?.headers
|
|
80
|
-
};
|
|
81
|
-
if (resolveMistralPromptCacheKey(options) && options?.sessionId) headers["x-affinity"] ||= options.sessionId;
|
|
82
|
-
const mistralStream = await mistral.chat.stream(payload, {
|
|
83
|
-
headers,
|
|
84
|
-
signal: options?.signal
|
|
85
|
-
});
|
|
73
|
+
const mistralStream = await mistral.chat.stream(payload, buildRequestOptions(model, options));
|
|
86
74
|
stream.push({
|
|
87
75
|
type: "start",
|
|
88
76
|
partial: output
|
|
89
77
|
});
|
|
90
78
|
await consumeChatStream(model, output, stream, mistralStream);
|
|
91
|
-
if (options?.signal?.aborted) throw
|
|
79
|
+
if (options?.signal?.aborted) throw new Error("Request was aborted");
|
|
92
80
|
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
|
|
93
81
|
stream.push({
|
|
94
82
|
type: "done",
|
|
@@ -116,10 +104,7 @@ const streamMistral = (model, context, options) => {
|
|
|
116
104
|
const streamSimpleMistral = (model, context, options) => {
|
|
117
105
|
const apiKey = options?.apiKey || getEnvApiKey(model.provider);
|
|
118
106
|
if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
119
|
-
const base =
|
|
120
|
-
...buildBaseOptions(model, options, apiKey),
|
|
121
|
-
maxTokens: clampMaxTokensToModel(model, options?.maxTokens)
|
|
122
|
-
};
|
|
107
|
+
const base = buildBaseOptions(model, options, apiKey);
|
|
123
108
|
const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : void 0;
|
|
124
109
|
const reasoning = clampedReasoning === "off" ? void 0 : clampedReasoning;
|
|
125
110
|
const shouldUseReasoning = model.reasoning && reasoning !== void 0;
|
|
@@ -177,7 +162,7 @@ function deriveMistralToolCallId(id, attempt) {
|
|
|
177
162
|
const normalized = id.replace(/[^a-zA-Z0-9]/g, "");
|
|
178
163
|
if (attempt === 0 && normalized.length === MISTRAL_TOOL_CALL_ID_LENGTH) return normalized;
|
|
179
164
|
const seedBase = normalized || id;
|
|
180
|
-
return shortHash(attempt === 0 ? seedBase : `${seedBase}:${attempt}`).replace(/[^a-zA-Z0-9]/g, "").
|
|
165
|
+
return shortHash(attempt === 0 ? seedBase : `${seedBase}:${attempt}`).replace(/[^a-zA-Z0-9]/g, "").slice(0, MISTRAL_TOOL_CALL_ID_LENGTH);
|
|
181
166
|
}
|
|
182
167
|
function formatMistralError(error) {
|
|
183
168
|
if (error instanceof Error) {
|
|
@@ -192,8 +177,7 @@ function formatMistralError(error) {
|
|
|
192
177
|
}
|
|
193
178
|
function truncateErrorText(text, maxChars) {
|
|
194
179
|
if (text.length <= maxChars) return text;
|
|
195
|
-
|
|
196
|
-
return `${truncated}... [truncated ${text.length - truncated.length} chars]`;
|
|
180
|
+
return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;
|
|
197
181
|
}
|
|
198
182
|
function safeJsonStringify(value) {
|
|
199
183
|
try {
|
|
@@ -203,6 +187,16 @@ function safeJsonStringify(value) {
|
|
|
203
187
|
return String(value);
|
|
204
188
|
}
|
|
205
189
|
}
|
|
190
|
+
function buildRequestOptions(model, options) {
|
|
191
|
+
const requestOptions = { retries: { strategy: "none" } };
|
|
192
|
+
if (options?.signal) requestOptions.signal = options.signal;
|
|
193
|
+
const headers = {};
|
|
194
|
+
if (model.headers) Object.assign(headers, model.headers);
|
|
195
|
+
if (options?.headers) Object.assign(headers, options.headers);
|
|
196
|
+
if (options?.sessionId && !headers["x-affinity"]) headers["x-affinity"] = options.sessionId;
|
|
197
|
+
if (Object.keys(headers).length > 0) requestOptions.headers = headers;
|
|
198
|
+
return requestOptions;
|
|
199
|
+
}
|
|
206
200
|
function buildChatPayload(model, context, messages, options) {
|
|
207
201
|
const payload = {
|
|
208
202
|
model: model.id,
|
|
@@ -224,86 +218,17 @@ function buildChatPayload(model, context, messages, options) {
|
|
|
224
218
|
}
|
|
225
219
|
if (options?.promptMode) payload.promptMode = options.promptMode;
|
|
226
220
|
if (options?.reasoningEffort) payload.reasoningEffort = options.reasoningEffort;
|
|
227
|
-
const promptCacheKey = resolveMistralPromptCacheKey(options);
|
|
228
|
-
if (promptCacheKey) payload.promptCacheKey = promptCacheKey;
|
|
229
221
|
if (context.systemPrompt) payload.messages.unshift({
|
|
230
222
|
role: "system",
|
|
231
223
|
content: sanitizeSurrogates(stripSystemPromptCacheBoundary(context.systemPrompt))
|
|
232
224
|
});
|
|
233
225
|
return payload;
|
|
234
226
|
}
|
|
235
|
-
function resolveMistralPromptCacheKey(options) {
|
|
236
|
-
if (options?.cacheRetention === "none") return;
|
|
237
|
-
return options?.promptCacheKey?.trim() || options?.sessionId?.trim() || void 0;
|
|
238
|
-
}
|
|
239
|
-
function readMistralCachedPromptTokens(usage, promptTokens) {
|
|
240
|
-
const record = usage;
|
|
241
|
-
const rawCachedTokens = record.promptTokensDetails?.cachedTokens ?? record.prompt_tokens_details?.cached_tokens ?? record.cachedTokens ?? record.cached_tokens;
|
|
242
|
-
return Math.min(promptTokens, Math.max(0, typeof rawCachedTokens === "number" && Number.isFinite(rawCachedTokens) ? rawCachedTokens : 0));
|
|
243
|
-
}
|
|
244
227
|
async function consumeChatStream(model, output, stream, mistralStream) {
|
|
245
228
|
let currentBlock = null;
|
|
246
229
|
const blocks = output.content;
|
|
247
230
|
const blockIndex = () => blocks.length - 1;
|
|
248
|
-
const
|
|
249
|
-
const normalizeMissingToolCallId = createMistralToolCallIdNormalizer();
|
|
250
|
-
const missingToolCallIdScope = randomUUID();
|
|
251
|
-
const createMissingToolCallId = (contentIndex) => normalizeMissingToolCallId(`${missingToolCallIdScope}:toolcall:${contentIndex}`);
|
|
252
|
-
const findIdentityCandidates = (matches, excludedContentIndexes) => {
|
|
253
|
-
const candidates = /* @__PURE__ */ new Set();
|
|
254
|
-
for (const [contentIndex, identity] of toolBlockIdentities) if (!excludedContentIndexes?.has(contentIndex) && matches(identity)) candidates.add(contentIndex);
|
|
255
|
-
return candidates;
|
|
256
|
-
};
|
|
257
|
-
const intersectCandidates = (left, right) => new Set([...left].filter((contentIndex) => right.has(contentIndex)));
|
|
258
|
-
const requireSingleCandidate = (candidates) => {
|
|
259
|
-
if (candidates.size > 1) throw new Error("Mistral streamed tool-call continuation is ambiguous; refusing to merge arguments");
|
|
260
|
-
return candidates.values().next().value;
|
|
261
|
-
};
|
|
262
|
-
const requireExistingCandidate = (candidates) => {
|
|
263
|
-
const candidate = requireSingleCandidate(candidates);
|
|
264
|
-
if (candidate === void 0) throw new Error("Mistral streamed tool-call identities conflict; refusing to merge arguments");
|
|
265
|
-
return candidate;
|
|
266
|
-
};
|
|
267
|
-
const resolveToolBlockIndex = (params) => {
|
|
268
|
-
const explicitId = params.explicitId;
|
|
269
|
-
const functionName = params.functionName;
|
|
270
|
-
const toolCallIndex = params.index;
|
|
271
|
-
const idCandidates = explicitId ? findIdentityCandidates((identity) => identity.explicitIds.has(explicitId), params.usedContentIndexes) : /* @__PURE__ */ new Set();
|
|
272
|
-
const nameCandidates = functionName ? findIdentityCandidates((identity) => identity.functionNames.has(functionName), params.usedContentIndexes) : /* @__PURE__ */ new Set();
|
|
273
|
-
const indexCandidates = toolCallIndex === void 0 ? /* @__PURE__ */ new Set() : findIdentityCandidates((identity) => identity.indexes.has(toolCallIndex), params.usedContentIndexes);
|
|
274
|
-
if (idCandidates.size > 0) {
|
|
275
|
-
let candidates = idCandidates;
|
|
276
|
-
if (nameCandidates.size > 0) candidates = intersectCandidates(candidates, nameCandidates);
|
|
277
|
-
return requireExistingCandidate(candidates);
|
|
278
|
-
}
|
|
279
|
-
if (nameCandidates.size > 0) {
|
|
280
|
-
const idCompatibleCandidates = new Set([...nameCandidates].filter((contentIndex) => {
|
|
281
|
-
const identity = toolBlockIdentities.get(contentIndex);
|
|
282
|
-
if (!identity) return false;
|
|
283
|
-
return !explicitId || identity.explicitIds.size === 0;
|
|
284
|
-
}));
|
|
285
|
-
if (idCompatibleCandidates.size <= 1 && (toolCallIndex === void 0 || toolCallIndex === 0)) return requireSingleCandidate(idCompatibleCandidates);
|
|
286
|
-
const indexCompatibleCandidates = new Set([...idCompatibleCandidates].filter((contentIndex) => {
|
|
287
|
-
const identity = toolBlockIdentities.get(contentIndex);
|
|
288
|
-
if (!identity) return false;
|
|
289
|
-
return toolCallIndex === void 0 || identity.indexes.size === 0 || identity.indexes.has(toolCallIndex);
|
|
290
|
-
}));
|
|
291
|
-
if (indexCompatibleCandidates.size === 0) return;
|
|
292
|
-
return requireSingleCandidate(indexCompatibleCandidates);
|
|
293
|
-
}
|
|
294
|
-
if (functionName) {
|
|
295
|
-
const namelessCandidates = new Set([...indexCandidates].filter((contentIndex) => {
|
|
296
|
-
const identity = toolBlockIdentities.get(contentIndex);
|
|
297
|
-
return identity?.functionNames.size === 0 && (!explicitId || identity.explicitIds.size === 0);
|
|
298
|
-
}));
|
|
299
|
-
return requireSingleCandidate(namelessCandidates);
|
|
300
|
-
}
|
|
301
|
-
if (explicitId) {
|
|
302
|
-
const idlessCandidates = new Set([...indexCandidates].filter((contentIndex) => toolBlockIdentities.get(contentIndex)?.explicitIds.size === 0));
|
|
303
|
-
return requireSingleCandidate(idlessCandidates);
|
|
304
|
-
}
|
|
305
|
-
return requireSingleCandidate(indexCandidates);
|
|
306
|
-
};
|
|
231
|
+
const toolBlocksByKey = /* @__PURE__ */ new Map();
|
|
307
232
|
const finishCurrentBlock = (block) => {
|
|
308
233
|
if (!block) return;
|
|
309
234
|
if (block.type === "text") {
|
|
@@ -326,13 +251,11 @@ async function consumeChatStream(model, output, stream, mistralStream) {
|
|
|
326
251
|
const chunk = event.data;
|
|
327
252
|
output.responseId ||= chunk.id;
|
|
328
253
|
if (chunk.usage) {
|
|
329
|
-
|
|
330
|
-
const cachedPromptTokens = readMistralCachedPromptTokens(chunk.usage, promptTokens);
|
|
331
|
-
output.usage.input = Math.max(0, promptTokens - cachedPromptTokens);
|
|
254
|
+
output.usage.input = chunk.usage.promptTokens || 0;
|
|
332
255
|
output.usage.output = chunk.usage.completionTokens || 0;
|
|
333
|
-
output.usage.cacheRead =
|
|
256
|
+
output.usage.cacheRead = 0;
|
|
334
257
|
output.usage.cacheWrite = 0;
|
|
335
|
-
output.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output
|
|
258
|
+
output.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output;
|
|
336
259
|
calculateCost(model, output.usage);
|
|
337
260
|
}
|
|
338
261
|
const choice = chunk.choices[0];
|
|
@@ -417,77 +340,52 @@ async function consumeChatStream(model, output, stream, mistralStream) {
|
|
|
417
340
|
}
|
|
418
341
|
}
|
|
419
342
|
const toolCalls = delta.toolCalls || [];
|
|
420
|
-
const usedToolBlockIndexes = /* @__PURE__ */ new Set();
|
|
421
343
|
for (const toolCall of toolCalls) {
|
|
422
344
|
if (currentBlock) {
|
|
423
345
|
finishCurrentBlock(currentBlock);
|
|
424
346
|
currentBlock = null;
|
|
425
347
|
}
|
|
426
|
-
const
|
|
427
|
-
const
|
|
428
|
-
const
|
|
429
|
-
const existingIndex = resolveToolBlockIndex({
|
|
430
|
-
explicitId: providedCallId,
|
|
431
|
-
functionName,
|
|
432
|
-
index: toolCallIndex,
|
|
433
|
-
usedContentIndexes: usedToolBlockIndexes
|
|
434
|
-
});
|
|
348
|
+
const callId = toolCall.id && toolCall.id !== "null" ? toolCall.id : deriveMistralToolCallId(`toolcall:${toolCall.index ?? 0}`, 0);
|
|
349
|
+
const key = `${callId}:${toolCall.index || 0}`;
|
|
350
|
+
const existingIndex = toolBlocksByKey.get(key);
|
|
435
351
|
let block;
|
|
436
352
|
if (existingIndex !== void 0) {
|
|
437
353
|
const existing = output.content[existingIndex];
|
|
438
354
|
if (existing?.type === "toolCall") block = existing;
|
|
439
355
|
}
|
|
440
356
|
if (!block) {
|
|
441
|
-
const contentIndex = output.content.length;
|
|
442
357
|
block = {
|
|
443
358
|
type: "toolCall",
|
|
444
|
-
id:
|
|
445
|
-
name:
|
|
359
|
+
id: callId,
|
|
360
|
+
name: toolCall.function.name,
|
|
446
361
|
arguments: {},
|
|
447
362
|
partialArgs: ""
|
|
448
363
|
};
|
|
449
364
|
output.content.push(block);
|
|
450
|
-
|
|
451
|
-
explicitIds: new Set(providedCallId ? [providedCallId] : []),
|
|
452
|
-
functionNames: new Set(functionName ? [functionName] : []),
|
|
453
|
-
indexes: new Set(toolCallIndex === void 0 ? [] : [toolCallIndex])
|
|
454
|
-
});
|
|
365
|
+
toolBlocksByKey.set(key, output.content.length - 1);
|
|
455
366
|
stream.push({
|
|
456
367
|
type: "toolcall_start",
|
|
457
|
-
contentIndex,
|
|
368
|
+
contentIndex: output.content.length - 1,
|
|
458
369
|
partial: output
|
|
459
370
|
});
|
|
460
371
|
}
|
|
461
|
-
const contentIndex = output.content.indexOf(block);
|
|
462
|
-
const identity = toolBlockIdentities.get(contentIndex);
|
|
463
|
-
if (!identity) throw new Error("Mistral streamed tool-call identity is missing");
|
|
464
|
-
usedToolBlockIndexes.add(contentIndex);
|
|
465
|
-
if (providedCallId) {
|
|
466
|
-
block.id = providedCallId;
|
|
467
|
-
identity.explicitIds.add(providedCallId);
|
|
468
|
-
}
|
|
469
|
-
if (functionName) {
|
|
470
|
-
if (identity.functionNames.size > 0 && !identity.functionNames.has(functionName)) throw new Error("Mistral streamed tool-call continuation changed function name; refusing to merge arguments");
|
|
471
|
-
block.name = functionName;
|
|
472
|
-
identity.functionNames.add(functionName);
|
|
473
|
-
}
|
|
474
|
-
if (toolCallIndex !== void 0) identity.indexes.add(toolCallIndex);
|
|
475
372
|
const argsDelta = typeof toolCall.function.arguments === "string" ? toolCall.function.arguments : JSON.stringify(toolCall.function.arguments || {});
|
|
476
373
|
block.partialArgs = (block.partialArgs || "") + argsDelta;
|
|
477
374
|
block.arguments = parseStreamingJson(block.partialArgs);
|
|
478
375
|
stream.push({
|
|
479
376
|
type: "toolcall_delta",
|
|
480
|
-
contentIndex,
|
|
377
|
+
contentIndex: toolBlocksByKey.get(key),
|
|
481
378
|
delta: argsDelta,
|
|
482
379
|
partial: output
|
|
483
380
|
});
|
|
484
381
|
}
|
|
485
382
|
}
|
|
486
383
|
finishCurrentBlock(currentBlock);
|
|
487
|
-
for (const index of
|
|
488
|
-
const block = output.content
|
|
489
|
-
if (block
|
|
384
|
+
for (const index of toolBlocksByKey.values()) {
|
|
385
|
+
const block = output.content[index];
|
|
386
|
+
if (block.type !== "toolCall") continue;
|
|
490
387
|
const toolBlock = block;
|
|
388
|
+
toolBlock.arguments = parseStreamingJson(toolBlock.partialArgs);
|
|
491
389
|
delete toolBlock.partialArgs;
|
|
492
390
|
stream.push({
|
|
493
391
|
type: "toolcall_end",
|
|
@@ -595,14 +493,14 @@ function toChatMessages(messages, supportsImages) {
|
|
|
595
493
|
continue;
|
|
596
494
|
}
|
|
597
495
|
const toolContent = [];
|
|
598
|
-
const toolText = buildToolResultText(extractToolResultText(msg.content), describeToolResultMediaPlaceholder(msg.content), msg.content.some(
|
|
496
|
+
const toolText = buildToolResultText(extractToolResultText(msg.content), describeToolResultMediaPlaceholder(msg.content), msg.content.some((part) => part.type === "image"), supportsImages, msg.isError);
|
|
599
497
|
toolContent.push({
|
|
600
498
|
type: "text",
|
|
601
499
|
text: toolText
|
|
602
500
|
});
|
|
603
501
|
for (const part of msg.content) {
|
|
604
502
|
if (!supportsImages) continue;
|
|
605
|
-
if (
|
|
503
|
+
if (part.type !== "image") continue;
|
|
606
504
|
toolContent.push({
|
|
607
505
|
type: "image_url",
|
|
608
506
|
imageUrl: `data:${part.mimeType};base64,${part.data}`
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { c as resolveClaudeNativeThinkingLevelMap, i as requiresClaudeMandatoryAdaptiveThinking } from "./src-CZ503MYJ.mjs";
|
|
2
|
+
//#region packages/ai/src/model-utils.ts
|
|
3
|
+
/** Calculates and stores model cost fields from token usage and per-million pricing. */
|
|
4
|
+
function calculateCost(model, usage) {
|
|
5
|
+
usage.cost.input = model.cost.input / 1e6 * usage.input;
|
|
6
|
+
usage.cost.output = model.cost.output / 1e6 * usage.output;
|
|
7
|
+
usage.cost.cacheRead = model.cost.cacheRead / 1e6 * usage.cacheRead;
|
|
8
|
+
usage.cost.cacheWrite = model.cost.cacheWrite / 1e6 * usage.cacheWrite;
|
|
9
|
+
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
10
|
+
return usage.cost;
|
|
11
|
+
}
|
|
12
|
+
/** Replaces the catalog estimate when the provider reports an authoritative billed total. */
|
|
13
|
+
function applyProviderReportedUsageCost(usage, reportedCost) {
|
|
14
|
+
if (typeof reportedCost !== "number" || !Number.isFinite(reportedCost) || reportedCost < 0) return;
|
|
15
|
+
usage.cost.total = reportedCost;
|
|
16
|
+
usage.cost.totalOrigin = "provider-billed";
|
|
17
|
+
}
|
|
18
|
+
const EXTENDED_THINKING_LEVELS = [
|
|
19
|
+
"off",
|
|
20
|
+
"minimal",
|
|
21
|
+
"low",
|
|
22
|
+
"medium",
|
|
23
|
+
"high",
|
|
24
|
+
"xhigh",
|
|
25
|
+
"max"
|
|
26
|
+
];
|
|
27
|
+
function resolveThinkingLevelMap(model) {
|
|
28
|
+
return model.api === "anthropic-messages" ? resolveClaudeNativeThinkingLevelMap(model) ?? model.thinkingLevelMap : model.thinkingLevelMap;
|
|
29
|
+
}
|
|
30
|
+
/** Returns thinking levels exposed by a reasoning-capable model. */
|
|
31
|
+
function getSupportedThinkingLevels(model) {
|
|
32
|
+
const mandatoryAdaptiveContract = model.api === "anthropic-messages" && requiresClaudeMandatoryAdaptiveThinking(model);
|
|
33
|
+
if (!model.reasoning && !mandatoryAdaptiveContract) return ["off"];
|
|
34
|
+
const thinkingLevelMap = resolveThinkingLevelMap(model);
|
|
35
|
+
return EXTENDED_THINKING_LEVELS.filter((level) => {
|
|
36
|
+
const mapped = thinkingLevelMap?.[level];
|
|
37
|
+
if (mapped === null) return false;
|
|
38
|
+
if (level === "xhigh" || level === "max") return mapped !== void 0;
|
|
39
|
+
return true;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** Clamps a requested thinking level to the closest supported level for a model. */
|
|
43
|
+
function clampThinkingLevel(model, level) {
|
|
44
|
+
const availableLevels = getSupportedThinkingLevels(model);
|
|
45
|
+
if (availableLevels.includes(level)) return level;
|
|
46
|
+
const requestedIndex = EXTENDED_THINKING_LEVELS.indexOf(level);
|
|
47
|
+
if (requestedIndex === -1) return availableLevels[0] ?? "off";
|
|
48
|
+
const thinkingLevelMap = resolveThinkingLevelMap(model);
|
|
49
|
+
if ((level === "xhigh" || level === "max") && thinkingLevelMap?.[level] === null) for (let i = requestedIndex - 1; i >= 0; i--) {
|
|
50
|
+
const candidate = EXTENDED_THINKING_LEVELS[i];
|
|
51
|
+
if (availableLevels.includes(candidate)) return candidate;
|
|
52
|
+
}
|
|
53
|
+
for (let i = requestedIndex; i < EXTENDED_THINKING_LEVELS.length; i++) {
|
|
54
|
+
const candidate = EXTENDED_THINKING_LEVELS[i];
|
|
55
|
+
if (availableLevels.includes(candidate)) return candidate;
|
|
56
|
+
}
|
|
57
|
+
for (let i = requestedIndex - 1; i >= 0; i--) {
|
|
58
|
+
const candidate = EXTENDED_THINKING_LEVELS[i];
|
|
59
|
+
if (availableLevels.includes(candidate)) return candidate;
|
|
60
|
+
}
|
|
61
|
+
return availableLevels[0] ?? "off";
|
|
62
|
+
}
|
|
63
|
+
/** Compares model identity by provider and id. */
|
|
64
|
+
function modelsAreEqual(a, b) {
|
|
65
|
+
if (!a || !b) return false;
|
|
66
|
+
return a.id === b.id && a.provider === b.provider;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { modelsAreEqual as a, getSupportedThinkingLevels as i, calculateCost as n, clampThinkingLevel as r, applyProviderReportedUsageCost as t };
|