@openclaw/ai 0.0.0 → 2026.7.1-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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -3
  3. package/dist/anthropic-B5gZQM5X.mjs +1383 -0
  4. package/dist/api-registry-BXYnCOIR.d.mts +33 -0
  5. package/dist/azure-openai-responses-DNoSk8Uy.mjs +141 -0
  6. package/dist/azure-openai-responses-client-compat-a_O_GVQV.mjs +41 -0
  7. package/dist/diagnostics-BaTA9eVl.d.mts +25 -0
  8. package/dist/diagnostics-COpOtRwq.mjs +36 -0
  9. package/dist/diagnostics.d.mts +2 -0
  10. package/dist/diagnostics.mjs +2 -0
  11. package/dist/env-api-keys-CtMlqaQ4.mjs +171 -0
  12. package/dist/event-stream-0nZeBKl2.d.mts +26 -0
  13. package/dist/event-stream-ReMmOTzX.mjs +65 -0
  14. package/dist/event-stream.d.mts +2 -0
  15. package/dist/event-stream.mjs +2 -0
  16. package/dist/github-copilot-headers-BsH5cqGj.mjs +48 -0
  17. package/dist/google-D6sIQ1bL.mjs +55 -0
  18. package/dist/google-shared-ZPSl2qTi.mjs +548 -0
  19. package/dist/google-vertex-rDGwkoZK.mjs +111 -0
  20. package/dist/hash-CHgqbJmD.mjs +16 -0
  21. package/dist/headers-B_e4-1J0.mjs +9 -0
  22. package/dist/host-4t713IeR.mjs +37 -0
  23. package/dist/index-BoTnz8cv.d.mts +74 -0
  24. package/dist/index.d.mts +69 -0
  25. package/dist/index.mjs +7 -0
  26. package/dist/internal/anthropic.d.mts +234 -0
  27. package/dist/internal/anthropic.mjs +4 -0
  28. package/dist/internal/openai.d.mts +244 -0
  29. package/dist/internal/openai.mjs +7 -0
  30. package/dist/internal/runtime.d.mts +245 -0
  31. package/dist/internal/runtime.mjs +176 -0
  32. package/dist/internal/shared.d.mts +48 -0
  33. package/dist/internal/shared.mjs +3 -0
  34. package/dist/json-parse-DzNSIQBq.mjs +134 -0
  35. package/dist/llm-request-activity-CehVkZP-.mjs +35 -0
  36. package/dist/mistral-CePVNdws.mjs +563 -0
  37. package/dist/model-utils-DgmOla96.mjs +69 -0
  38. package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +39 -0
  39. package/dist/openai-chatgpt-responses-DVC4Bk_A.mjs +1068 -0
  40. package/dist/openai-completions-B9QLIq2U.mjs +844 -0
  41. package/dist/openai-responses-B6LylGxM.mjs +136 -0
  42. package/dist/openai-responses-shared-sj2YUPYc.mjs +1944 -0
  43. package/dist/openai-tool-projection-BknoV11q.mjs +195 -0
  44. package/dist/providers.d.mts +11 -0
  45. package/dist/providers.mjs +109 -0
  46. package/dist/reasoning-tag-text-partitioner-axhAdUwg.mjs +394 -0
  47. package/dist/sanitize-unicode-BZiVbGwK.d.mts +24 -0
  48. package/dist/sanitize-unicode-DT5o51ur.mjs +26 -0
  49. package/dist/src-CZ503MYJ.mjs +99 -0
  50. package/dist/stream-CREqxHgU.mjs +74 -0
  51. package/dist/stream-first-event-timeout-RjWszj8c.mjs +106 -0
  52. package/dist/streaming-byte-guard-BrbkbwUu.mjs +46 -0
  53. package/dist/tool-schema-json-projection-BXtBc_mD.mjs +74 -0
  54. package/dist/transform-messages-BhGF_fF4.mjs +507 -0
  55. package/dist/types-BVVgDSdq.d.mts +1 -0
  56. package/dist/types-DRgdPqaZ.d.mts +587 -0
  57. package/dist/types.d.mts +6 -0
  58. package/dist/types.mjs +5 -0
  59. package/dist/validation-BDMWOr8d.d.mts +9 -0
  60. package/dist/validation-FrchoOlv.mjs +199 -0
  61. package/dist/validation.d.mts +2 -0
  62. package/dist/validation.mjs +2 -0
  63. package/npm-shrinkwrap.json +645 -0
  64. package/package.json +75 -3
