@calliopelabs/cli 2.5.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (490) hide show
  1. package/README.md +45 -661
  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/bin.d.ts +3 -7
  7. package/dist/bin.d.ts.map +1 -1
  8. package/dist/bin.js +56 -79
  9. package/dist/bin.js.map +1 -1
  10. package/dist/budget.d.ts +64 -0
  11. package/dist/budget.d.ts.map +1 -0
  12. package/dist/budget.js +157 -0
  13. package/dist/budget.js.map +1 -0
  14. package/dist/checkpoint.d.ts +63 -30
  15. package/dist/checkpoint.d.ts.map +1 -1
  16. package/dist/checkpoint.js +247 -160
  17. package/dist/checkpoint.js.map +1 -1
  18. package/dist/circuit-breaker/breaker.d.ts.map +1 -1
  19. package/dist/circuit-breaker/breaker.js.map +1 -1
  20. package/dist/config.d.ts +86 -81
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +236 -304
  23. package/dist/config.js.map +1 -1
  24. package/dist/cost.d.ts +114 -0
  25. package/dist/cost.d.ts.map +1 -0
  26. package/dist/cost.js +499 -0
  27. package/dist/cost.js.map +1 -0
  28. package/dist/diff.d.ts.map +1 -1
  29. package/dist/diff.js +11 -7
  30. package/dist/diff.js.map +1 -1
  31. package/dist/env-expansion.js.map +1 -1
  32. package/dist/errors.js +3 -3
  33. package/dist/errors.js.map +1 -1
  34. package/dist/files.js.map +1 -1
  35. package/dist/fleet.d.ts +30 -0
  36. package/dist/fleet.d.ts.map +1 -0
  37. package/dist/fleet.js +86 -0
  38. package/dist/fleet.js.map +1 -0
  39. package/dist/fuzzy-search.d.ts.map +1 -1
  40. package/dist/fuzzy-search.js +2 -1
  41. package/dist/fuzzy-search.js.map +1 -1
  42. package/dist/git-status.js.map +1 -1
  43. package/dist/headless.d.ts +1 -2
  44. package/dist/headless.d.ts.map +1 -1
  45. package/dist/headless.js +166 -24
  46. package/dist/headless.js.map +1 -1
  47. package/dist/hud/api.d.ts +3 -18
  48. package/dist/hud/api.d.ts.map +1 -1
  49. package/dist/hud/api.js +9 -352
  50. package/dist/hud/api.js.map +1 -1
  51. package/dist/hud/palettes.d.ts.map +1 -1
  52. package/dist/hud/palettes.js +0 -180
  53. package/dist/hud/palettes.js.map +1 -1
  54. package/dist/hud/skins.d.ts.map +1 -1
  55. package/dist/hud/skins.js +0 -263
  56. package/dist/hud/skins.js.map +1 -1
  57. package/dist/hud/types.d.ts +2 -5
  58. package/dist/hud/types.d.ts.map +1 -1
  59. package/dist/index.d.ts +1 -4
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +1 -4
  62. package/dist/index.js.map +1 -1
  63. package/dist/iteration-ledger.d.ts.map +1 -1
  64. package/dist/iteration-ledger.js +3 -2
  65. package/dist/iteration-ledger.js.map +1 -1
  66. package/dist/local-model.d.ts +150 -0
  67. package/dist/local-model.d.ts.map +1 -0
  68. package/dist/local-model.js +408 -0
  69. package/dist/local-model.js.map +1 -0
  70. package/dist/mcp.d.ts.map +1 -1
  71. package/dist/mcp.js +5 -2
  72. package/dist/mcp.js.map +1 -1
  73. package/dist/memory.d.ts.map +1 -1
  74. package/dist/memory.js +6 -4
  75. package/dist/memory.js.map +1 -1
  76. package/dist/model-detection.js +2 -2
  77. package/dist/model-detection.js.map +1 -1
  78. package/dist/parallel-tools.js.map +1 -1
  79. package/dist/plugins.d.ts +32 -1
  80. package/dist/plugins.d.ts.map +1 -1
  81. package/dist/plugins.js +116 -5
  82. package/dist/plugins.js.map +1 -1
  83. package/dist/policy.d.ts +43 -0
  84. package/dist/policy.d.ts.map +1 -0
  85. package/dist/policy.js +139 -0
  86. package/dist/policy.js.map +1 -0
  87. package/dist/project-config.d.ts +1 -2
  88. package/dist/project-config.d.ts.map +1 -1
  89. package/dist/project-config.js +0 -3
  90. package/dist/project-config.js.map +1 -1
  91. package/dist/providers/bedrock.d.ts.map +1 -1
  92. package/dist/providers/bedrock.js +2 -5
  93. package/dist/providers/bedrock.js.map +1 -1
  94. package/dist/providers/compat.d.ts +21 -0
  95. package/dist/providers/compat.d.ts.map +1 -1
  96. package/dist/providers/compat.js +176 -6
  97. package/dist/providers/compat.js.map +1 -1
  98. package/dist/providers/google.js.map +1 -1
  99. package/dist/providers/index.d.ts +19 -4
  100. package/dist/providers/index.d.ts.map +1 -1
  101. package/dist/providers/index.js +61 -10
  102. package/dist/providers/index.js.map +1 -1
  103. package/dist/providers/ollama.d.ts +2 -2
  104. package/dist/providers/ollama.d.ts.map +1 -1
  105. package/dist/providers/ollama.js +26 -6
  106. package/dist/providers/ollama.js.map +1 -1
  107. package/dist/providers/openai.d.ts +10 -10
  108. package/dist/providers/openai.d.ts.map +1 -1
  109. package/dist/providers/openai.js +18 -10
  110. package/dist/providers/openai.js.map +1 -1
  111. package/dist/providers/types.d.ts +8 -0
  112. package/dist/providers/types.d.ts.map +1 -1
  113. package/dist/providers/types.js.map +1 -1
  114. package/dist/replay.d.ts +37 -0
  115. package/dist/replay.d.ts.map +1 -0
  116. package/dist/replay.js +168 -0
  117. package/dist/replay.js.map +1 -0
  118. package/dist/router.d.ts +133 -0
  119. package/dist/router.d.ts.map +1 -0
  120. package/dist/{model-router.js → router.js} +329 -3
  121. package/dist/router.js.map +1 -0
  122. package/dist/runlog.d.ts +185 -0
  123. package/dist/runlog.d.ts.map +1 -0
  124. package/dist/runlog.js +398 -0
  125. package/dist/runlog.js.map +1 -0
  126. package/dist/{sandbox.d.ts → sandbox/docker.d.ts} +1 -1
  127. package/dist/sandbox/docker.d.ts.map +1 -0
  128. package/dist/{sandbox.js → sandbox/docker.js} +1 -1
  129. package/dist/sandbox/docker.js.map +1 -0
  130. package/dist/sandbox/index.d.ts +36 -0
  131. package/dist/sandbox/index.d.ts.map +1 -0
  132. package/dist/sandbox/index.js +62 -0
  133. package/dist/sandbox/index.js.map +1 -0
  134. package/dist/{sandbox-native.d.ts → sandbox/native.d.ts} +1 -1
  135. package/dist/sandbox/native.d.ts.map +1 -0
  136. package/dist/{sandbox-native.js → sandbox/native.js} +1 -1
  137. package/dist/sandbox/native.js.map +1 -0
  138. package/dist/scope.d.ts.map +1 -1
  139. package/dist/scope.js +1 -1
  140. package/dist/scope.js.map +1 -1
  141. package/dist/scuttlebot/client.d.ts.map +1 -1
  142. package/dist/scuttlebot/client.js.map +1 -1
  143. package/dist/scuttlebot/config.js.map +1 -1
  144. package/dist/scuttlebot/http-client.d.ts.map +1 -1
  145. package/dist/scuttlebot/irc-client.d.ts +5 -5
  146. package/dist/scuttlebot/irc-client.d.ts.map +1 -1
  147. package/dist/scuttlebot/irc-client.js.map +1 -1
  148. package/dist/setup.d.ts.map +1 -1
  149. package/dist/setup.js +25 -54
  150. package/dist/setup.js.map +1 -1
  151. package/dist/skills.d.ts +39 -0
  152. package/dist/skills.d.ts.map +1 -1
  153. package/dist/skills.js +90 -8
  154. package/dist/skills.js.map +1 -1
  155. package/dist/storage.d.ts.map +1 -1
  156. package/dist/storage.js +6 -3
  157. package/dist/storage.js.map +1 -1
  158. package/dist/streaming.d.ts +25 -0
  159. package/dist/streaming.d.ts.map +1 -1
  160. package/dist/streaming.js +59 -0
  161. package/dist/streaming.js.map +1 -1
  162. package/dist/styles.d.ts +62 -56
  163. package/dist/styles.d.ts.map +1 -1
  164. package/dist/styles.js +11 -0
  165. package/dist/styles.js.map +1 -1
  166. package/dist/summarization.d.ts.map +1 -1
  167. package/dist/summarization.js.map +1 -1
  168. package/dist/terminal-image.js +1 -1
  169. package/dist/terminal-image.js.map +1 -1
  170. package/dist/themes.d.ts +5 -4
  171. package/dist/themes.d.ts.map +1 -1
  172. package/dist/themes.js +35 -90
  173. package/dist/themes.js.map +1 -1
  174. package/dist/tools.d.ts +27 -3
  175. package/dist/tools.d.ts.map +1 -1
  176. package/dist/tools.js +128 -179
  177. package/dist/tools.js.map +1 -1
  178. package/dist/trust.js.map +1 -1
  179. package/dist/types.d.ts +4 -3
  180. package/dist/types.d.ts.map +1 -1
  181. package/dist/types.js +21 -40
  182. package/dist/types.js.map +1 -1
  183. package/dist/ui/agent.d.ts +3 -6
  184. package/dist/ui/agent.d.ts.map +1 -1
  185. package/dist/ui/agent.js +328 -38
  186. package/dist/ui/agent.js.map +1 -1
  187. package/dist/ui/animations.d.ts +37 -0
  188. package/dist/ui/animations.d.ts.map +1 -0
  189. package/dist/ui/animations.js +227 -0
  190. package/dist/ui/animations.js.map +1 -0
  191. package/dist/ui/chat-input-keys.d.ts +42 -0
  192. package/dist/ui/chat-input-keys.d.ts.map +1 -0
  193. package/dist/ui/chat-input-keys.js +360 -0
  194. package/dist/ui/chat-input-keys.js.map +1 -0
  195. package/dist/ui/chat-input.d.ts +4 -2
  196. package/dist/ui/chat-input.d.ts.map +1 -1
  197. package/dist/ui/chat-input.js +31 -350
  198. package/dist/ui/chat-input.js.map +1 -1
  199. package/dist/ui/commands.d.ts +14 -46
  200. package/dist/ui/commands.d.ts.map +1 -1
  201. package/dist/ui/commands.js +416 -2899
  202. package/dist/ui/commands.js.map +1 -1
  203. package/dist/ui/completions.d.ts +1 -0
  204. package/dist/ui/completions.d.ts.map +1 -1
  205. package/dist/ui/completions.js +36 -107
  206. package/dist/ui/completions.js.map +1 -1
  207. package/dist/ui/components.d.ts +20 -12
  208. package/dist/ui/components.d.ts.map +1 -1
  209. package/dist/ui/components.js +17 -226
  210. package/dist/ui/components.js.map +1 -1
  211. package/dist/ui/context.js +6 -6
  212. package/dist/ui/context.js.map +1 -1
  213. package/dist/ui/debug-log.d.ts +11 -0
  214. package/dist/ui/debug-log.d.ts.map +1 -0
  215. package/dist/ui/debug-log.js +21 -0
  216. package/dist/ui/debug-log.js.map +1 -0
  217. package/dist/ui/error-boundary.d.ts +1 -1
  218. package/dist/ui/error-boundary.d.ts.map +1 -1
  219. package/dist/ui/error-boundary.js.map +1 -1
  220. package/dist/ui/frame.d.ts +1 -1
  221. package/dist/ui/frame.d.ts.map +1 -1
  222. package/dist/ui/frame.js +1 -3
  223. package/dist/ui/frame.js.map +1 -1
  224. package/dist/ui/index.d.ts +11 -3
  225. package/dist/ui/index.d.ts.map +1 -1
  226. package/dist/ui/index.js +45 -1076
  227. package/dist/ui/index.js.map +1 -1
  228. package/dist/ui/messages.d.ts +5 -8
  229. package/dist/ui/messages.d.ts.map +1 -1
  230. package/dist/ui/messages.js +15 -30
  231. package/dist/ui/messages.js.map +1 -1
  232. package/dist/ui/modals/index.d.ts +11 -0
  233. package/dist/ui/modals/index.d.ts.map +1 -0
  234. package/dist/ui/modals/index.js +10 -0
  235. package/dist/ui/modals/index.js.map +1 -0
  236. package/dist/ui/modals/prompts.d.ts +38 -0
  237. package/dist/ui/modals/prompts.d.ts.map +1 -0
  238. package/dist/ui/modals/prompts.js +124 -0
  239. package/dist/ui/modals/prompts.js.map +1 -0
  240. package/dist/ui/modals/selectors.d.ts +34 -0
  241. package/dist/ui/modals/selectors.d.ts.map +1 -0
  242. package/dist/ui/modals/selectors.js +111 -0
  243. package/dist/ui/modals/selectors.js.map +1 -0
  244. package/dist/ui/modals/setup.d.ts +18 -0
  245. package/dist/ui/modals/setup.d.ts.map +1 -0
  246. package/dist/ui/modals/setup.js +51 -0
  247. package/dist/ui/modals/setup.js.map +1 -0
  248. package/dist/ui/regions/input-region.d.ts +40 -0
  249. package/dist/ui/regions/input-region.d.ts.map +1 -0
  250. package/dist/ui/regions/input-region.js +116 -0
  251. package/dist/ui/regions/input-region.js.map +1 -0
  252. package/dist/ui/regions/modal-host.d.ts +41 -0
  253. package/dist/ui/regions/modal-host.d.ts.map +1 -0
  254. package/dist/ui/regions/modal-host.js +51 -0
  255. package/dist/ui/regions/modal-host.js.map +1 -0
  256. package/dist/ui/regions/render-probe.d.ts +22 -0
  257. package/dist/ui/regions/render-probe.d.ts.map +1 -0
  258. package/dist/ui/regions/render-probe.js +45 -0
  259. package/dist/ui/regions/render-probe.js.map +1 -0
  260. package/dist/ui/regions/static-scrollback.d.ts +39 -0
  261. package/dist/ui/regions/static-scrollback.d.ts.map +1 -0
  262. package/dist/ui/regions/static-scrollback.js +68 -0
  263. package/dist/ui/regions/static-scrollback.js.map +1 -0
  264. package/dist/ui/regions/status-region.d.ts +24 -0
  265. package/dist/ui/regions/status-region.d.ts.map +1 -0
  266. package/dist/ui/regions/status-region.js +17 -0
  267. package/dist/ui/regions/status-region.js.map +1 -0
  268. package/dist/ui/regions/transcript-region.d.ts +41 -0
  269. package/dist/ui/regions/transcript-region.d.ts.map +1 -0
  270. package/dist/ui/regions/transcript-region.js +52 -0
  271. package/dist/ui/regions/transcript-region.js.map +1 -0
  272. package/dist/ui/self-restart.d.ts +9 -0
  273. package/dist/ui/self-restart.d.ts.map +1 -0
  274. package/dist/ui/self-restart.js +24 -0
  275. package/dist/ui/self-restart.js.map +1 -0
  276. package/dist/ui/state/use-chat-controller.d.ts +23 -0
  277. package/dist/ui/state/use-chat-controller.d.ts.map +1 -0
  278. package/dist/ui/state/use-chat-controller.js +643 -0
  279. package/dist/ui/state/use-chat-controller.js.map +1 -0
  280. package/dist/ui/state/use-loop-state.d.ts +23 -0
  281. package/dist/ui/state/use-loop-state.d.ts.map +1 -0
  282. package/dist/ui/state/use-loop-state.js +39 -0
  283. package/dist/ui/state/use-loop-state.js.map +1 -0
  284. package/dist/ui/state/use-modal-state.d.ts +52 -0
  285. package/dist/ui/state/use-modal-state.d.ts.map +1 -0
  286. package/dist/ui/state/use-modal-state.js +44 -0
  287. package/dist/ui/state/use-modal-state.js.map +1 -0
  288. package/dist/ui/state/use-model-state.d.ts +29 -0
  289. package/dist/ui/state/use-model-state.d.ts.map +1 -0
  290. package/dist/ui/state/use-model-state.js +47 -0
  291. package/dist/ui/state/use-model-state.js.map +1 -0
  292. package/dist/ui/state/use-processing-state.d.ts +24 -0
  293. package/dist/ui/state/use-processing-state.d.ts.map +1 -0
  294. package/dist/ui/state/use-processing-state.js +46 -0
  295. package/dist/ui/state/use-processing-state.js.map +1 -0
  296. package/dist/ui/state/use-queue-state.d.ts +19 -0
  297. package/dist/ui/state/use-queue-state.d.ts.map +1 -0
  298. package/dist/ui/state/use-queue-state.js +30 -0
  299. package/dist/ui/state/use-queue-state.js.map +1 -0
  300. package/dist/ui/state/use-session-init.d.ts +22 -0
  301. package/dist/ui/state/use-session-init.d.ts.map +1 -0
  302. package/dist/ui/state/use-session-init.js +77 -0
  303. package/dist/ui/state/use-session-init.js.map +1 -0
  304. package/dist/ui/state/use-session-stats.d.ts +16 -0
  305. package/dist/ui/state/use-session-stats.d.ts.map +1 -0
  306. package/dist/ui/state/use-session-stats.js +18 -0
  307. package/dist/ui/state/use-session-stats.js.map +1 -0
  308. package/dist/ui/state/use-terminal-width.d.ts +8 -0
  309. package/dist/ui/state/use-terminal-width.d.ts.map +1 -0
  310. package/dist/ui/state/use-terminal-width.js +22 -0
  311. package/dist/ui/state/use-terminal-width.js.map +1 -0
  312. package/dist/ui/state/use-transcript-state.d.ts +21 -0
  313. package/dist/ui/state/use-transcript-state.d.ts.map +1 -0
  314. package/dist/ui/state/use-transcript-state.js +49 -0
  315. package/dist/ui/state/use-transcript-state.js.map +1 -0
  316. package/dist/ui/status-bar.d.ts +1 -1
  317. package/dist/ui/status-bar.d.ts.map +1 -1
  318. package/dist/ui/status-bar.js +3 -4
  319. package/dist/ui/status-bar.js.map +1 -1
  320. package/dist/version-check.d.ts.map +1 -1
  321. package/dist/version-check.js +10 -0
  322. package/dist/version-check.js.map +1 -1
  323. package/package.json +17 -10
  324. package/dist/agents/agent-config-loader.d.ts +0 -60
  325. package/dist/agents/agent-config-loader.d.ts.map +0 -1
  326. package/dist/agents/agent-config-loader.js +0 -402
  327. package/dist/agents/agent-config-loader.js.map +0 -1
  328. package/dist/agents/agent-config-presets.d.ts +0 -10
  329. package/dist/agents/agent-config-presets.d.ts.map +0 -1
  330. package/dist/agents/agent-config-presets.js +0 -940
  331. package/dist/agents/agent-config-presets.js.map +0 -1
  332. package/dist/agents/agent-config-types.d.ts +0 -145
  333. package/dist/agents/agent-config-types.d.ts.map +0 -1
  334. package/dist/agents/agent-config-types.js +0 -12
  335. package/dist/agents/agent-config-types.js.map +0 -1
  336. package/dist/agents/agent-detection.d.ts +0 -35
  337. package/dist/agents/agent-detection.d.ts.map +0 -1
  338. package/dist/agents/agent-detection.js +0 -110
  339. package/dist/agents/agent-detection.js.map +0 -1
  340. package/dist/agents/aggregator.d.ts +0 -19
  341. package/dist/agents/aggregator.d.ts.map +0 -1
  342. package/dist/agents/aggregator.js +0 -141
  343. package/dist/agents/aggregator.js.map +0 -1
  344. package/dist/agents/cli-backend.d.ts +0 -32
  345. package/dist/agents/cli-backend.d.ts.map +0 -1
  346. package/dist/agents/cli-backend.js +0 -271
  347. package/dist/agents/cli-backend.js.map +0 -1
  348. package/dist/agents/council-types.d.ts +0 -115
  349. package/dist/agents/council-types.d.ts.map +0 -1
  350. package/dist/agents/council-types.js +0 -81
  351. package/dist/agents/council-types.js.map +0 -1
  352. package/dist/agents/council.d.ts +0 -112
  353. package/dist/agents/council.d.ts.map +0 -1
  354. package/dist/agents/council.js +0 -722
  355. package/dist/agents/council.js.map +0 -1
  356. package/dist/agents/decomposer.d.ts +0 -33
  357. package/dist/agents/decomposer.d.ts.map +0 -1
  358. package/dist/agents/decomposer.js +0 -138
  359. package/dist/agents/decomposer.js.map +0 -1
  360. package/dist/agents/dynamic-tools.d.ts +0 -52
  361. package/dist/agents/dynamic-tools.d.ts.map +0 -1
  362. package/dist/agents/dynamic-tools.js +0 -424
  363. package/dist/agents/dynamic-tools.js.map +0 -1
  364. package/dist/agents/index.d.ts +0 -29
  365. package/dist/agents/index.d.ts.map +0 -1
  366. package/dist/agents/index.js +0 -29
  367. package/dist/agents/index.js.map +0 -1
  368. package/dist/agents/installer.d.ts +0 -39
  369. package/dist/agents/installer.d.ts.map +0 -1
  370. package/dist/agents/installer.js +0 -205
  371. package/dist/agents/installer.js.map +0 -1
  372. package/dist/agents/orchestrator.d.ts +0 -106
  373. package/dist/agents/orchestrator.d.ts.map +0 -1
  374. package/dist/agents/orchestrator.js +0 -363
  375. package/dist/agents/orchestrator.js.map +0 -1
  376. package/dist/agents/sdk-backend.d.ts +0 -63
  377. package/dist/agents/sdk-backend.d.ts.map +0 -1
  378. package/dist/agents/sdk-backend.js +0 -489
  379. package/dist/agents/sdk-backend.js.map +0 -1
  380. package/dist/agents/swarm-types.d.ts +0 -84
  381. package/dist/agents/swarm-types.d.ts.map +0 -1
  382. package/dist/agents/swarm-types.js +0 -20
  383. package/dist/agents/swarm-types.js.map +0 -1
  384. package/dist/agents/swarm.d.ts +0 -79
  385. package/dist/agents/swarm.d.ts.map +0 -1
  386. package/dist/agents/swarm.js +0 -375
  387. package/dist/agents/swarm.js.map +0 -1
  388. package/dist/agents/tools.d.ts +0 -26
  389. package/dist/agents/tools.d.ts.map +0 -1
  390. package/dist/agents/tools.js +0 -776
  391. package/dist/agents/tools.js.map +0 -1
  392. package/dist/agents/types.d.ts +0 -108
  393. package/dist/agents/types.d.ts.map +0 -1
  394. package/dist/agents/types.js +0 -43
  395. package/dist/agents/types.js.map +0 -1
  396. package/dist/api-server.d.ts +0 -45
  397. package/dist/api-server.d.ts.map +0 -1
  398. package/dist/api-server.js +0 -326
  399. package/dist/api-server.js.map +0 -1
  400. package/dist/auto-checkpoint.d.ts +0 -35
  401. package/dist/auto-checkpoint.d.ts.map +0 -1
  402. package/dist/auto-checkpoint.js +0 -176
  403. package/dist/auto-checkpoint.js.map +0 -1
  404. package/dist/background-jobs.d.ts +0 -45
  405. package/dist/background-jobs.d.ts.map +0 -1
  406. package/dist/background-jobs.js +0 -127
  407. package/dist/background-jobs.js.map +0 -1
  408. package/dist/branching.d.ts +0 -56
  409. package/dist/branching.d.ts.map +0 -1
  410. package/dist/branching.js +0 -224
  411. package/dist/branching.js.map +0 -1
  412. package/dist/cli/agent.d.ts +0 -9
  413. package/dist/cli/agent.d.ts.map +0 -1
  414. package/dist/cli/agent.js +0 -330
  415. package/dist/cli/agent.js.map +0 -1
  416. package/dist/cli/commands.d.ts +0 -12
  417. package/dist/cli/commands.d.ts.map +0 -1
  418. package/dist/cli/commands.js +0 -1042
  419. package/dist/cli/commands.js.map +0 -1
  420. package/dist/cli/index.d.ts +0 -8
  421. package/dist/cli/index.d.ts.map +0 -1
  422. package/dist/cli/index.js +0 -268
  423. package/dist/cli/index.js.map +0 -1
  424. package/dist/cli/types.d.ts +0 -33
  425. package/dist/cli/types.d.ts.map +0 -1
  426. package/dist/cli/types.js +0 -21
  427. package/dist/cli/types.js.map +0 -1
  428. package/dist/companions.d.ts +0 -54
  429. package/dist/companions.d.ts.map +0 -1
  430. package/dist/companions.js +0 -440
  431. package/dist/companions.js.map +0 -1
  432. package/dist/file-watcher.d.ts +0 -91
  433. package/dist/file-watcher.d.ts.map +0 -1
  434. package/dist/file-watcher.js +0 -269
  435. package/dist/file-watcher.js.map +0 -1
  436. package/dist/hud/theme-packs/api.d.ts +0 -51
  437. package/dist/hud/theme-packs/api.d.ts.map +0 -1
  438. package/dist/hud/theme-packs/api.js +0 -145
  439. package/dist/hud/theme-packs/api.js.map +0 -1
  440. package/dist/hud/theme-packs/index.d.ts +0 -18
  441. package/dist/hud/theme-packs/index.d.ts.map +0 -1
  442. package/dist/hud/theme-packs/index.js +0 -38
  443. package/dist/hud/theme-packs/index.js.map +0 -1
  444. package/dist/hud/theme-packs/types.d.ts +0 -29
  445. package/dist/hud/theme-packs/types.d.ts.map +0 -1
  446. package/dist/hud/theme-packs/types.js +0 -9
  447. package/dist/hud/theme-packs/types.js.map +0 -1
  448. package/dist/idle-eviction.d.ts +0 -34
  449. package/dist/idle-eviction.d.ts.map +0 -1
  450. package/dist/idle-eviction.js +0 -85
  451. package/dist/idle-eviction.js.map +0 -1
  452. package/dist/model-router.d.ts +0 -67
  453. package/dist/model-router.d.ts.map +0 -1
  454. package/dist/model-router.js.map +0 -1
  455. package/dist/providers/openai-compat-shims.d.ts +0 -31
  456. package/dist/providers/openai-compat-shims.d.ts.map +0 -1
  457. package/dist/providers/openai-compat-shims.js +0 -179
  458. package/dist/providers/openai-compat-shims.js.map +0 -1
  459. package/dist/sandbox-native.d.ts.map +0 -1
  460. package/dist/sandbox-native.js.map +0 -1
  461. package/dist/sandbox.d.ts.map +0 -1
  462. package/dist/sandbox.js.map +0 -1
  463. package/dist/session-timeout.d.ts +0 -31
  464. package/dist/session-timeout.d.ts.map +0 -1
  465. package/dist/session-timeout.js +0 -100
  466. package/dist/session-timeout.js.map +0 -1
  467. package/dist/smart-router.d.ts +0 -73
  468. package/dist/smart-router.d.ts.map +0 -1
  469. package/dist/smart-router.js +0 -332
  470. package/dist/smart-router.js.map +0 -1
  471. package/dist/terminal-recording.d.ts +0 -55
  472. package/dist/terminal-recording.d.ts.map +0 -1
  473. package/dist/terminal-recording.js +0 -182
  474. package/dist/terminal-recording.js.map +0 -1
  475. package/dist/tmux.d.ts +0 -35
  476. package/dist/tmux.d.ts.map +0 -1
  477. package/dist/tmux.js +0 -106
  478. package/dist/tmux.js.map +0 -1
  479. package/dist/ui/modals.d.ts +0 -72
  480. package/dist/ui/modals.d.ts.map +0 -1
  481. package/dist/ui/modals.js +0 -266
  482. package/dist/ui/modals.js.map +0 -1
  483. package/dist/ui/pack-picker.d.ts +0 -12
  484. package/dist/ui/pack-picker.d.ts.map +0 -1
  485. package/dist/ui/pack-picker.js +0 -101
  486. package/dist/ui/pack-picker.js.map +0 -1
  487. package/dist/ui/theme-picker.d.ts +0 -24
  488. package/dist/ui/theme-picker.d.ts.map +0 -1
  489. package/dist/ui/theme-picker.js +0 -190
  490. package/dist/ui/theme-picker.js.map +0 -1
