attocode 0.1.0

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 (488) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE +21 -0
  3. package/README.md +164 -0
  4. package/dist/src/adapters.d.ts +83 -0
  5. package/dist/src/adapters.d.ts.map +1 -0
  6. package/dist/src/adapters.js +221 -0
  7. package/dist/src/adapters.js.map +1 -0
  8. package/dist/src/agent-tools/index.d.ts +7 -0
  9. package/dist/src/agent-tools/index.d.ts.map +1 -0
  10. package/dist/src/agent-tools/index.js +8 -0
  11. package/dist/src/agent-tools/index.js.map +1 -0
  12. package/dist/src/agent-tools/lsp-file-tools.d.ts +33 -0
  13. package/dist/src/agent-tools/lsp-file-tools.d.ts.map +1 -0
  14. package/dist/src/agent-tools/lsp-file-tools.js +200 -0
  15. package/dist/src/agent-tools/lsp-file-tools.js.map +1 -0
  16. package/dist/src/agent.d.ts +667 -0
  17. package/dist/src/agent.d.ts.map +1 -0
  18. package/dist/src/agent.js +2824 -0
  19. package/dist/src/agent.js.map +1 -0
  20. package/dist/src/cli.d.ts +36 -0
  21. package/dist/src/cli.d.ts.map +1 -0
  22. package/dist/src/cli.js +176 -0
  23. package/dist/src/cli.js.map +1 -0
  24. package/dist/src/commands/handler.d.ts +22 -0
  25. package/dist/src/commands/handler.d.ts.map +1 -0
  26. package/dist/src/commands/handler.js +1320 -0
  27. package/dist/src/commands/handler.js.map +1 -0
  28. package/dist/src/commands/init.d.ts +7 -0
  29. package/dist/src/commands/init.d.ts.map +1 -0
  30. package/dist/src/commands/init.js +153 -0
  31. package/dist/src/commands/init.js.map +1 -0
  32. package/dist/src/commands/types.d.ts +70 -0
  33. package/dist/src/commands/types.d.ts.map +1 -0
  34. package/dist/src/commands/types.js +8 -0
  35. package/dist/src/commands/types.js.map +1 -0
  36. package/dist/src/config.d.ts +22 -0
  37. package/dist/src/config.d.ts.map +1 -0
  38. package/dist/src/config.js +25 -0
  39. package/dist/src/config.js.map +1 -0
  40. package/dist/src/core/index.d.ts +32 -0
  41. package/dist/src/core/index.d.ts.map +1 -0
  42. package/dist/src/core/index.js +35 -0
  43. package/dist/src/core/index.js.map +1 -0
  44. package/dist/src/core/process-handlers.d.ts +43 -0
  45. package/dist/src/core/process-handlers.d.ts.map +1 -0
  46. package/dist/src/core/process-handlers.js +117 -0
  47. package/dist/src/core/process-handlers.js.map +1 -0
  48. package/dist/src/core/protocol/bridge.d.ts +117 -0
  49. package/dist/src/core/protocol/bridge.d.ts.map +1 -0
  50. package/dist/src/core/protocol/bridge.js +149 -0
  51. package/dist/src/core/protocol/bridge.js.map +1 -0
  52. package/dist/src/core/protocol/index.d.ts +8 -0
  53. package/dist/src/core/protocol/index.d.ts.map +1 -0
  54. package/dist/src/core/protocol/index.js +8 -0
  55. package/dist/src/core/protocol/index.js.map +1 -0
  56. package/dist/src/core/protocol/types.d.ts +539 -0
  57. package/dist/src/core/protocol/types.d.ts.map +1 -0
  58. package/dist/src/core/protocol/types.js +149 -0
  59. package/dist/src/core/protocol/types.js.map +1 -0
  60. package/dist/src/core/queues/atomic-counter.d.ts +36 -0
  61. package/dist/src/core/queues/atomic-counter.d.ts.map +1 -0
  62. package/dist/src/core/queues/atomic-counter.js +46 -0
  63. package/dist/src/core/queues/atomic-counter.js.map +1 -0
  64. package/dist/src/core/queues/event-queue.d.ts +126 -0
  65. package/dist/src/core/queues/event-queue.d.ts.map +1 -0
  66. package/dist/src/core/queues/event-queue.js +208 -0
  67. package/dist/src/core/queues/event-queue.js.map +1 -0
  68. package/dist/src/core/queues/index.d.ts +12 -0
  69. package/dist/src/core/queues/index.d.ts.map +1 -0
  70. package/dist/src/core/queues/index.js +15 -0
  71. package/dist/src/core/queues/index.js.map +1 -0
  72. package/dist/src/core/queues/submission-queue.d.ts +116 -0
  73. package/dist/src/core/queues/submission-queue.d.ts.map +1 -0
  74. package/dist/src/core/queues/submission-queue.js +236 -0
  75. package/dist/src/core/queues/submission-queue.js.map +1 -0
  76. package/dist/src/costs/index.d.ts +22 -0
  77. package/dist/src/costs/index.d.ts.map +1 -0
  78. package/dist/src/costs/index.js +22 -0
  79. package/dist/src/costs/index.js.map +1 -0
  80. package/dist/src/costs/model-registry.d.ts +80 -0
  81. package/dist/src/costs/model-registry.d.ts.map +1 -0
  82. package/dist/src/costs/model-registry.js +237 -0
  83. package/dist/src/costs/model-registry.js.map +1 -0
  84. package/dist/src/costs/types.d.ts +50 -0
  85. package/dist/src/costs/types.d.ts.map +1 -0
  86. package/dist/src/costs/types.js +2 -0
  87. package/dist/src/costs/types.js.map +1 -0
  88. package/dist/src/defaults.d.ts +114 -0
  89. package/dist/src/defaults.d.ts.map +1 -0
  90. package/dist/src/defaults.js +457 -0
  91. package/dist/src/defaults.js.map +1 -0
  92. package/dist/src/first-run.d.ts +35 -0
  93. package/dist/src/first-run.d.ts.map +1 -0
  94. package/dist/src/first-run.js +94 -0
  95. package/dist/src/first-run.js.map +1 -0
  96. package/dist/src/hello.d.ts +2 -0
  97. package/dist/src/hello.d.ts.map +1 -0
  98. package/dist/src/hello.js +4 -0
  99. package/dist/src/hello.js.map +1 -0
  100. package/dist/src/integrations/agent-registry.d.ts +160 -0
  101. package/dist/src/integrations/agent-registry.d.ts.map +1 -0
  102. package/dist/src/integrations/agent-registry.js +446 -0
  103. package/dist/src/integrations/agent-registry.js.map +1 -0
  104. package/dist/src/integrations/auto-compaction.d.ts +177 -0
  105. package/dist/src/integrations/auto-compaction.d.ts.map +1 -0
  106. package/dist/src/integrations/auto-compaction.js +428 -0
  107. package/dist/src/integrations/auto-compaction.js.map +1 -0
  108. package/dist/src/integrations/cancellation.d.ts +162 -0
  109. package/dist/src/integrations/cancellation.d.ts.map +1 -0
  110. package/dist/src/integrations/cancellation.js +339 -0
  111. package/dist/src/integrations/cancellation.js.map +1 -0
  112. package/dist/src/integrations/codebase-context.d.ts +319 -0
  113. package/dist/src/integrations/codebase-context.d.ts.map +1 -0
  114. package/dist/src/integrations/codebase-context.js +816 -0
  115. package/dist/src/integrations/codebase-context.js.map +1 -0
  116. package/dist/src/integrations/compaction.d.ts +192 -0
  117. package/dist/src/integrations/compaction.d.ts.map +1 -0
  118. package/dist/src/integrations/compaction.js +376 -0
  119. package/dist/src/integrations/compaction.js.map +1 -0
  120. package/dist/src/integrations/context-engineering.d.ts +246 -0
  121. package/dist/src/integrations/context-engineering.d.ts.map +1 -0
  122. package/dist/src/integrations/context-engineering.js +394 -0
  123. package/dist/src/integrations/context-engineering.js.map +1 -0
  124. package/dist/src/integrations/diff-utils.d.ts +105 -0
  125. package/dist/src/integrations/diff-utils.d.ts.map +1 -0
  126. package/dist/src/integrations/diff-utils.js +497 -0
  127. package/dist/src/integrations/diff-utils.js.map +1 -0
  128. package/dist/src/integrations/economics.d.ts +192 -0
  129. package/dist/src/integrations/economics.d.ts.map +1 -0
  130. package/dist/src/integrations/economics.js +431 -0
  131. package/dist/src/integrations/economics.js.map +1 -0
  132. package/dist/src/integrations/execution-policy.d.ts +189 -0
  133. package/dist/src/integrations/execution-policy.d.ts.map +1 -0
  134. package/dist/src/integrations/execution-policy.js +352 -0
  135. package/dist/src/integrations/execution-policy.js.map +1 -0
  136. package/dist/src/integrations/file-change-tracker.d.ts +161 -0
  137. package/dist/src/integrations/file-change-tracker.d.ts.map +1 -0
  138. package/dist/src/integrations/file-change-tracker.js +520 -0
  139. package/dist/src/integrations/file-change-tracker.js.map +1 -0
  140. package/dist/src/integrations/hierarchical-config.d.ts +212 -0
  141. package/dist/src/integrations/hierarchical-config.d.ts.map +1 -0
  142. package/dist/src/integrations/hierarchical-config.js +484 -0
  143. package/dist/src/integrations/hierarchical-config.js.map +1 -0
  144. package/dist/src/integrations/hooks.d.ts +114 -0
  145. package/dist/src/integrations/hooks.d.ts.map +1 -0
  146. package/dist/src/integrations/hooks.js +326 -0
  147. package/dist/src/integrations/hooks.js.map +1 -0
  148. package/dist/src/integrations/ignore.d.ts +143 -0
  149. package/dist/src/integrations/ignore.d.ts.map +1 -0
  150. package/dist/src/integrations/ignore.js +417 -0
  151. package/dist/src/integrations/ignore.js.map +1 -0
  152. package/dist/src/integrations/image-renderer.d.ts +119 -0
  153. package/dist/src/integrations/image-renderer.d.ts.map +1 -0
  154. package/dist/src/integrations/image-renderer.js +306 -0
  155. package/dist/src/integrations/image-renderer.js.map +1 -0
  156. package/dist/src/integrations/index.d.ts +42 -0
  157. package/dist/src/integrations/index.d.ts.map +1 -0
  158. package/dist/src/integrations/index.js +73 -0
  159. package/dist/src/integrations/index.js.map +1 -0
  160. package/dist/src/integrations/lsp.d.ts +196 -0
  161. package/dist/src/integrations/lsp.d.ts.map +1 -0
  162. package/dist/src/integrations/lsp.js +582 -0
  163. package/dist/src/integrations/lsp.js.map +1 -0
  164. package/dist/src/integrations/mcp-client.d.ts +270 -0
  165. package/dist/src/integrations/mcp-client.d.ts.map +1 -0
  166. package/dist/src/integrations/mcp-client.js +698 -0
  167. package/dist/src/integrations/mcp-client.js.map +1 -0
  168. package/dist/src/integrations/mcp-tool-search.d.ts +77 -0
  169. package/dist/src/integrations/mcp-tool-search.d.ts.map +1 -0
  170. package/dist/src/integrations/mcp-tool-search.js +220 -0
  171. package/dist/src/integrations/mcp-tool-search.js.map +1 -0
  172. package/dist/src/integrations/memory.d.ts +108 -0
  173. package/dist/src/integrations/memory.d.ts.map +1 -0
  174. package/dist/src/integrations/memory.js +288 -0
  175. package/dist/src/integrations/memory.js.map +1 -0
  176. package/dist/src/integrations/multi-agent.d.ts +150 -0
  177. package/dist/src/integrations/multi-agent.d.ts.map +1 -0
  178. package/dist/src/integrations/multi-agent.js +306 -0
  179. package/dist/src/integrations/multi-agent.js.map +1 -0
  180. package/dist/src/integrations/observability.d.ts +162 -0
  181. package/dist/src/integrations/observability.d.ts.map +1 -0
  182. package/dist/src/integrations/observability.js +406 -0
  183. package/dist/src/integrations/observability.js.map +1 -0
  184. package/dist/src/integrations/openrouter-pricing.d.ts +42 -0
  185. package/dist/src/integrations/openrouter-pricing.d.ts.map +1 -0
  186. package/dist/src/integrations/openrouter-pricing.js +124 -0
  187. package/dist/src/integrations/openrouter-pricing.js.map +1 -0
  188. package/dist/src/integrations/pending-plan.d.ts +171 -0
  189. package/dist/src/integrations/pending-plan.d.ts.map +1 -0
  190. package/dist/src/integrations/pending-plan.js +244 -0
  191. package/dist/src/integrations/pending-plan.js.map +1 -0
  192. package/dist/src/integrations/persistence.d.ts +48 -0
  193. package/dist/src/integrations/persistence.d.ts.map +1 -0
  194. package/dist/src/integrations/persistence.js +196 -0
  195. package/dist/src/integrations/persistence.js.map +1 -0
  196. package/dist/src/integrations/planning.d.ts +96 -0
  197. package/dist/src/integrations/planning.d.ts.map +1 -0
  198. package/dist/src/integrations/planning.js +338 -0
  199. package/dist/src/integrations/planning.js.map +1 -0
  200. package/dist/src/integrations/pty-shell.d.ts +169 -0
  201. package/dist/src/integrations/pty-shell.d.ts.map +1 -0
  202. package/dist/src/integrations/pty-shell.js +367 -0
  203. package/dist/src/integrations/pty-shell.js.map +1 -0
  204. package/dist/src/integrations/react.d.ts +139 -0
  205. package/dist/src/integrations/react.d.ts.map +1 -0
  206. package/dist/src/integrations/react.js +273 -0
  207. package/dist/src/integrations/react.js.map +1 -0
  208. package/dist/src/integrations/resources.d.ts +177 -0
  209. package/dist/src/integrations/resources.d.ts.map +1 -0
  210. package/dist/src/integrations/resources.js +311 -0
  211. package/dist/src/integrations/resources.js.map +1 -0
  212. package/dist/src/integrations/result-synthesizer.d.ts +389 -0
  213. package/dist/src/integrations/result-synthesizer.d.ts.map +1 -0
  214. package/dist/src/integrations/result-synthesizer.js +951 -0
  215. package/dist/src/integrations/result-synthesizer.js.map +1 -0
  216. package/dist/src/integrations/routing.d.ts +117 -0
  217. package/dist/src/integrations/routing.d.ts.map +1 -0
  218. package/dist/src/integrations/routing.js +347 -0
  219. package/dist/src/integrations/routing.js.map +1 -0
  220. package/dist/src/integrations/rules.d.ts +131 -0
  221. package/dist/src/integrations/rules.d.ts.map +1 -0
  222. package/dist/src/integrations/rules.js +284 -0
  223. package/dist/src/integrations/rules.js.map +1 -0
  224. package/dist/src/integrations/safety.d.ts +142 -0
  225. package/dist/src/integrations/safety.d.ts.map +1 -0
  226. package/dist/src/integrations/safety.js +342 -0
  227. package/dist/src/integrations/safety.js.map +1 -0
  228. package/dist/src/integrations/sandbox/basic.d.ts +74 -0
  229. package/dist/src/integrations/sandbox/basic.d.ts.map +1 -0
  230. package/dist/src/integrations/sandbox/basic.js +310 -0
  231. package/dist/src/integrations/sandbox/basic.js.map +1 -0
  232. package/dist/src/integrations/sandbox/docker.d.ts +94 -0
  233. package/dist/src/integrations/sandbox/docker.d.ts.map +1 -0
  234. package/dist/src/integrations/sandbox/docker.js +293 -0
  235. package/dist/src/integrations/sandbox/docker.js.map +1 -0
  236. package/dist/src/integrations/sandbox/index.d.ts +182 -0
  237. package/dist/src/integrations/sandbox/index.d.ts.map +1 -0
  238. package/dist/src/integrations/sandbox/index.js +382 -0
  239. package/dist/src/integrations/sandbox/index.js.map +1 -0
  240. package/dist/src/integrations/sandbox/landlock.d.ts +59 -0
  241. package/dist/src/integrations/sandbox/landlock.d.ts.map +1 -0
  242. package/dist/src/integrations/sandbox/landlock.js +326 -0
  243. package/dist/src/integrations/sandbox/landlock.js.map +1 -0
  244. package/dist/src/integrations/sandbox/seatbelt.d.ts +68 -0
  245. package/dist/src/integrations/sandbox/seatbelt.d.ts.map +1 -0
  246. package/dist/src/integrations/sandbox/seatbelt.js +298 -0
  247. package/dist/src/integrations/sandbox/seatbelt.js.map +1 -0
  248. package/dist/src/integrations/semantic-cache.d.ts +178 -0
  249. package/dist/src/integrations/semantic-cache.d.ts.map +1 -0
  250. package/dist/src/integrations/semantic-cache.js +372 -0
  251. package/dist/src/integrations/semantic-cache.js.map +1 -0
  252. package/dist/src/integrations/session-store.d.ts +183 -0
  253. package/dist/src/integrations/session-store.d.ts.map +1 -0
  254. package/dist/src/integrations/session-store.js +345 -0
  255. package/dist/src/integrations/session-store.js.map +1 -0
  256. package/dist/src/integrations/shared-blackboard.d.ts +403 -0
  257. package/dist/src/integrations/shared-blackboard.d.ts.map +1 -0
  258. package/dist/src/integrations/shared-blackboard.js +710 -0
  259. package/dist/src/integrations/shared-blackboard.js.map +1 -0
  260. package/dist/src/integrations/skills.d.ts +171 -0
  261. package/dist/src/integrations/skills.d.ts.map +1 -0
  262. package/dist/src/integrations/skills.js +403 -0
  263. package/dist/src/integrations/skills.js.map +1 -0
  264. package/dist/src/integrations/smart-decomposer.d.ts +322 -0
  265. package/dist/src/integrations/smart-decomposer.d.ts.map +1 -0
  266. package/dist/src/integrations/smart-decomposer.js +856 -0
  267. package/dist/src/integrations/smart-decomposer.js.map +1 -0
  268. package/dist/src/integrations/sourcegraph.d.ts +169 -0
  269. package/dist/src/integrations/sourcegraph.d.ts.map +1 -0
  270. package/dist/src/integrations/sourcegraph.js +379 -0
  271. package/dist/src/integrations/sourcegraph.js.map +1 -0
  272. package/dist/src/integrations/sqlite-store.d.ts +518 -0
  273. package/dist/src/integrations/sqlite-store.d.ts.map +1 -0
  274. package/dist/src/integrations/sqlite-store.js +1423 -0
  275. package/dist/src/integrations/sqlite-store.js.map +1 -0
  276. package/dist/src/integrations/streaming.d.ts +102 -0
  277. package/dist/src/integrations/streaming.d.ts.map +1 -0
  278. package/dist/src/integrations/streaming.js +362 -0
  279. package/dist/src/integrations/streaming.js.map +1 -0
  280. package/dist/src/integrations/thread-manager.d.ts +199 -0
  281. package/dist/src/integrations/thread-manager.d.ts.map +1 -0
  282. package/dist/src/integrations/thread-manager.js +357 -0
  283. package/dist/src/integrations/thread-manager.js.map +1 -0
  284. package/dist/src/main.d.ts +26 -0
  285. package/dist/src/main.d.ts.map +1 -0
  286. package/dist/src/main.js +170 -0
  287. package/dist/src/main.js.map +1 -0
  288. package/dist/src/modes/index.d.ts +10 -0
  289. package/dist/src/modes/index.d.ts.map +1 -0
  290. package/dist/src/modes/index.js +10 -0
  291. package/dist/src/modes/index.js.map +1 -0
  292. package/dist/src/modes/repl.d.ts +19 -0
  293. package/dist/src/modes/repl.d.ts.map +1 -0
  294. package/dist/src/modes/repl.js +393 -0
  295. package/dist/src/modes/repl.js.map +1 -0
  296. package/dist/src/modes/tui.d.ts +29 -0
  297. package/dist/src/modes/tui.d.ts.map +1 -0
  298. package/dist/src/modes/tui.js +272 -0
  299. package/dist/src/modes/tui.js.map +1 -0
  300. package/dist/src/modes.d.ts +179 -0
  301. package/dist/src/modes.d.ts.map +1 -0
  302. package/dist/src/modes.js +385 -0
  303. package/dist/src/modes.js.map +1 -0
  304. package/dist/src/observability/tracer.d.ts +111 -0
  305. package/dist/src/observability/tracer.d.ts.map +1 -0
  306. package/dist/src/observability/tracer.js +300 -0
  307. package/dist/src/observability/tracer.js.map +1 -0
  308. package/dist/src/observability/types.d.ts +271 -0
  309. package/dist/src/observability/types.d.ts.map +1 -0
  310. package/dist/src/observability/types.js +24 -0
  311. package/dist/src/observability/types.js.map +1 -0
  312. package/dist/src/paths.d.ts +101 -0
  313. package/dist/src/paths.d.ts.map +1 -0
  314. package/dist/src/paths.js +148 -0
  315. package/dist/src/paths.js.map +1 -0
  316. package/dist/src/persistence/index.d.ts +38 -0
  317. package/dist/src/persistence/index.d.ts.map +1 -0
  318. package/dist/src/persistence/index.js +48 -0
  319. package/dist/src/persistence/index.js.map +1 -0
  320. package/dist/src/persistence/migrator.d.ts +135 -0
  321. package/dist/src/persistence/migrator.d.ts.map +1 -0
  322. package/dist/src/persistence/migrator.js +303 -0
  323. package/dist/src/persistence/migrator.js.map +1 -0
  324. package/dist/src/persistence/schema.d.ts +101 -0
  325. package/dist/src/persistence/schema.d.ts.map +1 -0
  326. package/dist/src/persistence/schema.js +395 -0
  327. package/dist/src/persistence/schema.js.map +1 -0
  328. package/dist/src/providers/adapters/anthropic.d.ts +20 -0
  329. package/dist/src/providers/adapters/anthropic.d.ts.map +1 -0
  330. package/dist/src/providers/adapters/anthropic.js +124 -0
  331. package/dist/src/providers/adapters/anthropic.js.map +1 -0
  332. package/dist/src/providers/adapters/mock.d.ts +25 -0
  333. package/dist/src/providers/adapters/mock.d.ts.map +1 -0
  334. package/dist/src/providers/adapters/mock.js +133 -0
  335. package/dist/src/providers/adapters/mock.js.map +1 -0
  336. package/dist/src/providers/adapters/openai.d.ts +21 -0
  337. package/dist/src/providers/adapters/openai.d.ts.map +1 -0
  338. package/dist/src/providers/adapters/openai.js +126 -0
  339. package/dist/src/providers/adapters/openai.js.map +1 -0
  340. package/dist/src/providers/adapters/openrouter.d.ts +49 -0
  341. package/dist/src/providers/adapters/openrouter.d.ts.map +1 -0
  342. package/dist/src/providers/adapters/openrouter.js +363 -0
  343. package/dist/src/providers/adapters/openrouter.js.map +1 -0
  344. package/dist/src/providers/provider.d.ts +54 -0
  345. package/dist/src/providers/provider.d.ts.map +1 -0
  346. package/dist/src/providers/provider.js +111 -0
  347. package/dist/src/providers/provider.js.map +1 -0
  348. package/dist/src/providers/resilient-fetch.d.ts +99 -0
  349. package/dist/src/providers/resilient-fetch.d.ts.map +1 -0
  350. package/dist/src/providers/resilient-fetch.js +208 -0
  351. package/dist/src/providers/resilient-fetch.js.map +1 -0
  352. package/dist/src/providers/types.d.ts +227 -0
  353. package/dist/src/providers/types.d.ts.map +1 -0
  354. package/dist/src/providers/types.js +24 -0
  355. package/dist/src/providers/types.js.map +1 -0
  356. package/dist/src/session-picker.d.ts +28 -0
  357. package/dist/src/session-picker.d.ts.map +1 -0
  358. package/dist/src/session-picker.js +256 -0
  359. package/dist/src/session-picker.js.map +1 -0
  360. package/dist/src/test-sqlite.d.ts +2 -0
  361. package/dist/src/test-sqlite.d.ts.map +1 -0
  362. package/dist/src/test-sqlite.js +114 -0
  363. package/dist/src/test-sqlite.js.map +1 -0
  364. package/dist/src/tools/agent.d.ts +44 -0
  365. package/dist/src/tools/agent.d.ts.map +1 -0
  366. package/dist/src/tools/agent.js +110 -0
  367. package/dist/src/tools/agent.js.map +1 -0
  368. package/dist/src/tools/bash.d.ts +52 -0
  369. package/dist/src/tools/bash.d.ts.map +1 -0
  370. package/dist/src/tools/bash.js +141 -0
  371. package/dist/src/tools/bash.js.map +1 -0
  372. package/dist/src/tools/file.d.ts +47 -0
  373. package/dist/src/tools/file.d.ts.map +1 -0
  374. package/dist/src/tools/file.js +263 -0
  375. package/dist/src/tools/file.js.map +1 -0
  376. package/dist/src/tools/permission.d.ts +43 -0
  377. package/dist/src/tools/permission.d.ts.map +1 -0
  378. package/dist/src/tools/permission.js +216 -0
  379. package/dist/src/tools/permission.js.map +1 -0
  380. package/dist/src/tools/registry.d.ts +63 -0
  381. package/dist/src/tools/registry.d.ts.map +1 -0
  382. package/dist/src/tools/registry.js +250 -0
  383. package/dist/src/tools/registry.js.map +1 -0
  384. package/dist/src/tools/standard.d.ts +57 -0
  385. package/dist/src/tools/standard.d.ts.map +1 -0
  386. package/dist/src/tools/standard.js +113 -0
  387. package/dist/src/tools/standard.js.map +1 -0
  388. package/dist/src/tools/types.d.ts +146 -0
  389. package/dist/src/tools/types.d.ts.map +1 -0
  390. package/dist/src/tools/types.js +28 -0
  391. package/dist/src/tools/types.js.map +1 -0
  392. package/dist/src/tools/undo.d.ts +71 -0
  393. package/dist/src/tools/undo.d.ts.map +1 -0
  394. package/dist/src/tools/undo.js +123 -0
  395. package/dist/src/tools/undo.js.map +1 -0
  396. package/dist/src/tracing/cache-boundary-tracker.d.ts +189 -0
  397. package/dist/src/tracing/cache-boundary-tracker.d.ts.map +1 -0
  398. package/dist/src/tracing/cache-boundary-tracker.js +411 -0
  399. package/dist/src/tracing/cache-boundary-tracker.js.map +1 -0
  400. package/dist/src/tracing/trace-collector.d.ts +274 -0
  401. package/dist/src/tracing/trace-collector.d.ts.map +1 -0
  402. package/dist/src/tracing/trace-collector.js +727 -0
  403. package/dist/src/tracing/trace-collector.js.map +1 -0
  404. package/dist/src/tracing/types.d.ts +657 -0
  405. package/dist/src/tracing/types.d.ts.map +1 -0
  406. package/dist/src/tracing/types.js +39 -0
  407. package/dist/src/tracing/types.js.map +1 -0
  408. package/dist/src/tricks/failure-evidence.d.ts +268 -0
  409. package/dist/src/tricks/failure-evidence.d.ts.map +1 -0
  410. package/dist/src/tricks/failure-evidence.js +544 -0
  411. package/dist/src/tricks/failure-evidence.js.map +1 -0
  412. package/dist/src/tricks/json-utils.d.ts +77 -0
  413. package/dist/src/tricks/json-utils.d.ts.map +1 -0
  414. package/dist/src/tricks/json-utils.js +247 -0
  415. package/dist/src/tricks/json-utils.js.map +1 -0
  416. package/dist/src/tricks/kv-cache-context.d.ts +227 -0
  417. package/dist/src/tricks/kv-cache-context.d.ts.map +1 -0
  418. package/dist/src/tricks/kv-cache-context.js +377 -0
  419. package/dist/src/tricks/kv-cache-context.js.map +1 -0
  420. package/dist/src/tricks/recitation.d.ts +208 -0
  421. package/dist/src/tricks/recitation.d.ts.map +1 -0
  422. package/dist/src/tricks/recitation.js +374 -0
  423. package/dist/src/tricks/recitation.js.map +1 -0
  424. package/dist/src/tricks/reversible-compaction.d.ts +251 -0
  425. package/dist/src/tricks/reversible-compaction.d.ts.map +1 -0
  426. package/dist/src/tricks/reversible-compaction.js +555 -0
  427. package/dist/src/tricks/reversible-compaction.js.map +1 -0
  428. package/dist/src/tricks/serialization-diversity.d.ts +197 -0
  429. package/dist/src/tricks/serialization-diversity.d.ts.map +1 -0
  430. package/dist/src/tricks/serialization-diversity.js +460 -0
  431. package/dist/src/tricks/serialization-diversity.js.map +1 -0
  432. package/dist/src/tui/app.d.ts +42 -0
  433. package/dist/src/tui/app.d.ts.map +1 -0
  434. package/dist/src/tui/app.js +1076 -0
  435. package/dist/src/tui/app.js.map +1 -0
  436. package/dist/src/tui/components/ApprovalDialog.d.ts +28 -0
  437. package/dist/src/tui/components/ApprovalDialog.d.ts.map +1 -0
  438. package/dist/src/tui/components/ApprovalDialog.js +59 -0
  439. package/dist/src/tui/components/ApprovalDialog.js.map +1 -0
  440. package/dist/src/tui/components/InputArea.d.ts +35 -0
  441. package/dist/src/tui/components/InputArea.d.ts.map +1 -0
  442. package/dist/src/tui/components/InputArea.js +144 -0
  443. package/dist/src/tui/components/InputArea.js.map +1 -0
  444. package/dist/src/tui/components/MessageItem.d.ts +28 -0
  445. package/dist/src/tui/components/MessageItem.d.ts.map +1 -0
  446. package/dist/src/tui/components/MessageItem.js +27 -0
  447. package/dist/src/tui/components/MessageItem.js.map +1 -0
  448. package/dist/src/tui/components/ScrollableBox.d.ts +41 -0
  449. package/dist/src/tui/components/ScrollableBox.d.ts.map +1 -0
  450. package/dist/src/tui/components/ScrollableBox.js +101 -0
  451. package/dist/src/tui/components/ScrollableBox.js.map +1 -0
  452. package/dist/src/tui/components/ToolCallItem.d.ts +33 -0
  453. package/dist/src/tui/components/ToolCallItem.d.ts.map +1 -0
  454. package/dist/src/tui/components/ToolCallItem.js +91 -0
  455. package/dist/src/tui/components/ToolCallItem.js.map +1 -0
  456. package/dist/src/tui/components/index.d.ts +13 -0
  457. package/dist/src/tui/components/index.d.ts.map +1 -0
  458. package/dist/src/tui/components/index.js +15 -0
  459. package/dist/src/tui/components/index.js.map +1 -0
  460. package/dist/src/tui/event-display.d.ts +19 -0
  461. package/dist/src/tui/event-display.d.ts.map +1 -0
  462. package/dist/src/tui/event-display.js +178 -0
  463. package/dist/src/tui/event-display.js.map +1 -0
  464. package/dist/src/tui/index.d.ts +105 -0
  465. package/dist/src/tui/index.d.ts.map +1 -0
  466. package/dist/src/tui/index.js +214 -0
  467. package/dist/src/tui/index.js.map +1 -0
  468. package/dist/src/tui/input/CommandPalette.d.ts +55 -0
  469. package/dist/src/tui/input/CommandPalette.d.ts.map +1 -0
  470. package/dist/src/tui/input/CommandPalette.js +135 -0
  471. package/dist/src/tui/input/CommandPalette.js.map +1 -0
  472. package/dist/src/tui/input/index.d.ts +7 -0
  473. package/dist/src/tui/input/index.d.ts.map +1 -0
  474. package/dist/src/tui/input/index.js +7 -0
  475. package/dist/src/tui/input/index.js.map +1 -0
  476. package/dist/src/tui/theme/index.d.ts +45 -0
  477. package/dist/src/tui/theme/index.d.ts.map +1 -0
  478. package/dist/src/tui/theme/index.js +215 -0
  479. package/dist/src/tui/theme/index.js.map +1 -0
  480. package/dist/src/tui/types.d.ts +214 -0
  481. package/dist/src/tui/types.d.ts.map +1 -0
  482. package/dist/src/tui/types.js +27 -0
  483. package/dist/src/tui/types.js.map +1 -0
  484. package/dist/src/types.d.ts +905 -0
  485. package/dist/src/types.d.ts.map +1 -0
  486. package/dist/src/types.js +9 -0
  487. package/dist/src/types.js.map +1 -0
  488. package/package.json +89 -0
