@tyvm/knowhow 0.0.144 → 0.0.146

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 (253) hide show
  1. package/bin/knowhow.js +22 -20
  2. package/package.json +1 -1
  3. package/scripts/migrate-usage-json.js +147 -0
  4. package/src/agents/base/base.ts +65 -10
  5. package/src/agents/tools/patch.ts +84 -2
  6. package/src/agents/tools/textSearch.ts +98 -3
  7. package/src/chat/CliChatService.ts +16 -0
  8. package/src/chat/modules/AgentModule.ts +159 -29
  9. package/src/chat/modules/SessionsModule.ts +13 -5
  10. package/src/chat/types.ts +15 -0
  11. package/src/chat.ts +11 -0
  12. package/src/cli.ts +2 -0
  13. package/src/clients/anthropic.ts +80 -1
  14. package/src/clients/contextLimits.ts +40 -0
  15. package/src/clients/fireworks.ts +3 -0
  16. package/src/clients/gemini.ts +67 -5
  17. package/src/clients/http.ts +85 -4
  18. package/src/clients/index.ts +4 -0
  19. package/src/clients/openai.ts +186 -35
  20. package/src/clients/pricing/fireworks.ts +50 -1
  21. package/src/clients/pricing/index.ts +1 -1
  22. package/src/clients/pricing/models.ts +3 -1
  23. package/src/clients/pricing/openai.ts +2 -2
  24. package/src/clients/pricing/qwen.ts +80 -0
  25. package/src/clients/qwen.ts +16 -0
  26. package/src/clients/types.ts +99 -8
  27. package/src/clients/xai.ts +96 -8
  28. package/src/commands/agent.ts +29 -1
  29. package/src/commands/services.ts +49 -3
  30. package/src/index.ts +9 -0
  31. package/src/plugins/plugins.ts +16 -0
  32. package/src/processors/Base64ImageDetector.ts +46 -7
  33. package/src/processors/GemmaToolProcessor.ts +163 -0
  34. package/src/processors/TokenCompressor.ts +40 -8
  35. package/src/processors/ToolResponseCache.ts +17 -8
  36. package/src/processors/index.ts +1 -0
  37. package/src/processors/tools/boundedToolResponse.ts +49 -0
  38. package/src/processors/tools/grepToolResponse.ts +164 -38
  39. package/src/processors/tools/index.ts +2 -0
  40. package/src/processors/tools/jqToolResponse.ts +40 -10
  41. package/src/processors/tools/listStoredToolResponses.ts +51 -10
  42. package/src/processors/tools/tailToolResponse.ts +85 -17
  43. package/src/services/AgentSyncFs.ts +37 -0
  44. package/src/services/LazyToolsService.ts +7 -0
  45. package/src/services/Mcp.ts +9 -2
  46. package/src/services/RuntimeReloadService.ts +31 -0
  47. package/src/services/SessionManager.ts +14 -0
  48. package/src/services/Tools.ts +14 -0
  49. package/src/services/TracingService.ts +116 -0
  50. package/src/services/index.ts +8 -0
  51. package/src/services/modules/computerUse.ts +216 -0
  52. package/src/services/modules/index.ts +90 -9
  53. package/src/services/modules/types.ts +31 -1
  54. package/src/types.ts +3 -0
  55. package/src/util/Trace.ts +236 -0
  56. package/tests/clients/contextLimits.test.ts +4 -0
  57. package/tests/clients/fireworks.test.ts +65 -0
  58. package/tests/clients/openai.images.test.ts +105 -0
  59. package/tests/clients/pricing.test.ts +6 -0
  60. package/tests/clients/reasoningEffort.test.ts +79 -0
  61. package/tests/compressor/toolResponseCache.test.ts +2 -1
  62. package/tests/compressor/usageBase64.json +159 -0
  63. package/tests/compressor/usageBase64.test.ts +175 -0
  64. package/tests/manual/clients/completions.test.ts +27 -10
  65. package/tests/patching/fixtures/transcript-mangles/agent-sync-fs-nested-catch.json +9 -0
  66. package/tests/patching/fixtures/transcript-mangles/automation-functions-crossed.json +9 -0
  67. package/tests/patching/fixtures/transcript-mangles/fruit-ninja-confirmed-retirement.json +8 -0
  68. package/tests/patching/patchFileOutput.test.ts +112 -1
  69. package/tests/patching/transcriptMangleRegression.test.ts +125 -0
  70. package/tests/processors/Base64ImageDetector.test.ts +36 -1
  71. package/tests/processors/TokenCompressor.test.ts +17 -3
  72. package/tests/processors/tools/boundedRetrievalTools.test.ts +68 -0
  73. package/tests/processors/tools/grepToolResponse.test.ts +88 -1
  74. package/tests/unit/plugins/pluginLoading.test.ts +31 -0
  75. package/tests/unit/services/RuntimeReloadService.test.ts +29 -0
  76. package/ts_build/package.json +1 -1
  77. package/ts_build/src/agents/base/base.d.ts +8 -1
  78. package/ts_build/src/agents/base/base.js +37 -3
  79. package/ts_build/src/agents/base/base.js.map +1 -1
  80. package/ts_build/src/agents/tools/patch.d.ts +1 -0
  81. package/ts_build/src/agents/tools/patch.js +35 -2
  82. package/ts_build/src/agents/tools/patch.js.map +1 -1
  83. package/ts_build/src/agents/tools/textSearch.js +56 -2
  84. package/ts_build/src/agents/tools/textSearch.js.map +1 -1
  85. package/ts_build/src/chat/CliChatService.js +15 -0
  86. package/ts_build/src/chat/CliChatService.js.map +1 -1
  87. package/ts_build/src/chat/modules/AgentModule.d.ts +14 -1
  88. package/ts_build/src/chat/modules/AgentModule.js +86 -24
  89. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  90. package/ts_build/src/chat/modules/SessionsModule.js +5 -6
  91. package/ts_build/src/chat/modules/SessionsModule.js.map +1 -1
  92. package/ts_build/src/chat/types.d.ts +12 -0
  93. package/ts_build/src/chat.js +7 -0
  94. package/ts_build/src/chat.js.map +1 -1
  95. package/ts_build/src/cli.d.ts +2 -1
  96. package/ts_build/src/cli.js +1 -0
  97. package/ts_build/src/cli.js.map +1 -1
  98. package/ts_build/src/clients/anthropic.d.ts +1 -0
  99. package/ts_build/src/clients/anthropic.js +40 -1
  100. package/ts_build/src/clients/anthropic.js.map +1 -1
  101. package/ts_build/src/clients/contextLimits.js +25 -0
  102. package/ts_build/src/clients/contextLimits.js.map +1 -1
  103. package/ts_build/src/clients/fireworks.js +1 -0
  104. package/ts_build/src/clients/fireworks.js.map +1 -1
  105. package/ts_build/src/clients/gemini.js +56 -4
  106. package/ts_build/src/clients/gemini.js.map +1 -1
  107. package/ts_build/src/clients/http.d.ts +2 -0
  108. package/ts_build/src/clients/http.js +66 -9
  109. package/ts_build/src/clients/http.js.map +1 -1
  110. package/ts_build/src/clients/index.d.ts +1 -0
  111. package/ts_build/src/clients/index.js +4 -0
  112. package/ts_build/src/clients/index.js.map +1 -1
  113. package/ts_build/src/clients/openai.d.ts +6 -1
  114. package/ts_build/src/clients/openai.js +135 -35
  115. package/ts_build/src/clients/openai.js.map +1 -1
  116. package/ts_build/src/clients/pricing/fireworks.d.ts +4 -1
  117. package/ts_build/src/clients/pricing/fireworks.js +33 -1
  118. package/ts_build/src/clients/pricing/fireworks.js.map +1 -1
  119. package/ts_build/src/clients/pricing/index.d.ts +1 -1
  120. package/ts_build/src/clients/pricing/index.js +6 -2
  121. package/ts_build/src/clients/pricing/index.js.map +1 -1
  122. package/ts_build/src/clients/pricing/models.d.ts +2 -1
  123. package/ts_build/src/clients/pricing/models.js +4 -1
  124. package/ts_build/src/clients/pricing/models.js.map +1 -1
  125. package/ts_build/src/clients/pricing/openai.js +2 -2
  126. package/ts_build/src/clients/pricing/openai.js.map +1 -1
  127. package/ts_build/src/clients/pricing/qwen.d.ts +5 -0
  128. package/ts_build/src/clients/pricing/qwen.js +30 -0
  129. package/ts_build/src/clients/pricing/qwen.js.map +1 -0
  130. package/ts_build/src/clients/qwen.d.ts +4 -0
  131. package/ts_build/src/clients/qwen.js +15 -0
  132. package/ts_build/src/clients/qwen.js.map +1 -0
  133. package/ts_build/src/clients/types.d.ts +16 -1
  134. package/ts_build/src/clients/types.js +14 -0
  135. package/ts_build/src/clients/types.js.map +1 -1
  136. package/ts_build/src/clients/xai.d.ts +2 -0
  137. package/ts_build/src/clients/xai.js +79 -13
  138. package/ts_build/src/clients/xai.js.map +1 -1
  139. package/ts_build/src/commands/agent.js +15 -1
  140. package/ts_build/src/commands/agent.js.map +1 -1
  141. package/ts_build/src/commands/services.d.ts +2 -0
  142. package/ts_build/src/commands/services.js +45 -3
  143. package/ts_build/src/commands/services.js.map +1 -1
  144. package/ts_build/src/index.d.ts +2 -0
  145. package/ts_build/src/index.js +1 -0
  146. package/ts_build/src/index.js.map +1 -1
  147. package/ts_build/src/plugins/plugins.d.ts +1 -0
  148. package/ts_build/src/plugins/plugins.js +14 -0
  149. package/ts_build/src/plugins/plugins.js.map +1 -1
  150. package/ts_build/src/processors/Base64ImageDetector.js +22 -3
  151. package/ts_build/src/processors/Base64ImageDetector.js.map +1 -1
  152. package/ts_build/src/processors/GemmaToolProcessor.d.ts +14 -0
  153. package/ts_build/src/processors/GemmaToolProcessor.js +97 -0
  154. package/ts_build/src/processors/GemmaToolProcessor.js.map +1 -0
  155. package/ts_build/src/processors/TokenCompressor.js +15 -6
  156. package/ts_build/src/processors/TokenCompressor.js.map +1 -1
  157. package/ts_build/src/processors/ToolResponseCache.d.ts +3 -3
  158. package/ts_build/src/processors/ToolResponseCache.js +8 -8
  159. package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
  160. package/ts_build/src/processors/index.d.ts +1 -0
  161. package/ts_build/src/processors/index.js +3 -1
  162. package/ts_build/src/processors/index.js.map +1 -1
  163. package/ts_build/src/processors/tools/boundedToolResponse.d.ts +7 -0
  164. package/ts_build/src/processors/tools/boundedToolResponse.js +27 -0
  165. package/ts_build/src/processors/tools/boundedToolResponse.js.map +1 -0
  166. package/ts_build/src/processors/tools/grepToolResponse.d.ts +4 -0
  167. package/ts_build/src/processors/tools/grepToolResponse.js +101 -25
  168. package/ts_build/src/processors/tools/grepToolResponse.js.map +1 -1
  169. package/ts_build/src/processors/tools/index.d.ts +2 -2
  170. package/ts_build/src/processors/tools/index.js.map +1 -1
  171. package/ts_build/src/processors/tools/jqToolResponse.d.ts +5 -1
  172. package/ts_build/src/processors/tools/jqToolResponse.js +26 -9
  173. package/ts_build/src/processors/tools/jqToolResponse.js.map +1 -1
  174. package/ts_build/src/processors/tools/listStoredToolResponses.d.ts +7 -1
  175. package/ts_build/src/processors/tools/listStoredToolResponses.js +39 -9
  176. package/ts_build/src/processors/tools/listStoredToolResponses.js.map +1 -1
  177. package/ts_build/src/processors/tools/tailToolResponse.d.ts +5 -0
  178. package/ts_build/src/processors/tools/tailToolResponse.js +56 -13
  179. package/ts_build/src/processors/tools/tailToolResponse.js.map +1 -1
  180. package/ts_build/src/services/AgentSyncFs.js +17 -0
  181. package/ts_build/src/services/AgentSyncFs.js.map +1 -1
  182. package/ts_build/src/services/LazyToolsService.d.ts +1 -0
  183. package/ts_build/src/services/LazyToolsService.js +5 -0
  184. package/ts_build/src/services/LazyToolsService.js.map +1 -1
  185. package/ts_build/src/services/Mcp.js +8 -2
  186. package/ts_build/src/services/Mcp.js.map +1 -1
  187. package/ts_build/src/services/RuntimeReloadService.d.ts +12 -0
  188. package/ts_build/src/services/RuntimeReloadService.js +26 -0
  189. package/ts_build/src/services/RuntimeReloadService.js.map +1 -0
  190. package/ts_build/src/services/SessionManager.js +12 -0
  191. package/ts_build/src/services/SessionManager.js.map +1 -1
  192. package/ts_build/src/services/Tools.d.ts +3 -0
  193. package/ts_build/src/services/Tools.js +5 -0
  194. package/ts_build/src/services/Tools.js.map +1 -1
  195. package/ts_build/src/services/TracingService.d.ts +16 -0
  196. package/ts_build/src/services/TracingService.js +35 -0
  197. package/ts_build/src/services/TracingService.js.map +1 -0
  198. package/ts_build/src/services/index.d.ts +6 -0
  199. package/ts_build/src/services/index.js +7 -1
  200. package/ts_build/src/services/index.js.map +1 -1
  201. package/ts_build/src/services/modules/computerUse.d.ts +163 -0
  202. package/ts_build/src/services/modules/computerUse.js +3 -0
  203. package/ts_build/src/services/modules/computerUse.js.map +1 -0
  204. package/ts_build/src/services/modules/index.d.ts +6 -0
  205. package/ts_build/src/services/modules/index.js +49 -6
  206. package/ts_build/src/services/modules/index.js.map +1 -1
  207. package/ts_build/src/services/modules/types.d.ts +7 -0
  208. package/ts_build/src/types.d.ts +3 -0
  209. package/ts_build/src/types.js.map +1 -1
  210. package/ts_build/src/util/Trace.d.ts +13 -0
  211. package/ts_build/src/util/Trace.js +107 -0
  212. package/ts_build/src/util/Trace.js.map +1 -0
  213. package/ts_build/src/workers/tools/index.d.ts +1 -1
  214. package/ts_build/tests/clients/contextLimits.test.js +2 -0
  215. package/ts_build/tests/clients/contextLimits.test.js.map +1 -1
  216. package/ts_build/tests/clients/fireworks.test.d.ts +1 -0
  217. package/ts_build/tests/clients/fireworks.test.js +65 -0
  218. package/ts_build/tests/clients/fireworks.test.js.map +1 -0
  219. package/ts_build/tests/clients/openai.images.test.d.ts +1 -0
  220. package/ts_build/tests/clients/openai.images.test.js +94 -0
  221. package/ts_build/tests/clients/openai.images.test.js.map +1 -0
  222. package/ts_build/tests/clients/pricing.test.js +4 -0
  223. package/ts_build/tests/clients/pricing.test.js.map +1 -1
  224. package/ts_build/tests/clients/reasoningEffort.test.d.ts +1 -0
  225. package/ts_build/tests/clients/reasoningEffort.test.js +68 -0
  226. package/ts_build/tests/clients/reasoningEffort.test.js.map +1 -0
  227. package/ts_build/tests/compressor/toolResponseCache.test.js +1 -1
  228. package/ts_build/tests/compressor/toolResponseCache.test.js.map +1 -1
  229. package/ts_build/tests/compressor/usageBase64.test.d.ts +1 -0
  230. package/ts_build/tests/compressor/usageBase64.test.js +109 -0
  231. package/ts_build/tests/compressor/usageBase64.test.js.map +1 -0
  232. package/ts_build/tests/manual/clients/completions.test.js +19 -6
  233. package/ts_build/tests/manual/clients/completions.test.js.map +1 -1
  234. package/ts_build/tests/patching/patchFileOutput.test.js +82 -0
  235. package/ts_build/tests/patching/patchFileOutput.test.js.map +1 -1
  236. package/ts_build/tests/patching/transcriptMangleRegression.test.d.ts +1 -0
  237. package/ts_build/tests/patching/transcriptMangleRegression.test.js +104 -0
  238. package/ts_build/tests/patching/transcriptMangleRegression.test.js.map +1 -0
  239. package/ts_build/tests/processors/Base64ImageDetector.test.js +24 -0
  240. package/ts_build/tests/processors/Base64ImageDetector.test.js.map +1 -1
  241. package/ts_build/tests/processors/TokenCompressor.test.js +11 -2
  242. package/ts_build/tests/processors/TokenCompressor.test.js.map +1 -1
  243. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.d.ts +1 -0
  244. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js +57 -0
  245. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js.map +1 -0
  246. package/ts_build/tests/processors/tools/grepToolResponse.test.js +37 -0
  247. package/ts_build/tests/processors/tools/grepToolResponse.test.js.map +1 -1
  248. package/ts_build/tests/unit/plugins/pluginLoading.test.js +59 -0
  249. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
  250. package/ts_build/tests/unit/services/RuntimeReloadService.test.d.ts +1 -0
  251. package/ts_build/tests/unit/services/RuntimeReloadService.test.js +26 -0
  252. package/ts_build/tests/unit/services/RuntimeReloadService.test.js.map +1 -0
  253. package/x-home.png +0 -0
