@framers/agentos 0.10.22 → 0.10.24

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 (204) hide show
  1. package/README.md +1 -1
  2. package/dist/api/AgentOS.d.ts.map +1 -1
  3. package/dist/api/AgentOS.js +3 -2
  4. package/dist/api/AgentOS.js.map +1 -1
  5. package/dist/api/agent.d.ts.map +1 -1
  6. package/dist/api/agent.js +25 -10
  7. package/dist/api/agent.js.map +1 -1
  8. package/dist/api/embedText.d.ts.map +1 -1
  9. package/dist/api/embedText.js +53 -17
  10. package/dist/api/embedText.js.map +1 -1
  11. package/dist/api/generateImage.d.ts.map +1 -1
  12. package/dist/api/generateImage.js +51 -7
  13. package/dist/api/generateImage.js.map +1 -1
  14. package/dist/api/generateText.d.ts +50 -7
  15. package/dist/api/generateText.d.ts.map +1 -1
  16. package/dist/api/generateText.js +265 -35
  17. package/dist/api/generateText.js.map +1 -1
  18. package/dist/api/model.d.ts +25 -1
  19. package/dist/api/model.d.ts.map +1 -1
  20. package/dist/api/model.js +108 -3
  21. package/dist/api/model.js.map +1 -1
  22. package/dist/api/runtime/SelfImprovementSessionManager.d.ts +34 -2
  23. package/dist/api/runtime/SelfImprovementSessionManager.d.ts.map +1 -1
  24. package/dist/api/runtime/SelfImprovementSessionManager.js +119 -33
  25. package/dist/api/runtime/SelfImprovementSessionManager.js.map +1 -1
  26. package/dist/api/runtime/global-default.d.ts +9 -1
  27. package/dist/api/runtime/global-default.d.ts.map +1 -1
  28. package/dist/api/runtime/global-default.js.map +1 -1
  29. package/dist/api/runtime/provider-defaults.d.ts.map +1 -1
  30. package/dist/api/runtime/provider-defaults.js +10 -4
  31. package/dist/api/runtime/provider-defaults.js.map +1 -1
  32. package/dist/api/runtime/tool-emulation/history.d.ts +16 -0
  33. package/dist/api/runtime/tool-emulation/history.d.ts.map +1 -0
  34. package/dist/api/runtime/tool-emulation/history.js +89 -0
  35. package/dist/api/runtime/tool-emulation/history.js.map +1 -0
  36. package/dist/api/runtime/tool-emulation/index.d.ts +1 -0
  37. package/dist/api/runtime/tool-emulation/index.d.ts.map +1 -1
  38. package/dist/api/runtime/tool-emulation/index.js +1 -0
  39. package/dist/api/runtime/tool-emulation/index.js.map +1 -1
  40. package/dist/api/runtime/tool-emulation/loop.d.ts +6 -0
  41. package/dist/api/runtime/tool-emulation/loop.d.ts.map +1 -1
  42. package/dist/api/runtime/tool-emulation/loop.js +1 -0
  43. package/dist/api/runtime/tool-emulation/loop.js.map +1 -1
  44. package/dist/api/sessionTranscript.d.ts +34 -0
  45. package/dist/api/sessionTranscript.d.ts.map +1 -1
  46. package/dist/api/sessionTranscript.js +61 -1
  47. package/dist/api/sessionTranscript.js.map +1 -1
  48. package/dist/api/streamText.d.ts.map +1 -1
  49. package/dist/api/streamText.js +120 -24
  50. package/dist/api/streamText.js.map +1 -1
  51. package/dist/api/types/AgentOSInput.d.ts +11 -0
  52. package/dist/api/types/AgentOSInput.d.ts.map +1 -1
  53. package/dist/api/types.d.ts +14 -6
  54. package/dist/api/types.d.ts.map +1 -1
  55. package/dist/api/types.js.map +1 -1
  56. package/dist/cognition/emergent/AdaptPersonalityTool.d.ts +13 -4
  57. package/dist/cognition/emergent/AdaptPersonalityTool.d.ts.map +1 -1
  58. package/dist/cognition/emergent/AdaptPersonalityTool.js +32 -23
  59. package/dist/cognition/emergent/AdaptPersonalityTool.js.map +1 -1
  60. package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts +18 -6
  61. package/dist/cognition/emergent/EmergentCapabilityEngine.d.ts.map +1 -1
  62. package/dist/cognition/emergent/EmergentCapabilityEngine.js.map +1 -1
  63. package/dist/cognition/emergent/SelfEvaluateTool.d.ts +10 -3
  64. package/dist/cognition/emergent/SelfEvaluateTool.d.ts.map +1 -1
  65. package/dist/cognition/emergent/SelfEvaluateTool.js +3 -2
  66. package/dist/cognition/emergent/SelfEvaluateTool.js.map +1 -1
  67. package/dist/cognition/substrate/CognitiveMemoryBridge.d.ts +51 -2
  68. package/dist/cognition/substrate/CognitiveMemoryBridge.d.ts.map +1 -1
  69. package/dist/cognition/substrate/CognitiveMemoryBridge.js +84 -2
  70. package/dist/cognition/substrate/CognitiveMemoryBridge.js.map +1 -1
  71. package/dist/cognition/substrate/ConversationHistoryManager.d.ts +8 -4
  72. package/dist/cognition/substrate/ConversationHistoryManager.d.ts.map +1 -1
  73. package/dist/cognition/substrate/ConversationHistoryManager.js +17 -5
  74. package/dist/cognition/substrate/ConversationHistoryManager.js.map +1 -1
  75. package/dist/cognition/substrate/GMI.d.ts +92 -5
  76. package/dist/cognition/substrate/GMI.d.ts.map +1 -1
  77. package/dist/cognition/substrate/GMI.js +291 -65
  78. package/dist/cognition/substrate/GMI.js.map +1 -1
  79. package/dist/cognition/substrate/GMIManager.d.ts +12 -0
  80. package/dist/cognition/substrate/GMIManager.d.ts.map +1 -1
  81. package/dist/cognition/substrate/GMIManager.js +22 -16
  82. package/dist/cognition/substrate/GMIManager.js.map +1 -1
  83. package/dist/cognition/substrate/IGMI.d.ts +23 -0
  84. package/dist/cognition/substrate/IGMI.d.ts.map +1 -1
  85. package/dist/cognition/substrate/IGMI.js.map +1 -1
  86. package/dist/cognition/substrate/MetapromptExecutor.d.ts +183 -28
  87. package/dist/cognition/substrate/MetapromptExecutor.d.ts.map +1 -1
  88. package/dist/cognition/substrate/MetapromptExecutor.js +431 -108
  89. package/dist/cognition/substrate/MetapromptExecutor.js.map +1 -1
  90. package/dist/cognition/substrate/personas/IPersonaDefinition.d.ts +5 -0
  91. package/dist/cognition/substrate/personas/IPersonaDefinition.d.ts.map +1 -1
  92. package/dist/cognition/substrate/personas/PersonaValidation.d.ts.map +1 -1
  93. package/dist/cognition/substrate/personas/PersonaValidation.js +30 -0
  94. package/dist/cognition/substrate/personas/PersonaValidation.js.map +1 -1
  95. package/dist/cognition/substrate/personas/SoulLoader.d.ts +14 -1
  96. package/dist/cognition/substrate/personas/SoulLoader.d.ts.map +1 -1
  97. package/dist/cognition/substrate/personas/SoulLoader.js +45 -12
  98. package/dist/cognition/substrate/personas/SoulLoader.js.map +1 -1
  99. package/dist/cognition/substrate/personas/definitions/default_assistant_persona.json +3 -35
  100. package/dist/cognition/substrate/personas/hexaco.d.ts +34 -0
  101. package/dist/cognition/substrate/personas/hexaco.d.ts.map +1 -0
  102. package/dist/cognition/substrate/personas/hexaco.js +66 -0
  103. package/dist/cognition/substrate/personas/hexaco.js.map +1 -0
  104. package/dist/cognition/substrate/userFeedback.d.ts +69 -0
  105. package/dist/cognition/substrate/userFeedback.d.ts.map +1 -0
  106. package/dist/cognition/substrate/userFeedback.js +107 -0
  107. package/dist/cognition/substrate/userFeedback.js.map +1 -0
  108. package/dist/core/conversation/ConversationMessage.d.ts +9 -0
  109. package/dist/core/conversation/ConversationMessage.d.ts.map +1 -1
  110. package/dist/core/conversation/ConversationMessage.js.map +1 -1
  111. package/dist/core/llm/IPromptEngine.d.ts +9 -0
  112. package/dist/core/llm/IPromptEngine.d.ts.map +1 -1
  113. package/dist/core/llm/IPromptEngine.js.map +1 -1
  114. package/dist/core/llm/PromptEngine.d.ts +30 -1
  115. package/dist/core/llm/PromptEngine.d.ts.map +1 -1
  116. package/dist/core/llm/PromptEngine.js +229 -92
  117. package/dist/core/llm/PromptEngine.js.map +1 -1
  118. package/dist/core/llm/providers/AIModelProviderManager.d.ts +20 -0
  119. package/dist/core/llm/providers/AIModelProviderManager.d.ts.map +1 -1
  120. package/dist/core/llm/providers/AIModelProviderManager.js +35 -5
  121. package/dist/core/llm/providers/AIModelProviderManager.js.map +1 -1
  122. package/dist/core/llm/providers/IProvider.d.ts +28 -8
  123. package/dist/core/llm/providers/IProvider.d.ts.map +1 -1
  124. package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts +135 -49
  125. package/dist/core/llm/providers/implementations/AnthropicProvider.d.ts.map +1 -1
  126. package/dist/core/llm/providers/implementations/AnthropicProvider.js +323 -114
  127. package/dist/core/llm/providers/implementations/AnthropicProvider.js.map +1 -1
  128. package/dist/core/llm/providers/implementations/ClaudeCodeProvider.d.ts.map +1 -1
  129. package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js +15 -1
  130. package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js.map +1 -1
  131. package/dist/core/llm/providers/implementations/GeminiCLIProvider.d.ts +1 -1
  132. package/dist/core/llm/providers/implementations/GeminiCLIProvider.d.ts.map +1 -1
  133. package/dist/core/llm/providers/implementations/GeminiCLIProvider.js +51 -24
  134. package/dist/core/llm/providers/implementations/GeminiCLIProvider.js.map +1 -1
  135. package/dist/core/llm/providers/implementations/GeminiProvider.d.ts +25 -6
  136. package/dist/core/llm/providers/implementations/GeminiProvider.d.ts.map +1 -1
  137. package/dist/core/llm/providers/implementations/GeminiProvider.js +108 -90
  138. package/dist/core/llm/providers/implementations/GeminiProvider.js.map +1 -1
  139. package/dist/core/llm/providers/implementations/MistralProvider.d.ts +11 -0
  140. package/dist/core/llm/providers/implementations/MistralProvider.d.ts.map +1 -1
  141. package/dist/core/llm/providers/implementations/MistralProvider.js +32 -2
  142. package/dist/core/llm/providers/implementations/MistralProvider.js.map +1 -1
  143. package/dist/core/llm/providers/implementations/OllamaProvider.js +7 -7
  144. package/dist/core/llm/providers/implementations/OllamaProvider.js.map +1 -1
  145. package/dist/core/llm/providers/implementations/OpenAIProvider.d.ts +53 -2
  146. package/dist/core/llm/providers/implementations/OpenAIProvider.d.ts.map +1 -1
  147. package/dist/core/llm/providers/implementations/OpenAIProvider.js +84 -17
  148. package/dist/core/llm/providers/implementations/OpenAIProvider.js.map +1 -1
  149. package/dist/core/llm/providers/implementations/OpenRouterProvider.d.ts.map +1 -1
  150. package/dist/core/llm/providers/implementations/OpenRouterProvider.js +8 -3
  151. package/dist/core/llm/providers/implementations/OpenRouterProvider.js.map +1 -1
  152. package/dist/core/llm/providers/implementations/TogetherProvider.d.ts +3 -3
  153. package/dist/core/llm/providers/implementations/TogetherProvider.d.ts.map +1 -1
  154. package/dist/core/llm/providers/implementations/TogetherProvider.js +25 -13
  155. package/dist/core/llm/providers/implementations/TogetherProvider.js.map +1 -1
  156. package/dist/core/llm/providers/implementations/cacheLeakDetector.d.ts +15 -7
  157. package/dist/core/llm/providers/implementations/cacheLeakDetector.d.ts.map +1 -1
  158. package/dist/core/llm/providers/implementations/cacheLeakDetector.js +12 -7
  159. package/dist/core/llm/providers/implementations/cacheLeakDetector.js.map +1 -1
  160. package/dist/core/llm/providers/model-cache-capabilities.d.ts +24 -9
  161. package/dist/core/llm/providers/model-cache-capabilities.d.ts.map +1 -1
  162. package/dist/core/llm/providers/model-cache-capabilities.js +59 -44
  163. package/dist/core/llm/providers/model-cache-capabilities.js.map +1 -1
  164. package/dist/core/llm/providers/model-effort.d.ts +14 -0
  165. package/dist/core/llm/providers/model-effort.d.ts.map +1 -1
  166. package/dist/core/llm/providers/model-effort.js +22 -0
  167. package/dist/core/llm/providers/model-effort.js.map +1 -1
  168. package/dist/core/llm/providers/model-forced-tool-choice.d.ts +13 -6
  169. package/dist/core/llm/providers/model-forced-tool-choice.d.ts.map +1 -1
  170. package/dist/core/llm/providers/model-forced-tool-choice.js +14 -7
  171. package/dist/core/llm/providers/model-forced-tool-choice.js.map +1 -1
  172. package/dist/core/llm/providers/model-thinking.d.ts +64 -13
  173. package/dist/core/llm/providers/model-thinking.d.ts.map +1 -1
  174. package/dist/core/llm/providers/model-thinking.js +52 -12
  175. package/dist/core/llm/providers/model-thinking.js.map +1 -1
  176. package/dist/core/llm/providers/openrouter-only-params.d.ts +26 -7
  177. package/dist/core/llm/providers/openrouter-only-params.d.ts.map +1 -1
  178. package/dist/core/llm/providers/openrouter-only-params.js +58 -9
  179. package/dist/core/llm/providers/openrouter-only-params.js.map +1 -1
  180. package/dist/core/llm/providers/url-secrets.d.ts +42 -0
  181. package/dist/core/llm/providers/url-secrets.d.ts.map +1 -0
  182. package/dist/core/llm/providers/url-secrets.js +64 -0
  183. package/dist/core/llm/providers/url-secrets.js.map +1 -0
  184. package/dist/core/llm/streaming/StreamingBatcher.d.ts +4 -3
  185. package/dist/core/llm/streaming/StreamingBatcher.d.ts.map +1 -1
  186. package/dist/core/llm/streaming/StreamingBatcher.js +8 -3
  187. package/dist/core/llm/streaming/StreamingBatcher.js.map +1 -1
  188. package/dist/core/safety/LLMProviderHealthRegistry.d.ts +4 -0
  189. package/dist/core/safety/LLMProviderHealthRegistry.d.ts.map +1 -1
  190. package/dist/core/safety/LLMProviderHealthRegistry.js +26 -0
  191. package/dist/core/safety/LLMProviderHealthRegistry.js.map +1 -1
  192. package/dist/core/utils/sha256.d.ts +19 -0
  193. package/dist/core/utils/sha256.d.ts.map +1 -0
  194. package/dist/core/utils/sha256.js +101 -0
  195. package/dist/core/utils/sha256.js.map +1 -0
  196. package/dist/index.d.ts +1 -1
  197. package/dist/index.d.ts.map +1 -1
  198. package/dist/index.js +1 -1
  199. package/dist/index.js.map +1 -1
  200. package/dist/orchestration/pipeline/query/types.js +3 -3
  201. package/dist/orchestration/pipeline/query/types.js.map +1 -1
  202. package/dist/orchestration/planning/ProviderAssignmentEngine.js +2 -2
  203. package/dist/orchestration/planning/ProviderAssignmentEngine.js.map +1 -1
  204. package/package.json +1 -1
