@calliopelabs/cli 2.3.0 → 3.0.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 (538) hide show
  1. package/README.md +45 -644
  2. package/dist/acp.d.ts +78 -0
  3. package/dist/acp.d.ts.map +1 -0
  4. package/dist/acp.js +572 -0
  5. package/dist/acp.js.map +1 -0
  6. package/dist/auto-compressor.d.ts.map +1 -1
  7. package/dist/auto-compressor.js +9 -5
  8. package/dist/auto-compressor.js.map +1 -1
  9. package/dist/bin.d.ts +9 -5
  10. package/dist/bin.d.ts.map +1 -1
  11. package/dist/bin.js +108 -76
  12. package/dist/bin.js.map +1 -1
  13. package/dist/budget.d.ts +64 -0
  14. package/dist/budget.d.ts.map +1 -0
  15. package/dist/budget.js +157 -0
  16. package/dist/budget.js.map +1 -0
  17. package/dist/checkpoint.d.ts +63 -30
  18. package/dist/checkpoint.d.ts.map +1 -1
  19. package/dist/checkpoint.js +249 -150
  20. package/dist/checkpoint.js.map +1 -1
  21. package/dist/circuit-breaker/breaker.js.map +1 -1
  22. package/dist/config.d.ts +86 -81
  23. package/dist/config.d.ts.map +1 -1
  24. package/dist/config.js +237 -305
  25. package/dist/config.js.map +1 -1
  26. package/dist/cost.d.ts +114 -0
  27. package/dist/cost.d.ts.map +1 -0
  28. package/dist/cost.js +499 -0
  29. package/dist/cost.js.map +1 -0
  30. package/dist/diff.d.ts.map +1 -1
  31. package/dist/diff.js +53 -11
  32. package/dist/diff.js.map +1 -1
  33. package/dist/errors.d.ts.map +1 -1
  34. package/dist/errors.js +33 -6
  35. package/dist/errors.js.map +1 -1
  36. package/dist/files.js.map +1 -1
  37. package/dist/fleet.d.ts +30 -0
  38. package/dist/fleet.d.ts.map +1 -0
  39. package/dist/fleet.js +86 -0
  40. package/dist/fleet.js.map +1 -0
  41. package/dist/fuzzy-search.d.ts.map +1 -1
  42. package/dist/fuzzy-search.js +2 -1
  43. package/dist/fuzzy-search.js.map +1 -1
  44. package/dist/git-status.js.map +1 -1
  45. package/dist/headless.d.ts +1 -2
  46. package/dist/headless.d.ts.map +1 -1
  47. package/dist/headless.js +222 -26
  48. package/dist/headless.js.map +1 -1
  49. package/dist/hooks.d.ts +8 -2
  50. package/dist/hooks.d.ts.map +1 -1
  51. package/dist/hooks.js +97 -11
  52. package/dist/hooks.js.map +1 -1
  53. package/dist/hud/api.d.ts +3 -18
  54. package/dist/hud/api.d.ts.map +1 -1
  55. package/dist/hud/api.js +9 -352
  56. package/dist/hud/api.js.map +1 -1
  57. package/dist/hud/palettes.d.ts.map +1 -1
  58. package/dist/hud/palettes.js +0 -180
  59. package/dist/hud/palettes.js.map +1 -1
  60. package/dist/hud/skins.d.ts.map +1 -1
  61. package/dist/hud/skins.js +0 -263
  62. package/dist/hud/skins.js.map +1 -1
  63. package/dist/hud/types.d.ts +2 -5
  64. package/dist/hud/types.d.ts.map +1 -1
  65. package/dist/index.d.ts +1 -4
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +1 -4
  68. package/dist/index.js.map +1 -1
  69. package/dist/iteration-ledger.d.ts.map +1 -1
  70. package/dist/iteration-ledger.js +3 -2
  71. package/dist/iteration-ledger.js.map +1 -1
  72. package/dist/local-model.d.ts +150 -0
  73. package/dist/local-model.d.ts.map +1 -0
  74. package/dist/local-model.js +408 -0
  75. package/dist/local-model.js.map +1 -0
  76. package/dist/markdown.d.ts.map +1 -1
  77. package/dist/markdown.js +32 -10
  78. package/dist/markdown.js.map +1 -1
  79. package/dist/mcp.d.ts +35 -5
  80. package/dist/mcp.d.ts.map +1 -1
  81. package/dist/mcp.js +190 -13
  82. package/dist/mcp.js.map +1 -1
  83. package/dist/memory.d.ts.map +1 -1
  84. package/dist/memory.js +6 -4
  85. package/dist/memory.js.map +1 -1
  86. package/dist/model-detection.d.ts +14 -1
  87. package/dist/model-detection.d.ts.map +1 -1
  88. package/dist/model-detection.js +308 -115
  89. package/dist/model-detection.js.map +1 -1
  90. package/dist/parallel-tools.d.ts +9 -1
  91. package/dist/parallel-tools.d.ts.map +1 -1
  92. package/dist/parallel-tools.js +6 -5
  93. package/dist/parallel-tools.js.map +1 -1
  94. package/dist/plugins.d.ts +68 -0
  95. package/dist/plugins.d.ts.map +1 -1
  96. package/dist/plugins.js +201 -3
  97. package/dist/plugins.js.map +1 -1
  98. package/dist/policy.d.ts +43 -0
  99. package/dist/policy.d.ts.map +1 -0
  100. package/dist/policy.js +139 -0
  101. package/dist/policy.js.map +1 -0
  102. package/dist/project-config.d.ts +1 -2
  103. package/dist/project-config.d.ts.map +1 -1
  104. package/dist/project-config.js +0 -3
  105. package/dist/project-config.js.map +1 -1
  106. package/dist/providers/anthropic.d.ts.map +1 -1
  107. package/dist/providers/anthropic.js +36 -2
  108. package/dist/providers/anthropic.js.map +1 -1
  109. package/dist/providers/bedrock.d.ts.map +1 -1
  110. package/dist/providers/bedrock.js +83 -22
  111. package/dist/providers/bedrock.js.map +1 -1
  112. package/dist/providers/compat.d.ts +21 -0
  113. package/dist/providers/compat.d.ts.map +1 -1
  114. package/dist/providers/compat.js +176 -6
  115. package/dist/providers/compat.js.map +1 -1
  116. package/dist/providers/google.js.map +1 -1
  117. package/dist/providers/index.d.ts +19 -4
  118. package/dist/providers/index.d.ts.map +1 -1
  119. package/dist/providers/index.js +62 -9
  120. package/dist/providers/index.js.map +1 -1
  121. package/dist/providers/ollama.d.ts +2 -2
  122. package/dist/providers/ollama.d.ts.map +1 -1
  123. package/dist/providers/ollama.js +26 -6
  124. package/dist/providers/ollama.js.map +1 -1
  125. package/dist/providers/openai.d.ts.map +1 -1
  126. package/dist/providers/openai.js +14 -10
  127. package/dist/providers/openai.js.map +1 -1
  128. package/dist/providers/types.d.ts +8 -0
  129. package/dist/providers/types.d.ts.map +1 -1
  130. package/dist/providers/types.js +19 -10
  131. package/dist/providers/types.js.map +1 -1
  132. package/dist/replay.d.ts +37 -0
  133. package/dist/replay.d.ts.map +1 -0
  134. package/dist/replay.js +168 -0
  135. package/dist/replay.js.map +1 -0
  136. package/dist/risk.d.ts.map +1 -1
  137. package/dist/risk.js +15 -5
  138. package/dist/risk.js.map +1 -1
  139. package/dist/router.d.ts +133 -0
  140. package/dist/router.d.ts.map +1 -0
  141. package/dist/{model-router.js → router.js} +336 -10
  142. package/dist/router.js.map +1 -0
  143. package/dist/runlog.d.ts +185 -0
  144. package/dist/runlog.d.ts.map +1 -0
  145. package/dist/runlog.js +398 -0
  146. package/dist/runlog.js.map +1 -0
  147. package/dist/{sandbox.d.ts → sandbox/docker.d.ts} +1 -1
  148. package/dist/sandbox/docker.d.ts.map +1 -0
  149. package/dist/{sandbox.js → sandbox/docker.js} +1 -1
  150. package/dist/sandbox/docker.js.map +1 -0
  151. package/dist/sandbox/index.d.ts +36 -0
  152. package/dist/sandbox/index.d.ts.map +1 -0
  153. package/dist/sandbox/index.js +62 -0
  154. package/dist/sandbox/index.js.map +1 -0
  155. package/dist/{sandbox-native.d.ts → sandbox/native.d.ts} +2 -1
  156. package/dist/sandbox/native.d.ts.map +1 -0
  157. package/dist/{sandbox-native.js → sandbox/native.js} +38 -6
  158. package/dist/sandbox/native.js.map +1 -0
  159. package/dist/scope.d.ts +10 -0
  160. package/dist/scope.d.ts.map +1 -1
  161. package/dist/scope.js +76 -16
  162. package/dist/scope.js.map +1 -1
  163. package/dist/scuttlebot/client.d.ts +83 -0
  164. package/dist/scuttlebot/client.d.ts.map +1 -0
  165. package/dist/scuttlebot/client.js +350 -0
  166. package/dist/scuttlebot/client.js.map +1 -0
  167. package/dist/scuttlebot/config.d.ts +28 -0
  168. package/dist/scuttlebot/config.d.ts.map +1 -0
  169. package/dist/scuttlebot/config.js +91 -0
  170. package/dist/scuttlebot/config.js.map +1 -0
  171. package/dist/scuttlebot/http-client.d.ts +63 -0
  172. package/dist/scuttlebot/http-client.d.ts.map +1 -0
  173. package/dist/scuttlebot/http-client.js +124 -0
  174. package/dist/scuttlebot/http-client.js.map +1 -0
  175. package/dist/scuttlebot/index.d.ts +13 -0
  176. package/dist/scuttlebot/index.d.ts.map +1 -0
  177. package/dist/scuttlebot/index.js +10 -0
  178. package/dist/scuttlebot/index.js.map +1 -0
  179. package/dist/scuttlebot/irc-client.d.ts +124 -0
  180. package/dist/scuttlebot/irc-client.d.ts.map +1 -0
  181. package/dist/scuttlebot/irc-client.js +599 -0
  182. package/dist/scuttlebot/irc-client.js.map +1 -0
  183. package/dist/setup.d.ts.map +1 -1
  184. package/dist/setup.js +22 -54
  185. package/dist/setup.js.map +1 -1
  186. package/dist/skills.d.ts +58 -0
  187. package/dist/skills.d.ts.map +1 -1
  188. package/dist/skills.js +186 -16
  189. package/dist/skills.js.map +1 -1
  190. package/dist/storage.d.ts +0 -4
  191. package/dist/storage.d.ts.map +1 -1
  192. package/dist/storage.js +87 -8
  193. package/dist/storage.js.map +1 -1
  194. package/dist/streaming.d.ts +25 -0
  195. package/dist/streaming.d.ts.map +1 -1
  196. package/dist/streaming.js +59 -0
  197. package/dist/streaming.js.map +1 -1
  198. package/dist/styles.d.ts +6 -0
  199. package/dist/styles.d.ts.map +1 -1
  200. package/dist/styles.js +11 -0
  201. package/dist/styles.js.map +1 -1
  202. package/dist/summarization.js.map +1 -1
  203. package/dist/terminal-image.js +1 -1
  204. package/dist/terminal-image.js.map +1 -1
  205. package/dist/themes.d.ts +5 -4
  206. package/dist/themes.d.ts.map +1 -1
  207. package/dist/themes.js +35 -90
  208. package/dist/themes.js.map +1 -1
  209. package/dist/tools.d.ts +27 -3
  210. package/dist/tools.d.ts.map +1 -1
  211. package/dist/tools.js +352 -209
  212. package/dist/tools.js.map +1 -1
  213. package/dist/trust.d.ts +16 -3
  214. package/dist/trust.d.ts.map +1 -1
  215. package/dist/trust.js +23 -4
  216. package/dist/trust.js.map +1 -1
  217. package/dist/types.d.ts +4 -3
  218. package/dist/types.d.ts.map +1 -1
  219. package/dist/types.js +34 -44
  220. package/dist/types.js.map +1 -1
  221. package/dist/ui/agent.d.ts +4 -7
  222. package/dist/ui/agent.d.ts.map +1 -1
  223. package/dist/ui/agent.js +354 -73
  224. package/dist/ui/agent.js.map +1 -1
  225. package/dist/ui/animations.d.ts +37 -0
  226. package/dist/ui/animations.d.ts.map +1 -0
  227. package/dist/ui/animations.js +227 -0
  228. package/dist/ui/animations.js.map +1 -0
  229. package/dist/ui/chat-input-keys.d.ts +42 -0
  230. package/dist/ui/chat-input-keys.d.ts.map +1 -0
  231. package/dist/ui/chat-input-keys.js +360 -0
  232. package/dist/ui/chat-input-keys.js.map +1 -0
  233. package/dist/ui/chat-input.d.ts +5 -2
  234. package/dist/ui/chat-input.d.ts.map +1 -1
  235. package/dist/ui/chat-input.js +54 -308
  236. package/dist/ui/chat-input.js.map +1 -1
  237. package/dist/ui/commands.d.ts +15 -45
  238. package/dist/ui/commands.d.ts.map +1 -1
  239. package/dist/ui/commands.js +461 -2636
  240. package/dist/ui/commands.js.map +1 -1
  241. package/dist/ui/completions.d.ts +1 -0
  242. package/dist/ui/completions.d.ts.map +1 -1
  243. package/dist/ui/completions.js +36 -107
  244. package/dist/ui/completions.js.map +1 -1
  245. package/dist/ui/components.d.ts +14 -6
  246. package/dist/ui/components.d.ts.map +1 -1
  247. package/dist/ui/components.js +17 -226
  248. package/dist/ui/components.js.map +1 -1
  249. package/dist/ui/context.js +6 -6
  250. package/dist/ui/context.js.map +1 -1
  251. package/dist/ui/debug-log.d.ts +11 -0
  252. package/dist/ui/debug-log.d.ts.map +1 -0
  253. package/dist/ui/debug-log.js +21 -0
  254. package/dist/ui/debug-log.js.map +1 -0
  255. package/dist/ui/error-boundary.d.ts.map +1 -1
  256. package/dist/ui/error-boundary.js.map +1 -1
  257. package/dist/ui/frame.d.ts.map +1 -1
  258. package/dist/ui/frame.js +1 -3
  259. package/dist/ui/frame.js.map +1 -1
  260. package/dist/ui/index.d.ts +11 -3
  261. package/dist/ui/index.d.ts.map +1 -1
  262. package/dist/ui/index.js +46 -887
  263. package/dist/ui/index.js.map +1 -1
  264. package/dist/ui/input-utils.d.ts +20 -0
  265. package/dist/ui/input-utils.d.ts.map +1 -0
  266. package/dist/ui/input-utils.js +35 -0
  267. package/dist/ui/input-utils.js.map +1 -0
  268. package/dist/ui/messages.d.ts +8 -7
  269. package/dist/ui/messages.d.ts.map +1 -1
  270. package/dist/ui/messages.js +51 -35
  271. package/dist/ui/messages.js.map +1 -1
  272. package/dist/ui/modals/index.d.ts +11 -0
  273. package/dist/ui/modals/index.d.ts.map +1 -0
  274. package/dist/ui/modals/index.js +10 -0
  275. package/dist/ui/modals/index.js.map +1 -0
  276. package/dist/ui/{modals.d.ts → modals/prompts.d.ts} +5 -20
  277. package/dist/ui/modals/prompts.d.ts.map +1 -0
  278. package/dist/ui/{modals.js → modals/prompts.js} +14 -94
  279. package/dist/ui/modals/prompts.js.map +1 -0
  280. package/dist/ui/modals/selectors.d.ts +33 -0
  281. package/dist/ui/modals/selectors.d.ts.map +1 -0
  282. package/dist/ui/modals/selectors.js +111 -0
  283. package/dist/ui/modals/selectors.js.map +1 -0
  284. package/dist/ui/modals/setup.d.ts +17 -0
  285. package/dist/ui/modals/setup.d.ts.map +1 -0
  286. package/dist/ui/modals/setup.js +51 -0
  287. package/dist/ui/modals/setup.js.map +1 -0
  288. package/dist/ui/regions/input-region.d.ts +40 -0
  289. package/dist/ui/regions/input-region.d.ts.map +1 -0
  290. package/dist/ui/regions/input-region.js +116 -0
  291. package/dist/ui/regions/input-region.js.map +1 -0
  292. package/dist/ui/regions/modal-host.d.ts +41 -0
  293. package/dist/ui/regions/modal-host.d.ts.map +1 -0
  294. package/dist/ui/regions/modal-host.js +51 -0
  295. package/dist/ui/regions/modal-host.js.map +1 -0
  296. package/dist/ui/regions/render-probe.d.ts +22 -0
  297. package/dist/ui/regions/render-probe.d.ts.map +1 -0
  298. package/dist/ui/regions/render-probe.js +45 -0
  299. package/dist/ui/regions/render-probe.js.map +1 -0
  300. package/dist/ui/regions/static-scrollback.d.ts +39 -0
  301. package/dist/ui/regions/static-scrollback.d.ts.map +1 -0
  302. package/dist/ui/regions/static-scrollback.js +68 -0
  303. package/dist/ui/regions/static-scrollback.js.map +1 -0
  304. package/dist/ui/regions/status-region.d.ts +24 -0
  305. package/dist/ui/regions/status-region.d.ts.map +1 -0
  306. package/dist/ui/regions/status-region.js +17 -0
  307. package/dist/ui/regions/status-region.js.map +1 -0
  308. package/dist/ui/regions/transcript-region.d.ts +41 -0
  309. package/dist/ui/regions/transcript-region.d.ts.map +1 -0
  310. package/dist/ui/regions/transcript-region.js +52 -0
  311. package/dist/ui/regions/transcript-region.js.map +1 -0
  312. package/dist/ui/self-restart.d.ts +9 -0
  313. package/dist/ui/self-restart.d.ts.map +1 -0
  314. package/dist/ui/self-restart.js +24 -0
  315. package/dist/ui/self-restart.js.map +1 -0
  316. package/dist/ui/state/use-chat-controller.d.ts +23 -0
  317. package/dist/ui/state/use-chat-controller.d.ts.map +1 -0
  318. package/dist/ui/state/use-chat-controller.js +643 -0
  319. package/dist/ui/state/use-chat-controller.js.map +1 -0
  320. package/dist/ui/state/use-loop-state.d.ts +23 -0
  321. package/dist/ui/state/use-loop-state.d.ts.map +1 -0
  322. package/dist/ui/state/use-loop-state.js +39 -0
  323. package/dist/ui/state/use-loop-state.js.map +1 -0
  324. package/dist/ui/state/use-modal-state.d.ts +52 -0
  325. package/dist/ui/state/use-modal-state.d.ts.map +1 -0
  326. package/dist/ui/state/use-modal-state.js +44 -0
  327. package/dist/ui/state/use-modal-state.js.map +1 -0
  328. package/dist/ui/state/use-model-state.d.ts +29 -0
  329. package/dist/ui/state/use-model-state.d.ts.map +1 -0
  330. package/dist/ui/state/use-model-state.js +47 -0
  331. package/dist/ui/state/use-model-state.js.map +1 -0
  332. package/dist/ui/state/use-processing-state.d.ts +24 -0
  333. package/dist/ui/state/use-processing-state.d.ts.map +1 -0
  334. package/dist/ui/state/use-processing-state.js +46 -0
  335. package/dist/ui/state/use-processing-state.js.map +1 -0
  336. package/dist/ui/state/use-queue-state.d.ts +19 -0
  337. package/dist/ui/state/use-queue-state.d.ts.map +1 -0
  338. package/dist/ui/state/use-queue-state.js +30 -0
  339. package/dist/ui/state/use-queue-state.js.map +1 -0
  340. package/dist/ui/state/use-session-init.d.ts +22 -0
  341. package/dist/ui/state/use-session-init.d.ts.map +1 -0
  342. package/dist/ui/state/use-session-init.js +77 -0
  343. package/dist/ui/state/use-session-init.js.map +1 -0
  344. package/dist/ui/state/use-session-stats.d.ts +16 -0
  345. package/dist/ui/state/use-session-stats.d.ts.map +1 -0
  346. package/dist/ui/state/use-session-stats.js +18 -0
  347. package/dist/ui/state/use-session-stats.js.map +1 -0
  348. package/dist/ui/state/use-terminal-width.d.ts +8 -0
  349. package/dist/ui/state/use-terminal-width.d.ts.map +1 -0
  350. package/dist/ui/state/use-terminal-width.js +22 -0
  351. package/dist/ui/state/use-terminal-width.js.map +1 -0
  352. package/dist/ui/state/use-transcript-state.d.ts +21 -0
  353. package/dist/ui/state/use-transcript-state.d.ts.map +1 -0
  354. package/dist/ui/state/use-transcript-state.js +49 -0
  355. package/dist/ui/state/use-transcript-state.js.map +1 -0
  356. package/dist/ui/status-bar.d.ts +4 -1
  357. package/dist/ui/status-bar.d.ts.map +1 -1
  358. package/dist/ui/status-bar.js +13 -3
  359. package/dist/ui/status-bar.js.map +1 -1
  360. package/dist/ui/types.d.ts +3 -0
  361. package/dist/ui/types.d.ts.map +1 -1
  362. package/dist/version-check.d.ts.map +1 -1
  363. package/dist/version-check.js +10 -0
  364. package/dist/version-check.js.map +1 -1
  365. package/package.json +12 -8
  366. package/dist/agents/agent-config-loader.d.ts +0 -60
  367. package/dist/agents/agent-config-loader.d.ts.map +0 -1
  368. package/dist/agents/agent-config-loader.js +0 -402
  369. package/dist/agents/agent-config-loader.js.map +0 -1
  370. package/dist/agents/agent-config-presets.d.ts +0 -10
  371. package/dist/agents/agent-config-presets.d.ts.map +0 -1
  372. package/dist/agents/agent-config-presets.js +0 -940
  373. package/dist/agents/agent-config-presets.js.map +0 -1
  374. package/dist/agents/agent-config-types.d.ts +0 -145
  375. package/dist/agents/agent-config-types.d.ts.map +0 -1
  376. package/dist/agents/agent-config-types.js +0 -12
  377. package/dist/agents/agent-config-types.js.map +0 -1
  378. package/dist/agents/agent-detection.d.ts +0 -35
  379. package/dist/agents/agent-detection.d.ts.map +0 -1
  380. package/dist/agents/agent-detection.js +0 -110
  381. package/dist/agents/agent-detection.js.map +0 -1
  382. package/dist/agents/aggregator.d.ts +0 -19
  383. package/dist/agents/aggregator.d.ts.map +0 -1
  384. package/dist/agents/aggregator.js +0 -141
  385. package/dist/agents/aggregator.js.map +0 -1
  386. package/dist/agents/cli-backend.d.ts +0 -32
  387. package/dist/agents/cli-backend.d.ts.map +0 -1
  388. package/dist/agents/cli-backend.js +0 -271
  389. package/dist/agents/cli-backend.js.map +0 -1
  390. package/dist/agents/council-types.d.ts +0 -115
  391. package/dist/agents/council-types.d.ts.map +0 -1
  392. package/dist/agents/council-types.js +0 -81
  393. package/dist/agents/council-types.js.map +0 -1
  394. package/dist/agents/council.d.ts +0 -112
  395. package/dist/agents/council.d.ts.map +0 -1
  396. package/dist/agents/council.js +0 -722
  397. package/dist/agents/council.js.map +0 -1
  398. package/dist/agents/decomposer.d.ts +0 -33
  399. package/dist/agents/decomposer.d.ts.map +0 -1
  400. package/dist/agents/decomposer.js +0 -138
  401. package/dist/agents/decomposer.js.map +0 -1
  402. package/dist/agents/dynamic-tools.d.ts +0 -52
  403. package/dist/agents/dynamic-tools.d.ts.map +0 -1
  404. package/dist/agents/dynamic-tools.js +0 -395
  405. package/dist/agents/dynamic-tools.js.map +0 -1
  406. package/dist/agents/index.d.ts +0 -29
  407. package/dist/agents/index.d.ts.map +0 -1
  408. package/dist/agents/index.js +0 -29
  409. package/dist/agents/index.js.map +0 -1
  410. package/dist/agents/installer.d.ts +0 -39
  411. package/dist/agents/installer.d.ts.map +0 -1
  412. package/dist/agents/installer.js +0 -205
  413. package/dist/agents/installer.js.map +0 -1
  414. package/dist/agents/orchestrator.d.ts +0 -106
  415. package/dist/agents/orchestrator.d.ts.map +0 -1
  416. package/dist/agents/orchestrator.js +0 -363
  417. package/dist/agents/orchestrator.js.map +0 -1
  418. package/dist/agents/sdk-backend.d.ts +0 -63
  419. package/dist/agents/sdk-backend.d.ts.map +0 -1
  420. package/dist/agents/sdk-backend.js +0 -489
  421. package/dist/agents/sdk-backend.js.map +0 -1
  422. package/dist/agents/swarm-types.d.ts +0 -84
  423. package/dist/agents/swarm-types.d.ts.map +0 -1
  424. package/dist/agents/swarm-types.js +0 -20
  425. package/dist/agents/swarm-types.js.map +0 -1
  426. package/dist/agents/swarm.d.ts +0 -79
  427. package/dist/agents/swarm.d.ts.map +0 -1
  428. package/dist/agents/swarm.js +0 -375
  429. package/dist/agents/swarm.js.map +0 -1
  430. package/dist/agents/tools.d.ts +0 -26
  431. package/dist/agents/tools.d.ts.map +0 -1
  432. package/dist/agents/tools.js +0 -776
  433. package/dist/agents/tools.js.map +0 -1
  434. package/dist/agents/types.d.ts +0 -108
  435. package/dist/agents/types.d.ts.map +0 -1
  436. package/dist/agents/types.js +0 -43
  437. package/dist/agents/types.js.map +0 -1
  438. package/dist/api-server.d.ts +0 -36
  439. package/dist/api-server.d.ts.map +0 -1
  440. package/dist/api-server.js +0 -255
  441. package/dist/api-server.js.map +0 -1
  442. package/dist/auto-checkpoint.d.ts +0 -35
  443. package/dist/auto-checkpoint.d.ts.map +0 -1
  444. package/dist/auto-checkpoint.js +0 -143
  445. package/dist/auto-checkpoint.js.map +0 -1
  446. package/dist/background-jobs.d.ts +0 -45
  447. package/dist/background-jobs.d.ts.map +0 -1
  448. package/dist/background-jobs.js +0 -127
  449. package/dist/background-jobs.js.map +0 -1
  450. package/dist/branching.d.ts +0 -56
  451. package/dist/branching.d.ts.map +0 -1
  452. package/dist/branching.js +0 -211
  453. package/dist/branching.js.map +0 -1
  454. package/dist/cli/agent.d.ts +0 -9
  455. package/dist/cli/agent.d.ts.map +0 -1
  456. package/dist/cli/agent.js +0 -314
  457. package/dist/cli/agent.js.map +0 -1
  458. package/dist/cli/commands.d.ts +0 -12
  459. package/dist/cli/commands.d.ts.map +0 -1
  460. package/dist/cli/commands.js +0 -943
  461. package/dist/cli/commands.js.map +0 -1
  462. package/dist/cli/index.d.ts +0 -8
  463. package/dist/cli/index.d.ts.map +0 -1
  464. package/dist/cli/index.js +0 -237
  465. package/dist/cli/index.js.map +0 -1
  466. package/dist/cli/types.d.ts +0 -33
  467. package/dist/cli/types.d.ts.map +0 -1
  468. package/dist/cli/types.js +0 -21
  469. package/dist/cli/types.js.map +0 -1
  470. package/dist/companions.d.ts +0 -54
  471. package/dist/companions.d.ts.map +0 -1
  472. package/dist/companions.js +0 -440
  473. package/dist/companions.js.map +0 -1
  474. package/dist/completion.d.ts +0 -75
  475. package/dist/completion.d.ts.map +0 -1
  476. package/dist/completion.js +0 -234
  477. package/dist/completion.js.map +0 -1
  478. package/dist/file-watcher.d.ts +0 -91
  479. package/dist/file-watcher.d.ts.map +0 -1
  480. package/dist/file-watcher.js +0 -269
  481. package/dist/file-watcher.js.map +0 -1
  482. package/dist/hud/theme-packs/api.d.ts +0 -51
  483. package/dist/hud/theme-packs/api.d.ts.map +0 -1
  484. package/dist/hud/theme-packs/api.js +0 -145
  485. package/dist/hud/theme-packs/api.js.map +0 -1
  486. package/dist/hud/theme-packs/index.d.ts +0 -18
  487. package/dist/hud/theme-packs/index.d.ts.map +0 -1
  488. package/dist/hud/theme-packs/index.js +0 -38
  489. package/dist/hud/theme-packs/index.js.map +0 -1
  490. package/dist/hud/theme-packs/types.d.ts +0 -29
  491. package/dist/hud/theme-packs/types.d.ts.map +0 -1
  492. package/dist/hud/theme-packs/types.js +0 -9
  493. package/dist/hud/theme-packs/types.js.map +0 -1
  494. package/dist/idle-eviction.d.ts +0 -34
  495. package/dist/idle-eviction.d.ts.map +0 -1
  496. package/dist/idle-eviction.js +0 -78
  497. package/dist/idle-eviction.js.map +0 -1
  498. package/dist/keyboard.d.ts +0 -57
  499. package/dist/keyboard.d.ts.map +0 -1
  500. package/dist/keyboard.js +0 -265
  501. package/dist/keyboard.js.map +0 -1
  502. package/dist/model-router.d.ts +0 -67
  503. package/dist/model-router.d.ts.map +0 -1
  504. package/dist/model-router.js.map +0 -1
  505. package/dist/providers/openai-compat-shims.d.ts +0 -31
  506. package/dist/providers/openai-compat-shims.d.ts.map +0 -1
  507. package/dist/providers/openai-compat-shims.js +0 -179
  508. package/dist/providers/openai-compat-shims.js.map +0 -1
  509. package/dist/sandbox-native.d.ts.map +0 -1
  510. package/dist/sandbox-native.js.map +0 -1
  511. package/dist/sandbox.d.ts.map +0 -1
  512. package/dist/sandbox.js.map +0 -1
  513. package/dist/session-timeout.d.ts +0 -31
  514. package/dist/session-timeout.d.ts.map +0 -1
  515. package/dist/session-timeout.js +0 -100
  516. package/dist/session-timeout.js.map +0 -1
  517. package/dist/smart-router.d.ts +0 -73
  518. package/dist/smart-router.d.ts.map +0 -1
  519. package/dist/smart-router.js +0 -332
  520. package/dist/smart-router.js.map +0 -1
  521. package/dist/terminal-recording.d.ts +0 -55
  522. package/dist/terminal-recording.d.ts.map +0 -1
  523. package/dist/terminal-recording.js +0 -182
  524. package/dist/terminal-recording.js.map +0 -1
  525. package/dist/tmux.d.ts +0 -35
  526. package/dist/tmux.d.ts.map +0 -1
  527. package/dist/tmux.js +0 -106
  528. package/dist/tmux.js.map +0 -1
  529. package/dist/ui/modals.d.ts.map +0 -1
  530. package/dist/ui/modals.js.map +0 -1
  531. package/dist/ui/pack-picker.d.ts +0 -12
  532. package/dist/ui/pack-picker.d.ts.map +0 -1
  533. package/dist/ui/pack-picker.js +0 -101
  534. package/dist/ui/pack-picker.js.map +0 -1
  535. package/dist/ui/theme-picker.d.ts +0 -24
  536. package/dist/ui/theme-picker.d.ts.map +0 -1
  537. package/dist/ui/theme-picker.js +0 -190
  538. package/dist/ui/theme-picker.js.map +0 -1
