@calliopelabs/cli 2.5.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 (476) 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.js.map +1 -1
  19. package/dist/config.d.ts +86 -81
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +236 -304
  22. package/dist/config.js.map +1 -1
  23. package/dist/cost.d.ts +114 -0
  24. package/dist/cost.d.ts.map +1 -0
  25. package/dist/cost.js +499 -0
  26. package/dist/cost.js.map +1 -0
  27. package/dist/diff.d.ts.map +1 -1
  28. package/dist/diff.js +11 -7
  29. package/dist/diff.js.map +1 -1
  30. package/dist/errors.js +3 -3
  31. package/dist/errors.js.map +1 -1
  32. package/dist/files.js.map +1 -1
  33. package/dist/fleet.d.ts +30 -0
  34. package/dist/fleet.d.ts.map +1 -0
  35. package/dist/fleet.js +86 -0
  36. package/dist/fleet.js.map +1 -0
  37. package/dist/fuzzy-search.d.ts.map +1 -1
  38. package/dist/fuzzy-search.js +2 -1
  39. package/dist/fuzzy-search.js.map +1 -1
  40. package/dist/git-status.js.map +1 -1
  41. package/dist/headless.d.ts +1 -2
  42. package/dist/headless.d.ts.map +1 -1
  43. package/dist/headless.js +166 -24
  44. package/dist/headless.js.map +1 -1
  45. package/dist/hud/api.d.ts +3 -18
  46. package/dist/hud/api.d.ts.map +1 -1
  47. package/dist/hud/api.js +9 -352
  48. package/dist/hud/api.js.map +1 -1
  49. package/dist/hud/palettes.d.ts.map +1 -1
  50. package/dist/hud/palettes.js +0 -180
  51. package/dist/hud/palettes.js.map +1 -1
  52. package/dist/hud/skins.d.ts.map +1 -1
  53. package/dist/hud/skins.js +0 -263
  54. package/dist/hud/skins.js.map +1 -1
  55. package/dist/hud/types.d.ts +2 -5
  56. package/dist/hud/types.d.ts.map +1 -1
  57. package/dist/index.d.ts +1 -4
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +1 -4
  60. package/dist/index.js.map +1 -1
  61. package/dist/iteration-ledger.d.ts.map +1 -1
  62. package/dist/iteration-ledger.js +3 -2
  63. package/dist/iteration-ledger.js.map +1 -1
  64. package/dist/local-model.d.ts +150 -0
  65. package/dist/local-model.d.ts.map +1 -0
  66. package/dist/local-model.js +408 -0
  67. package/dist/local-model.js.map +1 -0
  68. package/dist/mcp.d.ts.map +1 -1
  69. package/dist/mcp.js +5 -2
  70. package/dist/mcp.js.map +1 -1
  71. package/dist/memory.d.ts.map +1 -1
  72. package/dist/memory.js +6 -4
  73. package/dist/memory.js.map +1 -1
  74. package/dist/model-detection.js +2 -2
  75. package/dist/model-detection.js.map +1 -1
  76. package/dist/parallel-tools.js.map +1 -1
  77. package/dist/plugins.d.ts +32 -1
  78. package/dist/plugins.d.ts.map +1 -1
  79. package/dist/plugins.js +116 -5
  80. package/dist/plugins.js.map +1 -1
  81. package/dist/policy.d.ts +43 -0
  82. package/dist/policy.d.ts.map +1 -0
  83. package/dist/policy.js +139 -0
  84. package/dist/policy.js.map +1 -0
  85. package/dist/project-config.d.ts +1 -2
  86. package/dist/project-config.d.ts.map +1 -1
  87. package/dist/project-config.js +0 -3
  88. package/dist/project-config.js.map +1 -1
  89. package/dist/providers/bedrock.d.ts.map +1 -1
  90. package/dist/providers/bedrock.js +2 -5
  91. package/dist/providers/bedrock.js.map +1 -1
  92. package/dist/providers/compat.d.ts +21 -0
  93. package/dist/providers/compat.d.ts.map +1 -1
  94. package/dist/providers/compat.js +176 -6
  95. package/dist/providers/compat.js.map +1 -1
  96. package/dist/providers/google.js.map +1 -1
  97. package/dist/providers/index.d.ts +19 -4
  98. package/dist/providers/index.d.ts.map +1 -1
  99. package/dist/providers/index.js +61 -10
  100. package/dist/providers/index.js.map +1 -1
  101. package/dist/providers/ollama.d.ts +2 -2
  102. package/dist/providers/ollama.d.ts.map +1 -1
  103. package/dist/providers/ollama.js +26 -6
  104. package/dist/providers/ollama.js.map +1 -1
  105. package/dist/providers/openai.d.ts.map +1 -1
  106. package/dist/providers/openai.js +14 -10
  107. package/dist/providers/openai.js.map +1 -1
  108. package/dist/providers/types.d.ts +8 -0
  109. package/dist/providers/types.d.ts.map +1 -1
  110. package/dist/providers/types.js.map +1 -1
  111. package/dist/replay.d.ts +37 -0
  112. package/dist/replay.d.ts.map +1 -0
  113. package/dist/replay.js +168 -0
  114. package/dist/replay.js.map +1 -0
  115. package/dist/router.d.ts +133 -0
  116. package/dist/router.d.ts.map +1 -0
  117. package/dist/{model-router.js → router.js} +329 -3
  118. package/dist/router.js.map +1 -0
  119. package/dist/runlog.d.ts +185 -0
  120. package/dist/runlog.d.ts.map +1 -0
  121. package/dist/runlog.js +398 -0
  122. package/dist/runlog.js.map +1 -0
  123. package/dist/{sandbox.d.ts → sandbox/docker.d.ts} +1 -1
  124. package/dist/sandbox/docker.d.ts.map +1 -0
  125. package/dist/{sandbox.js → sandbox/docker.js} +1 -1
  126. package/dist/sandbox/docker.js.map +1 -0
  127. package/dist/sandbox/index.d.ts +36 -0
  128. package/dist/sandbox/index.d.ts.map +1 -0
  129. package/dist/sandbox/index.js +62 -0
  130. package/dist/sandbox/index.js.map +1 -0
  131. package/dist/{sandbox-native.d.ts → sandbox/native.d.ts} +1 -1
  132. package/dist/sandbox/native.d.ts.map +1 -0
  133. package/dist/{sandbox-native.js → sandbox/native.js} +1 -1
  134. package/dist/sandbox/native.js.map +1 -0
  135. package/dist/scope.js +1 -1
  136. package/dist/scope.js.map +1 -1
  137. package/dist/scuttlebot/config.js.map +1 -1
  138. package/dist/scuttlebot/irc-client.js.map +1 -1
  139. package/dist/setup.d.ts.map +1 -1
  140. package/dist/setup.js +22 -54
  141. package/dist/setup.js.map +1 -1
  142. package/dist/skills.d.ts +39 -0
  143. package/dist/skills.d.ts.map +1 -1
  144. package/dist/skills.js +90 -8
  145. package/dist/skills.js.map +1 -1
  146. package/dist/storage.d.ts.map +1 -1
  147. package/dist/storage.js +6 -3
  148. package/dist/storage.js.map +1 -1
  149. package/dist/streaming.d.ts +25 -0
  150. package/dist/streaming.d.ts.map +1 -1
  151. package/dist/streaming.js +59 -0
  152. package/dist/streaming.js.map +1 -1
  153. package/dist/styles.d.ts +6 -0
  154. package/dist/styles.d.ts.map +1 -1
  155. package/dist/styles.js +11 -0
  156. package/dist/styles.js.map +1 -1
  157. package/dist/summarization.js.map +1 -1
  158. package/dist/terminal-image.js +1 -1
  159. package/dist/terminal-image.js.map +1 -1
  160. package/dist/themes.d.ts +5 -4
  161. package/dist/themes.d.ts.map +1 -1
  162. package/dist/themes.js +35 -90
  163. package/dist/themes.js.map +1 -1
  164. package/dist/tools.d.ts +27 -3
  165. package/dist/tools.d.ts.map +1 -1
  166. package/dist/tools.js +128 -179
  167. package/dist/tools.js.map +1 -1
  168. package/dist/types.d.ts +4 -3
  169. package/dist/types.d.ts.map +1 -1
  170. package/dist/types.js +21 -40
  171. package/dist/types.js.map +1 -1
  172. package/dist/ui/agent.d.ts +3 -6
  173. package/dist/ui/agent.d.ts.map +1 -1
  174. package/dist/ui/agent.js +328 -38
  175. package/dist/ui/agent.js.map +1 -1
  176. package/dist/ui/animations.d.ts +37 -0
  177. package/dist/ui/animations.d.ts.map +1 -0
  178. package/dist/ui/animations.js +227 -0
  179. package/dist/ui/animations.js.map +1 -0
  180. package/dist/ui/chat-input-keys.d.ts +42 -0
  181. package/dist/ui/chat-input-keys.d.ts.map +1 -0
  182. package/dist/ui/chat-input-keys.js +360 -0
  183. package/dist/ui/chat-input-keys.js.map +1 -0
  184. package/dist/ui/chat-input.d.ts +2 -1
  185. package/dist/ui/chat-input.d.ts.map +1 -1
  186. package/dist/ui/chat-input.js +31 -350
  187. package/dist/ui/chat-input.js.map +1 -1
  188. package/dist/ui/commands.d.ts +14 -46
  189. package/dist/ui/commands.d.ts.map +1 -1
  190. package/dist/ui/commands.js +416 -2899
  191. package/dist/ui/commands.js.map +1 -1
  192. package/dist/ui/completions.d.ts +1 -0
  193. package/dist/ui/completions.d.ts.map +1 -1
  194. package/dist/ui/completions.js +36 -107
  195. package/dist/ui/completions.js.map +1 -1
  196. package/dist/ui/components.d.ts +14 -6
  197. package/dist/ui/components.d.ts.map +1 -1
  198. package/dist/ui/components.js +17 -226
  199. package/dist/ui/components.js.map +1 -1
  200. package/dist/ui/context.js +6 -6
  201. package/dist/ui/context.js.map +1 -1
  202. package/dist/ui/debug-log.d.ts +11 -0
  203. package/dist/ui/debug-log.d.ts.map +1 -0
  204. package/dist/ui/debug-log.js +21 -0
  205. package/dist/ui/debug-log.js.map +1 -0
  206. package/dist/ui/error-boundary.d.ts.map +1 -1
  207. package/dist/ui/error-boundary.js.map +1 -1
  208. package/dist/ui/frame.d.ts.map +1 -1
  209. package/dist/ui/frame.js +1 -3
  210. package/dist/ui/frame.js.map +1 -1
  211. package/dist/ui/index.d.ts +11 -3
  212. package/dist/ui/index.d.ts.map +1 -1
  213. package/dist/ui/index.js +45 -1076
  214. package/dist/ui/index.js.map +1 -1
  215. package/dist/ui/messages.d.ts +4 -7
  216. package/dist/ui/messages.d.ts.map +1 -1
  217. package/dist/ui/messages.js +15 -30
  218. package/dist/ui/messages.js.map +1 -1
  219. package/dist/ui/modals/index.d.ts +11 -0
  220. package/dist/ui/modals/index.d.ts.map +1 -0
  221. package/dist/ui/modals/index.js +10 -0
  222. package/dist/ui/modals/index.js.map +1 -0
  223. package/dist/ui/modals/prompts.d.ts +37 -0
  224. package/dist/ui/modals/prompts.d.ts.map +1 -0
  225. package/dist/ui/modals/prompts.js +124 -0
  226. package/dist/ui/modals/prompts.js.map +1 -0
  227. package/dist/ui/modals/selectors.d.ts +33 -0
  228. package/dist/ui/modals/selectors.d.ts.map +1 -0
  229. package/dist/ui/modals/selectors.js +111 -0
  230. package/dist/ui/modals/selectors.js.map +1 -0
  231. package/dist/ui/modals/setup.d.ts +17 -0
  232. package/dist/ui/modals/setup.d.ts.map +1 -0
  233. package/dist/ui/modals/setup.js +51 -0
  234. package/dist/ui/modals/setup.js.map +1 -0
  235. package/dist/ui/regions/input-region.d.ts +40 -0
  236. package/dist/ui/regions/input-region.d.ts.map +1 -0
  237. package/dist/ui/regions/input-region.js +116 -0
  238. package/dist/ui/regions/input-region.js.map +1 -0
  239. package/dist/ui/regions/modal-host.d.ts +41 -0
  240. package/dist/ui/regions/modal-host.d.ts.map +1 -0
  241. package/dist/ui/regions/modal-host.js +51 -0
  242. package/dist/ui/regions/modal-host.js.map +1 -0
  243. package/dist/ui/regions/render-probe.d.ts +22 -0
  244. package/dist/ui/regions/render-probe.d.ts.map +1 -0
  245. package/dist/ui/regions/render-probe.js +45 -0
  246. package/dist/ui/regions/render-probe.js.map +1 -0
  247. package/dist/ui/regions/static-scrollback.d.ts +39 -0
  248. package/dist/ui/regions/static-scrollback.d.ts.map +1 -0
  249. package/dist/ui/regions/static-scrollback.js +68 -0
  250. package/dist/ui/regions/static-scrollback.js.map +1 -0
  251. package/dist/ui/regions/status-region.d.ts +24 -0
  252. package/dist/ui/regions/status-region.d.ts.map +1 -0
  253. package/dist/ui/regions/status-region.js +17 -0
  254. package/dist/ui/regions/status-region.js.map +1 -0
  255. package/dist/ui/regions/transcript-region.d.ts +41 -0
  256. package/dist/ui/regions/transcript-region.d.ts.map +1 -0
  257. package/dist/ui/regions/transcript-region.js +52 -0
  258. package/dist/ui/regions/transcript-region.js.map +1 -0
  259. package/dist/ui/self-restart.d.ts +9 -0
  260. package/dist/ui/self-restart.d.ts.map +1 -0
  261. package/dist/ui/self-restart.js +24 -0
  262. package/dist/ui/self-restart.js.map +1 -0
  263. package/dist/ui/state/use-chat-controller.d.ts +23 -0
  264. package/dist/ui/state/use-chat-controller.d.ts.map +1 -0
  265. package/dist/ui/state/use-chat-controller.js +643 -0
  266. package/dist/ui/state/use-chat-controller.js.map +1 -0
  267. package/dist/ui/state/use-loop-state.d.ts +23 -0
  268. package/dist/ui/state/use-loop-state.d.ts.map +1 -0
  269. package/dist/ui/state/use-loop-state.js +39 -0
  270. package/dist/ui/state/use-loop-state.js.map +1 -0
  271. package/dist/ui/state/use-modal-state.d.ts +52 -0
  272. package/dist/ui/state/use-modal-state.d.ts.map +1 -0
  273. package/dist/ui/state/use-modal-state.js +44 -0
  274. package/dist/ui/state/use-modal-state.js.map +1 -0
  275. package/dist/ui/state/use-model-state.d.ts +29 -0
  276. package/dist/ui/state/use-model-state.d.ts.map +1 -0
  277. package/dist/ui/state/use-model-state.js +47 -0
  278. package/dist/ui/state/use-model-state.js.map +1 -0
  279. package/dist/ui/state/use-processing-state.d.ts +24 -0
  280. package/dist/ui/state/use-processing-state.d.ts.map +1 -0
  281. package/dist/ui/state/use-processing-state.js +46 -0
  282. package/dist/ui/state/use-processing-state.js.map +1 -0
  283. package/dist/ui/state/use-queue-state.d.ts +19 -0
  284. package/dist/ui/state/use-queue-state.d.ts.map +1 -0
  285. package/dist/ui/state/use-queue-state.js +30 -0
  286. package/dist/ui/state/use-queue-state.js.map +1 -0
  287. package/dist/ui/state/use-session-init.d.ts +22 -0
  288. package/dist/ui/state/use-session-init.d.ts.map +1 -0
  289. package/dist/ui/state/use-session-init.js +77 -0
  290. package/dist/ui/state/use-session-init.js.map +1 -0
  291. package/dist/ui/state/use-session-stats.d.ts +16 -0
  292. package/dist/ui/state/use-session-stats.d.ts.map +1 -0
  293. package/dist/ui/state/use-session-stats.js +18 -0
  294. package/dist/ui/state/use-session-stats.js.map +1 -0
  295. package/dist/ui/state/use-terminal-width.d.ts +8 -0
  296. package/dist/ui/state/use-terminal-width.d.ts.map +1 -0
  297. package/dist/ui/state/use-terminal-width.js +22 -0
  298. package/dist/ui/state/use-terminal-width.js.map +1 -0
  299. package/dist/ui/state/use-transcript-state.d.ts +21 -0
  300. package/dist/ui/state/use-transcript-state.d.ts.map +1 -0
  301. package/dist/ui/state/use-transcript-state.js +49 -0
  302. package/dist/ui/state/use-transcript-state.js.map +1 -0
  303. package/dist/ui/status-bar.d.ts.map +1 -1
  304. package/dist/ui/status-bar.js +2 -3
  305. package/dist/ui/status-bar.js.map +1 -1
  306. package/dist/version-check.d.ts.map +1 -1
  307. package/dist/version-check.js +10 -0
  308. package/dist/version-check.js.map +1 -1
  309. package/package.json +10 -3
  310. package/dist/agents/agent-config-loader.d.ts +0 -60
  311. package/dist/agents/agent-config-loader.d.ts.map +0 -1
  312. package/dist/agents/agent-config-loader.js +0 -402
  313. package/dist/agents/agent-config-loader.js.map +0 -1
  314. package/dist/agents/agent-config-presets.d.ts +0 -10
  315. package/dist/agents/agent-config-presets.d.ts.map +0 -1
  316. package/dist/agents/agent-config-presets.js +0 -940
  317. package/dist/agents/agent-config-presets.js.map +0 -1
  318. package/dist/agents/agent-config-types.d.ts +0 -145
  319. package/dist/agents/agent-config-types.d.ts.map +0 -1
  320. package/dist/agents/agent-config-types.js +0 -12
  321. package/dist/agents/agent-config-types.js.map +0 -1
  322. package/dist/agents/agent-detection.d.ts +0 -35
  323. package/dist/agents/agent-detection.d.ts.map +0 -1
  324. package/dist/agents/agent-detection.js +0 -110
  325. package/dist/agents/agent-detection.js.map +0 -1
  326. package/dist/agents/aggregator.d.ts +0 -19
  327. package/dist/agents/aggregator.d.ts.map +0 -1
  328. package/dist/agents/aggregator.js +0 -141
  329. package/dist/agents/aggregator.js.map +0 -1
  330. package/dist/agents/cli-backend.d.ts +0 -32
  331. package/dist/agents/cli-backend.d.ts.map +0 -1
  332. package/dist/agents/cli-backend.js +0 -271
  333. package/dist/agents/cli-backend.js.map +0 -1
  334. package/dist/agents/council-types.d.ts +0 -115
  335. package/dist/agents/council-types.d.ts.map +0 -1
  336. package/dist/agents/council-types.js +0 -81
  337. package/dist/agents/council-types.js.map +0 -1
  338. package/dist/agents/council.d.ts +0 -112
  339. package/dist/agents/council.d.ts.map +0 -1
  340. package/dist/agents/council.js +0 -722
  341. package/dist/agents/council.js.map +0 -1
  342. package/dist/agents/decomposer.d.ts +0 -33
  343. package/dist/agents/decomposer.d.ts.map +0 -1
  344. package/dist/agents/decomposer.js +0 -138
  345. package/dist/agents/decomposer.js.map +0 -1
  346. package/dist/agents/dynamic-tools.d.ts +0 -52
  347. package/dist/agents/dynamic-tools.d.ts.map +0 -1
  348. package/dist/agents/dynamic-tools.js +0 -424
  349. package/dist/agents/dynamic-tools.js.map +0 -1
  350. package/dist/agents/index.d.ts +0 -29
  351. package/dist/agents/index.d.ts.map +0 -1
  352. package/dist/agents/index.js +0 -29
  353. package/dist/agents/index.js.map +0 -1
  354. package/dist/agents/installer.d.ts +0 -39
  355. package/dist/agents/installer.d.ts.map +0 -1
  356. package/dist/agents/installer.js +0 -205
  357. package/dist/agents/installer.js.map +0 -1
  358. package/dist/agents/orchestrator.d.ts +0 -106
  359. package/dist/agents/orchestrator.d.ts.map +0 -1
  360. package/dist/agents/orchestrator.js +0 -363
  361. package/dist/agents/orchestrator.js.map +0 -1
  362. package/dist/agents/sdk-backend.d.ts +0 -63
  363. package/dist/agents/sdk-backend.d.ts.map +0 -1
  364. package/dist/agents/sdk-backend.js +0 -489
  365. package/dist/agents/sdk-backend.js.map +0 -1
  366. package/dist/agents/swarm-types.d.ts +0 -84
  367. package/dist/agents/swarm-types.d.ts.map +0 -1
  368. package/dist/agents/swarm-types.js +0 -20
  369. package/dist/agents/swarm-types.js.map +0 -1
  370. package/dist/agents/swarm.d.ts +0 -79
  371. package/dist/agents/swarm.d.ts.map +0 -1
  372. package/dist/agents/swarm.js +0 -375
  373. package/dist/agents/swarm.js.map +0 -1
  374. package/dist/agents/tools.d.ts +0 -26
  375. package/dist/agents/tools.d.ts.map +0 -1
  376. package/dist/agents/tools.js +0 -776
  377. package/dist/agents/tools.js.map +0 -1
  378. package/dist/agents/types.d.ts +0 -108
  379. package/dist/agents/types.d.ts.map +0 -1
  380. package/dist/agents/types.js +0 -43
  381. package/dist/agents/types.js.map +0 -1
  382. package/dist/api-server.d.ts +0 -45
  383. package/dist/api-server.d.ts.map +0 -1
  384. package/dist/api-server.js +0 -326
  385. package/dist/api-server.js.map +0 -1
  386. package/dist/auto-checkpoint.d.ts +0 -35
  387. package/dist/auto-checkpoint.d.ts.map +0 -1
  388. package/dist/auto-checkpoint.js +0 -176
  389. package/dist/auto-checkpoint.js.map +0 -1
  390. package/dist/background-jobs.d.ts +0 -45
  391. package/dist/background-jobs.d.ts.map +0 -1
  392. package/dist/background-jobs.js +0 -127
  393. package/dist/background-jobs.js.map +0 -1
  394. package/dist/branching.d.ts +0 -56
  395. package/dist/branching.d.ts.map +0 -1
  396. package/dist/branching.js +0 -224
  397. package/dist/branching.js.map +0 -1
  398. package/dist/cli/agent.d.ts +0 -9
  399. package/dist/cli/agent.d.ts.map +0 -1
  400. package/dist/cli/agent.js +0 -330
  401. package/dist/cli/agent.js.map +0 -1
  402. package/dist/cli/commands.d.ts +0 -12
  403. package/dist/cli/commands.d.ts.map +0 -1
  404. package/dist/cli/commands.js +0 -1042
  405. package/dist/cli/commands.js.map +0 -1
  406. package/dist/cli/index.d.ts +0 -8
  407. package/dist/cli/index.d.ts.map +0 -1
  408. package/dist/cli/index.js +0 -268
  409. package/dist/cli/index.js.map +0 -1
  410. package/dist/cli/types.d.ts +0 -33
  411. package/dist/cli/types.d.ts.map +0 -1
  412. package/dist/cli/types.js +0 -21
  413. package/dist/cli/types.js.map +0 -1
  414. package/dist/companions.d.ts +0 -54
  415. package/dist/companions.d.ts.map +0 -1
  416. package/dist/companions.js +0 -440
  417. package/dist/companions.js.map +0 -1
  418. package/dist/file-watcher.d.ts +0 -91
  419. package/dist/file-watcher.d.ts.map +0 -1
  420. package/dist/file-watcher.js +0 -269
  421. package/dist/file-watcher.js.map +0 -1
  422. package/dist/hud/theme-packs/api.d.ts +0 -51
  423. package/dist/hud/theme-packs/api.d.ts.map +0 -1
  424. package/dist/hud/theme-packs/api.js +0 -145
  425. package/dist/hud/theme-packs/api.js.map +0 -1
  426. package/dist/hud/theme-packs/index.d.ts +0 -18
  427. package/dist/hud/theme-packs/index.d.ts.map +0 -1
  428. package/dist/hud/theme-packs/index.js +0 -38
  429. package/dist/hud/theme-packs/index.js.map +0 -1
  430. package/dist/hud/theme-packs/types.d.ts +0 -29
  431. package/dist/hud/theme-packs/types.d.ts.map +0 -1
  432. package/dist/hud/theme-packs/types.js +0 -9
  433. package/dist/hud/theme-packs/types.js.map +0 -1
  434. package/dist/idle-eviction.d.ts +0 -34
  435. package/dist/idle-eviction.d.ts.map +0 -1
  436. package/dist/idle-eviction.js +0 -85
  437. package/dist/idle-eviction.js.map +0 -1
  438. package/dist/model-router.d.ts +0 -67
  439. package/dist/model-router.d.ts.map +0 -1
  440. package/dist/model-router.js.map +0 -1
  441. package/dist/providers/openai-compat-shims.d.ts +0 -31
  442. package/dist/providers/openai-compat-shims.d.ts.map +0 -1
  443. package/dist/providers/openai-compat-shims.js +0 -179
  444. package/dist/providers/openai-compat-shims.js.map +0 -1
  445. package/dist/sandbox-native.d.ts.map +0 -1
  446. package/dist/sandbox-native.js.map +0 -1
  447. package/dist/sandbox.d.ts.map +0 -1
  448. package/dist/sandbox.js.map +0 -1
  449. package/dist/session-timeout.d.ts +0 -31
  450. package/dist/session-timeout.d.ts.map +0 -1
  451. package/dist/session-timeout.js +0 -100
  452. package/dist/session-timeout.js.map +0 -1
  453. package/dist/smart-router.d.ts +0 -73
  454. package/dist/smart-router.d.ts.map +0 -1
  455. package/dist/smart-router.js +0 -332
  456. package/dist/smart-router.js.map +0 -1
  457. package/dist/terminal-recording.d.ts +0 -55
  458. package/dist/terminal-recording.d.ts.map +0 -1
  459. package/dist/terminal-recording.js +0 -182
  460. package/dist/terminal-recording.js.map +0 -1
  461. package/dist/tmux.d.ts +0 -35
  462. package/dist/tmux.d.ts.map +0 -1
  463. package/dist/tmux.js +0 -106
  464. package/dist/tmux.js.map +0 -1
  465. package/dist/ui/modals.d.ts +0 -72
  466. package/dist/ui/modals.d.ts.map +0 -1
  467. package/dist/ui/modals.js +0 -266
  468. package/dist/ui/modals.js.map +0 -1
  469. package/dist/ui/pack-picker.d.ts +0 -12
  470. package/dist/ui/pack-picker.d.ts.map +0 -1
  471. package/dist/ui/pack-picker.js +0 -101
  472. package/dist/ui/pack-picker.js.map +0 -1
  473. package/dist/ui/theme-picker.d.ts +0 -24
  474. package/dist/ui/theme-picker.d.ts.map +0 -1
  475. package/dist/ui/theme-picker.js +0 -190
  476. package/dist/ui/theme-picker.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"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"}