@@ -5,9 +5,10 @@
5
5
  * Anthropic structured output and `toolChoice: 'required'` both resolve to a
6
6
  * FORCED `tool_choice` on the Messages API (`{ type: 'tool', name }` or
7
7
  * `{ type: 'any' }`). Most Claude models accept this, and it is the most
8
- * reliable way to constrain output. Claude Fable 5 / 5.1 and Claude Opus 5.5
9
- * reject a forced `tool_choice` at the API level with a 400. Those models can
10
- * still call tools under `{ type: 'auto' }`; they only refuse to be forced.
8
+ * reliable way to constrain output. Claude Fable 5 / 5.1, Claude Mythos 5.1,
9
+ * Claude Opus 5.5 and Claude Sonnet 5.5 reject a forced `tool_choice` at the
10
+ * API level with a 400. Those models can still call tools under
11
+ * `{ type: 'auto' }`; they only refuse to be forced.
11
12
  *
12
13
  * Two consumers read this:
13
14
  * - {@link AnthropicProvider} clamps any resolved forced `tool_choice` to
@@ -26,22 +27,28 @@
26
27
  * Whether Anthropic will accept a forced `tool_choice` (`{ type: 'tool' }` or
27
28
  * `{ type: 'any' }`) for the given Claude model id.
28
29
  *
