@pellux/goodvibes-sdk 0.34.0 → 0.34.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 (189) hide show
  1. package/dist/contracts/artifacts/operator-contract.json +1 -1
  2. package/dist/events/workflows.d.ts +4 -0
  3. package/dist/events/workflows.d.ts.map +1 -1
  4. package/dist/platform/agents/message-bus-core.d.ts +11 -0
  5. package/dist/platform/agents/message-bus-core.d.ts.map +1 -1
  6. package/dist/platform/agents/message-bus-core.js +28 -21
  7. package/dist/platform/agents/orchestrator-runner.d.ts.map +1 -1
  8. package/dist/platform/agents/orchestrator-runner.js +6 -4
  9. package/dist/platform/agents/wrfc-config.d.ts.map +1 -1
  10. package/dist/platform/agents/wrfc-config.js +16 -10
  11. package/dist/platform/agents/wrfc-controller.d.ts +26 -0
  12. package/dist/platform/agents/wrfc-controller.d.ts.map +1 -1
  13. package/dist/platform/agents/wrfc-controller.js +134 -138
  14. package/dist/platform/agents/wrfc-runtime-events.d.ts +1 -0
  15. package/dist/platform/agents/wrfc-runtime-events.d.ts.map +1 -1
  16. package/dist/platform/agents/wrfc-runtime-events.js +4 -1
  17. package/dist/platform/automation/delivery-manager.d.ts.map +1 -1
  18. package/dist/platform/automation/delivery-manager.js +1 -6
  19. package/dist/platform/batch/manager.d.ts.map +1 -1
  20. package/dist/platform/batch/manager.js +1 -3
  21. package/dist/platform/channels/policy-manager.d.ts.map +1 -1
  22. package/dist/platform/channels/policy-manager.js +1 -3
  23. package/dist/platform/channels/reply-pipeline.d.ts.map +1 -1
  24. package/dist/platform/channels/reply-pipeline.js +4 -0
  25. package/dist/platform/config/schema-domain-core.d.ts +1 -1
  26. package/dist/platform/config/schema-domain-core.d.ts.map +1 -1
  27. package/dist/platform/config/schema-domain-core.js +12 -12
  28. package/dist/platform/config/schema-domain-runtime.d.ts +1 -1
  29. package/dist/platform/config/schema-domain-runtime.d.ts.map +1 -1
  30. package/dist/platform/config/schema-domain-runtime.js +19 -18
  31. package/dist/platform/config/schema-domain-surfaces.d.ts +1 -1
  32. package/dist/platform/config/schema-domain-surfaces.d.ts.map +1 -1
  33. package/dist/platform/config/schema-domain-surfaces.js +4 -3
  34. package/dist/platform/config/schema-shared.d.ts +6 -0
  35. package/dist/platform/config/schema-shared.d.ts.map +1 -1
  36. package/dist/platform/config/schema-shared.js +21 -1
  37. package/dist/platform/control-plane/approval-broker.d.ts.map +1 -1
  38. package/dist/platform/control-plane/approval-broker.js +1 -3
  39. package/dist/platform/control-plane/session-broker-state.d.ts.map +1 -1
  40. package/dist/platform/control-plane/session-broker-state.js +1 -3
  41. package/dist/platform/core/compaction-sections.d.ts +5 -1
  42. package/dist/platform/core/compaction-sections.d.ts.map +1 -1
  43. package/dist/platform/core/compaction-sections.js +73 -66
  44. package/dist/platform/core/context-compaction.d.ts.map +1 -1
  45. package/dist/platform/core/context-compaction.js +9 -16
  46. package/dist/platform/core/orchestrator-context-runtime.d.ts +2 -2
  47. package/dist/platform/core/orchestrator-context-runtime.d.ts.map +1 -1
  48. package/dist/platform/core/orchestrator-context-runtime.js +24 -21
  49. package/dist/platform/core/orchestrator-tool-runtime.d.ts.map +1 -1
  50. package/dist/platform/core/orchestrator-tool-runtime.js +2 -1
  51. package/dist/platform/core/session-lineage.d.ts +2 -5
  52. package/dist/platform/core/session-lineage.d.ts.map +1 -1
  53. package/dist/platform/core/session-lineage.js +4 -16
  54. package/dist/platform/core/wrfc-routing.d.ts.map +1 -1
  55. package/dist/platform/core/wrfc-routing.js +1 -3
  56. package/dist/platform/daemon/http/mcp-routes.d.ts.map +1 -1
  57. package/dist/platform/daemon/http/mcp-routes.js +1 -3
  58. package/dist/platform/daemon/http/openai-compatible-routes.d.ts.map +1 -1
  59. package/dist/platform/daemon/http/openai-compatible-routes.js +1 -3
  60. package/dist/platform/daemon/http/runtime-routes.d.ts.map +1 -1
  61. package/dist/platform/daemon/http/runtime-routes.js +1 -3
  62. package/dist/platform/hooks/runners/http.d.ts.map +1 -1
  63. package/dist/platform/hooks/runners/http.js +9 -19
  64. package/dist/platform/integrations/webhooks.js +2 -11
  65. package/dist/platform/knowledge/semantic/self-improvement.d.ts.map +1 -1
  66. package/dist/platform/knowledge/semantic/self-improvement.js +2 -21
  67. package/dist/platform/mcp/client.d.ts.map +1 -1
  68. package/dist/platform/mcp/client.js +1 -3
  69. package/dist/platform/mcp/config.d.ts.map +1 -1
  70. package/dist/platform/mcp/config.js +1 -3
  71. package/dist/platform/media/builtin-generation-providers.d.ts.map +1 -1
  72. package/dist/platform/media/builtin-generation-providers.js +1 -6
  73. package/dist/platform/providers/anthropic-compat.d.ts.map +1 -1
  74. package/dist/platform/providers/anthropic-compat.js +11 -131
  75. package/dist/platform/providers/anthropic-sdk-provider.d.ts.map +1 -1
  76. package/dist/platform/providers/anthropic-sdk-provider.js +8 -42
  77. package/dist/platform/providers/anthropic-sse-assembler.d.ts +80 -0
  78. package/dist/platform/providers/anthropic-sse-assembler.d.ts.map +1 -0
  79. package/dist/platform/providers/anthropic-sse-assembler.js +146 -0
  80. package/dist/platform/providers/anthropic-stream.d.ts +30 -0
  81. package/dist/platform/providers/anthropic-stream.d.ts.map +1 -0
  82. package/dist/platform/providers/anthropic-stream.js +44 -0
  83. package/dist/platform/providers/anthropic-vertex.d.ts.map +1 -1
  84. package/dist/platform/providers/anthropic-vertex.js +1 -3
  85. package/dist/platform/providers/anthropic.d.ts.map +1 -1
  86. package/dist/platform/providers/anthropic.js +15 -151
  87. package/dist/platform/providers/capabilities.d.ts.map +1 -1
  88. package/dist/platform/providers/capabilities.js +11 -7
  89. package/dist/platform/providers/context-discovery.d.ts.map +1 -1
  90. package/dist/platform/providers/context-discovery.js +9 -16
  91. package/dist/platform/providers/context-window-fallback.d.ts +24 -0
  92. package/dist/platform/providers/context-window-fallback.d.ts.map +1 -0
  93. package/dist/platform/providers/context-window-fallback.js +48 -0
  94. package/dist/platform/providers/gemini.d.ts.map +1 -1
  95. package/dist/platform/providers/gemini.js +3 -6
  96. package/dist/platform/providers/json-ttl-cache.d.ts +35 -0
  97. package/dist/platform/providers/json-ttl-cache.d.ts.map +1 -0
  98. package/dist/platform/providers/json-ttl-cache.js +52 -0
  99. package/dist/platform/providers/llama-cpp.d.ts.map +1 -1
  100. package/dist/platform/providers/llama-cpp.js +2 -23
  101. package/dist/platform/providers/lm-studio-helpers.d.ts +1 -1
  102. package/dist/platform/providers/lm-studio-helpers.d.ts.map +1 -1
  103. package/dist/platform/providers/lm-studio-helpers.js +5 -25
  104. package/dist/platform/providers/model-benchmarks.d.ts.map +1 -1
  105. package/dist/platform/providers/model-benchmarks.js +11 -34
  106. package/dist/platform/providers/model-catalog-cache.d.ts.map +1 -1
  107. package/dist/platform/providers/model-catalog-cache.js +15 -38
  108. package/dist/platform/providers/model-catalog-synthetic.d.ts.map +1 -1
  109. package/dist/platform/providers/model-catalog-synthetic.js +3 -2
  110. package/dist/platform/providers/model-catalog.d.ts.map +1 -1
  111. package/dist/platform/providers/model-catalog.js +3 -2
  112. package/dist/platform/providers/model-limits.d.ts.map +1 -1
  113. package/dist/platform/providers/model-limits.js +18 -42
  114. package/dist/platform/providers/ollama.d.ts.map +1 -1
  115. package/dist/platform/providers/ollama.js +3 -24
  116. package/dist/platform/providers/openai-codex.d.ts.map +1 -1
  117. package/dist/platform/providers/openai-codex.js +8 -9
  118. package/dist/platform/providers/openai-compat.d.ts.map +1 -1
  119. package/dist/platform/providers/openai-compat.js +13 -40
  120. package/dist/platform/providers/openai-stream-helpers.d.ts +62 -0
  121. package/dist/platform/providers/openai-stream-helpers.d.ts.map +1 -0
  122. package/dist/platform/providers/openai-stream-helpers.js +73 -0
  123. package/dist/platform/providers/openai.d.ts.map +1 -1
  124. package/dist/platform/providers/openai.js +13 -41
  125. package/dist/platform/providers/provider-error.d.ts +17 -0
  126. package/dist/platform/providers/provider-error.d.ts.map +1 -0
  127. package/dist/platform/providers/provider-error.js +33 -0
  128. package/dist/platform/providers/provider-stop-reason.d.ts +15 -0
  129. package/dist/platform/providers/provider-stop-reason.d.ts.map +1 -0
  130. package/dist/platform/providers/provider-stop-reason.js +15 -0
  131. package/dist/platform/providers/sse-line-buffer.d.ts +13 -0
  132. package/dist/platform/providers/sse-line-buffer.d.ts.map +1 -0
  133. package/dist/platform/providers/sse-line-buffer.js +23 -0
  134. package/dist/platform/providers/tool-formats.d.ts +5 -0
  135. package/dist/platform/providers/tool-formats.d.ts.map +1 -1
  136. package/dist/platform/providers/tool-formats.js +14 -0
  137. package/dist/platform/runtime/bootstrap-runtime-events.d.ts.map +1 -1
  138. package/dist/platform/runtime/bootstrap-runtime-events.js +6 -0
  139. package/dist/platform/runtime/bootstrap-services.d.ts.map +1 -1
  140. package/dist/platform/runtime/bootstrap-services.js +4 -5
  141. package/dist/platform/runtime/emitters/workflows.d.ts +4 -0
  142. package/dist/platform/runtime/emitters/workflows.d.ts.map +1 -1
  143. package/dist/platform/runtime/emitters/workflows.js +3 -0
  144. package/dist/platform/runtime/remote/distributed-runtime-store.d.ts.map +1 -1
  145. package/dist/platform/runtime/remote/distributed-runtime-store.js +1 -3
  146. package/dist/platform/runtime/retention/pruner.js +2 -5
  147. package/dist/platform/runtime/store/helpers/reducers/lifecycle.d.ts.map +1 -1
  148. package/dist/platform/runtime/store/helpers/reducers/lifecycle.js +15 -14
  149. package/dist/platform/runtime/store/helpers/reducers/shared.d.ts +6 -0
  150. package/dist/platform/runtime/store/helpers/reducers/shared.d.ts.map +1 -1
  151. package/dist/platform/runtime/store/helpers/reducers/shared.js +8 -1
  152. package/dist/platform/runtime/telemetry/exporters/queue.d.ts.map +1 -1
  153. package/dist/platform/runtime/telemetry/exporters/queue.js +1 -7
  154. package/dist/platform/runtime/transports/http-helpers.d.ts +0 -1
  155. package/dist/platform/runtime/transports/http-helpers.d.ts.map +1 -1
  156. package/dist/platform/runtime/transports/http-helpers.js +1 -3
  157. package/dist/platform/runtime/ui-read-model-helpers.d.ts +2 -0
  158. package/dist/platform/runtime/ui-read-model-helpers.d.ts.map +1 -1
  159. package/dist/platform/runtime/ui-read-model-helpers.js +8 -0
  160. package/dist/platform/runtime/ui-read-models-core.d.ts.map +1 -1
  161. package/dist/platform/runtime/ui-read-models-core.js +3 -5
  162. package/dist/platform/runtime/ui-read-models-observability-remote.d.ts.map +1 -1
  163. package/dist/platform/runtime/ui-read-models-observability-remote.js +2 -4
  164. package/dist/platform/runtime/ui-read-models-operations.d.ts.map +1 -1
  165. package/dist/platform/runtime/ui-read-models-operations.js +8 -26
  166. package/dist/platform/scheduler/scheduler.d.ts.map +1 -1
  167. package/dist/platform/scheduler/scheduler.js +1 -3
  168. package/dist/platform/tools/exec/runtime.d.ts.map +1 -1
  169. package/dist/platform/tools/exec/runtime.js +1 -7
  170. package/dist/platform/tools/fetch/runtime.d.ts.map +1 -1
  171. package/dist/platform/tools/fetch/runtime.js +9 -20
  172. package/dist/platform/tools/shared/process-manager.d.ts.map +1 -1
  173. package/dist/platform/tools/shared/process-manager.js +1 -6
  174. package/dist/platform/utils/concurrency.d.ts +1 -0
  175. package/dist/platform/utils/concurrency.d.ts.map +1 -1
  176. package/dist/platform/utils/concurrency.js +1 -0
  177. package/dist/platform/utils/error-display.d.ts +9 -0
  178. package/dist/platform/utils/error-display.d.ts.map +1 -1
  179. package/dist/platform/utils/error-display.js +11 -0
  180. package/dist/platform/utils/fetch-with-timeout.d.ts +22 -2
  181. package/dist/platform/utils/fetch-with-timeout.d.ts.map +1 -1
  182. package/dist/platform/utils/fetch-with-timeout.js +33 -15
  183. package/dist/platform/utils/record-coerce.d.ts +5 -0
  184. package/dist/platform/utils/record-coerce.d.ts.map +1 -1
  185. package/dist/platform/utils/record-coerce.js +7 -0
  186. package/dist/platform/utils/retry.d.ts.map +1 -1
  187. package/dist/platform/utils/retry.js +2 -4
  188. package/dist/platform/version.js +1 -1
  189. package/package.json +9 -9