@@ -1,49 +1,82 @@
1
1
  /**
2
- * Calliope CLI - Checkpoint/Restore Module (#20)
2
+ * Calliope CLI - Checkpoint / Restore (git-based, #181)
3
3
  *
4
- * Saves file content before overwrites so users can restore previous versions.
5
- * Checkpoints are stored as individual JSON files in ~/.calliope-cli/checkpoints/
6
- * organized by session date.
4
+ * A single, git-backed checkpoint mechanism. Before a destructive tool call the
5
+ * agent creates a checkpoint commit of the working tree (createCheckpoint) and
6
+ * records a lightweight ref under refs/calliope/checkpoints/ so the checkpoint
7
+ * can later be listed, restored from, or cleared — all without rewriting
8
+ * history:
9
+ * - listCheckpoints() enumerates the checkpoint refs (newest first)
10
+ * - restoreFromCheckpoint() restores a single file's content from a checkpoint
11
+ * commit via `git show <ref>:<path>`
12
+ * - clearCheckpoints() deletes the checkpoint refs (the commits remain
13
+ * reachable from branch history; only the pointers
14
+ * are dropped, so history is never rewritten)
15
+ * - revertToLastCheckpoint() hard-resets the repo to the last checkpoint commit
16
+ *
17
+ * Inspired by autoresearch's git-as-ledger pattern where every experiment is a
18
+ * commit, making the full history auditable.
19
+ *
20
+ * Outside a git work tree every operation is a clean no-op: shouldCheckpoint
21
+ * returns false, createCheckpoint returns null, listCheckpoints returns [],
22
+ * restoreFromCheckpoint returns undefined, and clearCheckpoints returns 0.
7
23
  */