29
- * Deny-by-explicit-model. Two families reject forced tool use, and every other
30
- * current Claude model (Sonnet, Opus 5 and earlier, Haiku) accepts it:
30
+ * Deny-by-explicit-model. These models reject forced tool use, and every
31
+ * other current Claude model (Sonnet 5 and earlier, Opus 5 and earlier,
32
+ * Haiku) accepts it:
31
33
  *
32
34
  * - Claude Fable 5 and 5.1, including dated variants such as
33
35
  * `claude-fable-5-20260601`. The `fable-5` alternative also matches
34
36
  * `claude-fable-5-1` because `\b` matches at the hyphen, which is intended
35
37
  * since 5.1 is the same family under the same constraint.
38
+ * - Claude Mythos 5.1 (`claude-mythos-5-1`), per Anthropic's model docs.
36
39
  * - Claude Opus 5.5 (`claude-opus-5-5`). Claude Opus 5 accepts forced tool
37
40
  * use, so the pattern names the full `opus-5-5` id. A bare `opus-5` prefix
38
41
  * would deny Opus 5 as well.
42
+ * - Claude Sonnet 5.5 (`claude-sonnet-5-5`). Claude Sonnet 5 accepts forced
43
+ * tool use, so the pattern names the full `sonnet-5-5` id for the same
44
+ * reason.
39
45
  *
40
46
  * Live-probed 2026-09-29 on the Messages API. `{type:'tool'}` and
41
47
  * `{type:'any'}` both return HTTP 400 on `claude-opus-5-5` and
42
48
  * `claude-fable-5-1`, with the message `tool_choice: type "tool" and "any" are
43
49
  * not supported for this model.` The same two requests return 200 on
44
- * `claude-opus-5`.
50
+ * `claude-opus-5`. Both return HTTP 400 on `claude-sonnet-5-5` (probed
51
+ * 2026-09-30).
45
52
  *
46
53
  * `AnthropicProvider` clamps an unsupported forced choice to `{ type: 'auto' }`
47
54
  * and logs a warning. An extra entry here therefore costs guaranteed tool
@@ -55,6 +62,6 @@
55
62
  * model, `true` otherwise.
56
63
  */
57
64
  export function modelSupportsForcedToolChoice(modelId) {
58
- return !/^claude-(fable-5|opus-5-5)\b/i.test(modelId);
65
+ return !/^claude-(fable-5|mythos-5-1|opus-5-5|sonnet-5-5)\b/i.test(modelId);
59
66
  }
60
67
  //# sourceMappingURL=model-forced-tool-choice.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-forced-tool-choice.js","sourceRoot":"","sources":["../../../../src/core/llm/providers/model-forced-tool-choice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,6BAA6B,CAAC,OAAe;IAC3D,OAAO,CAAC,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"model-forced-tool-choice.js","sourceRoot":"","sources":["../../../../src/core/llm/providers/model-forced-tool-choice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,UAAU,6BAA6B,CAAC,OAAe;IAC3D,OAAO,CAAC,qDAAqD,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC9E,CAAC"}
@@ -2,20 +2,23 @@
2
2
  * @fileoverview Extended-thinking helpers for the Anthropic
3
3
  * reasoning-default Claude models.
4
4
  *
5
- * The Opus 4.7 / 4.8 family and Fable 5 reason by default and accept ONLY
6
- * the adaptive thinking form on the Messages API: `thinking: { type:
7
- * 'adaptive' }`. The older manual form `thinking: { type: 'enabled',
8
- * budget_tokens }` is removed on this family and returns a 400
9
- * ('"thinking.type.enabled" is not supported for this model'). Fable 5 adds
10
- * one more constraint — an explicit `thinking: { type: 'disabled' }` also
11
- * 400s — but the provider only ever emits the adaptive form (or nothing),
12
- * never `disabled`, so that path is never hit. Depth is
5
+ * Turning thinking on: the Opus 4.7 / 4.8 family, Opus 5.x, Sonnet 5.x and
6
+ * Fable 5.x take ONLY the adaptive form as the on-switch on the Messages API:
7
+ * `thinking: { type: 'adaptive' }`. The older manual form `thinking: { type:
8
+ * 'enabled', budget_tokens }` is removed on this family and returns a 400
9
+ * ('"thinking.type.enabled" is not supported for this model'). Depth is
13
10
  * controlled by `output_config.effort`, not a token budget, so the
