@openclaw/ai 2026.7.2-beta.3 → 2026.7.2-beta.4

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 (45) hide show
  1. package/README.md +6 -5
  2. package/dist/{anthropic-D7SyZQ5v.mjs → anthropic-CrUDIBpM.mjs} +123 -16
  3. package/dist/{api-registry-DXBIXISf.d.mts → api-registry-BMphkFf1.d.mts} +1 -2
  4. package/dist/{azure-openai-responses-BkZgyZ3I.mjs → azure-openai-responses-CbrpVeEv.mjs} +7 -10
  5. package/dist/{env-api-keys-DnhYpc27.mjs → env-api-keys-DrgeBuva.mjs} +1 -1
  6. package/dist/{event-stream-BPemFrFW.d.mts → event-stream-Douf9dob.d.mts} +1 -1
  7. package/dist/event-stream.d.mts +1 -1
  8. package/dist/{google-C_biGbV7.mjs → google-Cs62KA7t.mjs} +4 -4
  9. package/dist/{google-shared-BK-NoHl8.mjs → google-shared-CMLI-tCZ.mjs} +3 -3
  10. package/dist/{google-vertex-CvdzF1U7.mjs → google-vertex-B4SD3U0f.mjs} +3 -3
  11. package/dist/host-WvWBo4h8.d.mts +173 -0
  12. package/dist/host-XYGZcgO8.mjs +98 -0
  13. package/dist/index-BVVgDSdq.d.mts +1 -0
  14. package/dist/index.d.mts +7 -50
  15. package/dist/index.mjs +1 -1
  16. package/dist/internal/anthropic.d.mts +2 -2
  17. package/dist/internal/anthropic.mjs +2 -2
  18. package/dist/internal/openai.d.mts +2 -280
  19. package/dist/internal/openai.mjs +5 -5
  20. package/dist/internal/runtime.d.mts +8 -5
  21. package/dist/internal/runtime.mjs +19 -10
  22. package/dist/internal/shared.d.mts +1 -1
  23. package/dist/internal/shared.mjs +1 -1
  24. package/dist/{mistral-BdrQmDWp.mjs → mistral-D5Ps7Led.mjs} +4 -4
  25. package/dist/openai-CoGicoDt.d.mts +332 -0
  26. package/dist/{openai-chatgpt-responses-DP63Qt01.mjs → openai-chatgpt-responses-h0o5yV8Y.mjs} +40 -43
  27. package/dist/{openai-completions-zLDfebnN.mjs → openai-completions-exO8NFQf.mjs} +316 -100
  28. package/dist/{openai-responses-ClspWt4I.mjs → openai-responses-BHpmtUKo.mjs} +5 -5
  29. package/dist/{openai-responses-shared-CwnGU0KW.mjs → openai-responses-shared-CzCurmY1.mjs} +230 -71
  30. package/dist/{openai-tool-projection-WHf2nuOI.mjs → openai-tool-projection-ITOU9bG1.mjs} +1 -1
  31. package/dist/{provider-error-LMfTEkfO.mjs → provider-error-C4VvV_3t.mjs} +2 -1
  32. package/dist/providers.d.mts +1 -1
  33. package/dist/providers.mjs +8 -8
  34. package/dist/{stream-first-event-timeout-RjWszj8c.mjs → stream-first-event-timeout-DP4xEyBY.mjs} +45 -1
  35. package/dist/{transform-messages-eb6lxDLB.mjs → system-prompt-cache-boundary-CbHeV4_l.mjs} +164 -160
  36. package/dist/transports.d.mts +590 -0
  37. package/dist/transports.mjs +5701 -0
  38. package/dist/{types-CYORveZ7.d.mts → types-AFwwWium.d.mts} +1 -0
  39. package/dist/types.d.mts +4 -4
  40. package/dist/{validation-BX8euiDv.d.mts → validation-sxvxC8J-.d.mts} +1 -1
  41. package/dist/validation.d.mts +1 -1
  42. package/npm-shrinkwrap.json +43 -50
  43. package/package.json +36 -10
  44. package/dist/host-4t713IeR.mjs +0 -37
  45. /package/dist/{index-BoTnz8cv.d.mts → anthropic-BoTnz8cv.d.mts} +0 -0