package/dist/ui/index.js CHANGED
@@ -1,899 +1,65 @@
1
- import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /**
3
3
  * UI Module - Entry Point
4
4
  *
5
- * TerminalChat (main component), App wrapper, printBanner, startInkCLI.
6
- * Imports extracted modules and wires state through context bags.
5
+ * TerminalChat (composition), App wrapper, printBanner, startInkCLI. All state
6
+ * and orchestration live in useChatController; the JSX here just wires the four
7
+ * memoized regions together inside the HUD frame.
7
8
  */
8
- import React, { useState, useCallback, useRef, useEffect } from 'react';
9
- import { render, Box, Text, useApp, useStdout } from 'ink';
10
- import * as fs from 'fs';
9
+ import { useEffect } from 'react';
10
+ import { render, Box } from 'ink';
11
11
  import * as config from '../config.js';
12
- import { selectProvider } from '../providers/index.js';
13
- import { getSystemPrompt, DEFAULT_MODELS, supportsVision } from '../types.js';
12
+ import { selectProvider, ProviderUnavailableError } from '../providers/index.js';
13
+ import { DEFAULT_MODELS } from '../types.js';
14
14
  import { getVersion } from '../version-check.js';
15
- import { getModelContextLimit, preWarmModelCache } from '../model-detection.js';
16
- import { detectComplexity } from '../risk.js';
17
- import * as storage from '../storage.js';
18
- import { parseFileReferences, processFilesForMessage, formatFileInfo } from '../files.js';
19
- import * as memory from '../memory.js';
20
- import * as hooks from '../hooks.js';
21
- import { getCurrentSkin, getCurrentPalette, paletteColorize, applySkin, applyPalette } from '../hud/api.js';
15
+ import { getCurrentSkin, paletteColorize } from '../hud/api.js';
22
16
  import { renderColoredBanner, renderSplashAnimation, renderTransition, colorFg } from '../terminal-image.js';