@@ -0,0 +1,146 @@
1
+ import { mapAnthropicStopReason } from './stop-reason-maps.js';
2
+ import { fromAnthropicContent, parseToolCallArguments } from './tool-formats.js';
3
+ import { logger } from '../utils/logger.js';
4
+ import { SseLineBuffer } from './sse-line-buffer.js';
5
+ /** Create a fresh zero-valued SSE accumulator. */
6
+ export function createAnthropicSSEState() {
7
+ return {
8
+ responseText: '',
9
+ inputTokens: 0,
10
+ outputTokens: 0,
11
+ cacheReadTokens: 0,
12
+ cacheWriteTokens: 0,
13
+ rawStopReason: undefined,
14
+ stopReason: 'unknown',
15
+ toolBlocks: new Map(),
16
+ };
17
+ }
18
+ /**
19
+ * Dispatch one Anthropic SSE event into the accumulator.
20
+ * Mutates state in place and calls onDelta for real-time delivery.
21
+ */
22
+ export function processAnthropicSSEEvent(event, state, onDelta) {
23
+ if (event.type === 'content_block_start' && event.content_block?.type === 'tool_use') {
24
+ const idx = event.index ?? 0;
25
+ state.toolBlocks.set(idx, {
26
+ id: event.content_block.id ?? '',
27
+ name: event.content_block.name ?? '',
28
+ args: '',
29
+ });
30
+ if (onDelta) {
31
+ onDelta({ toolCalls: [{ index: idx, id: event.content_block.id, name: event.content_block.name }] });
32
+ }
33
+ }
34
+ else if (event.type === 'content_block_delta') {
35
+ const idx = event.index ?? 0;
36
+ if (event.delta?.type === 'text_delta' && event.delta.text) {
37
+ state.responseText += event.delta.text;
38
+ if (onDelta)
39
+ onDelta({ content: event.delta.text });
40
+ }
41
+ else if (event.delta?.type === 'thinking_delta' && event.delta.thinking) {
42
+ if (onDelta)
43
+ onDelta({ reasoning: event.delta.thinking });
44
+ }
45
+ else if (event.delta?.type === 'input_json_delta' && event.delta.partial_json) {
46
+ const block = state.toolBlocks.get(idx);
47
+ if (block)
48
+ block.args += event.delta.partial_json;
49
+ if (onDelta) {
50
+ onDelta({ toolCalls: [{ index: idx, arguments: event.delta.partial_json }] });
51
+ }
52
+ }
53
+ }
54
+ else if (event.type === 'message_delta') {
55
+ if (event.delta?.stop_reason) {
56
+ state.rawStopReason = event.delta.stop_reason;
57
+ state.stopReason = mapAnthropicStopReason(state.rawStopReason);
58
+ }
59
+ if (event.usage?.output_tokens)
60
+ state.outputTokens = event.usage.output_tokens;
61
+ if (event.usage?.cache_read_input_tokens != null)
62
+ state.cacheReadTokens = event.usage.cache_read_input_tokens;
63
+ if (event.usage?.cache_creation_input_tokens != null)
64
+ state.cacheWriteTokens = event.usage.cache_creation_input_tokens;
65
+ }
66
+ else if (event.type === 'message_start') {
67
+ if (event.message?.usage) {
68
+ state.inputTokens = event.message.usage.input_tokens;
69
+ state.outputTokens = event.message.usage.output_tokens;
70
+ state.cacheReadTokens = event.message.usage.cache_read_input_tokens ?? 0;
71
+ state.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;
72
+ }
73
+ }
74
+ }
75
+ /**
76
+ * Read an Anthropic SSE stream to completion, dispatching each event through
77
+ * processAnthropicSSEEvent. Uses SseLineBuffer for correct CRLF handling.
78
+ *
79
+ * @param reader ReadableStream reader from the fetch response body.
80
+ * @param state Accumulator to mutate (created with createAnthropicSSEState).
81
+ * @param onDelta Optional streaming delta callback.
82
+ * @param providerLabel Used in warn logs, e.g. 'Anthropic' or 'AnthropicCompat(my-proxy)'.
83
+ */
84
+ export async function readAnthropicSSEStream(reader, state, onDelta, providerLabel) {
85
+ const sseBuffer = new SseLineBuffer();
86
+ try {
87
+ while (true) {
88
+ const { done, value } = await reader.read();
89
+ if (done)
90
+ break;
91
+ for (const line of sseBuffer.feed(value)) {
92
+ if (!line.startsWith('data: '))
93
+ continue;
94
+ const data = line.slice(6).trim();
95
+ if (!data || data === '[DONE]')
96
+ continue;
97
+ let event;
98
+ try {
99
+ event = JSON.parse(data);
100
+ }
101
+ catch {
102
+ logger.warn(`${providerLabel} SSE: failed to parse JSON chunk`, {
103
+ chunkPreview: data.slice(0, 200),
104
+ chunkLength: data.length,
105
+ });
106
+ continue;
107
+ }
108
+ processAnthropicSSEEvent(event, state, onDelta);
109
+ }
110
+ }
111
+ }
112
+ finally {
113
+ reader.releaseLock();
114
+ }
115
+ }
116
+ /**
117
+ * Assemble the final content + toolCalls from accumulated streaming state.
118
+ * Sorts tool blocks by stream index, parses JSON arguments, and calls
119
+ * fromAnthropicContent to produce the canonical response shape.
120
+ *
121
+ * @param fallbackBlocks Used by the SDK provider: if no streaming content was
122
+ * accumulated, fall back to finalMessage.content instead of returning empty.
123
+ */
124
+ export function assembleAnthropicContentBlocks(toolBlocks, responseText, providerName, fallbackBlocks) {
125
+ const contentBlocks = [];
126
+ if (responseText) {
127
+ contentBlocks.push({ type: 'text', text: responseText });
128
+ }
129
+ for (const [, block] of [...toolBlocks.entries()].sort(([a], [b]) => a - b)) {
130
+ const parsedInput = parseToolCallArguments(block.args, {
131
+ provider: providerName,
132
+ toolName: block.name,
133
+ callId: block.id,
134
+ });
135
+ if (parsedInput === undefined)
136
+ continue;
137
+ contentBlocks.push({
138
+ type: 'tool_use',
139
+ id: block.id,
140
+ name: block.name,
141
+ input: parsedInput,
142
+ });
143
+ }
144
+ const target = contentBlocks.length > 0 ? contentBlocks : (fallbackBlocks ?? []);
145
+ return fromAnthropicContent(target);
146
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Shared Anthropic streaming helpers.
3
+ *
4
+ * Extracted to avoid duplicating thinking-budget logic across the three
5
+ * Anthropic-family providers (anthropic.ts, anthropic-compat.ts,
6
+ * anthropic-sdk-provider.ts).
7
+ */
8
+ /**
9
+ * Extra output tokens added above the thinking budget to satisfy the
10
+ * Anthropic API invariant: max_tokens > budget_tokens.
11
+ */
12
+ export declare const ANTHROPIC_THINKING_HEADROOM = 4096;
13
+ /**
14
+ * Apply Anthropic extended-thinking parameters to a mutable request body.
15
+ *
16
+ * Sets `body.thinking` and adjusts `body.max_tokens` so that:
17
+ * - `max_tokens > budget_tokens` (Anthropic API requirement), and
18
+ * - `max_tokens <= modelOutputCap` (avoids over-cap requests).
19
+ *
20
+ * If the budget meets or exceeds the model's output cap, thinking is skipped
21
+ * entirely — it is impossible to satisfy `max_tokens > budget_tokens` within
22
+ * the cap. Pass `Infinity` for compat/SDK providers that have no per-model cap;
23
+ * this preserves the original `budget + HEADROOM` behaviour for those paths.
24
+ *
25
+ * @param body Mutable request body (mutated in place).
26
+ * @param reasoningEffort Effort label ('low'|'medium'|'high'|'instant') or falsy.
27
+ * @param modelOutputCap Maximum output tokens the model accepts.
28
+ */
29
+ export declare function applyAnthropicThinking(body: Record<string, unknown>, reasoningEffort: string | null | undefined, modelOutputCap: number): void;
30
+ //# sourceMappingURL=anthropic-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-stream.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/anthropic-stream.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;GAGG;AACH,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC1C,cAAc,EAAE,MAAM,GACrB,IAAI,CAWN"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Shared Anthropic streaming helpers.
3
+ *
4
+ * Extracted to avoid duplicating thinking-budget logic across the three
5
+ * Anthropic-family providers (anthropic.ts, anthropic-compat.ts,
6
+ * anthropic-sdk-provider.ts).
7
+ */
8
+ import { REASONING_BUDGET_MAP } from './interface.js';
9
+ /**
10
+ * Extra output tokens added above the thinking budget to satisfy the
11
+ * Anthropic API invariant: max_tokens > budget_tokens.
12
+ */
13
+ export const ANTHROPIC_THINKING_HEADROOM = 4096;
14
+ /**
15
+ * Apply Anthropic extended-thinking parameters to a mutable request body.
16
+ *
17
+ * Sets `body.thinking` and adjusts `body.max_tokens` so that:
18
+ * - `max_tokens > budget_tokens` (Anthropic API requirement), and
19
+ * - `max_tokens <= modelOutputCap` (avoids over-cap requests).
20
+ *
21
+ * If the budget meets or exceeds the model's output cap, thinking is skipped
22
+ * entirely — it is impossible to satisfy `max_tokens > budget_tokens` within
23
+ * the cap. Pass `Infinity` for compat/SDK providers that have no per-model cap;
24
+ * this preserves the original `budget + HEADROOM` behaviour for those paths.
25
+ *
26
+ * @param body Mutable request body (mutated in place).
27
+ * @param reasoningEffort Effort label ('low'|'medium'|'high'|'instant') or falsy.
28
+ * @param modelOutputCap Maximum output tokens the model accepts.
29
+ */
30
+ export function applyAnthropicThinking(body, reasoningEffort, modelOutputCap) {
31
+ if (!reasoningEffort || reasoningEffort === 'instant')
32
+ return;
33
+ const budget = REASONING_BUDGET_MAP[reasoningEffort];
34
+ if (typeof budget !== 'number' || budget <= 0)
35
+ return;
36
+ // Cannot satisfy API invariant max_tokens > budget_tokens within the model cap.
37
+ if (budget >= modelOutputCap)
38
+ return;
39
+ body['thinking'] = { type: 'enabled', budget_tokens: budget };
40
+ const currentMax = body['max_tokens'] ?? modelOutputCap;
41
+ if (currentMax <= budget) {
42
+ body['max_tokens'] = Math.min(budget + ANTHROPIC_THINKING_HEADROOM, modelOutputCap);
43
+ }
44
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-vertex.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/anthropic-vertex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAoMnE,qBAAa,uBAAwB,SAAQ,oBAAoB;;CAmChE"}
1
+ {"version":3,"file":"anthropic-vertex.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/anthropic-vertex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAkMnE,qBAAa,uBAAwB,SAAQ,oBAAoB;;CAmChE"}
@@ -2,6 +2,7 @@ import { BaseAnthropic } from '@anthropic-ai/sdk/client';
2
2
  import * as Resources from '@anthropic-ai/sdk/resources/index';
3
3
  import { AuthClient, GoogleAuth } from 'google-auth-library';
4
4
  import { AnthropicSdkProvider } from './anthropic-sdk-provider.js';
5
+ import { isRecord } from '../utils/record-coerce.js';
5
6
  const DEFAULT_VERSION = 'vertex-2023-10-16';
6
7
  const MODEL_ENDPOINTS = new Set(['/v1/messages', '/v1/messages?beta=true']);
7
8
  const VERTEX_MODELS = [
@@ -12,9 +13,6 @@ const VERTEX_MODELS = [
12
13
  function readEnv(name) {
13
14
  return process.env[name] ?? null;
14
15
  }
15
- function isRecord(value) {
16
- return typeof value === 'object' && value !== null && !Array.isArray(value);
17
- }
18
16
  function resolveVertexBaseUrl(region) {
19
17
  if (region === 'global')
20
18
  return 'https://aiplatform.googleapis.com/v1';
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EAEZ,oBAAoB,EAKpB,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AAKxB,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,qBAAqB,CAAC;AA4EzE;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAM;IAC/B,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IAErC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqD;gBAGnF,MAAM,EAAE,MAAM,EACd,eAAe,GAAE,IAAI,CAAC,eAAe,EAAE,YAAY,GAAG,YAAY,CAA0B;IAcxF,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwUhD,eAAe,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA4C1F,YAAY,IAAI,OAAO;YAIT,eAAe;YAmBf,aAAa;YAcb,WAAW;YAcX,eAAe;IAuC7B,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,6BAA6B;IAwBrC,OAAO,CAAC,uBAAuB;YAUjB,gBAAgB;IAsB9B,OAAO,CAAC,yBAAyB;IA2BjC,OAAO,CAAC,mCAAmC;CAoB5C"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EAEZ,oBAAoB,EAKpB,uBAAuB,EACvB,2BAA2B,EAC5B,MAAM,gBAAgB,CAAC;AAKxB,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAgDzE;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACnD,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAM;IAC/B,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IAErC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqD;gBAGnF,MAAM,EAAE,MAAM,EACd,eAAe,GAAE,IAAI,CAAC,eAAe,EAAE,YAAY,GAAG,YAAY,CAA0B;IAcxF,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwNhD,eAAe,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA4C1F,YAAY,IAAI,OAAO;YAIT,eAAe;YAmBf,aAAa;YAcb,WAAW;YAcX,eAAe;IAuC7B,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,6BAA6B;IAiBrC,OAAO,CAAC,uBAAuB;YAUjB,gBAAgB;IAsB9B,OAAO,CAAC,yBAAyB;IA2BjC,OAAO,CAAC,mCAAmC;CAoB5C"}
@@ -1,12 +1,13 @@
1
- import { REASONING_BUDGET_MAP } from './interface.js';
1
+ import { applyAnthropicThinking } from './anthropic-stream.js';
2
2
  import { getCacheCapability } from './cache-capability.js';
3
3
  import { mapAnthropicStopReason } from './stop-reason-maps.js';
4
4
  import { getDefaultStrategy } from './cache-strategy.js';
5
5
  import { ProviderError } from '../types/errors.js';
6
6
  import { withRetry } from '../utils/retry.js';
7
- import { logger } from '../utils/logger.js';
8
7
  import { instrumentedLlmCall } from '../runtime/llm-observability.js';
9
- import { toAnthropicTools, toAnthropicMessages, fromAnthropicContent, parseToolCallArguments, } from './tool-formats.js';
8
+ import { toAnthropicTools, toAnthropicMessages, fromAnthropicContent, normalizeAnthropicModel, } from './tool-formats.js';
9
+ import { createAnthropicSSEState, readAnthropicSSEStream, assembleAnthropicContentBlocks } from './anthropic-sse-assembler.js';
10
+ import { resolveCompletedStopReason, withProviderStopReason } from './provider-stop-reason.js';
10
11
  import { summarizeError, toProviderError } from '../utils/error-display.js';
11
12
  import { instrumentedFetch } from '../utils/fetch-with-timeout.js';
12
13
  import { toRecord } from '../utils/record-coerce.js';
@@ -24,13 +25,6 @@ const NOOP_CACHE_HIT_TRACKER = {
24
25
  getHitRate: () => 0,
25
26
  recordTurn: () => { },
26
27
  };
27
- function normalizeAnthropicModel(model) {
28
- if (model.startsWith('anthropic:'))
29
- return model.slice('anthropic:'.length);
30
- if (model.startsWith('anthropic/'))
31
- return model.slice('anthropic/'.length);
32
- return model;
33
- }
34
28
  /** Clamp max_tokens to the model's known limit. */
35
29
  function clampMaxTokens(model, requested) {
36
30
  for (const { match, cap } of ANTHROPIC_MAX_OUTPUT) {
@@ -180,17 +174,7 @@ export class AnthropicProvider {
180
174
  }
181
175
  }
182
176
  body['messages'] = anthropicMessages;
183
- if (reasoningEffort && reasoningEffort !== 'instant') {
184
- const budget = REASONING_BUDGET_MAP[reasoningEffort];
185
- if (budget !== undefined && budget > 0) {
186
- body['thinking'] = { type: 'enabled', budget_tokens: budget };
187
- // max_tokens must be strictly greater than thinking.budget_tokens
188
- const currentMax = body['max_tokens'] ?? 8192;
189
- if (currentMax <= budget) {
190
- body['max_tokens'] = budget + 4096;
191
- }
192
- }
193
- }
177
+ applyAnthropicThinking(body, reasoningEffort, clampMaxTokens(resolvedModel, Infinity));
194
178
  const headers = {
195
179
  'Content-Type': 'application/json',
196
180
  'anthropic-version': ANTHROPIC_API_VERSION,
@@ -235,15 +219,7 @@ export class AnthropicProvider {
235
219
  });
236
220
  }
237
221
  // Parse SSE stream
238
- let responseText = '';
239
- let inputTokens = 0;
240
- let outputTokens = 0;
241
- let cacheReadTokens = 0;
242
- let cacheWriteTokens = 0;
243
- let rawStopReason;
244
- let stopReason = 'unknown';
245
- // Accumulate tool use blocks by index
246
- const toolBlocks = new Map();
222
+ const state = createAnthropicSSEState();
247
223
  const reader = res.body?.getReader();
248
224
  if (!reader) {
249
225
  throw new ProviderError('Anthropic chat returned no response body.', {
@@ -253,125 +229,21 @@ export class AnthropicProvider {
253
229
  phase: 'response',
254
230
  });
255
231
  }
256
- const decoder = new TextDecoder();
257
- let buffer = '';
258
- try {
259
- while (true) {
260
- const { done, value } = await reader.read();
261
- if (done)
262
- break;
263
- buffer += decoder.decode(value, { stream: true });
264
- const lines = buffer.split('\n');
265
- // Keep the last (potentially incomplete) line in buffer
266
- buffer = lines.pop() ?? '';
267
- for (const line of lines) {
268
- if (!line.startsWith('data: '))
269
- continue;
270
- const data = line.slice(6).trim();
271
- if (!data || data === '[DONE]')
272
- continue;
273
- let event;
274
- try {
275
- event = JSON.parse(data);
276
- }
277
- catch {
278
- logger.warn('Anthropic SSE: failed to parse JSON chunk', {
279
- chunkPreview: data.slice(0, 200),
280
- chunkLength: data.length,
281
- });
282
- continue;
283
- }
284
- if (event.type === 'content_block_start' && event.content_block?.type === 'tool_use') {
285
- const idx = event.index ?? 0;
286
- toolBlocks.set(idx, {
287
- id: event.content_block.id ?? '',
288
- name: event.content_block.name ?? '',
289
- args: '',
290
- });
291
- if (onDelta) {
292
- onDelta({ toolCalls: [{ index: idx, id: event.content_block.id, name: event.content_block.name }] });
293
- }
294
- }
295
- else if (event.type === 'content_block_delta') {
296
- const idx = event.index ?? 0;
297
- if (event.delta?.type === 'text_delta' && event.delta.text) {
298
- responseText += event.delta.text;
299
- if (onDelta)
300
- onDelta({ content: event.delta.text });
301
- }
302
- else if (event.delta?.type === 'thinking_delta' && event.delta.thinking) {
303
- if (onDelta)
304
- onDelta({ reasoning: event.delta.thinking });
305
- }
306
- else if (event.delta?.type === 'input_json_delta' && event.delta.partial_json) {
307
- const block = toolBlocks.get(idx);
308
- if (block)
309
- block.args += event.delta.partial_json;
310
- if (onDelta) {
311
- onDelta({ toolCalls: [{ index: idx, arguments: event.delta.partial_json }] });
312
- }
313
- }
314
- }
315
- else if (event.type === 'message_delta') {
316
- if (event.delta?.stop_reason) {
317
- rawStopReason = event.delta.stop_reason;
318
- stopReason = mapAnthropicStopReason(rawStopReason);
319
- }
320
- if (event.usage?.output_tokens)
321
- outputTokens = event.usage.output_tokens;
322
- if (event.usage?.cache_read_input_tokens != null)
323
- cacheReadTokens = event.usage.cache_read_input_tokens;
324
- if (event.usage?.cache_creation_input_tokens != null)
325
- cacheWriteTokens = event.usage.cache_creation_input_tokens;
326
- }
327
- else if (event.type === 'message_start') {
328
- if (event.message?.usage) {
329
- inputTokens = event.message.usage.input_tokens;
330
- outputTokens = event.message.usage.output_tokens;
331
- cacheReadTokens = event.message.usage.cache_read_input_tokens ?? 0;
332
- cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;
333
- }
334
- }
335
- }
336
- }
337
- }
338
- finally {
339
- reader.releaseLock();
340
- }
341
- // Build the content blocks for fromAnthropicContent
342
- const contentBlocks = [];
343
- if (responseText) {
344
- contentBlocks.push({ type: 'text', text: responseText });
345
- }
346
- for (const [, block] of [...toolBlocks.entries()].sort(([a], [b]) => a - b)) {
347
- const parsedInput = parseToolCallArguments(block.args, {
348
- provider: this.name,
349
- toolName: block.name,
350
- callId: block.id,
351
- });
352
- if (parsedInput === undefined)
353
- continue;
354
- contentBlocks.push({
355
- type: 'tool_use',
356
- id: block.id,
357
- name: block.name,
358
- input: parsedInput,
359
- });
360
- }
361
- const { text, toolCalls } = fromAnthropicContent(contentBlocks);
232
+ await readAnthropicSSEStream(reader, state, onDelta, 'Anthropic');
233
+ const { text, toolCalls } = assembleAnthropicContentBlocks(state.toolBlocks, state.responseText, this.name);
362
234
  // Record cache metrics for strategy adaptation.
363
- this.cacheHitTracker.recordTurn({ inputTokens, cacheReadTokens, cacheWriteTokens });
235
+ this.cacheHitTracker.recordTurn({ inputTokens: state.inputTokens, cacheReadTokens: state.cacheReadTokens, cacheWriteTokens: state.cacheWriteTokens });
364
236
  const cap = getCacheCapability('anthropic');
365
237
  // Exclude write tokens from the denominator: writes are a one-time cost and inflate the
366
238
  // apparent miss rate on the first request. Read rate = reads / (billed input + reads).
367
- const hitRateDenom = inputTokens + cacheReadTokens;
368
- const hitRate = hitRateDenom > 0 ? cacheReadTokens / hitRateDenom : undefined;
239
+ const hitRateDenom = state.inputTokens + state.cacheReadTokens;
240
+ const hitRate = hitRateDenom > 0 ? state.cacheReadTokens / hitRateDenom : undefined;
369
241
  return {
370
242
  content: text,
371
243
  toolCalls,
372
- usage: { inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens },
373
- stopReason: stopReason === 'unknown' && text ? 'completed' : stopReason,
374
- ...(rawStopReason !== undefined ? { providerStopReason: rawStopReason } : {}),
244
+ usage: { inputTokens: state.inputTokens, outputTokens: state.outputTokens, cacheReadTokens: state.cacheReadTokens, cacheWriteTokens: state.cacheWriteTokens },
245
+ stopReason: resolveCompletedStopReason(state.stopReason, text),
246
+ ...withProviderStopReason(state.rawStopReason),
375
247
  cacheMetrics: {
376
248
  strategy: cap.type === 'explicit' ? `explicit-${cap.maxBreakpoints}bp` : cap.type,
377
249
  breakpointsPlaced,
@@ -531,15 +403,7 @@ export class AnthropicProvider {
531
403
  if (params.tools && params.tools.length > 0) {
532
404
  body['tools'] = toAnthropicTools(params.tools);
533
405
  }
534
- if (params.reasoningEffort && params.reasoningEffort !== 'instant') {
535
- const budget = REASONING_BUDGET_MAP[params.reasoningEffort];
536
- if (budget !== undefined && budget > 0) {
537
- body['thinking'] = { type: 'enabled', budget_tokens: budget };
538
- const currentMax = body['max_tokens'] ?? 8192;
539
- if (currentMax <= budget)
540
- body['max_tokens'] = budget + 4096;
541
- }
542
- }
406
+ applyAnthropicThinking(body, params.reasoningEffort, clampMaxTokens(resolvedModel, Infinity));
543
407
  return body;
544
408
  }
545
409
  mapAnthropicBatchStatus(body) {
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/capabilities.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/capabilities.ts"],"names":[],"mappings":"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"}
@@ -240,7 +240,7 @@ const PROVIDER_DEFAULTS = {
240
240
  parallelTools: true,
241
241
  jsonMode: true,
242
242
  reasoningControls: false,
243
- maxContextTokens: 131_072,
243
+ maxContextTokens: 256_000,
244
244
  maxOutputTokens: 8_192,
245
245
  timeoutMs: 120_000,
246
246
  },
@@ -274,12 +274,16 @@ const MODEL_OVERRIDES = {
274
274
  'claude-3-5-sonnet-20241022': { maxOutputTokens: 8_192 },
275
275
  'claude-3-7-sonnet-20250219': { reasoningControls: true, maxOutputTokens: 64_000 },
276
276
  // OpenAI reasoning models
277
- 'o1': { reasoningControls: true, jsonMode: false, maxOutputTokens: 32_768 },
278
- 'o1-mini': { reasoningControls: true, jsonMode: false, maxOutputTokens: 65_536 },
279
- 'o1-preview': { reasoningControls: true, jsonMode: false, maxOutputTokens: 32_768 },
280
- 'o3': { reasoningControls: true, maxOutputTokens: 100_000 },
281
- 'o3-mini': { reasoningControls: true, maxOutputTokens: 65_536 },
282
- 'o4-mini': { reasoningControls: true, maxOutputTokens: 65_536 },
277
+ 'o1': { reasoningControls: true, jsonMode: false, maxContextTokens: 200_000, maxOutputTokens: 32_768 },
278
+ 'o1-mini': { reasoningControls: true, jsonMode: false, maxContextTokens: 200_000, maxOutputTokens: 65_536 },
279
+ 'o1-preview': { reasoningControls: true, jsonMode: false, maxContextTokens: 200_000, maxOutputTokens: 32_768 },
280
+ 'o3': { reasoningControls: true, maxContextTokens: 200_000, maxOutputTokens: 100_000 },
281
+ 'o3-mini': { reasoningControls: true, maxContextTokens: 200_000, maxOutputTokens: 65_536 },
282
+ 'o4-mini': { reasoningControls: true, maxContextTokens: 200_000, maxOutputTokens: 65_536 },
283
+ // OpenAI large-context models
284
+ 'gpt-5': { maxContextTokens: 400_000 },
285
+ 'gpt-4.1': { maxContextTokens: 400_000 },
286
+ 'gpt-4.1-mini': { maxContextTokens: 400_000 },
283
287
  // Mercury models (InceptionLabs)
284
288
  'mercury-2': { toolCalling: false, parallelTools: false, reasoningControls: true, maxOutputTokens: 32_000 },
285
289
  'mercury-edit': { toolCalling: false, parallelTools: false, reasoningControls: false, maxOutputTokens: 32_000 },
@@ -1 +1 @@
1
- {"version":3,"file":"context-discovery.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/context-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAaH,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,eAAe,CAAC;AA8WlD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA0C9B"}
1
+ {"version":3,"file":"context-discovery.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/context-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAaH,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAuWlD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA0C9B"}
@@ -18,7 +18,7 @@
18
18
  */
19
19
  import { logger } from '../utils/logger.js';
20
20
  import { summarizeError } from '../utils/error-display.js';
21
- import { instrumentedFetch } from '../utils/fetch-with-timeout.js';
21
+ import { instrumentedFetch, fetchWithTimeout } from '../utils/fetch-with-timeout.js';
22
22
  // ---------------------------------------------------------------------------
23
23
  // Constants
24
24
  // ---------------------------------------------------------------------------
@@ -48,21 +48,17 @@ function extractOrigin(baseURL) {
48
48
  * Returns the Response on success, or null on any error (timeout, network, 4xx/5xx).
49
49
  */
50
50
  async function probe(url, options = {}) {
51
- const controller = new AbortController();
52
- const timer = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
53
- timer.unref?.();
51
+ const headers = { Accept: 'application/json' };
52
+ if (options.apiKey)
53
+ headers['Authorization'] = `Bearer ${options.apiKey}`;
54
+ if (options.body)
55
+ headers['Content-Type'] = 'application/json';
54
56
  try {
55
- const headers = { Accept: 'application/json' };
56
- if (options.apiKey)
57
- headers['Authorization'] = `Bearer ${options.apiKey}`;
58
- if (options.body)
59
- headers['Content-Type'] = 'application/json';
60
- const response = await instrumentedFetch(url, {
57
+ const response = await fetchWithTimeout(url, {
61
58
  method: options.method ?? 'GET',
62
59
  headers,
63
60
  ...(options.body !== undefined ? { body: options.body } : {}),
64
- signal: controller.signal,
65
- });
61
+ }, PROBE_TIMEOUT_MS, instrumentedFetch);
66
62
  if (!response.ok) {
67
63
  logger.debug('[context-discovery] Non-OK probe response', { url, status: response.status });
68
64
  return null;
@@ -71,7 +67,7 @@ async function probe(url, options = {}) {
71
67
  }
72
68
  catch (err) {
73
69
  const name = err?.name;
74
- if (name === 'AbortError') {
70
+ if (name === 'AbortError' || name === 'TimeoutError') {
75
71
  logger.debug('[context-discovery] Probe timed out', { url });
76
72
  }
77
73
  else {
@@ -79,9 +75,6 @@ async function probe(url, options = {}) {
79
75
  }
80
76
  return null;
81
77
  }
82
- finally {
83
- clearTimeout(timer);
84
- }
85
78
  }
86
79
  /**
87
80
  * Safely parse JSON from a Response. Returns null on parse error.
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Provider/model-family-aware context-window fallback.
3
+ *
4
+ * Used only when neither the live catalog (models.dev) nor the provider API
5
+ * reports a context window for a model — e.g. a model newer than the models.dev
6
+ * snapshot (the "brand-new gpt-5.5" case). A single flat default badly mis-sizes
7
+ * the window and drives auto-compaction to fire far too early (small default) or
8
+ * too late (large default, risking a provider "context length exceeded" error).
9
+ * Infer a sane family default from the provider and model id instead.
10
+ *
11
+ * The real window always wins whenever the catalog / OpenRouter / provider_api
12
+ * supplies one; this is the last line of defense, not a primary source.
13
+ */
14
+ /** Last-resort default when neither provider nor model id is recognised. */
15
+ export declare const FALLBACK_CONTEXT_WINDOW = 128000;
16
+ /**
17
+ * Best-effort context window (in tokens) inferred from provider + model id.
18
+ *
19
+ * Over-estimating is the dangerous direction (it risks context-overflow errors),
20
+ * so only known-large families get a large window; older/unknown families stay at
21
+ * the conservative {@link FALLBACK_CONTEXT_WINDOW}.
22
+ */
23
+ export declare function inferFallbackContextWindow(provider: string, modelId?: string): number;
24
+ //# sourceMappingURL=context-window-fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-window-fallback.d.ts","sourceRoot":"","sources":["../../../src/platform/providers/context-window-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,SAAU,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBrF"}