@openclaw/ai 2026.9.7 → 2026.10.1-beta.1

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 (115) hide show
  1. package/README.md +4 -1
  2. package/dist/{anthropic-Cw2pgccz.mjs → anthropic-CZv6XFER.mjs} +52 -147
  3. package/dist/{anthropic-payload-policy-NIPVYXPq.d.mts → anthropic-payload-policy-BhCcgNdm.d.mts} +7 -4
  4. package/dist/{anthropic-stream-reducer-D9MCkl8Z.mjs → anthropic-stream-reducer-BQ1tjd7x.mjs} +369 -233
  5. package/dist/{api-registry-D-nbmSqr.d.mts → api-registry-DpU0Rj-I.d.mts} +4 -4
  6. package/dist/{provider-transcript-transform-JbFbHV8h.mjs → assistant-output-OLm-Oln0.mjs} +17 -17
  7. package/dist/{assistant-text-phase-C20rxWwP.mjs → assistant-text-phase-Bl1aDCB7.mjs} +2 -8
  8. package/dist/{azure-openai-responses-BwT3-X8P.mjs → azure-openai-responses-DH7bd3QT.mjs} +12 -17
  9. package/dist/{azure-openai-responses-client-compat-C7K7QfUE.mjs → azure-openai-responses-client-compat-D0dvJMbZ.mjs} +3 -10
  10. package/dist/{base64-C1PsYcRQ.mjs → base64-C8CdcsjU.mjs} +3 -45
  11. package/dist/cloudflare-5qSGvIUH.mjs +39 -0
  12. package/dist/{diagnostics-CJaB6g8J.mjs → diagnostics-Caj-4RBA.mjs} +19 -37
  13. package/dist/diagnostics.d.mts +4 -4
  14. package/dist/diagnostics.mjs +2 -2
  15. package/dist/{event-stream-vd9UnCAU.mjs → event-stream-C5AbCAaZ.mjs} +29 -1
  16. package/dist/event-stream-DqDQWqiy.d.mts +1 -0
  17. package/dist/{event-stream-DOPFYVqs.d.mts → event-stream-DrRM_90c.d.mts} +1 -1
  18. package/dist/event-stream.d.mts +2 -2
  19. package/dist/event-stream.mjs +1 -1
  20. package/dist/{github-copilot-request-facts-BTEBMeOv.mjs → github-copilot-request-facts-DEE6gcB9.mjs} +3 -1
  21. package/dist/{google-BfapkS_K.mjs → google-1WLOtb8w.mjs} +12 -9
  22. package/dist/{google-interactions-DW3iXzjc.mjs → google-interactions-wrnE6MLw.mjs} +39 -49
  23. package/dist/{google-messages-CtjVtVot.mjs → google-messages-BwPPycw6.mjs} +11 -17
  24. package/dist/{google-shared-Y2YfotEu.mjs → google-shared-Eql1OMPU.mjs} +5 -6
  25. package/dist/{google-vertex-Dov4kBWu.mjs → google-vertex-0LrlRoO3.mjs} +11 -11
  26. package/dist/{host-rxlNaBwm.d.mts → host-BinBeGcQ.d.mts} +12 -4
  27. package/dist/{host-CHi3X87F.mjs → host-DCW52iHe.mjs} +57 -9
  28. package/dist/{host-policy-BOAwRg_M.mjs → host-policy-B3jc4Rpn.mjs} +9 -2
  29. package/dist/{index-D6KsSE74.d.mts → index-a8e_oKnu.d.mts} +7 -5
  30. package/dist/index.d.mts +23 -7
  31. package/dist/index.mjs +7 -7
  32. package/dist/internal/anthropic.d.mts +6 -6
  33. package/dist/internal/anthropic.mjs +5 -5
  34. package/dist/internal/google-model-family.mjs +1 -1
  35. package/dist/internal/openai-completions-compat.d.mts +1 -1
  36. package/dist/internal/openai-completions-compat.mjs +1 -1
  37. package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
  38. package/dist/internal/openai-responses-payload-policy.mjs +2 -2
  39. package/dist/internal/openai.d.mts +14 -10
  40. package/dist/internal/openai.mjs +12 -12
  41. package/dist/internal/runtime.d.mts +18 -9
  42. package/dist/internal/runtime.mjs +9 -9
  43. package/dist/internal/shared.d.mts +6 -4
  44. package/dist/internal/shared.mjs +6 -6
  45. package/dist/internal/tool-schema.mjs +1 -1
  46. package/dist/json-schema-Bp07Qui3.mjs +22 -0
  47. package/dist/{llm-request-activity-BjtkplhG.mjs → llm-request-activity-D8f_oxHj.mjs} +1 -2
  48. package/dist/{mistral-RS6mboC-.mjs → mistral-DSt4vQAO.mjs} +18 -29
  49. package/dist/number-coercion-V8-BhME4.mjs +47 -0
  50. package/dist/{openai-chatgpt-responses-CYbidtrn.mjs → openai-chatgpt-responses-BC2x0Oqx.mjs} +215 -164
  51. package/dist/openai-completions-DNyHnXKg.mjs +25 -0
  52. package/dist/{openai-completions-compat-qJjmqQ71.d.mts → openai-completions-compat-BYdYpXhU.d.mts} +3 -3
  53. package/dist/{openai-completions-compat-BOVWBZDn.mjs → openai-completions-compat-BdmlhD4u.mjs} +30 -23
  54. package/dist/{openai-completions-stream-CDCuw3DP.mjs → openai-completions-transport-DWM2mQDB.mjs} +389 -76
  55. package/dist/{openai-prompt-cache-CouErLh7.d.mts → openai-prompt-cache-45-AH_xv.d.mts} +2 -2
  56. package/dist/{openai-prompt-cache-D2V7MqR7.mjs → openai-prompt-cache-I8YQTzf8.mjs} +1 -1
  57. package/dist/{openai-responses-compaction-replay-DiYn-gFM.d.mts → openai-responses-compaction-replay-BClApUIf.d.mts} +4 -4
  58. package/dist/{openai-responses-compaction-window-UNK1GDpy.mjs → openai-responses-compaction-window-m878aVpU.mjs} +25 -83
  59. package/dist/{openai-reasoning-effort-ConhwkeX.mjs → openai-responses-contracts-BKu8O7l4.mjs} +106 -7
  60. package/dist/{openai-responses-contracts-D1iZ0njF.d.mts → openai-responses-contracts-Br5IIw_h.d.mts} +16 -5
  61. package/dist/openai-responses-prompt-observer-internal-CCg7B6l4.mjs +32 -0
  62. package/dist/{openai-responses-shared-DL4ulQn7.mjs → openai-responses-shared-C7oVyjED.mjs} +297 -312
  63. package/dist/{openai-responses-terminal-usage-BE7lf7nW.d.mts → openai-responses-terminal-usage-DgImcyJu.d.mts} +2 -2
  64. package/dist/{openai-responses-CKCBEc2W.mjs → openai-responses-uZ5oWSp7.mjs} +12 -21
  65. package/dist/{openai-tool-schema-vsl-cE-n.mjs → openai-tool-schema-DYNePiF8.mjs} +66 -36
  66. package/dist/{openai-transport-params-BwlpzX-2.mjs → openai-transport-params-JFsnIyto.mjs} +25 -30
  67. package/dist/openai-web-search-tools-Cfu0uLyN.mjs +14 -0
  68. package/dist/{positive-integer-CjN5OJbH.mjs → positive-integer-CwLi8LUL.mjs} +1 -1
  69. package/dist/{provider-error-CwT_j2v0.mjs → provider-error-DQBE1bUQ.mjs} +17 -28
  70. package/dist/{provider-options-Df7ov0K1.d.mts → provider-options-D5ABCV_l.d.mts} +2 -2
  71. package/dist/{provider-replay-context-DsyI5jOP.mjs → provider-replay-context-C7Bmi84a.mjs} +6 -2
  72. package/dist/{provider-transport-turn-state-BheUi_hl.mjs → provider-transport-turn-state-_M2kLdUE.mjs} +25 -3
  73. package/dist/{provider-types-d4XnoZMd.d.mts → provider-types-F8Mqc9Ma.d.mts} +3 -3
  74. package/dist/provider-types.d.mts +6 -6
  75. package/dist/providers.d.mts +2 -2
  76. package/dist/providers.mjs +14 -26
  77. package/dist/{reasoning-tag-text-partitioner-B6FIIBt6.mjs → reasoning-tag-text-partitioner-Ju9VpUGl.mjs} +23 -37
  78. package/dist/required-api-key-D4kn3252.mjs +9 -0
  79. package/dist/sanitize-unicode-CjDG6jJx.d.mts +5 -0
  80. package/dist/{session-affinity-Bcunsn4I.mjs → session-affinity-DA4WHv1h.mjs} +2 -6
  81. package/dist/session-resources-D1wgDQ8C.mjs +40 -0
  82. package/dist/{simple-options-CGAkCwtM.mjs → simple-options-BkKTXxhp.mjs} +7 -11
  83. package/dist/{src-H4aXcFuX.mjs → src-B0NIt2UK.mjs} +7 -4
  84. package/dist/stream-DSdzKsDK.mjs +275 -0
  85. package/dist/{stream-first-event-timeout-B9o0S4SZ.mjs → stream-first-event-timeout-D9ZmL_s9.mjs} +3 -3
  86. package/dist/{string-coerce-fsri9iCu.mjs → string-coerce-CtgOVOSv.mjs} +5 -1
  87. package/dist/{string-normalization-J9ZiLfGO.mjs → string-normalization-PN10hf6d.mjs} +1 -1
  88. package/dist/{transport-utils-C-4bf2Ok.mjs → text-signature-MLwfi6fq.mjs} +18 -18
  89. package/dist/{transport-stream-shared-yYhXa4kX.d.mts → transport-stream-shared-BcAKh2XH.d.mts} +6 -19
  90. package/dist/{transport-stream-shared-Dh5qKJ8e.mjs → transport-stream-shared-CxXXz_Dd.mjs} +171 -56
  91. package/dist/transports.d.mts +22 -23
  92. package/dist/transports.mjs +251 -495
  93. package/dist/types-BuiEBM3u.d.mts +1 -0
  94. package/dist/types-CQc6JNG4.mjs +69 -0
  95. package/dist/{types-CLLR3eB4.d.mts → types-DvzmWW8J.d.mts} +58 -6
  96. package/dist/types.d.mts +6 -6
  97. package/dist/types.mjs +5 -5
  98. package/dist/usage-CJH5D6Ea.mjs +19 -0
  99. package/dist/{validation-Cat2wQsc.d.mts → validation-B3lQt_VE.d.mts} +1 -1
  100. package/dist/{validation-BFZc40Ig.mjs → validation-DbqlIfDn.mjs} +15 -30
  101. package/dist/validation.d.mts +1 -1
  102. package/dist/validation.mjs +1 -1
  103. package/package.json +4 -4
  104. package/dist/cache-retention-0x979a5V.mjs +0 -12
  105. package/dist/event-stream-CMQfX_yr.d.mts +0 -1
  106. package/dist/github-copilot-headers-B37TB3rB.mjs +0 -30
  107. package/dist/openai-completions-D14ihPYk.mjs +0 -188
  108. package/dist/openai-provider-client-CwfsGBbA.mjs +0 -24
  109. package/dist/openai-responses-contracts-CLxnqS9p.mjs +0 -81
  110. package/dist/openai-responses-prompt-observer-internal-iAqLb4tk.mjs +0 -198
  111. package/dist/sanitize-unicode-BZiVbGwK.d.mts +0 -24
  112. package/dist/session-resources-CkR4WWy1.mjs +0 -21
  113. package/dist/stream-DDsCBgd-.mjs +0 -68
  114. package/dist/types-CB-_vNyI.d.mts +0 -1
  115. package/dist/types-LFWwv0cF.mjs +0 -8