8
- export interface Checkpoint {
9
- filePath: string;
10
- content: string;
11
- timestamp: string;
12
- sessionId?: string;
13
- }
14
24
  export interface CheckpointSummary {
15
- file: string;
16
- filePath: string;
25
+ /** Full ref name under refs/calliope/checkpoints/. */
26
+ ref: string;
27
+ /** Short commit hash of the checkpoint. */
28
+ hash: string;
29
+ /** Commit subject (e.g. "[checkpoint] before write_file: src/main.ts"). */
30
+ subject: string;
31
+ /** ISO-8601 commit timestamp. */
17
32
  timestamp: string;
18
- sessionId?: string;
19
- size: number;
20
33
  }
21
34
  /**
22
- * Returns the checkpoint directory path (~/.calliope-cli/checkpoints/).
35
+ * Check if a tool call should trigger a checkpoint.
36
+ */
37
+ export declare function shouldCheckpoint(tool: string, args: Record<string, unknown>): boolean;
38
+ /**
39
+ * Create a checkpoint commit with the current staged + unstaged changes and
40
+ * record a ref pointing at it. Returns the commit hash if successful, null if
41
+ * nothing to commit.
42
+ */
43
+ export declare function createCheckpoint(tool: string, args: Record<string, unknown>): string | null;
44
+ /**
45
+ * Revert to the last checkpoint.
23
46
  */