14
11
  * caller-facing `{ budgetTokens }` option acts as the on-switch and the
15
12
  * number itself is not sent. {@link AnthropicProvider} sends the block
16
13
  * through {@link resolveThinkingPayload} when a caller passes a thinking
17
14
  * budget AND the model supports it.
18
15
  *
16
+ * Turning thinking off (`thinking: false`): leaving the field out keeps the
17
+ * model's default, which is thinking ON for Opus 5, Sonnet 5 and Sonnet 5.5,
18
+ * and always on for Opus 5.5, Fable and Mythos. The models that can turn it
19
+ * off each take their own shape, and some only at a capped effort;
20
+ * {@link resolveThinkingOff} maps a model id to it.
21
+ *
19
22
  * This is the thinking-capability sibling of `modelSupportsTemperature`
20
23
  * in AnthropicProvider.ts — the same reasoning-default family that
21
24
  * REJECTS `temperature` is the family that ACCEPTS `thinking`. Kept in
@@ -27,10 +30,13 @@
27
30
  * `thinking` parameter.
28
31
  *
29
32
  * Allow-by-explicit-family: only the reasoning-default Opus 4.7 / 4.8
30
- * line, Sonnet 5, and Fable 5 (and their dated variants like
33
+ * line, Opus 5, Sonnet 5, and Fable 5 (and their dated variants like
31
34
  * `claude-opus-4-8-20260501`) accept it; every other Claude model ignores
32
- * or rejects it. Future reasoning-first siblings get added to the regex as
33
- * Anthropic releases them, in lockstep with `modelSupportsTemperature`.
35
+ * or rejects it. Opus 5.5, Sonnet 5.5 and Fable 5.1 match the `opus-5`,
36
+ * `sonnet-5` and `fable-5` alternatives on purpose, because `\b` matches at
37
+ * the hyphen before their trailing version digit. Future reasoning-first
38
+ * siblings get added to the regex as Anthropic releases them, in lockstep
39
+ * with `modelSupportsTemperature`.
34
40
  *
35
41
  * @param modelId Anthropic-side model id.
36
42
  * @returns `true` when Anthropic accepts a `thinking` block for this model.
@@ -58,10 +64,55 @@ export interface ResolvedThinkingPayload {
58
64
  * max_tokens change).
59
65
  *
60
66
  * @param modelId Anthropic-side model id.
61
- * @param thinking Caller-supplied `{ budgetTokens }`, or `undefined`.
67
+ * @param thinking Caller-supplied `{ budgetTokens }`; `false` (thinking
68
+ * off, see {@link resolveThinkingOff}) and `undefined` return `null`.
62
69
  * @param requestedMaxTokens The max_tokens already resolved for the request.
63
70
  */
64
71
  export declare function resolveThinkingPayload(modelId: string, thinking: {
65
72
  budgetTokens: number;
66
- } | undefined, requestedMaxTokens: number | undefined): ResolvedThinkingPayload | null;
73
+ } | false | undefined, requestedMaxTokens: number | undefined): ResolvedThinkingPayload | null;
74
+ /**
75
+ * How one model takes a request to turn thinking off.
76
+ *
77
+ * - `omit`: the model does not think unless asked, so leaving `thinking` out
78
+ * is off.
79
+ * - `send`: the model thinks by default and turns it off only for this
80
+ * `thinking` value. `maxEffort` is the highest `output_config.effort` the
81
+ * value is accepted with; absent means any effort.
82
+ * - `always_on`: the model always thinks and rejects every off shape.
83
+ */
84
+ export type ThinkingOffShape = {
85
+ kind: 'omit';
86
+ } | {
87
+ kind: 'send';
88
+ thinking: {
89
+ type: 'disabled';
90
+ } | {
91
+ type: 'between_tools';
92
+ };
93
+ maxEffort?: 'high';
94
+ } | {
95
+ kind: 'always_on';
96
+ };
97
+ /**
98
+ * The request shape that turns thinking off on a Claude model, for a caller
99
+ * passing `thinking: false`.
100
+ *
101
+ * | Model | Off shape | Source |
102
+ * | --- | --- | --- |
103
+ * | Sonnet 5.5 | `{ type: 'between_tools' }` at effort high or below | probed 2026-09-30: `disabled` returns 400, `between_tools` 200 |
104
+ * | Opus 5 | `{ type: 'disabled' }` at effort high or below | probed 2026-09-30: `disabled` 200, `between_tools` 400 |
105
+ * | Sonnet 5 | `{ type: 'disabled' }` | Anthropic's model docs |
106
+ * | Opus 5.5, Fable 5.x, Mythos 5.x | none: always on | probed 2026-09-30 on Opus 5.5 and Fable 5.1: both shapes return 400 |
107
+ * | everything else | omit the field | thinks only when asked |
108
+ *
109
+ * The 5.5 checks run first because `opus-5\b` and `sonnet-5\b` also match
110
+ * the 5.5 ids. An unknown id gets `omit`, which never sends a shape that
111
+ * could return 400. Anchored like {@link modelSupportsThinking}, so the id
112
+ * is the bare Anthropic-side one.
113
+ *
114
+ * @param modelId Anthropic-side model id, bare or dated.
115
+ * @returns The off shape for the model.
116
+ */
117
+ export declare function resolveThinkingOff(modelId: string): ThinkingOffShape;
67
118
  //# sourceMappingURL=model-thinking.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-thinking.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/providers/model-thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,0EAA0E;AAC1E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAC9C,kBAAkB,EAAE,MAAM,GAAG,SAAS,GACrC,uBAAuB,GAAG,IAAI,CAGhC"}
1
+ {"version":3,"file":"model-thinking.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/providers/model-thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,0EAA0E;AAC1E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,GAAG,SAAS,EACtD,kBAAkB,EAAE,MAAM,GAAG,SAAS,GACrC,uBAAuB,GAAG,IAAI,CAGhC;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IACE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACD;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAUpE"}
@@ -2,20 +2,23 @@
2
2
  * @fileoverview Extended-thinking helpers for the Anthropic
3
3
  * reasoning-default Claude models.
4
4
  *
5
- * The Opus 4.7 / 4.8 family and Fable 5 reason by default and accept ONLY
6
- * the adaptive thinking form on the Messages API: `thinking: { type:
7
- * 'adaptive' }`. The older manual form `thinking: { type: 'enabled',
8
- * budget_tokens }` is removed on this family and returns a 400
9
- * ('"thinking.type.enabled" is not supported for this model'). Fable 5 adds
10
- * one more constraint — an explicit `thinking: { type: 'disabled' }` also
11
- * 400s — but the provider only ever emits the adaptive form (or nothing),
12
- * never `disabled`, so that path is never hit. Depth is
5
+ * Turning thinking on: the Opus 4.7 / 4.8 family, Opus 5.x, Sonnet 5.x and
6
+ * Fable 5.x take ONLY the adaptive form as the on-switch on the Messages API:
7
+ * `thinking: { type: 'adaptive' }`. The older manual form `thinking: { type:
8
+ * 'enabled', budget_tokens }` is removed on this family and returns a 400
9
+ * ('"thinking.type.enabled" is not supported for this model'). Depth is
13
10
  * controlled by `output_config.effort`, not a token budget, so the