@@ -1,10 +1,10 @@
1
- import "./index-D6KsSE74.mjs";
2
- import { G as SimpleStreamOptions, J as StreamFunction, O as Model, Y as StreamOptions, d as Context, n as Api, s as AssistantMessageEventStreamContract } from "./types-CLLR3eB4.mjs";
1
+ import "./index-a8e_oKnu.mjs";
2
+ import { Q as SimpleStreamOptions, n as Api, nt as StreamOptions, tt as StreamFunction } from "./types-DvzmWW8J.mjs";
3
3
  //#region packages/ai/src/api-registry.d.ts
4
4
  /** Runtime stream adapter signature stored in the API provider registry. */
5
- type ApiStreamFunction = (model: Model, context: Context, options?: StreamOptions) => AssistantMessageEventStreamContract;
5
+ type ApiStreamFunction = StreamFunction;
6
6
  /** Runtime simple-stream adapter signature stored in the API provider registry. */
7
- type ApiStreamSimpleFunction = (model: Model, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStreamContract;
7
+ type ApiStreamSimpleFunction = StreamFunction<Api, SimpleStreamOptions>;
8
8
  /** Provider implementation registered by core or plugins for a specific model API. */
9
9
  interface ApiProvider<TApi extends Api = Api, TOptions extends StreamOptions = StreamOptions> {
10
10
  /** Model API id this provider handles. */
@@ -1,19 +1,5 @@
1
- import { i as transformMessages } from "./host-CHi3X87F.mjs";
2
- import { a as createEmptyTransportUsage } from "./transport-stream-shared-Dh5qKJ8e.mjs";
3
- //#region packages/ai/src/transports/assistant-output.ts
4
- function createAssistantOutput(model, api = model.api) {
5
- return {
6
- role: "assistant",
7
- content: [],
8
- api,
9
- provider: model.provider,
10
- model: model.id,
11
- usage: createEmptyTransportUsage(),
12
- stopReason: "stop",
13
- timestamp: Date.now()
14
- };
15
- }
16
- //#endregion
1
+ import { c as transformMessages } from "./host-DCW52iHe.mjs";
2
+ import { a as createEmptyTransportUsage } from "./transport-stream-shared-CxXXz_Dd.mjs";
17
3
  //#region packages/ai/src/provider-transcript-transform.ts
18
4
  const IMAGE_OMISSION = "(image omitted: model does not support images)";
19
5
  const VIDEO_OMISSION = "(video omitted: provider does not support video input)";
@@ -44,4 +30,18 @@ function transformProviderMessages(messages, model, normalizeToolCallId) {
44
30
  }), target, normalizeToolCallId);