24
- export declare function getCheckpointDir(): string;
47
+ export declare function revertToLastCheckpoint(): boolean;
25
48
  /**
26
- * Create a checkpoint for a file before it gets overwritten.
27
- * If content is provided, uses that; otherwise reads current content from disk.
28
- * Returns the checkpoint filename on success, or undefined if the file doesn't exist
29
- * and no content was provided.
49
+ * Get checkpoint stats.
30
50
  */
31
- export declare function createCheckpoint(filePath: string, content?: string, sessionId?: string): string | undefined;
51
+ export declare function getCheckpointStats(): {
52
+ enabled: boolean;
53
+ count: number;
54
+ lastHash: string | null;
55
+ };
32
56
  /**
33
- * Restore a file from its most recent checkpoint (or a specific index).
34
- * Index 0 = most recent, 1 = second most recent, etc.
35
- * Returns the restored content, or undefined if no checkpoint found.
57
+ * Enable or disable automatic checkpointing.
36
58
  */
37
- export declare function restoreCheckpoint(filePath: string, index?: number): string | undefined;
59
+ export declare function setEnabled(value: boolean): void;
38
60
  /**
39
- * List available checkpoints, optionally filtered by file path.
40
- * Returns summaries sorted newest-first.
61
+ * List available checkpoints, newest-first. When filePath is provided, only
62
+ * checkpoints whose commit tree contains that file are returned. Outside a git
63
+ * work tree this returns an empty list.
41
64
  */