@@ -1,4 +1,4 @@
1
- import { ModelPricing } from "./types";
1
+ import { ModelPricing, ModelCatalogEntry, completions, embeddings } from "./types";
2
2
 
3
3
  /**
4
4
  * Fireworks AI model IDs, pricing, and catalog.
@@ -101,3 +101,52 @@ export const FireworksEmbeddingPricing: Record<string, ModelPricing> = {
101
101
  // Qwen3 Reranker 8B — $0.20/M tokens, context 40k
102
102
  [FireworksModels.Qwen3Reranker8b]: { input: 0.20, output: 0.20 },
103
103
  };
104
+
105
+
106
+ // ─── Active text models (non-deprecated) ─────────────────────────────────────
107
+
108
+ export const FireworksActiveTextModels: string[] = [
109
+ // Moonshot AI
110
+ FireworksModels.KimiK3,
111
+ FireworksModels.KimiK2p7Code,
112
+ FireworksModels.KimiK2_6,
113
+ FireworksModels.KimiK2_5,
114
+ // MiniMax
115
+ FireworksModels.MinimaxM3,
116
+ FireworksModels.MinimaxM2_7,
117
+ FireworksModels.MinimaxM2_5,
118
+ // Qwen
119
+ FireworksModels.Qwen3p7Plus,
120
+ // Z.ai
121
+ FireworksModels.Glm5p2,
122
+ FireworksModels.Glm5p1,
123
+ // DeepSeek AI
124
+ FireworksModels.DeepseekV4Pro,
125
+ FireworksModels.DeepseekV4Flash,
126
+ // OpenAI OSS
127
+ FireworksModels.GptOss120b,
128
+ ];
129
+
130
+ export const FireworksDeprecatedTextModels: string[] = [
131
+ FireworksModels.Qwen3_6Plus,
132
+ FireworksModels.Qwen3p6Plus,
133
+ FireworksModels.Qwen3Vl30bA3bThinking,
134
+ FireworksModels.Qwen3Vl30bA3bInstruct,
135
+ FireworksModels.Qwen3_8b,
136
+ FireworksModels.Glm5,
137
+ FireworksModels.Glm4_7,
138
+ FireworksModels.DeepseekV3_2,
139
+ FireworksModels.DeepseekV3_1,
140
+ ];
141
+
142
+ // ─── Catalog ──────────────────────────────────────────────────────────────────
143
+
144
+ export const FIREWORKS_MODEL_CATALOG: ModelCatalogEntry[] = [
145
+ ...completions(FireworksActiveTextModels, "fireworks", FireworksTextPricing),
146
+ ...completions(FireworksDeprecatedTextModels, "fireworks", FireworksTextPricing),
147
+ ...embeddings(
148
+ [FireworksModels.Qwen3Embedding8b, FireworksModels.Qwen3Reranker8b],
149
+ "fireworks",
150
+ FireworksEmbeddingPricing,
151
+ ),
152
+ ];
@@ -35,7 +35,7 @@ export { GitHubModelsTextPricing } from "./github";
35
35
  export { OpenRouterTextPricing } from "./openrouter";
36
36
  export { LlamaTextPricing } from "./llama";
37
37
  export { CopilotTextPricing, CopilotModelMultipliers } from "./copilot";
38
- export { FireworksTextPricing } from "./fireworks";
38
+ export { FireworksTextPricing, FireworksEmbeddingPricing, FIREWORKS_MODEL_CATALOG, FireworksActiveTextModels, FireworksDeprecatedTextModels } from "./fireworks";
39
39
  export { MetaTextPricing, MetaWebSearchPricingPer1000Queries } from "./meta";
40
40
 
41
41
  // ─── Combined catalog ─────────────────────────────────────────────────────────
@@ -7,17 +7,19 @@ import { OPENAI_MODEL_CATALOG } from "./openai";
7
7
  import { ANTHROPIC_MODEL_CATALOG } from "./anthropic";
8
8
  import { GOOGLE_MODEL_CATALOG } from "./google";
9
9
  import { XAI_MODEL_CATALOG } from "./xai";
10
+ import { FIREWORKS_MODEL_CATALOG } from "./fireworks";
10
11
 
11
12
  export { ModelPricing, ModelType, ModelCatalogEntry };
12
13
 
13
14
  /** 2.5% platform markup applied on top of all provider base rates */
