@openclaw/ai 2026.7.2-beta.7 → 2026.7.34

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.
Files changed (78) hide show
  1. package/README.md +5 -6
  2. package/dist/{anthropic-CH4UUnZr.mjs → anthropic-Bcdbq-l5.mjs} +467 -100
  3. package/dist/{api-registry-DlMgPR39.d.mts → api-registry-BXYnCOIR.d.mts} +2 -1
  4. package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-2xhpNPWg.mjs} +13 -11
  5. package/dist/{azure-openai-responses-client-compat-C7K7QfUE.mjs → azure-openai-responses-client-compat-a_O_GVQV.mjs} +2 -23
  6. package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-CtMlqaQ4.mjs} +4 -5
  7. package/dist/{event-stream-YjaPW20U.d.mts → event-stream-0nZeBKl2.d.mts} +1 -1
  8. package/dist/{event-stream-D8n2uFee.mjs → event-stream-ReMmOTzX.mjs} +6 -14
  9. package/dist/event-stream.d.mts +1 -1
  10. package/dist/event-stream.mjs +1 -1
  11. package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-BsH5cqGj.mjs} +12 -1
  12. package/dist/{google-CtSg0iTS.mjs → google-C6P31moq.mjs} +5 -5
  13. package/dist/{google-shared-DNBz5rcD.mjs → google-shared-BeyXFAcf.mjs} +26 -34
  14. package/dist/{google-vertex-31f1uS9L.mjs → google-vertex--9_gT74B.mjs} +19 -6
  15. package/dist/host-4t713IeR.mjs +37 -0
  16. package/dist/{anthropic-SrGtwsJu.d.mts → index-CGDEoorl.d.mts} +2 -6
  17. package/dist/index.d.mts +50 -7
  18. package/dist/index.mjs +5 -5
  19. package/dist/internal/anthropic.d.mts +61 -21
  20. package/dist/internal/anthropic.mjs +4 -5
  21. package/dist/internal/openai.d.mts +89 -98
  22. package/dist/internal/openai.mjs +6 -8
  23. package/dist/internal/runtime.d.mts +34 -13
  24. package/dist/internal/runtime.mjs +14 -26
  25. package/dist/internal/shared.d.mts +9 -26
  26. package/dist/internal/shared.mjs +2 -6
  27. package/dist/{json-parse-BvXNt1-7.mjs → json-parse-DzNSIQBq.mjs} +6 -4
  28. package/dist/{llm-request-activity-BjtkplhG.mjs → llm-request-activity-CehVkZP-.mjs} +19 -1
  29. package/dist/{mistral-CWmpvWYh.mjs → mistral-CBm3OQWD.mjs} +39 -141
  30. package/dist/model-utils-Cn9KAz3z.mjs +69 -0
  31. package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-M2RVpycr.mjs} +154 -101
  32. package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-BUlMEeBc.mjs} +295 -81
  33. package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-DW61C22l.mjs} +9 -14
  34. package/dist/openai-responses-shared-BhYsVkwW.mjs +1949 -0
  35. package/dist/{openai-tool-projection-OhX64DoP.mjs → openai-tool-projection-g4HuxD26.mjs} +20 -31
  36. package/dist/providers.d.mts +2 -3
  37. package/dist/providers.mjs +10 -11
  38. package/dist/reasoning-tag-text-partitioner-axhAdUwg.mjs +394 -0
  39. package/dist/{src-QkygScBs.mjs → src-CjOfhrH3.mjs} +6 -17
  40. package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-RjWszj8c.mjs} +22 -2
  41. package/dist/transform-messages-DoWx35pj.mjs +509 -0
  42. package/dist/{types-bzp5k29J.d.mts → types-DRgdPqaZ.d.mts} +0 -19
  43. package/dist/types.d.mts +5 -5
  44. package/dist/types.mjs +4 -4
  45. package/dist/{validation-B-j7cOYp.d.mts → validation-BDMWOr8d.d.mts} +1 -1
  46. package/dist/{validation-DAa_yFOM.mjs → validation-FrchoOlv.mjs} +7 -2
  47. package/dist/validation.d.mts +1 -1
  48. package/dist/validation.mjs +1 -1
  49. package/npm-shrinkwrap.json +645 -0
  50. package/package.json +11 -36
  51. package/dist/anthropic-usage-DWU-x8MI.mjs +0 -459
  52. package/dist/cache-retention-0x979a5V.mjs +0 -12
  53. package/dist/deferred-event-buffer-DAvyP7qA.mjs +0 -19
  54. package/dist/error-coercion-DgxlWC0n.mjs +0 -15
  55. package/dist/host-B9GUmcra.d.mts +0 -173
  56. package/dist/host-Dog2WQiR.mjs +0 -369
  57. package/dist/index-BVVgDSdq.d.mts +0 -1
  58. package/dist/internal/retry-after.d.mts +0 -5
  59. package/dist/internal/retry-after.mjs +0 -101
  60. package/dist/number-coercion-DvG7SNMg.mjs +0 -129
  61. package/dist/openai-completions-compat-DBWjXoMZ.d.mts +0 -43
  62. package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
  63. package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
  64. package/dist/openai-reasoning-compat-YgeLncHw.mjs +0 -396
  65. package/dist/openai-responses-shared-pXl6Wd8S.mjs +0 -392
  66. package/dist/openai-responses-stream-internal-Cw5txaGW.mjs +0 -2964
  67. package/dist/prompt-cache-stability-Cwcjv_fx.d.mts +0 -13
  68. package/dist/provider-error-CAEvRjry.mjs +0 -47
  69. package/dist/provider-options-D8bB3z9b.d.mts +0 -144
  70. package/dist/reasoning-tag-text-partitioner-CGDyLWUR.mjs +0 -12209
  71. package/dist/simple-options-9lhRrN73.mjs +0 -50
  72. package/dist/stream-first-event-timeout-DvDeSucC.d.mts +0 -29
  73. package/dist/tls-certificate-errors-DXSpluKI.mjs +0 -93
  74. package/dist/tool-result-text-CTpIRbYd.mjs +0 -225
  75. package/dist/transform-messages-C8mBqZxF.mjs +0 -2
  76. package/dist/transport-stream-shared-D81p90xq.mjs +0 -297
  77. package/dist/transports.d.mts +0 -573
  78. package/dist/transports.mjs +0 -4110