42
65
  export declare function listCheckpoints(filePath?: string): CheckpointSummary[];
43
66
  /**
44
- * Clean up old checkpoints. If olderThanDays is provided, removes checkpoints
45
- * older than that many days. If omitted, removes all checkpoints.
46
- * Returns the number of checkpoints removed.
67
+ * Restore a single file's content from a checkpoint. Index 0 = most recent
68
+ * checkpoint containing the file, 1 = next, etc. The file's content is read
69
+ * from the checkpoint commit (`git show <hash>:<path>`) and written back to
70
+ * disk. Returns the restored content, or undefined if no matching checkpoint
71
+ * exists (including outside a git work tree).
72
+ */
73
+ export declare function restoreFromCheckpoint(filePath: string, index?: number): string | undefined;
74
+ /**
75
+ * Delete checkpoint refs. When olderThanDays is provided, only refs whose
76
+ * checkpoint commit is older than that many days are dropped; otherwise all
77
+ * checkpoint refs are dropped. The underlying commits remain reachable from
78
+ * branch history — only the checkpoint pointers are removed, so git history is
79
+ * never rewritten. Returns the number of refs removed (0 outside a git repo).
47
80
  */
48
81
  export declare function clearCheckpoints(olderThanDays?: number): number;
49
82
  //# sourceMappingURL=checkpoint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkpoint.d.ts","sourceRoot":"","sources":["../src/checkpoint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AA0BD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmD3G;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,MAAM,GAAG,SAAS,CAiBzF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAsCtE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAiC/D"}