@@ -1,164 +1,6 @@
1
1
  import { a as resolveClaudeFable5ModelIdentity, i as requiresClaudeMandatoryAdaptiveThinking, l as resolveClaudeSonnet5ModelIdentity, r as requiresClaudeDefaultSampling, s as resolveClaudeMythos5ModelIdentity } from "./src-CXno1H5g.mjs";
2
- import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
2
+ import { n as getAiTransportHost } from "./host-XYGZcgO8.mjs";
3
3
  import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
4
- //#region packages/normalization-core/src/string-coerce.ts
5
- /** Trims string input and returns null for non-strings or empty strings. */
6
- function normalizeNullableString(value) {
7
- if (typeof value !== "string") return null;
8
- const trimmed = value.trim();
9
- return trimmed ? trimmed : null;
10
- }
11
- /** Trims string input and returns undefined for non-strings or empty strings. */
12
- function normalizeOptionalString(value) {
13
- return normalizeNullableString(value) ?? void 0;
14
- }
15
- /** Lowercases a normalized optional string. */
16
- function normalizeOptionalLowercaseString(value) {
17
- return normalizeOptionalString(value)?.toLowerCase();
18
- }
19
- /** Lowercases a normalized string or returns an empty string when absent. */
20
- function normalizeLowercaseStringOrEmpty(value) {
21
- return normalizeOptionalLowercaseString(value) ?? "";
22
- }
23
- //#endregion
24
- //#region packages/ai/src/utils/prompt-cache-stability.ts
25
- /**
26
- * Prompt-cache normalization helpers. They keep generated prompt sections
27
- * deterministic across platform newlines, trailing whitespace, and input
28
- * ordering.
29
- */
30
- /** Normalize structured prompt text before hashing or snapshot comparison. */
31
- function normalizeStructuredPromptSection(text) {
32
- return sanitizeSurrogates(text).replace(/\r\n?/g, "\n").replace(/[ \t]+$/gm, "").trim();
33
- }
34
- /** Normalize, de-dupe, and sort capability ids for stable prompt payloads. */
35
- function normalizePromptCapabilityIds(capabilities) {
36
- const seen = /* @__PURE__ */ new Set();
37
- const normalized = [];
38
- for (const capability of capabilities) {
39
- const value = normalizeLowercaseStringOrEmpty(normalizeStructuredPromptSection(capability));
40
- if (!value || seen.has(value)) continue;
41
- seen.add(value);
42
- normalized.push(value);
43
- }
44
- return normalized.toSorted((left, right) => left.localeCompare(right));
45
- }
46
- //#endregion
47
- //#region packages/ai/src/utils/system-prompt-cache-boundary.ts
48
- /**
49
- * System prompt cache-boundary helpers.
50
- *
51
- * Keeps stable prompt prefixes separate from dynamic runtime additions for provider prompt caching.
52
- */
53
- const SYSTEM_PROMPT_CACHE_BOUNDARY = "\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n";
54
- function stripSystemPromptCacheBoundary(text) {
55
- return text.replaceAll(SYSTEM_PROMPT_CACHE_BOUNDARY, "\n");
56
- }
57
- function ensureSystemPromptCacheBoundary(systemPrompt) {
58
- if (systemPrompt.trim().length === 0) return systemPrompt;
59
- return systemPrompt.includes("\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n") ? systemPrompt : `${systemPrompt}${SYSTEM_PROMPT_CACHE_BOUNDARY}`;
60
- }
61
- function splitSystemPromptCacheBoundary(text) {
62
- const boundaryIndex = text.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
63
- if (boundaryIndex === -1) return;
64
- return {
65
- stablePrefix: text.slice(0, boundaryIndex).trimEnd(),
66
- dynamicSuffix: text.slice(boundaryIndex + 34).trimStart()
67
- };
68
- }
69
- function prependSystemPromptAdditionAfterCacheBoundary(params) {
70
- const systemPromptAddition = typeof params.systemPromptAddition === "string" ? normalizeStructuredPromptSection(params.systemPromptAddition) : "";
71
- if (!systemPromptAddition) return params.systemPrompt;
72
- if (params.systemPrompt.trim().length === 0) return systemPromptAddition;
73
- const split = splitSystemPromptCacheBoundary(params.systemPrompt);
74
- if (!split) return `${systemPromptAddition}\n\n${params.systemPrompt}`;
75
- const dynamicSuffix = split.dynamicSuffix ? normalizeStructuredPromptSection(split.dynamicSuffix) : "";
76
- if (!dynamicSuffix) return `${split.stablePrefix}${SYSTEM_PROMPT_CACHE_BOUNDARY}${systemPromptAddition}`;
77
- return `${split.stablePrefix}${SYSTEM_PROMPT_CACHE_BOUNDARY}${systemPromptAddition}\n\n${dynamicSuffix}`;
78
- }
79
- //#endregion
80
- //#region packages/ai/src/providers/anthropic-model-contract.ts
81
- function normalizeModelId(modelId) {
82
- const normalized = normalizeLowercaseStringOrEmpty(modelId);
83
- return (normalized.startsWith("anthropic/") ? normalized.slice(10) : normalized).replace(/[._\s]+/g, "-");
84
- }
85
- function normalizeApi(api) {
86
- const normalized = normalizeLowercaseStringOrEmpty(api);
87
- return normalized === "openclaw-anthropic-messages-transport" ? "anthropic-messages" : normalized;
88
- }
89
- function hasConcreteResponseModel(ref) {
90
- const responseModelId = normalizeModelId(ref.responseModelId);
91
- return responseModelId.length > 0 && responseModelId !== normalizeModelId(ref.modelId);
92
- }
93
- function usesClaudeFable5MessagesContract(model) {
94
- return normalizeApi(model.api) === "anthropic-messages" && resolveClaudeFable5ModelIdentity(model) !== void 0;
95
- }
96
- /** Return whether streamed output must wait for the terminal refusal decision. */
97
- function usesClaudeStreamingRefusalContract(model) {
98
- if (normalizeApi(model.api) !== "anthropic-messages") return false;
99
- return resolveClaudeFable5ModelIdentity(model) !== void 0 || resolveClaudeMythos5ModelIdentity(model) !== void 0 || resolveClaudeSonnet5ModelIdentity(model) !== void 0;
100
- }
101
- function requiresClaudeAdaptiveThinking(model) {
102
- if (normalizeApi(model.api) !== "anthropic-messages") return false;
103
- return requiresClaudeMandatoryAdaptiveThinking(model);
104
- }
105
- /** Return whether omitted thinking should default to adaptive/high. */
106
- function defaultsClaudeAdaptiveThinking(model) {
107
- return requiresClaudeAdaptiveThinking(model) || normalizeApi(model.api) === "anthropic-messages" && resolveClaudeSonnet5ModelIdentity(model) !== void 0;
108
- }
109
- /** Remove Sonnet 5 assistant prefills while preserving completed tool-use turns. */
110
- function prepareClaudeSonnet5RequestContext(model, context) {
111
- if (!resolveClaudeSonnet5ModelIdentity(model)) return context;
112
- let end = context.messages.length;
113
- while (end > 0) {
114
- const message = context.messages[end - 1];
115
- if (message?.role !== "assistant" || Array.isArray(message.content) && message.content.some((block) => block.type === "toolCall")) break;
116
- end -= 1;
117
- }
118
- return end === context.messages.length ? context : {
119
- ...context,
120
- messages: context.messages.slice(0, end)
121
- };
122
- }
123
- function applyClaudeRequestContract(params, model) {
124
- if (normalizeApi(model.api) !== "anthropic-messages") return;
125
- const sonnet5 = resolveClaudeSonnet5ModelIdentity(model) !== void 0;
126
- if (!requiresClaudeDefaultSampling(model) && !sonnet5) return;
127
- delete params.temperature;
128
- delete params.top_p;
129
- delete params.top_k;
130
- if (sonnet5) delete params.service_tier;
131
- }
132
- function resolveReplayModelBoundIdentity(ref) {
133
- if (normalizeApi(ref.api) !== "anthropic-messages") return;
134
- const modelRef = hasConcreteResponseModel(ref) ? { id: ref.responseModelId } : {
135
- id: ref.modelId,
136
- params: ref.modelParams
137
- };
138
- const fableIdentity = resolveClaudeFable5ModelIdentity(modelRef);
139
- if (fableIdentity) return `fable:${fableIdentity}`;
140
- const mythosIdentity = resolveClaudeMythos5ModelIdentity(modelRef);
141
- if (mythosIdentity) return `mythos:${mythosIdentity}`;
142
- const sonnetIdentity = resolveClaudeSonnet5ModelIdentity(modelRef);
143
- return sonnetIdentity ? `sonnet:${sonnetIdentity}` : void 0;
144
- }
145
- function resolveModelBoundThinkingReplayMode(params) {
146
- const sourceApi = normalizeApi(params.source.api);
147
- const targetApi = normalizeApi(params.target.api);
148
- const sourceIdentity = resolveReplayModelBoundIdentity(params.source);
149
- const targetIdentity = resolveReplayModelBoundIdentity(params.target);
150
- const sameRoute = normalizeLowercaseStringOrEmpty(params.source.provider) === normalizeLowercaseStringOrEmpty(params.target.provider) && sourceApi === targetApi && normalizeModelId(params.source.modelId) === normalizeModelId(params.target.modelId);
151
- if (!sourceIdentity && !targetIdentity) return "default";
152
- if (!sourceIdentity && !hasConcreteResponseModel(params.source) && targetIdentity && sameRoute) return "preserve";
153
- return sourceApi === targetApi && sourceIdentity === targetIdentity ? "preserve" : "drop";
154
- }
155
- //#endregion
156
- //#region packages/normalization-core/src/record-coerce.ts
157
- /** Type guard for non-array object records at browser-safe boundaries. */
158
- function isRecord(value) {
159
- return value !== null && typeof value === "object" && !Array.isArray(value);
160
- }
161
- //#endregion
162
4
  //#region packages/ai/src/providers/simple-options.ts
