@pentoshi/clai 4.14.4 → 4.15.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 (463) hide show
  1. package/CONTRIBUTING.md +4 -0
  2. package/PROVIDERS.md +2 -0
  3. package/README.md +41 -5
  4. package/dist/agent/compaction-summary.d.ts +6 -1
  5. package/dist/agent/compaction-summary.js +46 -20
  6. package/dist/agent/compaction-summary.js.map +1 -1
  7. package/dist/agent/confirm-port.d.ts +3 -8
  8. package/dist/agent/confirm-port.js +9 -7
  9. package/dist/agent/confirm-port.js.map +1 -1
  10. package/dist/agent/context/compact-with-summary.js +55 -14
  11. package/dist/agent/context/compact-with-summary.js.map +1 -1
  12. package/dist/agent/context/compaction-recent-history.js +4 -2
  13. package/dist/agent/context/compaction-recent-history.js.map +1 -1
  14. package/dist/agent/context/compaction-user-instructions.d.ts +12 -0
  15. package/dist/agent/context/compaction-user-instructions.js +264 -0
  16. package/dist/agent/context/compaction-user-instructions.js.map +1 -0
  17. package/dist/agent/context/compaction-work-history.d.ts +13 -0
  18. package/dist/agent/context/compaction-work-history.js +150 -0
  19. package/dist/agent/context/compaction-work-history.js.map +1 -0
  20. package/dist/agent/context-manager.js +19 -5
  21. package/dist/agent/context-manager.js.map +1 -1
  22. package/dist/agent/plan-implement-compact.js +2 -1
  23. package/dist/agent/plan-implement-compact.js.map +1 -1
  24. package/dist/agent/subagents/read-only-tools.js +2 -2
  25. package/dist/agent/subagents/read-only-tools.js.map +1 -1
  26. package/dist/agent/turn/loop/stream-session.js +33 -27
  27. package/dist/agent/turn/loop/stream-session.js.map +1 -1
  28. package/dist/agent/turn/tool-execution/authorization.js +1 -1
  29. package/dist/agent/turn/tool-execution/authorization.js.map +1 -1
  30. package/dist/app/adapters/current-store-adapter.js +2 -2
  31. package/dist/app/adapters/current-store-adapter.js.map +1 -1
  32. package/dist/app/adapters/current-updates-adapter.d.ts +1 -1
  33. package/dist/app/adapters/current-updates-adapter.js +4 -13
  34. package/dist/app/adapters/current-updates-adapter.js.map +1 -1
  35. package/dist/app/commands/catalog.js +1 -0
  36. package/dist/app/commands/catalog.js.map +1 -1
  37. package/dist/app/controllers/session-changes.d.ts +24 -0
  38. package/dist/app/controllers/session-changes.js +75 -0
  39. package/dist/app/controllers/session-changes.js.map +1 -0
  40. package/dist/app/controllers/session-controller.d.ts +9 -0
  41. package/dist/app/controllers/session-controller.js +67 -7
  42. package/dist/app/controllers/session-controller.js.map +1 -1
  43. package/dist/app/ports/confirm-port.d.ts +4 -1
  44. package/dist/app/ports/persistence-port.d.ts +2 -0
  45. package/dist/app/ports/transcript-item.d.ts +2 -0
  46. package/dist/app/ports/updates-port.d.ts +1 -1
  47. package/dist/classic/app/ClassicApp.js +42 -33
  48. package/dist/classic/app/ClassicApp.js.map +1 -1
  49. package/dist/classic/app/action-handlers.js +7 -0
  50. package/dist/classic/app/action-handlers.js.map +1 -1
  51. package/dist/classic/app/app-wiring.d.ts +8 -1
  52. package/dist/classic/app/app-wiring.js +23 -4
  53. package/dist/classic/app/app-wiring.js.map +1 -1
  54. package/dist/classic/app/paint-pacing.d.ts +3 -1
  55. package/dist/classic/app/paint-pacing.js +9 -1
  56. package/dist/classic/app/paint-pacing.js.map +1 -1
  57. package/dist/classic/app/use-feed.js +8 -3
  58. package/dist/classic/app/use-feed.js.map +1 -1
  59. package/dist/classic/app/wiring-composer-pointer.d.ts +3 -0
  60. package/dist/classic/app/wiring-composer-pointer.js +22 -0
  61. package/dist/classic/app/wiring-composer-pointer.js.map +1 -0
  62. package/dist/classic/app/wiring-disclosure.d.ts +3 -0
  63. package/dist/classic/app/wiring-disclosure.js +31 -0
  64. package/dist/classic/app/wiring-disclosure.js.map +1 -0
  65. package/dist/classic/app/wiring-interactions.d.ts +1 -0
  66. package/dist/classic/app/wiring-interactions.js +16 -16
  67. package/dist/classic/app/wiring-interactions.js.map +1 -1
  68. package/dist/classic/app/wiring-jump-to-latest.d.ts +3 -0
  69. package/dist/classic/app/wiring-jump-to-latest.js +38 -0
  70. package/dist/classic/app/wiring-jump-to-latest.js.map +1 -0
  71. package/dist/classic/app/wiring-lifecycle.d.ts +1 -1
  72. package/dist/classic/app/wiring-lifecycle.js +19 -10
  73. package/dist/classic/app/wiring-lifecycle.js.map +1 -1
  74. package/dist/classic/app/wiring-selection.d.ts +1 -0
  75. package/dist/classic/app/wiring-selection.js +10 -1
  76. package/dist/classic/app/wiring-selection.js.map +1 -1
  77. package/dist/classic/app/wiring-types.d.ts +12 -1
  78. package/dist/classic/blocks/assistant-lines.js +1 -1
  79. package/dist/classic/blocks/assistant-lines.js.map +1 -1
  80. package/dist/classic/blocks/batch-lines.d.ts +1 -1
  81. package/dist/classic/blocks/batch-lines.js +47 -59
  82. package/dist/classic/blocks/batch-lines.js.map +1 -1
  83. package/dist/classic/blocks/block-context.d.ts +8 -1
  84. package/dist/classic/blocks/block-context.js.map +1 -1
  85. package/dist/classic/blocks/compacted-lines.d.ts +0 -1
  86. package/dist/classic/blocks/compacted-lines.js +12 -44
  87. package/dist/classic/blocks/compacted-lines.js.map +1 -1
  88. package/dist/classic/blocks/diff-lines.d.ts +3 -5
  89. package/dist/classic/blocks/diff-lines.js +113 -152
  90. package/dist/classic/blocks/diff-lines.js.map +1 -1
  91. package/dist/classic/blocks/disclosure-lines.d.ts +16 -0
  92. package/dist/classic/blocks/disclosure-lines.js +20 -0
  93. package/dist/classic/blocks/disclosure-lines.js.map +1 -0
  94. package/dist/classic/blocks/intro-lines.js +2 -0
  95. package/dist/classic/blocks/intro-lines.js.map +1 -1
  96. package/dist/classic/blocks/notice-lines.js +4 -16
  97. package/dist/classic/blocks/notice-lines.js.map +1 -1
  98. package/dist/classic/blocks/output-lines.d.ts +10 -0
  99. package/dist/classic/blocks/output-lines.js +35 -0
  100. package/dist/classic/blocks/output-lines.js.map +1 -0
  101. package/dist/classic/blocks/thinking-lines.d.ts +0 -1
  102. package/dist/classic/blocks/thinking-lines.js +15 -32
  103. package/dist/classic/blocks/thinking-lines.js.map +1 -1
  104. package/dist/classic/blocks/tool-label.d.ts +2 -0
  105. package/dist/classic/blocks/tool-label.js +8 -0
  106. package/dist/classic/blocks/tool-label.js.map +1 -0
  107. package/dist/classic/blocks/tool-lines.d.ts +3 -5
  108. package/dist/classic/blocks/tool-lines.js +90 -150
  109. package/dist/classic/blocks/tool-lines.js.map +1 -1
  110. package/dist/classic/blocks/turn-summary-lines.js +7 -1
  111. package/dist/classic/blocks/turn-summary-lines.js.map +1 -1
  112. package/dist/classic/blocks/user-lines.js +9 -15
  113. package/dist/classic/blocks/user-lines.js.map +1 -1
  114. package/dist/classic/bootstrap/start-classic.js +2 -0
  115. package/dist/classic/bootstrap/start-classic.js.map +1 -1
  116. package/dist/classic/chrome/Composer.d.ts +4 -2
  117. package/dist/classic/chrome/Composer.js +12 -6
  118. package/dist/classic/chrome/Composer.js.map +1 -1
  119. package/dist/classic/chrome/composer-controller.d.ts +3 -0
  120. package/dist/classic/chrome/composer-controller.js +15 -22
  121. package/dist/classic/chrome/composer-controller.js.map +1 -1
  122. package/dist/classic/chrome/composer-frame.d.ts +1 -1
  123. package/dist/classic/chrome/composer-frame.js +2 -1
  124. package/dist/classic/chrome/composer-frame.js.map +1 -1
  125. package/dist/classic/chrome/composer-mentions.d.ts +2 -0
  126. package/dist/classic/chrome/composer-mentions.js +16 -0
  127. package/dist/classic/chrome/composer-mentions.js.map +1 -0
  128. package/dist/classic/chrome/composer-pointer.d.ts +13 -0
  129. package/dist/classic/chrome/composer-pointer.js +22 -0
  130. package/dist/classic/chrome/composer-pointer.js.map +1 -0
  131. package/dist/classic/chrome/directory-row.d.ts +20 -2
  132. package/dist/classic/chrome/directory-row.js +45 -1
  133. package/dist/classic/chrome/directory-row.js.map +1 -1
  134. package/dist/classic/chrome/editor-view.js +6 -1
  135. package/dist/classic/chrome/editor-view.js.map +1 -1
  136. package/dist/classic/chrome/queue-rows.d.ts +1 -0
  137. package/dist/classic/chrome/queue-rows.js +12 -2
  138. package/dist/classic/chrome/queue-rows.js.map +1 -1
  139. package/dist/classic/chrome/status-rows.d.ts +1 -0
  140. package/dist/classic/chrome/status-rows.js +5 -4
  141. package/dist/classic/chrome/status-rows.js.map +1 -1
  142. package/dist/classic/chrome/toast-rows.js +7 -6
  143. package/dist/classic/chrome/toast-rows.js.map +1 -1
  144. package/dist/classic/feed/LiveTail.d.ts +4 -3
  145. package/dist/classic/feed/LiveTail.js +26 -15
  146. package/dist/classic/feed/LiveTail.js.map +1 -1
  147. package/dist/classic/feed/feed-blocks.d.ts +2 -0
  148. package/dist/classic/feed/feed-blocks.js +4 -2
  149. package/dist/classic/feed/feed-blocks.js.map +1 -1
  150. package/dist/classic/feed/transcript-disclosure.d.ts +6 -0
  151. package/dist/classic/feed/transcript-disclosure.js +9 -0
  152. package/dist/classic/feed/transcript-disclosure.js.map +1 -0
  153. package/dist/classic/feed/transcript-resources.d.ts +23 -0
  154. package/dist/classic/feed/transcript-resources.js +140 -0
  155. package/dist/classic/feed/transcript-resources.js.map +1 -0
  156. package/dist/classic/feed/transcript-window.js +43 -18
  157. package/dist/classic/feed/transcript-window.js.map +1 -1
  158. package/dist/classic/input/input-router.d.ts +2 -0
  159. package/dist/classic/input/input-router.js +6 -0
  160. package/dist/classic/input/input-router.js.map +1 -1
  161. package/dist/classic/input/raw-decoder.js +3 -2
  162. package/dist/classic/input/raw-decoder.js.map +1 -1
  163. package/dist/classic/panels/confirm-panel.js +17 -10
  164. package/dist/classic/panels/confirm-panel.js.map +1 -1
  165. package/dist/classic/panels/pager-panel.d.ts +6 -2
  166. package/dist/classic/panels/pager-panel.js +11 -4
  167. package/dist/classic/panels/pager-panel.js.map +1 -1
  168. package/dist/classic/panels/panel-controller.js +4 -1
  169. package/dist/classic/panels/panel-controller.js.map +1 -1
  170. package/dist/classic/panels/panel-host.js +1 -1
  171. package/dist/classic/panels/panel-host.js.map +1 -1
  172. package/dist/classic/panels/panel-wheel.js +1 -1
  173. package/dist/classic/panels/panel-wheel.js.map +1 -1
  174. package/dist/classic/render/shell-width.d.ts +0 -2
  175. package/dist/classic/render/shell-width.js +0 -6
  176. package/dist/classic/render/shell-width.js.map +1 -1
  177. package/dist/commands/update/detection.d.ts +20 -0
  178. package/dist/commands/update/detection.js +207 -0
  179. package/dist/commands/update/detection.js.map +1 -0
  180. package/dist/commands/update/download.d.ts +3 -0
  181. package/dist/commands/update/download.js +63 -0
  182. package/dist/commands/update/download.js.map +1 -0
  183. package/dist/commands/update/installers.d.ts +16 -5
  184. package/dist/commands/update/installers.js +12 -513
  185. package/dist/commands/update/installers.js.map +1 -1
  186. package/dist/commands/update/lock.d.ts +6 -0
  187. package/dist/commands/update/lock.js +86 -0
  188. package/dist/commands/update/lock.js.map +1 -0
  189. package/dist/commands/update/metadata.d.ts +6 -0
  190. package/dist/commands/update/metadata.js +36 -0
  191. package/dist/commands/update/metadata.js.map +1 -0
  192. package/dist/commands/update/native.d.ts +3 -0
  193. package/dist/commands/update/native.js +179 -0
  194. package/dist/commands/update/native.js.map +1 -0
  195. package/dist/commands/update/package-managers.d.ts +4 -0
  196. package/dist/commands/update/package-managers.js +158 -0
  197. package/dist/commands/update/package-managers.js.map +1 -0
  198. package/dist/commands/update/process.d.ts +17 -0
  199. package/dist/commands/update/process.js +114 -0
  200. package/dist/commands/update/process.js.map +1 -0
  201. package/dist/commands/update/source-worker.d.ts +2 -0
  202. package/dist/commands/update/source-worker.js +71 -0
  203. package/dist/commands/update/source-worker.js.map +1 -0
  204. package/dist/commands/update/source.d.ts +2 -0
  205. package/dist/commands/update/source.js +79 -0
  206. package/dist/commands/update/source.js.map +1 -0
  207. package/dist/commands/update/verification.d.ts +7 -0
  208. package/dist/commands/update/verification.js +73 -0
  209. package/dist/commands/update/verification.js.map +1 -0
  210. package/dist/commands/update/windows-stage.d.ts +21 -0
  211. package/dist/commands/update/windows-stage.js +186 -0
  212. package/dist/commands/update/windows-stage.js.map +1 -0
  213. package/dist/commands/update-install.d.ts +4 -13
  214. package/dist/commands/update-install.js +20 -152
  215. package/dist/commands/update-install.js.map +1 -1
  216. package/dist/commands/update.d.ts +4 -9
  217. package/dist/commands/update.js +51 -103
  218. package/dist/commands/update.js.map +1 -1
  219. package/dist/index.js +1 -1
  220. package/dist/index.js.map +1 -1
  221. package/dist/instructions/record.d.ts +1 -1
  222. package/dist/instructions/record.js +3 -3
  223. package/dist/llm/free-client.d.ts +2 -0
  224. package/dist/llm/free-client.js +52 -0
  225. package/dist/llm/free-client.js.map +1 -0
  226. package/dist/llm/free.d.ts +1 -0
  227. package/dist/llm/free.js +77 -176
  228. package/dist/llm/free.js.map +1 -1
  229. package/dist/llm/key-rotation.d.ts +1 -0
  230. package/dist/llm/key-rotation.js +13 -2
  231. package/dist/llm/key-rotation.js.map +1 -1
  232. package/dist/llm/reasoning-errors.js +1 -1
  233. package/dist/llm/reasoning-errors.js.map +1 -1
  234. package/dist/llm/responses-error.d.ts +3 -0
  235. package/dist/llm/responses-error.js +37 -0
  236. package/dist/llm/responses-error.js.map +1 -0
  237. package/dist/llm/responses-http.js +5 -2
  238. package/dist/llm/responses-http.js.map +1 -1
  239. package/dist/llm/responses-replay.d.ts +2 -0
  240. package/dist/llm/responses-replay.js +37 -1
  241. package/dist/llm/responses-replay.js.map +1 -1
  242. package/dist/llm/responses-stream-events.js +3 -20
  243. package/dist/llm/responses-stream-events.js.map +1 -1
  244. package/dist/llm/responses-stream.js +2 -0
  245. package/dist/llm/responses-stream.js.map +1 -1
  246. package/dist/llm/wire/reasoning-artifacts.js +1 -1
  247. package/dist/llm/wire/reasoning-artifacts.js.map +1 -1
  248. package/dist/noninteractive/stdio-confirm-port.js +4 -3
  249. package/dist/noninteractive/stdio-confirm-port.js.map +1 -1
  250. package/dist/os/bun-runtime.js +2 -1
  251. package/dist/os/bun-runtime.js.map +1 -1
  252. package/dist/os/update-origin.d.ts +7 -0
  253. package/dist/os/update-origin.js +30 -0
  254. package/dist/os/update-origin.js.map +1 -0
  255. package/dist/prompts/embedded.js +2 -2
  256. package/dist/prompts/embedded.js.map +1 -1
  257. package/dist/prompts/index.js +25 -22
  258. package/dist/prompts/index.js.map +1 -1
  259. package/dist/prompts/system.agent.md +7 -1
  260. package/dist/prompts/system.ask.md +1 -1
  261. package/dist/safety/filesystem-permissions.d.ts +8 -0
  262. package/dist/safety/filesystem-permissions.js +38 -18
  263. package/dist/safety/filesystem-permissions.js.map +1 -1
  264. package/dist/safety/patterns.d.ts +1 -1
  265. package/dist/safety/patterns.js +7 -7
  266. package/dist/safety/patterns.js.map +1 -1
  267. package/dist/safety/permission-mode.js +1 -1
  268. package/dist/safety/permission-mode.js.map +1 -1
  269. package/dist/safety/shell-classification.js +1 -1
  270. package/dist/safety/shell-classification.js.map +1 -1
  271. package/dist/session-runtime/client.js +2 -1
  272. package/dist/session-runtime/client.js.map +1 -1
  273. package/dist/session-runtime/view-manager.js +1 -1
  274. package/dist/session-runtime/view-manager.js.map +1 -1
  275. package/dist/store/history/jsonl-lock.js +10 -7
  276. package/dist/store/history/jsonl-lock.js.map +1 -1
  277. package/dist/store/history/recovery.d.ts +1 -0
  278. package/dist/store/history/recovery.js +2 -1
  279. package/dist/store/history/recovery.js.map +1 -1
  280. package/dist/store/history/sqlite-backend.js +2 -0
  281. package/dist/store/history/sqlite-backend.js.map +1 -1
  282. package/dist/store/history.d.ts +2 -2
  283. package/dist/store/history.js +8 -4
  284. package/dist/store/history.js.map +1 -1
  285. package/dist/store/session-prompts.d.ts +5 -0
  286. package/dist/store/session-prompts.js +60 -1
  287. package/dist/store/session-prompts.js.map +1 -1
  288. package/dist/tools/definitions/aggregate.js +7 -2
  289. package/dist/tools/definitions/aggregate.js.map +1 -1
  290. package/dist/tools/definitions/fs-read.js +1 -1
  291. package/dist/tools/definitions/fs-read.js.map +1 -1
  292. package/dist/tools/fs/read-input.d.ts +1 -1
  293. package/dist/tools/fs/read-input.js +2 -2
  294. package/dist/tools/fs/read-input.js.map +1 -1
  295. package/dist/tools/instructions.js +8 -1
  296. package/dist/tools/instructions.js.map +1 -1
  297. package/dist/tui-v2/app/App.js +18 -7
  298. package/dist/tui-v2/app/App.js.map +1 -1
  299. package/dist/tui-v2/bootstrap/frame-pacing.d.ts +4 -0
  300. package/dist/tui-v2/bootstrap/frame-pacing.js +5 -0
  301. package/dist/tui-v2/bootstrap/frame-pacing.js.map +1 -0
  302. package/dist/tui-v2/bootstrap/runtime-view.js +2 -0
  303. package/dist/tui-v2/bootstrap/runtime-view.js.map +1 -1
  304. package/dist/tui-v2/bootstrap/start-tui-v2.js +2 -0
  305. package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
  306. package/dist/tui-v2/components/modal/confirm-modal.d.ts +2 -0
  307. package/dist/tui-v2/components/modal/confirm-modal.js +21 -35
  308. package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -1
  309. package/dist/tui-v2/components/overlay/overlay-host.js +1 -1
  310. package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
  311. package/dist/tui-v2/components/pager/pager.js +4 -1
  312. package/dist/tui-v2/components/pager/pager.js.map +1 -1
  313. package/dist/tui-v2/components/plan/plan-interaction.d.ts +11 -0
  314. package/dist/tui-v2/components/plan/plan-interaction.js +56 -0
  315. package/dist/tui-v2/components/plan/plan-interaction.js.map +1 -0
  316. package/dist/tui-v2/components/plan/plan-view.d.ts +7 -1
  317. package/dist/tui-v2/components/plan/plan-view.js +78 -175
  318. package/dist/tui-v2/components/plan/plan-view.js.map +1 -1
  319. package/dist/tui-v2/components/plan/task-title.d.ts +9 -0
  320. package/dist/tui-v2/components/plan/task-title.js +17 -0
  321. package/dist/tui-v2/components/plan/task-title.js.map +1 -0
  322. package/dist/tui-v2/components/plan/use-task-disclosure.d.ts +25 -0
  323. package/dist/tui-v2/components/plan/use-task-disclosure.js +125 -0
  324. package/dist/tui-v2/components/plan/use-task-disclosure.js.map +1 -0
  325. package/dist/tui-v2/components/queue/queue-panel.js +2 -7
  326. package/dist/tui-v2/components/queue/queue-panel.js.map +1 -1
  327. package/dist/tui-v2/components/status/jump-to-latest.d.ts +7 -0
  328. package/dist/tui-v2/components/status/jump-to-latest.js +16 -0
  329. package/dist/tui-v2/components/status/jump-to-latest.js.map +1 -0
  330. package/dist/tui-v2/components/status/status-line.d.ts +1 -0
  331. package/dist/tui-v2/components/status/status-line.js +14 -4
  332. package/dist/tui-v2/components/status/status-line.js.map +1 -1
  333. package/dist/tui-v2/components/toast/toast-host.js +4 -7
  334. package/dist/tui-v2/components/toast/toast-host.js.map +1 -1
  335. package/dist/tui-v2/components/transcript/file-diff-card.d.ts +1 -0
  336. package/dist/tui-v2/components/transcript/file-diff-card.js +25 -11
  337. package/dist/tui-v2/components/transcript/file-diff-card.js.map +1 -1
  338. package/dist/tui-v2/components/transcript/tool-card.js +24 -20
  339. package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
  340. package/dist/tui-v2/components/transcript/transcript-row.js +6 -3
  341. package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
  342. package/dist/tui-v2/components/transcript/transcript-scroll-port.d.ts +1 -0
  343. package/dist/tui-v2/components/transcript/transcript-scroll-port.js +3 -1
  344. package/dist/tui-v2/components/transcript/transcript-scroll-port.js.map +1 -1
  345. package/dist/tui-v2/components/transcript/transcript-scrollbar.js +17 -11
  346. package/dist/tui-v2/components/transcript/transcript-scrollbar.js.map +1 -1
  347. package/dist/tui-v2/components/transcript/transcript-view.js +41 -21
  348. package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
  349. package/dist/tui-v2/composer/composer-editor.js +17 -9
  350. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  351. package/dist/tui-v2/rendering/pager-markdown.d.ts +3 -0
  352. package/dist/tui-v2/rendering/pager-markdown.js +3 -0
  353. package/dist/tui-v2/rendering/pager-markdown.js.map +1 -1
  354. package/dist/types.d.ts +12 -0
  355. package/dist/types.js.map +1 -1
  356. package/dist/ui/mentions/file-suggestions.js +17 -8
  357. package/dist/ui/mentions/file-suggestions.js.map +1 -1
  358. package/dist/ui-core/actions/action-id.d.ts +1 -1
  359. package/dist/ui-core/actions/action-id.js +7 -0
  360. package/dist/ui-core/actions/action-id.js.map +1 -1
  361. package/dist/ui-core/actions/format-shortcuts.js +9 -0
  362. package/dist/ui-core/actions/format-shortcuts.js.map +1 -1
  363. package/dist/ui-core/bootstrap/overlay-ports.js +8 -3
  364. package/dist/ui-core/bootstrap/overlay-ports.js.map +1 -1
  365. package/dist/ui-core/bootstrap/session-resume.js +1 -0
  366. package/dist/ui-core/bootstrap/session-resume.js.map +1 -1
  367. package/dist/ui-core/commands/change-commands.d.ts +4 -0
  368. package/dist/ui-core/commands/change-commands.js +48 -0
  369. package/dist/ui-core/commands/change-commands.js.map +1 -0
  370. package/dist/ui-core/commands/command-handlers.js +2 -0
  371. package/dist/ui-core/commands/command-handlers.js.map +1 -1
  372. package/dist/ui-core/commands/config-commands.js +12 -6
  373. package/dist/ui-core/commands/config-commands.js.map +1 -1
  374. package/dist/ui-core/commands/prompt-commands.d.ts +1 -1
  375. package/dist/ui-core/commands/prompt-commands.js +12 -2
  376. package/dist/ui-core/commands/prompt-commands.js.map +1 -1
  377. package/dist/ui-core/composer/arrow-intent.js +2 -0
  378. package/dist/ui-core/composer/arrow-intent.js.map +1 -1
  379. package/dist/ui-core/composer/paste-placeholder.js +2 -2
  380. package/dist/ui-core/composer/paste-placeholder.js.map +1 -1
  381. package/dist/ui-core/composer/prompt-history.d.ts +12 -0
  382. package/dist/ui-core/composer/prompt-history.js +75 -1
  383. package/dist/ui-core/composer/prompt-history.js.map +1 -1
  384. package/dist/ui-core/composer/saved-prompt-history.d.ts +5 -0
  385. package/dist/ui-core/composer/saved-prompt-history.js +33 -0
  386. package/dist/ui-core/composer/saved-prompt-history.js.map +1 -0
  387. package/dist/ui-core/controllers/overlay-controller.d.ts +1 -0
  388. package/dist/ui-core/controllers/overlay-controller.js.map +1 -1
  389. package/dist/ui-core/controllers/toast-controller.js +4 -4
  390. package/dist/ui-core/controllers/toast-controller.js.map +1 -1
  391. package/dist/ui-core/react/use-transcript-store.js +4 -2
  392. package/dist/ui-core/react/use-transcript-store.js.map +1 -1
  393. package/dist/ui-core/rendering/artifact-pager-source.d.ts +3 -0
  394. package/dist/ui-core/rendering/artifact-pager-source.js.map +1 -1
  395. package/dist/ui-core/rendering/batch-sections.d.ts +3 -2
  396. package/dist/ui-core/rendering/batch-sections.js +5 -5
  397. package/dist/ui-core/rendering/batch-sections.js.map +1 -1
  398. package/dist/ui-core/rendering/card-style.d.ts +2 -0
  399. package/dist/ui-core/rendering/card-style.js +3 -0
  400. package/dist/ui-core/rendering/card-style.js.map +1 -0
  401. package/dist/ui-core/rendering/confirmation-preview.d.ts +9 -0
  402. package/dist/ui-core/rendering/confirmation-preview.js +33 -0
  403. package/dist/ui-core/rendering/confirmation-preview.js.map +1 -0
  404. package/dist/ui-core/rendering/duration.d.ts +2 -1
  405. package/dist/ui-core/rendering/duration.js +4 -6
  406. package/dist/ui-core/rendering/duration.js.map +1 -1
  407. package/dist/ui-core/rendering/intro-header.d.ts +1 -0
  408. package/dist/ui-core/rendering/intro-header.js +19 -15
  409. package/dist/ui-core/rendering/intro-header.js.map +1 -1
  410. package/dist/ui-core/rendering/jump-to-latest.d.ts +1 -0
  411. package/dist/ui-core/rendering/jump-to-latest.js +7 -0
  412. package/dist/ui-core/rendering/jump-to-latest.js.map +1 -0
  413. package/dist/ui-core/rendering/line-change-labels.d.ts +6 -0
  414. package/dist/ui-core/rendering/line-change-labels.js +12 -0
  415. package/dist/ui-core/rendering/line-change-labels.js.map +1 -0
  416. package/dist/ui-core/rendering/markdown.d.ts +5 -1
  417. package/dist/ui-core/rendering/markdown.js +20 -5
  418. package/dist/ui-core/rendering/markdown.js.map +1 -1
  419. package/dist/ui-core/rendering/plan-view.js +24 -12
  420. package/dist/ui-core/rendering/plan-view.js.map +1 -1
  421. package/dist/ui-core/rendering/render-markdown-lines.d.ts +3 -0
  422. package/dist/ui-core/rendering/render-markdown-lines.js +6 -1
  423. package/dist/ui-core/rendering/render-markdown-lines.js.map +1 -1
  424. package/dist/ui-core/rendering/session-prompts-pager-source.js +2 -0
  425. package/dist/ui-core/rendering/session-prompts-pager-source.js.map +1 -1
  426. package/dist/ui-core/rendering/status-segments.js +10 -5
  427. package/dist/ui-core/rendering/status-segments.js.map +1 -1
  428. package/dist/ui-core/rendering/subagent-presentation.js +39 -11
  429. package/dist/ui-core/rendering/subagent-presentation.js.map +1 -1
  430. package/dist/ui-core/rendering/subagent-source.js +11 -48
  431. package/dist/ui-core/rendering/subagent-source.js.map +1 -1
  432. package/dist/ui-core/rendering/subagent-tool-usage.d.ts +5 -0
  433. package/dist/ui-core/rendering/subagent-tool-usage.js +42 -0
  434. package/dist/ui-core/rendering/subagent-tool-usage.js.map +1 -0
  435. package/dist/ui-core/rendering/task-disclosure.d.ts +19 -0
  436. package/dist/ui-core/rendering/task-disclosure.js +70 -0
  437. package/dist/ui-core/rendering/task-disclosure.js.map +1 -0
  438. package/dist/ui-core/rendering/tool-diff-preview.d.ts +21 -0
  439. package/dist/ui-core/rendering/tool-diff-preview.js +27 -0
  440. package/dist/ui-core/rendering/tool-diff-preview.js.map +1 -0
  441. package/dist/ui-core/rendering/tool-presenter.d.ts +4 -2
  442. package/dist/ui-core/rendering/tool-presenter.js +19 -4
  443. package/dist/ui-core/rendering/tool-presenter.js.map +1 -1
  444. package/dist/ui-core/rendering/tool-usage-label.d.ts +2 -0
  445. package/dist/ui-core/rendering/tool-usage-label.js +42 -0
  446. package/dist/ui-core/rendering/tool-usage-label.js.map +1 -0
  447. package/dist/ui-core/state/hydrate/classic-transcript.js +2 -0
  448. package/dist/ui-core/state/hydrate/classic-transcript.js.map +1 -1
  449. package/dist/ui-core/state/transcript/apply-app-event.js +16 -5
  450. package/dist/ui-core/state/transcript/apply-app-event.js.map +1 -1
  451. package/dist/ui-core/state/transcript-hydrate.js +1 -0
  452. package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
  453. package/dist/ui-core/state/transcript-types.d.ts +4 -0
  454. package/dist/ui-core/state/transcript-types.js.map +1 -1
  455. package/dist/version.generated.d.ts +2 -2
  456. package/dist/version.generated.js +2 -2
  457. package/package.json +1 -1
  458. package/dist/classic/feed/ScrollbarGutter.d.ts +0 -9
  459. package/dist/classic/feed/ScrollbarGutter.js +0 -41
  460. package/dist/classic/feed/ScrollbarGutter.js.map +0 -1
  461. package/dist/classic/feed/scrollbar-rows.d.ts +0 -5
  462. package/dist/classic/feed/scrollbar-rows.js +0 -17
  463. package/dist/classic/feed/scrollbar-rows.js.map +0 -1