1
+ {"version":3,"file":"checkpoint.d.ts","sourceRoot":"","sources":["../src/checkpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AA8BH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAgBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAYrF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAmD3F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAoBhD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAEjG;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE/C;AAMD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,iBAAiB,EAAE,CA0CtE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,MAAM,GAAG,SAAS,CAyB7F;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAmC/D"}
@@ -1,231 +1,318 @@
1
1
  /**
2
- * Calliope CLI - Checkpoint/Restore Module (#20)
2
+ * Calliope CLI - Checkpoint / Restore (git-based, #181)
3
3
  *
4
- * Saves file content before overwrites so users can restore previous versions.
5
- * Checkpoints are stored as individual JSON files in ~/.calliope-cli/checkpoints/
6
- * organized by session date.
4
+ * A single, git-backed checkpoint mechanism. Before a destructive tool call the
5
+ * agent creates a checkpoint commit of the working tree (createCheckpoint) and
6
+ * records a lightweight ref under refs/calliope/checkpoints/ so the checkpoint
7
+ * can later be listed, restored from, or cleared — all without rewriting
8
+ * history:
9
+ * - listCheckpoints() enumerates the checkpoint refs (newest first)
10
+ * - restoreFromCheckpoint() restores a single file's content from a checkpoint
11
+ * commit via `git show <ref>:<path>`
12
+ * - clearCheckpoints() deletes the checkpoint refs (the commits remain
13
+ * reachable from branch history; only the pointers
14
+ * are dropped, so history is never rewritten)
15
+ * - revertToLastCheckpoint() hard-resets the repo to the last checkpoint commit
16
+ *
17
+ * Inspired by autoresearch's git-as-ledger pattern where every experiment is a
18
+ * commit, making the full history auditable.
19
+ *
20
+ * Outside a git work tree every operation is a clean no-op: shouldCheckpoint
21
+ * returns false, createCheckpoint returns null, listCheckpoints returns [],
22
+ * restoreFromCheckpoint returns undefined, and clearCheckpoints returns 0.
7
23
  */
24
+ import { execFileSync } from 'child_process';
8
25
  import * as fs from 'fs';
9
26
  import * as path from 'path';
10
- import * as os from 'os';
11
27
  // ============================================================================
12
- // Directory Management
28
+ // Configuration
29
+ // ============================================================================
30
+ /** Namespace for the lightweight refs that mark each checkpoint commit. */
31
+ const CHECKPOINT_REF_PREFIX = 'refs/calliope/checkpoints';
32
+ /** Shell commands that are destructive (write, delete, move). */
33
+ const DESTRUCTIVE_SHELL_PATTERNS = [
34
+ /\brm\b/,
35
+ /\bmv\b/,
36
+ /\bcp\b.*\s-[^-]*f/, // cp -f (force overwrite)
37
+ /\bgit\s+(reset|checkout\s+--)\b/,
38
+ /\bgit\s+clean\b/,
39
+ /\bsed\s+-i\b/,
40
+ />\s*\S/, // output redirection
41
+ /\bdd\b/,
42
+ /\btruncate\b/,
43
+ ];
44
+ // ============================================================================
45
+ // State
46
+ // ============================================================================
47
+ let enabled = true;
48
+ let lastCheckpointHash = null;
49
+ /** Repo root the lastCheckpointHash belongs to — revert must target this, not live cwd. */
50
+ let lastCheckpointRoot = null;
51
+ let checkpointCount = 0;
52
+ // ============================================================================
53
+ // Public API — automatic checkpointing (agent loop)
13
54
  // ============================================================================
14
55
  /**
15
- * Returns the checkpoint directory path (~/.calliope-cli/checkpoints/).
56
+ * Check if a tool call should trigger a checkpoint.
16
57
  */
17
- export function getCheckpointDir() {
18
- const dir = path.join(os.homedir(), '.calliope-cli', 'checkpoints');
19
- if (!fs.existsSync(dir)) {
20
- fs.mkdirSync(dir, { recursive: true });
58
+ export function shouldCheckpoint(tool, args) {
59
+ if (!enabled)
60
+ return false;
61
+ if (!isGitRepo())
62
+ return false;
63
+ if (tool === 'write_file')
64
+ return true;
65
+ if (tool === 'shell') {
66
+ const command = String(args.command || '');
67
+ return DESTRUCTIVE_SHELL_PATTERNS.some(p => p.test(command));
21
68
  }
22
- return dir;
23
- }
24
- let checkpointCounter = 0;
25
- /** Auto-cleanup: remove checkpoints older than this many days */
26
- const AUTO_CLEANUP_DAYS = 7;
27
- /** Minimum interval between auto-cleanup runs (1 hour in ms) */
28
- const AUTO_CLEANUP_INTERVAL = 60 * 60 * 1000;
29
- /** Timestamp of last auto-cleanup run */
30
- let lastAutoCleanup = 0;
31
- /**
32
- * Generate a unique checkpoint filename from a timestamp.
33
- */
34
- function makeFilename(timestamp) {
35
- // Replace colons and dots for filesystem safety + add counter to avoid same-millisecond collisions
36
- const counter = String(checkpointCounter++).padStart(4, '0');
37
- return `checkpoint-${timestamp.replace(/[:\.]/g, '-')}-${counter}.json`;
69
+ return false;
38
70
  }
39
- // ============================================================================
40
- // Core API
41
- // ============================================================================
42
71
  /**
43
- * Create a checkpoint for a file before it gets overwritten.
44
- * If content is provided, uses that; otherwise reads current content from disk.
45
- * Returns the checkpoint filename on success, or undefined if the file doesn't exist
46
- * and no content was provided.
72
+ * Create a checkpoint commit with the current staged + unstaged changes and
73
+ * record a ref pointing at it. Returns the commit hash if successful, null if
74
+ * nothing to commit.
47
75
  */
48
- export function createCheckpoint(filePath, content, sessionId) {
49
- // Auto-cleanup old checkpoints periodically (at most once per hour)
50
- const now = Date.now();
51
- if (now - lastAutoCleanup > AUTO_CLEANUP_INTERVAL) {
52
- lastAutoCleanup = now;
76
+ export function createCheckpoint(tool, args) {
77
+ if (!isGitRepo())
78
+ return null;
79
+ try {
80
+ // Capture the repo root once, at checkpoint time, and pin every git call for
81
+ // this checkpoint to it. process.cwd() may change before the matching revert.
82
+ const root = gitRepoRoot();
83
+ if (!root)
84
+ return null;
85
+ // Check if there are any changes to commit
86
+ const status = git(root, 'status', '--porcelain');
87
+ if (!status.trim())
88
+ return null; // Nothing to checkpoint
89
+ // Stage all tracked changes (don't add untracked files)
90
+ git(root, 'add', '-u');
91
+ // Check if there's anything staged
92
+ const staged = git(root, 'diff', '--cached', '--stat');
93
+ if (!staged.trim())
94
+ return null;
95
+ // Create checkpoint commit
96
+ const argSummary = tool === 'write_file'
97
+ ? String(args.path || '')
98
+ : tool === 'shell'
99
+ ? String(args.command || '').substring(0, 50)
100
+ : tool;
101
+ const message = `[checkpoint] before ${tool}: ${argSummary}`;
102
+ git(root, 'commit', '-m', message, '--no-gpg-sign');
103
+ // Get the commit hash
104
+ const hash = git(root, 'rev-parse', '--short', 'HEAD').trim();
105
+ lastCheckpointHash = hash;
106
+ lastCheckpointRoot = root;
107
+ checkpointCount++;
108
+ // Record a lightweight ref so this checkpoint can be listed, restored, and
109
+ // cleared without rewriting history. Best-effort: a ref failure must not
110
+ // invalidate the (already committed) checkpoint.
53
111
  try {
54
- clearCheckpoints(AUTO_CLEANUP_DAYS);
112
+ const refId = `${new Date().toISOString().replace(/[:.]/g, '-')}-${String(checkpointCount).padStart(4, '0')}`;
113
+ git(root, 'update-ref', `${CHECKPOINT_REF_PREFIX}/${refId}`, hash);
55
114
  }
56
115
  catch {
57
- // Don't let cleanup errors block checkpoint creation
116
+ // Ref tracking is best-effort; the checkpoint commit already exists.
58
117
  }
118
+ return hash;
59
119
  }
60
- const absPath = path.resolve(filePath);
61
- // Determine content to save
62
- let fileContent;
63
- if (content !== undefined) {
64
- fileContent = content;
120
+ catch {
121
+ // Checkpoint failed silently — don't block the agent
122
+ return null;
65
123
  }
66
- else {
67
- try {
68
- if (!fs.existsSync(absPath)) {
69
- return undefined;
70
- }
71
- fileContent = fs.readFileSync(absPath, 'utf-8');
72
- }
73
- catch {
74
- return undefined;
75
- }
124
+ }
125
+ /**
126
+ * Revert to the last checkpoint.
127
+ */
128
+ export function revertToLastCheckpoint() {
129
+ if (!lastCheckpointHash || !lastCheckpointRoot)
130
+ return false;
131
+ // Reset only the repo the checkpoint was created in. If that root has since
132
+ // moved or no longer resolves to the same repo, bail rather than risk a
133
+ // destructive cross-repo `git reset --hard` against the live cwd.
134
+ let currentRoot;
135
+ try {
136
+ currentRoot = gitRepoRoot(lastCheckpointRoot);
76
137
  }
77
- const timestamp = new Date().toISOString();
78
- const checkpoint = {
79
- filePath: absPath,
80
- content: fileContent,
81
- timestamp,
82
- ...(sessionId ? { sessionId } : {}),
83
- };
84
- const dir = getCheckpointDir();
85
- const filename = makeFilename(timestamp);
86
- const fullPath = path.join(dir, filename);
87
- // Atomic write so a crash mid-write can't leave a truncated checkpoint.
88
- const tmp = `${fullPath}.${process.pid}.${Date.now()}.tmp`;
138
+ catch {
139
+ return false;
140
+ }
141
+ if (currentRoot !== lastCheckpointRoot)
142
+ return false;
89
143
  try {
90
- fs.writeFileSync(tmp, JSON.stringify(checkpoint, null, 2));
91
- fs.renameSync(tmp, fullPath);
144
+ git(lastCheckpointRoot, 'reset', '--hard', lastCheckpointHash);
145
+ return true;
92
146
  }
93
- catch (e) {
94
- try {
95
- fs.unlinkSync(tmp);
96
- }
97
- catch { /* best effort */ }
98
- throw e;
147
+ catch {
148
+ return false;
99
149
  }
100
- return filename;
101
150
  }
102
151
  /**
103
- * Restore a file from its most recent checkpoint (or a specific index).
104
- * Index 0 = most recent, 1 = second most recent, etc.
105
- * Returns the restored content, or undefined if no checkpoint found.
152
+ * Get checkpoint stats.
106
153
  */
107
- export function restoreCheckpoint(filePath, index = 0) {
108
- const absPath = path.resolve(filePath);
109
- const checkpoints = getCheckpointsForFile(absPath);
110
- if (index < 0 || index >= checkpoints.length) {
111
- return undefined;
112
- }
113
- const checkpoint = checkpoints[index];
114
- // Write the content back to the original file
115
- const dir = path.dirname(absPath);
116
- if (!fs.existsSync(dir)) {
117
- fs.mkdirSync(dir, { recursive: true });
118
- }
119
- fs.writeFileSync(absPath, checkpoint.content);
120
- return checkpoint.content;
154
+ export function getCheckpointStats() {
155
+ return { enabled, count: checkpointCount, lastHash: lastCheckpointHash };
156
+ }
157
+ /**
158
+ * Enable or disable automatic checkpointing.
159
+ */
160
+ export function setEnabled(value) {
161
+ enabled = value;
121
162
  }
163
+ // ============================================================================
164
+ // Public API — list / restore / clear (user commands)
165
+ // ============================================================================
122
166
  /**
123
- * List available checkpoints, optionally filtered by file path.
124
- * Returns summaries sorted newest-first.
167
+ * List available checkpoints, newest-first. When filePath is provided, only
168
+ * checkpoints whose commit tree contains that file are returned. Outside a git
169
+ * work tree this returns an empty list.
125
170
  */
126
171
  export function listCheckpoints(filePath) {
127
- const dir = getCheckpointDir();
128
- let files;
172
+ const root = gitRepoRoot();
173
+ if (!root)
174
+ return [];
175
+ let out;
129
176
  try {
130
- files = fs.readdirSync(dir).filter(f => f.startsWith('checkpoint-') && f.endsWith('.json'));
177
+ out = git(root, 'for-each-ref', '--sort=-refname', '--format=%(objectname:short)%09%(refname)%09%(committerdate:iso-strict)%09%(subject)', CHECKPOINT_REF_PREFIX);
131
178
  }
132
179
  catch {
133
180
  return [];
134
181
  }
182
+ const rel = filePath !== undefined ? path.relative(root, path.resolve(filePath)) : undefined;
135
183
  const summaries = [];
136
- for (const file of files) {
137
- try {
138
- const raw = fs.readFileSync(path.join(dir, file), 'utf-8');
139
- const cp = JSON.parse(raw);
140
- // Filter by file path if specified
141
- if (filePath) {
142
- const absFilter = path.resolve(filePath);
143
- if (cp.filePath !== absFilter)
144
- continue;
184
+ for (const line of out.split('\n')) {
185
+ if (!line.trim())
186
+ continue;
187
+ const parts = line.split('\t');
188
+ const hash = parts[0];
189
+ const ref = parts[1];
190
+ const timestamp = parts[2];
191
+ const subject = parts.slice(3).join('\t');
192
+ if (!hash || !ref)
193
+ continue;
194
+ // When filtering by file, keep only checkpoints whose tree contains it.
195
+ if (rel !== undefined) {
196
+ try {
197
+ git(root, 'cat-file', '-e', `${hash}:${rel}`);
198
+ }
199
+ catch {
200
+ continue;
145
201
  }
146
- summaries.push({
147
- file,
148
- filePath: cp.filePath,
149
- timestamp: cp.timestamp,
150
- sessionId: cp.sessionId,
151
- size: cp.content.length,
152
- });
153
- }
154
- catch {
155
- // Skip corrupted checkpoint files
156
202
  }
203
+ summaries.push({ ref, hash, subject, timestamp: timestamp ?? '' });
157
204
  }
158
- // Sort newest first
159
- summaries.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
160
205
  return summaries;
161
206
  }
162
207
  /**
163
- * Clean up old checkpoints. If olderThanDays is provided, removes checkpoints
164
- * older than that many days. If omitted, removes all checkpoints.
165
- * Returns the number of checkpoints removed.
208
+ * Restore a single file's content from a checkpoint. Index 0 = most recent
209
+ * checkpoint containing the file, 1 = next, etc. The file's content is read
210
+ * from the checkpoint commit (`git show <hash>:<path>`) and written back to
211
+ * disk. Returns the restored content, or undefined if no matching checkpoint
212
+ * exists (including outside a git work tree).
213
+ */
214
+ export function restoreFromCheckpoint(filePath, index = 0) {
215
+ const root = gitRepoRoot();
216
+ if (!root)
217
+ return undefined;
218
+ const checkpoints = listCheckpoints(filePath);
219
+ if (index < 0 || index >= checkpoints.length)
220
+ return undefined;
221
+ const cp = checkpoints[index];
222
+ const absPath = path.resolve(filePath);
223
+ const rel = path.relative(root, absPath);
224
+ let content;
225
+ try {
226
+ content = git(root, 'show', `${cp.hash}:${rel}`);
227
+ }
228
+ catch {
229
+ return undefined;
230
+ }
231
+ const dir = path.dirname(absPath);
232
+ if (!fs.existsSync(dir)) {
233
+ fs.mkdirSync(dir, { recursive: true });
234
+ }
235
+ fs.writeFileSync(absPath, content);
236
+ return content;
237
+ }
238
+ /**
239
+ * Delete checkpoint refs. When olderThanDays is provided, only refs whose
240
+ * checkpoint commit is older than that many days are dropped; otherwise all
241
+ * checkpoint refs are dropped. The underlying commits remain reachable from
242
+ * branch history — only the checkpoint pointers are removed, so git history is
243
+ * never rewritten. Returns the number of refs removed (0 outside a git repo).
166
244
  */
167
245
  export function clearCheckpoints(olderThanDays) {
168
- const dir = getCheckpointDir();
169
- let files;
246
+ const root = gitRepoRoot();
247
+ if (!root)
248
+ return 0;
249
+ let out;
170
250
  try {
171
- files = fs.readdirSync(dir).filter(f => f.startsWith('checkpoint-') && f.endsWith('.json'));
251
+ out = git(root, 'for-each-ref', '--format=%(refname)%09%(committerdate:unix)', CHECKPOINT_REF_PREFIX);
172
252
  }
173
253
  catch {
174
254
  return 0;
175
255
  }
176
256
  const cutoff = olderThanDays !== undefined
177
- ? new Date(Date.now() - olderThanDays * 24 * 60 * 60 * 1000)
257
+ ? Date.now() - olderThanDays * 24 * 60 * 60 * 1000
178
258
  : null;
179
259
  let removed = 0;
180
- for (const file of files) {
181
- const fullPath = path.join(dir, file);
260
+ for (const line of out.split('\n')) {
261
+ if (!line.trim())
262
+ continue;
263
+ const [ref, unix] = line.split('\t');
264
+ if (!ref)
265
+ continue;
266
+ if (cutoff !== null) {
267
+ const ts = parseInt(unix ?? '', 10) * 1000;
268
+ if (Number.isFinite(ts) && ts >= cutoff)
269
+ continue; // keep recent
270
+ }
182
271
  try {
183
- if (cutoff) {
184
- const raw = fs.readFileSync(fullPath, 'utf-8');
185
- const cp = JSON.parse(raw);
186
- const cpDate = new Date(cp.timestamp);
187
- if (cpDate >= cutoff)
188
- continue;
189
- }
190
- fs.unlinkSync(fullPath);
272
+ git(root, 'update-ref', '-d', ref);
191
273
  removed++;
192
274
  }
193
275
  catch {
194
- // Skip files that can't be read/deleted
276
+ // Skip refs we can't delete.
195
277
  }
196
278
  }
197
279
  return removed;
198
280
  }
199
281
  // ============================================================================
200
- // Internal Helpers
282
+ // Helpers
201
283
  // ============================================================================
202
284
  /**
203
- * Get all checkpoints for a specific file path, sorted newest-first.
285
+ * Whether the given directory (default: live cwd) is inside a git work tree.
286
+ * Not memoized: the answer depends on cwd, which changes over a session.
204
287
  */
205
- function getCheckpointsForFile(absPath) {
206
- const dir = getCheckpointDir();
207
- let files;
288
+ function isGitRepo(cwd = process.cwd()) {
208
289
  try {
209
- files = fs.readdirSync(dir).filter(f => f.startsWith('checkpoint-') && f.endsWith('.json'));
290
+ git(cwd, 'rev-parse', '--is-inside-work-tree');
291
+ return true;
210
292
  }
211
293
  catch {
212
- return [];
294
+ return false;
213
295
  }
214
- const checkpoints = [];
215
- for (const file of files) {
216
- try {
217
- const raw = fs.readFileSync(path.join(dir, file), 'utf-8');
218
- const cp = JSON.parse(raw);
219
- if (cp.filePath === absPath) {
220
- checkpoints.push(cp);
221
- }
222
- }
223
- catch {
224
- // Skip corrupted files
225
- }
296
+ }
297
+ /**
298
+ * Resolve the absolute repo root for the given directory (default: live cwd).
299
+ * Returns null if not inside a git work tree.
300
+ */
301
+ function gitRepoRoot(cwd = process.cwd()) {
302
+ try {
303
+ const root = git(cwd, 'rev-parse', '--show-toplevel').trim();
304
+ return root || null;
305
+ }
306
+ catch {
307
+ return null;
226
308
  }
227
- // Sort newest first
228
- checkpoints.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
229
- return checkpoints;
309
+ }
310
+ function git(cwd, ...args) {
311
+ return execFileSync('git', args, {
312
+ cwd,
313
+ encoding: 'utf-8',
314
+ timeout: 5000,
315
+ stdio: ['pipe', 'pipe', 'pipe'],
316
+ });
230
317
  }
231
318
  //# sourceMappingURL=checkpoint.js.map