163
5
  function buildBaseOptions(model, options, apiKey) {
164
6
  const firstEventOptions = options;
@@ -208,6 +50,12 @@ function adjustMaxTokensForThinking(baseMaxTokens, modelMaxTokens, reasoningLeve
208
50
  };
209
51
  }
210
52
  //#endregion
53
+ //#region packages/normalization-core/src/record-coerce.ts
54
+ /** Type guard for non-array object records at browser-safe boundaries. */
55
+ function isRecord(value) {
56
+ return value !== null && typeof value === "object" && !Array.isArray(value);
57
+ }
58
+ //#endregion
211
59
  //#region packages/normalization-core/src/utf16-slice.ts
212
60
  function isHighSurrogate(codeUnit) {
213
61
  return codeUnit >= 55296 && codeUnit <= 56319;
@@ -365,6 +213,106 @@ function extractToolResultText(blocks) {
365
213
  return sanitizeSurrogates(truncateProviderToolText(structuredTexts.join("\n")));
366
214
  }
367
215
  //#endregion
216
+ //#region packages/normalization-core/src/string-coerce.ts
217
+ /** Reads a value only when it is already a string, preserving whitespace. */
218
+ function readStringValue(value) {
219
+ return typeof value === "string" ? value : void 0;
220
+ }
221
+ /** Trims string input and returns null for non-strings or empty strings. */
222
+ function normalizeNullableString(value) {
223
+ if (typeof value !== "string") return null;
224
+ const trimmed = value.trim();
225
+ return trimmed ? trimmed : null;
226
+ }
227
+ /** Trims string input and returns undefined for non-strings or empty strings. */
228
+ function normalizeOptionalString(value) {
229
+ return normalizeNullableString(value) ?? void 0;
230
+ }
231
+ /** Lowercases a normalized optional string. */
232
+ function normalizeOptionalLowercaseString(value) {
233
+ return normalizeOptionalString(value)?.toLowerCase();
234
+ }
235
+ /** Lowercases a normalized string or returns an empty string when absent. */
236
+ function normalizeLowercaseStringOrEmpty(value) {
237
+ return normalizeOptionalLowercaseString(value) ?? "";
238
+ }
239
+ //#endregion
240
+ //#region packages/ai/src/providers/anthropic-model-contract.ts
241
+ function normalizeModelId(modelId) {
242
+ const normalized = normalizeLowercaseStringOrEmpty(modelId);
243
+ return (normalized.startsWith("anthropic/") ? normalized.slice(10) : normalized).replace(/[._\s]+/g, "-");
244
+ }
245
+ function normalizeApi(api) {
246
+ const normalized = normalizeLowercaseStringOrEmpty(api);
247
+ return normalized === "openclaw-anthropic-messages-transport" ? "anthropic-messages" : normalized;
248
+ }
249
+ function hasConcreteResponseModel(ref) {
250
+ const responseModelId = normalizeModelId(ref.responseModelId);
251
+ return responseModelId.length > 0 && responseModelId !== normalizeModelId(ref.modelId);
252
+ }
253
+ function usesClaudeFable5MessagesContract(model) {
254
+ return normalizeApi(model.api) === "anthropic-messages" && resolveClaudeFable5ModelIdentity(model) !== void 0;
255
+ }
256
+ /** Return whether streamed output must wait for the terminal refusal decision. */
257
+ function usesClaudeStreamingRefusalContract(model) {
258
+ if (normalizeApi(model.api) !== "anthropic-messages") return false;
259
+ return resolveClaudeFable5ModelIdentity(model) !== void 0 || resolveClaudeMythos5ModelIdentity(model) !== void 0 || resolveClaudeSonnet5ModelIdentity(model) !== void 0;
260
+ }
261
+ function requiresClaudeAdaptiveThinking(model) {
262
+ if (normalizeApi(model.api) !== "anthropic-messages") return false;
263
+ return requiresClaudeMandatoryAdaptiveThinking(model);
264
+ }
265
+ /** Return whether omitted thinking should default to adaptive/high. */
266
+ function defaultsClaudeAdaptiveThinking(model) {
267
+ return requiresClaudeAdaptiveThinking(model) || normalizeApi(model.api) === "anthropic-messages" && resolveClaudeSonnet5ModelIdentity(model) !== void 0;
268
+ }
269
+ /** Remove Sonnet 5 assistant prefills while preserving completed tool-use turns. */
270
+ function prepareClaudeSonnet5RequestContext(model, context) {
271
+ if (!resolveClaudeSonnet5ModelIdentity(model)) return context;
272
+ let end = context.messages.length;
273
+ while (end > 0) {
274
+ const message = context.messages[end - 1];
275
+ if (message?.role !== "assistant" || Array.isArray(message.content) && message.content.some((block) => block.type === "toolCall")) break;
276
+ end -= 1;
277
+ }
278
+ return end === context.messages.length ? context : {
279
+ ...context,
280
+ messages: context.messages.slice(0, end)
281
+ };
282
+ }
283
+ function applyClaudeRequestContract(params, model) {
284
+ if (normalizeApi(model.api) !== "anthropic-messages") return;
285
+ const sonnet5 = resolveClaudeSonnet5ModelIdentity(model) !== void 0;
286
+ if (!requiresClaudeDefaultSampling(model) && !sonnet5) return;
287
+ delete params.temperature;
288
+ delete params.top_p;
289
+ delete params.top_k;
290
+ if (sonnet5) delete params.service_tier;
291
+ }
292
+ function resolveReplayModelBoundIdentity(ref) {
293
+ if (normalizeApi(ref.api) !== "anthropic-messages") return;
294
+ const modelRef = hasConcreteResponseModel(ref) ? { id: ref.responseModelId } : {
295
+ id: ref.modelId,
296
+ params: ref.modelParams
297
+ };
298
+ const fableIdentity = resolveClaudeFable5ModelIdentity(modelRef);
299
+ if (fableIdentity) return `fable:${fableIdentity}`;
300
+ const mythosIdentity = resolveClaudeMythos5ModelIdentity(modelRef);
301
+ if (mythosIdentity) return `mythos:${mythosIdentity}`;
302
+ const sonnetIdentity = resolveClaudeSonnet5ModelIdentity(modelRef);
303
+ return sonnetIdentity ? `sonnet:${sonnetIdentity}` : void 0;
304
+ }
305
+ function resolveModelBoundThinkingReplayMode(params) {
306
+ const sourceApi = normalizeApi(params.source.api);
307
+ const targetApi = normalizeApi(params.target.api);
308
+ const sourceIdentity = resolveReplayModelBoundIdentity(params.source);
309
+ const targetIdentity = resolveReplayModelBoundIdentity(params.target);
310
+ const sameRoute = normalizeLowercaseStringOrEmpty(params.source.provider) === normalizeLowercaseStringOrEmpty(params.target.provider) && sourceApi === targetApi && normalizeModelId(params.source.modelId) === normalizeModelId(params.target.modelId);
311
+ if (!sourceIdentity && !targetIdentity) return "default";
312
+ if (!sourceIdentity && !hasConcreteResponseModel(params.source) && targetIdentity && sameRoute) return "preserve";
313
+ return sourceApi === targetApi && sourceIdentity === targetIdentity ? "preserve" : "drop";
314
+ }
315
+ //#endregion
368
316
  //#region packages/ai/src/providers/transform-messages.ts
369
317
  const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
370
318
  const NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
@@ -519,4 +467,60 @@ function transformMessages(messages, model, normalizeToolCallId) {
519
467
  return result;
520
468
  }
521
469
  //#endregion
522
- export { splitSystemPromptCacheBoundary as C, normalizeLowercaseStringOrEmpty as D, normalizeStructuredPromptSection as E, normalizeOptionalString as O, prependSystemPromptAdditionAfterCacheBoundary as S, normalizePromptCapabilityIds as T, resolveModelBoundThinkingReplayMode as _, hasMediaPayload as a, SYSTEM_PROMPT_CACHE_BOUNDARY as b, adjustMaxTokensForThinking as c, clampReasoning as d, isRecord as f, requiresClaudeAdaptiveThinking as g, prepareClaudeSonnet5RequestContext as h, extractToolResultText as i, buildBaseOptions as l, defaultsClaudeAdaptiveThinking as m, describeToolResultMediaPlaceholder as n, isImageWithMediaPayload as o, applyClaudeRequestContract as p, extractToolResultBlockText as r, truncateUtf16Safe as s, transformMessages as t, clampMaxTokensToModel as u, usesClaudeFable5MessagesContract as v, stripSystemPromptCacheBoundary as w, ensureSystemPromptCacheBoundary as x, usesClaudeStreamingRefusalContract as y };
470
+ //#region packages/ai/src/utils/prompt-cache-stability.ts
471
+ /**
472
+ * Prompt-cache normalization helpers. They keep generated prompt sections
473
+ * deterministic across platform newlines, trailing whitespace, and input
474
+ * ordering.
475
+ */
476
+ /** Normalize structured prompt text before hashing or snapshot comparison. */
477
+ function normalizeStructuredPromptSection(text) {
478
+ return sanitizeSurrogates(text).replace(/\r\n?/g, "\n").replace(/[ \t]+$/gm, "").trim();
479
+ }
480
+ /** Normalize, de-dupe, and sort capability ids for stable prompt payloads. */
481
+ function normalizePromptCapabilityIds(capabilities) {
482
+ const seen = /* @__PURE__ */ new Set();
483
+ const normalized = [];
484
+ for (const capability of capabilities) {
485
+ const value = normalizeLowercaseStringOrEmpty(normalizeStructuredPromptSection(capability));
486
+ if (!value || seen.has(value)) continue;
487
+ seen.add(value);
488
+ normalized.push(value);
489
+ }
490
+ return normalized.toSorted((left, right) => left.localeCompare(right));
491
+ }
492
+ //#endregion
493
+ //#region packages/ai/src/utils/system-prompt-cache-boundary.ts
494
+ /**
495
+ * System prompt cache-boundary helpers.
496
+ *
497
+ * Keeps stable prompt prefixes separate from dynamic runtime additions for provider prompt caching.
498
+ */
499
+ const SYSTEM_PROMPT_CACHE_BOUNDARY = "\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n";
500
+ function stripSystemPromptCacheBoundary(text) {
501
+ return text.replaceAll(SYSTEM_PROMPT_CACHE_BOUNDARY, "\n");
502
+ }
503
+ function ensureSystemPromptCacheBoundary(systemPrompt) {
504
+ if (systemPrompt.trim().length === 0) return systemPrompt;
505
+ return systemPrompt.includes("\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n") ? systemPrompt : `${systemPrompt}${SYSTEM_PROMPT_CACHE_BOUNDARY}`;
506
+ }
507
+ function splitSystemPromptCacheBoundary(text) {
508
+ const boundaryIndex = text.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
509
+ if (boundaryIndex === -1) return;
510
+ return {
511
+ stablePrefix: text.slice(0, boundaryIndex).trimEnd(),
512
+ dynamicSuffix: text.slice(boundaryIndex + 34).trimStart()
513
+ };
514
+ }
515
+ function prependSystemPromptAdditionAfterCacheBoundary(params) {
516
+ const systemPromptAddition = typeof params.systemPromptAddition === "string" ? normalizeStructuredPromptSection(params.systemPromptAddition) : "";
517
+ if (!systemPromptAddition) return params.systemPrompt;
518
+ if (params.systemPrompt.trim().length === 0) return systemPromptAddition;
519
+ const split = splitSystemPromptCacheBoundary(params.systemPrompt);
520
+ if (!split) return `${systemPromptAddition}\n\n${params.systemPrompt}`;
521
+ const dynamicSuffix = split.dynamicSuffix ? normalizeStructuredPromptSection(split.dynamicSuffix) : "";
522
+ if (!dynamicSuffix) return `${split.stablePrefix}${SYSTEM_PROMPT_CACHE_BOUNDARY}${systemPromptAddition}`;
523
+ return `${split.stablePrefix}${SYSTEM_PROMPT_CACHE_BOUNDARY}${systemPromptAddition}\n\n${dynamicSuffix}`;
524
+ }
525
+ //#endregion
526
+ export { isImageWithMediaPayload as C, buildBaseOptions as D, adjustMaxTokensForThinking as E, clampMaxTokensToModel as O, hasMediaPayload as S, isRecord as T, normalizeOptionalString as _, stripSystemPromptCacheBoundary as a, extractToolResultBlockText as b, transformMessages as c, prepareClaudeSonnet5RequestContext as d, requiresClaudeAdaptiveThinking as f, normalizeLowercaseStringOrEmpty as g, usesClaudeStreamingRefusalContract as h, splitSystemPromptCacheBoundary as i, clampReasoning as k, applyClaudeRequestContract as l, usesClaudeFable5MessagesContract as m, ensureSystemPromptCacheBoundary as n, normalizePromptCapabilityIds as o, resolveModelBoundThinkingReplayMode as p, prependSystemPromptAdditionAfterCacheBoundary as r, normalizeStructuredPromptSection as s, SYSTEM_PROMPT_CACHE_BOUNDARY as t, defaultsClaudeAdaptiveThinking as u, readStringValue as v, truncateUtf16Safe as w, extractToolResultText as x, describeToolResultMediaPlaceholder as y };