14
11
  * caller-facing `{ budgetTokens }` option acts as the on-switch and the
15
12
  * number itself is not sent. {@link AnthropicProvider} sends the block
16
13
  * through {@link resolveThinkingPayload} when a caller passes a thinking
17
14
  * budget AND the model supports it.
18
15
  *
16
+ * Turning thinking off (`thinking: false`): leaving the field out keeps the
17
+ * model's default, which is thinking ON for Opus 5, Sonnet 5 and Sonnet 5.5,
18
+ * and always on for Opus 5.5, Fable and Mythos. The models that can turn it
19
+ * off each take their own shape, and some only at a capped effort;
20
+ * {@link resolveThinkingOff} maps a model id to it.
21
+ *
19
22
  * This is the thinking-capability sibling of `modelSupportsTemperature`
20
23
  * in AnthropicProvider.ts — the same reasoning-default family that
21
24
  * REJECTS `temperature` is the family that ACCEPTS `thinking`. Kept in
@@ -27,10 +30,13 @@
27
30
  * `thinking` parameter.
28
31
  *
29
32
  * Allow-by-explicit-family: only the reasoning-default Opus 4.7 / 4.8
30
- * line, Sonnet 5, and Fable 5 (and their dated variants like
33
+ * line, Opus 5, Sonnet 5, and Fable 5 (and their dated variants like
31
34
  * `claude-opus-4-8-20260501`) accept it; every other Claude model ignores
32
- * or rejects it. Future reasoning-first siblings get added to the regex as
33
- * Anthropic releases them, in lockstep with `modelSupportsTemperature`.
35
+ * or rejects it. Opus 5.5, Sonnet 5.5 and Fable 5.1 match the `opus-5`,
36
+ * `sonnet-5` and `fable-5` alternatives on purpose, because `\b` matches at
37
+ * the hyphen before their trailing version digit. Future reasoning-first
38
+ * siblings get added to the regex as Anthropic releases them, in lockstep
39
+ * with `modelSupportsTemperature`.
34
40
  *
35
41
  * @param modelId Anthropic-side model id.
36
42
  * @returns `true` when Anthropic accepts a `thinking` block for this model.
@@ -53,7 +59,8 @@ export function modelSupportsThinking(modelId) {
53
59
  * max_tokens change).
54
60
  *
55
61
  * @param modelId Anthropic-side model id.
56
- * @param thinking Caller-supplied `{ budgetTokens }`, or `undefined`.
62
+ * @param thinking Caller-supplied `{ budgetTokens }`; `false` (thinking
63
+ * off, see {@link resolveThinkingOff}) and `undefined` return `null`.
57
64
  * @param requestedMaxTokens The max_tokens already resolved for the request.
58
65
  */
59
66
  export function resolveThinkingPayload(modelId, thinking, requestedMaxTokens) {
@@ -61,4 +68,37 @@ export function resolveThinkingPayload(modelId, thinking, requestedMaxTokens) {
61
68
  return null;
62
69
  return { thinking: { type: 'adaptive' }, maxTokens: requestedMaxTokens ?? 0 };
63
70
  }
71
+ /**
72
+ * The request shape that turns thinking off on a Claude model, for a caller
73
+ * passing `thinking: false`.
74
+ *
75
+ * | Model | Off shape | Source |
76
+ * | --- | --- | --- |
77
+ * | Sonnet 5.5 | `{ type: 'between_tools' }` at effort high or below | probed 2026-09-30: `disabled` returns 400, `between_tools` 200 |
78
+ * | Opus 5 | `{ type: 'disabled' }` at effort high or below | probed 2026-09-30: `disabled` 200, `between_tools` 400 |
79
+ * | Sonnet 5 | `{ type: 'disabled' }` | Anthropic's model docs |
80
+ * | Opus 5.5, Fable 5.x, Mythos 5.x | none: always on | probed 2026-09-30 on Opus 5.5 and Fable 5.1: both shapes return 400 |
81
+ * | everything else | omit the field | thinks only when asked |
82
+ *
83
+ * The 5.5 checks run first because `opus-5\b` and `sonnet-5\b` also match
84
+ * the 5.5 ids. An unknown id gets `omit`, which never sends a shape that
85
+ * could return 400. Anchored like {@link modelSupportsThinking}, so the id
86
+ * is the bare Anthropic-side one.
87
+ *
88
+ * @param modelId Anthropic-side model id, bare or dated.
89
+ * @returns The off shape for the model.
90
+ */
91
+ export function resolveThinkingOff(modelId) {
92
+ if (/^claude-sonnet-5-5\b/i.test(modelId)) {
93
+ return { kind: 'send', thinking: { type: 'between_tools' }, maxEffort: 'high' };
94
+ }
95
+ if (/^claude-(opus-5-5|fable-5|mythos-5)\b/i.test(modelId))
96
+ return { kind: 'always_on' };
97
+ if (/^claude-opus-5\b/i.test(modelId)) {
98
+ return { kind: 'send', thinking: { type: 'disabled' }, maxEffort: 'high' };
99
+ }
100
+ if (/^claude-sonnet-5\b/i.test(modelId))
101
+ return { kind: 'send', thinking: { type: 'disabled' } };
102
+ return { kind: 'omit' };
103
+ }
64
104
  //# sourceMappingURL=model-thinking.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-thinking.js","sourceRoot":"","sources":["../../../../src/core/llm/providers/model-thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,mDAAmD,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC3E,CAAC;AAQD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAe,EACf,QAA8C,EAC9C,kBAAsC;IAEtC,IAAI,CAAC,QAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9D,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,kBAAkB,IAAI,CAAC,EAAE,CAAC;AAChF,CAAC"}
1
+ {"version":3,"file":"model-thinking.js","sourceRoot":"","sources":["../../../../src/core/llm/providers/model-thinking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,mDAAmD,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC3E,CAAC;AAQD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAe,EACf,QAAsD,EACtD,kBAAsC;IAEtC,IAAI,CAAC,QAAQ,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9D,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,kBAAkB,IAAI,CAAC,EAAE,CAAC;AAChF,CAAC;AAqBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,IAAI,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAClF,CAAC;IACD,IAAI,wCAAwC,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACzF,IAAI,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7E,CAAC;IACD,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC;IACjG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC"}
@@ -11,9 +11,13 @@
11
11
  * into the native Gemini body).
12
12
  *
13
13
  * Native providers strip these keys at their payload boundary; the
14
- * OpenRouterProvider keeps spreading everything. Vendor-specific extras a
15
- * caller legitimately aims at a native vendor (e.g. Anthropic `metadata`)
16
- * pass through untouched.
14
+ * OpenRouterProvider keeps them. Gemini's request fields (`thinkingConfig`,
15
+ * `topK`, `safetySettings`, ...) are the mirror case: GeminiProvider consumes
16
+ * them, and every other provider strips them, so a Gemini call that fails
17
+ * over does not hand them to OpenAI or Anthropic, which reject unknown
18
+ * top-level fields with HTTP 400. Vendor-specific extras a caller
19
+ * legitimately aims at a native vendor (e.g. Anthropic `metadata`) pass
20
+ * through untouched.
17
21
  */
18
22
  /**
19
23
  * OpenRouter request-body routing controls, per its API reference:
@@ -22,10 +26,25 @@
22
26
  */
23
27
  export declare const OPENROUTER_ONLY_PARAM_KEYS: readonly ["provider", "models", "route", "transforms"];
24
28
  /**
25
- * A copy of `params` without the OpenRouter-only routing controls.
26
- * `undefined` in, or nothing surviving the strip, yields `undefined` so
27
- * callers can keep their existing `if (params)` / spread guards. Never
28
- * mutates the input — fallback legs reuse the same object.
29
+ * Gemini generateContent request fields, in the camelCase names GeminiProvider
30
+ * accepts through `customModelParams` (it moves `thinkingConfig` and `topK`
31
+ * into `generationConfig`). No other vendor's API defines them.
32
+ */
33
+ export declare const GEMINI_ONLY_PARAM_KEYS: readonly ["thinkingConfig", "topK", "safetySettings", "toolConfig", "cachedContent", "generationConfig", "systemInstruction", "responseMimeType", "responseSchema", "responseModalities", "speechConfig", "mediaResolution"];
34
+ /**
35
+ * A copy of `params` without the OpenRouter-only routing controls, for
36
+ * GeminiProvider (which handles its own Gemini fields).
29
37
  */
30
38
  export declare function stripOpenRouterOnlyParams(params: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
39
+ /**
40
+ * A copy of `params` without Gemini's request fields, for OpenRouterProvider
41
+ * (which keeps its own routing controls).
42
+ */
43
+ export declare function stripGeminiOnlyParams(params: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
44
+ /**
45
+ * A copy of `params` without OpenRouter's routing controls and Gemini's
46
+ * request fields, for native providers other than Gemini (OpenAI, Anthropic,
47
+ * Ollama).
48
+ */
49
+ export declare function stripForeignVendorParams(params: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
31
50
  //# sourceMappingURL=openrouter-only-params.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openrouter-only-params.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/providers/openrouter-only-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,wDAK7B,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAQrC"}
1
+ {"version":3,"file":"openrouter-only-params.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/providers/openrouter-only-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,wDAK7B,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,8NAazB,CAAC;AA0BX;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAErC"}
@@ -11,9 +11,13 @@
11
11
  * into the native Gemini body).
12
12
  *
13
13
  * Native providers strip these keys at their payload boundary; the
14
- * OpenRouterProvider keeps spreading everything. Vendor-specific extras a
15
- * caller legitimately aims at a native vendor (e.g. Anthropic `metadata`)
16
- * pass through untouched.
14
+ * OpenRouterProvider keeps them. Gemini's request fields (`thinkingConfig`,
15
+ * `topK`, `safetySettings`, ...) are the mirror case: GeminiProvider consumes
16
+ * them, and every other provider strips them, so a Gemini call that fails
17
+ * over does not hand them to OpenAI or Anthropic, which reject unknown
18
+ * top-level fields with HTTP 400. Vendor-specific extras a caller
19
+ * legitimately aims at a native vendor (e.g. Anthropic `metadata`) pass
20
+ * through untouched.
17
21
  */
18
22
  /**
19
23
  * OpenRouter request-body routing controls, per its API reference:
@@ -27,20 +31,65 @@ export const OPENROUTER_ONLY_PARAM_KEYS = [
27
31
  'transforms',
28
32
  ];
29
33
  /**
30
- * A copy of `params` without the OpenRouter-only routing controls.
31
- * `undefined` in, or nothing surviving the strip, yields `undefined` so
32
- * callers can keep their existing `if (params)` / spread guards. Never
33
- * mutates the input — fallback legs reuse the same object.
34
+ * Gemini generateContent request fields, in the camelCase names GeminiProvider
35
+ * accepts through `customModelParams` (it moves `thinkingConfig` and `topK`
36
+ * into `generationConfig`). No other vendor's API defines them.
34
37
  */
35
- export function stripOpenRouterOnlyParams(params) {
38
+ export const GEMINI_ONLY_PARAM_KEYS = [
39
+ 'thinkingConfig',
40
+ 'topK',
41
+ 'safetySettings',
42
+ 'toolConfig',
43
+ 'cachedContent',
44
+ 'generationConfig',
45
+ 'systemInstruction',
46
+ 'responseMimeType',
47
+ 'responseSchema',
48
+ 'responseModalities',
49
+ 'speechConfig',
50
+ 'mediaResolution',
51
+ ];
52
+ /** Keys no native provider other than their own vendor accepts. */
53
+ const FOREIGN_VENDOR_PARAM_KEYS = [
54
+ ...OPENROUTER_ONLY_PARAM_KEYS,
55
+ ...GEMINI_ONLY_PARAM_KEYS,
56
+ ];
57
+ /**
58
+ * A copy of `params` without `keys`. `undefined` in, or nothing surviving the
59
+ * strip, yields `undefined` so callers can keep their existing `if (params)` /
60
+ * spread guards. Never mutates the input — fallback legs reuse the same object.
61
+ */
62
+ function withoutKeys(params, keys) {
36
63
  if (!params)
37
64
  return undefined;
38
65
  let stripped;
39
66
  for (const key of Object.keys(params)) {
40
- if (OPENROUTER_ONLY_PARAM_KEYS.includes(key))
67
+ if (keys.includes(key))
41
68
  continue;
42
69
  (stripped ?? (stripped = {}))[key] = params[key];
43
70
  }
44
71
  return stripped;
45
72
  }
73
+ /**
74
+ * A copy of `params` without the OpenRouter-only routing controls, for
75
+ * GeminiProvider (which handles its own Gemini fields).
76
+ */
77
+ export function stripOpenRouterOnlyParams(params) {
78
+ return withoutKeys(params, OPENROUTER_ONLY_PARAM_KEYS);
79
+ }
80
+ /**
81
+ * A copy of `params` without Gemini's request fields, for OpenRouterProvider
82
+ * (which keeps its own routing controls).
83
+ */
84
+ export function stripGeminiOnlyParams(params) {
85
+ return withoutKeys(params, GEMINI_ONLY_PARAM_KEYS);
86
+ }
87
+ /**
88
+ * A copy of `params` without OpenRouter's routing controls and Gemini's
89
+ * request fields, for native providers other than Gemini (OpenAI, Anthropic,
90
+ * Ollama).
91
+ */
92
+ export function stripForeignVendorParams(params) {
93
+ return withoutKeys(params, FOREIGN_VENDOR_PARAM_KEYS);
94
+ }
46
95
  //# sourceMappingURL=openrouter-only-params.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openrouter-only-params.js","sourceRoot":"","sources":["../../../../src/core/llm/providers/openrouter-only-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,UAAU;IACV,QAAQ;IACR,OAAO;IACP,YAAY;CACJ,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAA2C;IAE3C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,QAA6C,CAAC;IAClD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAK,0BAAgD,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QAC9E,CAAC,QAAQ,KAAR,QAAQ,GAAK,EAAE,EAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"openrouter-only-params.js","sourceRoot":"","sources":["../../../../src/core/llm/providers/openrouter-only-params.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,UAAU;IACV,QAAQ;IACR,OAAO;IACP,YAAY;CACJ,CAAC;AAEX;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,gBAAgB;IAChB,MAAM;IACN,gBAAgB;IAChB,YAAY;IACZ,eAAe;IACf,kBAAkB;IAClB,mBAAmB;IACnB,kBAAkB;IAClB,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;IACd,iBAAiB;CACT,CAAC;AAEX,mEAAmE;AACnE,MAAM,yBAAyB,GAAsB;IACnD,GAAG,0BAA0B;IAC7B,GAAG,sBAAsB;CAC1B,CAAC;AAEF;;;;GAIG;AACH,SAAS,WAAW,CAClB,MAA2C,EAC3C,IAAuB;IAEvB,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,QAA6C,CAAC;IAClD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QACjC,CAAC,QAAQ,KAAR,QAAQ,GAAK,EAAE,EAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAA2C;IAE3C,OAAO,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAA2C;IAE3C,OAAO,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAA2C;IAE3C,OAAO,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @module core/llm/providers/url-secrets
3
+ *
4
+ * Masks the secrets a provider request carries out of error text. fetch
5
+ * (undici) names secrets in three rejection messages:
6
+ *
7
+ * - `Failed to parse URL from <url>` for a base URL it cannot parse,
8
+ * - `Request cannot be constructed from a URL that includes credentials: <url>`
9
+ * for a base URL with `user:password@`,
10
+ * - `Headers.append: "<value>" is an invalid header value.` for a header
11
+ * value it rejects, which quotes an API key sent in a header.
12
+ *
13
+ * Providers and `embedText` pass every such message through
14
+ * {@link redactUrlSecrets} before it reaches an error, a log line or a span.
15
+ * This module has no imports, so any layer can use it without a cycle.
16
+ */
17
+ /**
18
+ * The credentials part of a base URL, read from the raw string: the text
19
+ * between the authority start (after a leading `scheme://` or `//`, else the
20
+ * start of a scheme-less URL) and the last `@`. The last `@` is used because
21
+ * an email-style username carries its own `@`, and the raw string because a
22
+ * URL that fails to parse (for example with a `/` in the password) still
23
+ * appears verbatim in fetch's error.
24
+ *
25
+ * @param baseUrl Configured base URL.
26
+ * @returns The credentials substring, or undefined when there is none.
27
+ */
28
+ export declare function baseUrlCredentials(baseUrl: string | undefined): string | undefined;
29
+ /**
30
+ * Masks the secrets a request carries out of a message: any credentials in
31
+ * the base URL and each known secret (API keys, whether they travel in the
32
+ * URL or in a header). The known values are replaced literally, since a
33
+ * pattern cannot tell where arbitrary credentials end.
34
+ *
35
+ * @param message Text that may contain the request URL or a header value.
36
+ * @param baseUrl Configured base URL.
37
+ * @param knownSecrets Other secrets the request carried, such as API keys.
38
+ * Empty and undefined entries are ignored.
39
+ * @returns The message with those secrets replaced by `[redacted]`.
40
+ */
41
+ export declare function redactUrlSecrets(message: string, baseUrl: string | undefined, knownSecrets?: ReadonlyArray<string | undefined>): string;
42
+ //# sourceMappingURL=url-secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-secrets.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/providers/url-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAQlF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,YAAY,GAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAM,GACnD,MAAM,CAYR"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @module core/llm/providers/url-secrets
3
+ *
4
+ * Masks the secrets a provider request carries out of error text. fetch
5
+ * (undici) names secrets in three rejection messages:
6
+ *
7
+ * - `Failed to parse URL from <url>` for a base URL it cannot parse,
8
+ * - `Request cannot be constructed from a URL that includes credentials: <url>`
9
+ * for a base URL with `user:password@`,
10
+ * - `Headers.append: "<value>" is an invalid header value.` for a header
11
+ * value it rejects, which quotes an API key sent in a header.
12
+ *
13
+ * Providers and `embedText` pass every such message through
14
+ * {@link redactUrlSecrets} before it reaches an error, a log line or a span.
15
+ * This module has no imports, so any layer can use it without a cycle.
16
+ */
17
+ /**
18
+ * The credentials part of a base URL, read from the raw string: the text
19
+ * between the authority start (after a leading `scheme://` or `//`, else the
20
+ * start of a scheme-less URL) and the last `@`. The last `@` is used because
21
+ * an email-style username carries its own `@`, and the raw string because a
22
+ * URL that fails to parse (for example with a `/` in the password) still
23
+ * appears verbatim in fetch's error.
24
+ *
25
+ * @param baseUrl Configured base URL.
26
+ * @returns The credentials substring, or undefined when there is none.
27
+ */
28
+ export function baseUrlCredentials(baseUrl) {
29
+ if (!baseUrl)
30
+ return undefined;
31
+ // Only a leading scheme or `//` opens the authority; a `//` later in the
32
+ // path must not move the start past the credentials.
33
+ const scheme = /^[a-z][a-z\d+.-]*:\/\//i.exec(baseUrl);
34
+ const start = scheme ? scheme[0].length : baseUrl.startsWith('//') ? 2 : 0;
35
+ const at = baseUrl.lastIndexOf('@');
36
+ return at > start ? baseUrl.slice(start, at) : undefined;
37
+ }
38
+ /**
39
+ * Masks the secrets a request carries out of a message: any credentials in
40
+ * the base URL and each known secret (API keys, whether they travel in the
41
+ * URL or in a header). The known values are replaced literally, since a
42
+ * pattern cannot tell where arbitrary credentials end.
43
+ *
44
+ * @param message Text that may contain the request URL or a header value.
45
+ * @param baseUrl Configured base URL.
46
+ * @param knownSecrets Other secrets the request carried, such as API keys.
47
+ * Empty and undefined entries are ignored.
48
+ * @returns The message with those secrets replaced by `[redacted]`.
49
+ */
50
+ export function redactUrlSecrets(message, baseUrl, knownSecrets = []) {
51
+ // Longest first, so a key that also appears inside the credentials cannot
52
+ // split them before the whole credentials string is replaced.
53
+ const secrets = [baseUrlCredentials(baseUrl), ...knownSecrets]
54
+ .filter((secret) => Boolean(secret))
55
+ .sort((a, b) => b.length - a.length);
56
+ let out = message;
57
+ for (const secret of secrets)
58
+ out = out.split(secret).join('[redacted]');
59
+ // Backstops for any other key= value or //user:password@ credentials.
60
+ return out
61
+ .replace(/([?&]key=)[^&\s"')]+/g, '$1[redacted]')
62
+ .replace(/(\/\/)[^/\s@"')]+@/g, '$1[redacted]@');
63
+ }
64
+ //# sourceMappingURL=url-secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-secrets.js","sourceRoot":"","sources":["../../../../src/core/llm/providers/url-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA2B;IAC5D,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,yEAAyE;IACzE,qDAAqD;IACrD,MAAM,MAAM,GAAG,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,OAA2B,EAC3B,eAAkD,EAAE;IAEpD,0EAA0E;IAC1E,8DAA8D;IAC9D,MAAM,OAAO,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,GAAG,YAAY,CAAC;SAC3D,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;SACrD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,GAAG,GAAG,OAAO,CAAC;IAClB,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzE,sEAAsE;IACtE,OAAO,GAAG;SACP,OAAO,CAAC,uBAAuB,EAAE,cAAc,CAAC;SAChD,OAAO,CAAC,qBAAqB,EAAE,eAAe,CAAC,CAAC;AACrD,CAAC"}
@@ -2,14 +2,15 @@
2
2
  * @fileoverview Backpressure batching wrapper for provider streaming chunks (`ModelCompletionResponse`).
3
3
  * Combines small, high-frequency deltas into larger aggregated chunks to reduce downstream
4
4
  * dispatch overhead (websocket emissions, DOM updates, etc.) while preserving core invariants:
5
- * - Text remains append-only (merged into a single `responseTextDelta` per batch).
5
+ * - Text remains append-only (merged into a single `responseTextDelta` per batch), and so does
6
+ * reasoning-summary text (`reasoningTextDelta`), kept apart from it.
6
7
  * - Tool/function argument deltas merged per (choiceIndex, toolCallId) into single consolidated delta.
7
8
  * - Exactly one terminal chunk with `isFinal: true` (forwarded from original final chunk).
8
9
  * - Usage & error surfaced only when FINAL chunk encountered (or if intermediate provider error semantics change).
9
10
  *
10
11
  * Flush Triggers (any):
11
12
  * 1. Latency: maxLatencyMs elapsed since first unflushed chunk arrival.
12
- * 2. Size: accumulated text delta length >= maxTextDeltaChars.
13
+ * 2. Size: accumulated text and reasoning delta length >= maxTextDeltaChars.
13
14
  * 3. Chunk Count: buffer size >= maxChunksPerBatch.
14
15
  * 4. Explicit final provider chunk.
15
16
  * 5. Manual tool argument size threshold (maxToolArgumentChars) exceeded.
@@ -28,7 +29,7 @@ import { ModelCompletionResponse } from '../providers/IProvider';
28
29
  export interface StreamingBatcherOptions {
29
30
  /** Max wall-clock latency before forcing a flush (milliseconds). */
30
31
  maxLatencyMs?: number;
31
- /** Max accumulated text delta characters before flush. */
32
+ /** Max accumulated text delta characters (answer and reasoning text together) before flush. */
32
33
  maxTextDeltaChars?: number;
33
34
  /** Max accumulated tool argument characters (combined per tool call) before flush. */
34
35
  maxToolArgumentChars?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"StreamingBatcher.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/streaming/StreamingBatcher.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sFAAsF;IACtF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAuGD;;;;;GAKG;AACH,wBAAuB,WAAW,CAChC,MAAM,EAAE,cAAc,CAAC,uBAAuB,EAAE,IAAI,EAAE,SAAS,CAAC,EAChE,OAAO,GAAE,uBAA4B,GACpC,cAAc,CAAC,uBAAuB,EAAE,IAAI,EAAE,SAAS,CAAC,CA0E1D;AAED,sFAAsF;AACtF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAoC;gBACpC,OAAO,GAAE,uBAA4B;IAGjD,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,uBAAuB,EAAE,IAAI,EAAE,SAAS,CAAC;CAGvE;AAED,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"StreamingBatcher.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/streaming/StreamingBatcher.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+FAA+F;IAC/F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sFAAsF;IACtF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA2GD;;;;;GAKG;AACH,wBAAuB,WAAW,CAChC,MAAM,EAAE,cAAc,CAAC,uBAAuB,EAAE,IAAI,EAAE,SAAS,CAAC,EAChE,OAAO,GAAE,uBAA4B,GACpC,cAAc,CAAC,uBAAuB,EAAE,IAAI,EAAE,SAAS,CAAC,CA2E1D;AAED,sFAAsF;AACtF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAAoC;gBACpC,OAAO,GAAE,uBAA4B;IAGjD,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC,uBAAuB,EAAE,IAAI,EAAE,SAAS,CAAC;CAGvE;AAED,eAAe,gBAAgB,CAAC"}
@@ -10,6 +10,8 @@ function accumulate(state, chunk) {
10
10
  state.chunks.push(chunk);
11
11
  if (chunk.responseTextDelta)
12
12
  state.textBuffer += chunk.responseTextDelta;
13
+ if (chunk.reasoningTextDelta)
14
+ state.reasoningBuffer += chunk.reasoningTextDelta;
13
15
  if (chunk.toolCallsDeltas) {
14
16
  for (const d of chunk.toolCallsDeltas) {
15
17
  const key = `${d.index}|${d.id || '_'}`;
@@ -53,6 +55,7 @@ function buildBatch(state, batchSequence, isFinalOverride = false) {
53
55
  modelId: first.modelId,
54
56
  choices: first.choices, // assume stable choice metadata
55
57
  responseTextDelta: state.textBuffer.length > 0 ? state.textBuffer : undefined,
58
+ reasoningTextDelta: state.reasoningBuffer.length > 0 ? state.reasoningBuffer : undefined,
56
59
  toolCallsDeltas: mergedToolCalls.length > 0 ? mergedToolCalls : undefined,
57
60
  // Only propagate usage/error when final provider chunk present.
58
61
  usage: finalProviderChunk?.usage,
@@ -66,6 +69,7 @@ function buildBatch(state, batchSequence, isFinalOverride = false) {
66
69
  // Reset state for next batch
67
70
  state.chunks = [];
68
71
  state.textBuffer = '';
72
+ state.reasoningBuffer = '';
69
73
  state.toolBuffers = {};
70
74
  state.firstChunkAt = 0;
71
75
  return batched;
@@ -77,7 +81,7 @@ function shouldFlush(state, opts) {
77
81
  const now = Date.now();
78
82
  if (state.firstChunkAt && (now - state.firstChunkAt) >= opts.maxLatencyMs)
79
83
  return true;
80
- if (state.textBuffer.length >= opts.maxTextDeltaChars)
84
+ if (state.textBuffer.length + state.reasoningBuffer.length >= opts.maxTextDeltaChars)
81
85
  return true;
82
86
  if (state.chunks.length >= opts.maxChunksPerBatch)
83
87
  return true;
@@ -96,7 +100,7 @@ function shouldFlush(state, opts) {
96
100
  export async function* batchStream(stream, options = {}) {
97
101
  const opts = { ...DEFAULT_BATCHER_OPTIONS, ...options };
98
102
  let batchSequence = 0;
99
- const state = { chunks: [], textBuffer: '', toolBuffers: {}, firstChunkAt: 0 };
103
+ const state = { chunks: [], textBuffer: '', reasoningBuffer: '', toolBuffers: {}, firstChunkAt: 0 };
100
104
  const flush = (isFinal = false) => {
101
105
  const chunk = buildBatch(state, batchSequence++, isFinal);
102
106
  if (chunk && !opts.annotateBatches) {
@@ -137,11 +141,12 @@ export async function* batchStream(stream, options = {}) {
137
141
  }
138
142
  // Flush buffered chunks first, then emit final chunk.
139
143
  let preFinal = flush(false);
140
- if (!preFinal && state.textBuffer) {
144
+ if (!preFinal && (state.textBuffer || state.reasoningBuffer)) {
141
145
  preFinal = {
142
146
  ...state.chunks[0],
143
147
  id: `${state.chunks[0]?.id || 'chunk'}-batch-${batchSequence++}`,
144
148
  responseTextDelta: state.textBuffer || undefined,
149
+ reasoningTextDelta: state.reasoningBuffer || undefined,
145
150
  isFinal: false,
146
151
  };
147
152
  }