@@ -0,0 +1,176 @@
1
+ import { n as getEnvApiKey, t as findEnvKeys } from "../env-api-keys-CtMlqaQ4.mjs";
2
+ import { n as createApiRegistry, t as createLlmRuntime } from "../stream-CREqxHgU.mjs";
3
+ import { a as modelsAreEqual, i as getSupportedThinkingLevels, n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "../model-utils-DgmOla96.mjs";
4
+ import { n as onLlmRequestActivity, r as createDeferredEventBuffer, t as notifyLlmRequestActivity } from "../llm-request-activity-CehVkZP-.mjs";
5
+ import { t as headersToRecord } from "../headers-B_e4-1J0.mjs";
6
+ import { n as parseStreamingJson, r as repairJson, t as parseJsonWithRepair } from "../json-parse-DzNSIQBq.mjs";
7
+ import { t as sanitizeSurrogates } from "../sanitize-unicode-DT5o51ur.mjs";
8
+ import { t as createReasoningTagTextPartitioner } from "../reasoning-tag-text-partitioner-axhAdUwg.mjs";
9
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, n as createFirstStreamEventTimeoutError, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "../stream-first-event-timeout-RjWszj8c.mjs";
10
+ import { t as shortHash } from "../hash-CHgqbJmD.mjs";
11
+ import { i as registerSessionResourceCleanup, n as resolveOpenAICodexAccountId, r as cleanupSessionResources, t as decodeOpenAICodexJwtPayload } from "../openai-chatgpt-jwt-DhAAzLkj.mjs";
12
+ import { t as createSseByteGuard } from "../streaming-byte-guard-BrbkbwUu.mjs";
13
+ //#region packages/ai/src/internal/default-runtime.ts
14
+ const DEFAULT_RUNTIME_KEY = Symbol.for("openclaw.ai.defaultRuntime");
15
+ function resolveDefaultRuntime() {
16
+ const globalStore = globalThis;
17
+ if (Object.hasOwn(globalStore, DEFAULT_RUNTIME_KEY)) return globalStore[DEFAULT_RUNTIME_KEY];
18
+ const registry = createApiRegistry();
19
+ const state = {
20
+ registry,
21
+ runtime: createLlmRuntime(registry)
22
+ };
23
+ globalStore[DEFAULT_RUNTIME_KEY] = state;
24
+ return state;
25
+ }
26
+ const defaultRuntime = resolveDefaultRuntime();
27
+ const defaultApiRegistry = defaultRuntime.registry;
28
+ const defaultLlmRuntime = defaultRuntime.runtime;
29
+ const { registerApiProvider, getApiProvider, getApiProviders, unregisterApiProviders, clearApiProviders } = defaultApiRegistry;
30
+ const { stream, complete, streamSimple, completeSimple } = defaultLlmRuntime;
31
+ //#endregion
32
+ //#region packages/ai/src/utils/overflow.ts
33
+ const CONFIGURED_CONTEXT_SIZE_OVERFLOW_RE = /prompt has [\d,]+ tokens?, but the configured context size is [\d,]+ tokens?/i;
34
+ /** Detects DS4-style raw token-count context overflow errors. */
35
+ function isConfiguredContextSizeOverflowError(errorMessage) {
36
+ return CONFIGURED_CONTEXT_SIZE_OVERFLOW_RE.test(errorMessage);
37
+ }
38
+ /**
39
+ * Regex patterns to detect context overflow errors from different providers.
40
+ *
41
+ * These patterns match error messages returned when the input exceeds
42
+ * the model's context window.
43
+ *
44
+ * Provider-specific patterns (with example error messages):
45
+ *
46
+ * - Anthropic: "prompt is too long: 213462 tokens > 200000 maximum"
47
+ * - Anthropic: "413 {\"error\":{\"type\":\"request_too_large\",\"message\":\"Request exceeds the maximum size\"}}"
48
+ * - OpenAI: "Your input exceeds the context window of this model"
49
+ * - OpenAI/LiteLLM: "Requested token count exceeds the model's maximum context length of 131072 tokens"
50
+ * - Google: "The input token count (1196265) exceeds the maximum number of tokens allowed (1048575)"
51
+ * - xAI: "This model's maximum prompt length is 131072 but the request contains 537812 tokens"
52
+ * - Groq: "Please reduce the length of the messages or completion"
53
+ * - OpenRouter: "This endpoint's maximum context length is X tokens. However, you requested about Y tokens"
54
+ * - Together AI: "The input (X tokens) is longer than the model's context length (Y tokens)."
55
+ * - llama.cpp: "the request exceeds the available context size, try increasing it"
56
+ * - LM Studio: "tokens to keep from the initial prompt is greater than the context length"
57
+ * - GitHub Copilot: "prompt token count of X exceeds the limit of Y"
58
+ * - MiniMax: "invalid params, context window exceeds limit"
59
+ * - Kimi For Coding: "Your request exceeded model token limit: X (requested: Y)"
60
+ * - Cerebras: "400/413 status code (no body)"
61
+ * - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
62
+ * - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow
63
+ * - Xiaomi MiMo: Truncates input to fill contextWindow exactly, then returns finish_reason "length"
64
+ * with output=0 (no room left to generate). Detected via stopReason "length" + zero output +
65
+ * input filling the context window.
66
+ * - Ollama: Some deployments truncate silently, others return errors like "prompt too long; exceeded max context length by X tokens"
67
+ */
68
+ const OVERFLOW_PATTERNS = [
69
+ /prompt is too long/i,
70
+ /request_too_large/i,
71
+ /input is too long for requested model/i,
72
+ /exceeds the context window/i,
73
+ /exceeds (?:the )?(?:model'?s )?maximum context length of [\d,]+ tokens?/i,
74
+ /input token count.*exceeds the maximum/i,
75
+ /maximum prompt length is \d+/i,
76
+ /reduce the length of the messages/i,
77
+ /maximum context length is \d+ tokens/i,
78
+ /input \(\d+ tokens\) is longer than the model'?s context length \(\d+ tokens\)/i,
79
+ /exceeds the limit of \d+/i,
80
+ /exceeds the available context size/i,
81
+ /greater than the context length/i,
82
+ /context window exceeds limit/i,
83
+ /exceeded model token limit/i,
84
+ /too large for model with \d+ maximum context length/i,
85
+ CONFIGURED_CONTEXT_SIZE_OVERFLOW_RE,
86
+ /model_context_window_exceeded/i,
87
+ /prompt too long; exceeded (?:max )?context length/i,
88
+ /context[_ ]length[_ ]exceeded/i,
89
+ /too many tokens/i,
90
+ /token limit exceeded/i,
91
+ /^4(?:00|13)\s*(?:status code)?\s*\(no body\)/i
92
+ ];
93
+ /**
94
+ * Patterns that indicate non-overflow errors (e.g. rate limiting, server errors).
95
+ * Error messages matching unknown of these are excluded from overflow detection
96
+ * even if they also match an OVERFLOW_PATTERN.
97
+ *
98
+ * Example: Bedrock formats throttling errors as "ThrottlingException: Too many tokens,
99
+ * please wait before trying again." which would match the /too many tokens/i overflow
100
+ * pattern without this exclusion.
101
+ */
102
+ const NON_OVERFLOW_PATTERNS = [
103
+ /^(Throttling error|Service unavailable):/i,
104
+ /rate limit/i,
105
+ /too many requests/i
106
+ ];
107
+ function resolveContextInputTokens(message) {
108
+ if (message.usage.contextUsage?.state === "available") return message.usage.contextUsage.promptTokens;
109
+ if (message.usage.contextUsage?.state === "unavailable") return;
110
+ return message.usage.input + message.usage.cacheRead;
111
+ }
112
+ /**
113
+ * Check if an assistant message represents a context overflow error.
114
+ *
115
+ * This handles two cases:
116
+ * 1. Error-based overflow: Most providers return stopReason "error" with a
117
+ * specific error message pattern.
118
+ * 2. Silent overflow: Some providers accept overflow requests and return
119
+ * successfully. For these, we check if usage.input exceeds the context window.
120
+ *
121
+ * ## Reliability by Provider
122
+ *
123
+ * **Reliable detection (returns error with detectable message):**
124
+ * - Anthropic: "prompt is too long: X tokens > Y maximum" or "request_too_large"
125
+ * - OpenAI (Completions & Responses): "exceeds the context window" or "exceeds the model's maximum context length of X tokens"
126
+ * - Google Gemini: "input token count exceeds the maximum"
127
+ * - xAI (Grok): "maximum prompt length is X but request contains Y"
128
+ * - Groq: "reduce the length of the messages"
129
+ * - Cerebras: 400/413 status code (no body)
130
+ * - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
131
+ * - OpenRouter (all backends): "maximum context length is X tokens"
132
+ * - Together AI: "The input (X tokens) is longer than the model's context length (Y tokens)."
133
+ * - llama.cpp: "exceeds the available context size"
134
+ * - LM Studio: "greater than the context length"
135
+ * - Kimi For Coding: "exceeded model token limit: X (requested: Y)"
136
+ *
137
+ * **Unreliable detection:**
138
+ * - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),
139
+ * sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.
140
+ * - Xiaomi MiMo: Truncates input to fit contextWindow then returns stopReason "length" with
141
+ * output=0. Pass contextWindow param to detect via the "filled context + zero output" signal.
142
+ * - Ollama: May truncate input silently for some setups, but may also return explicit
143
+ * overflow errors that match the patterns above. Silent truncation still cannot be
144
+ * detected here because we do not know the expected token count.
145
+ *
146
+ * ## Custom Providers
147
+ *
148
+ * If you've added custom models via settings.json, this function may not detect
149
+ * overflow errors from those providers. To add support:
150
+ *
151
+ * 1. Send a request that exceeds the model's context window
152
+ * 2. Check the errorMessage in the response
153
+ * 3. Create a regex pattern that matches the error
154
+ * 4. The pattern should be added to OVERFLOW_PATTERNS in this file, or
155
+ * check the errorMessage yourself before calling this function
156
+ *
157
+ * @param message - The assistant message to check
158
+ * @param contextWindow - Optional context window size for detecting silent overflow (z.ai)
159
+ * @returns true if the message indicates a context overflow
160
+ */
161
+ function isContextOverflow(message, contextWindow) {
162
+ if (message.stopReason === "error" && message.errorMessage) {
163
+ if (!NON_OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage)) && OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage))) return true;
164
+ }
165
+ if (contextWindow && message.stopReason === "stop") {
166
+ const inputTokens = resolveContextInputTokens(message);
167
+ if (inputTokens !== void 0 && inputTokens > contextWindow) return true;
168
+ }
169
+ if (contextWindow && message.stopReason === "length" && message.usage.output === 0) {
170
+ const inputTokens = resolveContextInputTokens(message);
171
+ if (inputTokens !== void 0 && inputTokens >= contextWindow * .99) return true;
172
+ }
173
+ return false;
174
+ }
175
+ //#endregion
176
+ export { applyProviderReportedUsageCost, calculateCost, clampThinkingLevel, cleanupSessionResources, clearApiProviders, complete, completeSimple, createDeferredEventBuffer, createFirstStreamEventAbortController, createFirstStreamEventTimeoutError, createReasoningTagTextPartitioner, createSseByteGuard, decodeOpenAICodexJwtPayload, defaultApiRegistry, defaultLlmRuntime, findEnvKeys, getApiProvider, getApiProviders, getEnvApiKey, getFirstStreamEventTimeoutHandler, getFirstStreamEventTimeoutMs, getSupportedThinkingLevels, headersToRecord, isConfiguredContextSizeOverflowError, isContextOverflow, modelsAreEqual, notifyLlmRequestActivity, onLlmRequestActivity, parseJsonWithRepair, parseStreamingJson, registerApiProvider, registerSessionResourceCleanup, repairJson, resolveOpenAICodexAccountId, sanitizeSurrogates, shortHash, stream, streamSimple, unregisterApiProviders, withFirstStreamEventTimeout };
@@ -0,0 +1,48 @@
1
+ import { E as Model, F as SimpleStreamOptions, H as ThinkingBudgets, T as Message, W as ThinkingLevel, i as AssistantMessage, n as Api, z as StreamOptions } from "../types-DRgdPqaZ.mjs";
2
+ import { t as sanitizeSurrogates } from "../sanitize-unicode-BZiVbGwK.mjs";
3
+
4
+ //#region packages/ai/src/providers/simple-options.d.ts
5
+ type FirstEventStreamOptions = {
6
+ firstEventTimeoutMs?: number;
7
+ onFirstEventTimeout?: (reason: Error) => void;
8
+ };
9
+ declare function buildBaseOptions(model: Model, options?: SimpleStreamOptions, apiKey?: string): StreamOptions & FirstEventStreamOptions;
10
+ declare function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, "xhigh"> | undefined;
11
+ declare function adjustMaxTokensForThinking(baseMaxTokens: number | undefined, modelMaxTokens: number, reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): {
12
+ maxTokens: number;
13
+ thinkingBudget: number;
14
+ };
15
+ //#endregion
16
+ //#region packages/ai/src/providers/tool-result-text.d.ts
17
+ declare function describeToolResultMediaPlaceholder(blocks: readonly unknown[]): string | undefined;
18
+ declare function extractToolResultBlockText(block: unknown): string | undefined;
19
+ declare function extractToolResultText(blocks: readonly unknown[]): string;
20
+ //#endregion
21
+ //#region packages/ai/src/providers/transform-messages.d.ts
22
+ /**
23
+ * Normalize tool call ID for cross-provider compatibility.
24
+ * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
25
+ * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
26
+ */
27
+ declare function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>, normalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string): Message[];
28
+ //#endregion
29
+ //#region packages/ai/src/utils/prompt-cache-stability.d.ts
30
+ /** Normalize structured prompt text before hashing or snapshot comparison. */
31
+ declare function normalizeStructuredPromptSection(text: string): string;
32
+ /** Normalize, de-dupe, and sort capability ids for stable prompt payloads. */
33
+ declare function normalizePromptCapabilityIds(capabilities: ReadonlyArray<string>): string[];
34
+ //#endregion
35
+ //#region packages/ai/src/utils/system-prompt-cache-boundary.d.ts
36
+ declare const SYSTEM_PROMPT_CACHE_BOUNDARY = "\n<!-- OPENCLAW_CACHE_BOUNDARY -->\n";
37
+ declare function stripSystemPromptCacheBoundary(text: string): string;
38
+ declare function ensureSystemPromptCacheBoundary(systemPrompt: string): string;
39
+ declare function splitSystemPromptCacheBoundary(text: string): {
40
+ stablePrefix: string;
41
+ dynamicSuffix: string;
42
+ } | undefined;
43
+ declare function prependSystemPromptAdditionAfterCacheBoundary(params: {
44
+ systemPrompt: string;
45
+ systemPromptAddition?: string;
46
+ }): string;
47
+ //#endregion
48
+ export { SYSTEM_PROMPT_CACHE_BOUNDARY, adjustMaxTokensForThinking, buildBaseOptions, clampReasoning, describeToolResultMediaPlaceholder, ensureSystemPromptCacheBoundary, extractToolResultBlockText, extractToolResultText, normalizePromptCapabilityIds, normalizeStructuredPromptSection, prependSystemPromptAdditionAfterCacheBoundary, sanitizeSurrogates, splitSystemPromptCacheBoundary, stripSystemPromptCacheBoundary, transformMessages };
@@ -0,0 +1,3 @@
1
+ import { t as sanitizeSurrogates } from "../sanitize-unicode-DT5o51ur.mjs";
2
+ import { S as normalizeStructuredPromptSection, _ as ensureSystemPromptCacheBoundary, a as adjustMaxTokensForThinking, b as stripSystemPromptCacheBoundary, g as SYSTEM_PROMPT_CACHE_BOUNDARY, i as extractToolResultText, n as describeToolResultMediaPlaceholder, o as buildBaseOptions, r as extractToolResultBlockText, s as clampReasoning, t as transformMessages, v as prependSystemPromptAdditionAfterCacheBoundary, x as normalizePromptCapabilityIds, y as splitSystemPromptCacheBoundary } from "../transform-messages-BhGF_fF4.mjs";
3
+ export { SYSTEM_PROMPT_CACHE_BOUNDARY, adjustMaxTokensForThinking, buildBaseOptions, clampReasoning, describeToolResultMediaPlaceholder, ensureSystemPromptCacheBoundary, extractToolResultBlockText, extractToolResultText, normalizePromptCapabilityIds, normalizeStructuredPromptSection, prependSystemPromptAdditionAfterCacheBoundary, sanitizeSurrogates, splitSystemPromptCacheBoundary, stripSystemPromptCacheBoundary, transformMessages };
@@ -0,0 +1,134 @@
1
+ import { parse } from "partial-json";
2
+ //#region packages/ai/src/utils/json-parse.ts
3
+ const VALID_JSON_ESCAPES = /* @__PURE__ */ new Set([
4
+ "\"",
5
+ "\\",
6
+ "/",
7
+ "b",
8
+ "f",
9
+ "n",
10
+ "r",
11
+ "t",
12
+ "u"
13
+ ]);
14
+ const JSON_CONTROL_ESCAPES = /* @__PURE__ */ new Set([
15
+ "b",
16
+ "f",
17
+ "n",
18
+ "r",
19
+ "t"
20
+ ]);
21
+ function isControlCharacter(char) {
22
+ const codePoint = char.codePointAt(0);
23
+ return codePoint !== void 0 && codePoint >= 0 && codePoint <= 31;
24
+ }
25
+ function escapeControlCharacter(char) {
26
+ switch (char) {
27
+ case "\b": return "\\b";
28
+ case "\f": return "\\f";
29
+ case "\n": return "\\n";
30
+ case "\r": return "\\r";
31
+ case " ": return "\\t";
32
+ default: return `\\u${char.codePointAt(0)?.toString(16).padStart(4, "0") ?? "0000"}`;
33
+ }
34
+ }
35
+ /**
36
+ * Repairs malformed JSON string literals by:
37
+ * - escaping raw control characters inside strings
38
+ * - doubling backslashes before invalid escape characters
39
+ */
40
+ function repairJson(json) {
41
+ let repaired = "";
42
+ let inString = false;
43
+ let stringValuePrefix = "";
44
+ for (let index = 0; index < json.length; index++) {
45
+ const char = json[index];
46
+ if (!inString) {
47
+ repaired += char;
48
+ if (char === "\"") {
49
+ inString = true;
50
+ stringValuePrefix = "";
51
+ }
52
+ continue;
53
+ }
54
+ if (char === "\"") {
55
+ repaired += char;
56
+ inString = false;
57
+ stringValuePrefix = "";
58
+ continue;
59
+ }
60
+ if (char === "\\") {
61
+ const nextChar = json[index + 1];
62
+ if (nextChar === void 0) {
63
+ repaired += "\\\\";
64
+ continue;
65
+ }
66
+ if (nextChar === "u") {
67
+ const unicodeDigits = json.slice(index + 2, index + 6);
68
+ if (/^[0-9a-fA-F]{4}$/.test(unicodeDigits)) {
69
+ repaired += `\\u${unicodeDigits}`;
70
+ stringValuePrefix += `\\u${unicodeDigits}`;
71
+ index += 5;
72
+ continue;
73
+ }
74
+ repaired += "\\\\";
75
+ stringValuePrefix += "\\";
76
+ continue;
77
+ }
78
+ if (JSON_CONTROL_ESCAPES.has(nextChar) && looksLikeWindowsPathPrefix(stringValuePrefix)) {
79
+ repaired += "\\\\";
80
+ stringValuePrefix += "\\";
81
+ continue;
82
+ }
83
+ if (VALID_JSON_ESCAPES.has(nextChar)) {
84
+ repaired += `\\${nextChar}`;
85
+ stringValuePrefix += nextChar === "\\" ? "\\" : `\\${nextChar}`;
86
+ index += 1;
87
+ continue;
88
+ }
89
+ repaired += "\\\\";
90
+ stringValuePrefix += "\\";
91
+ continue;
92
+ }
93
+ repaired += isControlCharacter(char) ? escapeControlCharacter(char) : char;
94
+ stringValuePrefix += char;
95
+ }
96
+ return repaired;
97
+ }
98
+ function parseJsonWithRepair(json) {
99
+ const repairedJson = repairJson(json);
100
+ if (repairedJson !== json) return JSON.parse(repairedJson);
101
+ return JSON.parse(json);
102
+ }
103
+ function looksLikeWindowsPathPrefix(prefix) {
104
+ const tail = prefix.slice(-160);
105
+ return /(?:^|[^A-Za-z0-9])[A-Za-z]:(?:[\\/][^"\\/:*?<>|\r\n]*)*$/.test(tail);
106
+ }
107
+ function asStreamingJsonRecord(value) {
108
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
109
+ }
110
+ /**
111
+ * Attempts to parse potentially incomplete JSON during streaming.
112
+ * Always returns a valid object, even if the JSON is incomplete.
113
+ *
114
+ * @param partialJson The partial JSON string from streaming
115
+ * @returns Parsed object or empty object if parsing fails
116
+ */
117
+ function parseStreamingJson(partialJson) {
118
+ if (!partialJson || partialJson.trim() === "") return {};
119
+ try {
120
+ return asStreamingJsonRecord(parseJsonWithRepair(partialJson));
121
+ } catch {
122
+ try {
123
+ return asStreamingJsonRecord(parse(partialJson));
124
+ } catch {
125
+ try {
126
+ return asStreamingJsonRecord(parse(repairJson(partialJson)));
127
+ } catch {
128
+ return {};
129
+ }
130
+ }
131
+ }
132
+ }
133
+ //#endregion
134
+ export { parseStreamingJson as n, repairJson as r, parseJsonWithRepair as t };
@@ -0,0 +1,35 @@
1
+ //#region packages/ai/src/utils/deferred-event-buffer.ts
2
+ function createDeferredEventBuffer(sink, onBufferedEvent) {
3
+ let events = [];
4
+ return {
5
+ push(event) {
6
+ events.push(event);
7
+ onBufferedEvent?.();
8
+ },
9
+ flush() {
10
+ for (const event of events) sink.push(event);
11
+ events = [];
12
+ },
13
+ discard() {
14
+ events = [];
15
+ }
16
+ };
17
+ }
18
+ //#endregion
19
+ //#region packages/ai/src/utils/llm-request-activity.ts
20
+ const requestActivityListeners = /* @__PURE__ */ new WeakMap();
21
+ function notifyLlmRequestActivity(signal) {
22
+ if (!signal) return;
23
+ for (const listener of requestActivityListeners.get(signal) ?? []) listener();
24
+ }
25
+ function onLlmRequestActivity(signal, listener) {
26
+ const listeners = requestActivityListeners.get(signal) ?? /* @__PURE__ */ new Set();
27
+ listeners.add(listener);
28
+ requestActivityListeners.set(signal, listeners);
29
+ return () => {
30
+ listeners.delete(listener);
31
+ if (listeners.size === 0) requestActivityListeners.delete(signal);
32
+ };
33
+ }
34
+ //#endregion
35
+ export { onLlmRequestActivity as n, createDeferredEventBuffer as r, notifyLlmRequestActivity as t };