45
31
  }
46
32
  //#endregion
47
- export { createAssistantOutput as n, transformProviderMessages as t };
33
+ //#region packages/ai/src/transports/assistant-output.ts
34
+ function createAssistantOutput(model, api = model.api) {
35
+ return {
36
+ role: "assistant",
37
+ content: [],
38
+ api,
39
+ provider: model.provider,
40
+ model: model.id,
41
+ usage: createEmptyTransportUsage(),
42
+ stopReason: "stop",
43
+ timestamp: Date.now()
44
+ };
45
+ }
46
+ //#endregion
47
+ export { transformProviderMessages as n, createAssistantOutput as t };
@@ -1,3 +1,4 @@
1
+ import { t as encodeTextSignatureV1 } from "./text-signature-MLwfi6fq.mjs";
1
2
  import { randomUUID } from "node:crypto";
2
3
  //#region packages/ai/src/utils/assistant-text-phase.ts
3
4
  const EMPTY_ASSISTANT_TEXT_BLOCK_SET = /* @__PURE__ */ new Set();
@@ -6,20 +7,13 @@ function isAssistantTextPhaseBlock(block) {
6
7
  const record = block;
7
8
  return record.type === "text" && typeof record.text === "string";
8
9
  }
9
- function encodeAssistantTextSignatureV1(id, phase) {
10
- return JSON.stringify({
11
- v: 1,
12
- id,
13
- ...phase ? { phase } : {}
14
- });
15
- }
16
10
  function tagUnphasedText(content, phase, idPrefix) {
17
11
  const textBlocks = content.filter(isAssistantTextPhaseBlock);
18
12
  let phaseIndex = textBlocks.filter((block) => block.textSignature !== void 0).length;
19
13
  const tagged = /* @__PURE__ */ new Map();
20
14
  for (const block of textBlocks) {
21
15
  if (block.text.trim().length === 0 || block.textSignature !== void 0) continue;
22
- const signature = encodeAssistantTextSignatureV1(`${idPrefix}-${phaseIndex}-${randomUUID().replaceAll("-", "").slice(0, 24)}`, phase);
16
+ const signature = encodeTextSignatureV1(`${idPrefix}-${phaseIndex}-${randomUUID().replaceAll("-", "").slice(0, 24)}`, phase);
23
17
  block.textSignature = signature;
24
18
  tagged.set(block, signature);
25
19
  phaseIndex += 1;
@@ -1,12 +1,12 @@
1
- import { t as AssistantMessageEventStream } from "./event-stream-vd9UnCAU.mjs";
2
- import { n as getAiTransportHost } from "./host-CHi3X87F.mjs";
3
- import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-D2V7MqR7.mjs";
4
- import { n as buildBaseOptions } from "./simple-options-CGAkCwtM.mjs";
5
- import { g as resolveOpenAISimpleReasoningEffort } from "./openai-transport-params-BwlpzX-2.mjs";
1
+ import { t as AssistantMessageEventStream } from "./event-stream-C5AbCAaZ.mjs";
2
+ import { r as getAiTransportHost } from "./host-DCW52iHe.mjs";
3
+ import { n as buildBaseOptions } from "./simple-options-BkKTXxhp.mjs";
4
+ import { g as resolveOpenAISimpleReasoningEffort, k as resolvePromptCacheKey } from "./openai-transport-params-JFsnIyto.mjs";
6
5
  import { n as getEnvApiKey } from "./env-api-keys-CyX4VKGO.mjs";
7
- import { n as createAssistantOutput } from "./provider-transcript-transform-JbFbHV8h.mjs";
8
- import { P as convertProviderResponsesMessages, r as runResponsesStreamLifecycle, t as applyCommonResponsesParams } from "./openai-responses-shared-DL4ulQn7.mjs";
9
- import { i as resolveAzureDeploymentNameFromMap, n as isTraditionalAzureOpenAIHost, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
6
+ import { t as createAssistantOutput } from "./assistant-output-OLm-Oln0.mjs";
7
+ import { P as convertProviderResponsesMessages, r as runResponsesStreamLifecycle, t as applyCommonResponsesParams } from "./openai-responses-shared-C7oVyjED.mjs";
8
+ import { i as resolveAzureDeploymentNameFromMap, n as isTraditionalAzureOpenAIHost, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-D0dvJMbZ.mjs";
9
+ import { t as requireApiKey } from "./required-api-key-D4kn3252.mjs";
10
10
  import OpenAI, { AzureOpenAI } from "openai";
11
11
  //#region packages/ai/src/providers/azure-openai-responses.ts
12
12
  const DEFAULT_AZURE_API_VERSION = "v1";
@@ -45,8 +45,7 @@ const streamAzureOpenAIResponses = (model, context, options) => {
45
45
  return stream;
46
46
  };
47
47
  const streamSimpleAzureOpenAIResponses = (model, context, options) => {
48
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
49
- if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
48
+ const apiKey = requireApiKey(model.provider, options?.apiKey);
50
49
  const base = buildBaseOptions(model, options, apiKey);
51
50
  const authProfileId = options?.authProfileId;
52
51
  return streamAzureOpenAIResponses(model, context, {
@@ -57,12 +56,8 @@ const streamSimpleAzureOpenAIResponses = (model, context, options) => {
57
56
  };
58
57
  function normalizeAzureBaseUrl(baseUrl) {
59
58
  const trimmed = baseUrl.trim().replace(/\/+$/, "");
60
- let url;
61
- try {
62
- url = new URL(trimmed);
63
- } catch {
64
- throw new Error(`Invalid Azure OpenAI base URL: ${baseUrl}`);
65
- }
59
+ const url = URL.parse(trimmed);
60
+ if (!url) throw new Error(`Invalid Azure OpenAI base URL: ${baseUrl}`);
66
61
  const normalizedPath = url.pathname.replace(/\/+$/, "");
67
62
  if (isTraditionalAzureOpenAIHost(url.hostname) && (normalizedPath === "" || normalizedPath === "/" || normalizedPath === "/openai")) {
68
63
  url.pathname = "/openai/v1";
@@ -112,7 +107,7 @@ function buildParams(model, context, options, deploymentName, replayMode = "chec
112
107
  replayMode
113
108
  }),
114
109
  stream: true,
115
- prompt_cache_key: options?.cacheRetention === "none" ? void 0 : clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId),
110
+ prompt_cache_key: resolvePromptCacheKey(options, options?.cacheRetention ?? "short"),
116
111
  store: false
117
112
  };
118
113
  applyCommonResponsesParams(params, model, context, options);
@@ -20,12 +20,10 @@ function getDeploymentLookup(source) {
20
20
  const cached = cachedDeploymentLookup;
21
21
  if (cached && cached.source === source) return cached;
22
22
  const exact = parseAzureDeploymentNameMap(source);
23
- const folded = /* @__PURE__ */ new Map();
24
- for (const [modelId, deploymentName] of exact) folded.set(modelId.toLowerCase(), deploymentName);
25
23
  cachedDeploymentLookup = {
26
24
  source,
27
25
  exact,
28
- folded
26
+ folded: new Map([...exact].map(([modelId, deployment]) => [modelId.toLowerCase(), deployment]))
29
27
  };
30
28
  return cachedDeploymentLookup;
31
29
  }
@@ -46,13 +44,8 @@ function isTraditionalAzureOpenAIHost(hostname) {
46
44
  return hostname.endsWith(".openai.azure.com") || hostname.endsWith(".cognitiveservices.azure.com");
47
45
  }
48
46
  function isOpenAICompatibleAzureResponsesBaseUrl(baseUrl) {
49
- let url;
50
- try {
51
- url = new URL(baseUrl);
52
- } catch {
53
- return false;
54
- }
55
- if (isTraditionalAzureOpenAIHost(url.hostname)) return false;
47
+ const url = URL.parse(baseUrl);
48
+ if (!url || isTraditionalAzureOpenAIHost(url.hostname)) return false;
56
49
  const hostname = url.hostname.toLowerCase();
57
50
  if (!(hostname.endsWith(".services.ai.azure.com") || hostname.endsWith(".api.cognitive.microsoft.com"))) return false;
58
51
  const normalizedPath = url.pathname.replace(/\/+$/, "");
@@ -1,43 +1,3 @@
1
- import { a as normalizeOptionalString } from "./string-coerce-fsri9iCu.mjs";
2
- //#region packages/normalization-core/src/number-coercion.ts
3
- /** Returns a number only when the input is already finite. */
4
- function asFiniteNumber(value) {
5
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
6
- }
7
- /** Returns a finite number only when it is zero or greater. */
8
- function asNonNegativeFiniteNumber(value) {
9
- const number = asFiniteNumber(value);
10
- return number && number < 0 ? void 0 : number;
11
- }
12
- /** Parses only safe integer numbers or base-10 integer strings. */
13
- function parseStrictInteger(value) {
14
- if (typeof value === "number") return Number.isSafeInteger(value) ? value : void 0;
15
- const normalized = normalizeOptionalString(value);
16
- if (!normalized || !/^[+-]?\d+$/.test(normalized)) return;
17
- const parsed = Number(normalized);
18
- return Number.isSafeInteger(parsed) ? parsed : void 0;
19
- }
20
- /** Conservative upper bound for Node timer delays. */
21
- const MAX_TIMER_TIMEOUT_MS = 2147e6;
22
- /** Clamps finite millisecond values into the Node-safe timer range. */
23
- function clampTimerTimeoutMs(valueMs, minMs = 1) {
24
- const value = asFiniteNumber(valueMs);
25
- if (value === void 0) return;
26
- return Math.min(Math.max(Math.floor(value), Math.max(1, Math.floor(minMs))), MAX_TIMER_TIMEOUT_MS);
27
- }
28
- /** Resolves arbitrary timeout input with fallback and minimum timer bounds. */
29
- function resolveTimerTimeoutMs(valueMs, fallbackMs, minMs = 1) {
30
- const value = asFiniteNumber(valueMs) ?? asFiniteNumber(fallbackMs);
31
- const min = Math.max(0, Math.floor(minMs));
32
- if (value === void 0) return min;
33
- return Math.min(Math.max(Math.floor(value), min), MAX_TIMER_TIMEOUT_MS);
34
- }
35
- /** Parses strict positive integer values from numbers or strings. */
36
- function parseStrictPositiveInteger(value) {
37
- const parsed = parseStrictInteger(value);
38
- return parsed !== void 0 && parsed > 0 ? parsed : void 0;
39
- }
40
- //#endregion
41
1
  //#region packages/media-core/src/base64.ts
42
2
  /** Estimates decoded bytes without allocating a cleaned copy of the base64 payload. */
43
3
  function estimateBase64DecodedBytes(base64) {
@@ -79,7 +39,6 @@ function inspectBase64(base64, dialect) {
79
39
  let out;
80
40
  let outLen = 0;
81
41
  let padding = 0;
82
- let sawPadding = false;
83
42
  let lastDataValue = 0;
84
43
  for (let i = 0; i < base64.length; i += 1) {
85
44
  const code = base64.charCodeAt(i);
@@ -95,10 +54,9 @@ function inspectBase64(base64, dialect) {
95
54
  if (code === 61) {
96
55
  padding += 1;
97
56
  if (padding > 2) return;
98
- sawPadding = true;
99
57
  } else {
100
58
  const value = base64DataValue(code);
101
- if (sawPadding || value < 0) return;
59
+ if (padding > 0 || value < 0) return;
102
60
  lastDataValue = value;
103
61
  }
104
62
  if (out !== void 0) {
@@ -109,7 +67,7 @@ function inspectBase64(base64, dialect) {
109
67
  const cleanedLength = out === void 0 ? base64.length : outLen;
110
68
  if (cleanedLength === 0) return;
111
69
  const remainder = cleanedLength % 4;
112
- if (remainder !== 0 && (sawPadding || remainder === 1)) return;
70
+ if (remainder !== 0 && (padding > 0 || remainder === 1)) return;
113
71
  const effectivePadding = remainder === 0 ? padding : 4 - remainder;
114
72
  const padBitMask = effectivePadding === 2 ? 15 : effectivePadding === 1 ? 3 : 0;
115
73
  const cleaned = out === void 0 ? base64 : out.subarray(0, outLen).toString("latin1");
@@ -120,4 +78,4 @@ function inspectBase64(base64, dialect) {
120
78
  };
121
79
  }
122
80
  //#endregion
123
- export { clampTimerTimeoutMs as a, asNonNegativeFiniteNumber as i, estimateBase64DecodedBytes as n, parseStrictPositiveInteger as o, asFiniteNumber as r, resolveTimerTimeoutMs as s, canonicalizeBase64 as t };
81
+ export { estimateBase64DecodedBytes as n, canonicalizeBase64 as t };
@@ -0,0 +1,39 @@
1
+ import { t as projectCopilotRequestFacts } from "./github-copilot-request-facts-DEE6gcB9.mjs";
2
+ //#region packages/ai/src/providers/cache-retention.ts
3
+ /**
4
+ * Resolve cache retention preference.
5
+ * Defaults to "short" and uses OPENCLAW_CACHE_RETENTION for backward compatibility.
6
+ */
7
+ function resolveCacheRetention(cacheRetention) {
8
+ if (cacheRetention === "short" || cacheRetention === "long" || cacheRetention === "none") return cacheRetention;
9
+ if (typeof process !== "undefined" && process.env.OPENCLAW_CACHE_RETENTION === "long") return "long";
10
+ return "short";
11
+ }
12
+ //#endregion
13
+ //#region packages/ai/src/providers/github-copilot-headers.ts
14
+ function buildCopilotDynamicHeaders(messages) {
15
+ const { initiator, hasImages } = projectCopilotRequestFacts(messages, "direct");
16
+ const headers = {
17
+ "X-Initiator": initiator,
18
+ "Openai-Intent": "conversation-edits"
19
+ };
20
+ if (hasImages) headers["Copilot-Vision-Request"] = "true";
21
+ return headers;
22
+ }
23
+ //#endregion
24
+ //#region packages/ai/src/providers/cloudflare.ts
25
+ function isCloudflareProvider(provider) {
26
+ return provider === "cloudflare-workers-ai" || provider === "cloudflare-ai-gateway";
27
+ }
28
+ /** Substitute `{VAR}` placeholders in a Cloudflare baseUrl from process.env. */
29
+ function resolveCloudflareBaseUrl(model) {
30
+ const url = model.baseUrl;
31
+ if (!url.includes("{")) return url;
32
+ return url.replace(/\{([A-Z_][A-Z0-9_]*)\}/g, (_match, name) => {
33
+ const value = process.env[name];
34
+ if (!value) throw new Error(`${name} is required for provider ${model.provider} but is not set.`);
35
+ return value;
36
+ });
37
+ }
38
+ //#endregion
39
+ export { resolveCacheRetention as i, resolveCloudflareBaseUrl as n, buildCopilotDynamicHeaders as r, isCloudflareProvider as t };
@@ -1,8 +1,8 @@
1
1
  import { a as isProviderRefusalAssistantError } from "./diagnostics-DzrF1h4J.mjs";
2
2
  import { i as asOptionalRecord, o as isRecord } from "./record-coerce-CNDovvft.mjs";
3
- import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
4
- import "./provider-error-CwT_j2v0.mjs";
5
- import { r as asFiniteNumber } from "./base64-C1PsYcRQ.mjs";
3
+ import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-CtgOVOSv.mjs";
4
+ import { n as asNonNegativeFiniteNumber, t as asFiniteNumber } from "./number-coercion-V8-BhME4.mjs";
5
+ import "./provider-error-DQBE1bUQ.mjs";
6
6
  //#region packages/normalization-core/src/error-coercion.ts
7
7
  function readProperty(value, key) {
8
8
  try {
@@ -26,8 +26,7 @@ function toErrorObject(value, fallbackMessage) {
26
26
  function extractErrorCode(err) {
27
27
  if (!err || typeof err !== "object") return;
28
28
  const code = readProperty(err, "code");
29
- if (typeof code === "string") return code;
30
- if (typeof code === "number") return String(code);
29
+ return typeof code === "string" || typeof code === "number" ? String(code) : void 0;
31
30
  }
32
31
  function readErrorName(err) {
33
32
  if (!err || typeof err !== "object") return "";
@@ -98,11 +97,8 @@ function safeParseJsonRecord(value) {
98
97
  function isResponsesOutputLimitToolCallError(message) {
99
98
  return message.stopReason === "error" && message.errorCode === "incomplete_tool_call" && !isProviderRefusalAssistantError(message) && message.diagnostics?.some(({ type, details }) => type === "openai_responses_terminal" && details?.eventType === "response.incomplete" && details.stopReason === "length" && details.incompleteReason === "max_output_tokens") === true;
100
99
  }
101
- function readReportedCount(value) {
102
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
103
- }
104
100
  function readCount(value) {
105
- return readReportedCount(value) ?? 0;
101
+ return asNonNegativeFiniteNumber(value) ?? 0;
106
102
  }
107
103
  /**
108
104
  * Split a terminal usage payload into the priced buckets.
@@ -121,9 +117,9 @@ function mapResponsesTerminalUsage(usage) {
121
117
  const output = readCount(usage.output_tokens);
122
118
  const bucketTotal = input + output + cacheRead + cacheWrite;
123
119
  const totalTokens = Math.max(bucketTotal, readCount(usage.total_tokens));
124
- const reportedInput = readReportedCount(usage.input_tokens);
125
- const reportedOutput = readReportedCount(usage.output_tokens);
126
- const reportedTotal = readReportedCount(usage.total_tokens);
120
+ const reportedInput = asNonNegativeFiniteNumber(usage.input_tokens);
121
+ const reportedOutput = asNonNegativeFiniteNumber(usage.output_tokens);
122
+ const reportedTotal = asNonNegativeFiniteNumber(usage.total_tokens);
127
123
  return {
128
124
  input,
129
125
  output,
@@ -253,8 +249,7 @@ const TRANSIENT_NETWORK_MESSAGE_SNIPPETS = [
253
249
  ];
254
250
  const RETRYABLE_CONNECTION_ERROR_CODE_RE = /\b(?:ECONNRESET|ECONNREFUSED|ETIMEDOUT|EPIPE|EHOSTUNREACH|ENETUNREACH|EAI_AGAIN|UND_ERR_SOCKET)\b/i;
255
251
  function isWrappedFetchFailedMessage(message) {
256
- if (message === "fetch failed") return true;
257
- return /:\s*fetch failed$/.test(message);
252
+ return message === "fetch failed" || /:\s*fetch failed$/.test(message);
258
253
  }
259
254
  function hasRetryableConnectionErrorCode(message) {
260
255
  return RETRYABLE_CONNECTION_ERROR_CODE_RE.test(message);
@@ -272,20 +267,12 @@ function isTransientNetworkError(err) {
272
267
  if (!candidate || typeof candidate !== "object") continue;
273
268
  const message = normalizeLowercaseStringOrEmpty(candidate.message);
274
269
  if (!message) continue;
275
- if (TRANSIENT_NETWORK_MESSAGE_CODE_RE.test(message)) return true;
276
- if (isWrappedFetchFailedMessage(message)) return true;
277
- if (TRANSIENT_NETWORK_MESSAGE_SNIPPETS.some((snippet) => message.includes(snippet))) return true;
270
+ if (TRANSIENT_NETWORK_MESSAGE_CODE_RE.test(message) || isWrappedFetchFailedMessage(message) || TRANSIENT_NETWORK_MESSAGE_SNIPPETS.some((snippet) => message.includes(snippet))) return true;
278
271
  }
279
272
  return false;
280
273
  }
281
274
  //#endregion
282
275
  //#region packages/ai/src/transports/model-transport-debug.ts
283
- /**
284
- * Environment-driven debug controls for model transport logging.
285
- *
286
- * Model adapters share these helpers so payload, SSE, and transport diagnostics
287
- * interpret OpenClaw debug environment variables consistently.
288
- */
289
276
  function isTruthyEnv(value) {
290
277
  const normalized = normalizeLowercaseStringOrEmpty(value);
291
278
  return normalized.length > 0 && normalized !== "0" && normalized !== "false" && normalized !== "off" && normalized !== "no";
@@ -293,16 +280,14 @@ function isTruthyEnv(value) {
293
280
  /** Resolves model payload debug verbosity from `OPENCLAW_DEBUG_MODEL_PAYLOAD`. */
294
281
  function resolveModelPayloadDebugMode(env = process.env) {
295
282
  const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_MODEL_PAYLOAD);
296
- if (normalized === "tools" || normalized === "full-redacted") return normalized;
297
- if (normalized === "summary") return "summary";
283
+ if (normalized === "tools" || normalized === "full-redacted" || normalized === "summary") return normalized;
298
284
  return "off";
299
285
  }
300
286
  /** Resolves SSE stream debug verbosity from `OPENCLAW_DEBUG_SSE`. */
301
287
  function resolveModelSseDebugMode(env = process.env) {
302
288
  const normalized = normalizeLowercaseStringOrEmpty(env.OPENCLAW_DEBUG_SSE);
303
289
  if (normalized === "peek") return "peek";
304
- if (normalized === "events" || isTruthyEnv(normalized)) return "events";
305
- return "off";
290
+ return isTruthyEnv(normalized) ? "events" : "off";
306
291
  }
307
292
  /** Returns whether any model transport debug channel is enabled. */
308
293
  function isModelTransportDebugEnabled(env = process.env) {
@@ -324,16 +309,13 @@ function emitModelTransportDebug(log, message) {
324
309
  */
325
310
  /** Return a sanitized URL suitable for logs and diagnostics. */
326
311
  function formatModelTransportDebugUrl(rawUrl) {
327
- try {
328
- const parsed = new URL(rawUrl);
329
- parsed.username = "";
330
- parsed.password = "";
331
- parsed.search = "";
332
- parsed.hash = "";
333
- return parsed.toString();
334
- } catch {
335
- return "<invalid-url>";
336
- }
312
+ const parsed = URL.parse(rawUrl);
313
+ if (!parsed) return "<invalid-url>";
314
+ parsed.username = "";
315
+ parsed.password = "";
316
+ parsed.search = "";
317
+ parsed.hash = "";
318
+ return parsed.toString();
337
319
  }
338
320
  /** Format a configured base URL for debug output, or the implicit default. */
339
321
  function formatModelTransportDebugBaseUrl(rawUrl) {
@@ -1,7 +1,7 @@
1
- import { a as ProviderRefusalReview, o as readProviderRefusalReview } from "./index-D6KsSE74.mjs";
2
- import { a as AssistantMessage, dt as DiagnosticErrorInfo, ft as appendAssistantMessageDiagnostic, gt as isProviderRefusalAssistantError, ht as formatThrownValue, mt as extractDiagnosticError, pt as createAssistantMessageDiagnostic, ut as AssistantMessageDiagnostic } from "./types-CLLR3eB4.mjs";
3
- import "./types-CB-_vNyI.mjs";
4
- import { n as isResponsesOutputLimitToolCallError } from "./openai-responses-terminal-usage-BE7lf7nW.mjs";
1
+ import { a as ProviderRefusalReview, o as readProviderRefusalReview } from "./index-a8e_oKnu.mjs";
2
+ import { At as extractDiagnosticError, Dt as DiagnosticErrorInfo, Et as AssistantMessageDiagnostic, Mt as isProviderRefusalAssistantError, Ot as appendAssistantMessageDiagnostic, a as AssistantMessage, jt as formatThrownValue, kt as createAssistantMessageDiagnostic } from "./types-DvzmWW8J.mjs";
3
+ import "./types-BuiEBM3u.mjs";
4
+ import { n as isResponsesOutputLimitToolCallError } from "./openai-responses-terminal-usage-DgImcyJu.mjs";
5
5
  import { n as ProviderErrorRedactor, r as configureProviderErrorRedactor } from "./provider-error-xumb1V3F.mjs";
6
6
  import { r as projectDiagnosticValue, t as DiagnosticProjectionPolicy } from "./credential-redaction-BKv49aiv.mjs";
7
7
  import { n as formatModelTransportDebugUrl, r as emitModelTransportDebug, t as formatModelTransportDebugBaseUrl } from "./model-transport-url-C5f59L3Y.mjs";
@@ -1,4 +1,4 @@
1
1
  import { a as isProviderRefusalAssistantError, i as formatThrownValue, n as createAssistantMessageDiagnostic, o as readProviderRefusalReview, r as extractDiagnosticError, t as appendAssistantMessageDiagnostic } from "./diagnostics-DzrF1h4J.mjs";
2
- import { i as projectDiagnosticValue, t as configureProviderErrorRedactor } from "./provider-error-CwT_j2v0.mjs";
3
- import { c as isTransientNetworkError, f as resolveResponsesOutputIdentityRetry, n as formatModelTransportDebugUrl, o as WEBSOCKET_NON_RETRYABLE_CLOSE_ERROR_CODE, p as isResponsesOutputLimitToolCallError, r as emitModelTransportDebug, s as hasRetryableConnectionErrorCode, t as formatModelTransportDebugBaseUrl } from "./diagnostics-CJaB6g8J.mjs";
2
+ import { i as projectDiagnosticValue, t as configureProviderErrorRedactor } from "./provider-error-DQBE1bUQ.mjs";
3
+ import { c as isTransientNetworkError, f as resolveResponsesOutputIdentityRetry, n as formatModelTransportDebugUrl, o as WEBSOCKET_NON_RETRYABLE_CLOSE_ERROR_CODE, p as isResponsesOutputLimitToolCallError, r as emitModelTransportDebug, s as hasRetryableConnectionErrorCode, t as formatModelTransportDebugBaseUrl } from "./diagnostics-Caj-4RBA.mjs";
4
4
  export { WEBSOCKET_NON_RETRYABLE_CLOSE_ERROR_CODE, appendAssistantMessageDiagnostic, configureProviderErrorRedactor, createAssistantMessageDiagnostic, emitModelTransportDebug, extractDiagnosticError, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, formatThrownValue, hasRetryableConnectionErrorCode, isProviderRefusalAssistantError, isResponsesOutputLimitToolCallError, isTransientNetworkError, projectDiagnosticValue, readProviderRefusalReview, resolveResponsesOutputIdentityRetry };
@@ -20,6 +20,34 @@ const eventStreamCompletions = /* @__PURE__ */ new WeakMap();
20
20
  function getEventStreamCompletion(stream) {
21
21
  return eventStreamCompletions.get(stream);
22
22
  }
23
+ /** Bind consumer operations without mutating provider streams or losing producer settlement. */
24
+ function bindAssistantMessageEventStream(source, run, options) {
25
+ const push = source.push.bind(source);
26
+ const end = source.end.bind(source);
27
+ const result = options?.result ?? source.result.bind(source);
28
+ const iterate = source[Symbol.asyncIterator].bind(source);
29
+ const bound = {
30
+ push: (event) => run(() => push(event)),
31
+ end: (message) => run(() => end(message)),
32
+ result: () => run(result),
33
+ [Symbol.asyncIterator]: () => {
34
+ const iterator = run(iterate);
35
+ const finish = iterator.return?.bind(iterator);
36
+ const fail = iterator.throw?.bind(iterator);
37
+ return {
38
+ [Symbol.asyncIterator]() {
39
+ return this;
40
+ },
41
+ next: (...args) => run(() => iterator.next(...args)),
42
+ ...finish ? { return: (value) => run(() => finish(value)) } : {},
43
+ ...fail ? { throw: (error) => run(() => fail(error)) } : {}
44
+ };
45
+ }
46
+ };
47
+ const completion = eventStreamCompletions.get(source);
48
+ if (completion) eventStreamCompletions.set(bound, completion);
49
+ return bound;
50
+ }
23
51
  /** Generic async-iterable event stream with a separately awaited final result. */
24
52
  var EventStream = class {
25
53
  constructor(isComplete, extractResult) {
@@ -139,4 +167,4 @@ function createAssistantMessageEventStream() {
139
167
  return new AssistantMessageEventStream();
140
168
  }
141
169
  //#endregion
142
- export { getEventStreamCompletion as a, createAssistantMessageEventStream as i, EventStream as n, readAssistantThinkingAppend as o, appendAssistantThinking as r, AssistantMessageEventStream as t };
170
+ export { createAssistantMessageEventStream as a, bindAssistantMessageEventStream as i, EventStream as n, getEventStreamCompletion as o, appendAssistantThinking as r, readAssistantThinkingAppend as s, AssistantMessageEventStream as t };
@@ -0,0 +1 @@
1
+ import "./event-stream-DrRM_90c.mjs";
@@ -1,4 +1,4 @@
1
- import { $ as ThinkingContent, a as AssistantMessage, o as AssistantMessageEvent, s as AssistantMessageEventStreamContract } from "./types-CLLR3eB4.mjs";
1
+ import { a as AssistantMessage, o as AssistantMessageEvent, ot as ThinkingContent, s as AssistantMessageEventStreamContract } from "./types-DvzmWW8J.mjs";
2
2
  //#region packages/llm-core/src/utils/event-stream.d.ts
3
3
  /** Returns only an append whose current and previously observed snapshots still match. */
4
4
  declare function readAssistantThinkingAppend(block: ThinkingContent, previous: string): string | undefined;
@@ -1,3 +1,3 @@
1
- import { n as EventStream, r as createAssistantMessageEventStream, t as AssistantMessageEventStream } from "./event-stream-DOPFYVqs.mjs";
2
- import "./event-stream-CMQfX_yr.mjs";
1
+ import { n as EventStream, r as createAssistantMessageEventStream, t as AssistantMessageEventStream } from "./event-stream-DrRM_90c.mjs";
2
+ import "./event-stream-DqDQWqiy.mjs";
3
3
  export { AssistantMessageEventStream, EventStream, createAssistantMessageEventStream };
@@ -1,2 +1,2 @@
1
- import { i as createAssistantMessageEventStream, n as EventStream, t as AssistantMessageEventStream } from "./event-stream-vd9UnCAU.mjs";
1
+ import { a as createAssistantMessageEventStream, n as EventStream, t as AssistantMessageEventStream } from "./event-stream-C5AbCAaZ.mjs";
2
2
  export { AssistantMessageEventStream, EventStream, createAssistantMessageEventStream };
@@ -1,7 +1,9 @@
1
+ import { f as hasRuntimeContextMarker } from "./types-CQc6JNG4.mjs";
2
+ import "./types.mjs";
1
3
  //#region packages/ai/src/providers/github-copilot-request-facts.ts
2
4
  /** Request facts shared by Copilot transports; identity headers remain plugin-owned. */
3
5
  function projectCopilotRequestFacts(messages, contentMode, hasImages) {
4
- const last = messages.at(-1);
6
+ const last = messages.findLast((message) => !hasRuntimeContextMarker(message));
5
7
  return {
6
8
  initiator: last && (last.role !== "user" || contentMode === "nested" && containsContentType(last.content, "tool_result")) ? "agent" : "user",
7
9
  hasImages: hasImages ?? messages.some((message) => (message.role === "user" || message.role === "toolResult") && Array.isArray(message.content) && message.content.some((item) => containsContentType(item, "image", contentMode)))
@@ -1,11 +1,13 @@
1
- import { t as AssistantMessageEventStream } from "./event-stream-vd9UnCAU.mjs";
2
- import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-CHi3X87F.mjs";
3
- import { f as mergeTransportHeaders } from "./transport-stream-shared-Dh5qKJ8e.mjs";
4
- import { n as buildBaseOptions } from "./simple-options-CGAkCwtM.mjs";
1
+ import { t as AssistantMessageEventStream } from "./event-stream-C5AbCAaZ.mjs";
2
+ import { a as resolveAiTransportHeaderSentinels, r as getAiTransportHost } from "./host-DCW52iHe.mjs";
3
+ import { n as buildManagedModelFetch } from "./host-policy-B3jc4Rpn.mjs";
4
+ import { f as mergeTransportHeaders } from "./transport-stream-shared-CxXXz_Dd.mjs";
5
+ import { n as buildBaseOptions } from "./simple-options-BkKTXxhp.mjs";
5
6
  import { n as getEnvApiKey } from "./env-api-keys-CyX4VKGO.mjs";
6
- import { n as createAssistantOutput } from "./provider-transcript-transform-JbFbHV8h.mjs";
7
- import { n as resolveOpencodeSessionHeaders } from "./session-affinity-Bcunsn4I.mjs";
8
- import { i as runGoogleGenerateContentLifecycle, r as buildGoogleSimpleThinking, t as buildGoogleGenerateContentParams } from "./google-shared-Y2YfotEu.mjs";
7
+ import { t as createAssistantOutput } from "./assistant-output-OLm-Oln0.mjs";
8
+ import { n as resolveOpencodeSessionHeaders } from "./session-affinity-DA4WHv1h.mjs";
9
+ import { t as requireApiKey } from "./required-api-key-D4kn3252.mjs";
10
+ import { i as runGoogleGenerateContentLifecycle, r as buildGoogleSimpleThinking, t as buildGoogleGenerateContentParams } from "./google-shared-Eql1OMPU.mjs";
9
11
  import { GoogleGenAI } from "@google/genai";
10
12
  //#region packages/ai/src/providers/google.ts
11
13
  let toolCallCounter = 0;
@@ -26,8 +28,7 @@ const streamGoogle = (model, context, options) => {
26
28
  return stream;
27
29
  };
28
30
  const streamSimpleGoogle = (model, context, options) => {
29
- const apiKey = options?.apiKey || getEnvApiKey(model.provider);
30
- if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
31
+ const apiKey = requireApiKey(model.provider, options?.apiKey);
31
32
  const base = buildBaseOptions(model, options, apiKey);
32
33
  return streamGoogle(model, context, {
33
34
  ...base,
@@ -36,6 +37,8 @@ const streamSimpleGoogle = (model, context, options) => {
36
37
  };
37
38
  function createClient(model, apiKey, optionsHeaders) {
38
39
  const httpOptions = {};
40
+ const fetcher = buildManagedModelFetch(model);
41
+ if (fetcher) httpOptions.fetch = fetcher;
39
42
  if (model.baseUrl) {
40
43
  httpOptions.baseUrl = model.baseUrl;
41
44
  httpOptions.apiVersion = "";