@@ -0,0 +1,1320 @@
1
+ /**
2
+ * Unified Command Handler
3
+ *
4
+ * Handles all slash commands for both REPL and TUI modes.
5
+ * Uses CommandContext.output for all output, making it mode-agnostic.
6
+ */
7
+ import { persistenceDebug, saveCheckpointToStore, } from '../integrations/persistence.js';
8
+ import { formatServerList, getContextUsage, formatCompactionResult } from '../integrations/index.js';
9
+ import { formatSessionsTable } from '../session-picker.js';
10
+ // =============================================================================
11
+ // ANSI COLOR UTILITIES
12
+ // =============================================================================
13
+ const colors = {
14
+ reset: '\x1b[0m',
15
+ bold: '\x1b[1m',
16
+ dim: '\x1b[2m',
17
+ red: '\x1b[31m',
18
+ green: '\x1b[32m',
19
+ yellow: '\x1b[33m',
20
+ blue: '\x1b[34m',
21
+ magenta: '\x1b[35m',
22
+ cyan: '\x1b[36m',
23
+ white: '\x1b[37m',
24
+ };
25
+ /**
26
+ * Apply ANSI color to text.
27
+ */
28
+ function c(text, color) {
29
+ return `${colors[color]}${text}${colors.reset}`;
30
+ }
31
+ // =============================================================================
32
+ // HELP TEXT
33
+ // =============================================================================
34
+ function getHelpText() {
35
+ return `
36
+ ${c('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'dim')}
37
+ ${c(' ATTOCODE HELP', 'bold')}
38
+ ${c('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'dim')}
39
+
40
+ ${c('GENERAL', 'bold')}
41
+ ${c('/help', 'cyan')} Show this help (alias: /h, /?)
42
+ ${c('/status', 'cyan')} Show session stats, metrics & token usage
43
+ ${c('/clear', 'cyan')} Clear the screen
44
+ ${c('/reset', 'cyan')} Reset agent state (clears conversation)
45
+ ${c('/quit', 'cyan')} Exit attocode (alias: /exit, /q)
46
+
47
+ ${c('AGENT MODES', 'bold')}
48
+ ${c('/mode', 'cyan')} Show current mode and available modes
49
+ ${c('/mode <name>', 'cyan')} Switch to mode (build, plan, review, debug)
50
+ ${c('/plan', 'cyan')} Toggle plan mode (writes queued for approval)
51
+
52
+ ${c('PLAN APPROVAL (in Plan Mode)', 'bold')}
53
+ ${c('/show-plan', 'cyan')} Show pending plan with proposed changes
54
+ ${c('/approve', 'cyan')} Approve and execute all pending changes
55
+ ${c('/approve <n>', 'cyan')} Approve and execute first n changes only
56
+ ${c('/reject', 'cyan')} Reject and discard all pending changes
57
+
58
+ ${c('SESSIONS & PERSISTENCE', 'bold')}
59
+ ${c('/save', 'cyan')} Save current session to disk
60
+ ${c('/load <id>', 'cyan')} Load a previous session by ID
61
+ ${c('/sessions', 'cyan')} List all saved sessions with timestamps
62
+ ${c('/resume', 'cyan')} Resume most recent session (auto-loads last checkpoint)
63
+
64
+ ${c('CONTEXT MANAGEMENT', 'bold')}
65
+ ${c('/context', 'cyan')} Show context window usage (tokens used/available)
66
+ ${c('/context breakdown', 'cyan')} Detailed token breakdown by category
67
+ ${c('/compact', 'cyan')} Summarize & compress context to free tokens
68
+ ${c('/compact status', 'cyan')} Check if compaction is recommended
69
+
70
+ ${c('CHECKPOINTS & THREADS', 'bold')}
71
+ ${c('/checkpoint [label]', 'cyan')} Create a named checkpoint (alias: /cp)
72
+ ${c('/checkpoints', 'cyan')} List all checkpoints (alias: /cps)
73
+ ${c('/restore <id>', 'cyan')} Restore conversation to a checkpoint
74
+ ${c('/rollback [n]', 'cyan')} Rollback n steps (default: 1) (alias: /rb)
75
+ ${c('/fork <name>', 'cyan')} Fork conversation into a new thread
76
+ ${c('/threads', 'cyan')} List all conversation threads
77
+ ${c('/switch <id>', 'cyan')} Switch to a different thread
78
+
79
+ ${c('REASONING MODES', 'bold')}
80
+ ${c('/react <task>', 'cyan')} Run with ReAct (Reason + Act) pattern
81
+ ${c('/team <task>', 'cyan')} Run with multi-agent team coordination
82
+
83
+ ${c('SUBAGENTS', 'bold')}
84
+ ${c('/agents', 'cyan')} List all available agents with descriptions
85
+ ${c('/spawn <agent> <task>', 'cyan')} Spawn a specific agent to handle task
86
+ ${c('/find <query>', 'cyan')} Find agents by keyword search
87
+ ${c('/suggest <task>', 'cyan')} AI-powered agent suggestion for task
88
+ ${c('/auto <task>', 'cyan')} Auto-route task to best agent
89
+
90
+ ${c('MCP INTEGRATION', 'bold')}
91
+ ${c('/mcp', 'cyan')} List MCP servers and connection status
92
+ ${c('/mcp connect <name>', 'cyan')} Connect to an MCP server
93
+ ${c('/mcp disconnect <name>', 'cyan')} Disconnect from server
94
+ ${c('/mcp tools', 'cyan')} List all available MCP tools
95
+ ${c('/mcp search <query>', 'cyan')} Search & lazy-load MCP tools
96
+ ${c('/mcp stats', 'cyan')} Show MCP context usage statistics
97
+
98
+ ${c('BUDGET & ECONOMICS', 'bold')}
99
+ ${c('/budget', 'cyan')} Show token/cost budget and usage
100
+ ${c('/extend <type> <n>', 'cyan')} Extend budget limit
101
+
102
+ ${c('PERMISSIONS & SECURITY', 'bold')}
103
+ ${c('/grants', 'cyan')} Show active permission grants
104
+ ${c('/audit', 'cyan')} Show security audit log
105
+
106
+ ${c('DEBUGGING & TESTING', 'bold')}
107
+ ${c('/skills', 'cyan')} List loaded skills
108
+ ${c('/sandbox', 'cyan')} Show sandbox modes available
109
+ ${c('/shell', 'cyan')} Show PTY shell integration info
110
+ ${c('/lsp', 'cyan')} Show LSP integration status
111
+ ${c('/tui', 'cyan')} Show TUI features & capabilities
112
+
113
+ ${c('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'dim')}
114
+ ${c('SHORTCUTS', 'bold')}
115
+ ${c('Ctrl+C', 'yellow')} Exit ${c('Ctrl+L', 'yellow')} Clear screen
116
+ ${c('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'dim')}
117
+ `;
118
+ }
119
+ // =============================================================================
120
+ // MAIN COMMAND HANDLER
121
+ // =============================================================================
122
+ /**
123
+ * Handle a slash command.
124
+ *
125
+ * @param cmd - Command string (with leading slash)
126
+ * @param args - Command arguments
127
+ * @param ctx - Command context with agent, output, integrations
128
+ * @returns 'quit' to exit, void otherwise
129
+ */
130
+ export async function handleCommand(cmd, args, ctx) {
131
+ const { agent, sessionId, output, integrations } = ctx;
132
+ const { sessionStore, mcpClient, compactor } = integrations;
133
+ switch (cmd) {
134
+ // =========================================================================
135
+ // GENERAL COMMANDS
136
+ // =========================================================================
137
+ case '/quit':
138
+ case '/exit':
139
+ case '/q':
140
+ return 'quit';
141
+ case '/help':
142
+ case '/h':
143
+ case '/?':
144
+ output.log(getHelpText());
145
+ break;
146
+ case '/status': {
147
+ const metrics = agent.getMetrics();
148
+ const state = agent.getState();
149
+ // Get goals summary if SQLite store
150
+ let goalsSummary = '';
151
+ if ('listActiveGoals' in sessionStore) {
152
+ const sqlStore = sessionStore;
153
+ const activeGoals = sqlStore.listActiveGoals();
154
+ if (activeGoals.length > 0) {
155
+ let totalCurrent = 0;
156
+ let totalExpected = 0;
157
+ const goalLines = [];
158
+ for (const goal of activeGoals) {
159
+ if (goal.progressTotal) {
160
+ totalCurrent += goal.progressCurrent;
161
+ totalExpected += goal.progressTotal;
162
+ const pct = Math.round((goal.progressCurrent / goal.progressTotal) * 100);
163
+ goalLines.push(` - ${goal.goalText} (${goal.progressCurrent}/${goal.progressTotal} - ${pct}%)`);
164
+ }
165
+ else {
166
+ goalLines.push(` - ${goal.goalText}`);
167
+ }
168
+ }
169
+ goalsSummary = `\n${c('Active Goals:', 'bold')} (${activeGoals.length})`;
170
+ if (totalExpected > 0) {
171
+ const overallPct = Math.round((totalCurrent / totalExpected) * 100);
172
+ goalsSummary += c(` [Overall: ${overallPct}%]`, 'cyan');
173
+ }
174
+ goalsSummary += '\n' + goalLines.slice(0, 5).join('\n');
175
+ if (activeGoals.length > 5) {
176
+ goalsSummary += c(`\n ... and ${activeGoals.length - 5} more`, 'dim');
177
+ }
178
+ }
179
+ }
180
+ output.log(`
181
+ ${c('Session Status:', 'bold')}
182
+ Session ID: ${sessionId}
183
+ Status: ${state.status}
184
+ Iteration: ${state.iteration}
185
+ Messages: ${state.messages.length}
186
+
187
+ ${c('Token Usage:', 'bold')}
188
+ Input tokens: ${metrics.inputTokens.toLocaleString()}
189
+ Output tokens: ${metrics.outputTokens.toLocaleString()}
190
+ Total tokens: ${metrics.totalTokens.toLocaleString()}
191
+
192
+ ${c('Activity:', 'bold')}
193
+ LLM calls: ${metrics.llmCalls}
194
+ Tool calls: ${metrics.toolCalls}
195
+ Duration: ${metrics.duration}ms
196
+ Est. Cost: $${metrics.estimatedCost.toFixed(4)}
197
+ ${goalsSummary}`);
198
+ break;
199
+ }
200
+ case '/clear':
201
+ output.clear();
202
+ output.log(c(`Production Agent - Session: ${sessionId}`, 'cyan'));
203
+ break;
204
+ case '/reset':
205
+ agent.reset();
206
+ output.log(c('+ Agent state reset', 'green'));
207
+ break;
208
+ // =========================================================================
209
+ // MODE MANAGEMENT
210
+ // =========================================================================
211
+ case '/mode': {
212
+ if (args.length === 0) {
213
+ const modeInfo = agent.getModeInfo();
214
+ const hasPlan = agent.hasPendingPlan();
215
+ const pendingCount = agent.getPendingChangeCount();
216
+ output.log(`
217
+ ${c('Current Mode:', 'bold')} ${modeInfo.color}${modeInfo.icon} ${modeInfo.name}\x1b[0m
218
+ ${hasPlan ? c(` Pending Plan: ${pendingCount} change(s) awaiting approval`, 'yellow') : ''}
219
+
220
+ ${agent.getAvailableModes()}
221
+
222
+ ${c('Usage:', 'dim')} /mode <name> to switch, /plan to toggle plan mode`);
223
+ }
224
+ else {
225
+ const newMode = args[0].toLowerCase();
226
+ agent.setMode(newMode);
227
+ const modeInfo = agent.getModeInfo();
228
+ output.log(`${c('Mode changed to:', 'green')} ${modeInfo.color}${modeInfo.icon} ${modeInfo.name}\x1b[0m`);
229
+ if (newMode !== 'plan' && agent.hasPendingPlan()) {
230
+ output.log(c('Warning: You have a pending plan. Use /show-plan to view, /approve or /reject to resolve.', 'yellow'));
231
+ }
232
+ }
233
+ break;
234
+ }
235
+ case '/plan': {
236
+ const newMode = agent.togglePlanMode();
237
+ const modeInfo = agent.getModeInfo();
238
+ output.log(`${c('Mode toggled to:', 'green')} ${modeInfo.color}${modeInfo.icon} ${modeInfo.name}\x1b[0m`);
239
+ if (newMode === 'plan') {
240
+ output.log(c(`
241
+ In Plan Mode:
242
+ - You can explore the codebase and use all tools
243
+ - Write operations will be QUEUED for approval
244
+ - Use /show-plan to see queued changes
245
+ - Use /approve to execute, /reject to discard
246
+ `, 'dim'));
247
+ }
248
+ else if (agent.hasPendingPlan()) {
249
+ output.log(c('Note: You have a pending plan. Use /show-plan, /approve, or /reject.', 'yellow'));
250
+ }
251
+ break;
252
+ }
253
+ // =========================================================================
254
+ // PLAN APPROVAL COMMANDS
255
+ // =========================================================================
256
+ case '/show-plan': {
257
+ if (!agent.hasPendingPlan()) {
258
+ output.log(c('No pending plan. Enter plan mode with /plan and make requests that would modify files.', 'dim'));
259
+ }
260
+ else {
261
+ output.log(`\n${agent.formatPendingPlan()}`);
262
+ }
263
+ break;
264
+ }
265
+ case '/approve': {
266
+ if (!agent.hasPendingPlan()) {
267
+ output.log(c('No pending plan to approve.', 'dim'));
268
+ break;
269
+ }
270
+ const count = args[0] ? parseInt(args[0], 10) : undefined;
271
+ if (args[0] && (isNaN(count) || count < 1)) {
272
+ output.log(c('Invalid count. Use /approve or /approve <number>', 'red'));
273
+ break;
274
+ }
275
+ const pendingCount = agent.getPendingChangeCount();
276
+ const toApprove = count ?? pendingCount;
277
+ output.log(c(`Approving ${toApprove} of ${pendingCount} change(s)...`, 'yellow'));
278
+ const result = await agent.approvePlan(count);
279
+ if (result.success) {
280
+ output.log(c(`\n+ Successfully executed ${result.executed} change(s)`, 'green'));
281
+ }
282
+ else {
283
+ output.log(c(`\n! Executed ${result.executed} change(s) with ${result.errors.length} error(s):`, 'yellow'));
284
+ for (const err of result.errors) {
285
+ output.log(c(` - ${err}`, 'red'));
286
+ }
287
+ }
288
+ if (agent.getMode() === 'plan') {
289
+ agent.setMode('build');
290
+ output.log(c('\nSwitched to Build mode.', 'dim'));
291
+ }
292
+ break;
293
+ }
294
+ case '/reject': {
295
+ if (!agent.hasPendingPlan()) {
296
+ output.log(c('No pending plan to reject.', 'dim'));
297
+ break;
298
+ }
299
+ const pendingCount = agent.getPendingChangeCount();
300
+ agent.rejectPlan();
301
+ output.log(c(`x Rejected plan with ${pendingCount} change(s). All proposed changes discarded.`, 'yellow'));
302
+ if (agent.getMode() === 'plan') {
303
+ agent.setMode('build');
304
+ output.log(c('Switched to Build mode.', 'dim'));
305
+ }
306
+ break;
307
+ }
308
+ // =========================================================================
309
+ // GOALS
310
+ // =========================================================================
311
+ case '/goals':
312
+ if ('listActiveGoals' in sessionStore) {
313
+ const sqliteStore = sessionStore;
314
+ const subCmd = args[0]?.toLowerCase();
315
+ if (!subCmd || subCmd === 'list') {
316
+ const goals = sqliteStore.listActiveGoals();
317
+ if (goals.length === 0) {
318
+ output.log(c('No active goals. Use /goals add <text> to create one.', 'dim'));
319
+ }
320
+ else {
321
+ output.log(c('\nActive Goals:', 'bold'));
322
+ for (const goal of goals) {
323
+ const progress = goal.progressTotal
324
+ ? ` (${goal.progressCurrent}/${goal.progressTotal})`
325
+ : '';
326
+ const priority = goal.priority === 1 ? c(' [HIGH]', 'red') :
327
+ goal.priority === 3 ? c(' [low]', 'dim') : '';
328
+ output.log(` - ${goal.goalText}${progress}${priority}`);
329
+ output.log(c(` ID: ${goal.id}`, 'dim'));
330
+ }
331
+ }
332
+ }
333
+ else if (subCmd === 'add' && args.length > 1) {
334
+ const goalText = args.slice(1).join(' ');
335
+ const goalId = sqliteStore.createGoal(goalText);
336
+ output.log(c(`+ Goal created: ${goalId}`, 'green'));
337
+ }
338
+ else if (subCmd === 'done' && args[1]) {
339
+ sqliteStore.completeGoal(args[1]);
340
+ output.log(c(`+ Goal completed: ${args[1]}`, 'green'));
341
+ }
342
+ else if (subCmd === 'progress' && args[1] && args[2] && args[3]) {
343
+ sqliteStore.updateGoal(args[1], {
344
+ progressCurrent: parseInt(args[2], 10),
345
+ progressTotal: parseInt(args[3], 10),
346
+ });
347
+ output.log(c(`+ Progress updated: ${args[2]}/${args[3]}`, 'green'));
348
+ }
349
+ else if (subCmd === 'all') {
350
+ const goals = sqliteStore.listGoals();
351
+ output.log(c('\nAll Goals:', 'bold'));
352
+ for (const goal of goals) {
353
+ const status = goal.status === 'completed' ? c('+', 'green') :
354
+ goal.status === 'abandoned' ? c('x', 'red') : ' ';
355
+ output.log(` ${status} ${goal.goalText} [${goal.status}]`);
356
+ }
357
+ }
358
+ else if (subCmd === 'junctures') {
359
+ const junctures = sqliteStore.listJunctures(undefined, 10);
360
+ if (junctures.length === 0) {
361
+ output.log(c('No junctures logged yet.', 'dim'));
362
+ }
363
+ else {
364
+ output.log(c('\nRecent Key Moments:', 'bold'));
365
+ for (const j of junctures) {
366
+ const icon = j.type === 'failure' ? c('x', 'red') :
367
+ j.type === 'breakthrough' ? c('*', 'yellow') :
368
+ j.type === 'decision' ? c('>', 'cyan') : c('~', 'magenta');
369
+ output.log(` ${icon} [${j.type}] ${j.description}`);
370
+ if (j.outcome)
371
+ output.log(c(` -> ${j.outcome}`, 'dim'));
372
+ }
373
+ }
374
+ }
375
+ else {
376
+ output.log(c('Usage:', 'bold'));
377
+ output.log(c(' /goals - List active goals', 'dim'));
378
+ output.log(c(' /goals add <text> - Create a new goal', 'dim'));
379
+ output.log(c(' /goals done <id> - Mark goal as completed', 'dim'));
380
+ output.log(c(' /goals progress <id> <current> <total> - Update progress', 'dim'));
381
+ output.log(c(' /goals all - List all goals (including completed)', 'dim'));
382
+ output.log(c(' /goals junctures - Show recent key moments', 'dim'));
383
+ }
384
+ }
385
+ else {
386
+ output.log(c('Goals require SQLite store (not available with JSONL fallback)', 'yellow'));
387
+ }
388
+ break;
389
+ case '/handoff':
390
+ if ('exportSessionManifest' in sessionStore) {
391
+ const sqliteStore = sessionStore;
392
+ const format = args[0]?.toLowerCase() || 'markdown';
393
+ if (format === 'json') {
394
+ const manifest = sqliteStore.exportSessionManifest();
395
+ if (manifest) {
396
+ output.log(JSON.stringify(manifest, null, 2));
397
+ }
398
+ else {
399
+ output.log(c('No active session to export', 'yellow'));
400
+ }
401
+ }
402
+ else {
403
+ const markdown = sqliteStore.exportSessionMarkdown();
404
+ output.log(markdown);
405
+ }
406
+ }
407
+ else {
408
+ output.log(c('Handoff requires SQLite store (not available with JSONL fallback)', 'yellow'));
409
+ }
410
+ break;
411
+ // =========================================================================
412
+ // REASONING MODES
413
+ // =========================================================================
414
+ case '/react':
415
+ if (args.length === 0) {
416
+ output.log(c('Usage: /react <task>', 'yellow'));
417
+ }
418
+ else {
419
+ const task = args.join(' ');
420
+ output.log(c(`\nRunning with ReAct pattern: ${task}`, 'cyan'));
421
+ try {
422
+ const trace = await agent.runWithReAct(task);
423
+ output.log(c('\n--- ReAct Trace ---', 'magenta'));
424
+ output.log(agent.formatReActTrace(trace));
425
+ output.log(c('-------------------', 'magenta'));
426
+ }
427
+ catch (error) {
428
+ output.log(c(`Error: ${error.message}`, 'red'));
429
+ }
430
+ }
431
+ break;
432
+ case '/team':
433
+ if (args.length === 0) {
434
+ output.log(c('Usage: /team <task>', 'yellow'));
435
+ }
436
+ else {
437
+ const task = args.join(' ');
438
+ output.log(c(`\nRunning with team: ${task}`, 'cyan'));
439
+ try {
440
+ const { CODER_ROLE, REVIEWER_ROLE, RESEARCHER_ROLE } = await import('../integrations/multi-agent.js');
441
+ const result = await agent.runWithTeam({ id: `team-${Date.now()}`, goal: task, context: '' }, [RESEARCHER_ROLE, CODER_ROLE, REVIEWER_ROLE]);
442
+ output.log(c('\n--- Team Result ---', 'magenta'));
443
+ output.log(`Success: ${result.success}`);
444
+ output.log(`Coordinator: ${result.coordinator}`);
445
+ if (result.consensus) {
446
+ output.log(`Consensus: ${result.consensus.agreed ? 'Agreed' : 'Disagreed'} - ${result.consensus.result}`);
447
+ }
448
+ output.log(c('-------------------', 'magenta'));
449
+ }
450
+ catch (error) {
451
+ output.log(c(`Error: ${error.message}`, 'red'));
452
+ }
453
+ }
454
+ break;
455
+ // =========================================================================
456
+ // CHECKPOINTS & THREADS
457
+ // =========================================================================
458
+ case '/checkpoint':
459
+ case '/cp':
460
+ try {
461
+ const label = args.length > 0 ? args.join(' ') : undefined;
462
+ const checkpoint = agent.createCheckpoint(label);
463
+ output.log(c(`+ Checkpoint created: ${checkpoint.id}${label ? ` (${label})` : ''}`, 'green'));
464
+ }
465
+ catch (error) {
466
+ output.log(c(`Error: ${error.message}`, 'red'));
467
+ }
468
+ break;
469
+ case '/checkpoints':
470
+ case '/cps':
471
+ try {
472
+ const checkpoints = agent.getCheckpoints();
473
+ if (checkpoints.length === 0) {
474
+ output.log(c('No checkpoints.', 'dim'));
475
+ }
476
+ else {
477
+ output.log(c('\nCheckpoints:', 'bold'));
478
+ checkpoints.forEach(cp => {
479
+ output.log(` ${c(cp.id, 'cyan')}${cp.label ? ` - ${cp.label}` : ''}`);
480
+ });
481
+ }
482
+ }
483
+ catch (error) {
484
+ output.log(c(`Error: ${error.message}`, 'red'));
485
+ }
486
+ break;
487
+ case '/restore':
488
+ if (args.length === 0) {
489
+ output.log(c('Usage: /restore <checkpoint-id>', 'yellow'));
490
+ }
491
+ else {
492
+ const success = agent.restoreCheckpoint(args[0]);
493
+ output.log(success ? c(`+ Restored: ${args[0]}`, 'green') : c(`x Not found: ${args[0]}`, 'red'));
494
+ }
495
+ break;
496
+ case '/rollback':
497
+ case '/rb': {
498
+ const steps = args.length > 0 ? parseInt(args[0], 10) : 1;
499
+ if (isNaN(steps) || steps < 1) {
500
+ output.log(c('Usage: /rollback <steps>', 'yellow'));
501
+ }
502
+ else {
503
+ const success = agent.rollback(steps);
504
+ output.log(success ? c(`+ Rolled back ${steps} steps`, 'green') : c('x Rollback failed', 'red'));
505
+ }
506
+ break;
507
+ }
508
+ case '/fork':
509
+ if (args.length === 0) {
510
+ output.log(c('Usage: /fork <name>', 'yellow'));
511
+ }
512
+ else {
513
+ try {
514
+ const threadId = agent.fork(args.join(' '));
515
+ output.log(c(`+ Forked: ${threadId}`, 'green'));
516
+ }
517
+ catch (error) {
518
+ output.log(c(`Error: ${error.message}`, 'red'));
519
+ }
520
+ }
521
+ break;
522
+ case '/threads':
523
+ try {
524
+ const threads = agent.getAllThreads();
525
+ if (threads.length === 0) {
526
+ output.log(c('No threads.', 'dim'));
527
+ }
528
+ else {
529
+ output.log(c('\nThreads:', 'bold'));
530
+ threads.forEach((t) => {
531
+ output.log(` ${c(t.id, 'cyan')}${t.name ? ` - ${t.name}` : ''} (${t.messages?.length || 0} messages)`);
532
+ });
533
+ }
534
+ }
535
+ catch (error) {
536
+ output.log(c(`Error: ${error.message}`, 'red'));
537
+ }
538
+ break;
539
+ case '/switch':
540
+ if (args.length === 0) {
541
+ output.log(c('Usage: /switch <thread-id>', 'yellow'));
542
+ }
543
+ else {
544
+ const success = agent.switchThread(args[0]);
545
+ output.log(success ? c(`+ Switched to: ${args[0]}`, 'green') : c(`x Not found: ${args[0]}`, 'red'));
546
+ }
547
+ break;
548
+ // =========================================================================
549
+ // SECURITY
550
+ // =========================================================================
551
+ case '/grants':
552
+ try {
553
+ const grants = agent.getActiveGrants();
554
+ if (grants.length === 0) {
555
+ output.log(c('No active permission grants.', 'dim'));
556
+ }
557
+ else {
558
+ output.log(c('\nActive Grants:', 'bold'));
559
+ grants.forEach((g) => {
560
+ output.log(` ${c(g.id, 'cyan')} - ${g.toolName} (${g.grantedBy})`);
561
+ });
562
+ }
563
+ }
564
+ catch (error) {
565
+ output.log(c(`Error: ${error.message}`, 'red'));
566
+ }
567
+ break;
568
+ case '/audit':
569
+ try {
570
+ const log = agent.getAuditLog();
571
+ if (log.length === 0) {
572
+ output.log(c('No audit entries.', 'dim'));
573
+ }
574
+ else {
575
+ output.log(c('\nAudit Log:', 'bold'));
576
+ log.slice(-10).forEach((entry) => {
577
+ const status = entry.approved ? c('+', 'green') : c('x', 'red');
578
+ output.log(` ${status} ${entry.action} - ${entry.tool || 'n/a'}`);
579
+ });
580
+ }
581
+ }
582
+ catch (error) {
583
+ output.log(c(`Error: ${error.message}`, 'red'));
584
+ }
585
+ break;
586
+ // =========================================================================
587
+ // BUDGET
588
+ // =========================================================================
589
+ case '/budget':
590
+ try {
591
+ const usage = agent.getBudgetUsage();
592
+ const limits = agent.getBudgetLimits();
593
+ const progress = agent.getProgress();
594
+ if (!usage || !limits) {
595
+ output.log(c('Economics not available.', 'dim'));
596
+ }
597
+ else {
598
+ output.log(`
599
+ ${c('Budget Usage:', 'bold')}
600
+ Tokens: ${usage.tokens.toLocaleString()} / ${limits.maxTokens.toLocaleString()} (${usage.percentUsed.toFixed(1)}%)
601
+ Cost: $${usage.cost.toFixed(4)} / $${limits.maxCost.toFixed(2)}
602
+ Duration: ${Math.round(usage.duration / 1000)}s / ${Math.round(limits.maxDuration / 1000)}s
603
+ Iterations: ${usage.iterations} / ${limits.maxIterations}
604
+
605
+ ${c('Progress:', 'bold')}
606
+ Files read: ${progress?.filesRead || 0}
607
+ Files modified: ${progress?.filesModified || 0}
608
+ Commands run: ${progress?.commandsRun || 0}
609
+ Status: ${progress?.isStuck ? c('STUCK', 'red') : c('Active', 'green')}
610
+ `);
611
+ }
612
+ }
613
+ catch (error) {
614
+ output.log(c(`Error: ${error.message}`, 'red'));
615
+ }
616
+ break;
617
+ case '/extend':
618
+ if (args.length === 0) {
619
+ output.log(c('Usage: /extend <tokens|cost|time> <amount>', 'yellow'));
620
+ }
621
+ else {
622
+ const [what, amount] = args;
623
+ const value = parseFloat(amount);
624
+ if (isNaN(value)) {
625
+ output.log(c('Invalid amount', 'red'));
626
+ }
627
+ else {
628
+ const limits = agent.getBudgetLimits();
629
+ if (!limits) {
630
+ output.log(c('Economics not available', 'dim'));
631
+ }
632
+ else {
633
+ switch (what) {
634
+ case 'tokens':
635
+ agent.extendBudget({ maxTokens: limits.maxTokens + value });
636
+ output.log(c(`+ Token budget extended to ${(limits.maxTokens + value).toLocaleString()}`, 'green'));
637
+ break;
638
+ case 'cost':
639
+ agent.extendBudget({ maxCost: limits.maxCost + value });
640
+ output.log(c(`+ Cost budget extended to $${(limits.maxCost + value).toFixed(2)}`, 'green'));
641
+ break;
642
+ case 'time':
643
+ agent.extendBudget({ maxDuration: limits.maxDuration + value * 1000 });
644
+ output.log(c(`+ Time budget extended to ${Math.round((limits.maxDuration + value * 1000) / 1000)}s`, 'green'));
645
+ break;
646
+ default:
647
+ output.log(c('Unknown budget type. Use: tokens, cost, or time', 'yellow'));
648
+ }
649
+ }
650
+ }
651
+ }
652
+ break;
653
+ // =========================================================================
654
+ // SUBAGENTS
655
+ // =========================================================================
656
+ case '/agents':
657
+ try {
658
+ const agentList = agent.formatAgentList();
659
+ output.log(c('\nAvailable Agents:', 'bold'));
660
+ output.log(agentList);
661
+ }
662
+ catch (error) {
663
+ output.log(c(`Error: ${error.message}`, 'red'));
664
+ }
665
+ break;
666
+ case '/spawn':
667
+ if (args.length < 2) {
668
+ output.log(c('Usage: /spawn <agent-name> <task>', 'yellow'));
669
+ }
670
+ else {
671
+ const agentName = args[0];
672
+ const task = args.slice(1).join(' ');
673
+ output.log(c(`\nSpawning ${agentName}: ${task}`, 'cyan'));
674
+ try {
675
+ const result = await agent.spawnAgent(agentName, task);
676
+ output.log(c('\n--- Agent Result ---', 'magenta'));
677
+ output.log(`Success: ${result.success}`);
678
+ output.log(`Output: ${result.output}`);
679
+ output.log(c(`\nTokens: ${result.metrics.tokens} | Tools: ${result.metrics.toolCalls} | Duration: ${result.metrics.duration}ms`, 'dim'));
680
+ output.log(c('--------------------', 'magenta'));
681
+ }
682
+ catch (error) {
683
+ output.log(c(`Error: ${error.message}`, 'red'));
684
+ }
685
+ }
686
+ break;
687
+ case '/find':
688
+ if (args.length === 0) {
689
+ output.log(c('Usage: /find <query>', 'yellow'));
690
+ }
691
+ else {
692
+ const query = args.join(' ');
693
+ output.log(c(`\nFinding agents for: "${query}"`, 'cyan'));
694
+ const matches = agent.findAgentsForTask(query);
695
+ if (matches.length === 0) {
696
+ output.log(c('No matching agents found.', 'dim'));
697
+ }
698
+ else {
699
+ output.log(c('\nMatching Agents:', 'bold'));
700
+ matches.forEach((a, i) => {
701
+ output.log(` ${i + 1}. ${c(a.name, 'cyan')} (${a.source})`);
702
+ output.log(` ${a.description.split('.')[0]}`);
703
+ if (a.capabilities?.length) {
704
+ output.log(c(` Capabilities: ${a.capabilities.join(', ')}`, 'dim'));
705
+ }
706
+ });
707
+ output.log(c('\nUse /spawn <agent-name> <task> to run an agent.', 'dim'));
708
+ }
709
+ }
710
+ break;
711
+ case '/suggest':
712
+ if (args.length === 0) {
713
+ output.log(c('Usage: /suggest <task description>', 'yellow'));
714
+ }
715
+ else {
716
+ const taskDesc = args.join(' ');
717
+ output.log(c(`\nAnalyzing task: "${taskDesc}"`, 'cyan'));
718
+ try {
719
+ const { suggestions, shouldDelegate, delegateAgent } = await agent.suggestAgentForTask(taskDesc);
720
+ if (suggestions.length === 0) {
721
+ output.log(c('\nNo specialized agent recommended. Main agent should handle this task.', 'dim'));
722
+ }
723
+ else {
724
+ output.log(c('\nAgent Suggestions:', 'bold'));
725
+ suggestions.forEach((s, i) => {
726
+ const confidenceBar = '='.repeat(Math.round(s.confidence * 10)) + '-'.repeat(10 - Math.round(s.confidence * 10));
727
+ output.log(` ${i + 1}. ${c(s.agent.name, 'cyan')} [${confidenceBar}] ${(s.confidence * 100).toFixed(0)}%`);
728
+ output.log(` ${s.reason}`);
729
+ });
730
+ if (shouldDelegate && delegateAgent) {
731
+ output.log(c(`\nRecommendation: Delegate to "${delegateAgent}"`, 'green'));
732
+ output.log(c(` Run: /spawn ${delegateAgent} ${taskDesc}`, 'dim'));
733
+ }
734
+ else {
735
+ output.log(c('\nRecommendation: Main agent should handle this task.', 'dim'));
736
+ }
737
+ }
738
+ }
739
+ catch (error) {
740
+ output.log(c(`Error: ${error.message}`, 'red'));
741
+ }
742
+ }
743
+ break;
744
+ case '/auto':
745
+ if (args.length === 0) {
746
+ output.log(c('Usage: /auto <task>', 'yellow'));
747
+ }
748
+ else {
749
+ const autoTask = args.join(' ');
750
+ output.log(c(`\nAuto-routing: "${autoTask}"`, 'cyan'));
751
+ try {
752
+ // Create a confirmation callback
753
+ const confirmDelegate = async (suggestedAgent, reason) => {
754
+ output.log(c(`\nSuggested agent: ${suggestedAgent.name}`, 'yellow'));
755
+ output.log(c(` Reason: ${reason}`, 'dim'));
756
+ if (ctx.confirm) {
757
+ return ctx.confirm('Delegate to this agent?');
758
+ }
759
+ if (ctx.rl) {
760
+ const answer = await ctx.rl.question(c(' Delegate to this agent? (y/n): ', 'yellow'));
761
+ return answer.toLowerCase().startsWith('y');
762
+ }
763
+ return false;
764
+ };
765
+ const result = await agent.runWithAutoRouting(autoTask, {
766
+ confidenceThreshold: 0.75,
767
+ confirmDelegate,
768
+ });
769
+ if ('output' in result) {
770
+ output.log(c('\n--- Subagent Result ---', 'magenta'));
771
+ output.log(`Success: ${result.success}`);
772
+ output.log(result.output);
773
+ output.log(c(`\nTokens: ${result.metrics.tokens} | Duration: ${result.metrics.duration}ms`, 'dim'));
774
+ output.log(c('-----------------------', 'magenta'));
775
+ }
776
+ else {
777
+ output.log(c('\n--- Assistant ---', 'magenta'));
778
+ output.log(result.response);
779
+ output.log(c('-----------------', 'magenta'));
780
+ output.log(c(`\nTokens: ${result.metrics.inputTokens} in / ${result.metrics.outputTokens} out | Tools: ${result.metrics.toolCalls}`, 'dim'));
781
+ }
782
+ }
783
+ catch (error) {
784
+ output.log(c(`Error: ${error.message}`, 'red'));
785
+ }
786
+ }
787
+ break;
788
+ // =========================================================================
789
+ // MCP INTEGRATION
790
+ // =========================================================================
791
+ case '/mcp':
792
+ if (args.length === 0) {
793
+ const servers = mcpClient.listServers();
794
+ output.log(formatServerList(servers));
795
+ }
796
+ else if (args[0] === 'connect' && args[1]) {
797
+ output.log(c(`Connecting to ${args[1]}...`, 'cyan'));
798
+ try {
799
+ await mcpClient.connectServer(args[1]);
800
+ output.log(c(`+ Connected to ${args[1]}`, 'green'));
801
+ const tools = mcpClient.getAllTools();
802
+ for (const tool of tools) {
803
+ agent.addTool(tool);
804
+ }
805
+ output.log(c(` Added ${tools.length} tools from MCP servers`, 'dim'));
806
+ }
807
+ catch (error) {
808
+ output.log(c(`Error: ${error.message}`, 'red'));
809
+ }
810
+ }
811
+ else if (args[0] === 'disconnect' && args[1]) {
812
+ await mcpClient.disconnectServer(args[1]);
813
+ output.log(c(`+ Disconnected from ${args[1]}`, 'green'));
814
+ }
815
+ else if (args[0] === 'tools') {
816
+ const tools = mcpClient.getAllTools();
817
+ if (tools.length === 0) {
818
+ output.log(c('No MCP tools available.', 'dim'));
819
+ }
820
+ else {
821
+ output.log(c('\nMCP Tools:', 'bold'));
822
+ tools.forEach(t => {
823
+ const loaded = mcpClient.isToolLoaded(t.name);
824
+ const status = loaded ? c('+', 'green') : c('o', 'dim');
825
+ output.log(` ${status} ${c(t.name, 'cyan')} - ${t.description?.slice(0, 60) || 'No description'}...`);
826
+ });
827
+ const stats = mcpClient.getContextStats();
828
+ output.log(c(`\n Legend: + = full schema loaded, o = summary only`, 'dim'));
829
+ output.log(c(` Loaded: ${stats.loadedCount}/${stats.totalTools} tools`, 'dim'));
830
+ }
831
+ }
832
+ else if (args[0] === 'search') {
833
+ const query = args.slice(1).join(' ');
834
+ if (!query) {
835
+ output.log(c('Usage: /mcp search <query>', 'yellow'));
836
+ }
837
+ else {
838
+ output.log(c(`Searching for: "${query}"...`, 'cyan'));
839
+ const results = mcpClient.searchTools(query, { limit: 10 });
840
+ if (results.length === 0) {
841
+ output.log(c('No matching tools found.', 'dim'));
842
+ }
843
+ else {
844
+ output.log(c(`\nFound ${results.length} tool(s):`, 'bold'));
845
+ results.forEach(r => {
846
+ output.log(` ${c(r.name, 'cyan')} (${r.serverName})`);
847
+ output.log(` ${r.description}`);
848
+ });
849
+ const loadedTools = mcpClient.loadTools(results.map(r => r.name));
850
+ for (const tool of loadedTools) {
851
+ agent.addTool(tool);
852
+ }
853
+ output.log(c(`\n+ Loaded ${loadedTools.length} tool(s). They are now available for use.`, 'green'));
854
+ }
855
+ }
856
+ }
857
+ else if (args[0] === 'stats') {
858
+ const stats = mcpClient.getContextStats();
859
+ const fullLoadEstimate = stats.totalTools * 200;
860
+ const currentTokens = stats.summaryTokens + stats.definitionTokens;
861
+ const savingsPercent = fullLoadEstimate > 0
862
+ ? Math.round((1 - currentTokens / fullLoadEstimate) * 100)
863
+ : 0;
864
+ output.log(`
865
+ ${c('MCP Context Usage:', 'bold')}
866
+ Tool summaries: ${stats.summaryCount.toString().padStart(3)} tools (~${stats.summaryTokens.toLocaleString()} tokens)
867
+ Full definitions: ${stats.loadedCount.toString().padStart(3)} tools (~${stats.definitionTokens.toLocaleString()} tokens)
868
+ Total: ${stats.totalTools.toString().padStart(3)} tools (~${currentTokens.toLocaleString()} tokens)
869
+
870
+ Context savings: ${savingsPercent}% vs loading all full schemas
871
+ ${savingsPercent > 50 ? c('+ Good - lazy loading is saving context', 'green') : c('! Consider using lazy loading more', 'yellow')}
872
+
873
+ ${c('Tip:', 'dim')} Use /mcp search <query> to load specific tools on-demand.
874
+ `);
875
+ }
876
+ else {
877
+ output.log(c('Usage:', 'bold'));
878
+ output.log(c(' /mcp - List servers', 'dim'));
879
+ output.log(c(' /mcp connect <name> - Connect to server', 'dim'));
880
+ output.log(c(' /mcp disconnect <name> - Disconnect', 'dim'));
881
+ output.log(c(' /mcp tools - List available tools', 'dim'));
882
+ output.log(c(' /mcp search <query> - Search & load tools', 'dim'));
883
+ output.log(c(' /mcp stats - Show context usage stats', 'dim'));
884
+ }
885
+ break;
886
+ // =========================================================================
887
+ // SESSION MANAGEMENT
888
+ // =========================================================================
889
+ case '/save':
890
+ try {
891
+ const state = agent.getState();
892
+ const metrics = agent.getMetrics();
893
+ const saveCheckpointId = `ckpt-manual-${Date.now().toString(36)}`;
894
+ persistenceDebug.log('/save command - creating checkpoint', {
895
+ checkpointId: saveCheckpointId,
896
+ messageCount: state.messages?.length ?? 0,
897
+ });
898
+ saveCheckpointToStore(sessionStore, {
899
+ id: saveCheckpointId,
900
+ label: 'manual-save',
901
+ messages: state.messages,
902
+ iteration: state.iteration,
903
+ metrics: metrics,
904
+ plan: state.plan,
905
+ memoryContext: state.memoryContext,
906
+ });
907
+ output.log(c(`+ Session saved: ${sessionId} (checkpoint: ${saveCheckpointId})`, 'green'));
908
+ }
909
+ catch (error) {
910
+ persistenceDebug.error('/save command failed', error);
911
+ output.log(c(`Error saving session: ${error.message}`, 'red'));
912
+ }
913
+ break;
914
+ case '/load':
915
+ if (args.length === 0) {
916
+ output.log(c('Usage: /load <session-id>', 'yellow'));
917
+ output.log(c(' Use /sessions to list available sessions', 'dim'));
918
+ }
919
+ else {
920
+ const loadId = args[0];
921
+ try {
922
+ let checkpointData;
923
+ if ('loadLatestCheckpoint' in sessionStore && typeof sessionStore.loadLatestCheckpoint === 'function') {
924
+ const sqliteCheckpoint = sessionStore.loadLatestCheckpoint(loadId);
925
+ if (sqliteCheckpoint?.state) {
926
+ checkpointData = sqliteCheckpoint.state;
927
+ }
928
+ }
929
+ if (!checkpointData) {
930
+ const entries = await sessionStore.loadSession(loadId);
931
+ if (entries.length === 0) {
932
+ output.log(c(`No entries found for session: ${loadId}`, 'yellow'));
933
+ break;
934
+ }
935
+ const checkpoint = [...entries].reverse().find(e => e.type === 'checkpoint');
936
+ checkpointData = checkpoint?.data;
937
+ }
938
+ if (checkpointData?.messages) {
939
+ agent.loadState({
940
+ messages: checkpointData.messages,
941
+ iteration: checkpointData.iteration,
942
+ metrics: checkpointData.metrics,
943
+ plan: checkpointData.plan,
944
+ memoryContext: checkpointData.memoryContext,
945
+ });
946
+ output.log(c(`+ Loaded ${checkpointData.messages.length} messages from ${loadId}`, 'green'));
947
+ }
948
+ else {
949
+ output.log(c('No checkpoint found in session', 'yellow'));
950
+ }
951
+ }
952
+ catch (error) {
953
+ output.log(c(`Error loading session: ${error.message}`, 'red'));
954
+ }
955
+ }
956
+ break;
957
+ case '/resume':
958
+ try {
959
+ const recentSession = sessionStore.getRecentSession();
960
+ if (!recentSession) {
961
+ output.log(c('No previous sessions found', 'yellow'));
962
+ }
963
+ else {
964
+ output.log(c(`Found recent session: ${recentSession.id}`, 'dim'));
965
+ output.log(c(` Created: ${new Date(recentSession.createdAt).toLocaleString()}`, 'dim'));
966
+ output.log(c(` Messages: ${recentSession.messageCount}`, 'dim'));
967
+ let resumeCheckpointData;
968
+ if ('loadLatestCheckpoint' in sessionStore && typeof sessionStore.loadLatestCheckpoint === 'function') {
969
+ const sqliteCheckpoint = sessionStore.loadLatestCheckpoint(recentSession.id);
970
+ if (sqliteCheckpoint?.state) {
971
+ resumeCheckpointData = sqliteCheckpoint.state;
972
+ }
973
+ }
974
+ if (!resumeCheckpointData) {
975
+ const entriesResult = sessionStore.loadSession(recentSession.id);
976
+ const entries = Array.isArray(entriesResult) ? entriesResult : await entriesResult;
977
+ const checkpoint = [...entries].reverse().find(e => e.type === 'checkpoint');
978
+ if (checkpoint?.data) {
979
+ resumeCheckpointData = checkpoint.data;
980
+ }
981
+ else {
982
+ const messages = entries
983
+ .filter((e) => e.type === 'message')
984
+ .map((e) => e.data);
985
+ if (messages.length > 0) {
986
+ agent.loadState({ messages: messages });
987
+ output.log(c(`+ Resumed ${messages.length} messages from last session`, 'green'));
988
+ }
989
+ else {
990
+ output.log(c('No messages found in last session', 'yellow'));
991
+ }
992
+ }
993
+ }
994
+ if (resumeCheckpointData?.messages) {
995
+ agent.loadState({
996
+ messages: resumeCheckpointData.messages,
997
+ iteration: resumeCheckpointData.iteration,
998
+ metrics: resumeCheckpointData.metrics,
999
+ plan: resumeCheckpointData.plan,
1000
+ memoryContext: resumeCheckpointData.memoryContext,
1001
+ });
1002
+ output.log(c(`+ Resumed ${resumeCheckpointData.messages.length} messages from last session`, 'green'));
1003
+ if (resumeCheckpointData.iteration) {
1004
+ output.log(c(` Iteration: ${resumeCheckpointData.iteration}`, 'dim'));
1005
+ }
1006
+ if (resumeCheckpointData.plan) {
1007
+ output.log(c(` Plan restored`, 'dim'));
1008
+ }
1009
+ if ('getPendingPlan' in sessionStore && typeof sessionStore.getPendingPlan === 'function') {
1010
+ const pendingPlan = sessionStore.getPendingPlan(recentSession.id);
1011
+ if (pendingPlan && pendingPlan.status === 'pending') {
1012
+ output.log(c(`\nFound pending plan: "${pendingPlan.task}"`, 'yellow'));
1013
+ output.log(c(` ${pendingPlan.proposedChanges.length} change(s) awaiting approval`, 'yellow'));
1014
+ output.log(c(' Use /show-plan to view, /approve to execute, /reject to discard', 'dim'));
1015
+ }
1016
+ }
1017
+ }
1018
+ }
1019
+ }
1020
+ catch (error) {
1021
+ output.log(c(`Error resuming session: ${error.message}`, 'red'));
1022
+ }
1023
+ break;
1024
+ case '/sessions':
1025
+ try {
1026
+ const sessions = await sessionStore.listSessions();
1027
+ output.log(formatSessionsTable(sessions));
1028
+ }
1029
+ catch (error) {
1030
+ output.log(c(`Error: ${error.message}`, 'red'));
1031
+ }
1032
+ break;
1033
+ // =========================================================================
1034
+ // CONTEXT MANAGEMENT
1035
+ // =========================================================================
1036
+ case '/compact':
1037
+ try {
1038
+ const state = agent.getState();
1039
+ const contextUsage = getContextUsage(state.messages, 80000);
1040
+ if (args[0] === 'status') {
1041
+ output.log(`
1042
+ ${c('Context Status:', 'bold')}
1043
+ Messages: ${state.messages.length}
1044
+ Est. Tokens: ${contextUsage.tokens.toLocaleString()}
1045
+ Usage: ${contextUsage.percent}%
1046
+ Threshold: 80%
1047
+ Should Compact: ${contextUsage.shouldCompact ? c('Yes', 'yellow') : c('No', 'green')}
1048
+ `);
1049
+ }
1050
+ else {
1051
+ if (state.messages.length < 5) {
1052
+ output.log(c('Not enough messages to compact.', 'dim'));
1053
+ }
1054
+ else {
1055
+ output.log(c('Compacting context...', 'cyan'));
1056
+ const result = await compactor.compact(state.messages);
1057
+ agent.loadMessages(result.preservedMessages);
1058
+ output.log(formatCompactionResult(result));
1059
+ }
1060
+ }
1061
+ }
1062
+ catch (error) {
1063
+ output.log(c(`Error: ${error.message}`, 'red'));
1064
+ }
1065
+ break;
1066
+ case '/context':
1067
+ try {
1068
+ const state = agent.getState();
1069
+ if (args[0] === 'breakdown') {
1070
+ // Detailed token breakdown
1071
+ const mcpStats = mcpClient.getContextStats();
1072
+ const systemPrompt = agent.getSystemPromptWithMode();
1073
+ const estimateTokens = (str) => Math.ceil(str.length / 3.2);
1074
+ const systemTokens = estimateTokens(systemPrompt);
1075
+ const mcpTokens = mcpStats.summaryTokens + mcpStats.definitionTokens;
1076
+ const agentTools = agent.getTools().filter(t => !t.name.startsWith('mcp_'));
1077
+ const agentToolTokens = agentTools.length * 150;
1078
+ const convTokens = state.messages
1079
+ .filter(m => m.role !== 'system')
1080
+ .reduce((sum, m) => sum + estimateTokens(m.content), 0);
1081
+ const totalTokens = systemTokens + mcpTokens + agentToolTokens + convTokens;
1082
+ const messageCount = state.messages.filter(m => m.role !== 'system').length;
1083
+ const sysPct = totalTokens > 0 ? Math.round((systemTokens / totalTokens) * 100) : 0;
1084
+ const mcpPct = totalTokens > 0 ? Math.round((mcpTokens / totalTokens) * 100) : 0;
1085
+ const agentPct = totalTokens > 0 ? Math.round((agentToolTokens / totalTokens) * 100) : 0;
1086
+ const convPct = totalTokens > 0 ? Math.round((convTokens / totalTokens) * 100) : 0;
1087
+ output.log(`
1088
+ ${c('Context Token Breakdown', 'bold')} (Total: ~${totalTokens.toLocaleString()} tokens)
1089
+
1090
+ ${c(' Category Tokens % of Total', 'dim')}
1091
+ System prompt: ${systemTokens.toLocaleString().padStart(7)} tokens ${sysPct.toString().padStart(3)}%
1092
+ MCP tools: ${mcpTokens.toLocaleString().padStart(7)} tokens ${mcpPct.toString().padStart(3)}% (${mcpStats.loadedCount} loaded / ${mcpStats.totalTools} total)
1093
+ Agent tools: ${agentToolTokens.toLocaleString().padStart(7)} tokens ${agentPct.toString().padStart(3)}% (${agentTools.length} tools)
1094
+ Conversation: ${convTokens.toLocaleString().padStart(7)} tokens ${convPct.toString().padStart(3)}% (${messageCount} messages)
1095
+ `);
1096
+ }
1097
+ else {
1098
+ // Simple context overview
1099
+ const mcpStats = mcpClient.getContextStats();
1100
+ const systemPrompt = agent.getSystemPromptWithMode();
1101
+ const estimateTokens = (str) => Math.ceil(str.length / 3.2);
1102
+ const systemTokens = estimateTokens(systemPrompt);
1103
+ const mcpTokens = mcpStats.summaryTokens + mcpStats.definitionTokens;
1104
+ const agentTools = agent.getTools().filter(t => !t.name.startsWith('mcp_'));
1105
+ const agentToolTokens = agentTools.length * 150;
1106
+ const baseTokens = systemTokens + mcpTokens + agentToolTokens;
1107
+ const convTokens = state.messages
1108
+ .filter(m => m.role !== 'system')
1109
+ .reduce((sum, m) => sum + estimateTokens(m.content), 0);
1110
+ const totalTokens = baseTokens + convTokens;
1111
+ const contextLimit = 80000;
1112
+ const percent = Math.round((totalTokens / contextLimit) * 100);
1113
+ const shouldCompact = percent >= 80;
1114
+ const bar = '='.repeat(Math.min(20, Math.round(percent / 5))) +
1115
+ '-'.repeat(Math.max(0, 20 - Math.round(percent / 5)));
1116
+ const color = percent >= 80 ? 'red' : percent >= 60 ? 'yellow' : 'green';
1117
+ output.log(`
1118
+ ${c('Context Window:', 'bold')}
1119
+ [${c(bar, color)}] ${percent}%
1120
+ Base: ~${baseTokens.toLocaleString()} tokens (system + ${agentTools.length} agent tools)
1121
+ MCP: ~${mcpTokens.toLocaleString()} tokens (${mcpStats.loadedCount}/${mcpStats.totalTools} tools loaded)
1122
+ Messages: ${state.messages.filter(m => m.role !== 'system').length} (~${convTokens.toLocaleString()} tokens)
1123
+ Total: ~${totalTokens.toLocaleString()} / ${(contextLimit / 1000).toFixed(0)}k tokens
1124
+ ${shouldCompact ? c('! Consider running /compact', 'yellow') : c('+ Healthy', 'green')}
1125
+ `);
1126
+ }
1127
+ }
1128
+ catch (error) {
1129
+ output.log(c(`Error: ${error.message}`, 'red'));
1130
+ }
1131
+ break;
1132
+ // =========================================================================
1133
+ // THEME
1134
+ // =========================================================================
1135
+ case '/theme':
1136
+ try {
1137
+ const { getThemeNames, getTheme } = await import('../tui/theme/index.js');
1138
+ const themes = getThemeNames();
1139
+ if (args.length === 0) {
1140
+ output.log(`
1141
+ ${c('Available Themes:', 'bold')}
1142
+ ${themes.map(t => ` ${c(t, 'cyan')}`).join('\n')}
1143
+
1144
+ ${c('Usage:', 'dim')} /theme <name>
1145
+ ${c('Note:', 'dim')} Theme switching is visual in TUI mode. REPL mode uses fixed ANSI colors.
1146
+ `);
1147
+ }
1148
+ else {
1149
+ const themeName = args[0];
1150
+ if (themes.includes(themeName)) {
1151
+ const selectedTheme = getTheme(themeName);
1152
+ output.log(c(`+ Theme set to: ${themeName}`, 'green'));
1153
+ output.log(c(` Primary: ${selectedTheme.colors.primary}`, 'dim'));
1154
+ output.log(c(` Note: Full theme support requires TUI mode`, 'dim'));
1155
+ }
1156
+ else {
1157
+ output.log(c(`Unknown theme: ${themeName}`, 'red'));
1158
+ output.log(c(`Available: ${themes.join(', ')}`, 'dim'));
1159
+ }
1160
+ }
1161
+ }
1162
+ catch (error) {
1163
+ output.log(c(`Error loading themes: ${error.message}`, 'red'));
1164
+ }
1165
+ break;
1166
+ // =========================================================================
1167
+ // DEBUGGING & TESTING
1168
+ // =========================================================================
1169
+ case '/skills':
1170
+ try {
1171
+ const skills = agent.getSkills();
1172
+ if (skills.length === 0) {
1173
+ output.log(c('No skills loaded.', 'dim'));
1174
+ output.log(c('Add .md files to .skills/ directory to create skills.', 'dim'));
1175
+ }
1176
+ else {
1177
+ output.log(c('\nLoaded Skills:', 'bold'));
1178
+ skills.forEach((skill) => {
1179
+ const active = skill.active ? c('+', 'green') : c('o', 'dim');
1180
+ output.log(` ${active} ${c(skill.name, 'cyan')} - ${skill.description || 'No description'}`);
1181
+ if (skill.triggers?.length > 0) {
1182
+ output.log(c(` Triggers: ${skill.triggers.join(', ')}`, 'dim'));
1183
+ }
1184
+ });
1185
+ }
1186
+ }
1187
+ catch (error) {
1188
+ output.log(c(`Skills not available: ${error.message}`, 'yellow'));
1189
+ }
1190
+ break;
1191
+ case '/sandbox':
1192
+ try {
1193
+ const { createSandboxManager } = await import('../integrations/sandbox/index.js');
1194
+ const sandboxManager = createSandboxManager({ mode: 'auto', verbose: true });
1195
+ const available = await sandboxManager.getAvailableSandboxes();
1196
+ output.log(c('\nSandbox Modes:', 'bold'));
1197
+ for (const { mode, available: isAvailable } of available) {
1198
+ const icon = isAvailable ? c('+', 'green') : c('x', 'red');
1199
+ const desc = {
1200
+ auto: 'Auto-detect best available sandbox',
1201
+ seatbelt: 'macOS sandbox-exec with Seatbelt profiles',
1202
+ landlock: 'Linux Landlock LSM / bubblewrap / firejail',
1203
+ docker: 'Docker container isolation',
1204
+ basic: 'Allowlist-based command validation',
1205
+ none: 'No sandboxing (passthrough)',
1206
+ };
1207
+ output.log(` ${icon} ${c(mode.padEnd(10), 'cyan')} ${desc[mode] || ''}`);
1208
+ }
1209
+ const sandbox = await sandboxManager.getSandbox();
1210
+ output.log(c(`\nActive sandbox: ${sandbox.getType()}`, 'green'));
1211
+ if (args[0] === 'test') {
1212
+ output.log(c('\nTesting sandbox with "echo hello"...', 'dim'));
1213
+ const result = await sandboxManager.execute('echo hello');
1214
+ output.log(` Exit code: ${result.exitCode}`);
1215
+ output.log(` Output: ${result.stdout.trim()}`);
1216
+ output.log(` Sandboxed: ${sandbox.getType() !== 'none' ? 'Yes' : 'No'}`);
1217
+ }
1218
+ else {
1219
+ output.log(c('\nUse /sandbox test to run a test command.', 'dim'));
1220
+ }
1221
+ await sandboxManager.cleanup();
1222
+ }
1223
+ catch (error) {
1224
+ output.log(c(`Sandbox error: ${error.message}`, 'red'));
1225
+ }
1226
+ break;
1227
+ case '/shell':
1228
+ try {
1229
+ const { createPTYShell } = await import('../integrations/pty-shell.js');
1230
+ if (args[0] === 'test') {
1231
+ output.log(c('\nTesting persistent PTY shell...', 'cyan'));
1232
+ const shell = createPTYShell({ timeout: 5000 });
1233
+ await shell.start();
1234
+ output.log(c(' 1. Setting variable: export TEST_VAR="hello"', 'dim'));
1235
+ await shell.execute('export TEST_VAR="hello"');
1236
+ output.log(c(' 2. Reading variable back...', 'dim'));
1237
+ const result = await shell.execute('echo $TEST_VAR');
1238
+ output.log(` Result: ${result.output}`);
1239
+ output.log(` Exit code: ${result.exitCode}`);
1240
+ output.log(c(' 3. Checking state persistence...', 'dim'));
1241
+ const state = shell.getState();
1242
+ output.log(` CWD: ${state.cwd}`);
1243
+ output.log(` Commands run: ${state.history.length}`);
1244
+ output.log(` Shell running: ${state.isRunning}`);
1245
+ await shell.cleanup();
1246
+ output.log(c('\n+ PTY shell test passed!', 'green'));
1247
+ }
1248
+ else {
1249
+ output.log(`
1250
+ ${c('PTY Shell:', 'bold')}
1251
+ The persistent shell maintains state between commands:
1252
+ - Working directory persists across cd commands
1253
+ - Environment variables are retained
1254
+ - Command history is tracked
1255
+
1256
+ ${c('Use /shell test to run a quick test.', 'dim')}
1257
+ `);
1258
+ }
1259
+ }
1260
+ catch (error) {
1261
+ output.log(c(`Shell error: ${error.message}`, 'red'));
1262
+ }
1263
+ break;
1264
+ case '/lsp':
1265
+ output.log(`
1266
+ ${c('LSP Integration:', 'bold')}
1267
+ The LSP-enhanced file tools provide real-time diagnostics:
1268
+
1269
+ ${c('LSP-Enhanced Tools:', 'bold')}
1270
+ - ${c('lsp_edit_file', 'cyan')} - Edit with diagnostics feedback
1271
+ - ${c('lsp_write_file', 'cyan')} - Write with diagnostics feedback
1272
+
1273
+ ${c('How it works:', 'dim')}
1274
+ 1. After edit/write, LSP server analyzes the file
1275
+ 2. Returns errors, warnings, and hints inline
1276
+ 3. Agent can self-correct based on feedback
1277
+ `);
1278
+ break;
1279
+ case '/tui':
1280
+ output.log(`
1281
+ ${c('TUI (Terminal UI):', 'bold')}
1282
+ Status: ${c('Active', 'green')}
1283
+
1284
+ ${c('Features:', 'bold')}
1285
+ - Syntax highlighting for code blocks
1286
+ - Colored tool call display
1287
+ - Progress spinners
1288
+ - Error/success styling
1289
+
1290
+ ${c('Code Highlighting Languages:', 'dim')}
1291
+ Python, JavaScript, TypeScript
1292
+
1293
+ ${c('Test it:', 'dim')}
1294
+ Ask the agent to write code, e.g.:
1295
+ "Write a Python function to calculate factorial"
1296
+ `);
1297
+ break;
1298
+ // =========================================================================
1299
+ // UNKNOWN COMMAND
1300
+ // =========================================================================
1301
+ default:
1302
+ output.log(c(`Unknown command: ${cmd}. Type /help`, 'yellow'));
1303
+ }
1304
+ output.log('');
1305
+ }
1306
+ // =============================================================================
1307
+ // CONSOLE OUTPUT ADAPTER
1308
+ // =============================================================================
1309
+ /**
1310
+ * Create a CommandOutput that writes to console.
1311
+ * Used by REPL mode.
1312
+ */
1313
+ export function createConsoleOutput() {
1314
+ return {
1315
+ log: (message) => console.log(message),
1316
+ error: (message) => console.error(message),
1317
+ clear: () => console.clear(),
1318
+ };
1319
+ }
1320
+ //# sourceMappingURL=handler.js.map