@tyvm/knowhow 0.0.145 → 0.0.147

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 (320) hide show
  1. package/autodoc/cli-reference.md +36 -7
  2. package/bin/knowhow.js +8 -6
  3. package/package.json +1 -1
  4. package/src/agents/base/base.ts +24 -0
  5. package/src/agents/historyRollback.ts +36 -0
  6. package/src/agents/tools/startAgentTask.ts +41 -9
  7. package/src/auth/browserLogin.ts +9 -3
  8. package/src/auth/keyAuth.ts +115 -0
  9. package/src/auth/keyManager.ts +166 -0
  10. package/src/chat/CliChatService.ts +16 -0
  11. package/src/chat/modules/AgentModule.ts +144 -56
  12. package/src/chat/modules/AskModule.ts +2 -0
  13. package/src/chat/modules/BaseChatModule.ts +0 -1
  14. package/src/chat/modules/CustomCommandsModule.ts +2 -0
  15. package/src/chat/modules/InternalChatModule.ts +2 -0
  16. package/src/chat/modules/RemoteSyncModule.ts +4 -0
  17. package/src/chat/modules/RendererModule.ts +2 -0
  18. package/src/chat/modules/SearchModule.ts +2 -0
  19. package/src/chat/modules/SessionsModule.ts +110 -39
  20. package/src/chat/modules/SetupModule.ts +2 -0
  21. package/src/chat/modules/ShellCommandModule.ts +2 -0
  22. package/src/chat/modules/SystemModule.ts +2 -0
  23. package/src/chat/types.ts +5 -2
  24. package/src/cli.ts +1 -1
  25. package/src/clients/anthropic.ts +24 -0
  26. package/src/clients/fireworks.ts +3 -0
  27. package/src/clients/gemini.ts +8 -0
  28. package/src/clients/index.ts +2 -0
  29. package/src/clients/openai.ts +7 -4
  30. package/src/clients/types.ts +30 -7
  31. package/src/clients/xai.ts +23 -4
  32. package/src/commands/agent.ts +11 -39
  33. package/src/commands/agents.ts +403 -53
  34. package/src/commands/misc.ts +3 -2
  35. package/src/commands/services.ts +49 -3
  36. package/src/login.ts +89 -28
  37. package/src/plugins/plugins.ts +16 -0
  38. package/src/processors/TokenCompressor.ts +40 -8
  39. package/src/processors/ToolResponseCache.ts +17 -8
  40. package/src/processors/tools/boundedToolResponse.ts +49 -0
  41. package/src/processors/tools/grepToolResponse.ts +164 -38
  42. package/src/processors/tools/index.ts +2 -0
  43. package/src/processors/tools/jqToolResponse.ts +40 -10
  44. package/src/processors/tools/listStoredToolResponses.ts +51 -10
  45. package/src/processors/tools/tailToolResponse.ts +85 -17
  46. package/src/services/AgentService.ts +2 -0
  47. package/src/services/AgentSyncFs.ts +65 -0
  48. package/src/services/AgentSyncKnowhowWeb.ts +22 -4
  49. package/src/services/BehaviorsService.ts +2 -0
  50. package/src/services/DockerService.ts +2 -0
  51. package/src/services/EmbeddingService.ts +2 -0
  52. package/src/services/EmbeddingsService.ts +3 -0
  53. package/src/services/KnowhowClient.ts +68 -7
  54. package/src/services/LazyToolsService.ts +16 -0
  55. package/src/services/Mcp.ts +11 -2
  56. package/src/services/McpServer.ts +2 -0
  57. package/src/services/MessageProcessor.ts +2 -0
  58. package/src/services/MinimalToolsService.ts +2 -0
  59. package/src/services/RuntimeReloadService.ts +31 -0
  60. package/src/services/SessionManager.ts +5 -0
  61. package/src/services/SkillsService.ts +2 -0
  62. package/src/services/SyncedAgentWatcher.ts +2 -0
  63. package/src/services/SyncerService.ts +23 -8
  64. package/src/services/TaskRegistry.ts +2 -0
  65. package/src/services/Tools.ts +13 -0
  66. package/src/services/TracingService.ts +116 -0
  67. package/src/services/index.ts +10 -0
  68. package/src/services/modules/index.ts +49 -3
  69. package/src/services/modules/types.ts +8 -0
  70. package/src/types.ts +2 -0
  71. package/src/util/Trace.ts +236 -0
  72. package/src/utils/http.ts +18 -2
  73. package/tests/clients/fireworks.test.ts +65 -0
  74. package/tests/clients/reasoningEffort.test.ts +79 -0
  75. package/tests/compressor/toolResponseCache.test.ts +2 -1
  76. package/tests/manual/clients/completions.test.ts +27 -10
  77. package/tests/processors/TokenCompressor.test.ts +17 -3
  78. package/tests/processors/tools/boundedRetrievalTools.test.ts +68 -0
  79. package/tests/processors/tools/grepToolResponse.test.ts +88 -1
  80. package/tests/unit/agents/historyRollback.test.ts +53 -0
  81. package/tests/unit/auth/keyAuth.test.ts +102 -0
  82. package/tests/unit/auth/keyManager.test.ts +67 -0
  83. package/tests/unit/chat/historyCommandArgs.test.ts +37 -0
  84. package/tests/unit/commands/agents.test.ts +68 -0
  85. package/tests/unit/login.test.ts +119 -0
  86. package/tests/unit/plugins/pluginLoading.test.ts +31 -0
  87. package/tests/unit/services/AgentSyncKnowhowWeb.test.ts +38 -0
  88. package/tests/unit/services/LazyToolsService.test.ts +29 -0
  89. package/tests/unit/services/RuntimeReloadService.test.ts +29 -0
  90. package/tests/unit/services/SessionManager.test.ts +43 -0
  91. package/tests/unit/services/SyncerService.test.ts +45 -0
  92. package/tests/unit/util/Trace.test.ts +119 -0
  93. package/tests/unit/utils/http.test.ts +43 -0
  94. package/ts_build/package.json +1 -1
  95. package/ts_build/src/agents/base/base.d.ts +1 -0
  96. package/ts_build/src/agents/base/base.js +31 -2
  97. package/ts_build/src/agents/base/base.js.map +1 -1
  98. package/ts_build/src/agents/historyRollback.d.ts +2 -0
  99. package/ts_build/src/agents/historyRollback.js +22 -0
  100. package/ts_build/src/agents/historyRollback.js.map +1 -0
  101. package/ts_build/src/agents/tools/startAgentTask.d.ts +2 -0
  102. package/ts_build/src/agents/tools/startAgentTask.js +36 -9
  103. package/ts_build/src/agents/tools/startAgentTask.js.map +1 -1
  104. package/ts_build/src/auth/browserLogin.d.ts +1 -0
  105. package/ts_build/src/auth/browserLogin.js +5 -2
  106. package/ts_build/src/auth/browserLogin.js.map +1 -1
  107. package/ts_build/src/auth/keyAuth.d.ts +5 -0
  108. package/ts_build/src/auth/keyAuth.js +79 -0
  109. package/ts_build/src/auth/keyAuth.js.map +1 -0
  110. package/ts_build/src/auth/keyManager.d.ts +14 -0
  111. package/ts_build/src/auth/keyManager.js +145 -0
  112. package/ts_build/src/auth/keyManager.js.map +1 -0
  113. package/ts_build/src/chat/CliChatService.js +15 -0
  114. package/ts_build/src/chat/CliChatService.js.map +1 -1
  115. package/ts_build/src/chat/modules/AgentModule.d.ts +13 -1
  116. package/ts_build/src/chat/modules/AgentModule.js +96 -43
  117. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  118. package/ts_build/src/chat/modules/AskModule.js +12 -2
  119. package/ts_build/src/chat/modules/AskModule.js.map +1 -1
  120. package/ts_build/src/chat/modules/BaseChatModule.js.map +1 -1
  121. package/ts_build/src/chat/modules/CustomCommandsModule.js +12 -2
  122. package/ts_build/src/chat/modules/CustomCommandsModule.js.map +1 -1
  123. package/ts_build/src/chat/modules/InternalChatModule.js +16 -2
  124. package/ts_build/src/chat/modules/InternalChatModule.js.map +1 -1
  125. package/ts_build/src/chat/modules/RemoteSyncModule.js +19 -2
  126. package/ts_build/src/chat/modules/RemoteSyncModule.js.map +1 -1
  127. package/ts_build/src/chat/modules/RendererModule.js +17 -2
  128. package/ts_build/src/chat/modules/RendererModule.js.map +1 -1
  129. package/ts_build/src/chat/modules/SearchModule.js +12 -2
  130. package/ts_build/src/chat/modules/SearchModule.js.map +1 -1
  131. package/ts_build/src/chat/modules/SessionsModule.d.ts +6 -0
  132. package/ts_build/src/chat/modules/SessionsModule.js +114 -24
  133. package/ts_build/src/chat/modules/SessionsModule.js.map +1 -1
  134. package/ts_build/src/chat/modules/SetupModule.js +17 -2
  135. package/ts_build/src/chat/modules/SetupModule.js.map +1 -1
  136. package/ts_build/src/chat/modules/ShellCommandModule.js +12 -2
  137. package/ts_build/src/chat/modules/ShellCommandModule.js.map +1 -1
  138. package/ts_build/src/chat/modules/SystemModule.js +12 -2
  139. package/ts_build/src/chat/modules/SystemModule.js.map +1 -1
  140. package/ts_build/src/chat/types.d.ts +5 -2
  141. package/ts_build/src/cli.js +1 -1
  142. package/ts_build/src/cli.js.map +1 -1
  143. package/ts_build/src/clients/anthropic.d.ts +1 -0
  144. package/ts_build/src/clients/anthropic.js +12 -0
  145. package/ts_build/src/clients/anthropic.js.map +1 -1
  146. package/ts_build/src/clients/fireworks.js +1 -0
  147. package/ts_build/src/clients/fireworks.js.map +1 -1
  148. package/ts_build/src/clients/gemini.js +8 -0
  149. package/ts_build/src/clients/gemini.js.map +1 -1
  150. package/ts_build/src/clients/index.js +19 -4
  151. package/ts_build/src/clients/index.js.map +1 -1
  152. package/ts_build/src/clients/openai.js +4 -2
  153. package/ts_build/src/clients/openai.js.map +1 -1
  154. package/ts_build/src/clients/types.d.ts +4 -1
  155. package/ts_build/src/clients/types.js +14 -0
  156. package/ts_build/src/clients/types.js.map +1 -1
  157. package/ts_build/src/clients/xai.d.ts +1 -0
  158. package/ts_build/src/clients/xai.js +23 -4
  159. package/ts_build/src/clients/xai.js.map +1 -1
  160. package/ts_build/src/commands/agent.js +7 -22
  161. package/ts_build/src/commands/agent.js.map +1 -1
  162. package/ts_build/src/commands/agents.d.ts +1 -1
  163. package/ts_build/src/commands/agents.js +174 -16
  164. package/ts_build/src/commands/agents.js.map +1 -1
  165. package/ts_build/src/commands/misc.js +3 -2
  166. package/ts_build/src/commands/misc.js.map +1 -1
  167. package/ts_build/src/commands/services.d.ts +2 -0
  168. package/ts_build/src/commands/services.js +45 -3
  169. package/ts_build/src/commands/services.js.map +1 -1
  170. package/ts_build/src/login.d.ts +1 -1
  171. package/ts_build/src/login.js +53 -15
  172. package/ts_build/src/login.js.map +1 -1
  173. package/ts_build/src/plugins/plugins.d.ts +1 -0
  174. package/ts_build/src/plugins/plugins.js +14 -0
  175. package/ts_build/src/plugins/plugins.js.map +1 -1
  176. package/ts_build/src/processors/TokenCompressor.js +15 -6
  177. package/ts_build/src/processors/TokenCompressor.js.map +1 -1
  178. package/ts_build/src/processors/ToolResponseCache.d.ts +3 -3
  179. package/ts_build/src/processors/ToolResponseCache.js +8 -8
  180. package/ts_build/src/processors/ToolResponseCache.js.map +1 -1
  181. package/ts_build/src/processors/tools/boundedToolResponse.d.ts +7 -0
  182. package/ts_build/src/processors/tools/boundedToolResponse.js +27 -0
  183. package/ts_build/src/processors/tools/boundedToolResponse.js.map +1 -0
  184. package/ts_build/src/processors/tools/grepToolResponse.d.ts +4 -0
  185. package/ts_build/src/processors/tools/grepToolResponse.js +101 -25
  186. package/ts_build/src/processors/tools/grepToolResponse.js.map +1 -1
  187. package/ts_build/src/processors/tools/index.d.ts +2 -2
  188. package/ts_build/src/processors/tools/index.js.map +1 -1
  189. package/ts_build/src/processors/tools/jqToolResponse.d.ts +5 -1
  190. package/ts_build/src/processors/tools/jqToolResponse.js +26 -9
  191. package/ts_build/src/processors/tools/jqToolResponse.js.map +1 -1
  192. package/ts_build/src/processors/tools/listStoredToolResponses.d.ts +7 -1
  193. package/ts_build/src/processors/tools/listStoredToolResponses.js +39 -9
  194. package/ts_build/src/processors/tools/listStoredToolResponses.js.map +1 -1
  195. package/ts_build/src/processors/tools/tailToolResponse.d.ts +5 -0
  196. package/ts_build/src/processors/tools/tailToolResponse.js +56 -13
  197. package/ts_build/src/processors/tools/tailToolResponse.js.map +1 -1
  198. package/ts_build/src/services/AgentService.js +18 -2
  199. package/ts_build/src/services/AgentService.js.map +1 -1
  200. package/ts_build/src/services/AgentSyncFs.d.ts +3 -0
  201. package/ts_build/src/services/AgentSyncFs.js +62 -15
  202. package/ts_build/src/services/AgentSyncFs.js.map +1 -1
  203. package/ts_build/src/services/AgentSyncKnowhowWeb.d.ts +2 -0
  204. package/ts_build/src/services/AgentSyncKnowhowWeb.js +28 -6
  205. package/ts_build/src/services/AgentSyncKnowhowWeb.js.map +1 -1
  206. package/ts_build/src/services/BehaviorsService.js +12 -2
  207. package/ts_build/src/services/BehaviorsService.js.map +1 -1
  208. package/ts_build/src/services/DockerService.js +20 -8
  209. package/ts_build/src/services/DockerService.js.map +1 -1
  210. package/ts_build/src/services/EmbeddingService.js +16 -2
  211. package/ts_build/src/services/EmbeddingService.js.map +1 -1
  212. package/ts_build/src/services/EmbeddingsService.js +12 -2
  213. package/ts_build/src/services/EmbeddingsService.js.map +1 -1
  214. package/ts_build/src/services/KnowhowClient.d.ts +7 -2
  215. package/ts_build/src/services/KnowhowClient.js +108 -10
  216. package/ts_build/src/services/KnowhowClient.js.map +1 -1
  217. package/ts_build/src/services/LazyToolsService.d.ts +2 -0
  218. package/ts_build/src/services/LazyToolsService.js +26 -2
  219. package/ts_build/src/services/LazyToolsService.js.map +1 -1
  220. package/ts_build/src/services/Mcp.js +20 -4
  221. package/ts_build/src/services/Mcp.js.map +1 -1
  222. package/ts_build/src/services/McpServer.js +17 -2
  223. package/ts_build/src/services/McpServer.js.map +1 -1
  224. package/ts_build/src/services/MessageProcessor.js +16 -2
  225. package/ts_build/src/services/MessageProcessor.js.map +1 -1
  226. package/ts_build/src/services/MinimalToolsService.js +16 -2
  227. package/ts_build/src/services/MinimalToolsService.js.map +1 -1
  228. package/ts_build/src/services/RuntimeReloadService.d.ts +12 -0
  229. package/ts_build/src/services/RuntimeReloadService.js +26 -0
  230. package/ts_build/src/services/RuntimeReloadService.js.map +1 -0
  231. package/ts_build/src/services/SessionManager.js +19 -2
  232. package/ts_build/src/services/SessionManager.js.map +1 -1
  233. package/ts_build/src/services/SkillsService.js +16 -2
  234. package/ts_build/src/services/SkillsService.js.map +1 -1
  235. package/ts_build/src/services/SyncedAgentWatcher.js +16 -2
  236. package/ts_build/src/services/SyncedAgentWatcher.js.map +1 -1
  237. package/ts_build/src/services/SyncerService.d.ts +1 -0
  238. package/ts_build/src/services/SyncerService.js +27 -5
  239. package/ts_build/src/services/SyncerService.js.map +1 -1
  240. package/ts_build/src/services/TaskRegistry.js +12 -2
  241. package/ts_build/src/services/TaskRegistry.js.map +1 -1
  242. package/ts_build/src/services/Tools.d.ts +1 -0
  243. package/ts_build/src/services/Tools.js +21 -2
  244. package/ts_build/src/services/Tools.js.map +1 -1
  245. package/ts_build/src/services/TracingService.d.ts +16 -0
  246. package/ts_build/src/services/TracingService.js +35 -0
  247. package/ts_build/src/services/TracingService.js.map +1 -0
  248. package/ts_build/src/services/index.d.ts +8 -0
  249. package/ts_build/src/services/index.js +9 -1
  250. package/ts_build/src/services/index.js.map +1 -1
  251. package/ts_build/src/services/modules/index.d.ts +6 -0
  252. package/ts_build/src/services/modules/index.js +29 -3
  253. package/ts_build/src/services/modules/index.js.map +1 -1
  254. package/ts_build/src/services/modules/types.d.ts +3 -0
  255. package/ts_build/src/types.d.ts +1 -0
  256. package/ts_build/src/types.js.map +1 -1
  257. package/ts_build/src/util/Trace.d.ts +11 -0
  258. package/ts_build/src/util/Trace.js +107 -0
  259. package/ts_build/src/util/Trace.js.map +1 -0
  260. package/ts_build/src/utils/http.d.ts +6 -2
  261. package/ts_build/src/utils/http.js +8 -2
  262. package/ts_build/src/utils/http.js.map +1 -1
  263. package/ts_build/tests/clients/fireworks.test.d.ts +1 -0
  264. package/ts_build/tests/clients/fireworks.test.js +65 -0
  265. package/ts_build/tests/clients/fireworks.test.js.map +1 -0
  266. package/ts_build/tests/clients/reasoningEffort.test.d.ts +1 -0
  267. package/ts_build/tests/clients/reasoningEffort.test.js +68 -0
  268. package/ts_build/tests/clients/reasoningEffort.test.js.map +1 -0
  269. package/ts_build/tests/compressor/toolResponseCache.test.js +1 -1
  270. package/ts_build/tests/compressor/toolResponseCache.test.js.map +1 -1
  271. package/ts_build/tests/manual/clients/completions.test.js +19 -6
  272. package/ts_build/tests/manual/clients/completions.test.js.map +1 -1
  273. package/ts_build/tests/processors/TokenCompressor.test.js +11 -2
  274. package/ts_build/tests/processors/TokenCompressor.test.js.map +1 -1
  275. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.d.ts +1 -0
  276. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js +57 -0
  277. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js.map +1 -0
  278. package/ts_build/tests/processors/tools/grepToolResponse.test.js +37 -0
  279. package/ts_build/tests/processors/tools/grepToolResponse.test.js.map +1 -1
  280. package/ts_build/tests/unit/agents/historyRollback.test.d.ts +1 -0
  281. package/ts_build/tests/unit/agents/historyRollback.test.js +42 -0
  282. package/ts_build/tests/unit/agents/historyRollback.test.js.map +1 -0
  283. package/ts_build/tests/unit/auth/keyAuth.test.d.ts +1 -0
  284. package/ts_build/tests/unit/auth/keyAuth.test.js +77 -0
  285. package/ts_build/tests/unit/auth/keyAuth.test.js.map +1 -0
  286. package/ts_build/tests/unit/auth/keyManager.test.d.ts +1 -0
  287. package/ts_build/tests/unit/auth/keyManager.test.js +52 -0
  288. package/ts_build/tests/unit/auth/keyManager.test.js.map +1 -0
  289. package/ts_build/tests/unit/chat/historyCommandArgs.test.d.ts +1 -0
  290. package/ts_build/tests/unit/chat/historyCommandArgs.test.js +29 -0
  291. package/ts_build/tests/unit/chat/historyCommandArgs.test.js.map +1 -0
  292. package/ts_build/tests/unit/commands/agents.test.d.ts +1 -0
  293. package/ts_build/tests/unit/commands/agents.test.js +91 -0
  294. package/ts_build/tests/unit/commands/agents.test.js.map +1 -0
  295. package/ts_build/tests/unit/login.test.d.ts +1 -0
  296. package/ts_build/tests/unit/login.test.js +97 -0
  297. package/ts_build/tests/unit/login.test.js.map +1 -0
  298. package/ts_build/tests/unit/plugins/pluginLoading.test.js +59 -0
  299. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +1 -1
  300. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.d.ts +1 -0
  301. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js +32 -0
  302. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js.map +1 -0
  303. package/ts_build/tests/unit/services/LazyToolsService.test.d.ts +1 -0
  304. package/ts_build/tests/unit/services/LazyToolsService.test.js +27 -0
  305. package/ts_build/tests/unit/services/LazyToolsService.test.js.map +1 -0
  306. package/ts_build/tests/unit/services/RuntimeReloadService.test.d.ts +1 -0
  307. package/ts_build/tests/unit/services/RuntimeReloadService.test.js +26 -0
  308. package/ts_build/tests/unit/services/RuntimeReloadService.test.js.map +1 -0
  309. package/ts_build/tests/unit/services/SessionManager.test.d.ts +1 -0
  310. package/ts_build/tests/unit/services/SessionManager.test.js +72 -0
  311. package/ts_build/tests/unit/services/SessionManager.test.js.map +1 -0
  312. package/ts_build/tests/unit/services/SyncerService.test.d.ts +1 -0
  313. package/ts_build/tests/unit/services/SyncerService.test.js +40 -0
  314. package/ts_build/tests/unit/services/SyncerService.test.js.map +1 -0
  315. package/ts_build/tests/unit/util/Trace.test.d.ts +1 -0
  316. package/ts_build/tests/unit/util/Trace.test.js +107 -0
  317. package/ts_build/tests/unit/util/Trace.test.js.map +1 -0
  318. package/ts_build/tests/unit/utils/http.test.d.ts +1 -0
  319. package/ts_build/tests/unit/utils/http.test.js +69 -0
  320. package/ts_build/tests/unit/utils/http.test.js.map +1 -0