17
+ import { fleetPostOffline } from '../fleet.js';
23
18
  import { HUDFrame } from './frame.js';
24
- import { getCurrentCompanion, applyCompanion, setEmojiConfig } from '../companions.js';
25
- import { CircuitBreaker } from '../circuit-breaker.js';
26
- import { IterationLedger } from '../iteration-ledger.js';
27
- import { getDefaultSmartRoutingConfig } from '../smart-router.js';
28
- import * as recording from '../terminal-recording.js';
29
- import * as sessionTimeout from '../session-timeout.js';
30
- import * as idleEviction from '../idle-eviction.js';
31
- import { isTmux, getTmuxInfo } from '../tmux.js';
32
19
  import { ErrorBoundary } from './error-boundary.js';
33
- import { ThinkingDisplay, ProcessingIndicator, StreamingIndicator, StateTransition } from './components.js';
34
- import { MessageHistory } from './messages.js';
35
- import { ModelSelector, SessionSelector, UpgradePrompt, ComplexityWarning, SessionResumePrompt, KeybindingsModal, } from './modals.js';
36
- import { ThemePicker } from './theme-picker.js';
37
- import { PackPicker } from './pack-picker.js';
38
- import { applyThemePack, getCurrentPack, getCompanionMode, getThemePack } from '../hud/theme-packs/api.js';
39
- import { ChatInput } from './chat-input.js';
40
- import { StatusBar } from './status-bar.js';
41
- import { handleCommand } from './commands.js';
42
- import { runAgentImpl, runLoopImpl, validateAndRepairMessagesImpl } from './agent.js';
43
- import { resolveIterationLimit } from '../iteration-limit.js';
44
- // Wire emoji config at module load (breaks circular dep: companions → config)
45
- setEmojiConfig(config);
46
- // Module-level state for agterm mode
47
- let moduleAgtermEnabled = false;
48
- // Debug logging for flow control issues
49
- let debugEnabled = process.env.CALLIOPE_DEBUG === '1';
50
- const debugLog = (label, ...args) => {
51
- if (debugEnabled) {
52
- const timestamp = new Date().toISOString().split('T')[1].slice(0, 12);
53
- console.error(`[${timestamp}] ${label}:`, ...args);
54
- }
55
- };
56
- // ============================================================================
57
- // Main Chat Component
58
- // ============================================================================
59
- function TerminalChat() {
60
- const { exit } = useApp();
61
- const { stdout } = useStdout();
62
- // Reactive terminal width - re-renders on resize via SIGWINCH
63
- const [width, setWidth] = useState(() => stdout?.columns || 80);
20
+ import { spawnPendingRestart } from './self-restart.js';
21
+ import { useChatController } from './state/use-chat-controller.js';
22
+ import { TranscriptRegion } from './regions/transcript-region.js';
23
+ import { StatusRegion } from './regions/status-region.js';
24
+ import { InputRegion } from './regions/input-region.js';
25
+ import { ModalHost } from './regions/modal-host.js';
26
+ import { probeMount } from './regions/render-probe.js';
27
+ export function TerminalChat({ controllerRef }) {
28
+ const c = useChatController();
29
+ // Mount counter for the reset-without-remount assertion (no-op in production).
30
+ useEffect(() => { probeMount('terminal-chat'); }, []);
31
+ // Expose resetSession for tests/automation; production renders without a ref.
64
32
  useEffect(() => {
65
- const onResize = () => {
66
- const cols = stdout?.columns || process.stdout.columns || 80;
67
- setWidth(cols);
68
- };
69
- process.stdout.on('resize', onResize);
70
- return () => { process.stdout.off('resize', onResize); };
71
- }, [stdout]);
72
- // Core state
73
- const [input, setInput] = useState('');
74
- const [suggestions, setSuggestions] = useState([]);
75
- const [messages, setMessages] = useState([]);
76
- const [isProcessing, setIsProcessing] = useState(false);
77
- const [thinkingState, setThinkingState] = useState(null);
78
- const [streamingResponse, setStreamingResponse] = useState('');
79
- const [activityState, setActivityState] = useState(null);
80
- // State transition tracking
81
- const prevProcessingState = useRef('idle');
82
- const [transition, setTransition] = useState(null);
83
- useEffect(() => {
84
- const current = isProcessing && thinkingState && !streamingResponse ? 'thinking' :
85
- isProcessing && streamingResponse ? 'streaming' :
86
- !isProcessing && prevProcessingState.current !== 'idle' ? 'done' : 'idle';
87
- if (current !== prevProcessingState.current) {
88
- const from = prevProcessingState.current;
89
- // Only show transitions for meaningful state changes
90
- if (from !== 'idle' || current !== 'idle') {
91
- setTransition({ from, to: current });
92
- }
93
- prevProcessingState.current = current;
94
- }
95
- }, [isProcessing, thinkingState, streamingResponse]);
96
- // Input history for up/down arrow navigation
97
- const [inputHistory, setInputHistory] = useState([]);
98
- const [historyIndex, setHistoryIndex] = useState(-1);
99
- const [savedInput, setSavedInput] = useState(''); // Save current input when navigating
100
- // Smart suggestions context
101
- const [hasGitRepo] = useState(() => {
102
- try {
103
- return fs.existsSync('.git') || fs.existsSync('../.git');
104
- }
105
- catch {
106
- return false;
107
- }
108
- });
109
- const recentCommands = React.useMemo(() => inputHistory.filter(cmd => cmd.startsWith('/')).slice(-10), [inputHistory]);
110
- // Clear suggestions when input changes significantly
111
- const handleInputChange = useCallback((newValue) => {
112
- setInput(newValue);
113
- // Clear suggestions if user clears input or submits
114
- if (!newValue || !newValue.startsWith('/')) {
115
- setSuggestions([]);
116
- }
117
- // Reset history navigation when user types
118
- setHistoryIndex(-1);
119
- }, []);
120
- // Navigate input history
121
- const navigateHistory = useCallback((direction) => {
122
- if (inputHistory.length === 0)
33
+ if (!controllerRef)
123
34
  return;
124
- if (direction === 'up') {
125
- if (historyIndex === -1) {
126
- // Save current input before navigating
127
- setSavedInput(input);
128
- setHistoryIndex(inputHistory.length - 1);
129
- setInput(inputHistory[inputHistory.length - 1]);
130
- }
131
- else if (historyIndex > 0) {
132
- setHistoryIndex(historyIndex - 1);
133
- setInput(inputHistory[historyIndex - 1]);
134
- }
135
- }
136
- else {
137
- if (historyIndex === -1)
138
- return;
139
- if (historyIndex < inputHistory.length - 1) {
140
- setHistoryIndex(historyIndex + 1);
141
- setInput(inputHistory[historyIndex + 1]);
142
- }
143
- else {
144
- // Return to saved input
145
- setHistoryIndex(-1);
146
- setInput(savedInput);
147
- }
148
- }
149
- }, [inputHistory, historyIndex, input, savedInput]);
150
- // Add to history when submitting
151
- const addToHistory = useCallback((value) => {
152
- if (value.trim() && (inputHistory.length === 0 || inputHistory[inputHistory.length - 1] !== value)) {
153
- setInputHistory(prev => [...prev.slice(-100), value]); // Keep last 100 entries
154
- }
155
- setHistoryIndex(-1);
156
- setSavedInput('');
157
- }, [inputHistory]);
158
- // Config state
159
- // Use lazy initializers to avoid calling config.get() on every render
160
- const [provider, setProvider] = useState(() => process.env.CALLIOPE_PROVIDER || config.get('defaultProvider'));
161
- const [model, setModel] = useState(() => process.env.CALLIOPE_MODEL || config.get('defaultModel'));
162
- const [persona, setPersona] = useState(() => config.get('persona'));
163
- const [mode, setMode] = useState('hybrid'); // Default to hybrid mode
164
- const [confirmMode, setConfirmMode] = useState(true); // Require confirmation for risky ops
165
- const [layout, setLayout] = useState(() => config.get('layout') || 'response-bottom');
166
- const [density, setDensity] = useState(() => config.get('density') || 'normal');
167
- const [collapseSettings, setCollapseSettings] = useState(() => ({
168
- collapseTools: config.get('collapseTools') ?? false,
169
- collapseThinking: config.get('collapseThinking') ?? false,
170
- toolDisplayLimit: config.get('toolDisplayLimit') ?? 0,
171
- }));
172
- // Modal state
173
- const [modalMode, setModalMode] = useState('none');
174
- const [pendingComplexPrompt, setPendingComplexPrompt] = useState(null);
175
- const [previousSession, setPreviousSession] = useState(null);
176
- const [pendingToolCall, setPendingToolCall] = useState(null);
177
- const [availableModels, setAvailableModels] = useState([]);
178
- const [availableSessions, setAvailableSessions] = useState([]);
179
- const [latestVersion, setLatestVersion] = useState(null);
180
- // Stats
181
- const [stats, setStats] = useState({
182
- inputTokens: 0,
183
- outputTokens: 0,
184
- cost: 0,
185
- messageCount: 0,
186
- });
187
- const [contextTokens, setContextTokens] = useState(0);
188
- // Message queue for human-in-the-loop feedback during processing
189
- const [queuedMessages, setQueuedMessages] = useState([]);
190
- const queuedMessagesRef = useRef([]); // Ref to avoid stale closure in runAgent
191
- const [queueInput, setQueueInput] = useState('');
192
- const [editingQueueIndex, setEditingQueueIndex] = useState(null);
193
- // Keep ref in sync with state
194
- useEffect(() => {
195
- queuedMessagesRef.current = queuedMessages;
196
- }, [queuedMessages]);
197
- // Undo/Redo history - stores snapshots of conversation state
198
- const undoStack = useRef([]);
199
- const redoStack = useRef([]);
200
- const MAX_UNDO_HISTORY = 10;
201
- // Conversation bookmarks
202
- const [bookmarks, setBookmarks] = useState([]);
203
- // Prompt templates
204
- const [templates, setTemplates] = useState([]);
205
- // Save state before changes (call before modifying messages)
206
- const saveUndoState = useCallback(() => {
207
- undoStack.current.push({
208
- messages: [...messages],
209
- llmMessages: [...llmMessages.current],
210
- timestamp: new Date(),
211
- });
212
- // Limit stack size
213
- if (undoStack.current.length > MAX_UNDO_HISTORY) {
214
- undoStack.current.shift();
215
- }
216
- // Clear redo stack on new action
217
- redoStack.current = [];
218
- }, [messages]);
219
- // LLM conversation history
220
- const llmMessages = useRef([
221
- { role: 'system', content: getSystemPrompt(persona) }
222
- ]);
223
- // Keep system prompt in sync when persona changes (fixes #46 - persona lost on model fallback)
224
- useEffect(() => {
225
- const firstMsg = llmMessages.current[0];
226
- if (firstMsg && firstMsg.role === 'system') {
227
- // Preserve any appended memory context
228
- const currentContent = typeof firstMsg.content === 'string' ? firstMsg.content : '';
229
- const memoryIdx = currentContent.indexOf('\n\n--- Project Context ---\n');
230
- const memoryPart = memoryIdx >= 0 ? currentContent.slice(memoryIdx) : '';
231
- llmMessages.current[0] = {
232
- role: 'system',
233
- content: getSystemPrompt(persona) + memoryPart,
234
- };
235
- }
236
- }, [persona]);
237
- // Estimate context tokens (conservative: ~2.5 chars per token + 1.35x overhead)
238
- const estimateContextTokens = useCallback(() => {
239
- let chars = 0;
240
- let msgCount = 0;
241
- for (const msg of llmMessages.current) {
242
- msgCount++;
243
- if (typeof msg.content === 'string') {
244
- chars += msg.content.length;
245
- }
246
- else if (Array.isArray(msg.content)) {
247
- for (const block of msg.content) {
248
- if (block.type === 'text') {
249
- chars += block.text.length;
250
- }
251
- else if (block.type === 'image') {
252
- chars += 1000; // Images count as ~250 tokens
253
- }
254
- }
255
- }
256
- // Include tool call arguments in estimation
257
- if (msg.toolCalls) {
258
- for (const tool of msg.toolCalls) {
259
- chars += JSON.stringify(tool.arguments || {}).length;
260
- }
261
- }
262
- }
263
- // Conservative: 2.5 chars/token, 1.35x overhead for formatting/metadata, +50 per message
264
- return Math.round((chars / 2.5) * 1.35 + msgCount * 50);
265
- }, []);
266
- // Session state
267
- const sessionRef = useRef(null);
268
- const [autoRoute, setAutoRoute] = useState(false); // Auto model routing
269
- const [smartRouteActive, setSmartRouteActive] = useState(() => config.get('smartRoutingEnabled') ?? false);
270
- const [breakerHealth, setBreakerHealth] = useState('ok');
271
- const ledgerRef = useRef(new IterationLedger());
272
- const circuitBreakerRef = useRef(config.get('circuitBreakersEnabled') !== false ? (() => {
273
- const iterTimeSec = config.get('maxIterationTime');
274
- const cb = new CircuitBreaker();
275
- if (typeof iterTimeSec === 'number' && iterTimeSec > 0) {
276
- cb.adjust('wall-clock', { maxIterationDurationMs: iterTimeSec * 1000 });
277
- }
278
- // Local/free providers: disable cost breaker, relax token limits
279
- const prov = config.get('defaultProvider');
280
- if (prov === 'ollama' || prov === 'litellm') {
281
- cb.adjust('cost-runaway', { maxSessionCost: 999999, maxCostPerMinute: 999999 });
282
- cb.adjust('token-burn', { maxTokensPerIteration: 500_000, maxTotalTokens: 20_000_000 });
283
- }
284
- return cb;
285
- })() : null);
286
- const smartRoutingConfigRef = useRef({
287
- ...getDefaultSmartRoutingConfig(),
288
- enabled: config.get('smartRoutingEnabled') ?? false,
289
- costSensitivity: config.get('smartRoutingCostSensitivity') ?? 0.3,
290
- });
291
- const [memoryLoaded, setMemoryLoaded] = useState(false);
292
- // Agent loop state
293
- const [loopActive, setLoopActive] = useState(false);
294
- const [loopPrompt, setLoopPrompt] = useState('');
295
- const [loopMaxIterations, setLoopMaxIterations] = useState(() => resolveIterationLimit(config.get('maxIterations')));
296
- const [loopCompletionPromise, setLoopCompletionPromise] = useState();
297
- const [loopIteration, setLoopIteration] = useState(0);
298
- const loopCancelledRef = useRef(false);
299
- // Initialize session and load memory on mount
300
- useEffect(() => {
301
- const cwd = process.cwd();
302
- // Check for existing session with messages
303
- const existingSessions = storage.listSessions(5);
304
- const recentSession = existingSessions.find(s => s.projectPath === cwd &&
305
- s.messageCount > 0 &&
306
- Date.now() - new Date(s.lastAccessedAt).getTime() < 24 * 60 * 60 * 1000 // Within 24 hours
307
- );
308
- if (recentSession && !sessionRef.current) {
309
- // Offer to resume
310
- setPreviousSession({
311
- projectName: recentSession.projectName,
312
- lastAccessedAt: recentSession.lastAccessedAt,
313
- messageCount: recentSession.messageCount,
314
- });
315
- setModalMode('session-resume');
316
- }
317
- const session = storage.getOrCreateSession(cwd);
318
- sessionRef.current = session;
319
- ledgerRef.current.setRetentionLimit(config.get('sessionLogLimit') ?? 0);
320
- ledgerRef.current.setOnChange(() => {
321
- const activeSessionId = sessionRef.current?.id;
322
- if (activeSessionId) {
323
- storage.saveIterationLedger(ledgerRef.current, activeSessionId);
324
- }
325
- });
326
- ledgerRef.current.loadSnapshot(storage.loadIterationLedger(session.id));
327
- storage.saveIterationLedger(ledgerRef.current, session.id);
328
- // Load memory context into system prompt
329
- if (!memoryLoaded) {
330
- const cwdMem = process.cwd();
331
- const memoryContext = memory.buildMemoryContext(cwdMem);
332
- if (memoryContext.trim()) {
333
- // Append memory context to system prompt
334
- const currentSystem = llmMessages.current[0];
335
- if (currentSystem && currentSystem.role === 'system') {
336
- const systemContent = typeof currentSystem.content === 'string'
337
- ? currentSystem.content
338
- : '';
339
- llmMessages.current[0] = {
340
- role: 'system',
341
- content: systemContent + '\n\n--- Project Context ---\n' + memoryContext,
342
- };
343
- }
344
- }
345
- setMemoryLoaded(true);
346
- // Execute session start hooks
347
- hooks.executeHooks('session-start', {}).catch((err) => {
348
- debugLog('hooks', 'session-start hook failed:', err instanceof Error ? err.message : err);
349
- });
350
- // Start session recording (audit log) — respects config
351
- recording.setRecordingEnabled(config.get('recordSessions') !== false);
352
- recording.setRetentionDays(config.get('recordingRetentionDays') ?? 0);
353
- recording.startRecording({
354
- provider: selectProvider(provider),
355
- model: model || DEFAULT_MODELS[selectProvider(provider)],
356
- cwd: cwdMem,
357
- });
358
- // Configure session timeout (opt-in via config)
359
- const timeoutMs = config.get('sessionTimeoutMs');
360
- if (timeoutMs) {
361
- sessionTimeout.configureTimeout({
362
- enabled: true,
363
- idleTimeoutMs: typeof timeoutMs === 'number' ? timeoutMs : 2 * 60 * 60 * 1000,
364
- });
365
- sessionTimeout.onTimeout((type) => {
366
- if (type === 'warning') {
367
- addMessage('system', `\u23f1\ufe0f Session will timeout in ${sessionTimeout.formatTimeRemaining()}`);
368
- }
369
- else {
370
- addMessage('system', '\ud83d\udeaa Session timeout. Saving and exiting...');
371
- storage.saveMessageHistory(llmMessages.current);
372
- }
373
- });
374
- }
375
- // Start idle eviction monitor
376
- idleEviction.configureEviction({ enabled: true });
377
- idleEviction.onEviction((action) => {
378
- if (action === 'auto-save') {
379
- storage.saveMessageHistory(llmMessages.current);
380
- }
381
- });
382
- // Log tmux context if applicable
383
- if (isTmux()) {
384
- const info = getTmuxInfo();
385
- if (info) {
386
- debugLog('tmux', `session=${info.session}, windows=${info.windows}, panes=${info.panes}`);
387
- }
388
- }
389
- // Load templates from storage
390
- const savedTemplates = storage.getTemplates();
391
- if (savedTemplates.length > 0) {
392
- setTemplates(savedTemplates.map(t => ({
393
- name: t.name,
394
- prompt: t.prompt,
395
- createdAt: new Date(t.createdAt),
396
- })));
397
- }
398
- // Pre-warm model cache in background for faster model switching
399
- preWarmModelCache().catch((err) => {
400
- debugLog('cache', 'model cache pre-warm failed:', err instanceof Error ? err.message : err);
401
- });
402
- }
403
- }, [memoryLoaded]);
404
- // Derived values
405
- const actualProvider = selectProvider(provider);
406
- const actualModel = model || DEFAULT_MODELS[actualProvider];
407
- const isModalActive = modalMode !== 'none';
408
- // Add message helper
409
- const addMessage = useCallback((type, content) => {
410
- setMessages(prev => [...prev, {
411
- id: `${Date.now()}-${Math.random().toString(36).slice(2)}`,
412
- type,
413
- content
414
- }]);
415
- // Persist user and assistant messages to storage for session history
416
- if (type === 'user' || type === 'assistant') {
417
- storage.addChatMessage({ role: type, content });
418
- }
419
- }, []);
420
- // Handler to edit or delete a queued message
421
- const handleEditQueuedMessage = useCallback((index, newMsg) => {
422
- if (newMsg === '') {
423
- // Delete the message
424
- setQueuedMessages(prev => prev.filter((_, i) => i !== index));
425
- addMessage('system', `🗑️ Deleted queued message #${index + 1}`);
426
- }
427
- else {
428
- // Update the message
429
- setQueuedMessages(prev => prev.map((msg, i) => i === index ? newMsg : msg));
430
- addMessage('system', `✏️ Updated queued message #${index + 1}`);
431
- }
432
- }, [addMessage]);
433
- // Validate and repair message history
434
- const validateAndRepairMessages = useCallback(() => {
435
- return validateAndRepairMessagesImpl({
436
- llmMessages,
437
- addMessage,
438
- debugLog,
439
- });
440
- }, [addMessage]);
441
- // Build agent context
442
- const buildAgentContext = useCallback(() => ({
443
- provider,
444
- model,
445
- mode,
446
- confirmMode,
447
- autoRoute,
448
- actualProvider,
449
- actualModel,
450
- stats,
451
- agtermEnabled: moduleAgtermEnabled,
452
- ledger: ledgerRef.current,
453
- circuitBreaker: circuitBreakerRef.current || undefined,
454
- smartRouteActive,
455
- smartRoutingConfig: smartRoutingConfigRef.current,
456
- setBreakerHealth,
457
- setStats,
458
- setStreamingResponse,
459
- setThinkingState,
460
- setActivityState,
461
- setContextTokens,
462
- setIsProcessing,
463
- setQueuedMessages,
464
- setEditingQueueIndex,
465
- setLoopIteration,
466
- setLoopActive,
467
- llmMessages,
468
- queuedMessagesRef,
469
- loopCancelledRef,
470
- sessionRef,
471
- addMessage,
472
- estimateContextTokens,
473
- validateAndRepairMessages,
474
- debugLog,
475
- }), [provider, model, mode, confirmMode, autoRoute, smartRouteActive, actualProvider, actualModel, stats, addMessage, estimateContextTokens, validateAndRepairMessages]);
476
- // Run agent with user prompt
477
- const runAgent = useCallback(async (content) => {
478
- const ctx = buildAgentContext();
479
- await runAgentImpl(ctx, content);
480
- }, [buildAgentContext]);
481
- // Agent loop - runs prompt repeatedly until completion promise or max iterations
482
- const runLoop = useCallback(async (prompt, maxIter, completionPromise) => {
483
- const ctx = buildAgentContext();
484
- await runLoopImpl(ctx, prompt, maxIter, completionPromise);
485
- }, [buildAgentContext]);
486
- // Build command context
487
- const buildCommandContext = useCallback(() => ({
488
- actualProvider,
489
- actualModel,
490
- provider,
491
- model,
492
- persona,
493
- mode,
494
- confirmMode,
495
- autoRoute,
496
- layout,
497
- density,
498
- collapseSettings,
499
- messages,
500
- stats,
501
- loopActive,
502
- isProcessing,
503
- thinkingState,
504
- streamingResponse,
505
- queuedMessages,
506
- bookmarks,
507
- templates,
508
- agtermEnabled: moduleAgtermEnabled,
509
- debugEnabled,
510
- modalMode,
511
- circuitBreaker: circuitBreakerRef.current || undefined,
512
- smartRouteActive,
513
- smartRoutingConfig: smartRoutingConfigRef.current,
514
- ledger: ledgerRef.current,
515
- setProvider,
516
- setModel,
517
- setPersona,
518
- setMode,
519
- setConfirmMode,
520
- setAutoRoute,
521
- setLayout: setLayout,
522
- setDensity: setDensity,
523
- setCollapseSettings,
524
- setMessages,
525
- setStats,
526
- setModalMode: setModalMode,
527
- setPendingComplexPrompt,
528
- setAvailableModels,
529
- setAvailableSessions,
530
- setLatestVersion,
531
- setLoopActive,
532
- setLoopPrompt,
533
- setLoopMaxIterations,
534
- setLoopCompletionPromise,
535
- setLoopIteration,
536
- setIsProcessing,
537
- setThinkingState,
538
- setStreamingResponse,
539
- setQueuedMessages,
540
- setInput,
541
- setBookmarks,
542
- setTemplates,
543
- setContextTokens,
544
- setDebugEnabled: (v) => { debugEnabled = v; },
545
- setSmartRouteActive,
546
- setBreakerHealth,
547
- llmMessages,
548
- undoStack,
549
- redoStack,
550
- loopCancelledRef,
551
- sessionRef,
552
- addMessage,
553
- estimateContextTokens,
554
- saveUndoState,
555
- runAgent,
556
- runLoop,
557
- exit,
558
- }), [actualProvider, actualModel, provider, model, persona, mode, confirmMode, autoRoute, smartRouteActive,
559
- layout, density, collapseSettings, messages, stats, loopActive, isProcessing,
560
- thinkingState, streamingResponse, queuedMessages, bookmarks, templates, modalMode,
561
- addMessage, estimateContextTokens, saveUndoState, runAgent, runLoop, exit]);
562
- // Handle slash commands
563
- const handleCommandWrapped = useCallback(async (cmd) => {
564
- const ctx = buildCommandContext();
565
- await handleCommand(cmd, ctx);
566
- }, [buildCommandContext]);
567
- // Handle input submission
568
- const handleSubmit = useCallback(async (value) => {
569
- const trimmed = value.trim();
570
- if (!trimmed || isProcessing)
571
- return;
572
- // Record activity for timeout/eviction and audit log
573
- sessionTimeout.recordActivity();
574
- idleEviction.recordActivity();
575
- recording.recordEvent('input', trimmed);
576
- // Add to history for up/down arrow navigation
577
- addToHistory(trimmed);
578
- setInput('');
579
- if (trimmed.startsWith('/')) {
580
- await handleCommandWrapped(trimmed);
581
- return;
582
- }
583
- // ! prefix executes shell commands directly
584
- if (trimmed.startsWith('!')) {
585
- const shellCmd = trimmed.slice(1).trim();
586
- if (shellCmd) {
587
- addMessage('system', `$ ${shellCmd}`);
588
- try {
589
- const { execSync } = await import('child_process');
590
- const activeCwd = sessionRef.current?.projectPath ?? process.cwd();
591
- const output = execSync(shellCmd, {
592
- cwd: activeCwd,
593
- encoding: 'utf-8',
594
- timeout: 30000,
595
- stdio: ['pipe', 'pipe', 'pipe'],
596
- maxBuffer: 10 * 1024 * 1024,
597
- }).trim();
598
- addMessage('system', output || '(no output)');
599
- }
600
- catch (err) {
601
- const execErr = err;
602
- addMessage('error', execErr.stderr?.trim() || execErr.message || String(err));
603
- }
604
- }
605
- return;
606
- }
607
- // In hybrid mode, check for complex operations
608
- if (mode === 'hybrid') {
609
- const complexity = detectComplexity(trimmed);
610
- if (complexity.isComplex) {
611
- setPendingComplexPrompt({ prompt: trimmed, complexity });
612
- setModalMode('complexity-warning');
613
- return;
614
- }
615
- }
616
- // Save state for undo before modifying conversation
617
- saveUndoState();
618
- // Parse file references from input
619
- const activeCwd = sessionRef.current?.projectPath ?? process.cwd();
620
- const { text: cleanText, files } = parseFileReferences(trimmed, activeCwd);
621
- // Show user message (with file info if any)
622
- if (files.length > 0) {
623
- const fileInfo = formatFileInfo(files);
624
- addMessage('user', `${cleanText}\n📎 ${fileInfo}`);
625
- }
626
- else {
627
- addMessage('user', trimmed);
628
- }
629
- setIsProcessing(true);
630
- try {
631
- // Build message content (with file/image support)
632
- let messageContent;
633
- if (files.length > 0) {
634
- const visionSupported = supportsVision(provider, model);
635
- const { content, warnings } = processFilesForMessage(cleanText || trimmed, files, visionSupported);
636
- // Show any warnings about files
637
- for (const warning of warnings) {
638
- addMessage('system', warning);
639
- }
640
- messageContent = content;
641
- }
642
- else {
643
- messageContent = trimmed;
644
- }
645
- await runAgent(messageContent);
646
- }
647
- finally {
648
- setIsProcessing(false);
649
- setThinkingState(null);
650
- setStreamingResponse('');
651
- }
652
- }, [isProcessing, handleCommandWrapped, runAgent, addMessage, provider, model, saveUndoState, addToHistory, mode]);
653
- // Modal handlers
654
- const handleModelSelect = useCallback((selectedModel) => {
655
- setModel(selectedModel);
656
- addMessage('system', `Model: ${selectedModel}`);
657
- setModalMode('none');
658
- setAvailableModels([]);
659
- }, [addMessage]);
660
- const handleModalCancel = useCallback(() => {
661
- setModalMode('none');
662
- setAvailableModels([]);
663
- setLatestVersion(null);
664
- }, []);
665
- const handleUpgradeConfirm = useCallback(async () => {
666
- setModalMode('none');
667
- addMessage('system', 'Upgrading...');
668
- try {
669
- const { performUpgrade } = await import('../version-check.js');
670
- const success = await performUpgrade();
671
- if (success) {
672
- addMessage('system', 'Upgrade complete! Restarting...');
673
- const { spawn } = await import('child_process');
674
- const child = spawn(process.argv[0], process.argv.slice(1), {
675
- stdio: 'inherit',
676
- detached: true,
677
- });
678
- child.unref();
679
- process.exit(0);
680
- }
681
- else {
682
- addMessage('error', 'Upgrade failed. Try: npm install -g @calliopelabs/cli@latest');
683
- }
684
- }
685
- catch (e) {
686
- addMessage('error', `Upgrade failed: ${e instanceof Error ? e.message : String(e)}`);
687
- }
688
- setLatestVersion(null);
689
- }, [addMessage]);
690
- // Cycle through modes
691
- const cycleMode = useCallback(() => {
692
- setMode(current => {
693
- const modes = ['plan', 'hybrid', 'work'];
694
- const idx = modes.indexOf(current);
695
- const next = modes[(idx + 1) % modes.length];
696
- return next;
697
- });
698
- }, []);
699
- // Handle Escape key - cancel operation if processing, otherwise show hint
700
- const handleEscape = useCallback(() => {
701
- if (isProcessing) {
702
- // Cancel current operation
703
- setIsProcessing(false);
704
- setThinkingState(null);
705
- setStreamingResponse('');
706
- setLoopActive(false);
707
- setEditingQueueIndex(null);
708
- addMessage('system', '⏹ Operation cancelled. Use /exit to quit.');
709
- }
710
- else if (modalMode !== 'none') {
711
- // Close any open modal
712
- setModalMode('none');
713
- setPendingComplexPrompt(null);
714
- }
715
- else {
716
- // Not processing - show hint instead of exiting
717
- addMessage('system', '💡 Use /exit to quit, or Ctrl+C.');
718
- }
719
- }, [isProcessing, modalMode, addMessage]);
720
- // Handle direct send (Shift+Enter) - interrupts current operation and sends immediately
721
- const handleDirectSend = useCallback((msg) => {
722
- // Stop current processing
723
- setIsProcessing(false);
724
- setThinkingState(null);
725
- setStreamingResponse('');
726
- setEditingQueueIndex(null);
727
- // Show what happened
728
- addMessage('system', '⚡ Direct send - interrupting current operation');
729
- addMessage('user', msg);
730
- // Start new agent run with this message
731
- setIsProcessing(true);
732
- runAgent(msg).finally(() => {
733
- setIsProcessing(false);
734
- setThinkingState(null);
735
- setStreamingResponse('');
736
- setEditingQueueIndex(null);
737
- });
738
- }, [addMessage, runAgent]);
739
- // Streaming response component (reused across layouts)
740
- const StreamingResponseBox = streamingResponse ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "cyan", children: ["\u2727 ", getCurrentCompanion().name, ":"] }), streamingResponse.split('\n').map((line, i) => (_jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "\u2502" }), " ", line] }, i))), _jsx(Text, { color: "cyan", children: "\u258C" })] })) : null;
741
- // Thinking/Processing indicator component with state transitions
742
- const ProcessingBox = (_jsxs(_Fragment, { children: [transition && (_jsx(StateTransition, { from: transition.from, to: transition.to, onComplete: () => setTransition(null) })), isProcessing && thinkingState && !streamingResponse && _jsx(ThinkingDisplay, { state: thinkingState }), isProcessing && !thinkingState && !streamingResponse && _jsx(ProcessingIndicator, { label: "Waiting for response" }), isProcessing && streamingResponse && _jsx(StreamingIndicator, { activity: activityState ?? undefined })] }));
743
- // Render based on layout
744
- return (_jsx(HUDFrame, { width: width, children: _jsxs(Box, { flexDirection: "column", width: width, children: [layout === 'split' && (_jsxs(Box, { flexDirection: "row", width: width, children: [_jsxs(Box, { flexDirection: "column", width: "50%", children: [_jsx(Text, { color: "yellow", dimColor: true, children: "\u2500 Tools \u2500" }), _jsx(MessageHistory, { messages: messages, collapseSettings: collapseSettings }), ProcessingBox] }), _jsxs(Box, { flexDirection: "column", width: "50%", borderStyle: "single", borderLeft: true, borderColor: "gray", children: [_jsx(Text, { color: "cyan", dimColor: true, children: "\u2500 Response \u2500" }), StreamingResponseBox] })] })), layout === 'classic' && (_jsxs(_Fragment, { children: [_jsx(MessageHistory, { messages: messages, collapseSettings: collapseSettings }), ProcessingBox, StreamingResponseBox] })), layout === 'response-top' && (_jsxs(_Fragment, { children: [StreamingResponseBox, _jsx(MessageHistory, { messages: messages, collapseSettings: collapseSettings }), ProcessingBox] })), layout === 'response-bottom' && (_jsxs(_Fragment, { children: [_jsx(MessageHistory, { messages: messages, collapseSettings: collapseSettings }), ProcessingBox, StreamingResponseBox] })), layout === 'zen' && (_jsxs(_Fragment, { children: [_jsx(MessageHistory, { messages: messages.filter(m => m.type === 'user' || m.type === 'assistant'), collapseSettings: { collapseTools: true, collapseThinking: true, toolDisplayLimit: 0 } }), ProcessingBox, StreamingResponseBox] })), layout === 'focus' && (_jsxs(_Fragment, { children: [StreamingResponseBox, ProcessingBox, _jsx(MessageHistory, { messages: messages, collapseSettings: { collapseTools: true, collapseThinking: true, toolDisplayLimit: 3 } })] })), layout === 'dashboard' && (_jsxs(_Fragment, { children: [_jsxs(Text, { dimColor: true, children: [' ', stats.inputTokens ? `tokens: ${stats.inputTokens}/${stats.outputTokens}` : '', stats.cost ? ` | cost: $${stats.cost.toFixed(4)}` : '', model ? ` | ${model}` : '', ` | ${getCurrentCompanion().name}`] }), StreamingResponseBox, ProcessingBox, _jsx(MessageHistory, { messages: messages, collapseSettings: collapseSettings })] })), layout === 'minimal' && (_jsxs(_Fragment, { children: [_jsx(MessageHistory, { messages: messages, collapseSettings: collapseSettings }), ProcessingBox, StreamingResponseBox] })), debugEnabled && (_jsx(Box, { marginY: 0, children: _jsxs(Text, { dimColor: true, children: ["[dbg] proc=", isProcessing ? 'Y' : 'N', " think=", thinkingState ? 'Y' : 'N', " stream=", streamingResponse.length, " mode=", mode, " queue=", queuedMessages.length, " activity=", activityState?.action || 'none'] }) })), modalMode === 'model' && availableModels.length > 0 && (_jsx(ModelSelector, { models: availableModels, onSelect: handleModelSelect, onCancel: handleModalCancel })), modalMode === 'sessions' && (_jsx(SessionSelector, { sessions: availableSessions, onSelect: (session) => {
745
- // Load history from selected session
746
- addMessage('system', `Loading session: ${session.projectName}...`);
747
- addMessage('system', `Session path: ${session.projectPath}\nTo load this session, run calliope from that directory.`);
748
- setModalMode('none');
749
- }, onDelete: (session) => {
750
- if (storage.deleteSession(session.id)) {
751
- addMessage('system', `🗑️ Deleted session: ${session.projectName}`);
752
- // Refresh the list
753
- setAvailableSessions(prev => prev.filter(s => s.id !== session.id));
754
- }
755
- else {
756
- addMessage('error', `Failed to delete session: ${session.projectName}`);
757
- }
758
- }, onCancel: handleModalCancel })), modalMode === 'upgrade' && latestVersion && (_jsx(UpgradePrompt, { currentVersion: getVersion(), latestVersion: latestVersion, onConfirm: handleUpgradeConfirm, onCancel: handleModalCancel })), modalMode === 'session-resume' && previousSession && (_jsx(SessionResumePrompt, { session: previousSession, onResume: () => {
759
- const savedMessages = storage.loadMessageHistory();
760
- if (savedMessages && savedMessages.length > 0) {
761
- llmMessages.current.length = 0;
762
- for (const msg of savedMessages) {
763
- llmMessages.current.push(msg);
764
- }
765
- addMessage('system', `✓ Resumed session with ${savedMessages.length} saved messages loaded`);
766
- const activeSessionId = sessionRef.current?.id;
767
- if (activeSessionId) {
768
- ledgerRef.current.loadSnapshot(storage.loadIterationLedger(activeSessionId));
769
- storage.saveIterationLedger(ledgerRef.current, activeSessionId);
770
- }
771
- setContextTokens(estimateContextTokens());
772
- }
773
- else {
774
- const history = storage.getChatHistory(20);
775
- if (history.length > 0) {
776
- llmMessages.current.length = 0;
777
- const activeCwd = sessionRef.current?.projectPath ?? process.cwd();
778
- const basePrompt = getSystemPrompt(persona);
779
- const memoryContext = memory.buildMemoryContext(activeCwd);
780
- llmMessages.current.push({
781
- role: 'system',
782
- content: memoryContext.trim()
783
- ? `${basePrompt}\n\n--- Project Context ---\n${memoryContext}`
784
- : basePrompt,
785
- });
786
- for (const msg of history) {
787
- if (msg.role === 'user' || msg.role === 'assistant') {
788
- llmMessages.current.push({
789
- role: msg.role,
790
- content: msg.content,
791
- });
792
- }
793
- }
794
- addMessage('system', `✓ Resumed session with ${history.length} chat messages loaded`);
795
- setContextTokens(estimateContextTokens());
796
- }
797
- }
798
- setModalMode('none');
799
- setPreviousSession(null);
800
- }, onNew: () => {
801
- addMessage('system', '✓ Starting fresh session');
802
- setModalMode('none');
803
- setPreviousSession(null);
804
- } })), modalMode === 'complexity-warning' && pendingComplexPrompt && (_jsx(ComplexityWarning, { reason: pendingComplexPrompt.complexity.reason || 'Complex operation detected', prompt: typeof pendingComplexPrompt.prompt === 'string' ? pendingComplexPrompt.prompt : undefined, onProceed: async () => {
805
- setModalMode('none');
806
- const prompt = pendingComplexPrompt.prompt;
807
- setPendingComplexPrompt(null);
808
- // Proceed with execution
809
- saveUndoState();
810
- addMessage('user', typeof prompt === 'string' ? prompt : JSON.stringify(prompt));
811
- setIsProcessing(true);
812
- try {
813
- await runAgent(prompt);
814
- }
815
- finally {
816
- setIsProcessing(false);
817
- }
818
- }, onPlan: () => {
819
- setModalMode('none');
820
- const prompt = pendingComplexPrompt.prompt;
821
- setPendingComplexPrompt(null);
822
- // Switch to plan mode and proceed
823
- setMode('plan');
824
- addMessage('system', '📋 Switched to Plan mode - I\'ll describe what I would do without executing.');
825
- saveUndoState();
826
- addMessage('user', typeof prompt === 'string' ? prompt : JSON.stringify(prompt));
827
- setIsProcessing(true);
828
- runAgent(prompt).finally(() => setIsProcessing(false));
829
- }, onCancel: () => {
830
- setModalMode('none');
831
- setPendingComplexPrompt(null);
832
- addMessage('system', 'Operation cancelled.');
833
- } })), modalMode === 'keys' && (_jsx(KeybindingsModal, { onClose: () => setModalMode('none') })), modalMode === 'theme-picker' && (_jsx(ThemePicker, { currentLayout: layout, currentSkin: getCurrentSkin().name, currentPalette: getCurrentPalette().name, currentCompanion: getCurrentCompanion().name, onApply: (selection) => {
834
- // Apply all selections
835
- setLayout(selection.layout);
836
- config.set('layout', selection.layout);
837
- applySkin(selection.skin);
838
- config.set('activeSkin', selection.skin);
839
- applyPalette(selection.palette);
840
- config.set('activePalette', selection.palette);
841
- applyCompanion(selection.companion);
842
- config.set('activeCompanion', selection.companion);
843
- const changes = [];
844
- if (selection.layout !== layout)
845
- changes.push(`layout=${selection.layout}`);
846
- if (selection.skin !== getCurrentSkin().name)
847
- changes.push(`skin=${selection.skin}`);
848
- if (selection.palette !== getCurrentPalette().name)
849
- changes.push(`palette=${selection.palette}`);
850
- if (selection.companion !== getCurrentCompanion().name)
851
- changes.push(`companion=${selection.companion}`);
852
- addMessage('system', changes.length > 0
853
- ? `Theme applied: ${changes.join(', ')}`
854
- : 'Theme unchanged.');
855
- setModalMode('none');
856
- }, onCancel: () => setModalMode('none') })), modalMode === 'pack-picker' && (_jsx(PackPicker, { onApply: async (packName) => {
857
- setModalMode('none');
858
- // Run transition animation if defined
859
- const targetPack = getThemePack(packName);
860
- if (targetPack?.skin.splash?.transition) {
861
- await renderTransition(targetPack.skin.splash.transition);
862
- }
863
- const success = applyThemePack(packName, getCompanionMode());
864
- if (success) {
865
- const pack = getCurrentPack();
866
- config.set('activeThemePack', packName);
867
- config.set('activeSkin', pack.skin.name);
868
- config.set('activePalette', pack.palette.name);
869
- const companion = getCompanionMode() === 'professional'
870
- ? pack.companions.professional
871
- : pack.companions.immersive;
872
- config.set('activeCompanion', companion.name);
873
- addMessage('system', `Theme pack: ${packName}\n` +
874
- ` Skin: ${pack.skin.name}, Palette: ${pack.palette.name}, Companion: ${companion.name}\n` +
875
- ` "${companion.greeting}"`);
876
- }
877
- }, onCancel: () => setModalMode('none') })), _jsx(ChatInput, { value: input, onChange: handleInputChange, onSubmit: handleSubmit, onEscape: handleEscape, onCycleMode: cycleMode, disabled: isModalActive, isProcessing: isProcessing, queuedCount: queuedMessages.length, queuedMessages: queuedMessages, editingQueueIndex: editingQueueIndex, onQueueMessage: (msg) => {
878
- setQueuedMessages(prev => [...prev, msg]);
879
- addMessage('system', `📨 Queued: "${msg.substring(0, 50)}${msg.length > 50 ? '...' : ''}"`);
880
- }, onEditQueuedMessage: handleEditQueuedMessage, onSetEditingQueueIndex: setEditingQueueIndex, onDirectSend: handleDirectSend, cwd: process.cwd(), suggestions: suggestions, onSuggestionsChange: setSuggestions, onNavigateHistory: navigateHistory,
881
- // Smart suggestions context
882
- currentMode: mode, contextPercentage: Math.round((contextTokens / getModelContextLimit(actualProvider, actualModel)) * 100), recentCommands: recentCommands, hasGitRepo: hasGitRepo }), _jsx(StatusBar, { provider: actualProvider, model: actualModel, mode: mode, stats: stats, contextTokens: contextTokens, breakerHealth: config.get('circuitBreakersEnabled') !== false ? breakerHealth : undefined, smartRouteActive: smartRouteActive, width: width })] }) }));
35
+ controllerRef.current = { resetSession: c.resetSession };
36
+ return () => { controllerRef.current = null; };
37
+ }, [controllerRef, c.resetSession]);
38
+ return (_jsx(HUDFrame, { width: c.width, children: _jsxs(Box, { flexDirection: "column", width: c.width, children: [_jsx(TranscriptRegion, { ...c.transcript }), _jsx(ModalHost, { ...c.modal }), _jsx(InputRegion, { ...c.input }), _jsx(StatusRegion, { ...c.status })] }) }));
883
39
  }