package/dist/acp.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Calliope CLI - Agent Client Protocol (ACP) agent mode.
3
+ *
4
+ * `calliope acp` speaks the Agent Client Protocol (https://agentclientprotocol.com)
5
+ * over stdio JSON-RPC, so editors that speak ACP (Zed, JetBrains, Neovim, …) can
6
+ * drive Calliope as a coding agent. This module is the adapter: it maps the ACP
7
+ * surface onto Calliope's existing agent core (the same provider `chat`, `TOOLS`,
8
+ * `executeTool`, governance and audit pieces the headless runner uses) — no forked
9
+ * agent logic.
10
+ *
11
+ * Baseline agent surface implemented: `initialize`, `authenticate`, `session/new`,
12
+ * `session/prompt`; `session/cancel`; streaming `session/update` notifications; and
13
+ * the `session/request_permission` flow. When the client advertises `fs`
14
+ * capabilities, file tools are routed through the client's `fs/read_text_file` and
15
+ * `fs/write_text_file` so edits land on the editor's (possibly unsaved) buffers.
16
+ *
17
+ * The protocol owns stdout/stdin; ALL diagnostics go to stderr (see {@link log}),
18
+ * so a stray `console.log` never corrupts the JSON-RPC stream. The whole module is
19
+ * lazy-loaded from bin.ts only for the `acp` subcommand, so it adds nothing to the
20
+ * default cold-start path.
21
+ */
22
+ import { AgentSideConnection, type Agent, type Stream, type InitializeRequest, type InitializeResponse, type NewSessionRequest, type NewSessionResponse, type AuthenticateResponse, type PromptRequest, type PromptResponse, type CancelNotification } from '@zed-industries/agent-client-protocol';
23
+ declare class CalliopeAgent implements Agent {
24
+ private readonly conn;
25
+ private clientCapabilities;
26
+ private readonly sessions;
27
+ /** Tail of the outgoing write chain; awaited to flush notifications. */
28
+ private lastWrite;
29
+ constructor(conn: AgentSideConnection);
30
+ initialize(params: InitializeRequest): Promise<InitializeResponse>;
31
+ authenticate(): Promise<AuthenticateResponse>;
32
+ newSession(params: NewSessionRequest): Promise<NewSessionResponse>;
33
+ prompt(params: PromptRequest): Promise<PromptResponse>;
34
+ cancel(params: CancelNotification): Promise<void>;
35
+ private runTurn;
36
+ /** Flush pending notifications and return the cancelled stop reason. */
37
+ private finishCancelled;
38
+ private runToolCall;
39
+ /** Send a terminal (completed/failed) tool_call_update to the client. */
40
+ private reportToolResult;
41
+ private gateToolCall;
42
+ /**
43
+ * Ask the client to authorize a tool call. Returns the user's decision, or
44
+ * falls back to Calliope's non-interactive default (deny) when the client does
45
+ * not support the permission request at all.
46
+ */
47
+ private requestPermission;
48
+ /**
49
+ * Build an {@link FsDelegate} that routes file tool reads/writes through the
50
+ * client's `fs/read_text_file` / `fs/write_text_file`, but only for the
51
+ * capabilities the client advertised. Returns undefined when the client has no
52
+ * fs capability, so tools fall back to local disk.
53
+ */
54
+ private clientFsDelegate;
55
+ /**
56
+ * Send a session/update notification. Writes serialize in call order via the
57
+ * SDK's write queue, so the tail promise flushes everything before it. Errors
58
+ * are swallowed to stderr — a failed notification must never crash the loop.
59
+ */
60
+ private emit;
61
+ /** Await all pending outgoing notifications. */
62
+ private flush;
63
+ /** Close every session's audit log (best-effort) on shutdown. */
64
+ shutdown(): Promise<void>;
65
+ }
66
+ /**
67
+ * Wire a {@link CalliopeAgent} onto an ACP {@link Stream}. Exposed for tests,
68
+ * which drive the SDK's client side against it over an in-memory stream pair.
69
+ * The SDK calls the factory synchronously, so the returned agent is ready.
70
+ */
71
+ export declare function serveAcp(stream: Stream): CalliopeAgent;
72
+ /**
73
+ * Run Calliope as an ACP agent over stdio (stdout/stdin carry JSON-RPC). Started
74
+ * from bin.ts when argv[0] === 'acp'. Resolves when the client closes the stream.
75
+ */
76
+ export declare function runAcpAgent(): Promise<number>;
77
+ export {};
78
+ //# sourceMappingURL=acp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../src/acp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,EACL,mBAAmB,EAInB,KAAK,KAAK,EACV,KAAK,MAAM,EAKX,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,uCAAuC,CAAC;AAwK/C,cAAM,aAAc,YAAW,KAAK;IAMtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IALjC,OAAO,CAAC,kBAAkB,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,wEAAwE;IACxE,OAAO,CAAC,SAAS,CAAoC;IAErD,YAA6B,IAAI,EAAE,mBAAmB,EAAI;IAIpD,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAoBvE;IAIK,YAAY,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAElD;IAIK,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAiDvE;IAIK,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAgB3D;IAIK,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtD;YAIa,OAAO;IAyErB,wEAAwE;YAC1D,eAAe;YAQf,WAAW;IA6DzB,yEAAyE;IACzE,OAAO,CAAC,gBAAgB;YAkBV,YAAY;IAkC1B;;;;OAIG;YACW,iBAAiB;IAiC/B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAsBxB;;;;OAIG;IACH,OAAO,CAAC,IAAI;IAQZ,gDAAgD;IAChD,OAAO,CAAC,KAAK;IAIb,iEAAiE;IAC3D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAc9B;CACF;AAMD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAQtD;AAED;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAkBnD"}
package/dist/acp.js ADDED
@@ -0,0 +1,572 @@
1
+ /**
2
+ * Calliope CLI - Agent Client Protocol (ACP) agent mode.
3
+ *
4
+ * `calliope acp` speaks the Agent Client Protocol (https://agentclientprotocol.com)
5
+ * over stdio JSON-RPC, so editors that speak ACP (Zed, JetBrains, Neovim, …) can
6
+ * drive Calliope as a coding agent. This module is the adapter: it maps the ACP
7
+ * surface onto Calliope's existing agent core (the same provider `chat`, `TOOLS`,
8
+ * `executeTool`, governance and audit pieces the headless runner uses) — no forked
9
+ * agent logic.
10
+ *
11
+ * Baseline agent surface implemented: `initialize`, `authenticate`, `session/new`,
12
+ * `session/prompt`; `session/cancel`; streaming `session/update` notifications; and
13
+ * the `session/request_permission` flow. When the client advertises `fs`
14
+ * capabilities, file tools are routed through the client's `fs/read_text_file` and
15
+ * `fs/write_text_file` so edits land on the editor's (possibly unsaved) buffers.
16
+ *
17
+ * The protocol owns stdout/stdin; ALL diagnostics go to stderr (see {@link log}),
18
+ * so a stray `console.log` never corrupts the JSON-RPC stream. The whole module is
19
+ * lazy-loaded from bin.ts only for the `acp` subcommand, so it adds nothing to the
20
+ * default cold-start path.
21
+ */
22
+ import * as path from 'node:path';
23
+ import { Readable, Writable } from 'node:stream';
24
+ import { AgentSideConnection, ndJsonStream, RequestError, PROTOCOL_VERSION, } from '@zed-industries/agent-client-protocol';
25
+ import * as config from './config.js';
26
+ import { chat, selectProvider } from './providers/index.js';
27
+ import { TOOLS, executeTool } from './tools.js';
28
+ import { DEFAULT_MODELS, calculateCost } from './types.js';
29
+ import { getSystemPromptForProvider, isLocalBackend } from './local-model.js';
30
+ import * as memory from './memory.js';
31
+ import { resolveIterationLimit } from './iteration-limit.js';
32
+ import { RunLog } from './runlog.js';
33
+ import { evaluatePolicy, isPolicyEnabled } from './policy.js';
34
+ import { assessToolRisk } from './risk.js';
35
+ import { checkHooksAllow } from './hooks.js';
36
+ // ============================================================================
37
+ // Diagnostics — stderr only (stdout carries the protocol).
38
+ // ============================================================================
39
+ function log(message) {
40
+ process.stderr.write(`[calliope-acp] ${message}\n`);
41
+ }
42
+ /** Chatty per-request trace, gated on CALLIOPE_DEBUG (matches the rest of the CLI). */
43
+ function debug(message) {
44
+ if (process.env.CALLIOPE_DEBUG === '1')
45
+ log(message);
46
+ }
47
+ /**
48
+ * Best-effort human message from a thrown value. Handles Error instances and the
49
+ * bare `{ code, message, data }` JSON-RPC error object the SDK rejects with.
50
+ */
51
+ function errMessage(err) {
52
+ if (err instanceof Error)
53
+ return err.message;
54
+ if (typeof err === 'object' && err !== null && 'message' in err) {
55
+ const m = err.message;
56
+ if (typeof m === 'string')
57
+ return m;
58
+ }
59
+ return String(err);
60
+ }
61
+ // ============================================================================
62
+ // Tool → permission / presentation mapping
63
+ // ============================================================================
64
+ /**
65
+ * Tools with side effects. These always route through the permission flow (and
66
+ * are denied under the non-interactive fallback), matching the headless runner's
67
+ * notion of a mutating tool.
68
+ */
69
+ const MUTATING_TOOLS = new Set(['shell', 'write_file', 'edit_file', 'git', 'execute_code', 'configure']);
70
+ /**
71
+ * Whether a tool call must ask the client for permission before running.
72
+ * Read-only tools (read_file, list_files, think, glob, grep, web_search) run
73
+ * silently; anything that mutates state or that Calliope's risk model flags for
74
+ * confirmation asks first.
75
+ */
76
+ function toolNeedsPermission(toolCall) {
77
+ if (MUTATING_TOOLS.has(toolCall.name))
78
+ return true;
79
+ return assessToolRisk(toolCall).requiresConfirmation;
80
+ }
81
+ /** Map a Calliope tool name to the ACP tool kind (drives client icons/UX). */
82
+ function toolKind(name) {
83
+ switch (name) {
84
+ case 'read_file':
85
+ case 'list_files':
86
+ case 'glob':
87
+ case 'grep':
88
+ return 'read';
89
+ case 'write_file':
90
+ case 'edit_file':
91
+ return 'edit';
92
+ case 'shell':
93
+ case 'execute_code':
94
+ case 'git':
95
+ return 'execute';
96
+ case 'web_search':
97
+ case 'web_fetch':
98
+ return 'fetch';
99
+ case 'think':
100
+ case 'create_plan':
101
+ return 'think';
102
+ default:
103
+ return 'other';
104
+ }
105
+ }
106
+ /** A short human-readable title for a tool call, e.g. `read_file: src/a.ts`. */
107
+ function toolTitle(toolCall) {
108
+ const a = toolCall.arguments;
109
+ const hint = typeof a.path === 'string'
110
+ ? a.path
111
+ : typeof a.command === 'string'
112
+ ? a.command
113
+ : typeof a.pattern === 'string'
114
+ ? a.pattern
115
+ : typeof a.query === 'string'
116
+ ? a.query
117
+ : '';
118
+ return hint ? `${toolCall.name}: ${hint}` : toolCall.name;
119
+ }
120
+ /** Absolute file location(s) a tool touches, for the client's follow-along UI. */
121
+ function toolLocations(toolCall, cwd) {
122
+ const p = toolCall.arguments.path;
123
+ if (typeof p !== 'string' || p.length === 0)
124
+ return undefined;
125
+ return [{ path: path.isAbsolute(p) ? p : path.join(cwd, p) }];
126
+ }
127
+ /**
128
+ * Flatten an ACP prompt (content blocks) into the plain text Calliope's agent
129
+ * loop consumes. Baseline requires Text and ResourceLink; a resource link is
130
+ * surfaced as an `@uri` mention, and an embedded text resource is inlined.
131
+ */
132
+ function promptToText(blocks) {
133
+ const parts = [];
134
+ for (const block of blocks) {
135
+ if (block.type === 'text') {
136
+ parts.push(block.text);
137
+ }
138
+ else if (block.type === 'resource_link') {
139
+ parts.push(`@${block.uri}`);
140
+ }
141
+ else if (block.type === 'resource') {
142
+ const resource = block.resource;
143
+ if (typeof resource.text === 'string') {
144
+ parts.push(resource.text);
145
+ }
146
+ else if (typeof resource.uri === 'string') {
147
+ parts.push(`@${resource.uri}`);
148
+ }
149
+ }
150
+ // image / audio blocks are not advertised in promptCapabilities; ignore.
151
+ }
152
+ return parts.join('\n');
153
+ }
154
+ // ============================================================================
155
+ // The agent
156
+ // ============================================================================
157
+ class CalliopeAgent {
158
+ conn;
159
+ clientCapabilities = {};
160
+ sessions = new Map();
161
+ /** Tail of the outgoing write chain; awaited to flush notifications. */
162
+ lastWrite = Promise.resolve();
163
+ constructor(conn) {
164
+ this.conn = conn;
165
+ }
166
+ // ---- ACP: initialize --------------------------------------------------
167
+ async initialize(params) {
168
+ this.clientCapabilities = params.clientCapabilities ?? {};
169
+ const requested = typeof params.protocolVersion === 'number' ? params.protocolVersion : PROTOCOL_VERSION;
170
+ // Negotiate down to the newest version we both support (we support 1).
171
+ const negotiated = requested >= 1 && requested <= PROTOCOL_VERSION ? requested : PROTOCOL_VERSION;
172
+ debug(`initialize: client protocol v${requested} -> v${negotiated}; ` +
173
+ `fs=${JSON.stringify(this.clientCapabilities.fs ?? {})} terminal=${this.clientCapabilities.terminal ?? false}`);
174
+ return {
175
+ protocolVersion: negotiated,
176
+ agentCapabilities: {
177
+ // session/load, MCP-over-ACP, and modes are not implemented yet.
178
+ loadSession: false,
179
+ promptCapabilities: { image: false, audio: false, embeddedContext: false },
180
+ },
181
+ // Calliope authenticates via locally-configured provider keys, so no ACP
182
+ // auth method is required.
183
+ authMethods: [],
184
+ };
185
+ }
186
+ // ---- ACP: authenticate (no-op; no auth methods advertised) ------------
187
+ async authenticate() {
188
+ return {};
189
+ }
190
+ // ---- ACP: session/new -------------------------------------------------
191
+ async newSession(params) {
192
+ const cwd = params.cwd || process.cwd();
193
+ const provider = process.env.CALLIOPE_PROVIDER || config.get('defaultProvider');
194
+ const model = process.env.CALLIOPE_MODEL || config.get('defaultModel') || '';
195
+ // Resolve the provider so 'auto' picks a real backend for the system prompt,
196
+ // cost model, and local-backend flag (mirrors the headless runner). Fall back
197
+ // to the raw provider if selection throws (chat() surfaces the real error).
198
+ let resolvedProvider;
199
+ try {
200
+ resolvedProvider = selectProvider(provider);
201
+ }
202
+ catch {
203
+ resolvedProvider = provider;
204
+ }
205
+ const localBackend = isLocalBackend(resolvedProvider);
206
+ const costModel = model || DEFAULT_MODELS[resolvedProvider];
207
+ const sessionId = `acp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
208
+ const runlog = RunLog.open(sessionId);
209
+ runlog.runStart({
210
+ session: sessionId,
211
+ cwd,
212
+ provider: resolvedProvider,
213
+ model: costModel,
214
+ config: config.getConfig(),
215
+ mode: 'acp',
216
+ });
217
+ const systemPrompt = getSystemPromptForProvider(resolvedProvider);
218
+ const memoryContext = memory.buildMemoryContext(cwd);
219
+ const fullPrompt = memoryContext.trim()
220
+ ? systemPrompt + '\n\n--- Project Context ---\n' + memoryContext
221
+ : systemPrompt;
222
+ this.sessions.set(sessionId, {
223
+ id: sessionId,
224
+ cwd,
225
+ provider,
226
+ resolvedProvider,
227
+ model,
228
+ localBackend,
229
+ messages: [{ role: 'system', content: fullPrompt }],
230
+ runlog,
231
+ cancelled: false,
232
+ totals: { inputTokens: 0, outputTokens: 0, cost: 0, toolCalls: 0 },
233
+ startedAt: Date.now(),
234
+ });
235
+ debug(`session/new: ${sessionId} cwd=${cwd} provider=${resolvedProvider} model=${costModel}`);
236
+ return { sessionId };
237
+ }
238
+ // ---- ACP: session/prompt ---------------------------------------------
239
+ async prompt(params) {
240
+ const session = this.sessions.get(params.sessionId);
241
+ if (!session) {
242
+ throw RequestError.invalidParams({ error: `unknown session: ${params.sessionId}` });
243
+ }
244
+ // Each prompt is a fresh turn; clear any stale cancel from a prior turn.
245
+ session.cancelled = false;
246
+ const text = promptToText(params.prompt);
247
+ session.messages.push({ role: 'user', content: text });
248
+ session.runlog.userPrompt(text);
249
+ debug(`session/prompt: ${session.id} (${text.length} chars)`);
250
+ const stopReason = await this.runTurn(session);
251
+ await session.runlog.flush();
252
+ return { stopReason };
253
+ }
254
+ // ---- ACP: session/cancel (notification) -------------------------------
255
+ async cancel(params) {
256
+ const session = this.sessions.get(params.sessionId);
257
+ if (session) {
258
+ session.cancelled = true;
259
+ debug(`session/cancel: ${params.sessionId}`);
260
+ }
261
+ }
262
+ // ---- The agent loop (ACP-flavoured mirror of the headless loop) --------
263
+ async runTurn(session) {
264
+ const maxIterations = resolveIterationLimit(config.get('maxIterations'));
265
+ const costModel = session.model || DEFAULT_MODELS[session.resolvedProvider];
266
+ let iteration = 0;
267
+ while (iteration < maxIterations) {
268
+ if (session.cancelled)
269
+ return this.finishCancelled(session);
270
+ iteration++;
271
+ // Stream assistant text as agent_message_chunk deltas via the chat seam.
272
+ let streamedChars = 0;
273
+ const onToken = (token) => {
274
+ if (!token)
275
+ return;
276
+ streamedChars += token.length;
277
+ this.emit(session.id, { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text: token } });
278
+ };
279
+ let response;
280
+ try {
281
+ response = await chat(session.provider, session.messages, TOOLS, session.model || undefined, onToken);
282
+ }
283
+ catch (err) {
284
+ const msg = errMessage(err);
285
+ log(`chat error: ${msg}`);
286
+ session.runlog.assistantMessage({ content: `[error: ${msg}]`, tokens: { input: 0, output: 0 }, cost: 0 });
287
+ await session.runlog.flush();
288
+ throw RequestError.internalError({ error: msg });
289
+ }
290
+ // Audit + spend accounting (mirrors headless).
291
+ if (response.usage) {
292
+ const cost = calculateCost(costModel, response.usage.inputTokens, response.usage.outputTokens);
293
+ session.totals.inputTokens += response.usage.inputTokens;
294
+ session.totals.outputTokens += response.usage.outputTokens;
295
+ session.totals.cost += cost;
296
+ session.runlog.assistantMessage({
297
+ content: response.content,
298
+ tokens: { input: response.usage.inputTokens, output: response.usage.outputTokens },
299
+ cost,
300
+ });
301
+ }
302
+ else {
303
+ session.runlog.assistantMessage({ content: response.content, tokens: { input: 0, output: 0 }, cost: 0 });
304
+ }
305
+ // Providers that don't stream: emit the assembled content once so the
306
+ // client still sees the assistant message.
307
+ if (streamedChars === 0 && response.content) {
308
+ this.emit(session.id, { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text: response.content } });
309
+ }
310
+ if (session.cancelled)
311
+ return this.finishCancelled(session);
312
+ if (response.toolCalls && response.toolCalls.length > 0) {
313
+ session.messages.push({ role: 'assistant', content: response.content, toolCalls: response.toolCalls });
314
+ for (const toolCall of response.toolCalls) {
315
+ if (session.cancelled)
316
+ return this.finishCancelled(session);
317
+ const outcome = await this.runToolCall(session, toolCall);
318
+ if (outcome === 'cancelled')
319
+ return this.finishCancelled(session);
320
+ }
321
+ continue; // next model turn
322
+ }
323
+ // No tool calls: this is the final assistant message → end of turn.
324
+ session.messages.push({ role: 'assistant', content: response.content });
325
+ await this.flush();
326
+ return response.finishReason === 'length' ? 'max_tokens' : 'end_turn';
327
+ }
328
+ // Exhausted the iteration budget.
329
+ await this.flush();
330
+ return 'max_turn_requests';
331
+ }
332
+ /** Flush pending notifications and return the cancelled stop reason. */
333
+ async finishCancelled(session) {
334
+ debug(`turn cancelled: ${session.id}`);
335
+ await this.flush();
336
+ return 'cancelled';
337
+ }
338
+ // ---- One tool call: announce → gate → execute → report ----------------
339
+ async runToolCall(session, toolCall) {
340
+ session.runlog.toolCall({ id: toolCall.id, name: toolCall.name, args: toolCall.arguments });
341
+ session.totals.toolCalls++;
342
+ // Announce the pending tool call.
343
+ await this.emit(session.id, {
344
+ sessionUpdate: 'tool_call',
345
+ toolCallId: toolCall.id,
346
+ title: toolTitle(toolCall),
347
+ kind: toolKind(toolCall.name),
348
+ status: 'pending',
349
+ rawInput: toolCall.arguments,
350
+ locations: toolLocations(toolCall, session.cwd),
351
+ });
352
+ // Permission + hard governance gates.
353
+ const gate = await this.gateToolCall(session, toolCall);
354
+ if (gate.decision === 'cancelled') {
355
+ await this.reportToolResult(session, toolCall.id, '[cancelled]', true);
356
+ session.runlog.toolResult({ id: toolCall.id, result: '[cancelled]', isError: true, durationMs: 0 });
357
+ session.messages.push({ role: 'tool', content: '[cancelled]', toolCallId: toolCall.id });
358
+ return 'cancelled';
359
+ }
360
+ if (gate.decision === 'deny') {
361
+ await this.reportToolResult(session, toolCall.id, gate.reason, true);
362
+ session.runlog.toolResult({ id: toolCall.id, result: gate.reason, isError: true, durationMs: 0 });
363
+ session.messages.push({ role: 'tool', content: gate.reason, toolCallId: toolCall.id });
364
+ return 'ok';
365
+ }
366
+ // Allowed: mark in-progress and execute through the shared tool runtime,
367
+ // preferring the client's filesystem when it advertised fs capabilities.
368
+ await this.emit(session.id, { sessionUpdate: 'tool_call_update', toolCallId: toolCall.id, status: 'in_progress' });
369
+ const started = Date.now();
370
+ let result;
371
+ try {
372
+ result = await executeTool(toolCall, session.cwd, 60000, undefined, {
373
+ appendAnchorHash: session.localBackend,
374
+ fs: this.clientFsDelegate(session.id),
375
+ });
376
+ }
377
+ catch (err) {
378
+ result = {
379
+ toolCallId: toolCall.id,
380
+ result: `Error: ${errMessage(err)}`,
381
+ isError: true,
382
+ };
383
+ }
384
+ const durationMs = Date.now() - started;
385
+ session.runlog.toolResult({
386
+ id: toolCall.id,
387
+ result: result.result,
388
+ isError: result.isError || false,
389
+ durationMs,
390
+ });
391
+ await this.reportToolResult(session, toolCall.id, result.displayResult || result.result, result.isError || false, result.result);
392
+ session.messages.push({ role: 'tool', content: result.result, toolCallId: toolCall.id });
393
+ return 'ok';
394
+ }
395
+ /** Send a terminal (completed/failed) tool_call_update to the client. */
396
+ reportToolResult(session, toolCallId, text, isError, rawResult) {
397
+ return this.emit(session.id, {
398
+ sessionUpdate: 'tool_call_update',
399
+ toolCallId,
400
+ status: isError ? 'failed' : 'completed',
401
+ content: [{ type: 'content', content: { type: 'text', text } }],
402
+ rawOutput: { result: rawResult ?? text, isError },
403
+ });
404
+ }
405
+ // ---- Gates: permission, then the hard hooks -------------------------
406
+ async gateToolCall(session, toolCall) {
407
+ // 1. Permission via the client (only for mutating / confirm-worthy tools).
408
+ if (toolNeedsPermission(toolCall)) {
409
+ const permission = await this.requestPermission(session, toolCall);
410
+ if (permission === 'cancelled')
411
+ return { decision: 'cancelled' };
412
+ if (permission === 'reject')
413
+ return { decision: 'deny', reason: '[Permission denied by user]' };
414
+ // 'allow' falls through to the hard gates below.
415
+ }
416
+ // 2. Pre-tool hooks — the hard gate, runs regardless of permission (exit-42
417
+ // veto contract; see hooks.ts / docs/governance.md).
418
+ const hookGate = await checkHooksAllow('pre-tool', { tool: toolCall.name, toolArgs: toolCall.arguments });
419
+ if (!hookGate.allowed) {
420
+ return { decision: 'deny', reason: `[Blocked by hook: ${hookGate.reason || 'no reason given'}]` };
421
+ }
422
+ // 3. Policy hook — the Zentinelle integration point (fail closed).
423
+ if (isPolicyEnabled()) {
424
+ const verdict = await evaluatePolicy(toolCall);
425
+ session.runlog.policyEvent({
426
+ tool: toolCall.name,
427
+ decision: verdict.decision,
428
+ source: verdict.source,
429
+ reason: verdict.reason,
430
+ durationMs: verdict.durationMs,
431
+ });
432
+ if (verdict.decision === 'deny') {
433
+ return { decision: 'deny', reason: `[Policy denied: ${verdict.reason || 'no reason given'}]` };
434
+ }
435
+ }
436
+ return { decision: 'allow' };
437
+ }
438
+ /**
439
+ * Ask the client to authorize a tool call. Returns the user's decision, or
440
+ * falls back to Calliope's non-interactive default (deny) when the client does
441
+ * not support the permission request at all.
442
+ */
443
+ async requestPermission(session, toolCall) {
444
+ try {
445
+ const res = await this.conn.requestPermission({
446
+ sessionId: session.id,
447
+ toolCall: {
448
+ toolCallId: toolCall.id,
449
+ title: toolTitle(toolCall),
450
+ kind: toolKind(toolCall.name),
451
+ rawInput: toolCall.arguments,
452
+ },
453
+ options: [
454
+ { optionId: 'allow', name: 'Allow', kind: 'allow_once' },
455
+ { optionId: 'allow_always', name: 'Always allow', kind: 'allow_always' },
456
+ { optionId: 'reject', name: 'Reject', kind: 'reject_once' },
457
+ ],
458
+ });
459
+ const outcome = res.outcome;
460
+ if (outcome.outcome === 'cancelled')
461
+ return 'cancelled';
462
+ if (outcome.outcome === 'selected')
463
+ return outcome.optionId.startsWith('allow') ? 'allow' : 'reject';
464
+ return 'reject';
465
+ }
466
+ catch (err) {
467
+ // Client can't handle permission requests: non-interactive default is to
468
+ // deny anything that needed asking (read-only tools never reach here).
469
+ log(`requestPermission unavailable (${errMessage(err)}); ` +
470
+ `denying ${toolCall.name} under the non-interactive default`);
471
+ return 'reject';
472
+ }
473
+ }
474
+ // ---- Client-side filesystem delegate ---------------------------------
475
+ /**
476
+ * Build an {@link FsDelegate} that routes file tool reads/writes through the
477
+ * client's `fs/read_text_file` / `fs/write_text_file`, but only for the
478
+ * capabilities the client advertised. Returns undefined when the client has no
479
+ * fs capability, so tools fall back to local disk.
480
+ */
481
+ clientFsDelegate(sessionId) {
482
+ const fsCap = this.clientCapabilities.fs;
483
+ if (!fsCap || (!fsCap.readTextFile && !fsCap.writeTextFile))
484
+ return undefined;
485
+ const conn = this.conn;
486
+ const delegate = {};
487
+ if (fsCap.readTextFile) {
488
+ delegate.readTextFile = async (absPath) => {
489
+ const res = await conn.readTextFile({ sessionId, path: absPath });
490
+ return res.content;
491
+ };
492
+ }
493
+ if (fsCap.writeTextFile) {
494
+ delegate.writeTextFile = async (absPath, content) => {
495
+ await conn.writeTextFile({ sessionId, path: absPath, content });
496
+ };
497
+ }
498
+ return delegate;
499
+ }
500
+ // ---- Notification plumbing -------------------------------------------
501
+ /**
502
+ * Send a session/update notification. Writes serialize in call order via the
503
+ * SDK's write queue, so the tail promise flushes everything before it. Errors
504
+ * are swallowed to stderr — a failed notification must never crash the loop.
505
+ */
506
+ emit(sessionId, update) {
507
+ const p = this.conn.sessionUpdate({ sessionId, update }).catch((err) => {
508
+ log(`sessionUpdate failed: ${errMessage(err)}`);
509
+ });
510
+ this.lastWrite = p;
511
+ return p;
512
+ }
513
+ /** Await all pending outgoing notifications. */
514
+ flush() {
515
+ return this.lastWrite;
516
+ }
517
+ /** Close every session's audit log (best-effort) on shutdown. */
518
+ async shutdown() {
519
+ for (const session of this.sessions.values()) {
520
+ session.runlog.runEnd({
521
+ totals: {
522
+ inputTokens: session.totals.inputTokens,
523
+ outputTokens: session.totals.outputTokens,
524
+ cost: session.totals.cost,
525
+ toolCalls: session.totals.toolCalls,
526
+ durationMs: Date.now() - session.startedAt,
527
+ },
528
+ exitReason: session.cancelled ? 'cancelled' : 'completed',
529
+ });
530
+ await session.runlog.close();
531
+ }
532
+ }
533
+ }
534
+ // ============================================================================
535
+ // Entry points
536
+ // ============================================================================
537
+ /**
538
+ * Wire a {@link CalliopeAgent} onto an ACP {@link Stream}. Exposed for tests,
539
+ * which drive the SDK's client side against it over an in-memory stream pair.
540
+ * The SDK calls the factory synchronously, so the returned agent is ready.
541
+ */
542
+ export function serveAcp(stream) {
543
+ let agent;
544
+ // eslint-disable-next-line no-new -- the connection registers itself and reads.
545
+ new AgentSideConnection((conn) => {
546
+ agent = new CalliopeAgent(conn);
547
+ return agent;
548
+ }, stream);
549
+ return agent;
550
+ }
551
+ /**
552
+ * Run Calliope as an ACP agent over stdio (stdout/stdin carry JSON-RPC). Started
553
+ * from bin.ts when argv[0] === 'acp'. Resolves when the client closes the stream.
554
+ */
555
+ export async function runAcpAgent() {
556
+ const input = Readable.toWeb(process.stdin);
557
+ const output = Writable.toWeb(process.stdout);
558
+ const stream = ndJsonStream(output, input);
559
+ const agent = serveAcp(stream);
560
+ log(`Calliope ACP agent ready on stdio (protocol v${PROTOCOL_VERSION}). Logs go to stderr.`);
561
+ // Stay alive until the client disconnects (stdin closes).
562
+ await new Promise((resolve) => {
563
+ const done = () => resolve();
564
+ process.stdin.on('end', done);
565
+ process.stdin.on('close', done);
566
+ process.stdin.on('error', done);
567
+ });
568
+ await agent.shutdown();
569
+ log('ACP client disconnected; shutting down.');
570
+ return 0;
571
+ }
572
+ //# sourceMappingURL=acp.js.map