@@ -5,11 +5,13 @@
5
5
  * Command semantics:
6
6
  * /attach <taskId> - Attach to a RUNNING session (in-memory, filesystem, or web).
7
7
  * If the task is completed, the user is told to use /resume instead.
8
- * /resume <taskId> - Resume a COMPLETED/saved session with optional additional context.
8
+ * /resume <taskId> [--rollback N] - Continue the same saved task.
9
+ * /fork <taskId> [--rollback N] - Start a new task from saved history.
9
10
  * /sessions - List sessions that can be attached to or resumed.
10
11
  * /logs [N] - Show the last N messages from the currently attached agent.
11
12
  */
12
13
  import { BaseChatModule } from "./BaseChatModule";
14
+ import { TraceAll } from "../../util/Trace";
13
15
  import { ChatCommand, ChatMode, ChatContext } from "../types";
14
16
  import { AgentModule } from "./AgentModule";
15
17
  import {
@@ -24,6 +26,33 @@ import { Marked } from "../../utils/index";
24
26
  import * as fs from "fs";
25
27
  import * as path from "path";
26
28
 
29
+ export function parseHistoryCommandArgs(args: string[]): {
30
+ id?: string;
31
+ rollback: number;
32
+ showAll: boolean;
33
+ } {
34
+ let id: string | undefined;
35
+ let rollback = 0;
36
+ let showAll = false;
37
+ for (let i = 0; i < args.length; i++) {
38
+ if (args[i] === "--all") {
39
+ showAll = true;
40
+ } else if (args[i] === "--rollback") {
41
+ const value = args[++i];
42
+ rollback = Number(value);
43
+ if (!Number.isInteger(rollback) || rollback < 0) {
44
+ throw new Error("--rollback must be a non-negative integer");
45
+ }
46
+ } else if (!id) {
47
+ id = args[i];
48
+ } else {
49
+ throw new Error(`Unexpected argument: ${args[i]}`);
50
+ }
51
+ }
52
+ return { id, rollback, showAll };
53
+ }
54
+
55
+ @TraceAll()
27
56
  export class SessionsModule extends BaseChatModule {
28
57
  name = "sessions";
29
58
  description = "Session and attachment management";
@@ -49,6 +78,12 @@ export class SessionsModule extends BaseChatModule {
49
78
  "Resume a completed/saved session with optional additional context",
50
79
  handler: this.handleResumeCommand.bind(this),
51
80
  },
81
+ {
82
+ name: "fork",
83
+ description:
84
+ "Fork a saved session into a new task; use --rollback N to discard recent agent interactions",
85
+ handler: this.handleForkCommand.bind(this),
86
+ },
52
87
  {
53
88
  name: "sessions",
54
89
  description:
@@ -214,7 +249,6 @@ export class SessionsModule extends BaseChatModule {
214
249
  // ── Case 1: in-memory running task ──────────────────────────────────────
215
250
  if (taskRegistry.has(id)) {
216
251
  const taskInfo = taskRegistry.get(id)!;
217
- const renderer = this.agentModule.getRenderer();
218
252
  const context = this.chatService?.getContext();
219
253
  const selectedAgent = taskInfo.agent;
220
254
 
@@ -222,13 +256,9 @@ export class SessionsModule extends BaseChatModule {
222
256
  context.selectedAgent = selectedAgent;
223
257
  context.agentMode = true;
224
258
  context.currentAgent = taskInfo.agentName;
225
- context.activeAgentTaskId = id;
226
259
  context.currentModel = selectedAgent.getModel();
227
260
  context.currentProvider = selectedAgent.getProvider();
228
261
  }
229
- this.agentModule.setActiveAgentTaskId(id);
230
- renderer.setActiveTaskId(id);
231
- if (this.chatService) this.chatService.setMode("agent:attached");
232
262
 
233
263
  console.log(`🔄 Attached to running task: ${id}`);
234
264
  console.log(` Agent : ${taskInfo.agentName}`);
@@ -237,6 +267,13 @@ export class SessionsModule extends BaseChatModule {
237
267
  console.log(
238
268
  ` Type /logs to see recent messages, or /detach to detach.`
239
269
  );
270
+
271
+ // Route through attachedAgentChatLoop so that:
272
+ // 1. wireAgentRendering is called (new output becomes visible)
273
+ // 2. attachedAgent is set (so /poke, /kill, /compact work)
274
+ // 3. a done listener is registered (mode resets when agent finishes)
275
+ // Do NOT pass initialInput — agent is already running, no need to call it again.
276
+ await this.agentModule.attachedAgentChatLoop(id, selectedAgent as any);
240
277
  return;
241
278
  }
242
279
 
@@ -303,10 +340,17 @@ export class SessionsModule extends BaseChatModule {
303
340
 
304
341
  async handleResumeCommand(args: string[]): Promise<void> {
305
342
  const sessionManager = this.agentModule.getSessionManager();
343
+ let parsed;
344
+ try {
345
+ parsed = parseHistoryCommandArgs(args);
346
+ } catch (error: any) {
347
+ console.error(`Usage: /resume <taskId> [--rollback N] [--all]\n${error.message}`);
348
+ return;
349
+ }
306
350
 
307
- if (args.length === 0 || args[0] === "--all") {
351
+ if (!parsed.id) {
308
352
  // Interactive: show saved sessions for selection
309
- const showAll = args[0] === "--all";
353
+ const showAll = parsed.showAll;
310
354
  const allSessions = sessionManager.listAvailableSessions();
311
355
  const savedSessions = showAll ? allSessions : allSessions.slice(0, 10);
312
356
  if (savedSessions.length === 0) {
@@ -326,18 +370,32 @@ export class SessionsModule extends BaseChatModule {
326
370
  );
327
371
 
328
372
  if (selectedId) {
329
- await this.resumeById(selectedId);
373
+ await this.resumeById(selectedId, parsed.rollback);
330
374
  }
331
375
  return;
332
376
  }
333
377
 
334
- await this.resumeById(args[0]);
378
+ await this.resumeById(parsed.id, parsed.rollback);
335
379
  }
336
380
 
337
- private async resumeById(id: string): Promise<void> {
381
+ async handleForkCommand(args: string[]): Promise<void> {
382
+ let parsed;
383
+ try {
384
+ parsed = parseHistoryCommandArgs(args);
385
+ } catch (error: any) {
386
+ console.error(`Usage: /fork <taskId> [--rollback N]\n${error.message}`);
387
+ return;
388
+ }
389
+ if (!parsed.id) {
390
+ console.error("Usage: /fork <taskId> [--rollback N]");
391
+ return;
392
+ }
393
+ await this.resumeById(parsed.id, parsed.rollback, true);
394
+ }
395
+
396
+ private async resumeById(id: string, rollback = 0, fork = false): Promise<void> {
338
397
  const sessionManager = this.agentModule.getSessionManager();
339
398
 
340
- // Check saved sessions first
341
399
  try {
342
400
  const session = sessionManager.loadSession(id);
343
401
  if (session) {
@@ -347,34 +405,46 @@ export class SessionsModule extends BaseChatModule {
347
405
  console.log(` Status : ${session.status}`);
348
406
 
349
407
  const additionalContext = await this.chatService?.getInput(
350
- "Add any additional context for resuming this session (or press Enter to skip): "
351
- );
352
- await this.agentModule.resumeSession(
353
- id,
354
- additionalContext?.trim() || undefined
408
+ `Add any additional context for ${fork ? "forking" : "resuming"} this session (or press Enter to skip): `
355
409
  );
410
+ if (fork) {
411
+ const result = await this.agentModule.resumeFromMessages({
412
+ agentName: session.agentName,
413
+ threads: session.threads,
414
+ input: additionalContext?.trim() || session.initialInput,
415
+ interactive: true,
416
+ rollback,
417
+ fork: true,
418
+ model: session.model,
419
+ provider: session.provider,
420
+ reasoningEffort: session.reasoningEffort,
421
+ summarizeReasoning: session.summarizeReasoning,
422
+ enabledTools: session.enabledTools,
423
+ });
424
+ console.log(`🌿 Forked ${id} into new task ${result.taskId}`);
425
+ } else {
426
+ await this.agentModule.resumeSession(
427
+ id,
428
+ additionalContext?.trim() || undefined,
429
+ rollback
430
+ );
431
+ }
356
432
  return;
357
433
  }
358
- } catch {
434
+ } catch (e: any) {
435
+ if (e?.message?.includes("rollback")) throw e;
359
436
  // not found as a saved session
360
437
  }
361
438
 
362
- // Check filesystem agent (may have metadata with threads)
363
439
  const fsAgentPath = path.join(".knowhow", "processes", "agents", id);
364
440
  if (fs.existsSync(fsAgentPath)) {
365
- // Try to load threads from metadata.json and resume
366
441
  const metadataPath = path.join(fsAgentPath, "metadata.json");
367
442
  if (fs.existsSync(metadataPath)) {
368
443
  try {
369
- const raw = fs.readFileSync(metadataPath, "utf-8");
370
- const metadata = JSON.parse(raw);
444
+ const metadata = JSON.parse(fs.readFileSync(metadataPath, "utf-8"));
371
445
  const threads: any[] = metadata.threads || [];
372
446
  const agentName = metadata.agentName || "Developer";
373
-
374
- // Try to get initialInput from the saved session file (more complete)
375
- // since metadata.json doesn't always store it
376
- const savedSession = sessionManager.loadSession(id);
377
- const initialInput = savedSession?.initialInput || metadata.initialInput || metadata.prompt || "";
447
+ const initialInput = metadata.initialInput || metadata.prompt || "";
378
448
 
379
449
  console.log(`\n📋 Found task in filesystem: ${id}`);
380
450
  console.log(` Agent : ${agentName}`);
@@ -382,30 +452,33 @@ export class SessionsModule extends BaseChatModule {
382
452
  console.log(` Status : ${metadata.status || "unknown"}`);
383
453
 
384
454
  const additionalContext = await this.chatService?.getInput(
385
- "Add any additional context for resuming this session (or press Enter to skip): "
455
+ `Add any additional context for ${fork ? "forking" : "resuming"} this session (or press Enter to skip): `
386
456
  );
387
-
388
- // Normalize threads: if flat Message[] (old buggy format), wrap in array
389
457
  const normalizedThreads = threads.length > 0 && !Array.isArray(threads[0])
390
458
  ? [threads]
391
459
  : threads;
392
-
393
- await this.agentModule.resumeFromMessages({
460
+ const result = await this.agentModule.resumeFromMessages({
394
461
  agentName,
395
- taskId: id,
462
+ remoteTaskId: fork
463
+ ? undefined
464
+ : metadata.remoteTaskId || metadata.knowhowTaskId,
465
+ taskId: fork ? undefined : id,
396
466
  threads: normalizedThreads,
397
- input: additionalContext?.trim() || initialInput || "",
467
+ input: additionalContext?.trim() || initialInput,
398
468
  interactive: true,
399
- // Restore the exact model/provider/reasoning the run used so
400
- // resuming doesn't silently drop back to agent defaults.
469
+ rollback,
470
+ fork,
401
471
  model: metadata.model,
402
472
  provider: metadata.provider,
403
473
  reasoningEffort: metadata.reasoningEffort,
404
474
  summarizeReasoning: metadata.summarizeReasoning,
475
+ enabledTools: metadata.enabledTools,
405
476
  });
477
+ if (fork) console.log(`🌿 Forked ${id} into new task ${result.taskId}`);
406
478
  return;
407
479
  } catch (e: any) {
408
480
  console.error(`⚠️ Failed to load metadata for task ${id}: ${e.message}`);
481
+ return;
409
482
  }
410
483
  }
411
484
  console.log(
@@ -415,9 +488,7 @@ export class SessionsModule extends BaseChatModule {
415
488
  return;
416
489
  }
417
490
 
418
- console.log(
419
- `Session "${id}" not found. Use /sessions to list available sessions.`
420
- );
491
+ console.log(`Session "${id}" not found. Use /sessions to list available sessions.`);
421
492
  }
422
493
 
423
494
  // ─────────────────────────────────────────────────────────────────────────────
@@ -1,4 +1,5 @@
1
1
  import { services } from "../../services";
2
+ import { TraceAll } from "../../util/Trace";
2
3
  import { login } from "../../login";
3
4
  import { ask } from "../../utils";
4
5
  import { CliChatService } from "../CliChatService";
@@ -6,6 +7,7 @@ import { ChatCommand, ChatMode } from "../types";
6
7
  import { AgentModule } from "./AgentModule";
7
8
  import { BaseChatModule } from "./BaseChatModule";
8
9
 
10
+ @TraceAll()
9
11
  export class SetupModule extends BaseChatModule {
10
12
  name = "setup";
11
13
  description = "Setup commands";
@@ -1,4 +1,5 @@
1
1
  import { BaseChatModule } from "./BaseChatModule";
2
+ import { TraceAll } from "../../util/Trace";
2
3
  import { ChatCommand, ChatContext, CommandResult } from "../types";
3
4
  import { execSync } from "child_process";
4
5
 
@@ -7,6 +8,7 @@ import { execSync } from "child_process";
7
8
  * /! - Execute command and display output in console (interactive if needed)
8
9
  * /!! - Execute command and send output to the AI agent
9
10
  */
11
+ @TraceAll()
10
12
  export class ShellCommandModule extends BaseChatModule {
11
13
  name = "shell-command";
12
14
  description = "Execute shell commands with /! and /!!";
@@ -1,10 +1,12 @@
1
1
  import { BaseChatModule } from "./BaseChatModule";
2
+ import { TraceAll } from "../../util/Trace";
2
3
  import { CliChatService } from "../CliChatService";
3
4
  import { ChatCommand, ChatMode, ChatContext } from "../types";
4
5
  import { ask } from "../../utils";
5
6
  import { services } from "../../services";
6
7
  import { Models } from "../../types";
7
8
 
9
+ @TraceAll()
8
10
  export class SystemModule extends BaseChatModule {
9
11
  name = "system";
10
12
  description = "System commands for model, provider, debug, and clear";
package/src/chat/types.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { ChatInteraction, Config } from "../types";
5
5
  import { BaseAgent } from "../agents/base/base";
6
+ import { ReasoningEffort } from "../clients/types";
6
7
  import { ToolsService } from "../services";
7
8
  import { AgentRenderer } from "./renderer/types";
8
9
 
@@ -101,8 +102,9 @@ export interface TaskInfo {
101
102
  // restore the exact configuration instead of falling back to agent defaults.
102
103
  model?: string;
103
104
  provider?: string;
104
- reasoningEffort?: "none" | "low" | "medium" | "high";
105
+ reasoningEffort?: ReasoningEffort;
105
106
  summarizeReasoning?: boolean;
107
+ enabledTools?: string[];
106
108
  }
107
109
 
108
110
  export interface ChatSession {
@@ -123,8 +125,9 @@ export interface ChatSession {
123
125
  // Persisted run configuration for exact resume restoration.
124
126
  model?: string;
125
127
  provider?: string;
126
- reasoningEffort?: "none" | "low" | "medium" | "high";
128
+ reasoningEffort?: ReasoningEffort;
127
129
  summarizeReasoning?: boolean;
130
+ enabledTools?: string[];
128
131
  }
129
132
 
130
133
  export interface ChatHistory {
package/src/cli.ts CHANGED
@@ -128,7 +128,7 @@ async function main() {
128
128
  addReplayCommand(program);
129
129
  addBehaviorsCommand(program);
130
130
  addSkillsCommand(program);
131
- addAgentsCommand(program);
131
+ addAgentsCommand(program, getChatService);
132
132
  addHashCommand(program);
133
133
  addSandboxCommand(program);
134
134
 
@@ -88,6 +88,25 @@ export class GenericAnthropicClient implements GenericClient {
88
88
  return undefined;
89
89
  }
90
90
 
91
+ /** Map provider-neutral effort names to Anthropic's output_config.effort. */
92
+ getEffortOutputConfig(
93
+ model: string,
94
+ reasoningEffort?: CompletionOptions["reasoning_effort"]
95
+ ): Anthropic.OutputConfig | undefined {
96
+ if (
97
+ reasoningEffort === undefined ||
98
+ reasoningEffort === "none" ||
99
+ (!alwaysOnModels.includes(model) && !optInModels.includes(model))
100
+ ) {
101
+ return undefined;
102
+ }
103
+
104
+ return {
105
+ // Anthropic uses `low` for the provider-neutral `minimal` level.
106
+ effort: reasoningEffort === "minimal" ? "low" : reasoningEffort,
107
+ };
108
+ }
109
+
91
110
  /**
92
111
  * Clean JSON Schema for Anthropic API compatibility.
93
112
  * Removes unsupported fields like additionalProperties, $ref, $defs, positional.
@@ -423,6 +442,10 @@ export class GenericAnthropicClient implements GenericClient {
423
442
  options.reasoning_effort,
424
443
  options.reasoning_summary,
425
444
  );
445
+ const effortOutputConfig = this.getEffortOutputConfig(
446
+ options.model,
447
+ options.reasoning_effort
448
+ );
426
449
 
427
450
  const systemMessage = options.messages
428
451
  .filter((msg) => msg.role === "system")
@@ -447,6 +470,7 @@ export class GenericAnthropicClient implements GenericClient {
447
470
  : undefined,
448
471
  max_tokens: options.max_tokens || 8000,
449
472
  ...(thinkingParam && { thinking: thinkingParam }),
473
+ ...(effortOutputConfig && { output_config: effortOutputConfig }),
450
474
  ...(tools.length && {
451
475
  tool_choice: { type: "auto" },
452
476
  tools,
@@ -51,6 +51,9 @@ export class GenericFireworksClient extends HttpClient {
51
51
  ...options,
52
52
  // Strip Anthropic-specific field not accepted by Fireworks
53
53
  long_ttl_cache: undefined,
54
+ // This is translated by the OpenAI/Anthropic clients, but is not part of
55
+ // Fireworks' OpenAI-compatible chat completion schema.
56
+ reasoning_summary: undefined,
54
57
  };
55
58
 
56
59
  if (sanitized.tools) {
@@ -434,9 +434,13 @@ export class GenericGeminiClient implements GenericClient {
434
434
  // Gemini 3.x — use thinkingLevel
435
435
  if (GoogleThinkingLevelModels.includes(model)) {
436
436
  const levelMap: Record<string, string> = {
437
+ none: "minimal",
438
+ minimal: "minimal",
437
439
  low: "low",
438
440
  medium: "medium",
439
441
  high: "high",
442
+ xhigh: "high",
443
+ max: "high",
440
444
  };
441
445
  return {
442
446
  thinkingLevel: levelMap[effort] ?? "low",
@@ -447,9 +451,13 @@ export class GenericGeminiClient implements GenericClient {
447
451
  if (GoogleThinkingBudgetModels.includes(model)) {
448
452
  // Map effort to token budget
449
453
  const budgetMap: Record<string, number> = {
454
+ none: 0,
455
+ minimal: 512,
450
456
  low: 1024,
451
457
  medium: 8192,
452
458
  high: -1, // dynamic
459
+ xhigh: -1,
460
+ max: -1,
453
461
  };
454
462
  return {
455
463
  thinkingBudget: budgetMap[effort] ?? 1024,
@@ -59,6 +59,7 @@ import { GenericLlamaClient } from "./llama";
59
59
  import { GenericFireworksClient } from "./fireworks";
60
60
  import { GenericMetaClient } from "./meta";
61
61
  import { GenericQwenClient } from "./qwen";
62
+ import { TraceAll } from "../util/Trace";
62
63
  export {
63
64
  OpenAiTextPricing,
64
65
  AnthropicTextPricing,
@@ -139,6 +140,7 @@ const DEFAULT_PROVIDERS: ModelProvider[] = [
139
140
  { provider: "qwen", envKey: "QWEN_CLOUD_API_KEY" },
140
141
  ];
141
142
 
143
+ @TraceAll()
142
144
  export class AIClient {
143
145
  clients: Record<string, GenericClient> = {};
144
146
 
@@ -112,9 +112,10 @@ export class GenericOpenAiClient implements GenericClient {
112
112
 
113
113
  resolveReasoningEffort(options: CompletionOptions): "low" | "medium" | "high" {
114
114
  const effort = options.reasoning_effort ?? this.detectReasoningEffort(options.messages);
115
- // "none" is not a valid SDK ReasoningEffort — callers that need "none" should
116
- // check isReasoningDisabled() separately and skip the reasoning params.
117
- if (effort === "none") return "low";
115
+ // Chat Completions only accepts low/medium/high. Preserve newer values on
116
+ // the Responses API, but map them to the nearest legacy level here.
117
+ if (effort === "none" || effort === "minimal") return "low";
118
+ if (effort === "xhigh" || effort === "max") return "high";
118
119
  return effort;
119
120
  }
120
121
 
@@ -125,7 +126,9 @@ export class GenericOpenAiClient implements GenericClient {
125
126
  */
126
127
  resolveReasoningEffortForModel(options: CompletionOptions): string {
127
128
  const raw = options.reasoning_effort ?? this.detectReasoningEffort(options.messages);
128
- const requested = raw === "none" ? "none" : raw;
129
+ // Anthropic calls its highest level `max`; OpenAI calls it `xhigh`.
130
+ // Accept both provider-neutral CLI spellings.
131
+ const requested = raw === "max" ? "xhigh" : raw;
129
132
  const pricing = OpenAiTextPricing[options.model];
130
133
  const supportedLevels = pricing?.reasoningLevels;
131
134
  if (!supportedLevels || supportedLevels.length === 0) {
@@ -136,6 +136,26 @@ export interface RetryOptions {
136
136
  signal?: AbortSignal;
137
137
  }
138
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
+
139
159
  export interface CompletionOptions extends RetryOptions {
140
160
  model: string;
141
161
  messages: Message[];
@@ -147,14 +167,17 @@ export interface CompletionOptions extends RetryOptions {
147
167
  * Maps to: OpenAI reasoning_effort/reasoning.effort, xAI reasoning.effort,
148
168
  * Gemini thinkingLevel/thinkingBudget, Anthropic thinking mode.
149
169
  *
150
- * "none" = disable thinking entirely (Anthropic: thinking.type="disabled",
151
- * OpenAI: reasoning.effort="none"). Only supported by models that
152
- * allow disabling thinking (e.g. claude-sonnet-5).
153
- * "low" = minimal thinking
154
- * "medium" = balanced (default for most models)
155
- * "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.
156
179
  */
157
- reasoning_effort?: "none" | "low" | "medium" | "high";
180
+ reasoning_effort?: ReasoningEffort;
158
181
  /**
159
182
  * When true, request a summarized view of the model's thinking process.
160
183
  * - Anthropic: thinking.display = "summarized"
@@ -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,
@@ -206,8 +216,17 @@ export class GenericXAIClient implements GenericClient {
206
216
  // Resolve reasoning effort, clamping to supported levels if defined in pricing
207
217
  const pricing = XaiTextPricing[options.model];
208
218
  const supportedLevels = pricing?.reasoningLevels;
209
- let reasoningEffort: string | undefined = options.reasoning_effort;
210
- 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) {
211
230
  if (!reasoningEffort || !supportedLevels.includes(reasoningEffort)) {
212
231
  reasoningEffort = supportedLevels[0];
213
232
  }
@@ -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> {
@@ -54,10 +55,10 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
54
55
  "AI provider (openai, anthropic, google, xai)"
55
56
  )
56
57
  .option("--model <model>", "Specific model for the provider")
57
- .option("--agent-name <name>", "Which agent to use", "Patcher")
58
+ .option("--agent-name <name>", "Which agent to use (default: Patcher)")
58
59
  .option(
59
60
  "--reasoning-effort <effort>",
60
- "Reasoning effort: none, low, medium, or high. Use 'none' to disable thinking on models that support it (e.g. for faster computer-use)."
61
+ `Reasoning effort: ${REASONING_EFFORTS.join(", ")}. Individual models support different subsets.`
61
62
  )
62
63
  .option(
63
64
  "--max-time-limit <minutes>",
@@ -93,16 +94,20 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
93
94
  )
94
95
  .option("--prompt-file <path>", "Custom prompt template file with {text}")
95
96
  .option("--input <text>", "Task input (fallback to stdin if not provided)")
96
- .option(
97
- "--resume",
98
- "Resume a previously started task using the --task-id (local FS or remote)"
99
- )
100
97
  .option(
101
98
  "--renderer <name>",
102
99
  "Renderer to use: basic, compact, fancy, or a path/package (default: from config or basic)"
103
100
  )
104
101
  .action(async (options) => {
105
102
  try {
103
+ if (
104
+ options.reasoningEffort !== undefined &&
105
+ !isReasoningEffort(options.reasoningEffort)
106
+ ) {
107
+ throw new Error(
108
+ `Invalid reasoning effort "${options.reasoningEffort}". Expected one of: ${REASONING_EFFORTS.join(", ")}.`
109
+ );
110
+ }
106
111
  const { setupServices } = await import("./services");
107
112
  await setupServices();
108
113
  const chatService = getChatService();
@@ -115,39 +120,6 @@ export function addAgentCommand(program: Command, getChatService: () => any): vo
115
120
 
116
121
  const agentModule = new AgentModule();
117
122
 
118
- if (options.resume) {
119
- const threads = await agentModule.loadThreadsForTask(
120
- options.taskId,
121
- options.messageId
122
- );
123
- // Restore the exact model/provider/reasoning the original run used
124
- // (falls back to agent defaults when not persisted / remote-only).
125
- const savedSettings = await agentModule.loadTaskSettings(
126
- options.taskId,
127
- options.messageId
128
- );
129
- const resumeInput =
130
- options.input || "Please continue from where you left off.";
131
-
132
- await agentModule.initialize(chatService);
133
- const { taskCompleted: resumed } =
134
- await agentModule.resumeFromMessages({
135
- agentName:
136
- options.agentName || savedSettings.agentName || "Patcher",
137
- input: resumeInput,
138
- threads,
139
- messageId: options.messageId,
140
- taskId: options.taskId,
141
- // CLI-provided model/provider still win over persisted ones.
142
- model: options.model || savedSettings.model,
143
- provider: options.provider || savedSettings.provider,
144
- reasoningEffort: savedSettings.reasoningEffort,
145
- summarizeReasoning: savedSettings.summarizeReasoning,
146
- });
147
- await resumed;
148
- return;
149
- }
150
-
151
123
  let input = options.input;
152
124
 
153
125
  if (!input && !options.promptFile) {