884
40
  // ============================================================================
885
41
  // App Wrapper & Entry Point
886
42
  // ============================================================================
887
43
  function App() {
888
- const [resetKey, setResetKey] = React.useState(0);
889
- const handleReset = React.useCallback(() => {
890
- setResetKey(k => k + 1);
891
- }, []);
892
- return (_jsx(ErrorBoundary, { onReset: handleReset, children: _jsx(TerminalChat, {}, resetKey) }));
44
+ // The ErrorBoundary swaps in a fallback on a render crash; retrying clears its
45
+ // error state, which remounts TerminalChat fresh — no remount key needed.
46
+ return (_jsx(ErrorBoundary, { children: _jsx(TerminalChat, {}) }));
893
47
  }
894
48
  // Print banner before Ink takes over (stays fixed at top)
895
49
  export async function printBanner() {
896
- const provider = selectProvider(config.get('defaultProvider'));
50
+ const requested = config.get('defaultProvider');
51
+ // Never claim a provider that won't serve (#217). If the selected provider is
52
+ // unconfigured, show the real selection annotated as such rather than
53
+ // crashing the banner or pretending a working provider.
54
+ let provider;
55
+ let providerNote = '';
56
+ try {
57
+ provider = selectProvider(requested);
58
+ }
59
+ catch (err) {
60
+ provider = err instanceof ProviderUnavailableError ? err.provider : requested;
61
+ providerNote = ' (not configured — run calliope --setup)';
62
+ }
897
63
  const model = config.get('defaultModel') || DEFAULT_MODELS[provider];
898
64
  const skin = getCurrentSkin();
899
65
  const dim = '\x1b[2m';
@@ -941,17 +107,11 @@ export async function printBanner() {
941
107
  console.log();
942
108
  }
943
109
  }
944
- const companion = getCurrentCompanion();
945
- console.log(`${dim} v${getVersion()} | ${provider}:${model}${reset}`);
110
+ console.log(`${dim} v${getVersion()} | ${provider}:${model}${providerNote}${reset}`);
946
111
  console.log(`${dim} /help for commands | ESC to exit${reset}`);
947
- if (companion.greeting) {
948
- console.log(`${dim} ${companion.greeting}${reset}`);
949
- }
950
112
  console.log();
951
113
  }
952
114
  export async function startInkCLI(options = {}) {
953
- // Set module-level agterm state
954
- moduleAgtermEnabled = options.agtermEnabled ?? false;
955
115
  // Print banner BEFORE Ink starts - it stays fixed at the top
956
116
  await printBanner();
957
117
  const { waitUntilExit } = render(_jsx(App, {}), {
@@ -959,8 +119,7 @@ export async function startInkCLI(options = {}) {
959
119
  });
960
120
  await waitUntilExit();
961
121
  // Session cleanup
962
- recording.stopRecording();
963
- sessionTimeout.clearTimers();
964
- idleEviction.stopMonitor();
122
+ await fleetPostOffline();
123
+ await spawnPendingRestart();
965
124
  }
966
125
  //# sourceMappingURL=index.js.map