@calliopelabs/cli 0.8.20 → 2.0.2

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 (402) hide show
  1. package/dist/agents/agent-config-loader.d.ts +60 -0
  2. package/dist/agents/agent-config-loader.d.ts.map +1 -0
  3. package/dist/agents/agent-config-loader.js +402 -0
  4. package/dist/agents/agent-config-loader.js.map +1 -0
  5. package/dist/agents/agent-config-presets.d.ts +10 -0
  6. package/dist/agents/agent-config-presets.d.ts.map +1 -0
  7. package/dist/agents/agent-config-presets.js +940 -0
  8. package/dist/agents/agent-config-presets.js.map +1 -0
  9. package/dist/agents/agent-config-types.d.ts +145 -0
  10. package/dist/agents/agent-config-types.d.ts.map +1 -0
  11. package/dist/agents/agent-config-types.js +12 -0
  12. package/dist/agents/agent-config-types.js.map +1 -0
  13. package/dist/{agterm → agents}/agent-detection.d.ts +1 -1
  14. package/dist/{agterm → agents}/agent-detection.d.ts.map +1 -1
  15. package/dist/{agterm → agents}/agent-detection.js +21 -5
  16. package/dist/agents/agent-detection.js.map +1 -0
  17. package/dist/agents/aggregator.d.ts +19 -0
  18. package/dist/agents/aggregator.d.ts.map +1 -0
  19. package/dist/agents/aggregator.js +141 -0
  20. package/dist/agents/aggregator.js.map +1 -0
  21. package/dist/{agterm → agents}/cli-backend.d.ts +1 -1
  22. package/dist/{agterm → agents}/cli-backend.d.ts.map +1 -1
  23. package/dist/{agterm → agents}/cli-backend.js +90 -12
  24. package/dist/agents/cli-backend.js.map +1 -0
  25. package/dist/agents/council-types.d.ts +113 -0
  26. package/dist/agents/council-types.d.ts.map +1 -0
  27. package/dist/agents/council-types.js +81 -0
  28. package/dist/agents/council-types.js.map +1 -0
  29. package/dist/agents/council.d.ts +107 -0
  30. package/dist/agents/council.d.ts.map +1 -0
  31. package/dist/agents/council.js +586 -0
  32. package/dist/agents/council.js.map +1 -0
  33. package/dist/agents/decomposer.d.ts +33 -0
  34. package/dist/agents/decomposer.d.ts.map +1 -0
  35. package/dist/agents/decomposer.js +138 -0
  36. package/dist/agents/decomposer.js.map +1 -0
  37. package/dist/agents/dynamic-tools.d.ts +52 -0
  38. package/dist/agents/dynamic-tools.d.ts.map +1 -0
  39. package/dist/agents/dynamic-tools.js +395 -0
  40. package/dist/agents/dynamic-tools.js.map +1 -0
  41. package/dist/agents/index.d.ts +29 -0
  42. package/dist/agents/index.d.ts.map +1 -0
  43. package/dist/agents/index.js +29 -0
  44. package/dist/agents/index.js.map +1 -0
  45. package/dist/agents/installer.d.ts +39 -0
  46. package/dist/agents/installer.d.ts.map +1 -0
  47. package/dist/agents/installer.js +205 -0
  48. package/dist/agents/installer.js.map +1 -0
  49. package/dist/{agterm → agents}/orchestrator.d.ts +7 -2
  50. package/dist/agents/orchestrator.d.ts.map +1 -0
  51. package/dist/{agterm → agents}/orchestrator.js +22 -2
  52. package/dist/agents/orchestrator.js.map +1 -0
  53. package/dist/agents/sdk-backend.d.ts +63 -0
  54. package/dist/agents/sdk-backend.d.ts.map +1 -0
  55. package/dist/agents/sdk-backend.js +489 -0
  56. package/dist/agents/sdk-backend.js.map +1 -0
  57. package/dist/agents/swarm-types.d.ts +83 -0
  58. package/dist/agents/swarm-types.d.ts.map +1 -0
  59. package/dist/agents/swarm-types.js +20 -0
  60. package/dist/agents/swarm-types.js.map +1 -0
  61. package/dist/agents/swarm.d.ts +74 -0
  62. package/dist/agents/swarm.d.ts.map +1 -0
  63. package/dist/agents/swarm.js +307 -0
  64. package/dist/agents/swarm.js.map +1 -0
  65. package/dist/{agterm → agents}/tools.d.ts +7 -5
  66. package/dist/agents/tools.d.ts.map +1 -0
  67. package/dist/agents/tools.js +776 -0
  68. package/dist/agents/tools.js.map +1 -0
  69. package/dist/{agterm → agents}/types.d.ts +14 -2
  70. package/dist/agents/types.d.ts.map +1 -0
  71. package/dist/{agterm → agents}/types.js +2 -2
  72. package/dist/agents/types.js.map +1 -0
  73. package/dist/api-server.d.ts +26 -0
  74. package/dist/api-server.d.ts.map +1 -0
  75. package/dist/api-server.js +230 -0
  76. package/dist/api-server.js.map +1 -0
  77. package/dist/auto-checkpoint.d.ts +35 -0
  78. package/dist/auto-checkpoint.d.ts.map +1 -0
  79. package/dist/auto-checkpoint.js +143 -0
  80. package/dist/auto-checkpoint.js.map +1 -0
  81. package/dist/auto-compressor.d.ts +44 -0
  82. package/dist/auto-compressor.d.ts.map +1 -0
  83. package/dist/auto-compressor.js +145 -0
  84. package/dist/auto-compressor.js.map +1 -0
  85. package/dist/background-jobs.d.ts +45 -0
  86. package/dist/background-jobs.d.ts.map +1 -0
  87. package/dist/background-jobs.js +122 -0
  88. package/dist/background-jobs.js.map +1 -0
  89. package/dist/bin.d.ts +6 -2
  90. package/dist/bin.d.ts.map +1 -1
  91. package/dist/bin.js +127 -24
  92. package/dist/bin.js.map +1 -1
  93. package/dist/checkpoint.d.ts +49 -0
  94. package/dist/checkpoint.d.ts.map +1 -0
  95. package/dist/checkpoint.js +219 -0
  96. package/dist/checkpoint.js.map +1 -0
  97. package/dist/circuit-breaker/breaker.d.ts +80 -0
  98. package/dist/circuit-breaker/breaker.d.ts.map +1 -0
  99. package/dist/circuit-breaker/breaker.js +408 -0
  100. package/dist/circuit-breaker/breaker.js.map +1 -0
  101. package/dist/circuit-breaker/defaults.d.ts +8 -0
  102. package/dist/circuit-breaker/defaults.d.ts.map +1 -0
  103. package/dist/circuit-breaker/defaults.js +35 -0
  104. package/dist/circuit-breaker/defaults.js.map +1 -0
  105. package/dist/circuit-breaker/index.d.ts +9 -0
  106. package/dist/circuit-breaker/index.d.ts.map +1 -0
  107. package/dist/circuit-breaker/index.js +8 -0
  108. package/dist/circuit-breaker/index.js.map +1 -0
  109. package/dist/circuit-breaker/types.d.ts +77 -0
  110. package/dist/circuit-breaker/types.d.ts.map +1 -0
  111. package/dist/circuit-breaker/types.js +8 -0
  112. package/dist/circuit-breaker/types.js.map +1 -0
  113. package/dist/circuit-breaker.d.ts +8 -0
  114. package/dist/circuit-breaker.d.ts.map +1 -0
  115. package/dist/circuit-breaker.js +7 -0
  116. package/dist/circuit-breaker.js.map +1 -0
  117. package/dist/cli/agent.d.ts +9 -0
  118. package/dist/cli/agent.d.ts.map +1 -0
  119. package/dist/cli/agent.js +262 -0
  120. package/dist/cli/agent.js.map +1 -0
  121. package/dist/cli/commands.d.ts +12 -0
  122. package/dist/cli/commands.d.ts.map +1 -0
  123. package/dist/{cli.js → cli/commands.js} +285 -422
  124. package/dist/cli/commands.js.map +1 -0
  125. package/dist/cli/index.d.ts +8 -0
  126. package/dist/cli/index.d.ts.map +1 -0
  127. package/dist/cli/index.js +222 -0
  128. package/dist/cli/index.js.map +1 -0
  129. package/dist/cli/types.d.ts +30 -0
  130. package/dist/cli/types.d.ts.map +1 -0
  131. package/dist/cli/types.js +20 -0
  132. package/dist/cli/types.js.map +1 -0
  133. package/dist/companions.d.ts +54 -0
  134. package/dist/companions.d.ts.map +1 -0
  135. package/dist/companions.js +440 -0
  136. package/dist/companions.js.map +1 -0
  137. package/dist/config.d.ts +23 -1
  138. package/dist/config.d.ts.map +1 -1
  139. package/dist/config.js +95 -22
  140. package/dist/config.js.map +1 -1
  141. package/dist/diff.d.ts +27 -0
  142. package/dist/diff.d.ts.map +1 -1
  143. package/dist/diff.js +415 -10
  144. package/dist/diff.js.map +1 -1
  145. package/dist/errors.d.ts.map +1 -1
  146. package/dist/errors.js +20 -11
  147. package/dist/errors.js.map +1 -1
  148. package/dist/git-status.d.ts +23 -0
  149. package/dist/git-status.d.ts.map +1 -0
  150. package/dist/git-status.js +92 -0
  151. package/dist/git-status.js.map +1 -0
  152. package/dist/headless.d.ts +25 -0
  153. package/dist/headless.d.ts.map +1 -0
  154. package/dist/headless.js +182 -0
  155. package/dist/headless.js.map +1 -0
  156. package/dist/hud/api.d.ts +35 -0
  157. package/dist/hud/api.d.ts.map +1 -0
  158. package/dist/hud/api.js +448 -0
  159. package/dist/hud/api.js.map +1 -0
  160. package/dist/hud/palettes.d.ts +9 -0
  161. package/dist/hud/palettes.d.ts.map +1 -0
  162. package/dist/hud/palettes.js +280 -0
  163. package/dist/hud/palettes.js.map +1 -0
  164. package/dist/hud/skins.d.ts +12 -0
  165. package/dist/hud/skins.d.ts.map +1 -0
  166. package/dist/hud/skins.js +365 -0
  167. package/dist/hud/skins.js.map +1 -0
  168. package/dist/hud/theme-packs/api.d.ts +51 -0
  169. package/dist/hud/theme-packs/api.d.ts.map +1 -0
  170. package/dist/hud/theme-packs/api.js +145 -0
  171. package/dist/hud/theme-packs/api.js.map +1 -0
  172. package/dist/hud/theme-packs/index.d.ts +18 -0
  173. package/dist/hud/theme-packs/index.d.ts.map +1 -0
  174. package/dist/hud/theme-packs/index.js +38 -0
  175. package/dist/hud/theme-packs/index.js.map +1 -0
  176. package/dist/hud/theme-packs/types.d.ts +29 -0
  177. package/dist/hud/theme-packs/types.d.ts.map +1 -0
  178. package/dist/hud/theme-packs/types.js +9 -0
  179. package/dist/hud/theme-packs/types.js.map +1 -0
  180. package/dist/hud/types.d.ts +182 -0
  181. package/dist/hud/types.d.ts.map +1 -0
  182. package/dist/hud/types.js +7 -0
  183. package/dist/hud/types.js.map +1 -0
  184. package/dist/idle-eviction.d.ts +34 -0
  185. package/dist/idle-eviction.d.ts.map +1 -0
  186. package/dist/idle-eviction.js +78 -0
  187. package/dist/idle-eviction.js.map +1 -0
  188. package/dist/index.d.ts +9 -3
  189. package/dist/index.d.ts.map +1 -1
  190. package/dist/index.js +9 -3
  191. package/dist/index.js.map +1 -1
  192. package/dist/iteration-ledger.d.ts +105 -0
  193. package/dist/iteration-ledger.d.ts.map +1 -0
  194. package/dist/iteration-ledger.js +237 -0
  195. package/dist/iteration-ledger.js.map +1 -0
  196. package/dist/markdown.d.ts.map +1 -1
  197. package/dist/markdown.js +1 -27
  198. package/dist/markdown.js.map +1 -1
  199. package/dist/mcp.d.ts +35 -0
  200. package/dist/mcp.d.ts.map +1 -1
  201. package/dist/mcp.js +291 -7
  202. package/dist/mcp.js.map +1 -1
  203. package/dist/memory.d.ts.map +1 -1
  204. package/dist/memory.js +12 -2
  205. package/dist/memory.js.map +1 -1
  206. package/dist/model-detection.d.ts +5 -0
  207. package/dist/model-detection.d.ts.map +1 -1
  208. package/dist/model-detection.js +278 -10
  209. package/dist/model-detection.js.map +1 -1
  210. package/dist/model-router.d.ts.map +1 -1
  211. package/dist/model-router.js +33 -11
  212. package/dist/model-router.js.map +1 -1
  213. package/dist/plugins.d.ts +8 -0
  214. package/dist/plugins.d.ts.map +1 -1
  215. package/dist/plugins.js +97 -6
  216. package/dist/plugins.js.map +1 -1
  217. package/dist/providers/anthropic.d.ts +10 -0
  218. package/dist/providers/anthropic.d.ts.map +1 -0
  219. package/dist/providers/anthropic.js +221 -0
  220. package/dist/providers/anthropic.js.map +1 -0
  221. package/dist/providers/bedrock.d.ts +17 -0
  222. package/dist/providers/bedrock.d.ts.map +1 -0
  223. package/dist/providers/bedrock.js +574 -0
  224. package/dist/providers/bedrock.js.map +1 -0
  225. package/dist/providers/compat.d.ts +13 -0
  226. package/dist/providers/compat.d.ts.map +1 -0
  227. package/dist/providers/compat.js +202 -0
  228. package/dist/providers/compat.js.map +1 -0
  229. package/dist/providers/google.d.ts +10 -0
  230. package/dist/providers/google.d.ts.map +1 -0
  231. package/dist/providers/google.js +203 -0
  232. package/dist/providers/google.js.map +1 -0
  233. package/dist/providers/index.d.ts +23 -0
  234. package/dist/providers/index.d.ts.map +1 -0
  235. package/dist/providers/index.js +145 -0
  236. package/dist/providers/index.js.map +1 -0
  237. package/dist/providers/ollama.d.ts +17 -0
  238. package/dist/providers/ollama.d.ts.map +1 -0
  239. package/dist/providers/ollama.js +289 -0
  240. package/dist/providers/ollama.js.map +1 -0
  241. package/dist/providers/openai.d.ts +121 -0
  242. package/dist/providers/openai.d.ts.map +1 -0
  243. package/dist/providers/openai.js +485 -0
  244. package/dist/providers/openai.js.map +1 -0
  245. package/dist/providers/types.d.ts +63 -0
  246. package/dist/providers/types.d.ts.map +1 -0
  247. package/dist/providers/types.js +164 -0
  248. package/dist/providers/types.js.map +1 -0
  249. package/dist/sandbox-native.d.ts +59 -0
  250. package/dist/sandbox-native.d.ts.map +1 -0
  251. package/dist/sandbox-native.js +292 -0
  252. package/dist/sandbox-native.js.map +1 -0
  253. package/dist/sandbox.d.ts +2 -2
  254. package/dist/sandbox.d.ts.map +1 -1
  255. package/dist/sandbox.js +59 -13
  256. package/dist/sandbox.js.map +1 -1
  257. package/dist/scope.d.ts +3 -1
  258. package/dist/scope.d.ts.map +1 -1
  259. package/dist/scope.js +13 -1
  260. package/dist/scope.js.map +1 -1
  261. package/dist/session-timeout.d.ts +31 -0
  262. package/dist/session-timeout.d.ts.map +1 -0
  263. package/dist/session-timeout.js +100 -0
  264. package/dist/session-timeout.js.map +1 -0
  265. package/dist/setup.d.ts.map +1 -1
  266. package/dist/setup.js +29 -17
  267. package/dist/setup.js.map +1 -1
  268. package/dist/smart-router.d.ts +73 -0
  269. package/dist/smart-router.d.ts.map +1 -0
  270. package/dist/smart-router.js +332 -0
  271. package/dist/smart-router.js.map +1 -0
  272. package/dist/storage.d.ts +19 -0
  273. package/dist/storage.d.ts.map +1 -1
  274. package/dist/storage.js +164 -1
  275. package/dist/storage.js.map +1 -1
  276. package/dist/streaming.d.ts +4 -0
  277. package/dist/streaming.d.ts.map +1 -1
  278. package/dist/streaming.js +12 -0
  279. package/dist/streaming.js.map +1 -1
  280. package/dist/styles.d.ts +32 -0
  281. package/dist/styles.d.ts.map +1 -1
  282. package/dist/styles.js +91 -0
  283. package/dist/styles.js.map +1 -1
  284. package/dist/summarization.d.ts +1 -1
  285. package/dist/summarization.js +4 -4
  286. package/dist/summarization.js.map +1 -1
  287. package/dist/terminal-image.d.ts +115 -0
  288. package/dist/terminal-image.d.ts.map +1 -0
  289. package/dist/terminal-image.js +766 -0
  290. package/dist/terminal-image.js.map +1 -0
  291. package/dist/terminal-recording.d.ts +55 -0
  292. package/dist/terminal-recording.d.ts.map +1 -0
  293. package/dist/terminal-recording.js +182 -0
  294. package/dist/terminal-recording.js.map +1 -0
  295. package/dist/themes.d.ts +19 -35
  296. package/dist/themes.d.ts.map +1 -1
  297. package/dist/themes.js +101 -210
  298. package/dist/themes.js.map +1 -1
  299. package/dist/tmux.d.ts +35 -0
  300. package/dist/tmux.d.ts.map +1 -0
  301. package/dist/tmux.js +106 -0
  302. package/dist/tmux.js.map +1 -0
  303. package/dist/tools.d.ts +3 -3
  304. package/dist/tools.d.ts.map +1 -1
  305. package/dist/tools.js +587 -45
  306. package/dist/tools.js.map +1 -1
  307. package/dist/trust.d.ts +53 -0
  308. package/dist/trust.d.ts.map +1 -0
  309. package/dist/trust.js +154 -0
  310. package/dist/trust.js.map +1 -0
  311. package/dist/types.d.ts +7 -3
  312. package/dist/types.d.ts.map +1 -1
  313. package/dist/types.js +70 -32
  314. package/dist/types.js.map +1 -1
  315. package/dist/ui/agent.d.ts +61 -0
  316. package/dist/ui/agent.d.ts.map +1 -0
  317. package/dist/ui/agent.js +768 -0
  318. package/dist/ui/agent.js.map +1 -0
  319. package/dist/ui/chat-input.d.ts +32 -0
  320. package/dist/ui/chat-input.d.ts.map +1 -0
  321. package/dist/ui/chat-input.js +355 -0
  322. package/dist/ui/chat-input.js.map +1 -0
  323. package/dist/ui/commands.d.ts +92 -0
  324. package/dist/ui/commands.d.ts.map +1 -0
  325. package/dist/ui/commands.js +3006 -0
  326. package/dist/ui/commands.js.map +1 -0
  327. package/dist/ui/completions.d.ts +22 -0
  328. package/dist/ui/completions.d.ts.map +1 -0
  329. package/dist/ui/completions.js +215 -0
  330. package/dist/ui/completions.js.map +1 -0
  331. package/dist/ui/components.d.ts +38 -0
  332. package/dist/ui/components.d.ts.map +1 -0
  333. package/dist/ui/components.js +422 -0
  334. package/dist/ui/components.js.map +1 -0
  335. package/dist/ui/context.d.ts +12 -0
  336. package/dist/ui/context.d.ts.map +1 -0
  337. package/dist/ui/context.js +102 -0
  338. package/dist/ui/context.js.map +1 -0
  339. package/dist/ui/error-boundary.d.ts +33 -0
  340. package/dist/ui/error-boundary.d.ts.map +1 -0
  341. package/dist/ui/error-boundary.js +94 -0
  342. package/dist/ui/error-boundary.js.map +1 -0
  343. package/dist/ui/frame.d.ts +13 -0
  344. package/dist/ui/frame.d.ts.map +1 -0
  345. package/dist/ui/frame.js +89 -0
  346. package/dist/ui/frame.js.map +1 -0
  347. package/dist/ui/index.d.ts +12 -0
  348. package/dist/ui/index.d.ts.map +1 -0
  349. package/dist/ui/index.js +928 -0
  350. package/dist/ui/index.js.map +1 -0
  351. package/dist/ui/messages.d.ts +19 -0
  352. package/dist/ui/messages.d.ts.map +1 -0
  353. package/dist/ui/messages.js +181 -0
  354. package/dist/ui/messages.js.map +1 -0
  355. package/dist/ui/modals.d.ts +52 -0
  356. package/dist/ui/modals.d.ts.map +1 -0
  357. package/dist/ui/modals.js +204 -0
  358. package/dist/ui/modals.js.map +1 -0
  359. package/dist/ui/pack-picker.d.ts +12 -0
  360. package/dist/ui/pack-picker.d.ts.map +1 -0
  361. package/dist/ui/pack-picker.js +101 -0
  362. package/dist/ui/pack-picker.js.map +1 -0
  363. package/dist/ui/status-bar.d.ts +20 -0
  364. package/dist/ui/status-bar.d.ts.map +1 -0
  365. package/dist/ui/status-bar.js +41 -0
  366. package/dist/ui/status-bar.js.map +1 -0
  367. package/dist/ui/theme-picker.d.ts +24 -0
  368. package/dist/ui/theme-picker.d.ts.map +1 -0
  369. package/dist/ui/theme-picker.js +190 -0
  370. package/dist/ui/theme-picker.js.map +1 -0
  371. package/dist/ui/types.d.ts +62 -0
  372. package/dist/ui/types.d.ts.map +1 -0
  373. package/dist/ui/types.js +7 -0
  374. package/dist/ui/types.js.map +1 -0
  375. package/dist/version-check.d.ts.map +1 -1
  376. package/dist/version-check.js +1 -9
  377. package/dist/version-check.js.map +1 -1
  378. package/package.json +8 -3
  379. package/dist/agterm/agent-detection.js.map +0 -1
  380. package/dist/agterm/cli-backend.js.map +0 -1
  381. package/dist/agterm/index.d.ts +0 -12
  382. package/dist/agterm/index.d.ts.map +0 -1
  383. package/dist/agterm/index.js +0 -15
  384. package/dist/agterm/index.js.map +0 -1
  385. package/dist/agterm/orchestrator.d.ts.map +0 -1
  386. package/dist/agterm/orchestrator.js.map +0 -1
  387. package/dist/agterm/tools.d.ts.map +0 -1
  388. package/dist/agterm/tools.js +0 -278
  389. package/dist/agterm/tools.js.map +0 -1
  390. package/dist/agterm/types.d.ts.map +0 -1
  391. package/dist/agterm/types.js.map +0 -1
  392. package/dist/cli.d.ts +0 -14
  393. package/dist/cli.d.ts.map +0 -1
  394. package/dist/cli.js.map +0 -1
  395. package/dist/providers.d.ts +0 -51
  396. package/dist/providers.d.ts.map +0 -1
  397. package/dist/providers.js +0 -1146
  398. package/dist/providers.js.map +0 -1
  399. package/dist/ui-cli.d.ts +0 -17
  400. package/dist/ui-cli.d.ts.map +0 -1
  401. package/dist/ui-cli.js +0 -3730
  402. package/dist/ui-cli.js.map +0 -1