@@ -0,0 +1,71 @@
1
+ export const sourceApplyWorker = String.raw `import { spawnSync } from 'node:child_process';
2
+ import { existsSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { basename, join } from 'node:path';
4
+ const data = JSON.parse(readFileSync(process.argv[2], 'utf8'));
5
+ for (const key of ['root', 'stage', 'worktree', 'head', 'commit', 'runtime', 'version']) {
6
+ if (typeof data[key] !== 'string' || !data[key]) throw new Error('Invalid source-update task');
7
+ }
8
+ function command(file, args) {
9
+ const result = spawnSync(file, args, { cwd: data.root, encoding: 'utf8', timeout: 30000, maxBuffer: 16384, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] });
10
+ if (result.error || result.status !== 0) throw new Error((result.error?.message || result.stderr || 'Source update command failed').slice(-1024));
11
+ return result.stdout.trim();
12
+ }
13
+ const moved = [];
14
+ let merged = false;
15
+ let preserve = false;
16
+ try {
17
+ const changes = command('git', ['status', '--porcelain', '--', '.', ':(exclude)' + basename(data.stage)]);
18
+ if (changes || command('git', ['rev-parse', 'HEAD']) !== data.head) throw new Error('Checkout changed while the update was building; existing files were kept');
19
+ command('git', ['merge', '--ff-only', data.commit]);
20
+ merged = true;
21
+ for (const name of ['node_modules', 'dist']) {
22
+ const target = join(data.root, name);
23
+ const backup = join(data.stage, 'previous-' + name);
24
+ const entry = { target, backup, previous: existsSync(target), installed: false };
25
+ moved.push(entry);
26
+ if (entry.previous) renameSync(target, backup);
27
+ renameSync(join(data.worktree, name), target);
28
+ entry.installed = true;
29
+ }
30
+ const actual = command(data.runtime, [join(data.root, 'dist', 'index.js'), '--version']).replace(/^clai\s+|^v/g, '');
31
+ if (actual !== data.version) throw new Error('Source-update runtime verification failed: ' + actual);
32
+ process.stdout.write(actual + '\n');
33
+ } catch (error) {
34
+ try {
35
+ for (const entry of moved.reverse()) {
36
+ if (entry.installed) rmSync(entry.target, { recursive: true, force: true });
37
+ if (entry.previous && existsSync(entry.backup)) renameSync(entry.backup, entry.target);
38
+ }
39
+ if (merged) command('git', ['reset', '--keep', data.head]);
40
+ } catch (rollbackError) {
41
+ preserve = true;
42
+ writeFileSync(join(data.stage, 'recovery'), 'Previous files retained for recovery');
43
+ process.stderr.write('Rollback could not finish. Recovery files: ' + data.stage + '\n' + String(rollbackError) + '\n');
44
+ }
45
+ process.stderr.write(String(error) + '\n');
46
+ process.exitCode = 1;
47
+ } finally {
48
+ if (!preserve) {
49
+ try { command('git', ['worktree', 'remove', '--force', data.worktree]); } catch {}
50
+ try { rmSync(data.stage, { recursive: true, force: true }); } catch {}
51
+ }
52
+ }
53
+ `;
54
+ export const sourceCleanupWorker = String.raw `import { spawnSync } from 'node:child_process';
55
+ import { existsSync, readFileSync, rmSync } from 'node:fs';
56
+ import { basename, dirname, join, resolve } from 'node:path';
57
+ const payload = process.argv.at(-1);
58
+ if (!payload || !existsSync(payload)) process.exit(0);
59
+ const data = JSON.parse(readFileSync(payload, 'utf8'));
60
+ for (const key of ['root', 'stage', 'worktree']) {
61
+ if (typeof data[key] !== 'string' || !data[key]) throw new Error('Invalid source-cleanup task');
62
+ }
63
+ if (dirname(resolve(data.stage)) !== resolve(data.root) || !basename(data.stage).startsWith('.clai-update-') || resolve(data.worktree) !== resolve(join(data.stage, 'worktree'))) throw new Error('Invalid source staging directory');
64
+ if (existsSync(join(data.stage, 'recovery'))) process.exit(0);
65
+ if (existsSync(data.worktree)) {
66
+ const result = spawnSync('git', ['worktree', 'remove', '--force', data.worktree], { cwd: data.root, timeout: 30000, encoding: 'utf8', windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] });
67
+ if (result.error || result.status !== 0) throw new Error((result.error?.message || result.stderr || 'Could not clean source worktree').slice(-1024));
68
+ }
69
+ rmSync(data.stage, { recursive: true, force: true });
70
+ `;
71
+ //# sourceMappingURL=source-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-worker.js","sourceRoot":"","sources":["../../../src/commands/update/source-worker.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD1C,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;CAgB5C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { type PerformUpdateOptions, type UpdateInstallResult } from "./installers.js";
2
+ export declare function installSourceUpdate(options: PerformUpdateOptions): Promise<UpdateInstallResult>;
@@ -0,0 +1,79 @@
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { PACKAGE_NAME } from "./installers.js";
4
+ import { runUpdateCommand, throwIfCancelled } from "./process.js";
5
+ import { sourceApplyWorker, sourceCleanupWorker } from "./source-worker.js";
6
+ import { compareVersions, releaseVersion, verifyCommand } from "./verification.js";
7
+ import { stageWindowsUpdate } from "./windows-stage.js";
8
+ export async function installSourceUpdate(options) {
9
+ const root = options.method.packageRoot;
10
+ const runtime = options.method.runtimePath;
11
+ if (!root || !runtime)
12
+ throw new Error("cannot identify the active source checkout and runtime");
13
+ const git = (args) => runUpdateCommand({ file: "git", args, cwd: root, env: { GIT_TERMINAL_PROMPT: "0", GIT_SSH_COMMAND: "ssh -o BatchMode=yes" } }, { signal: options.signal, timeoutMs: 120_000 });
14
+ throwIfCancelled(options.signal);
15
+ if (await git(["status", "--porcelain"]))
16
+ throw new Error("source checkout has local changes; commit or stash them before updating. Nothing was overwritten");
17
+ const head = await git(["rev-parse", "HEAD"]);
18
+ const branch = await git(["symbolic-ref", "--quiet", "--short", "HEAD"]);
19
+ const remote = await git(["config", "--get", `branch.${branch}.remote`]);
20
+ const ref = await git(["config", "--get", `branch.${branch}.merge`]);
21
+ const url = await git(["remote", "get-url", remote]);
22
+ if (!/^(?:https:\/\/github\.com\/|git@github\.com:|ssh:\/\/git@github\.com\/)pentoshi007\/clai(?:\.git)?\/?$/i.test(url)) {
23
+ throw new Error("source checkout must track the official clai upstream; custom remotes are not changed automatically");
24
+ }
25
+ if (!ref.startsWith("refs/heads/"))
26
+ throw new Error("source checkout has no upstream branch; configure tracking before updating");
27
+ options.log?.("Fetching the tracked source upstream…");
28
+ await git(["fetch", "--no-tags", remote, ref]);
29
+ const commit = await git(["rev-parse", "FETCH_HEAD"]);
30
+ try {
31
+ await git(["merge-base", "--is-ancestor", head, commit]);
32
+ }
33
+ catch {
34
+ throw new Error("source checkout has local or divergent commits; update requires a safe fast-forward. Nothing was overwritten");
35
+ }
36
+ const stage = mkdtempSync(join(root, ".clai-update-"));
37
+ const worktree = join(stage, "worktree");
38
+ let pending = false;
39
+ try {
40
+ await git(["worktree", "add", "--detach", worktree, commit]);
41
+ const manifest = JSON.parse(readFileSync(join(worktree, "package.json"), "utf8"));
42
+ if (!manifest || typeof manifest !== "object" || !("name" in manifest) || manifest.name !== PACKAGE_NAME || !("version" in manifest))
43
+ throw new Error("upstream is not a clai source checkout");
44
+ const version = releaseVersion(manifest.version);
45
+ if (!version || compareVersions(version, options.version) < 0)
46
+ throw new Error(`tracked source upstream has not reached v${options.version}; existing checkout was kept`);
47
+ options.onProgress?.({ phase: "installing", detail: "building isolated source worktree" });
48
+ const npm = process.platform === "win32" ? "npm.cmd" : "npm";
49
+ const runOptions = { signal: options.signal, log: options.log, timeoutMs: 600_000 };
50
+ await runUpdateCommand({ file: npm, args: ["ci", "--no-audit", "--no-fund"], cwd: worktree }, runOptions);
51
+ await runUpdateCommand({ file: npm, args: ["run", "build", "--silent"], cwd: worktree }, runOptions);
52
+ options.onProgress?.({ phase: "verifying" });
53
+ await verifyCommand({ file: runtime, args: [join(worktree, "dist", "index.js"), "--version"] }, version, { signal: options.signal });
54
+ const worker = join(stage, "apply-source.mjs");
55
+ const payload = join(stage, "task.json");
56
+ writeFileSync(worker, sourceApplyWorker);
57
+ writeFileSync(payload, JSON.stringify({ root, stage, worktree, head, commit, runtime, version }));
58
+ const application = { file: runtime, args: [worker, payload] };
59
+ const verification = { file: runtime, args: [join(root, "dist", "index.js"), "--version"] };
60
+ throwIfCancelled(options.signal);
61
+ if (process.platform === "win32") {
62
+ const cleanup = { file: runtime, args: ["--input-type=module", "-e", sourceCleanupWorker, payload] };
63
+ const statusFile = await stageWindowsUpdate({ kind: "commands", commands: [application], verification, version, allowNewer: false, cleanup }, { signal: options.signal, ...(options.lockFile ? { lockFile: options.lockFile, lockToken: options.lockToken } : {}) });
64
+ pending = true;
65
+ return { ok: true, method: "dev", outcome: "staged", needsRestart: true, statusFile, message: `source update built and staged; close clai to apply it. Result: ${statusFile}` };
66
+ }
67
+ await runUpdateCommand(application, { timeoutMs: 120_000, log: options.log });
68
+ const installedVersion = await verifyCommand(verification, version);
69
+ return { ok: true, method: "dev", outcome: "applied", installedVersion, needsRestart: true, message: `source checkout fast-forwarded, rebuilt and verified at v${installedVersion}` };
70
+ }
71
+ finally {
72
+ if (!pending && !existsSync(join(stage, "recovery"))) {
73
+ if (existsSync(worktree))
74
+ await runUpdateCommand({ file: "git", args: ["worktree", "remove", "--force", worktree], cwd: root }, { timeoutMs: 30_000 }).catch(() => { });
75
+ rmSync(stage, { recursive: true, force: true });
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../../src/commands/update/source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { InstallMethod } from "./installers.js";
2
+ import { type RunOptions, type UpdateCommand } from "./process.js";
3
+ export declare function releaseVersion(value: unknown): string | undefined;
4
+ export declare function compareVersions(left: string, right: string): number;
5
+ export declare function installedVersionCommand(method: InstallMethod): UpdateCommand;
6
+ export declare function verifyCommand(command: UpdateCommand, expected: string, options?: RunOptions, allowNewer?: boolean): Promise<string>;
7
+ export declare function verifyExecutable(path: string, expected: string, options?: RunOptions): Promise<string>;
@@ -0,0 +1,73 @@
1
+ import { join } from "node:path";
2
+ import { runUpdateCommand } from "./process.js";
3
+ export function releaseVersion(value) {
4
+ if (typeof value !== "string")
5
+ return undefined;
6
+ const version = value.trim().replace(/^v/, "");
7
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/.exec(version);
8
+ if (!match || match.slice(1, 4).some((part) => !Number.isSafeInteger(Number(part))))
9
+ return undefined;
10
+ if (match[4]?.split(".").some((part) => /^0\d+$/.test(part)))
11
+ return undefined;
12
+ return version;
13
+ }
14
+ function components(value) {
15
+ const version = value.split("+")[0];
16
+ const index = version.indexOf("-");
17
+ return { numbers: (index < 0 ? version : version.slice(0, index)).split(".").map(Number), pre: index < 0 ? [] : version.slice(index + 1).split(".") };
18
+ }
19
+ function compareIdentifier(left, right) {
20
+ if (left === right)
21
+ return 0;
22
+ const numericLeft = /^\d+$/.test(left);
23
+ const numericRight = /^\d+$/.test(right);
24
+ if (numericLeft !== numericRight)
25
+ return numericLeft ? -1 : 1;
26
+ if (numericLeft && left.length !== right.length)
27
+ return left.length - right.length;
28
+ return left < right ? -1 : 1;
29
+ }
30
+ export function compareVersions(left, right) {
31
+ if (!releaseVersion(left) || !releaseVersion(right))
32
+ throw new Error("invalid release version");
33
+ const a = components(left.replace(/^v/, ""));
34
+ const b = components(right.replace(/^v/, ""));
35
+ for (let i = 0; i < 3; i += 1) {
36
+ const difference = a.numbers[i] - b.numbers[i];
37
+ if (difference)
38
+ return difference;
39
+ }
40
+ if (a.pre.length === 0 || b.pre.length === 0)
41
+ return Number(b.pre.length > 0) - Number(a.pre.length > 0);
42
+ for (let i = 0; i < Math.min(a.pre.length, b.pre.length); i += 1) {
43
+ const difference = compareIdentifier(a.pre[i], b.pre[i]);
44
+ if (difference)
45
+ return difference;
46
+ }
47
+ return a.pre.length - b.pre.length;
48
+ }
49
+ export function installedVersionCommand(method) {
50
+ if (method.type === "pnpm" && method.scope === "global" && method.executablePath && !method.executablePath.endsWith(".mjs")) {
51
+ return { file: method.executablePath, args: ["--version"], env: { PNPM_SHIM_BYPASS: "1" } };
52
+ }
53
+ if (method.packageRoot && method.type !== "dev") {
54
+ if (!method.runtimePath)
55
+ throw new Error("cannot verify the installed package without its Node/Bun runtime");
56
+ return { file: method.runtimePath, args: [join(method.packageRoot, "bin", "clai.mjs"), "--version"] };
57
+ }
58
+ if (!method.executablePath)
59
+ throw new Error("cannot verify the active clai installation path");
60
+ return { file: method.executablePath, args: ["--version"] };
61
+ }
62
+ export async function verifyCommand(command, expected, options = {}, allowNewer = false) {
63
+ const output = await runUpdateCommand(command, { ...options, timeoutMs: 15_000, log: undefined });
64
+ const actual = releaseVersion(output.replace(/^clai\s+/i, ""));
65
+ if (!actual || (allowNewer ? compareVersions(actual, expected) < 0 : actual !== expected)) {
66
+ throw new Error(`update verification failed: expected ${allowNewer ? "at least " : ""}${expected}, installed command reports ${output.slice(0, 120) || "no version"}; restart or retry with the original installer`);
67
+ }
68
+ return actual;
69
+ }
70
+ export function verifyExecutable(path, expected, options = {}) {
71
+ return verifyCommand({ file: path, args: ["--version"] }, expected, options);
72
+ }
73
+ //# sourceMappingURL=verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.js","sourceRoot":"","sources":["../../../src/commands/update/verification.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type RunOptions, type UpdateCommand } from "./process.js";
2
+ export type WindowsUpdateTask = {
3
+ readonly kind: "binary";
4
+ readonly source: string;
5
+ readonly destination: string;
6
+ readonly digest: string;
7
+ readonly previousDigest: string;
8
+ readonly version: string;
9
+ } | {
10
+ readonly kind: "commands";
11
+ readonly commands: readonly UpdateCommand[];
12
+ readonly verification: UpdateCommand;
13
+ readonly version: string;
14
+ readonly allowNewer: boolean;
15
+ readonly cleanup?: UpdateCommand;
16
+ };
17
+ export declare function windowsUpdateScript(encoded: string): string;
18
+ export declare function stageWindowsUpdate(task: WindowsUpdateTask, options?: RunOptions & {
19
+ readonly lockFile?: string;
20
+ readonly lockToken?: string | undefined;
21
+ }, elevated?: boolean): Promise<string>;
@@ -0,0 +1,186 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { copyFileSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { psQuote, runUpdateCommand, throwIfCancelled } from "./process.js";
7
+ export function windowsUpdateScript(encoded) {
8
+ return String.raw `$ErrorActionPreference = 'Stop'
9
+ $data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encoded}')) | ConvertFrom-Json
10
+ $task = $data.task
11
+ $stage = $data.stage
12
+ $status = $data.status
13
+ $pending = $null
14
+ $backup = $null
15
+ $verified = $false
16
+ function Save-Status($state, $message) {
17
+ @{ state=$state; version=$task.version; message=$message; time=[DateTime]::UtcNow.ToString('o') } | ConvertTo-Json -Compress | Set-Content -LiteralPath $status -Encoding UTF8
18
+ }
19
+ function Quote-Argument($value) {
20
+ if ($value -notmatch '[\s"]' -and $value.Length -gt 0) { return $value }
21
+ $escaped = [regex]::Replace($value, '(\\*)"', '$1$1\"')
22
+ return '"' + [regex]::Replace($escaped, '(\\+)$', '$1$1') + '"'
23
+ }
24
+ function Get-ExecutableDigest($path) {
25
+ $hash = [Security.Cryptography.SHA256]::Create()
26
+ try {
27
+ $stream = [IO.File]::OpenRead($path)
28
+ try { return [BitConverter]::ToString($hash.ComputeHash($stream)).Replace('-', '').ToLowerInvariant() }
29
+ finally { $stream.Dispose() }
30
+ } finally { $hash.Dispose() }
31
+ }
32
+ function Invoke-CommandSpec($spec) {
33
+ if ($spec.env) { foreach ($property in $spec.env.PSObject.Properties) { [Environment]::SetEnvironmentVariable($property.Name, [string]$property.Value, 'Process') } }
34
+ $arguments = (@($spec.args | ForEach-Object { Quote-Argument ([string]$_) }) -join ' ')
35
+ $outFile = Join-Path $stage 'stdout.txt'
36
+ $errFile = Join-Path $stage 'stderr.txt'
37
+ $parameters = @{ FilePath=$spec.file; ArgumentList=$arguments; RedirectStandardOutput=$outFile; RedirectStandardError=$errFile; PassThru=$true; NoNewWindow=$true }
38
+ if ($spec.cwd) { $parameters.WorkingDirectory = $spec.cwd }
39
+ $child = Start-Process @parameters
40
+ $null = $child.Handle
41
+ $limit = 600000
42
+ if ($spec.args -contains '--version') { $limit = 15000 }
43
+ if (-not $child.WaitForExit($limit)) {
44
+ & taskkill.exe /PID $child.Id /T /F *> $null
45
+ throw "Update command timed out: $($spec.file)"
46
+ }
47
+ $output = (Get-Content -LiteralPath $outFile -Tail 64) -join [Environment]::NewLine
48
+ $exitCode = $child.ExitCode
49
+ if ($null -eq $exitCode) { throw "Cannot read update command exit status: $($spec.file)" }
50
+ if ($exitCode -ne 0) { throw "Update command exited with status $($exitCode): $($spec.file) $((Get-Content -LiteralPath $errFile -Tail 4) -join ' ') $output" }
51
+ return $output.Trim()
52
+ }
53
+ function Compare-Version($left, $right) {
54
+ $a = ($left -split '\+')[0] -split '-', 2
55
+ $b = ($right -split '\+')[0] -split '-', 2
56
+ $numbersA = $a[0].Split('.')
57
+ $numbersB = $b[0].Split('.')
58
+ for ($index = 0; $index -lt 3; $index++) {
59
+ $difference = ([long]$numbersA[$index]).CompareTo([long]$numbersB[$index])
60
+ if ($difference -ne 0) { return $difference }
61
+ }
62
+ if ($a.Count -eq 1 -or $b.Count -eq 1) { return [int]($b.Count -gt 1) - [int]($a.Count -gt 1) }
63
+ $preA = $a[1].Split('.')
64
+ $preB = $b[1].Split('.')
65
+ for ($index = 0; $index -lt [Math]::Min($preA.Count, $preB.Count); $index++) {
66
+ if ($preA[$index] -ceq $preB[$index]) { continue }
67
+ $numericA = $preA[$index] -match '^\d+$'
68
+ $numericB = $preB[$index] -match '^\d+$'
69
+ if ($numericA -ne $numericB) { return [int]$numericB - [int]$numericA }
70
+ if ($numericA -and $preA[$index].Length -ne $preB[$index].Length) { return $preA[$index].Length - $preB[$index].Length }
71
+ return [StringComparer]::Ordinal.Compare($preA[$index], $preB[$index])
72
+ }
73
+ return $preA.Count - $preB.Count
74
+ }
75
+ function Verify-Version($spec, $allowNewer) {
76
+ $value = (Invoke-CommandSpec $spec) -replace '^clai\s+', ''
77
+ if ($value -cnotmatch '^v?((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)$') { throw "Cannot verify installed version: $value" }
78
+ $actual = $Matches[1]
79
+ $parts = ($actual -split '\+')[0] -split '-', 2
80
+ if ($parts.Count -eq 2) { foreach ($part in $parts[1].Split('.')) { if ($part -match '^0\d+$') { throw "Invalid installed version: $value" } } }
81
+ if ($allowNewer) {
82
+ if ((Compare-Version $actual $task.version) -lt 0) { throw "Installer did not reach version $($task.version): $value" }
83
+ } elseif ($actual -cne $task.version) { throw "Installed version mismatch: $value" }
84
+ }
85
+ try {
86
+ Save-Status 'waiting' 'Close this clai installation to apply the staged update.'
87
+ if (-not (Test-Path -LiteralPath $stage) -or (Test-Path -LiteralPath (Join-Path $stage 'cancel'))) { throw 'Update cancelled before staging.' }
88
+ if ($data.lockFile) {
89
+ $owner = Get-Content -LiteralPath $data.lockFile -Raw | ConvertFrom-Json
90
+ if ($owner.token -ne $data.lockToken) { throw 'Update lock changed before staging; existing installation was kept.' }
91
+ @{ pid=$PID; token=$data.lockToken } | ConvertTo-Json -Compress | Set-Content -LiteralPath $data.lockFile
92
+ }
93
+ Set-Content -LiteralPath (Join-Path $stage 'ready') -Value 'ready'
94
+ $deadline = [DateTime]::UtcNow.AddSeconds(120)
95
+ while ($true) {
96
+ if (-not (Test-Path -LiteralPath $stage) -or (Test-Path -LiteralPath (Join-Path $stage 'cancel'))) { throw 'Update cancelled before installation.' }
97
+ $owner = Get-Process -Id $data.pid -ErrorAction SilentlyContinue
98
+ $holders = @()
99
+ if ($task.kind -eq 'binary') { $holders = @(Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path -and $_.Path -eq $task.destination }) }
100
+ if (-not $owner -and $holders.Count -eq 0) { break }
101
+ if ([DateTime]::UtcNow -ge $deadline) { throw 'Timed out waiting for clai to close; the previous installation was kept. Close all instances and retry.' }
102
+ Start-Sleep -Milliseconds 250
103
+ }
104
+ Save-Status 'installing' 'Applying staged update.'
105
+ if ($task.kind -eq 'binary') {
106
+ if ((Get-ExecutableDigest $task.source) -ne $task.digest) { throw 'Staged binary checksum mismatch.' }
107
+ Verify-Version @{ file=$task.source; args=@('--version') } $false
108
+ $pending = "$($task.destination).update-$([Guid]::NewGuid().ToString('N'))"
109
+ $backup = "$($task.destination).rollback-$([Guid]::NewGuid().ToString('N'))"
110
+ Copy-Item -LiteralPath $task.source -Destination $pending
111
+ if ((Get-ExecutableDigest $task.destination) -ne $task.previousDigest) { throw 'Installation changed while the update was staged; existing executable was kept.' }
112
+ [IO.File]::Replace($pending, $task.destination, $backup, $true)
113
+ try { Verify-Version @{ file=$task.destination; args=@('--version') } $false }
114
+ catch { [IO.File]::Replace($backup, $task.destination, $null, $true); throw }
115
+ } else {
116
+ foreach ($command in $task.commands) { $null = Invoke-CommandSpec $command }
117
+ Verify-Version $task.verification $task.allowNewer
118
+ }
119
+ $verified = $true
120
+ Save-Status 'applied' 'Update applied and verified.'
121
+ } catch {
122
+ $message = $_.Exception.Message
123
+ if ($backup -and (Test-Path -LiteralPath $backup)) { $message += "; recovery executable: $backup" }
124
+ Save-Status 'failed' $message
125
+ } finally {
126
+ if ($task.kind -eq 'commands' -and $task.cleanup) {
127
+ try { $null = [IO.Directory]::CreateDirectory($stage); $null = Invoke-CommandSpec $task.cleanup }
128
+ catch { Save-Status $(if ($verified) { 'applied' } else { 'failed' }) ("$message; staged source cleanup failed: " + $_.Exception.Message) }
129
+ }
130
+ if ($pending) { Remove-Item -LiteralPath $pending -Force -ErrorAction SilentlyContinue }
131
+ if ($verified -and $backup) { Remove-Item -LiteralPath $backup -Force -ErrorAction SilentlyContinue }
132
+ if ($data.lockFile -and (Test-Path -LiteralPath $data.lockFile)) {
133
+ try { if ((Get-Content -LiteralPath $data.lockFile -Raw | ConvertFrom-Json).token -eq $data.lockToken) { Remove-Item -LiteralPath $data.lockFile -Force } } catch {}
134
+ }
135
+ Remove-Item -LiteralPath $stage -Recurse -Force -ErrorAction SilentlyContinue
136
+ }
137
+ `;
138
+ }
139
+ export async function stageWindowsUpdate(task, options = {}, elevated = false) {
140
+ throwIfCancelled(options.signal);
141
+ if (options.lockFile && !options.lockToken)
142
+ throw new Error("cannot stage an update without its installation lock token");
143
+ const stage = mkdtempSync(join(tmpdir(), "clai-update-stage-"));
144
+ const identity = task.kind === "binary" ? task.destination : task.verification.file + task.verification.args.join("|");
145
+ const status = join(tmpdir(), `clai-update-status-${createHash("sha256").update(identity).update(stage).digest("hex").slice(0, 20)}.json`);
146
+ let accepted = false;
147
+ try {
148
+ const stagedTask = task.kind === "binary" ? { ...task, source: join(stage, "clai.exe") } : task;
149
+ if (task.kind === "binary" && stagedTask.kind === "binary")
150
+ copyFileSync(task.source, stagedTask.source);
151
+ const encoded = Buffer.from(JSON.stringify({ task: stagedTask, stage, status, pid: process.pid, lockFile: options.lockFile, lockToken: options.lockToken })).toString("base64");
152
+ const script = join(stage, "apply-update.ps1");
153
+ writeFileSync(script, windowsUpdateScript(encoded));
154
+ if (elevated) {
155
+ const argumentsText = `-NoProfile -NonInteractive -ExecutionPolicy Bypass -File "${script}"`;
156
+ await runUpdateCommand({ file: "powershell.exe", args: ["-NoProfile", "-NonInteractive", "-Command", `Start-Process -Verb RunAs -WindowStyle Hidden -FilePath powershell.exe -ArgumentList ${psQuote(argumentsText)}`] }, { ...options, timeoutMs: 120_000 });
157
+ }
158
+ else {
159
+ await new Promise((resolve, reject) => {
160
+ const child = spawn("powershell.exe", ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", script], { detached: true, stdio: "ignore", windowsHide: true });
161
+ child.once("error", reject);
162
+ child.once("spawn", () => { child.unref(); resolve(); });
163
+ });
164
+ }
165
+ const deadline = Date.now() + 15_000;
166
+ while (!existsSync(join(stage, "ready"))) {
167
+ throwIfCancelled(options.signal);
168
+ if (Date.now() >= deadline || !existsSync(stage)) {
169
+ const failure = existsSync(status) ? readFileSync(status, "utf8") : "worker did not acknowledge the staged update";
170
+ throw new Error(`could not stage Windows update: ${failure.slice(0, 500)}`);
171
+ }
172
+ await new Promise((resolve) => setTimeout(resolve, 100));
173
+ }
174
+ throwIfCancelled(options.signal);
175
+ accepted = true;
176
+ return status;
177
+ }
178
+ finally {
179
+ if (!accepted) {
180
+ if (existsSync(stage))
181
+ writeFileSync(join(stage, "cancel"), "cancel");
182
+ rmSync(stage, { recursive: true, force: true });
183
+ }
184
+ }
185
+ }
186
+ //# sourceMappingURL=windows-stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-stage.js","sourceRoot":"","sources":["../../../src/commands/update/windows-stage.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,8 @@
1
- import { InstallMethod, PerformUpdateOptions, UpdateInstallResult, installDirectBinary, installViaPackageManager } from "./update/installers.js";
1
+ import type { PerformUpdateOptions, UpdateInstallResult } from "./update/installers.js";
2
+ import { installDirectBinary, installViaPackageManager } from "./update/installers.js";
3
+ export { detectInstallMethod, resolveInstallEnv } from "./update/detection.js";
4
+ export type { DetectEnv } from "./update/detection.js";
2
5
  export { DEFAULT_MIRROR_BASE, ELEVATION_TIMEOUT_MS, PACKAGE_NAME, REPO, currentPlatformTarget, downloadBinary, mirrorBaseUrl } from "./update/installers.js";
3
6
  export { installDirectBinary, installViaPackageManager };
4
7
  export type { DownloadProgress, InstallMethod, InstallMethodType, PerformUpdateOptions, PlatformTarget, SecretRequester, UpdateElevation, UpdateInstallResult, UpdateProgress } from "./update/installers.js";
5
- export interface DetectEnv {
6
- readonly argv1: string;
7
- readonly execPath: string;
8
- readonly platform: NodeJS.Platform;
9
- readonly home: string;
10
- npmRoot?: string;
11
- bunRoot?: string;
12
- brewPrefix?: string;
13
- scoopShimsDir?: string;
14
- }
15
- export declare function detectInstallMethod(env: DetectEnv): InstallMethod;
16
- export declare function resolveInstallEnv(): Promise<DetectEnv>;
17
8
  export declare function performUpdate(options: PerformUpdateOptions): Promise<UpdateInstallResult>;