@openclaw/ai 2026.8.1-beta.1 → 2026.8.1-beta.2

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 (86) hide show
  1. package/dist/{anthropic-CE-7SkF6.mjs → anthropic-B6dLpq5L.mjs} +37 -22
  2. package/dist/{src-QkygScBs.mjs → anthropic-JsNA5KCu.mjs} +0 -1
  3. package/dist/{anthropic-usage-Ma4iX6uG.mjs → anthropic-compaction-replay-8lJNKXOE.mjs} +225 -102
  4. package/dist/anthropic-payload-policy-CiEuQS72.d.mts +49 -0
  5. package/dist/{api-registry-EpJoVwM1.d.mts → api-registry-k3zTz0cV.d.mts} +1 -1
  6. package/dist/{azure-openai-responses-Cc_kasye.mjs → azure-openai-responses-mxIOtUnn.mjs} +23 -29
  7. package/dist/diagnostics.d.mts +24 -1
  8. package/dist/diagnostics.mjs +2 -1
  9. package/dist/{event-stream-DRmDMRHH.d.mts → event-stream-BP6AWT8j.d.mts} +3 -1
  10. package/dist/{event-stream-CEV9t6da.mjs → event-stream-uSMZJ3FA.mjs} +16 -3
  11. package/dist/event-stream.d.mts +1 -1
  12. package/dist/event-stream.mjs +1 -1
  13. package/dist/{google-CGQu21aw.mjs → google-C7h2QzDX.mjs} +4 -4
  14. package/dist/{google-shared-Cq2UKx1l.mjs → google-shared-B0Qr9OR7.mjs} +9 -18
  15. package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
  16. package/dist/{google-vertex-CusxWzvE.mjs → google-vertex-Bhc3TjDl.mjs} +5 -4
  17. package/dist/{llm-request-activity-BjtkplhG.mjs → headers-DdOQtGuU.mjs} +9 -1
  18. package/dist/{host-Bl7Kgddo.mjs → host-DTqNc7ad.mjs} +227 -168
  19. package/dist/{host-Dn4_SZI2.d.mts → host-vWgMMhiJ.d.mts} +9 -4
  20. package/dist/index.d.mts +6 -6
  21. package/dist/index.mjs +7 -5
  22. package/dist/internal/anthropic.d.mts +13 -5
  23. package/dist/internal/anthropic.mjs +5 -5
  24. package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
  25. package/dist/internal/openai-responses-payload-policy.mjs +3 -0
  26. package/dist/internal/openai.d.mts +6 -6
  27. package/dist/internal/openai.mjs +8 -7
  28. package/dist/internal/runtime.d.mts +17 -5
  29. package/dist/internal/runtime.mjs +85 -73
  30. package/dist/internal/shared.d.mts +1 -6
  31. package/dist/internal/shared.mjs +3 -4
  32. package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
  33. package/dist/{mistral-Dx6VzNjf.mjs → mistral-CEWoQI_g.mjs} +26 -45
  34. package/dist/{number-coercion-1Miyb5MO.mjs → number-coercion-H9qHik3g.mjs} +7 -2
  35. package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
  36. package/dist/{openai-chatgpt-responses-SC9m0FSf.mjs → openai-chatgpt-responses-CrPmqERt.mjs} +225 -144
  37. package/dist/{openai-completions-BaIpl93j.mjs → openai-completions-BPnt4Sml.mjs} +28 -43
  38. package/dist/openai-completions-compat-Dt3dcawL.d.mts +43 -0
  39. package/dist/{openai-responses-Bdx3V_Yu.mjs → openai-responses-DhIKtOup.mjs} +17 -24
  40. package/dist/openai-responses-contracts-CyfIkQi5.mjs +253 -0
  41. package/dist/openai-responses-contracts-XpZJxrRG.d.mts +68 -0
  42. package/dist/openai-responses-payload-policy-BDxV-W0c.mjs +206 -0
  43. package/dist/openai-responses-payload-policy-BSs371VM.d.mts +40 -0
  44. package/dist/{openai-responses-prompt-observer-internal-DDZPxRfr.mjs → openai-responses-prompt-observer-internal-DgNTYnRY.mjs} +3 -3
  45. package/dist/{openai-responses-stream-internal-Bl8YyVtF.mjs → openai-responses-shared-DXIt3iY5.mjs} +1211 -908
  46. package/dist/{openai-reasoning-compat-DKebnIBL.mjs → openai-stop-reason-BkFkqqK0.mjs} +198 -172
  47. package/dist/{openai-transport-shared-Cipt7egQ.mjs → openai-tool-projection-CY04OcvQ.mjs} +151 -128
  48. package/dist/provider-error-BUwEnjXq.mjs +429 -0
  49. package/dist/provider-error-CzNw4BWX.d.mts +12 -0
  50. package/dist/{provider-options-C5kYML7i.d.mts → provider-options-B96RdNpH.d.mts} +9 -3
  51. package/dist/provider-transcript-transform-ePx-Bbfr.mjs +155 -0
  52. package/dist/provider-types.d.mts +31 -0
  53. package/dist/provider-types.mjs +8 -0
  54. package/dist/providers.d.mts +1 -1
  55. package/dist/providers.mjs +17 -19
  56. package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-rnPwX2pg.mjs} +14 -8
  57. package/dist/record-coerce-DdXsgUd_.mjs +23 -0
  58. package/dist/{model-utils-Dau5dlgm.mjs → sanitize-unicode-BYqrYtC_.mjs} +28 -2
  59. package/dist/session-resources-CkR4WWy1.mjs +21 -0
  60. package/dist/simple-options-D58D5Kvw.mjs +117 -0
  61. package/dist/src-D2H6yKkH.mjs +2 -0
  62. package/dist/{stream-first-event-timeout-BIBomOGq.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
  63. package/dist/string-coerce-fsri9iCu.mjs +34 -0
  64. package/dist/{tool-schema-json-projection-B1b-XCn5.mjs → tool-schema-json-projection-q5d7QX5c.mjs} +5 -7
  65. package/dist/transport-utils-DJqkxbhC.mjs +138 -0
  66. package/dist/transports.d.mts +135 -178
  67. package/dist/transports.mjs +1732 -1294
  68. package/dist/types-BDdaOVi2.mjs +6 -0
  69. package/dist/{types-CH7ReIcU.d.mts → types-BHNrPS1l.d.mts} +19 -1
  70. package/dist/types.d.mts +4 -4
  71. package/dist/types.mjs +6 -4
  72. package/dist/utf16-slice-CvGodqok.mjs +29 -0
  73. package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
  74. package/dist/{validation-CcPcuEbR.d.mts → validation-DT9SrFn3.d.mts} +1 -1
  75. package/dist/validation.d.mts +1 -1
  76. package/dist/validation.mjs +1 -1
  77. package/package.json +15 -1
  78. package/dist/headers-B_e4-1J0.mjs +0 -9
  79. package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
  80. package/dist/openai-responses-contracts-BBKBfAqR.d.mts +0 -116
  81. package/dist/openai-responses-shared-CCyMvg7M.mjs +0 -403
  82. package/dist/provider-error-DI0Ts28U.mjs +0 -47
  83. package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
  84. package/dist/tool-result-text-Dvkp2Dus.mjs +0 -274
  85. package/dist/transform-messages-DfjpNXNQ.mjs +0 -2
  86. package/dist/transport-stream-shared-CPNv7A3r.mjs +0 -297
@@ -0,0 +1,8 @@
1
+ //#region packages/ai/src/provider-types.ts
2
+ const PROVIDER_CONTEXT_HANDOFF = Symbol("providerContextHandoff");
3
+ /** Resolves provider-only context without widening the canonical call contract. */
4
+ async function resolveProviderContext(context, options) {
5
+ return options?.[PROVIDER_CONTEXT_HANDOFF]?.() ?? context;
6
+ }
7
+ //#endregion
8
+ export { PROVIDER_CONTEXT_HANDOFF, resolveProviderContext };
@@ -1,4 +1,4 @@
1
- import { n as ApiRegistry } from "./api-registry-EpJoVwM1.mjs";
1
+ import { n as ApiRegistry } from "./api-registry-k3zTz0cV.mjs";
2
2
  import { n as clampOpenAIPromptCacheKey, t as OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH } from "./openai-prompt-cache-2uo_1OR1.mjs";
3
3
 
4
4
  //#region packages/ai/src/providers/register-builtins.d.ts
@@ -1,15 +1,14 @@
1
- import { t as AssistantMessageEventStream } from "./event-stream-CEV9t6da.mjs";
1
+ import { t as AssistantMessageEventStream } from "./event-stream-uSMZJ3FA.mjs";
2
+ import { n as projectProviderError } from "./provider-error-BUwEnjXq.mjs";
2
3
  import { n as clampOpenAIPromptCacheKey, t as OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH } from "./openai-prompt-cache-mZTCdRPo.mjs";
3
4
  //#region packages/ai/src/providers/register-builtins.ts
4
5
  /** Source id used for built-in API provider registrations. */
5
6
  const BUILT_IN_API_PROVIDER_SOURCE_ID = "core:built-in";
6
- function forwardStream(target, source) {
7
- (async () => {
8
- for await (const event of source) target.push(event);
9
- target.end();
10
- })();
7
+ async function forwardStream(target, source) {
8
+ for await (const event of source) target.push(event);
9
+ target.end();
11
10
  }
12
- function createLazyLoadErrorMessage(model, error) {
11
+ function createLazyLoadErrorMessage(model, error, signal) {
13
12
  return {
14
13
  role: "assistant",
15
14
  content: [],
@@ -30,8 +29,7 @@ function createLazyLoadErrorMessage(model, error) {
30
29
  total: 0
31
30
  }
32
31
  },
33
- stopReason: "error",
34
- errorMessage: error instanceof Error ? error.message : String(error),
32
+ ...projectProviderError(error, signal),
35
33
  timestamp: Date.now()
36
34
  };
37
35
  }
@@ -39,10 +37,10 @@ function createLazyStream(load, select) {
39
37
  return (model, context, options) => {
40
38
  const outer = new AssistantMessageEventStream();
41
39
  load().then((streams) => forwardStream(outer, select(streams)(model, context, options))).catch((error) => {
42
- const message = createLazyLoadErrorMessage(model, error);
40
+ const message = createLazyLoadErrorMessage(model, error, options?.signal);
43
41
  outer.push({
44
42
  type: "error",
45
- reason: "error",
43
+ reason: message.stopReason,
46
44
  error: message
47
45
  });
48
46
  outer.end(message);
@@ -64,35 +62,35 @@ function createLazyRegistration(api, importModule, select) {
64
62
  };
65
63
  }
66
64
  const registerBuiltIns = [
67
- createLazyRegistration("anthropic-messages", () => import("./anthropic-CE-7SkF6.mjs").then((n) => n.t), (module) => ({
65
+ createLazyRegistration("anthropic-messages", () => import("./anthropic-B6dLpq5L.mjs").then((n) => n.t), (module) => ({
68
66
  stream: module.streamAnthropic,
69
67
  streamSimple: module.streamSimpleAnthropic
70
68
  })),
71
- createLazyRegistration("openai-completions", () => import("./openai-completions-BaIpl93j.mjs").then((n) => n.t), (module) => ({
69
+ createLazyRegistration("openai-completions", () => import("./openai-completions-BPnt4Sml.mjs").then((n) => n.t), (module) => ({
72
70
  stream: module.streamOpenAICompletions,
73
71
  streamSimple: module.streamSimpleOpenAICompletions
74
72
  })),
75
- createLazyRegistration("mistral-conversations", () => import("./mistral-Dx6VzNjf.mjs"), (module) => ({
73
+ createLazyRegistration("mistral-conversations", () => import("./mistral-CEWoQI_g.mjs"), (module) => ({
76
74
  stream: module.streamMistral,
77
75
  streamSimple: module.streamSimpleMistral
78
76
  })),
79
- createLazyRegistration("openai-responses", () => import("./openai-responses-Bdx3V_Yu.mjs").then((n) => n.t), (module) => ({
77
+ createLazyRegistration("openai-responses", () => import("./openai-responses-DhIKtOup.mjs").then((n) => n.t), (module) => ({
80
78
  stream: module.streamOpenAIResponses,
81
79
  streamSimple: module.streamSimpleOpenAIResponses
82
80
  })),
83
- createLazyRegistration("azure-openai-responses", () => import("./azure-openai-responses-Cc_kasye.mjs"), (module) => ({
81
+ createLazyRegistration("azure-openai-responses", () => import("./azure-openai-responses-mxIOtUnn.mjs"), (module) => ({
84
82
  stream: module.streamAzureOpenAIResponses,
85
83
  streamSimple: module.streamSimpleAzureOpenAIResponses
86
84
  })),
87
- createLazyRegistration("openai-chatgpt-responses", () => import("./openai-chatgpt-responses-SC9m0FSf.mjs"), (module) => ({
85
+ createLazyRegistration("openai-chatgpt-responses", () => import("./openai-chatgpt-responses-CrPmqERt.mjs"), (module) => ({
88
86
  stream: module.streamOpenAICodexResponses,
89
87
  streamSimple: module.streamSimpleOpenAICodexResponses
90
88
  })),
91
- createLazyRegistration("google-generative-ai", () => import("./google-CGQu21aw.mjs"), (module) => ({
89
+ createLazyRegistration("google-generative-ai", () => import("./google-C7h2QzDX.mjs"), (module) => ({
92
90
  stream: module.streamGoogle,
93
91
  streamSimple: module.streamSimpleGoogle
94
92
  })),
95
- createLazyRegistration("google-vertex", () => import("./google-vertex-CusxWzvE.mjs"), (module) => ({
93
+ createLazyRegistration("google-vertex", () => import("./google-vertex-Bhc3TjDl.mjs"), (module) => ({
96
94
  stream: module.streamGoogleVertex,
97
95
  streamSimple: module.streamSimpleGoogleVertex
98
96
  }))
@@ -11573,6 +11573,7 @@ const REASONING_TAG_NAMES = [
11573
11573
  "thinking",
11574
11574
  "thought",
11575
11575
  "reasoning",
11576
+ "internal",
11576
11577
  "antthinking",
11577
11578
  "antml:think",
11578
11579
  "antml:thinking",
@@ -11645,7 +11646,8 @@ function parseReasoningTagAt(text, start, final) {
11645
11646
  index: start,
11646
11647
  text: text.slice(start, end),
11647
11648
  isClose,
11648
- isSelfClosing: !isClose && lastSignificant === "/"
11649
+ isSelfClosing: !isClose && lastSignificant === "/",
11650
+ isPrivate: partialName === "internal"
11649
11651
  }
11650
11652
  };
11651
11653
  }
@@ -11748,16 +11750,18 @@ function reduceReasoningText(text, codeSpans, state, options) {
11748
11750
  index: scannedTag.index + start,
11749
11751
  isClose: scannedTag.isClose,
11750
11752
  isSelfClosing: scannedTag.isSelfClosing,
11753
+ isPrivate: scannedTag.isPrivate,
11751
11754
  text: scannedTag.text
11752
11755
  };
11753
11756
  if (!isInsideCode(tag.index, codeSpans)) tags.push(tag);
11754
11757
  }
11755
- const hasCloseAfter = [];
11758
+ const mustParseRemainder = [];
11756
11759
  if (options.scope === "leading") {
11757
- let seenClose = false;
11760
+ let mustParse = false;
11758
11761
  for (let index = tags.length - 1; index >= 0; index -= 1) {
11759
- hasCloseAfter[index] = seenClose;
11760
- seenClose ||= tags[index]?.isClose === true;
11762
+ mustParse ||= tags[index]?.isPrivate === true;
11763
+ mustParseRemainder[index] = mustParse;
11764
+ mustParse ||= tags[index]?.isClose === true;
11761
11765
  }
11762
11766
  }
11763
11767
  let cursor = start;
@@ -11777,17 +11781,19 @@ function reduceReasoningText(text, codeSpans, state, options) {
11777
11781
  continue;
11778
11782
  }
11779
11783
  if (!tag.isClose) {
11780
- if (state.depth === 0 && options.scope === "leading" && state.visibleEver && !hasCloseAfter[tagIndex]) {
11784
+ if (state.depth === 0 && options.scope === "leading" && state.visibleEver && !mustParseRemainder[tagIndex]) {
11781
11785
  emit("text", text.slice(tag.index));
11782
11786
  cursor = text.length;
11783
11787
  break;
11784
11788
  }
11785
11789
  if (state.depth === 0) state.pending = {
11786
11790
  content: "",
11791
+ containsPrivate: tag.isPrivate,
11787
11792
  openTag: tag.text,
11788
11793
  protectedClose: false,
11789
11794
  visibleBefore: state.visibleEver
11790
11795
  };
11796
+ else if (state.pending) state.pending.containsPrivate ||= tag.isPrivate;
11791
11797
  state.depth += 1;
11792
11798
  cursor = tagEnd;
11793
11799
  continue;
@@ -11795,7 +11801,7 @@ function reduceReasoningText(text, codeSpans, state, options) {
11795
11801
  if (state.depth > 0) {
11796
11802
  state.depth -= 1;
11797
11803
  if (state.depth === 0 && state.pending) {
11798
- emit("thinking", state.pending.content);
11804
+ if (!state.pending.containsPrivate) emit("thinking", state.pending.content);
11799
11805
  state.pending = void 0;
11800
11806
  } else if (state.pending) state.pending.protectedClose = true;
11801
11807
  cursor = tagEnd;
@@ -11815,7 +11821,7 @@ function reduceReasoningText(text, codeSpans, state, options) {
11815
11821
  append(text.slice(cursor));
11816
11822
  if (options.final && state.depth > 0 && state.pending) {
11817
11823
  const pending = state.pending;
11818
- if (options.mode === "static-preserve" || options.mode === "static-strict" && !pending.visibleBefore && !pending.protectedClose || options.mode === "visible" && !pending.protectedClose) emit("text", options.mode === "visible" && pending.visibleBefore ? pending.openTag + pending.content : pending.content);
11824
+ if (!pending.containsPrivate) if (options.mode === "static-preserve" || options.mode === "static-strict" && !pending.visibleBefore && !pending.protectedClose || options.mode === "visible" && !pending.protectedClose) emit("text", options.mode === "visible" && pending.visibleBefore ? pending.openTag + pending.content : pending.content);
11819
11825
  else emit("thinking", pending.content);
11820
11826
  state.depth = 0;
11821
11827
  state.pending = void 0;
@@ -0,0 +1,23 @@
1
+ //#region packages/normalization-core/src/record-coerce.ts
2
+ /** Type guard for non-array object records at browser-safe boundaries. */
3
+ function isRecord(value) {
4
+ return value !== null && typeof value === "object" && !Array.isArray(value);
5
+ }
6
+ /** Returns a non-array record or undefined. */
7
+ function asOptionalRecord(value) {
8
+ return isRecord(value) ? value : void 0;
9
+ }
10
+ /** Returns a non-array record or a fresh ordinary empty record. */
11
+ function asNonArrayRecord(value) {
12
+ return asOptionalRecord(value) ?? {};
13
+ }
14
+ /** Returns a non-array record or null. */
15
+ function asNullableRecord(value) {
16
+ return isRecord(value) ? value : null;
17
+ }
18
+ /** Returns any object-backed record, including arrays, or undefined. */
19
+ function asOptionalObjectRecord(value) {
20
+ return value && typeof value === "object" ? value : void 0;
21
+ }
22
+ //#endregion
23
+ export { isRecord as a, asOptionalRecord as i, asNullableRecord as n, asOptionalObjectRecord as r, asNonArrayRecord as t };
@@ -1,4 +1,5 @@
1
- import { a as requiresClaudeMandatoryAdaptiveThinking, l as resolveClaudeNativeThinkingLevelMap } from "./src-QkygScBs.mjs";
1
+ import { a as requiresClaudeMandatoryAdaptiveThinking, l as resolveClaudeNativeThinkingLevelMap } from "./anthropic-JsNA5KCu.mjs";
2
+ import "./src-D2H6yKkH.mjs";
2
3
  //#region packages/ai/src/model-utils.ts
3
4
  /** Calculates and stores model cost fields from token usage and per-million pricing. */
4
5
  function calculateCost(model, usage) {
@@ -61,4 +62,29 @@ function modelsAreEqual(a, b) {
61
62
  return a.id === b.id && a.provider === b.provider;
62
63
  }
63
64
  //#endregion
64
- export { modelsAreEqual as a, getSupportedThinkingLevels as i, calculateCost as n, clampThinkingLevel as r, applyProviderReportedUsageCost as t };
65
+ //#region packages/ai/src/utils/sanitize-unicode.ts
66
+ /**
67
+ * Removes unpaired Unicode surrogate characters from a string.
68
+ *
69
+ * Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,
70
+ * or vice versa) cause JSON serialization errors in many API providers.
71
+ *
72
+ * Valid emoji and other characters outside the Basic Multilingual Plane use properly paired
73
+ * surrogates and will NOT be affected by this function.
74
+ *
75
+ * @param text - The text to sanitize
76
+ * @returns The sanitized text with unpaired surrogates removed
77
+ *
78
+ * @example
79
+ * // Valid emoji (properly paired surrogates) are preserved
80
+ * sanitizeSurrogates("Hello 🙈 World") // => "Hello 🙈 World"
81
+ *
82
+ * // Unpaired high surrogate is removed
83
+ * const unpaired = String.fromCharCode(0xD83D); // high surrogate without low
84
+ * sanitizeSurrogates(`Text ${unpaired} here`) // => "Text here"
85
+ */
86
+ function sanitizeSurrogates(text) {
87
+ return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
88
+ }
89
+ //#endregion
90
+ export { getSupportedThinkingLevels as a, clampThinkingLevel as i, applyProviderReportedUsageCost as n, modelsAreEqual as o, calculateCost as r, sanitizeSurrogates as t };
@@ -0,0 +1,21 @@
1
+ //#region packages/ai/src/session-resources.ts
2
+ const sessionResourceCleanups = /* @__PURE__ */ new Set();
3
+ /** Registers a session-resource cleanup hook and returns an unregister function. */
4
+ function registerSessionResourceCleanup(cleanup) {
5
+ sessionResourceCleanups.add(cleanup);
6
+ return () => {
7
+ sessionResourceCleanups.delete(cleanup);
8
+ };
9
+ }
10
+ /** Runs all registered cleanup hooks, aggregating failures after every hook has run. */
11
+ function cleanupSessionResources(sessionId) {
12
+ const errors = [];
13
+ for (const cleanup of sessionResourceCleanups) try {
14
+ cleanup(sessionId);
15
+ } catch (error) {
16
+ errors.push(error);
17
+ }
18
+ if (errors.length > 0) throw new AggregateError(errors, "Failed to cleanup session resources");
19
+ }
20
+ //#endregion
21
+ export { registerSessionResourceCleanup as n, cleanupSessionResources as t };
@@ -0,0 +1,117 @@
1
+ import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
2
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-BYqrYtC_.mjs";
3
+ //#region packages/ai/src/utils/prompt-cache-stability.ts
4
+ /**
5
+ * Prompt-cache normalization helpers. They keep generated prompt sections
6
+ * deterministic across platform newlines, trailing whitespace, and input
7
+ * ordering.
8
+ */
9
+ /** Canonicalizes provider tool order without relying on host locale settings. */
10
+ function sortPromptCacheToolsByName(tools) {
11
+ const compareText = (left, right) => {
12
+ const leftText = left ?? "";
13
+ const rightText = right ?? "";
14
+ return leftText < rightText ? -1 : leftText > rightText ? 1 : 0;
15
+ };
16
+ return tools.toSorted((left, right) => compareText(left.wireName ?? left.name, right.wireName ?? right.name) || compareText(left.description, right.description));
17
+ }
18
+ /** Normalize structured prompt text before hashing or snapshot comparison. */
19
+ function normalizeStructuredPromptSection(text) {
20
+ return sanitizeSurrogates(text).replace(/\r\n?/g, "\n").replace(/[ \t]+$/gm, "").trim();
21
+ }
22
+ /** Normalize, de-dupe, and sort capability ids for stable prompt payloads. */
23
+ function normalizePromptCapabilityIds(capabilities) {
24
+ const seen = /* @__PURE__ */ new Set();
25
+ const normalized = [];
26
+ for (const capability of capabilities) {
27
+ const value = normalizeLowercaseStringOrEmpty(normalizeStructuredPromptSection(capability));
28
+ if (!value || seen.has(value)) continue;
29
+ seen.add(value);
30
+ normalized.push(value);
31
+ }
32
+ return normalized.toSorted((left, right) => left.localeCompare(right));
33
+ }
34
+ //#endregion
35
+ //#region packages/ai/src/utils/system-prompt-cache-boundary.ts
36
+ /**
37
+ * System prompt cache-boundary helpers.
38
+ *
39
+ * Keeps stable prompt prefixes separate from dynamic runtime additions for provider prompt caching.
40
+ */
41
+ const SYSTEM_PROMPT_CACHE_BOUNDARY = "\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n";
42
+ function stripSystemPromptCacheBoundary(text) {
43
+ return text.replaceAll(SYSTEM_PROMPT_CACHE_BOUNDARY, "\n");
44
+ }
45
+ function ensureSystemPromptCacheBoundary(systemPrompt) {
46
+ if (systemPrompt.trim().length === 0) return systemPrompt;
47
+ return systemPrompt.includes("\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n") ? systemPrompt : `${systemPrompt}${SYSTEM_PROMPT_CACHE_BOUNDARY}`;
48
+ }
49
+ function splitSystemPromptCacheBoundary(text) {
50
+ const boundaryIndex = text.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
51
+ if (boundaryIndex === -1) return;
52
+ return {
53
+ stablePrefix: text.slice(0, boundaryIndex).trimEnd(),
54
+ dynamicSuffix: text.slice(boundaryIndex + 34).trimStart()
55
+ };
56
+ }
57
+ function prependSystemPromptAdditionAfterCacheBoundary(params) {
58
+ const systemPromptAddition = typeof params.systemPromptAddition === "string" ? normalizeStructuredPromptSection(params.systemPromptAddition) : "";
59
+ if (!systemPromptAddition) return params.systemPrompt;
60
+ if (params.systemPrompt.trim().length === 0) return systemPromptAddition;
61
+ const split = splitSystemPromptCacheBoundary(params.systemPrompt);
62
+ if (!split) return `${systemPromptAddition}\n\n${params.systemPrompt}`;
63
+ const dynamicSuffix = split.dynamicSuffix ? normalizeStructuredPromptSection(split.dynamicSuffix) : "";
64
+ if (!dynamicSuffix) return `${split.stablePrefix}${SYSTEM_PROMPT_CACHE_BOUNDARY}${systemPromptAddition}`;
65
+ return `${split.stablePrefix}${SYSTEM_PROMPT_CACHE_BOUNDARY}${systemPromptAddition}\n\n${dynamicSuffix}`;
66
+ }
67
+ //#endregion
68
+ //#region packages/ai/src/providers/simple-options.ts
69
+ function buildBaseOptions(model, options, apiKey) {
70
+ const firstEventOptions = options;
71
+ return {
72
+ temperature: options?.temperature,
73
+ maxTokens: options?.maxTokens,
74
+ stop: options?.stop,
75
+ signal: options?.signal,
76
+ apiKey: apiKey || options?.apiKey,
77
+ transport: options?.transport,
78
+ cacheRetention: options?.cacheRetention,
79
+ sessionId: options?.sessionId,
80
+ promptCacheKey: options?.promptCacheKey,
81
+ headers: options?.headers,
82
+ onPayload: options?.onPayload,
83
+ onResponse: options?.onResponse,
84
+ timeoutMs: options?.timeoutMs,
85
+ firstEventTimeoutMs: firstEventOptions?.firstEventTimeoutMs,
86
+ onFirstEventTimeout: firstEventOptions?.onFirstEventTimeout,
87
+ maxRetries: options?.maxRetries,
88
+ maxRetryDelayMs: options?.maxRetryDelayMs,
89
+ metadata: options?.metadata
90
+ };
91
+ }
92
+ function clampMaxTokensToModel(model, requestedMaxTokens) {
93
+ return requestedMaxTokens === void 0 ? void 0 : Math.max(1, Math.min(requestedMaxTokens, model.maxTokens));
94
+ }
95
+ function clampReasoning(effort) {
96
+ return effort === "xhigh" ? "high" : effort;
97
+ }
98
+ function adjustMaxTokensForThinking(baseMaxTokens, modelMaxTokens, reasoningLevel, customBudgets) {
99
+ const budgets = {
100
+ minimal: 1024,
101
+ low: 2048,
102
+ medium: 8192,
103
+ high: 16384,
104
+ max: 32768,
105
+ ...customBudgets
106
+ };
107
+ const minOutputTokens = 1024;
108
+ let thinkingBudget = budgets[clampReasoning(reasoningLevel)];
109
+ const maxTokens = baseMaxTokens === void 0 ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);
110
+ if (maxTokens <= thinkingBudget) thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
111
+ return {
112
+ maxTokens,
113
+ thinkingBudget
114
+ };
115
+ }
116
+ //#endregion
117
+ export { SYSTEM_PROMPT_CACHE_BOUNDARY as a, splitSystemPromptCacheBoundary as c, normalizeStructuredPromptSection as d, sortPromptCacheToolsByName as f, clampReasoning as i, stripSystemPromptCacheBoundary as l, buildBaseOptions as n, ensureSystemPromptCacheBoundary as o, clampMaxTokensToModel as r, prependSystemPromptAdditionAfterCacheBoundary as s, adjustMaxTokensForThinking as t, normalizePromptCapabilityIds as u };
@@ -0,0 +1,2 @@
1
+ import "./validation-B61OhAio.mjs";
2
+ export {};
@@ -1,4 +1,4 @@
1
- import { n as clampTimerTimeoutMs } from "./number-coercion-1Miyb5MO.mjs";
1
+ import { i as clampTimerTimeoutMs } from "./number-coercion-H9qHik3g.mjs";
2
2
  //#region packages/ai/src/utils/stream-first-event-timeout.ts
3
3
  function getFirstStreamEventTimeoutMs(options) {
4
4
  return options?.firstEventTimeoutMs;
@@ -57,8 +57,8 @@ function withFirstStreamEventTimeout(stream, context) {
57
57
  timer = setTimeout(() => {
58
58
  const timeoutError = createFirstStreamEventTimeoutError(timeoutContext);
59
59
  timeoutContext.onTimeout?.(timeoutError);
60
- timeoutContext.abort?.(timeoutError);
61
60
  reject(timeoutError);
61
+ timeoutContext.abort?.(timeoutError);
62
62
  }, timeoutMs);
63
63
  timer.unref?.();
64
64
  iterator.next().then(resolve, reject);
@@ -0,0 +1,34 @@
1
+ //#region packages/normalization-core/src/string-coerce.ts
2
+ /** Reads a value only when it is already a string, preserving whitespace. */
3
+ function readStringValue(value) {
4
+ return typeof value === "string" ? value : void 0;
5
+ }
6
+ /** Trims string input and returns null for non-strings or empty strings. */
7
+ function normalizeNullableString(value) {
8
+ if (typeof value !== "string") return null;
9
+ const trimmed = value.trim();
10
+ return trimmed ? trimmed : null;
11
+ }
12
+ /** Trims string input and returns undefined for non-strings or empty strings. */
13
+ function normalizeOptionalString(value) {
14
+ return normalizeNullableString(value) ?? void 0;
15
+ }
16
+ /** Stringifies primitive ids/flags before applying optional string normalization. */
17
+ function normalizeStringifiedOptionalString(value) {
18
+ if (typeof value === "string") return normalizeOptionalString(value);
19
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return normalizeOptionalString(String(value));
20
+ }
21
+ /** Lowercases a normalized optional string. */
22
+ function normalizeOptionalLowercaseString(value) {
23
+ return normalizeOptionalString(value)?.toLowerCase();
24
+ }
25
+ /** Lowercases a normalized string or returns an empty string when absent. */
26
+ function normalizeLowercaseStringOrEmpty(value) {
27
+ return normalizeOptionalLowercaseString(value) ?? "";
28
+ }
29
+ /** Type guard for strings that remain non-empty after trimming. */
30
+ function hasNonEmptyString(value) {
31
+ return normalizeOptionalString(value) !== void 0;
32
+ }
33
+ //#endregion
34
+ export { normalizeOptionalString as a, normalizeOptionalLowercaseString as i, normalizeLowercaseStringOrEmpty as n, normalizeStringifiedOptionalString as o, normalizeNullableString as r, readStringValue as s, hasNonEmptyString as t };
@@ -1,4 +1,5 @@
1
- import { n as getAiTransportHost } from "./host-Bl7Kgddo.mjs";
1
+ import { n as getAiTransportHost } from "./host-DTqNc7ad.mjs";
2
+ import { a as isRecord } from "./record-coerce-DdXsgUd_.mjs";
2
3
  import { types } from "node:util";
3
4
  //#region packages/ai/src/transports/host-policy.ts
4
5
  function buildGuardedModelFetch(model, timeoutMs, options) {
@@ -39,9 +40,6 @@ function isJsonValue(value) {
39
40
  default: return false;
40
41
  }
41
42
  }
42
- function isJsonObject(value) {
43
- return value !== null && typeof value === "object" && !Array.isArray(value);
44
- }
45
43
  function isNonFiniteNumberValue(value) {
46
44
  if (typeof value === "number") return !Number.isFinite(value);
47
45
  if (value === null || typeof value !== "object" || !types.isNumberObject(value)) return false;
@@ -95,12 +93,12 @@ const schemaMapKeywords = /* @__PURE__ */ new Set([
95
93
  ]);
96
94
  function findDynamicSchemaKeywordViolations(schema, path) {
97
95
  if (Array.isArray(schema)) return schema.flatMap((entry, index) => findDynamicSchemaKeywordViolations(entry, `${path}[${index}]`));
98
- if (!isJsonObject(schema)) return [];
96
+ if (!isRecord(schema)) return [];
99
97
  const violations = [];
100
98
  for (const key of ["$dynamicRef", "$dynamicAnchor"]) if (key in schema) violations.push(`${path}.${key}`);
101
99
  for (const [key, value] of Object.entries(schema)) {
102
100
  if (!value || typeof value !== "object") continue;
103
- if (schemaMapKeywords.has(key) && isJsonObject(value)) for (const [schemaName, childSchema] of Object.entries(value)) violations.push(...findDynamicSchemaKeywordViolations(childSchema, `${path}.${key}.${schemaName}`));
101
+ if (schemaMapKeywords.has(key) && isRecord(value)) for (const [schemaName, childSchema] of Object.entries(value)) violations.push(...findDynamicSchemaKeywordViolations(childSchema, `${path}.${key}.${schemaName}`));
104
102
  else violations.push(...findDynamicSchemaKeywordViolations(value, `${path}.${key}`));
105
103
  }
106
104
  return violations;
@@ -109,7 +107,7 @@ function findDynamicSchemaKeywordViolations(schema, path) {
109
107
  function projectRuntimeToolInputSchema(schema, path = "parameters") {
110
108
  const projection = serializeToolInputSchema(schema, path);
111
109
  const violations = [...projection.violations];
112
- if (!isJsonObject(projection.schema)) violations.push(`${path} must be a JSON object schema`);
110
+ if (!isRecord(projection.schema)) violations.push(`${path} must be a JSON object schema`);
113
111
  else if (projection.schema.type !== void 0 && projection.schema.type !== "object") violations.push(`${path}.type must be "object"`);
114
112
  violations.push(...findDynamicSchemaKeywordViolations(projection.schema, path));
115
113
  return {
@@ -0,0 +1,138 @@
1
+ import { a as normalizeOptionalString } from "./string-coerce-fsri9iCu.mjs";
2
+ import { n as getAiTransportHost } from "./host-DTqNc7ad.mjs";
3
+ import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
4
+ import { a as parseStrictFiniteNumber, n as asFiniteNumberInRange, o as parseStrictNonNegativeInteger } from "./number-coercion-H9qHik3g.mjs";
5
+ import { parseRetryAfterHttpDateMs } from "./internal/retry-after.mjs";
6
+ import { createHash } from "node:crypto";
7
+ //#region packages/ai/src/transports/transport-utils.ts
8
+ const MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE = "OpenClaw transport error: malformed_streaming_fragment";
9
+ const NON_LATIN_RE = /[\u2E80-\u9FFF\uA000-\uA4FF\uAC00-\uD7AF\uF900-\uFAFF\uFF01-\uFF60\uFFE0-\uFFE6\u{20000}-\u{2FA1F}]/gu;
10
+ const CJK_SURROGATE_HIGH_RE = /[\uD840-\uD87E][\uDC00-\uDFFF]/g;
11
+ function sha256Hex(value) {
12
+ return createHash("sha256").update(value).digest("hex");
13
+ }
14
+ function sha256HexPrefix(value, length) {
15
+ return sha256Hex(value).slice(0, length);
16
+ }
17
+ function redactIdentifier(value, opts) {
18
+ const trimmed = normalizeOptionalString(value);
19
+ if (!trimmed) return "-";
20
+ return `sha256:${sha256HexPrefix(trimmed, Number.isFinite(opts?.len) ? Math.max(1, Math.floor(opts?.len ?? 12)) : 12)}`;
21
+ }
22
+ function redactSensitiveText(text, _options) {
23
+ return getAiTransportHost().redactToolPayloadText(text);
24
+ }
25
+ function resolveSecretSentinel(value) {
26
+ return getAiTransportHost().resolveSecretSentinel(value);
27
+ }
28
+ function resolveModelHeaderSentinels(model) {
29
+ if (!model.headers) return model;
30
+ let headers;
31
+ for (const [name, value] of Object.entries(model.headers)) {
32
+ const resolved = resolveSecretSentinel(value);
33
+ if (resolved !== value) {
34
+ headers ??= { ...model.headers };
35
+ headers[name] = resolved;
36
+ }
37
+ }
38
+ return headers ? {
39
+ ...model,
40
+ headers
41
+ } : model;
42
+ }
43
+ function createAbortError(message, options) {
44
+ const error = new Error(message, options);
45
+ error.name = "AbortError";
46
+ return error;
47
+ }
48
+ function estimateStringChars(text) {
49
+ if (!text) return 0;
50
+ const nonLatinCount = (text.match(NON_LATIN_RE) ?? []).length;
51
+ return (nonLatinCount === 0 ? text.length : text.length - (text.match(CJK_SURROGATE_HIGH_RE) ?? []).length) + nonLatinCount * 3;
52
+ }
53
+ function supportsModelTools(model) {
54
+ return (model.compat && typeof model.compat === "object" ? model.compat : void 0)?.supportsTools !== false;
55
+ }
56
+ function isCodeModeModelVisibleToolName(name, visibleToolNames) {
57
+ return visibleToolNames.has(name);
58
+ }
59
+ function isGoogleGemini3Model(modelId, family) {
60
+ const normalized = modelId.trim().toLowerCase();
61
+ const suffix = family === "pro" ? "pro" : "flash";
62
+ return new RegExp(`(?:^|/)gemini-(?:3(?:\\.\\d+)?-${suffix}|${suffix}${family === "flash" ? "(?:-lite)?" : ""}-latest)(?:-|$)`).test(normalized);
63
+ }
64
+ function isGoogleGemini3ProModel(modelId) {
65
+ return isGoogleGemini3Model(modelId, "pro");
66
+ }
67
+ function isGoogleGemini3FlashModel(modelId) {
68
+ return isGoogleGemini3Model(modelId, "flash");
69
+ }
70
+ function parseRetryAfterSeconds(headers) {
71
+ const retryAfterMs = headers.get("retry-after-ms");
72
+ if (retryAfterMs) {
73
+ const trimmed = retryAfterMs.trim();
74
+ if (/^\d+(?:\.\d+)?$/.test(trimmed)) {
75
+ const milliseconds = asFiniteNumberInRange(parseStrictFiniteNumber(trimmed), {
76
+ min: 0,
77
+ max: Number.MAX_SAFE_INTEGER
78
+ });
79
+ return milliseconds === void 0 ? Number.POSITIVE_INFINITY : milliseconds / 1e3;
80
+ }
81
+ }
82
+ const retryAfter = headers.get("retry-after")?.trim();
83
+ if (!retryAfter) return;
84
+ if (/^\d+$/.test(retryAfter)) return parseStrictNonNegativeInteger(retryAfter) ?? Number.POSITIVE_INFINITY;
85
+ const retryAt = parseRetryAfterHttpDateMs(retryAfter);
86
+ return retryAt === void 0 ? void 0 : Math.max(0, (retryAt - Date.now()) / 1e3);
87
+ }
88
+ async function readChunkWithIdleTimeout(reader, timeoutMs, onIdleTimeout) {
89
+ let timer;
90
+ try {
91
+ return await Promise.race([reader.read(), new Promise((_resolve, reject) => {
92
+ timer = setTimeout(() => reject(onIdleTimeout?.({ chunkTimeoutMs: timeoutMs }) ?? /* @__PURE__ */ new Error("Read timed out")), timeoutMs);
93
+ })]);
94
+ } finally {
95
+ if (timer) clearTimeout(timer);
96
+ }
97
+ }
98
+ async function readResponseTextSnippet(response, options) {
99
+ const maxBytes = options?.maxBytes ?? 8 * 1024;
100
+ const maxChars = options?.maxChars ?? 200;
101
+ const reader = response.body?.getReader();
102
+ if (!reader) return;
103
+ const chunks = [];
104
+ let bytes = 0;
105
+ let truncated = false;
106
+ try {
107
+ while (bytes < maxBytes) {
108
+ const result = options?.chunkTimeoutMs ? await readChunkWithIdleTimeout(reader, options.chunkTimeoutMs, options.onIdleTimeout) : await reader.read();
109
+ if (result.done) break;
110
+ if (!result.value?.length) continue;
111
+ const remaining = maxBytes - bytes;
112
+ chunks.push(result.value.subarray(0, remaining));
113
+ bytes += Math.min(result.value.length, remaining);
114
+ if (result.value.length >= remaining) {
115
+ truncated = true;
116
+ await reader.cancel().catch(() => void 0);
117
+ break;
118
+ }
119
+ }
120
+ } catch (error) {
121
+ await reader.cancel(error).catch(() => void 0);
122
+ throw error;
123
+ } finally {
124
+ reader.releaseLock();
125
+ }
126
+ const merged = new Uint8Array(bytes);
127
+ let offset = 0;
128
+ for (const chunk of chunks) {
129
+ merged.set(chunk, offset);
130
+ offset += chunk.length;
131
+ }
132
+ const collapsed = new TextDecoder().decode(merged).replace(/\s+/g, " ").trim();
133
+ if (!collapsed) return;
134
+ if (collapsed.length > maxChars) return `${truncateUtf16Safe(collapsed, maxChars)}…`;
135
+ return truncated ? `${collapsed}…` : collapsed;
136
+ }
137
+ //#endregion
138
+ export { isGoogleGemini3FlashModel as a, readResponseTextSnippet as c, resolveModelHeaderSentinels as d, resolveSecretSentinel as f, isCodeModeModelVisibleToolName as i, redactIdentifier as l, supportsModelTools as m, createAbortError as n, isGoogleGemini3ProModel as o, sha256Hex as p, estimateStringChars as r, parseRetryAfterSeconds as s, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE as t, redactSensitiveText as u };