@@ -1,210 +1,35 @@
1
1
  /**
2
- * Calliope CLI - Interactive REPL
2
+ * CLI Command Handlers
3
3
  *
4
- * Main interactive command-line interface.
4
+ * Slash command processing, help text, and upgrade flow.
5
5
  */
6
- import * as readline from 'readline';
7
6
  import * as path from 'path';
8
- import * as config from './config.js';
9
- import { chat, getAvailableProviders, selectProvider } from './providers.js';
10
- import { TOOLS, executeTool } from './tools.js';
11
- import { getSystemPrompt, DEFAULT_MODELS } from './types.js';
12
- import { checkForUpdates, getVersion, getLatestVersion, performUpgrade } from './version-check.js';
13
- import { selectModelInteractively } from './model-detection.js';
14
- import * as memory from './memory.js';
15
- import * as hooks from './hooks.js';
16
- import * as modelRouter from './model-router.js';
17
- import * as summarization from './summarization.js';
18
- import * as themes from './themes.js';
19
- import * as branching from './branching.js';
20
- import * as fuzzySearch from './fuzzy-search.js';
21
- import { MODE_CONFIG } from './types.js';
22
- import * as storage from './storage.js';
23
- import { addToScope, removeFromScope, getScopeSummary, getScopeDetails, resetScope } from './scope.js';
24
- // Debug logging helper
25
- const DEBUG = process.env.CALLIOPE_DEBUG === '1';
26
- function debugLog(message, ...args) {
27
- if (DEBUG)
28
- console.log(`[DEBUG:cli] ${message}`, ...args);
7
+ import * as config from '../config.js';
8
+ import { getAvailableProviders, selectProvider } from '../providers/index.js';
9
+ import { getSystemPrompt, DEFAULT_MODELS, MODE_CONFIG } from '../types.js';
10
+ import { getVersion, getLatestVersion, performUpgrade } from '../version-check.js';
11
+ import { selectModelInteractively } from '../model-detection.js';
12
+ import * as memory from '../memory.js';
13
+ import * as hooks from '../hooks.js';
14
+ import * as modelRouter from '../model-router.js';
15
+ import * as summarization from '../summarization.js';
16
+ import * as themes from '../themes.js';
17
+ import * as branching from '../branching.js';
18
+ import * as fuzzySearch from '../fuzzy-search.js';
19
+ import * as storage from '../storage.js';
20
+ import { addToScope, removeFromScope, getScopeSummary, getScopeDetails, resetScope } from '../scope.js';
21
+ import { color } from '../styles.js';
22
+ import { getCurrentSkin, getCurrentPalette, applySkin, applyPalette, listSkins, listPalettes } from '../hud/api.js';
23
+ import { getCurrentCompanion, applyCompanion, listCompanions, getMoodText } from '../companions.js';
24
+ import { applyThemePack, listThemePacks, getCurrentPack, getCompanionMode, setCompanionMode } from '../hud/theme-packs/api.js';
25
+ import { isDockerAvailable } from '../sandbox.js';
26
+ import { getSandboxStatus } from '../sandbox-native.js';
27
+ // Forward declaration — injected by index.ts to avoid circular imports
28
+ let _startLoop;
29
+ export function setStartLoop(fn) {
30
+ _startLoop = fn;
29
31
  }
30
- // ANSI colors
31
- const c = {
32
- reset: '\x1b[0m',
33
- bold: '\x1b[1m',
34
- dim: '\x1b[2m',
35
- cyan: '\x1b[36m',
36
- green: '\x1b[32m',
37
- yellow: '\x1b[33m',
38
- red: '\x1b[31m',
39
- blue: '\x1b[34m',
40
- magenta: '\x1b[35m',
41
- brightCyan: '\x1b[96m',
42
- };
43
- function color(text, style) {
44
- return `${c[style]}${text}${c.reset}`;
45
- }
46
- // Spinner frames
47
- const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
48
- const BANNER = `
49
- ${color(' ██████╗ █████╗ ██╗ ██╗ ██╗ ██████╗ ██████╗ ███████╗', 'brightCyan')}
50
- ${color('██╔════╝██╔══██╗██║ ██║ ██║██╔═══██╗██╔══██╗██╔════╝', 'brightCyan')}
51
- ${color('██║ ███████║██║ ██║ ██║██║ ██║██████╔╝█████╗ ', 'cyan')}
52
- ${color('██║ ██╔══██║██║ ██║ ██║██║ ██║██╔═══╝ ██╔══╝ ', 'cyan')}
53
- ${color('╚██████╗██║ ██║███████╗███████╗██║╚██████╔╝██║ ███████╗', 'brightCyan')}
54
- ${color(' ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚══════╝', 'cyan')}
55
-
56
- ${color('The Muse of Digital Eloquence', 'dim')}
57
- `;
58
- // Slash commands
59
- const COMMANDS = [
60
- '/help', '/h', '/provider', '/p', '/model', '/m', '/models', '/persona',
61
- '/clear', '/c', '/status', '/s', '/loop', '/cancel-loop',
62
- '/setup', '/config', '/upgrade', '/exit', '/quit', '/q',
63
- '/memory', '/hooks', '/route', '/summarize', '/theme', '/branch', '/find', '/search',
64
- '/mode', '/work', '/plan', '/debug', '/set', '/confirm',
65
- '/scope', '/add-dir', '/remove-dir', '/cost', '/costs', '/session', '/context',
66
- ];
67
- /**
68
- * Start the CLI
69
- */
70
- export async function startCLI(options = {}) {
71
- const state = {
72
- provider: config.get('defaultProvider'),
73
- model: config.get('defaultModel'),
74
- persona: config.get('persona'),
75
- messages: [],
76
- cwd: process.cwd(),
77
- running: true,
78
- skipPermissions: options.skipPermissions ?? false,
79
- loopActive: false,
80
- loopPrompt: '',
81
- loopIteration: 0,
82
- loopMaxIterations: 50,
83
- autoRoute: false,
84
- currentBranch: 'main',
85
- mode: 'hybrid',
86
- confirmMode: true,
87
- debugEnabled: process.env.CALLIOPE_DEBUG === '1',
88
- sessionCost: 0,
89
- };
90
- // Add system message with memory context
91
- const systemPrompt = getSystemPrompt(state.persona);
92
- const memoryContext = memory.buildMemoryContext(process.cwd());
93
- const fullPrompt = memoryContext.trim()
94
- ? systemPrompt + '\n\n--- Project Context ---\n' + memoryContext
95
- : systemPrompt;
96
- state.messages.push({
97
- role: 'system',
98
- content: fullPrompt,
99
- });
100
- // Execute session start hooks
101
- hooks.executeHooks('session-start', {}).catch((err) => {
102
- debugLog('session-start hook failed:', err instanceof Error ? err.message : err);
103
- });
104
- // Setup readline
105
- const rl = readline.createInterface({
106
- input: process.stdin,
107
- output: process.stdout,
108
- terminal: true,
109
- completer: (line) => {
110
- if (line.startsWith('/')) {
111
- const hits = COMMANDS.filter(cmd => cmd.startsWith(line));
112
- return [hits.length ? hits : COMMANDS, line];
113
- }
114
- return [[], line];
115
- },
116
- });
117
- // Check for updates (do this early, it's cached)
118
- let hasUpdate = false;
119
- // Print welcome
120
- if (config.get('fancyOutput')) {
121
- console.log(BANNER);
122
- const actualProvider = selectProvider(state.provider);
123
- const model = state.model || DEFAULT_MODELS[actualProvider];
124
- console.log(` ${color('v' + getVersion(), 'dim')}`);
125
- console.log();
126
- console.log(` ${color('Provider:', 'dim')} ${color(actualProvider, 'cyan')} (${color(model, 'dim')})`);
127
- console.log(` ${color('Persona:', 'dim')} ${color(state.persona, 'cyan')}`);
128
- console.log(` ${color('Directory:', 'dim')} ${color(state.cwd, 'dim')}`);
129
- // Check for updates
130
- hasUpdate = await checkForUpdates().catch(() => false);
131
- console.log(color(' ─────────────────────────────────────────────────────────────────', 'dim'));
132
- console.log(` ${color('TAB', 'cyan')} ${color('autocomplete', 'dim')} ${color('│', 'dim')} ${color('/help', 'cyan')} ${color('│', 'dim')} ${color('/loop', 'cyan')} ${color('│', 'dim')} ${color('/provider', 'cyan')} ${color('│', 'dim')} ${color('ESC', 'cyan')} ${color('stop', 'dim')}`);
133
- console.log(color(' ─────────────────────────────────────────────────────────────────', 'dim'));
134
- }
135
- else {
136
- console.log('Calliope CLI');
137
- console.log(`Provider: ${selectProvider(state.provider)}`);
138
- console.log('/help for commands');
139
- hasUpdate = await checkForUpdates(true).catch(() => false); // silent in non-fancy mode
140
- }
141
- console.log();
142
- // Prompt function
143
- const promptUser = () => {
144
- const promptStr = `${color('calliope', 'cyan')}${color('>', 'dim')} `;
145
- rl.question(promptStr, async (input) => {
146
- input = input.trim();
147
- if (!input) {
148
- promptUser();
149
- return;
150
- }
151
- // Handle commands
152
- if (input.startsWith('/')) {
153
- await handleCommand(input, state, rl);
154
- if (state.running)
155
- promptUser();
156
- return;
157
- }
158
- // Run agent
159
- await runAgent(input, state);
160
- if (state.running)
161
- promptUser();
162
- });
163
- };
164
- // Handle Ctrl+C
165
- rl.on('close', () => {
166
- console.log();
167
- console.log(color(' Farewell...', 'cyan'));
168
- console.log();
169
- process.exit(0);
170
- });
171
- // If update available and autoUpgrade enabled, prompt user
172
- if (hasUpdate && config.get('autoUpgrade')) {
173
- rl.question(`${color('Upgrade now? (y/N/never)', 'cyan')} `, async (answer) => {
174
- const a = answer.toLowerCase().trim();
175
- if (a === 'y' || a === 'yes') {
176
- const success = await performUpgrade();
177
- if (success) {
178
- console.log();
179
- console.log(color('Upgrade complete! Restarting...', 'green'));
180
- const { spawn } = await import('child_process');
181
- const child = spawn(process.argv[0], process.argv.slice(1), {
182
- stdio: 'inherit',
183
- detached: true,
184
- });
185
- child.unref();
186
- process.exit(0);
187
- }
188
- else {
189
- console.log(color('Upgrade failed. Use /upgrade to try again.', 'red'));
190
- }
191
- }
192
- else if (a === 'never') {
193
- config.set('autoUpgrade', false);
194
- console.log(color('Auto-upgrade disabled. Use /upgrade to update manually.', 'dim'));
195
- }
196
- console.log();
197
- promptUser();
198
- });
199
- }
200
- else {
201
- promptUser();
202
- }
203
- }
204
- /**
205
- * Handle slash commands
206
- */
207
- async function handleCommand(input, state, rl) {
32
+ export async function handleCommand(input, state, rl) {
208
33
  const parts = input.split(/\s+/);
209
34
  const cmd = parts[0].toLowerCase();
210
35
  switch (cmd) {
@@ -215,7 +40,7 @@ async function handleCommand(input, state, rl) {
215
40
  case '/provider':
216
41
  case '/p':
217
42
  if (parts[1]) {
218
- const validProviders = ['anthropic', 'google', 'openai', 'together', 'openrouter', 'groq', 'fireworks', 'mistral', 'ollama', 'ai21', 'huggingface', 'litellm', 'auto'];
43
+ const validProviders = ['anthropic', 'google', 'openai', 'together', 'openrouter', 'groq', 'fireworks', 'mistral', 'ollama', 'ai21', 'huggingface', 'litellm', 'bedrock', 'auto'];
219
44
  const requested = parts[1].toLowerCase();
220
45
  if (validProviders.includes(requested)) {
221
46
  state.provider = requested;
@@ -241,7 +66,6 @@ async function handleCommand(input, state, rl) {
241
66
  console.log();
242
67
  }
243
68
  else {
244
- // Interactive model selection
245
69
  const actualProvider = selectProvider(state.provider);
246
70
  console.log(`Current model: ${color(state.model || DEFAULT_MODELS[actualProvider], 'cyan')}`);
247
71
  console.log();
@@ -267,14 +91,14 @@ async function handleCommand(input, state, rl) {
267
91
  }
268
92
  break;
269
93
  case '/persona':
270
- if (parts[1] && ['calliope', 'professional', 'minimal'].includes(parts[1])) {
94
+ if (parts[1] && ['calliope', 'muse', 'minimal'].includes(parts[1])) {
271
95
  state.persona = parts[1];
272
96
  state.messages = [{ role: 'system', content: getSystemPrompt(state.persona) }];
273
97
  console.log(color(`Persona set to: ${parts[1]}`, 'green'));
274
98
  }
275
99
  else {
276
100
  console.log(`Current: ${color(state.persona, 'magenta')}`);
277
- console.log('Options: calliope, professional, minimal');
101
+ console.log('Options: calliope, muse, minimal');
278
102
  }
279
103
  console.log();
280
104
  break;
@@ -294,7 +118,7 @@ async function handleCommand(input, state, rl) {
294
118
  console.log();
295
119
  break;
296
120
  case '/loop':
297
- await startLoop(parts.slice(1).join(' '), state);
121
+ await _startLoop(parts.slice(1).join(' '), state);
298
122
  break;
299
123
  case '/cancel-loop':
300
124
  if (state.loopActive) {
@@ -307,7 +131,7 @@ async function handleCommand(input, state, rl) {
307
131
  console.log();
308
132
  break;
309
133
  case '/setup':
310
- const { reconfigure } = await import('./setup.js');
134
+ const { reconfigure } = await import('../setup.js');
311
135
  await reconfigure();
312
136
  break;
313
137
  case '/config':
@@ -428,9 +252,193 @@ async function handleCommand(input, state, rl) {
428
252
  }
429
253
  console.log();
430
254
  break;
255
+ case '/skin':
256
+ if (parts[1] === 'list' || !parts[1]) {
257
+ const skins = listSkins();
258
+ const currentSkin = getCurrentSkin();
259
+ console.log(`Skins: ${skins.map(s => s.name === currentSkin.name ? color(s.name, 'green') : s.name).join(', ')}`);
260
+ if (!parts[1])
261
+ console.log(`Current: ${color(currentSkin.name, 'cyan')} — ${currentSkin.description}`);
262
+ }
263
+ else {
264
+ applySkin(parts[1]);
265
+ const newSkin = getCurrentSkin();
266
+ if (newSkin.name === parts[1]) {
267
+ config.set('activeSkin', parts[1]);
268
+ console.log(color(`Skin set to: ${parts[1]}`, 'green'));
269
+ }
270
+ else {
271
+ console.log(color(`Skin not found: ${parts[1]}. Using: ${newSkin.name}`, 'yellow'));
272
+ }
273
+ }
274
+ console.log();
275
+ break;
276
+ case '/palette':
277
+ if (parts[1] === 'list' || !parts[1]) {
278
+ const palettes = listPalettes();
279
+ const currentPal = getCurrentPalette();
280
+ console.log(`Palettes: ${palettes.map(p => p.name === currentPal.name ? color(p.name, 'green') : p.name).join(', ')}`);
281
+ if (!parts[1])
282
+ console.log(`Current: ${color(currentPal.name, 'cyan')} — ${currentPal.description}`);
283
+ }
284
+ else {
285
+ applyPalette(parts[1]);
286
+ const newPal = getCurrentPalette();
287
+ if (newPal.name === parts[1]) {
288
+ config.set('activePalette', parts[1]);
289
+ console.log(color(`Palette set to: ${parts[1]}`, 'green'));
290
+ }
291
+ else {
292
+ console.log(color(`Palette not found: ${parts[1]}. Using: ${newPal.name}`, 'yellow'));
293
+ }
294
+ }
295
+ console.log();
296
+ break;
297
+ case '/companion':
298
+ if (parts[1] === 'list' || !parts[1]) {
299
+ const companions = listCompanions();
300
+ const currentComp = getCurrentCompanion();
301
+ console.log(`Companions: ${companions.map(comp => comp.name === currentComp.name ? color(comp.name, 'green') : comp.name).join(', ')}`);
302
+ if (!parts[1])
303
+ console.log(`Current: ${color(currentComp.name, 'cyan')} — ${currentComp.description}`);
304
+ }
305
+ else {
306
+ applyCompanion(parts[1]);
307
+ const newComp = getCurrentCompanion();
308
+ if (newComp.name === parts[1]) {
309
+ config.set('activeCompanion', parts[1]);
310
+ state.messages = [{ role: 'system', content: getSystemPrompt(state.persona) }];
311
+ console.log(color(`Companion set to: ${parts[1]}`, 'green'));
312
+ console.log(color(` "${newComp.greeting}"`, 'dim'));
313
+ }
314
+ else {
315
+ console.log(color(`Companion not found: ${parts[1]}. Using: ${newComp.name}`, 'yellow'));
316
+ }
317
+ }
318
+ console.log();
319
+ break;
320
+ case '/hud':
321
+ {
322
+ const hudSkin = getCurrentSkin();
323
+ const hudPalette = getCurrentPalette();
324
+ const hudCompanion = getCurrentCompanion();
325
+ const hudPack = getCurrentPack();
326
+ const hudIntensity = getCompanionMode();
327
+ console.log(color('HUD Configuration', 'bold'));
328
+ if (hudPack)
329
+ console.log(` Pack: ${color(hudPack.name, 'cyan')} — ${hudPack.description}`);
330
+ console.log(` Skin: ${color(hudSkin.name, 'cyan')} — ${hudSkin.description}`);
331
+ console.log(` Palette: ${color(hudPalette.name, 'cyan')} — ${hudPalette.description}`);
332
+ console.log(` Companion: ${color(hudCompanion.name, 'cyan')} — ${hudCompanion.description}`);
333
+ console.log(` Intensity: ${hudIntensity}`);
334
+ console.log(` Emojis: ${config.get('useEmojis') !== false ? 'ON' : 'OFF'}`);
335
+ console.log(` Mood: ${getMoodText()}`);
336
+ console.log();
337
+ console.log(color(' /pack <name> /intensity <pro|immersive> /emoji [on|off]', 'dim'));
338
+ console.log(color(' /skin <name> /palette <name> /companion <name>', 'dim'));
339
+ }
340
+ console.log();
341
+ break;
342
+ case '/pack':
343
+ if (parts[1] === 'list' || !parts[1]) {
344
+ const category = parts[2];
345
+ const packs = listThemePacks(category || undefined);
346
+ const currentP = getCurrentPack();
347
+ const grouped = new Map();
348
+ for (const p of packs) {
349
+ const group = grouped.get(p.category) || [];
350
+ group.push(p);
351
+ grouped.set(p.category, group);
352
+ }
353
+ console.log(color('Theme Packs:', 'bold'));
354
+ for (const [cat, catPacks] of grouped) {
355
+ console.log(color(`\n [${cat}]`, 'dim'));
356
+ for (const p of catPacks) {
357
+ const marker = currentP && p.name === currentP.name ? color(' *', 'green') : '';
358
+ console.log(` ${p.name}${marker} — ${p.description}`);
359
+ }
360
+ }
361
+ console.log(color('\n /pack <name>', 'dim'));
362
+ }
363
+ else {
364
+ const success = applyThemePack(parts[1], getCompanionMode());
365
+ if (success) {
366
+ const pack = getCurrentPack();
367
+ config.set('activeThemePack', parts[1]);
368
+ config.set('activeSkin', pack.skin.name);
369
+ config.set('activePalette', pack.palette.name);
370
+ const companion = getCompanionMode() === 'professional'
371
+ ? pack.companions.professional
372
+ : pack.companions.immersive;
373
+ config.set('activeCompanion', companion.name);
374
+ // Reset system prompt to use the companion's persona
375
+ state.messages = [{ role: 'system', content: getSystemPrompt(state.persona) }];
376
+ console.log(color(`Theme pack: ${parts[1]}`, 'green'));
377
+ console.log(color(` "${companion.greeting}"`, 'dim'));
378
+ }
379
+ else {
380
+ console.log(color(`Theme pack not found: ${parts[1]}`, 'yellow'));
381
+ }
382
+ }
383
+ console.log();
384
+ break;
385
+ case '/intensity':
386
+ if (parts[1] === 'professional' || parts[1] === 'pro') {
387
+ const success = setCompanionMode('professional');
388
+ if (success) {
389
+ const pack = getCurrentPack();
390
+ config.set('companionIntensity', 'professional');
391
+ config.set('activeCompanion', pack.companions.professional.name);
392
+ state.messages = [{ role: 'system', content: getSystemPrompt(state.persona) }];
393
+ console.log(color(`Switched to professional mode`, 'green'));
394
+ }
395
+ else {
396
+ console.log(color('No theme pack active. Use /pack <name> first.', 'yellow'));
397
+ }
398
+ }
399
+ else if (parts[1] === 'immersive' || parts[1] === 'imm') {
400
+ const success = setCompanionMode('immersive');
401
+ if (success) {
402
+ const pack = getCurrentPack();
403
+ config.set('companionIntensity', 'immersive');
404
+ config.set('activeCompanion', pack.companions.immersive.name);
405
+ state.messages = [{ role: 'system', content: getSystemPrompt(state.persona) }];
406
+ console.log(color(`Switched to immersive mode`, 'green'));
407
+ }
408
+ else {
409
+ console.log(color('No theme pack active. Use /pack <name> first.', 'yellow'));
410
+ }
411
+ }
412
+ else {
413
+ console.log(`Intensity: ${getCompanionMode()}`);
414
+ console.log(color('Options: /intensity professional (pro), /intensity immersive (imm)', 'dim'));
415
+ }
416
+ console.log();
417
+ break;
418
+ case '/emoji': {
419
+ const emojiArg = parts[1];
420
+ const emojiCurrent = config.get('useEmojis') !== false;
421
+ if (emojiArg === 'on') {
422
+ config.set('useEmojis', true);
423
+ console.log(color('Emojis enabled', 'green'));
424
+ }
425
+ else if (emojiArg === 'off') {
426
+ config.set('useEmojis', false);
427
+ console.log(color('Emojis disabled — text fallbacks will be used', 'green'));
428
+ }
429
+ else if (emojiArg === 'toggle') {
430
+ config.set('useEmojis', !emojiCurrent);
431
+ console.log(color(`Emojis ${!emojiCurrent ? 'enabled' : 'disabled'}`, 'green'));
432
+ }
433
+ else {
434
+ console.log(`Emojis: ${emojiCurrent ? 'ON' : 'OFF'}`);
435
+ console.log(color('Usage: /emoji [on|off|toggle]', 'dim'));
436
+ }
437
+ console.log();
438
+ break;
439
+ }
431
440
  case '/branch':
432
441
  {
433
- // Use a simple session ID for the legacy CLI
434
442
  const sessionId = 'default-session';
435
443
  if (parts[1] === 'list') {
436
444
  const branches = branching.listBranches(sessionId);
@@ -638,11 +646,68 @@ async function handleCommand(input, state, rl) {
638
646
  }
639
647
  console.log();
640
648
  break;
649
+ case '/sandbox':
650
+ {
651
+ const sandboxArg = parts[1];
652
+ const validModes = ['auto', 'native', 'docker', 'off'];
653
+ if (sandboxArg && validModes.includes(sandboxArg)) {
654
+ config.set('sandboxMode', sandboxArg);
655
+ console.log(color(`Sandbox mode set to: ${sandboxArg}`, 'green'));
656
+ }
657
+ else if (sandboxArg && !validModes.includes(sandboxArg)) {
658
+ console.log(color(`Invalid sandbox mode: ${sandboxArg}`, 'red'));
659
+ console.log(`Available modes: ${validModes.join(', ')}`);
660
+ }
661
+ else {
662
+ // Show sandbox status
663
+ const currentMode = config.get('sandboxMode') || 'auto';
664
+ const nativeStatus = getSandboxStatus();
665
+ const dockerReady = isDockerAvailable();
666
+ console.log(color('Sandbox Configuration', 'bold'));
667
+ console.log(` Mode: ${color(currentMode, 'cyan')}`);
668
+ console.log();
669
+ console.log(color(' Backends:', 'bold'));
670
+ console.log(` Docker: ${dockerReady ? color('available', 'green') : color('not available', 'dim')}`);
671
+ console.log(` Native: ${nativeStatus.available ? color('available', 'green') : color('not available', 'dim')}`);
672
+ if (nativeStatus.available) {
673
+ console.log(` ${nativeStatus.description}`);
674
+ }
675
+ console.log(` Platform: ${nativeStatus.platform}`);
676
+ console.log();
677
+ // Show effective behaviour
678
+ let effective;
679
+ switch (currentMode) {
680
+ case 'auto':
681
+ if (nativeStatus.available)
682
+ effective = `native (${nativeStatus.backend}) for shell commands`;
683
+ else
684
+ effective = 'unsandboxed (no native backend available)';
685
+ if (dockerReady)
686
+ effective += ', Docker for code execution';
687
+ break;
688
+ case 'native':
689
+ effective = nativeStatus.available ? `${nativeStatus.backend}` : 'ERROR: native not available';
690
+ break;
691
+ case 'docker':
692
+ effective = dockerReady ? 'Docker' : 'ERROR: Docker not available';
693
+ break;
694
+ case 'off':
695
+ effective = 'all sandboxing disabled';
696
+ break;
697
+ default:
698
+ effective = 'unknown';
699
+ }
700
+ console.log(` Effective: ${effective}`);
701
+ console.log();
702
+ console.log(color(' /sandbox <auto|native|docker|off>', 'dim'));
703
+ }
704
+ }
705
+ console.log();
706
+ break;
641
707
  case '/exit':
642
708
  case '/quit':
643
- case '/q':
644
709
  console.log();
645
- console.log(color(' Until we meet again...', 'cyan'));
710
+ console.log(color(` ${getCurrentCompanion().farewell}`, 'cyan'));
646
711
  console.log();
647
712
  state.running = false;
648
713
  rl.close();
@@ -653,9 +718,6 @@ async function handleCommand(input, state, rl) {
653
718
  console.log();
654
719
  }
655
720
  }
656
- /**
657
- * Handle upgrade command
658
- */
659
721
  async function handleUpgrade(rl) {
660
722
  console.log();
661
723
  console.log(color('Checking for updates...', 'cyan'));
@@ -685,7 +747,6 @@ async function handleUpgrade(rl) {
685
747
  console.log();
686
748
  console.log(`${color('Update available:', 'yellow')} v${currentVersion} → ${color('v' + latestVersion, 'green')}`);
687
749
  console.log();
688
- // Prompt for confirmation
689
750
  rl.question(`${color('Upgrade now? (y/N)', 'cyan')} `, async (answer) => {
690
751
  if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
691
752
  console.log();
@@ -695,7 +756,6 @@ async function handleUpgrade(rl) {
695
756
  console.log(color('Upgrade complete!', 'green'));
696
757
  console.log(color('Restarting Calliope...', 'dim'));
697
758
  console.log();
698
- // Restart the CLI
699
759
  const { spawn } = await import('child_process');
700
760
  const child = spawn(process.argv[0], process.argv.slice(1), {
701
761
  stdio: 'inherit',
@@ -717,9 +777,6 @@ async function handleUpgrade(rl) {
717
777
  }
718
778
  });
719
779
  }
720
- /**
721
- * Print help
722
- */
723
780
  function printHelp() {
724
781
  console.log();
725
782
  console.log(color('Commands:', 'bold'));
@@ -750,6 +807,7 @@ function printHelp() {
750
807
  console.log(' /scope [details|reset] Show/manage file access scope');
751
808
  console.log(' /add-dir <path> Add directory to scope');
752
809
  console.log(' /remove-dir <path> Remove directory from scope');
810
+ console.log(' /sandbox [mode] Sandbox status or set mode (auto|native|docker|off)');
753
811
  console.log();
754
812
  console.log(color('Navigation:', 'bold'));
755
813
  console.log(' /find <pattern> Fuzzy file search');
@@ -759,7 +817,13 @@ function printHelp() {
759
817
  console.log(' /hooks [init|list] Pre/post tool hooks');
760
818
  console.log(' /theme [name|list] Color themes');
761
819
  console.log();
762
- console.log(color('Ralph Wiggum Loop:', 'bold'));
820
+ console.log(color('HUD:', 'bold'));
821
+ console.log(' /skin [name|list] Switch visual skin');
822
+ console.log(' /palette [name|list] Switch color palette');
823
+ console.log(' /companion [name|list] Switch AI companion');
824
+ console.log(' /hud Show HUD status');
825
+ console.log();
826
+ console.log(color('Agent Loop:', 'bold'));
763
827
  console.log(' /loop "<prompt>" Start autonomous loop');
764
828
  console.log(' --max-iterations N');
765
829
  console.log(' --completion-promise "text"');
@@ -774,205 +838,4 @@ function printHelp() {
774
838
  console.log(' /exit Exit');
775
839
  console.log();
776
840
  }
777
- /**
778
- * Run the agent with a prompt
779
- */
780
- async function runAgent(prompt, state) {
781
- // Add user message
782
- state.messages.push({ role: 'user', content: prompt });
783
- // Spinner setup
784
- let spinnerIdx = 0;
785
- const spinnerInterval = setInterval(() => {
786
- process.stdout.write(`\r${color(SPINNER[spinnerIdx], 'cyan')} ${color('Thinking...', 'dim')}`);
787
- spinnerIdx = (spinnerIdx + 1) % SPINNER.length;
788
- }, 80);
789
- // Helper to clean up spinner
790
- const clearSpinner = () => {
791
- clearInterval(spinnerInterval);
792
- process.stdout.write('\r\x1b[K'); // Clear line
793
- };
794
- try {
795
- const maxIterations = config.get('maxIterations');
796
- let iteration = 0;
797
- let finalResponse = '';
798
- while (iteration < maxIterations) {
799
- iteration++;
800
- // Call LLM
801
- const response = await chat(state.provider, state.messages, TOOLS, state.model);
802
- // Handle tool calls
803
- if (response.toolCalls && response.toolCalls.length > 0) {
804
- clearSpinner();
805
- // Add assistant message with tool calls
806
- state.messages.push({
807
- role: 'assistant',
808
- content: response.content,
809
- toolCalls: response.toolCalls,
810
- });
811
- // Execute tools
812
- for (const toolCall of response.toolCalls) {
813
- // Execute pre-tool hooks
814
- const preHookResult = await hooks.checkHooksAllow('pre-tool', {
815
- tool: toolCall.name,
816
- toolArgs: toolCall.arguments,
817
- });
818
- if (!preHookResult.allowed) {
819
- console.log(`${color('│', 'dim')} ${color(`Blocked by hook: ${preHookResult.reason}`, 'red')}`);
820
- state.messages.push({
821
- role: 'tool',
822
- content: `[Blocked by hook: ${preHookResult.reason}]`,
823
- toolCallId: toolCall.id,
824
- });
825
- continue;
826
- }
827
- printToolCall(toolCall);
828
- const result = await executeTool(toolCall, state.cwd);
829
- printToolResult(toolCall.name, result.result);
830
- // Execute post-tool hooks
831
- hooks.executeHooks('post-tool', {
832
- tool: toolCall.name,
833
- toolArgs: toolCall.arguments,
834
- toolResult: result.result,
835
- }).catch((err) => {
836
- debugLog(`post-tool hook failed for ${toolCall.name}:`, err instanceof Error ? err.message : err);
837
- });
838
- state.messages.push({
839
- role: 'tool',
840
- content: result.result,
841
- toolCallId: toolCall.id,
842
- });
843
- }
844
- // Continue loop for next response
845
- continue;
846
- }
847
- // No tool calls - final response
848
- clearSpinner();
849
- state.messages.push({
850
- role: 'assistant',
851
- content: response.content,
852
- });
853
- finalResponse = response.content;
854
- console.log();
855
- console.log(`${color('✧', 'cyan')} ${color('Calliope:', 'dim')}`);
856
- console.log();
857
- printOutput(response.content);
858
- console.log();
859
- break;
860
- }
861
- return finalResponse;
862
- }
863
- catch (error) {
864
- const msg = error instanceof Error ? error.message : String(error);
865
- console.log();
866
- console.log(`${color('✗', 'red')} ${color(`Error: ${msg}`, 'red')}`);
867
- console.log();
868
- return '';
869
- }
870
- finally {
871
- // Ensure spinner is always cleaned up
872
- clearInterval(spinnerInterval);
873
- }
874
- }
875
- /**
876
- * Start an autonomous loop
877
- */
878
- async function startLoop(args, state) {
879
- // Parse args
880
- const maxIterMatch = args.match(/--max-iterations\s+(\d+)/);
881
- const completionMatch = args.match(/--completion-promise\s+"([^"]+)"/);
882
- let prompt = args
883
- .replace(/--max-iterations\s+\d+/, '')
884
- .replace(/--completion-promise\s+"[^"]+"/, '')
885
- .trim();
886
- const quotedMatch = prompt.match(/^"([^"]+)"$/);
887
- if (quotedMatch)
888
- prompt = quotedMatch[1];
889
- if (!prompt) {
890
- console.log(color('Usage: /loop "<prompt>" [--max-iterations N] [--completion-promise "text"]', 'red'));
891
- console.log();
892
- return;
893
- }
894
- state.loopActive = true;
895
- state.loopPrompt = prompt;
896
- state.loopIteration = 0;
897
- state.loopMaxIterations = maxIterMatch ? parseInt(maxIterMatch[1], 10) : 50;
898
- state.loopCompletionPromise = completionMatch ? completionMatch[1] : undefined;
899
- console.log();
900
- console.log(`${color('╭─', 'dim')} ${color('🔄 Ralph Loop Started', 'bold')}`);
901
- console.log(`${color('│', 'dim')} ${color('Max:', 'dim')} ${color(String(state.loopMaxIterations), 'cyan')}`);
902
- if (state.loopCompletionPromise) {
903
- console.log(`${color('│', 'dim')} ${color('Promise:', 'dim')} ${color(state.loopCompletionPromise, 'green')}`);
904
- }
905
- console.log(`${color('╰─', 'dim')} ${color('/cancel-loop to stop', 'dim')}`);
906
- console.log();
907
- // Run loop
908
- while (state.loopActive && state.loopIteration < state.loopMaxIterations) {
909
- state.loopIteration++;
910
- console.log(`${color('╭─', 'cyan')} ${color(`Iteration ${state.loopIteration}/${state.loopMaxIterations}`, 'bold')}`);
911
- const result = await runAgent(state.loopPrompt, state);
912
- // Check completion promise
913
- if (state.loopCompletionPromise && result.includes(state.loopCompletionPromise)) {
914
- console.log(`${color('🎉 Completion promise detected!', 'green')}`);
915
- state.loopActive = false;
916
- break;
917
- }
918
- if (!state.loopActive)
919
- break;
920
- // Delay between iterations
921
- await new Promise(r => setTimeout(r, 1000));
922
- }
923
- if (state.loopIteration >= state.loopMaxIterations) {
924
- console.log(`${color('⚠️ Max iterations reached', 'yellow')}`);
925
- }
926
- state.loopActive = false;
927
- console.log();
928
- }
929
- /**
930
- * Print tool call
931
- */
932
- function printToolCall(toolCall) {
933
- const icons = {
934
- shell: '⚡',
935
- read_file: '📄',
936
- write_file: '✍️',
937
- list_files: '📁',
938
- think: '💭',
939
- };
940
- console.log();
941
- console.log(`${color('╭─', 'dim')} ${icons[toolCall.name] || '⚙️'} ${color(toolCall.name, 'yellow')}`);
942
- if (toolCall.name === 'shell' && toolCall.arguments.command) {
943
- console.log(`${color('│', 'dim')} ${color('$', 'green')} ${toolCall.arguments.command}`);
944
- }
945
- else if (toolCall.name === 'think' && toolCall.arguments.thought) {
946
- const thought = String(toolCall.arguments.thought);
947
- const preview = thought.length > 80 ? thought.substring(0, 80) + '...' : thought;
948
- console.log(`${color('│', 'dim')} ${color(preview, 'dim')}`);
949
- }
950
- }
951
- /**
952
- * Print tool result
953
- */
954
- function printToolResult(name, result) {
955
- if (name === 'think') {
956
- console.log(`${color('╰─', 'dim')} ${color('✓', 'green')}`);
957
- return;
958
- }
959
- const lines = result.split('\n').slice(0, 10);
960
- for (const line of lines) {
961
- console.log(`${color('│', 'dim')} ${color(line.substring(0, 100), 'dim')}`);
962
- }
963
- if (result.split('\n').length > 10) {
964
- console.log(`${color('│', 'dim')} ${color(`... (${result.split('\n').length - 10} more lines)`, 'dim')}`);
965
- }
966
- const success = !result.toLowerCase().includes('error');
967
- console.log(`${color('╰─', 'dim')} ${success ? color('✓', 'green') : color('✗', 'red')}`);
968
- }
969
- /**
970
- * Print output with indentation
971
- */
972
- function printOutput(text) {
973
- const lines = text.split('\n');
974
- for (const line of lines) {
975
- console.log(`${color('│', 'blue')} ${line}`);
976
- }
977
- }
978
- //# sourceMappingURL=cli.js.map
841
+ //# sourceMappingURL=commands.js.map