@@ -1,14 +1,13 @@
1
- import { n as getEnvApiKey, t as findEnvKeys } from "../env-api-keys-DrgeBuva.mjs";
1
+ import { n as getEnvApiKey, t as findEnvKeys } from "../env-api-keys-CtMlqaQ4.mjs";
2
2
  import { n as createApiRegistry, t as createLlmRuntime } from "../stream-CREqxHgU.mjs";
3
+ import { a as modelsAreEqual, i as getSupportedThinkingLevels, n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "../model-utils-Cn9KAz3z.mjs";
4
+ import { n as onLlmRequestActivity, r as createDeferredEventBuffer, t as notifyLlmRequestActivity } from "../llm-request-activity-CehVkZP-.mjs";
5
+ import { t as headersToRecord } from "../headers-B_e4-1J0.mjs";
6
+ import { n as parseStreamingJson, r as repairJson, t as parseJsonWithRepair } from "../json-parse-DzNSIQBq.mjs";
3
7
  import { t as sanitizeSurrogates } from "../sanitize-unicode-DT5o51ur.mjs";
4
- import { c as calculateCost, d as modelsAreEqual, l as clampThinkingLevel, s as applyProviderReportedUsageCost, u as getSupportedThinkingLevels } from "../number-coercion-DvG7SNMg.mjs";
5
- import { t as createDeferredEventBuffer } from "../deferred-event-buffer-DAvyP7qA.mjs";
6
- import { n as parseStreamingJson, r as repairJson, t as parseJsonWithRepair } from "../json-parse-BvXNt1-7.mjs";
7
- import { n as onLlmRequestActivity, t as notifyLlmRequestActivity } from "../llm-request-activity-BjtkplhG.mjs";
8
- import { t as createReasoningTagTextPartitioner } from "../reasoning-tag-text-partitioner-CGDyLWUR.mjs";
9
- import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, n as createFirstStreamEventTimeoutError, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "../stream-first-event-timeout-BBys9hSb.mjs";
8
+ import { t as createReasoningTagTextPartitioner } from "../reasoning-tag-text-partitioner-axhAdUwg.mjs";
9
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, n as createFirstStreamEventTimeoutError, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "../stream-first-event-timeout-RjWszj8c.mjs";
10
10
  import { t as shortHash } from "../hash-CHgqbJmD.mjs";
11
- import { t as headersToRecord } from "../headers-B_e4-1J0.mjs";
12
11
  import { i as registerSessionResourceCleanup, n as resolveOpenAICodexAccountId, r as cleanupSessionResources, t as decodeOpenAICodexJwtPayload } from "../openai-chatgpt-jwt-DhAAzLkj.mjs";
13
12
  import { t as createSseByteGuard } from "../streaming-byte-guard-BrbkbwUu.mjs";
14
13
  //#region packages/ai/src/internal/default-runtime.ts
@@ -27,10 +26,7 @@ function resolveDefaultRuntime() {
27
26
  const defaultRuntime = resolveDefaultRuntime();
28
27
  const defaultApiRegistry = defaultRuntime.registry;
29
28
  const defaultLlmRuntime = defaultRuntime.runtime;
30
- const { getApiProvider, getApiProviders } = defaultApiRegistry;
31
- function clearApiProviders() {
32
- defaultApiRegistry.clearApiProviders();
33
- }
29
+ const { registerApiProvider, getApiProvider, getApiProviders, unregisterApiProviders, clearApiProviders } = defaultApiRegistry;
34
30
  const { stream, complete, streamSimple, completeSimple } = defaultLlmRuntime;
35
31
  //#endregion
36
32
  //#region packages/ai/src/utils/overflow.ts
@@ -63,9 +59,7 @@ function isConfiguredContextSizeOverflowError(errorMessage) {
63
59
  * - Kimi For Coding: "Your request exceeded model token limit: X (requested: Y)"
64
60
  * - Cerebras: "400/413 status code (no body)"
65
61
  * - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
66
- * - z.ai: May return "tokens in request more than max tokens allowed" (code 1210),
67
- * "Prompt exceeds max length" (code 1261), or accept overflow silently; handled via the
68
- * error patterns or usage.input > contextWindow
62
+ * - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow
69
63
  * - Xiaomi MiMo: Truncates input to fill contextWindow exactly, then returns finish_reason "length"
70
64
  * with output=0 (no room left to generate). Detected via stopReason "length" + zero output +
71
65
  * input filling the context window.
@@ -76,20 +70,17 @@ const OVERFLOW_PATTERNS = [
76
70
  /request_too_large/i,
77
71
  /input is too long for requested model/i,
78
72
  /exceeds the context window/i,
79
- /exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i,
73
+ /exceeds (?:the )?(?:model'?s )?maximum context length of [\d,]+ tokens?/i,
80
74
  /input token count.*exceeds the maximum/i,
81
75
  /maximum prompt length is \d+/i,
82
76
  /reduce the length of the messages/i,
83
77
  /maximum context length is \d+ tokens/i,
84
- /exceeds (?:the )?maximum allowed input length of [\d,]+ tokens?/i,
85
78
  /input \(\d+ tokens\) is longer than the model'?s context length \(\d+ tokens\)/i,
86
79
  /exceeds the limit of \d+/i,
87
80
  /exceeds the available context size/i,
88
81
  /greater than the context length/i,
89
82
  /context window exceeds limit/i,
90
83
  /exceeded model token limit/i,
91
- /tokens? in request more than max tokens? allowed/i,
92
- /prompt exceeds max(?:imum)? length/i,
93
84
  /too large for model with \d+ maximum context length/i,
94
85
  CONFIGURED_CONTEXT_SIZE_OVERFLOW_RE,
95
86
  /model_context_window_exceeded/i,
@@ -116,7 +107,7 @@ const NON_OVERFLOW_PATTERNS = [
116
107
  function resolveContextInputTokens(message) {
117
108
  if (message.usage.contextUsage?.state === "available") return message.usage.contextUsage.promptTokens;
118
109
  if (message.usage.contextUsage?.state === "unavailable") return;
119
- return message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
110
+ return message.usage.input + message.usage.cacheRead;
120
111
  }
121
112
  /**
122
113
  * Check if an assistant message represents a context overflow error.
@@ -142,12 +133,10 @@ function resolveContextInputTokens(message) {
142
133
  * - llama.cpp: "exceeds the available context size"
143
134
  * - LM Studio: "greater than the context length"
144
135
  * - Kimi For Coding: "exceeded model token limit: X (requested: Y)"
145
- * - z.ai: "tokens in request more than max tokens allowed" or "Prompt exceeds max length"
146
136
  *
147
137
  * **Unreliable detection:**
148
138
  * - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),
149
- * sometimes returns rate limit errors instead of the explicit overflow error above. Pass
150
- * contextWindow param to detect silent overflow.
139
+ * sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.
151
140
  * - Xiaomi MiMo: Truncates input to fit contextWindow then returns stopReason "length" with
152
141
  * output=0. Pass contextWindow param to detect via the "filled context + zero output" signal.
153
142
  * - Ollama: May truncate input silently for some setups, but may also return explicit
@@ -171,8 +160,7 @@ function resolveContextInputTokens(message) {
171
160
  */
172
161
  function isContextOverflow(message, contextWindow) {
173
162
  if (message.stopReason === "error" && message.errorMessage) {
174
- const errorMessage = message.errorMessage;
175
- if (!NON_OVERFLOW_PATTERNS.some((p) => p.test(errorMessage)) && OVERFLOW_PATTERNS.some((p) => p.test(errorMessage))) return true;
163
+ if (!NON_OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage)) && OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage))) return true;
176
164
  }
177
165
  if (contextWindow && message.stopReason === "stop") {
178
166
  const inputTokens = resolveContextInputTokens(message);
@@ -185,4 +173,4 @@ function isContextOverflow(message, contextWindow) {
185
173
  return false;
186
174
  }
187
175
  //#endregion
188
- export { applyProviderReportedUsageCost, calculateCost, clampThinkingLevel, cleanupSessionResources, clearApiProviders, complete, completeSimple, createDeferredEventBuffer, createFirstStreamEventAbortController, createFirstStreamEventTimeoutError, createReasoningTagTextPartitioner, createSseByteGuard, decodeOpenAICodexJwtPayload, defaultApiRegistry, defaultLlmRuntime, findEnvKeys, getApiProvider, getApiProviders, getEnvApiKey, getFirstStreamEventTimeoutHandler, getFirstStreamEventTimeoutMs, getSupportedThinkingLevels, headersToRecord, isConfiguredContextSizeOverflowError, isContextOverflow, modelsAreEqual, notifyLlmRequestActivity, onLlmRequestActivity, parseJsonWithRepair, parseStreamingJson, registerSessionResourceCleanup, repairJson, resolveOpenAICodexAccountId, sanitizeSurrogates, shortHash, stream, streamSimple, withFirstStreamEventTimeout };
176
+ export { applyProviderReportedUsageCost, calculateCost, clampThinkingLevel, cleanupSessionResources, clearApiProviders, complete, completeSimple, createDeferredEventBuffer, createFirstStreamEventAbortController, createFirstStreamEventTimeoutError, createReasoningTagTextPartitioner, createSseByteGuard, decodeOpenAICodexJwtPayload, defaultApiRegistry, defaultLlmRuntime, findEnvKeys, getApiProvider, getApiProviders, getEnvApiKey, getFirstStreamEventTimeoutHandler, getFirstStreamEventTimeoutMs, getSupportedThinkingLevels, headersToRecord, isConfiguredContextSizeOverflowError, isContextOverflow, modelsAreEqual, notifyLlmRequestActivity, onLlmRequestActivity, parseJsonWithRepair, parseStreamingJson, registerApiProvider, registerSessionResourceCleanup, repairJson, resolveOpenAICodexAccountId, sanitizeSurrogates, shortHash, stream, streamSimple, unregisterApiProviders, withFirstStreamEventTimeout };
@@ -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-bzp5k29J.mjs";
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/transcript-transform.d.ts
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
- //#region packages/ai/src/utils/tls-certificate-errors.d.ts
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 };
@@ -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 { a as isImageWithMediaPayload, c as ensureSystemPromptCacheBoundary, d as stripSystemPromptCacheBoundary, f as normalizePromptCapabilityIds, i as hasMediaPayload, l as prependSystemPromptAdditionAfterCacheBoundary, m as sortPromptCacheToolsByName, n as extractToolResultBlockText, p as normalizeStructuredPromptSection, r as extractToolResultText, s as SYSTEM_PROMPT_CACHE_BOUNDARY, t as describeToolResultMediaPlaceholder, u as splitSystemPromptCacheBoundary } from "../tool-result-text-CTpIRbYd.mjs";
4
- import { i as clampReasoning, n as buildBaseOptions, r as clampMaxTokensToModel, t as adjustMaxTokensForThinking } from "../simple-options-9lhRrN73.mjs";
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-DoWx35pj.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.charAt(index);
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.charAt(index + 1);
62
- if (!nextChar) {
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
- return JSON.parse(repairJson(json));
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-DrgeBuva.mjs";
2
- import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
3
- import { i as transformMessages, n as getAiTransportHost } from "./host-Dog2WQiR.mjs";
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-Cn9KAz3z.mjs";
5
+ import { n as parseStreamingJson } from "./json-parse-DzNSIQBq.mjs";
4
6
  import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
5
- import { a as isImageWithMediaPayload, d as stripSystemPromptCacheBoundary, o as truncateUtf16Safe, r as extractToolResultText, t as describeToolResultMediaPlaceholder } from "./tool-result-text-CTpIRbYd.mjs";
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-DoWx35pj.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 headers = {
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 transportAbortError(options.signal);
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, "").padEnd(MISTRAL_TOOL_CALL_ID_LENGTH, "0").slice(0, MISTRAL_TOOL_CALL_ID_LENGTH);
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
- const truncated = truncateUtf16Safe(text, maxChars);
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 toolBlockIdentities = /* @__PURE__ */ new Map();
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
- const promptTokens = chunk.usage.promptTokens || 0;
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 = cachedPromptTokens;
256
+ output.usage.cacheRead = 0;
334
257
  output.usage.cacheWrite = 0;
335
- output.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output + output.usage.cacheRead;
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 toolCallIndex = typeof toolCall.index === "number" && Number.isInteger(toolCall.index) ? toolCall.index : void 0;
427
- const providedCallId = toolCall.id && toolCall.id !== "null" ? toolCall.id : void 0;
428
- const functionName = toolCall.function.name.trim() || void 0;
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: providedCallId ?? createMissingToolCallId(contentIndex),
445
- name: functionName ?? "",
359
+ id: callId,
360
+ name: toolCall.function.name,
446
361
  arguments: {},
447
362
  partialArgs: ""
448
363
  };
449
364
  output.content.push(block);
450
- toolBlockIdentities.set(contentIndex, {
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 toolBlockIdentities.keys()) {
488
- const block = output.content.at(index);
489
- if (block?.type !== "toolCall") continue;
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(isImageWithMediaPayload), supportsImages, msg.isError);
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 (!isImageWithMediaPayload(part)) continue;
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 { a as requiresClaudeMandatoryAdaptiveThinking, l as resolveClaudeNativeThinkingLevelMap } from "./src-CjOfhrH3.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 };