14
15
  export const USAGE_MARKUP_PERCENT = 2.5 / 100;
15
16
 
16
- export { OPENAI_MODEL_CATALOG, ANTHROPIC_MODEL_CATALOG, GOOGLE_MODEL_CATALOG, XAI_MODEL_CATALOG };
17
+ export { OPENAI_MODEL_CATALOG, ANTHROPIC_MODEL_CATALOG, GOOGLE_MODEL_CATALOG, XAI_MODEL_CATALOG, FIREWORKS_MODEL_CATALOG };
17
18
 
18
19
  export const ALL_MODEL_CATALOG: ModelCatalogEntry[] = [
19
20
  ...OPENAI_MODEL_CATALOG,
20
21
  ...ANTHROPIC_MODEL_CATALOG,
21
22
  ...GOOGLE_MODEL_CATALOG,
22
23
  ...XAI_MODEL_CATALOG,
24
+ ...FIREWORKS_MODEL_CATALOG,
23
25
  ];
@@ -232,8 +232,8 @@ export const OpenAiSearchModels: string[] = [
232
232
  export const OpenAiTextPricing: Record<string, ModelPricing> = {
233
233
  // gpt-5.6 series — short context / long context pricing
234
234
  [OpenAiModels.GPT_56_Sol]: { input: 5.0, cached_input: 0.5, cache_write: 6.25, output: 30.0, input_gt_200k: 10.0, output_gt_200k: 45.0 },
235
- [OpenAiModels.GPT_56_Terra]: { input: 2.5, cached_input: 0.25, cache_write: 3.125, output: 15.0, input_gt_200k: 5.0, output_gt_200k: 22.5 },
236
- [OpenAiModels.GPT_56_Luna]: { input: 1.0, cached_input: 0.10, cache_write: 1.25, output: 6.0, input_gt_200k: 2.0, output_gt_200k: 9.0 },
235
+ [OpenAiModels.GPT_56_Terra]: { input: 2.0, cached_input: 0.20, cache_write: 2.5, output: 12.0, input_gt_200k: 4.0, output_gt_200k: 18.0 },
236
+ [OpenAiModels.GPT_56_Luna]: { input: 0.2, cached_input: 0.02, cache_write: 0.25, output: 1.2, input_gt_200k: 0.4, output_gt_200k: 1.8 },
237
237
  [OpenAiModels.GPT_55]: { input: 5.0, cached_input: 0.5, output: 30.0 },
238
238
  [OpenAiModels.GPT_55_Pro]: { input: 30.0, cached_input: 0, output: 180.0, reasoningLevels: ["medium", "high", "xhigh"] },
239
239
  [OpenAiModels.GPT_54]: { input: 2.5, cached_input: 0.25, output: 15.0 },
@@ -0,0 +1,80 @@
1
+ /**
2
+ * QWEN Cloud pricing (USD per 1M tokens)
3
+ * Source: https://home.qwencloud.com/data/api.json?product=AliyunDeliveryService&action=ListModelSeries
4
+ * International DashScope endpoint: https://dashscope-intl.aliyuncs.com/compatible-mode/v1
5
+ * Last updated: 2026-08-03
6
+ *
7
+ * Notes:
8
+ * - Several Qwen models use tiered pricing based on input context length.
9
+ * We use the standard tier (≤256k) as the base price here.
10
+ * - DeepSeek and GLM models are also available via QwenCloud's DashScope endpoint.
11
+ * - Video/image/audio generation models have per-second/per-image pricing (not per-token)
12
+ * and are NOT included in QwenTextPricing.
13
+ */
14
+
15
+ export const QwenTextPricing: Record<string, { input: number; output: number; cached_input?: number }> = {
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Qwen3.8 series (newest flagship, released 2026-08)
19
+ // ---------------------------------------------------------------------------
20
+ // qwen3.8-max: $2/$6, implicit cache: $0.25, explicit cache creation: $2.5, explicit cache read: $0.17
21
+ "qwen3.8-max": { input: 2.00, output: 6.00, cached_input: 0.25 },
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // Qwen3.7 series
25
+ // ---------------------------------------------------------------------------
26
+ // qwen3.7-plus: tiered — ≤256k: $0.4/$1.6, 256k-1M: $1.2/$4.8
27
+ // implicit cache: $0.08 (≤256k), explicit cache creation: $0.5, explicit cache read: $0.04
28
+ "qwen3.7-plus": { input: 0.40, output: 1.60, cached_input: 0.08 },
29
+ "qwen3.7-plus-2026-05-26": { input: 0.40, output: 1.60, cached_input: 0.08 },
30
+
31
+ // qwen3.7-flash: tiered — ≤32k: $0.03/$0.13, 32k-256k: $0.10/$0.40, 256k-1M: $0.20/$0.80
32
+ "qwen3.7-flash": { input: 0.03, output: 0.13, cached_input: 0.006 },
33
+ "qwen3.7-flash-2026-07-15": { input: 0.03, output: 0.13, cached_input: 0.006 },
34
+
35
+ // qwen3.7-max: $2.50/$7.50, cache: $0.50
36
+ "qwen3.7-max": { input: 2.50, output: 7.50, cached_input: 0.50 },
37
+ "qwen3.7-max-2026-06-08": { input: 2.50, output: 7.50, cached_input: 0.50 },
38
+ "qwen3.7-max-2026-05-20": { input: 2.50, output: 7.50 },
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // Qwen3.6 series
42
+ // ---------------------------------------------------------------------------
43
+ // qwen3.6-flash: tiered — ≤256k: $0.25/$1.50, 256k-1M: $1.00/$4.00
44
+ "qwen3.6-flash": { input: 0.25, output: 1.50, cached_input: 0.025 },
45
+ "qwen3.6-flash-2026-04-16": { input: 0.25, output: 1.50 },
46
+ // qwen3.6-plus: tiered — ≤256k: $0.50/$3.00, 256k-1M: $2.00/$6.00
47
+ "qwen3.6-plus": { input: 0.50, output: 3.00, cached_input: 0.05 },
48
+ "qwen3.6-plus-2026-04-02": { input: 0.50, output: 3.00 },
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // Legacy alias models (qwen-turbo, qwen-plus, qwen-max, qwen-long)
52
+ // These are rolling aliases that point to the latest generation.
53
+ // ---------------------------------------------------------------------------
54
+ "qwen-turbo": { input: 0.05, output: 0.20, cached_input: 0.005 },
55
+ "qwen-turbo-latest": { input: 0.05, output: 0.20, cached_input: 0.005 },
56
+ "qwen-plus": { input: 0.40, output: 1.20, cached_input: 0.04 },
57
+ "qwen-plus-latest": { input: 0.40, output: 1.20, cached_input: 0.04 },
58
+ "qwen-max": { input: 0.861, output: 3.44, cached_input: 0.086 },
59
+ "qwen-max-latest": { input: 0.861, output: 3.44, cached_input: 0.086 },
60
+ // qwen-long: extended context up to 10M tokens
61
+ "qwen-long": { input: 0.05, output: 0.20, cached_input: 0.005 },
62
+
63
+ // ---------------------------------------------------------------------------
64
+ // DeepSeek models (available via QwenCloud/DashScope endpoint)
65
+ // ---------------------------------------------------------------------------
66
+ // DeepSeek-V4-Flash: lightweight MoE, 284B params, 13B activated, 1M context
67
+ "deepseek-v4-flash": { input: 0.20, output: 0.40, cached_input: 0.04 },
68
+ "deepseek-v4-flash-0731": { input: 0.20, output: 0.40, cached_input: 0.04 },
69
+ // DeepSeek-V4-Pro: flagship MoE, 1.6T params, 49B activated, 1M context
70
+ "deepseek-v4-pro": { input: 2.40, output: 4.80, cached_input: 0.20 },
71
+ // DeepSeek-V3.2: sparse attention, 128k context
72
+ // explicit cache creation: $0.713, explicit cache read: $0.057
73
+ "deepseek-v3.2": { input: 0.57, output: 1.71, cached_input: 0.114 },
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // GLM models (Zhipu AI, available via QwenCloud/DashScope endpoint)
77
+ // ---------------------------------------------------------------------------
78
+ // GLM-5.2-Fast-Preview: 1M context, high-speed inference
79
+ "glm-5.2-fast-preview": { input: 2.80, output: 8.80, cached_input: 0.56 },
80
+ };
@@ -0,0 +1,16 @@
1
+ import { HttpClient } from "./http";
2
+ import { QwenTextPricing } from "./pricing/qwen";
3
+
4
+ /**
5
+ * QWEN Cloud client — OpenAI-compatible API
6
+ * https://dashscope-intl.aliyuncs.com/compatible-mode/v1
7
+ * Alibaba Cloud's Qwen model family via the international DashScope endpoint.
8
+ * Set env var QWEN_CLOUD_API_KEY to enable.
9
+ */
10
+ export class GenericQwenClient extends HttpClient {
11
+ constructor(apiKey = process.env.QWEN_CLOUD_API_KEY) {
12
+ super("https://dashscope-intl.aliyuncs.com/compatible-mode/v1");
13
+ if (apiKey) this.setJwt(apiKey);
14
+ this.setPrices(QwenTextPricing);
15
+ }
16
+ }
@@ -8,7 +8,10 @@ export type ModelModality =
8
8
 
9
9
  export type MessageContent =
10
10
  | { type: "text"; text: string }
11
- | { type: "image_url"; image_url: { url: string } }
11
+ | {
12
+ type: "image_url";
13
+ image_url: { url: string; detail?: "auto" | "low" | "high" };
14
+ }
12
15
  | { type: "audio_url"; audio_url: { url: string } }
13
16
  | { type: "video_url"; video_url: { url: string } };
14
17
 
@@ -23,6 +26,50 @@ export interface Message {
23
26
 
24
27
  export interface OutputMessage extends Message {
25
28
  content?: string | null;
29
+ /**
30
+ * The model's reasoning/thinking content, when the provider exposes it.
31
+ * - OpenAI Responses API: a human-readable summary of the model's reasoning
32
+ * (populated when reasoning_summary is requested).
33
+ */
34
+ reasoning_summary?: string;
35
+ /**
36
+ * OpenAI Responses API only (internal): the raw reasoning output items
37
+ * (carrying encrypted_content) captured from a stateless response. These are
38
+ * re-injected into the next request's input to preserve the reasoning chain.
39
+ * Not intended for display.
40
+ *
41
+ * @deprecated Prefer the provider-agnostic `_reasoning_details` slot. This is
42
+ * retained for backward compatibility with the OpenAI client only.
43
+ */
44
+ _reasoning_items?: any[];
45
+ /**
46
+ * Provider-agnostic (internal): an opaque, provider-tagged carrier for the
47
+ * model's reasoning artifact that must be round-tripped verbatim on the next
48
+ * tool-use turn to preserve reasoning continuity. Each provider stashes its
49
+ * own native artifact here and re-injects it only when the `provider` tag
50
+ * matches, so provider-specific payload never leaks into the generic
51
+ * (OpenAI-format) message shape.
52
+ *
53
+ * - openai / xai: Responses API `reasoning` output items (encrypted_content)
54
+ * - anthropic: `thinking` / `redacted_thinking` blocks (with signature/data)
55
+ * - gemini: `thoughtSignature` strings keyed by tool-call id (+ thought parts)
56
+ *
57
+ * Not intended for display.
58
+ */
59
+ _reasoning_details?: ReasoningDetails;
60
+ }
61
+
62
+ /**
63
+ * Opaque, provider-tagged reasoning artifact. The `items` are provider-native
64
+ * and only meaningful to the client whose id matches `provider`; any other
65
+ * client must ignore them (they are never mapped into a foreign provider's
66
+ * request payload).
67
+ */
68
+ export interface ReasoningDetails {
69
+ /** The provider that produced these items, e.g. "openai" | "xai" | "anthropic" | "gemini". */
70
+ provider: string;
71
+ /** Provider-native reasoning items to round-trip verbatim on the next turn. */
72
+ items: any[];
26
73
  }
27
74
 
28
75
  export interface ToolProp {
@@ -30,6 +77,7 @@ export interface ToolProp {
30
77
  description?: string;
31
78
  properties?: { [key: string]: ToolProp };
32
79
  items?: ToolProp;
80
+ enum?: any[];
33
81
  }
34
82
 
35
83
  export interface Tool {
@@ -88,6 +136,26 @@ export interface RetryOptions {
88
136
  signal?: AbortSignal;
89
137
  }
90
138
 
139
+ /**
140
+ * Every reasoning-effort spelling currently exposed by a supported provider.
141
+ * Individual models may support only a subset; provider clients are responsible
142
+ * for translating or clamping values where their APIs require it.
143
+ */
144
+ export const REASONING_EFFORTS = [
145
+ "none",
146
+ "minimal",
147
+ "low",
148
+ "medium",
149
+ "high",
150
+ "xhigh",
151
+ "max",
152
+ ] as const;
153
+ export type ReasoningEffort = (typeof REASONING_EFFORTS)[number];
154
+
155
+ export function isReasoningEffort(value: unknown): value is ReasoningEffort {
156
+ return typeof value === "string" && REASONING_EFFORTS.includes(value as ReasoningEffort);
157
+ }
158
+
91
159
  export interface CompletionOptions extends RetryOptions {
92
160
  model: string;
93
161
  messages: Message[];
@@ -99,14 +167,17 @@ export interface CompletionOptions extends RetryOptions {
99
167
  * Maps to: OpenAI reasoning_effort/reasoning.effort, xAI reasoning.effort,
100
168
  * Gemini thinkingLevel/thinkingBudget, Anthropic thinking mode.
101
169
  *
102
- * "none" = disable thinking entirely (Anthropic: thinking.type="disabled",
103
- * OpenAI: reasoning.effort="none"). Only supported by models that
104
- * allow disabling thinking (e.g. claude-sonnet-5).
105
- * "low" = minimal thinking
106
- * "medium" = balanced (default for most models)
107
- * "high" = maximum reasoning
170
+ * "none" = disable thinking where supported
171
+ * "minimal" = provider-defined minimum (for example Gemini/OpenAI)
172
+ * "low" = low reasoning
173
+ * "medium" = balanced reasoning
174
+ * "high" = high reasoning
175
+ * "xhigh" = extra-high reasoning (for example OpenAI/xAI/Anthropic)
176
+ * "max" = maximum reasoning (Anthropic)
177
+ *
178
+ * A model may support only a subset of these provider-level values.
108
179
  */
109
- reasoning_effort?: "none" | "low" | "medium" | "high";
180
+ reasoning_effort?: ReasoningEffort;
110
181
  /**
111
182
  * When true, request a summarized view of the model's thinking process.
112
183
  * - Anthropic: thinking.display = "summarized"
@@ -114,6 +185,20 @@ export interface CompletionOptions extends RetryOptions {
114
185
  * Defaults to false (no summary displayed).
115
186
  */
116
187
  reasoning_summary?: boolean;
188
+ /**
189
+ * OpenAI Responses API only: when true, OpenAI stores the response server-side
190
+ * so subsequent turns can reference it via `previous_response_id` instead of
191
+ * resending the full reasoning/message history. Defaults to false (stateless).
192
+ * When false, the client automatically requests `reasoning.encrypted_content`
193
+ * and threads the reasoning items back in the next request's input.
194
+ */
195
+ store?: boolean;
196
+ /**
197
+ * OpenAI Responses API only: the id of a previously-stored response to continue
198
+ * from. Only meaningful when `store` was true on the prior request. When set,
199
+ * the model keeps its prior chain-of-thought instead of re-deriving it.
200
+ */
201
+ previous_response_id?: string;
117
202
  /**
118
203
  * When true, hints to the client that this task is long-running and it should
119
204
  * use a long-TTL cache where available.
@@ -165,6 +250,12 @@ export interface CompletionResponse {
165
250
  model: string;
166
251
  usage: TokenUsage | undefined;
167
252
  usd_cost?: number;
253
+ /**
254
+ * OpenAI Responses API only: the id of this response. When `store` was true,
255
+ * this can be passed as `previous_response_id` on the next request to continue
256
+ * the reasoning chain without resending history.
257
+ */
258
+ response_id?: string;
168
259
  }
169
260
 
170
261
  /** A single chunk yielded by a streaming completion. */
@@ -52,6 +52,15 @@ export class GenericXAIClient implements GenericClient {
52
52
  });
53
53
  }
54
54
 
55
+ resolveLegacyReasoningEffort(
56
+ effort: CompletionOptions["reasoning_effort"]
57
+ ): "low" | "medium" | "high" | undefined {
58
+ if (effort === undefined || effort === "none") return undefined;
59
+ if (effort === "minimal") return "low";
60
+ if (effort === "xhigh" || effort === "max") return "high";
61
+ return effort;
62
+ }
63
+
55
64
  async createChatCompletion(
56
65
  options: CompletionOptions
57
66
  ): Promise<CompletionResponse> {
@@ -72,13 +81,14 @@ export class GenericXAIClient implements GenericClient {
72
81
  return msg as ChatCompletionMessageParam;
73
82
  });
74
83
 
84
+ const reasoningEffort = this.resolveLegacyReasoningEffort(options.reasoning_effort);
75
85
  const response = await this.client.chat.completions.create({
76
86
  model: options.model,
77
87
  messages: xaiMessages,
78
88
  max_tokens: options.max_tokens,
79
- ...(XaiReasoningModels.includes(options.model) && options.reasoning_effort && options.reasoning_effort !== "none" && {
89
+ ...(XaiReasoningModels.includes(options.model) && reasoningEffort && {
80
90
  // grok-3-mini models support reasoning_effort: "low" | "medium" | "high"
81
- reasoning_effort: options.reasoning_effort as "low" | "medium" | "high",
91
+ reasoning_effort: reasoningEffort,
82
92
  }),
83
93
  ...(options.tools && {
84
94
  tools: options.tools,
@@ -116,6 +126,20 @@ export class GenericXAIClient implements GenericClient {
116
126
  * Used for grok-4.20 reasoning/non-reasoning and multi-agent models.
117
127
  * Translates Chat Completions message format to Responses API format.
118
128
  */
129
+ /**
130
+ * Resolve the xai-native reasoning items (Responses API `reasoning` items
131
+ * with encrypted_content) to re-inject for an assistant message, reading the
132
+ * provider-agnostic `_reasoning_details` slot only when it was produced by
133
+ * this provider.
134
+ */
135
+ private getReasoningItems(msg: any): any[] {
136
+ const details = msg?._reasoning_details;
137
+ if (details && details.provider === "xai" && Array.isArray(details.items)) {
138
+ return details.items;
139
+ }
140
+ return [];
141
+ }
142
+
119
143
  async createChatResponse(
120
144
  options: CompletionOptions
121
145
  ): Promise<CompletionResponse> {
@@ -133,22 +157,46 @@ export class GenericXAIClient implements GenericClient {
133
157
  .trim() || undefined;
134
158
 
135
159
  // Convert chat messages to Responses API input items
160
+ // Responses API hard limit: 10,485,760 chars per function_call_output.output
161
+ const MAX_TOOL_OUTPUT = 10_485_000;
162
+ const truncateToolOutput = (s: string) =>
163
+ s.length > MAX_TOOL_OUTPUT
164
+ ? s.slice(0, MAX_TOOL_OUTPUT) + "\n\n[TRUNCATED: output exceeded 10MB API limit]"
165
+ : s;
136
166
  const input: any[] = nonSystemMessages.map((msg) => {
137
167
  if (msg.role === "tool") {
138
168
  return {
139
169
  type: "function_call_output",
140
170
  call_id: msg.tool_call_id,
141
- output: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
171
+ output: truncateToolOutput(typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)),
142
172
  };
143
173
  }
144
174
  if (msg.role === "assistant" && msg.tool_calls?.length) {
145
- return msg.tool_calls.map((tc) => ({
175
+ // Re-inject any captured reasoning items (encrypted_content) BEFORE the
176
+ // function_call items so the model keeps its chain-of-thought instead of
177
+ // re-deriving it from scratch each turn.
178
+ const reasoningItems = this.getReasoningItems(msg);
179
+ return [
180
+ ...reasoningItems,
181
+ ...msg.tool_calls.map((tc) => ({
146
182
  type: "function_call",
147
183
  id: tc.id.startsWith("fc") ? tc.id : `fc_${tc.id}`,
148
184
  call_id: tc.id,
149
185
  name: tc.function.name,
150
186
  arguments: tc.function.arguments,
151
- }));
187
+ })),
188
+ ];
189
+ }
190
+ if (msg.role === "assistant" && this.getReasoningItems(msg).length) {
191
+ // assistant message (no tool calls) that carried reasoning items →
192
+ // re-inject reasoning items, then the visible message content.
193
+ return [
194
+ ...this.getReasoningItems(msg),
195
+ {
196
+ role: msg.role,
197
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
198
+ },
199
+ ];
152
200
  }
153
201
  return {
154
202
  role: msg.role,
@@ -168,8 +216,17 @@ export class GenericXAIClient implements GenericClient {
168
216
  // Resolve reasoning effort, clamping to supported levels if defined in pricing
169
217
  const pricing = XaiTextPricing[options.model];
170
218
  const supportedLevels = pricing?.reasoningLevels;
171
- let reasoningEffort: string | undefined = options.reasoning_effort;
172
- if (supportedLevels?.length) {
219
+ const requestedEffort = options.reasoning_effort;
220
+ let reasoningEffort: string | undefined;
221
+ if (requestedEffort !== "none") {
222
+ reasoningEffort =
223
+ requestedEffort === "minimal"
224
+ ? "low"
225
+ : requestedEffort === "max"
226
+ ? "xhigh"
227
+ : requestedEffort;
228
+ }
229
+ if (requestedEffort !== "none" && supportedLevels?.length) {
173
230
  if (!reasoningEffort || !supportedLevels.includes(reasoningEffort)) {
174
231
  reasoningEffort = supportedLevels[0];
175
232
  }
@@ -182,7 +239,18 @@ export class GenericXAIClient implements GenericClient {
182
239
  ...(options.max_tokens && { max_output_tokens: Math.max(options.max_tokens, 16_000) }),
183
240
  ...(reasoningEffort && { reasoning: { effort: reasoningEffort } }),
184
241
  ...(tools?.length && { tools, tool_choice: "auto" }),
185
- store: false,
242
+ // Reasoning persistence (same construct as OpenAI's Responses API):
243
+ // - store === true → xAI persists the response; next turn passes
244
+ // previous_response_id to continue the reasoning chain server-side.
245
+ // - store !== true → stateless; request encrypted reasoning content so
246
+ // we can thread the reasoning items back into the next request ourselves.
247
+ store: options.store === true,
248
+ ...(options.previous_response_id && {
249
+ previous_response_id: options.previous_response_id,
250
+ }),
251
+ ...(options.store !== true && reasoningEffort && {
252
+ include: ["reasoning.encrypted_content"],
253
+ }),
186
254
  };
187
255
 
188
256
  const response = await fetch("https://api.x.ai/v1/responses", {
@@ -218,6 +286,10 @@ export class GenericXAIClient implements GenericClient {
218
286
  // Collect text content and tool calls from output items
219
287
  let textContent: string | null = null;
220
288
  const toolCalls: any[] = [];
289
+ // Reasoning items (with encrypted_content) to thread back into the next
290
+ // turn, plus a human-readable summary of the model's thinking (if present).
291
+ const reasoningItems: any[] = [];
292
+ let reasoningSummary: string | null = null;
221
293
 
222
294
  for (const item of data.output ?? []) {
223
295
  if (item.type === "message") {
@@ -226,6 +298,17 @@ export class GenericXAIClient implements GenericClient {
226
298
  textContent = (textContent ?? "") + part.text;
227
299
  }
228
300
  }
301
+ } else if (item.type === "reasoning") {
302
+ // Keep the raw reasoning item so it can be re-injected next turn
303
+ // (carries encrypted_content when include was requested).
304
+ reasoningItems.push(item);
305
+ const summaryParts = item.summary ?? [];
306
+ for (const part of summaryParts) {
307
+ const text = typeof part === "string" ? part : part?.text;
308
+ if (text) {
309
+ reasoningSummary = (reasoningSummary ?? "") + text;
310
+ }
311
+ }
229
312
  } else if (item.type === "function_call") {
230
313
  toolCalls.push({
231
314
  id: item.call_id,
@@ -245,12 +328,17 @@ export class GenericXAIClient implements GenericClient {
245
328
  role: "assistant",
246
329
  content: textContent,
247
330
  ...(toolCalls.length > 0 && { tool_calls: toolCalls }),
331
+ ...(reasoningSummary && { reasoning_summary: reasoningSummary }),
332
+ ...(reasoningItems.length > 0 && {
333
+ _reasoning_details: { provider: "xai", items: reasoningItems },
334
+ }),
248
335
  },
249
336
  },
250
337
  ],
251
338
  model: options.model,
252
339
  usage,
253
340
  usd_cost: usdCost,
341
+ response_id: data.id,
254
342
  };
255
343
  }
256
344
 
@@ -8,6 +8,7 @@ import { SessionsModule } from "../chat/modules/SessionsModule";
8
8
  import { SetupModule } from "../chat/modules/SetupModule";
9
9
  import { PlainRenderer } from "../chat/renderer/PlainRenderer";
10
10
  import { loadRenderer } from "../chat/renderer/loadRenderer";
11
+ import { isReasoningEffort, REASONING_EFFORTS } from "../clients/types";
11
12
  import { getConfig } from "../config";
12
13
 
13
14
  async function setupRenderer(chatService: any, rendererSpecifier: string): Promise<void> {
@@ -55,6 +56,10 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
55
56
  )
56
57
  .option("--model <model>", "Specific model for the provider")
57
58
  .option("--agent-name <name>", "Which agent to use", "Patcher")
59
+ .option(
60
+ "--reasoning-effort <effort>",
61
+ `Reasoning effort: ${REASONING_EFFORTS.join(", ")}. Individual models support different subsets.`
62
+ )
58
63
  .option(
59
64
  "--max-time-limit <minutes>",
60
65
  "Time limit for agent execution (minutes)",
@@ -99,6 +104,14 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
99
104
  )
100
105
  .action(async (options) => {
101
106
  try {
107
+ if (
108
+ options.reasoningEffort !== undefined &&
109
+ !isReasoningEffort(options.reasoningEffort)
110
+ ) {
111
+ throw new Error(
112
+ `Invalid reasoning effort "${options.reasoningEffort}". Expected one of: ${REASONING_EFFORTS.join(", ")}.`
113
+ );
114
+ }
102
115
  const { setupServices } = await import("./services");
103
116
  await setupServices();
104
117
  const chatService = getChatService();
@@ -116,17 +129,29 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
116
129
  options.taskId,
117
130
  options.messageId
118
131
  );
132
+ // Restore the exact model/provider/reasoning the original run used
133
+ // (falls back to agent defaults when not persisted / remote-only).
134
+ const savedSettings = await agentModule.loadTaskSettings(
135
+ options.taskId,
136
+ options.messageId
137
+ );
119
138
  const resumeInput =
120
139
  options.input || "Please continue from where you left off.";
121
140
 
122
141
  await agentModule.initialize(chatService);
123
142
  const { taskCompleted: resumed } =
124
143
  await agentModule.resumeFromMessages({
125
- agentName: options.agentName || "Patcher",
144
+ agentName:
145
+ options.agentName || savedSettings.agentName || "Patcher",
126
146
  input: resumeInput,
127
147
  threads,
128
148
  messageId: options.messageId,
129
149
  taskId: options.taskId,
150
+ // CLI-provided model/provider still win over persisted ones.
151
+ model: options.model || savedSettings.model,
152
+ provider: options.provider || savedSettings.provider,
153
+ reasoningEffort: savedSettings.reasoningEffort,
154
+ summarizeReasoning: savedSettings.summarizeReasoning,
130
155
  });
131
156
  await resumed;
132
157
  return;
@@ -208,6 +233,9 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
208
233
  input,
209
234
  maxTimeLimit: parseInt(options.maxTimeLimit, 10),
210
235
  maxSpendLimit: parseFloat(options.maxSpendLimit),
236
+ ...(options.reasoningEffort
237
+ ? { reasoningEffort: options.reasoningEffort }
238
+ : {}),
211
239
  ...(behaviorSystemPrompt ? { systemPrompt: behaviorSystemPrompt } : {}),
212
240
  ...(behaviorModel ? { model: behaviorModel } : {}),
213
241
  run: true,