@pentoshi/clai 3.18.2 → 4.0.1

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 (1074) hide show
  1. package/README.md +44 -24
  2. package/bin/postinstall-policy.mjs +3 -0
  3. package/bin/postinstall.mjs +6 -3
  4. package/dist/agent/confirm-port.d.ts +5 -17
  5. package/dist/agent/confirm-port.js +8 -65
  6. package/dist/agent/confirm-port.js.map +1 -1
  7. package/dist/agent/evidence-governor.d.ts +1 -1
  8. package/dist/agent/evidence-governor.js +2 -2
  9. package/dist/agent/evidence-governor.js.map +1 -1
  10. package/dist/agent/loop-guard.d.ts +1 -0
  11. package/dist/agent/loop-guard.js +34 -1
  12. package/dist/agent/loop-guard.js.map +1 -1
  13. package/dist/agent/plan-decision.d.ts +0 -29
  14. package/dist/agent/plan-decision.js +0 -96
  15. package/dist/agent/plan-decision.js.map +1 -1
  16. package/dist/agent/plan-tool.js +19 -14
  17. package/dist/agent/plan-tool.js.map +1 -1
  18. package/dist/agent/progress-pause-policy.d.ts +0 -15
  19. package/dist/agent/progress-pause-policy.js +0 -15
  20. package/dist/agent/progress-pause-policy.js.map +1 -1
  21. package/dist/agent/runner.js +152 -392
  22. package/dist/agent/runner.js.map +1 -1
  23. package/dist/agent/task-evidence.d.ts +6 -0
  24. package/dist/agent/task-evidence.js +48 -3
  25. package/dist/agent/task-evidence.js.map +1 -1
  26. package/dist/agent/tool-history.js +11 -4
  27. package/dist/agent/tool-history.js.map +1 -1
  28. package/dist/app/commands/catalog.js +397 -0
  29. package/dist/app/commands/catalog.js.map +1 -0
  30. package/dist/app/commands/registry.js +1 -1
  31. package/dist/app/commands/registry.js.map +1 -1
  32. package/dist/app/confirm-prompt-text.d.ts +17 -0
  33. package/dist/app/confirm-prompt-text.js +34 -0
  34. package/dist/app/confirm-prompt-text.js.map +1 -0
  35. package/dist/app/controllers/session-controller.d.ts +1 -1
  36. package/dist/app/controllers/session-controller.js +3 -1
  37. package/dist/app/controllers/session-controller.js.map +1 -1
  38. package/dist/app/controllers/session-prompt-queue.d.ts +5 -1
  39. package/dist/app/controllers/session-prompt-queue.js +47 -30
  40. package/dist/app/controllers/session-prompt-queue.js.map +1 -1
  41. package/dist/app/controllers/turn-controller.js +41 -3
  42. package/dist/app/controllers/turn-controller.js.map +1 -1
  43. package/dist/app/ports/confirm-port.d.ts +0 -1
  44. package/dist/app/ports/persistence-port.d.ts +1 -1
  45. package/dist/app/ports/transcript-item.d.ts +63 -0
  46. package/dist/app/ports/transcript-item.js +2 -0
  47. package/dist/app/ports/transcript-item.js.map +1 -0
  48. package/dist/classic/app/ClassicApp.d.ts +12 -0
  49. package/dist/classic/app/ClassicApp.js +117 -0
  50. package/dist/classic/app/ClassicApp.js.map +1 -0
  51. package/dist/classic/app/action-handlers.d.ts +45 -0
  52. package/dist/classic/app/action-handlers.js +280 -0
  53. package/dist/classic/app/action-handlers.js.map +1 -0
  54. package/dist/classic/app/app-wiring.d.ts +133 -0
  55. package/dist/classic/app/app-wiring.js +383 -0
  56. package/dist/classic/app/app-wiring.js.map +1 -0
  57. package/dist/classic/app/use-feed.d.ts +40 -0
  58. package/dist/classic/app/use-feed.js +52 -0
  59. package/dist/classic/app/use-feed.js.map +1 -0
  60. package/dist/classic/app/wiring-interactions.d.ts +40 -0
  61. package/dist/classic/app/wiring-interactions.js +430 -0
  62. package/dist/classic/app/wiring-interactions.js.map +1 -0
  63. package/dist/classic/app/wiring-lifecycle.d.ts +10 -0
  64. package/dist/classic/app/wiring-lifecycle.js +240 -0
  65. package/dist/classic/app/wiring-lifecycle.js.map +1 -0
  66. package/dist/classic/app/wiring-selection.d.ts +3 -0
  67. package/dist/classic/app/wiring-selection.js +113 -0
  68. package/dist/classic/app/wiring-selection.js.map +1 -0
  69. package/dist/classic/app/wiring-types.d.ts +157 -0
  70. package/dist/classic/app/wiring-types.js +2 -0
  71. package/dist/classic/app/wiring-types.js.map +1 -0
  72. package/dist/classic/blocks/AssistantBlock.d.ts +3 -0
  73. package/dist/classic/blocks/AssistantBlock.js +6 -0
  74. package/dist/classic/blocks/AssistantBlock.js.map +1 -0
  75. package/dist/classic/blocks/BatchBlock.d.ts +3 -0
  76. package/dist/classic/blocks/BatchBlock.js +6 -0
  77. package/dist/classic/blocks/BatchBlock.js.map +1 -0
  78. package/dist/classic/blocks/CompactedBlock.d.ts +3 -0
  79. package/dist/classic/blocks/CompactedBlock.js +6 -0
  80. package/dist/classic/blocks/CompactedBlock.js.map +1 -0
  81. package/dist/classic/blocks/DiffBlock.d.ts +3 -0
  82. package/dist/classic/blocks/DiffBlock.js +6 -0
  83. package/dist/classic/blocks/DiffBlock.js.map +1 -0
  84. package/dist/classic/blocks/IntroBlock.d.ts +3 -0
  85. package/dist/classic/blocks/IntroBlock.js +6 -0
  86. package/dist/classic/blocks/IntroBlock.js.map +1 -0
  87. package/dist/classic/blocks/NoticeBlock.d.ts +3 -0
  88. package/dist/classic/blocks/NoticeBlock.js +6 -0
  89. package/dist/classic/blocks/NoticeBlock.js.map +1 -0
  90. package/dist/classic/blocks/ThinkingBlock.d.ts +3 -0
  91. package/dist/classic/blocks/ThinkingBlock.js +6 -0
  92. package/dist/classic/blocks/ThinkingBlock.js.map +1 -0
  93. package/dist/classic/blocks/ToolBlock.d.ts +3 -0
  94. package/dist/classic/blocks/ToolBlock.js +6 -0
  95. package/dist/classic/blocks/ToolBlock.js.map +1 -0
  96. package/dist/classic/blocks/UserBlock.d.ts +3 -0
  97. package/dist/classic/blocks/UserBlock.js +6 -0
  98. package/dist/classic/blocks/UserBlock.js.map +1 -0
  99. package/dist/classic/blocks/assistant-lines.d.ts +10 -0
  100. package/dist/classic/blocks/assistant-lines.js +43 -0
  101. package/dist/classic/blocks/assistant-lines.js.map +1 -0
  102. package/dist/classic/blocks/batch-lines.d.ts +7 -0
  103. package/dist/classic/blocks/batch-lines.js +79 -0
  104. package/dist/classic/blocks/batch-lines.js.map +1 -0
  105. package/dist/classic/blocks/block-context.d.ts +33 -0
  106. package/dist/classic/blocks/block-context.js +41 -0
  107. package/dist/classic/blocks/block-context.js.map +1 -0
  108. package/dist/classic/blocks/compacted-lines.d.ts +5 -0
  109. package/dist/classic/blocks/compacted-lines.js +54 -0
  110. package/dist/classic/blocks/compacted-lines.js.map +1 -0
  111. package/dist/classic/blocks/diff-lines.d.ts +13 -0
  112. package/dist/classic/blocks/diff-lines.js +116 -0
  113. package/dist/classic/blocks/diff-lines.js.map +1 -0
  114. package/dist/classic/blocks/intro-lines.d.ts +16 -0
  115. package/dist/classic/blocks/intro-lines.js +23 -0
  116. package/dist/classic/blocks/intro-lines.js.map +1 -0
  117. package/dist/classic/blocks/notice-lines.d.ts +7 -0
  118. package/dist/classic/blocks/notice-lines.js +28 -0
  119. package/dist/classic/blocks/notice-lines.js.map +1 -0
  120. package/dist/classic/blocks/thinking-lines.d.ts +5 -0
  121. package/dist/classic/blocks/thinking-lines.js +34 -0
  122. package/dist/classic/blocks/thinking-lines.js.map +1 -0
  123. package/dist/classic/blocks/tool-lines.d.ts +22 -0
  124. package/dist/classic/blocks/tool-lines.js +135 -0
  125. package/dist/classic/blocks/tool-lines.js.map +1 -0
  126. package/dist/classic/blocks/user-lines.d.ts +5 -0
  127. package/dist/classic/blocks/user-lines.js +26 -0
  128. package/dist/classic/blocks/user-lines.js.map +1 -0
  129. package/dist/classic/bootstrap/osc52-renderer.d.ts +10 -0
  130. package/dist/classic/bootstrap/osc52-renderer.js +38 -0
  131. package/dist/classic/bootstrap/osc52-renderer.js.map +1 -0
  132. package/dist/classic/bootstrap/renderer-handle.d.ts +15 -0
  133. package/dist/classic/bootstrap/renderer-handle.js +22 -0
  134. package/dist/classic/bootstrap/renderer-handle.js.map +1 -0
  135. package/dist/classic/bootstrap/start-classic.d.ts +8 -0
  136. package/dist/classic/bootstrap/start-classic.js +130 -0
  137. package/dist/classic/bootstrap/start-classic.js.map +1 -0
  138. package/dist/classic/bootstrap/suspend-port.d.ts +14 -0
  139. package/dist/classic/bootstrap/suspend-port.js +29 -0
  140. package/dist/classic/bootstrap/suspend-port.js.map +1 -0
  141. package/dist/classic/bootstrap/terminal-session.d.ts +58 -0
  142. package/dist/classic/bootstrap/terminal-session.js +136 -0
  143. package/dist/classic/bootstrap/terminal-session.js.map +1 -0
  144. package/dist/classic/chrome/Chrome.d.ts +19 -0
  145. package/dist/classic/chrome/Chrome.js +30 -0
  146. package/dist/classic/chrome/Chrome.js.map +1 -0
  147. package/dist/classic/chrome/Composer.d.ts +12 -0
  148. package/dist/classic/chrome/Composer.js +61 -0
  149. package/dist/classic/chrome/Composer.js.map +1 -0
  150. package/dist/classic/chrome/QueuePanel.d.ts +3 -0
  151. package/dist/classic/chrome/QueuePanel.js +10 -0
  152. package/dist/classic/chrome/QueuePanel.js.map +1 -0
  153. package/dist/classic/chrome/ResponderStrip.d.ts +3 -0
  154. package/dist/classic/chrome/ResponderStrip.js +9 -0
  155. package/dist/classic/chrome/ResponderStrip.js.map +1 -0
  156. package/dist/classic/chrome/StatusBar.d.ts +3 -0
  157. package/dist/classic/chrome/StatusBar.js +7 -0
  158. package/dist/classic/chrome/StatusBar.js.map +1 -0
  159. package/dist/classic/chrome/ToastRow.d.ts +3 -0
  160. package/dist/classic/chrome/ToastRow.js +10 -0
  161. package/dist/classic/chrome/ToastRow.js.map +1 -0
  162. package/dist/classic/chrome/composer-controller.d.ts +57 -0
  163. package/dist/classic/chrome/composer-controller.js +345 -0
  164. package/dist/classic/chrome/composer-controller.js.map +1 -0
  165. package/dist/classic/chrome/composer-frame.d.ts +35 -0
  166. package/dist/classic/chrome/composer-frame.js +46 -0
  167. package/dist/classic/chrome/composer-frame.js.map +1 -0
  168. package/dist/classic/chrome/composer-keys.d.ts +4 -0
  169. package/dist/classic/chrome/composer-keys.js +45 -0
  170. package/dist/classic/chrome/composer-keys.js.map +1 -0
  171. package/dist/classic/chrome/context-limit-editor.d.ts +7 -0
  172. package/dist/classic/chrome/context-limit-editor.js +13 -0
  173. package/dist/classic/chrome/context-limit-editor.js.map +1 -0
  174. package/dist/classic/chrome/directory-row.d.ts +14 -0
  175. package/dist/classic/chrome/directory-row.js +26 -0
  176. package/dist/classic/chrome/directory-row.js.map +1 -0
  177. package/dist/classic/chrome/editor-model.d.ts +37 -0
  178. package/dist/classic/chrome/editor-model.js +195 -0
  179. package/dist/classic/chrome/editor-model.js.map +1 -0
  180. package/dist/classic/chrome/editor-view.d.ts +34 -0
  181. package/dist/classic/chrome/editor-view.js +133 -0
  182. package/dist/classic/chrome/editor-view.js.map +1 -0
  183. package/dist/classic/chrome/queue-rows.d.ts +10 -0
  184. package/dist/classic/chrome/queue-rows.js +32 -0
  185. package/dist/classic/chrome/queue-rows.js.map +1 -0
  186. package/dist/classic/chrome/responder-row.d.ts +9 -0
  187. package/dist/classic/chrome/responder-row.js +17 -0
  188. package/dist/classic/chrome/responder-row.js.map +1 -0
  189. package/dist/classic/chrome/row-budget.d.ts +43 -0
  190. package/dist/classic/chrome/row-budget.js +78 -0
  191. package/dist/classic/chrome/row-budget.js.map +1 -0
  192. package/dist/classic/chrome/status-rows.d.ts +44 -0
  193. package/dist/classic/chrome/status-rows.js +165 -0
  194. package/dist/classic/chrome/status-rows.js.map +1 -0
  195. package/dist/classic/chrome/toast-rows.d.ts +14 -0
  196. package/dist/classic/chrome/toast-rows.js +82 -0
  197. package/dist/classic/chrome/toast-rows.js.map +1 -0
  198. package/dist/classic/chrome/use-terminal-size.d.ts +14 -0
  199. package/dist/classic/chrome/use-terminal-size.js +38 -0
  200. package/dist/classic/chrome/use-terminal-size.js.map +1 -0
  201. package/dist/classic/feed/Feed.d.ts +17 -0
  202. package/dist/classic/feed/Feed.js +37 -0
  203. package/dist/classic/feed/Feed.js.map +1 -0
  204. package/dist/classic/feed/FeedStatic.d.ts +13 -0
  205. package/dist/classic/feed/FeedStatic.js +15 -0
  206. package/dist/classic/feed/FeedStatic.js.map +1 -0
  207. package/dist/classic/feed/LiveTail.d.ts +10 -0
  208. package/dist/classic/feed/LiveTail.js +20 -0
  209. package/dist/classic/feed/LiveTail.js.map +1 -0
  210. package/dist/classic/feed/ScrollbarGutter.d.ts +9 -0
  211. package/dist/classic/feed/ScrollbarGutter.js +42 -0
  212. package/dist/classic/feed/ScrollbarGutter.js.map +1 -0
  213. package/dist/classic/feed/block-height.d.ts +12 -0
  214. package/dist/classic/feed/block-height.js +34 -0
  215. package/dist/classic/feed/block-height.js.map +1 -0
  216. package/dist/classic/feed/commit-ledger.d.ts +26 -0
  217. package/dist/classic/feed/commit-ledger.js +52 -0
  218. package/dist/classic/feed/commit-ledger.js.map +1 -0
  219. package/dist/classic/feed/feed-blocks.d.ts +39 -0
  220. package/dist/classic/feed/feed-blocks.js +124 -0
  221. package/dist/classic/feed/feed-blocks.js.map +1 -0
  222. package/dist/classic/feed/live-tail-policy.d.ts +35 -0
  223. package/dist/classic/feed/live-tail-policy.js +80 -0
  224. package/dist/classic/feed/live-tail-policy.js.map +1 -0
  225. package/dist/classic/feed/scrollbar-rows.d.ts +6 -0
  226. package/dist/classic/feed/scrollbar-rows.js +18 -0
  227. package/dist/classic/feed/scrollbar-rows.js.map +1 -0
  228. package/dist/classic/feed/transcript-selection.d.ts +16 -0
  229. package/dist/classic/feed/transcript-selection.js +92 -0
  230. package/dist/classic/feed/transcript-selection.js.map +1 -0
  231. package/dist/classic/feed/transcript-window.d.ts +33 -0
  232. package/dist/classic/feed/transcript-window.js +53 -0
  233. package/dist/classic/feed/transcript-window.js.map +1 -0
  234. package/dist/classic/input/cancel-ladder.d.ts +47 -0
  235. package/dist/classic/input/cancel-ladder.js +100 -0
  236. package/dist/classic/input/cancel-ladder.js.map +1 -0
  237. package/dist/classic/input/chord-from-key.d.ts +2 -0
  238. package/dist/classic/input/chord-from-key.js +25 -0
  239. package/dist/classic/input/chord-from-key.js.map +1 -0
  240. package/dist/classic/input/input-router.d.ts +33 -0
  241. package/dist/classic/input/input-router.js +146 -0
  242. package/dist/classic/input/input-router.js.map +1 -0
  243. package/dist/classic/input/key-event.d.ts +39 -0
  244. package/dist/classic/input/key-event.js +12 -0
  245. package/dist/classic/input/key-event.js.map +1 -0
  246. package/dist/classic/input/paste-decoder.d.ts +1 -0
  247. package/dist/classic/input/paste-decoder.js +9 -0
  248. package/dist/classic/input/paste-decoder.js.map +1 -0
  249. package/dist/classic/input/raw-decoder.d.ts +31 -0
  250. package/dist/classic/input/raw-decoder.js +325 -0
  251. package/dist/classic/input/raw-decoder.js.map +1 -0
  252. package/dist/classic/input/sgr-mouse.d.ts +2 -0
  253. package/dist/classic/input/sgr-mouse.js +37 -0
  254. package/dist/classic/input/sgr-mouse.js.map +1 -0
  255. package/dist/classic/input/terminal-sequences.d.ts +38 -0
  256. package/dist/classic/input/terminal-sequences.js +111 -0
  257. package/dist/classic/input/terminal-sequences.js.map +1 -0
  258. package/dist/classic/panels/CompletionPanel.d.ts +3 -0
  259. package/dist/classic/panels/CompletionPanel.js +10 -0
  260. package/dist/classic/panels/CompletionPanel.js.map +1 -0
  261. package/dist/classic/panels/ConfirmPanel.d.ts +3 -0
  262. package/dist/classic/panels/ConfirmPanel.js +7 -0
  263. package/dist/classic/panels/ConfirmPanel.js.map +1 -0
  264. package/dist/classic/panels/JobsPanel.d.ts +3 -0
  265. package/dist/classic/panels/JobsPanel.js +7 -0
  266. package/dist/classic/panels/JobsPanel.js.map +1 -0
  267. package/dist/classic/panels/KeysPanel.d.ts +3 -0
  268. package/dist/classic/panels/KeysPanel.js +7 -0
  269. package/dist/classic/panels/KeysPanel.js.map +1 -0
  270. package/dist/classic/panels/PagerPanel.d.ts +3 -0
  271. package/dist/classic/panels/PagerPanel.js +7 -0
  272. package/dist/classic/panels/PagerPanel.js.map +1 -0
  273. package/dist/classic/panels/PanelFrame.d.ts +3 -0
  274. package/dist/classic/panels/PanelFrame.js +8 -0
  275. package/dist/classic/panels/PanelFrame.js.map +1 -0
  276. package/dist/classic/panels/PickerPanel.d.ts +3 -0
  277. package/dist/classic/panels/PickerPanel.js +7 -0
  278. package/dist/classic/panels/PickerPanel.js.map +1 -0
  279. package/dist/classic/panels/PlanPanel.d.ts +3 -0
  280. package/dist/classic/panels/PlanPanel.js +7 -0
  281. package/dist/classic/panels/PlanPanel.js.map +1 -0
  282. package/dist/classic/panels/PromptActionsPanel.d.ts +3 -0
  283. package/dist/classic/panels/PromptActionsPanel.js +7 -0
  284. package/dist/classic/panels/PromptActionsPanel.js.map +1 -0
  285. package/dist/classic/panels/ScopePanel.d.ts +3 -0
  286. package/dist/classic/panels/ScopePanel.js +7 -0
  287. package/dist/classic/panels/ScopePanel.js.map +1 -0
  288. package/dist/classic/panels/SearchPanel.d.ts +3 -0
  289. package/dist/classic/panels/SearchPanel.js +7 -0
  290. package/dist/classic/panels/SearchPanel.js.map +1 -0
  291. package/dist/classic/panels/SecretPanel.d.ts +3 -0
  292. package/dist/classic/panels/SecretPanel.js +7 -0
  293. package/dist/classic/panels/SecretPanel.js.map +1 -0
  294. package/dist/classic/panels/completion-accept.d.ts +17 -0
  295. package/dist/classic/panels/completion-accept.js +58 -0
  296. package/dist/classic/panels/completion-accept.js.map +1 -0
  297. package/dist/classic/panels/completion-rows.d.ts +29 -0
  298. package/dist/classic/panels/completion-rows.js +135 -0
  299. package/dist/classic/panels/completion-rows.js.map +1 -0
  300. package/dist/classic/panels/confirm-panel.d.ts +24 -0
  301. package/dist/classic/panels/confirm-panel.js +115 -0
  302. package/dist/classic/panels/confirm-panel.js.map +1 -0
  303. package/dist/classic/panels/jobs-panel.d.ts +32 -0
  304. package/dist/classic/panels/jobs-panel.js +116 -0
  305. package/dist/classic/panels/jobs-panel.js.map +1 -0
  306. package/dist/classic/panels/keys-panel.d.ts +40 -0
  307. package/dist/classic/panels/keys-panel.js +174 -0
  308. package/dist/classic/panels/keys-panel.js.map +1 -0
  309. package/dist/classic/panels/list-rows.d.ts +27 -0
  310. package/dist/classic/panels/list-rows.js +42 -0
  311. package/dist/classic/panels/list-rows.js.map +1 -0
  312. package/dist/classic/panels/list-window.d.ts +15 -0
  313. package/dist/classic/panels/list-window.js +25 -0
  314. package/dist/classic/panels/list-window.js.map +1 -0
  315. package/dist/classic/panels/pager-panel.d.ts +50 -0
  316. package/dist/classic/panels/pager-panel.js +238 -0
  317. package/dist/classic/panels/pager-panel.js.map +1 -0
  318. package/dist/classic/panels/panel-controller.d.ts +29 -0
  319. package/dist/classic/panels/panel-controller.js +320 -0
  320. package/dist/classic/panels/panel-controller.js.map +1 -0
  321. package/dist/classic/panels/panel-effect.d.ts +74 -0
  322. package/dist/classic/panels/panel-effect.js +7 -0
  323. package/dist/classic/panels/panel-effect.js.map +1 -0
  324. package/dist/classic/panels/panel-effects.d.ts +11 -0
  325. package/dist/classic/panels/panel-effects.js +105 -0
  326. package/dist/classic/panels/panel-effects.js.map +1 -0
  327. package/dist/classic/panels/panel-frame.d.ts +20 -0
  328. package/dist/classic/panels/panel-frame.js +47 -0
  329. package/dist/classic/panels/panel-frame.js.map +1 -0
  330. package/dist/classic/panels/panel-host.d.ts +16 -0
  331. package/dist/classic/panels/panel-host.js +49 -0
  332. package/dist/classic/panels/panel-host.js.map +1 -0
  333. package/dist/classic/panels/panel-initial-states.d.ts +18 -0
  334. package/dist/classic/panels/panel-initial-states.js +33 -0
  335. package/dist/classic/panels/panel-initial-states.js.map +1 -0
  336. package/dist/classic/panels/panel-types.d.ts +47 -0
  337. package/dist/classic/panels/panel-types.js +2 -0
  338. package/dist/classic/panels/panel-types.js.map +1 -0
  339. package/dist/classic/panels/panel-wheel.d.ts +20 -0
  340. package/dist/classic/panels/panel-wheel.js +82 -0
  341. package/dist/classic/panels/panel-wheel.js.map +1 -0
  342. package/dist/classic/panels/picker-panel.d.ts +35 -0
  343. package/dist/classic/panels/picker-panel.js +150 -0
  344. package/dist/classic/panels/picker-panel.js.map +1 -0
  345. package/dist/classic/panels/plan-panel.d.ts +27 -0
  346. package/dist/classic/panels/plan-panel.js +98 -0
  347. package/dist/classic/panels/plan-panel.js.map +1 -0
  348. package/dist/classic/panels/prompt-actions-panel.d.ts +25 -0
  349. package/dist/classic/panels/prompt-actions-panel.js +57 -0
  350. package/dist/classic/panels/prompt-actions-panel.js.map +1 -0
  351. package/dist/classic/panels/scope-panel.d.ts +27 -0
  352. package/dist/classic/panels/scope-panel.js +122 -0
  353. package/dist/classic/panels/scope-panel.js.map +1 -0
  354. package/dist/classic/panels/search-panel.d.ts +32 -0
  355. package/dist/classic/panels/search-panel.js +126 -0
  356. package/dist/classic/panels/search-panel.js.map +1 -0
  357. package/dist/classic/panels/secret-panel.d.ts +28 -0
  358. package/dist/classic/panels/secret-panel.js +70 -0
  359. package/dist/classic/panels/secret-panel.js.map +1 -0
  360. package/dist/classic/render/ansi-text.d.ts +36 -0
  361. package/dist/classic/render/ansi-text.js +234 -0
  362. package/dist/classic/render/ansi-text.js.map +1 -0
  363. package/dist/classic/render/glyphs.d.ts +49 -0
  364. package/dist/classic/render/glyphs.js +111 -0
  365. package/dist/classic/render/glyphs.js.map +1 -0
  366. package/dist/classic/render/ink-theme.d.ts +49 -0
  367. package/dist/classic/render/ink-theme.js +73 -0
  368. package/dist/classic/render/ink-theme.js.map +1 -0
  369. package/dist/classic/render/measure.d.ts +17 -0
  370. package/dist/classic/render/measure.js +33 -0
  371. package/dist/classic/render/measure.js.map +1 -0
  372. package/dist/classic/render/shell-width.d.ts +12 -0
  373. package/dist/classic/render/shell-width.js +23 -0
  374. package/dist/classic/render/shell-width.js.map +1 -0
  375. package/dist/classic/render/wrap.d.ts +19 -0
  376. package/dist/classic/render/wrap.js +102 -0
  377. package/dist/classic/render/wrap.js.map +1 -0
  378. package/dist/commands/doctor.js +9 -8
  379. package/dist/commands/doctor.js.map +1 -1
  380. package/dist/commands/providers.js +43 -50
  381. package/dist/commands/providers.js.map +1 -1
  382. package/dist/commands/search-providers.js +3 -5
  383. package/dist/commands/search-providers.js.map +1 -1
  384. package/dist/index.js +76 -84
  385. package/dist/index.js.map +1 -1
  386. package/dist/llm/capabilities.js +5 -2
  387. package/dist/llm/capabilities.js.map +1 -1
  388. package/dist/llm/custom-providers.js +16 -3
  389. package/dist/llm/custom-providers.js.map +1 -1
  390. package/dist/llm/http.d.ts +5 -0
  391. package/dist/llm/http.js +38 -8
  392. package/dist/llm/http.js.map +1 -1
  393. package/dist/llm/meta.js +56 -24
  394. package/dist/llm/meta.js.map +1 -1
  395. package/dist/llm/modal.js +3 -2
  396. package/dist/llm/modal.js.map +1 -1
  397. package/dist/llm/router.js +36 -23
  398. package/dist/llm/router.js.map +1 -1
  399. package/dist/llm/system-messages.d.ts +1 -0
  400. package/dist/llm/system-messages.js +6 -0
  401. package/dist/llm/system-messages.js.map +1 -1
  402. package/dist/llm/token-usage.js +11 -1
  403. package/dist/llm/token-usage.js.map +1 -1
  404. package/dist/llm/tool-protocol.js +10 -3
  405. package/dist/llm/tool-protocol.js.map +1 -1
  406. package/dist/modes/agent.d.ts +3 -0
  407. package/dist/modes/agent.js +10 -3
  408. package/dist/modes/agent.js.map +1 -1
  409. package/dist/modes/ask.js +2 -2
  410. package/dist/modes/ask.js.map +1 -1
  411. package/dist/noninteractive/read-stdin.d.ts +1 -0
  412. package/dist/noninteractive/read-stdin.js +8 -0
  413. package/dist/noninteractive/read-stdin.js.map +1 -0
  414. package/dist/noninteractive/readline-prompts.d.ts +47 -0
  415. package/dist/noninteractive/readline-prompts.js +201 -0
  416. package/dist/noninteractive/readline-prompts.js.map +1 -0
  417. package/dist/noninteractive/start-noninteractive.d.ts +32 -0
  418. package/dist/noninteractive/start-noninteractive.js +100 -0
  419. package/dist/noninteractive/start-noninteractive.js.map +1 -0
  420. package/dist/noninteractive/stdio-confirm-port.d.ts +15 -0
  421. package/dist/noninteractive/stdio-confirm-port.js +45 -0
  422. package/dist/noninteractive/stdio-confirm-port.js.map +1 -0
  423. package/dist/noninteractive/stream-blocks.d.ts +117 -0
  424. package/dist/noninteractive/stream-blocks.js +445 -0
  425. package/dist/noninteractive/stream-blocks.js.map +1 -0
  426. package/dist/noninteractive/stream-renderer.d.ts +40 -0
  427. package/dist/noninteractive/stream-renderer.js +164 -0
  428. package/dist/noninteractive/stream-renderer.js.map +1 -0
  429. package/dist/noninteractive/stream-spinner.d.ts +28 -0
  430. package/dist/noninteractive/stream-spinner.js +45 -0
  431. package/dist/noninteractive/stream-spinner.js.map +1 -0
  432. package/dist/os/bun-runtime.js +207 -0
  433. package/dist/os/bun-runtime.js.map +1 -0
  434. package/dist/prompts/embedded.js +1 -1
  435. package/dist/prompts/embedded.js.map +1 -1
  436. package/dist/prompts/system.agent.md +11 -7
  437. package/dist/store/config.d.ts +3 -1
  438. package/dist/store/config.js +37 -5
  439. package/dist/store/config.js.map +1 -1
  440. package/dist/store/history.d.ts +1 -1
  441. package/dist/store/history.js +3 -0
  442. package/dist/store/history.js.map +1 -1
  443. package/dist/store/keys.d.ts +5 -2
  444. package/dist/store/keys.js +97 -14
  445. package/dist/store/keys.js.map +1 -1
  446. package/dist/tools/definitions.js +1 -1
  447. package/dist/tools/definitions.js.map +1 -1
  448. package/dist/tools/registry.js +27 -4
  449. package/dist/tools/registry.js.map +1 -1
  450. package/dist/tools/web/providers/duckduckgo.js +1 -1
  451. package/dist/tools/web/providers/duckduckgo.js.map +1 -1
  452. package/dist/tools/web/readable.js +1 -1
  453. package/dist/tools/web/readable.js.map +1 -1
  454. package/dist/tui-v2/app/App.js +20 -28
  455. package/dist/tui-v2/app/App.js.map +1 -1
  456. package/dist/tui-v2/bootstrap/pager-export.d.ts +9 -18
  457. package/dist/tui-v2/bootstrap/pager-export.js +15 -72
  458. package/dist/tui-v2/bootstrap/pager-export.js.map +1 -1
  459. package/dist/tui-v2/bootstrap/start-tui-v2.js +8 -8
  460. package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
  461. package/dist/tui-v2/components/completion/completion-menu.d.ts +2 -2
  462. package/dist/tui-v2/components/composer/composer-input-box.d.ts +1 -1
  463. package/dist/tui-v2/components/composer/paste-chip.d.ts +2 -2
  464. package/dist/tui-v2/components/composer/paste-chip.js +1 -1
  465. package/dist/tui-v2/components/composer/paste-chip.js.map +1 -1
  466. package/dist/tui-v2/components/jobs/jobs-panel.d.ts +2 -2
  467. package/dist/tui-v2/components/jobs/jobs-panel.js +4 -4
  468. package/dist/tui-v2/components/jobs/jobs-panel.js.map +1 -1
  469. package/dist/tui-v2/components/modal/confirm-modal.d.ts +3 -3
  470. package/dist/tui-v2/components/modal/confirm-modal.js +6 -6
  471. package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -1
  472. package/dist/tui-v2/components/modal/keys-modal.d.ts +3 -3
  473. package/dist/tui-v2/components/modal/keys-modal.js +24 -9
  474. package/dist/tui-v2/components/modal/keys-modal.js.map +1 -1
  475. package/dist/tui-v2/components/modal/prompt-actions-modal.d.ts +3 -3
  476. package/dist/tui-v2/components/modal/prompt-actions-modal.js +2 -2
  477. package/dist/tui-v2/components/modal/prompt-actions-modal.js.map +1 -1
  478. package/dist/tui-v2/components/modal/scope-modal.d.ts +3 -3
  479. package/dist/tui-v2/components/modal/scope-modal.js +1 -1
  480. package/dist/tui-v2/components/modal/scope-modal.js.map +1 -1
  481. package/dist/tui-v2/components/modal/secret-modal.d.ts +3 -3
  482. package/dist/tui-v2/components/modal/secret-modal.js +2 -2
  483. package/dist/tui-v2/components/modal/secret-modal.js.map +1 -1
  484. package/dist/tui-v2/components/overlay/overlay-host.d.ts +2 -2
  485. package/dist/tui-v2/components/overlay/overlay-host.js +1 -1
  486. package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
  487. package/dist/tui-v2/components/pager/pager-line.d.ts +3 -3
  488. package/dist/tui-v2/components/pager/pager-line.js +3 -3
  489. package/dist/tui-v2/components/pager/pager-line.js.map +1 -1
  490. package/dist/tui-v2/components/pager/pager.d.ts +3 -3
  491. package/dist/tui-v2/components/pager/pager.js +6 -5
  492. package/dist/tui-v2/components/pager/pager.js.map +1 -1
  493. package/dist/tui-v2/components/picker/picker.d.ts +3 -3
  494. package/dist/tui-v2/components/picker/picker.js +2 -2
  495. package/dist/tui-v2/components/picker/picker.js.map +1 -1
  496. package/dist/tui-v2/components/plan/plan-pane-anim.js +1 -1
  497. package/dist/tui-v2/components/plan/plan-pane-anim.js.map +1 -1
  498. package/dist/tui-v2/components/plan/plan-view.d.ts +2 -2
  499. package/dist/tui-v2/components/plan/plan-view.js +2 -2
  500. package/dist/tui-v2/components/plan/plan-view.js.map +1 -1
  501. package/dist/tui-v2/components/queue/queue-panel.d.ts +2 -2
  502. package/dist/tui-v2/components/queue/queue-panel.js +3 -3
  503. package/dist/tui-v2/components/queue/queue-panel.js.map +1 -1
  504. package/dist/tui-v2/components/status/context-limit-chip.d.ts +1 -5
  505. package/dist/tui-v2/components/status/context-limit-chip.js +1 -38
  506. package/dist/tui-v2/components/status/context-limit-chip.js.map +1 -1
  507. package/dist/tui-v2/components/status/status-line.d.ts +5 -34
  508. package/dist/tui-v2/components/status/status-line.js +7 -99
  509. package/dist/tui-v2/components/status/status-line.js.map +1 -1
  510. package/dist/tui-v2/components/toast/toast-anim.d.ts +0 -1
  511. package/dist/tui-v2/components/toast/toast-anim.js +2 -3
  512. package/dist/tui-v2/components/toast/toast-anim.js.map +1 -1
  513. package/dist/tui-v2/components/toast/toast-host.d.ts +2 -2
  514. package/dist/tui-v2/components/toast/toast-host.js +2 -2
  515. package/dist/tui-v2/components/toast/toast-host.js.map +1 -1
  516. package/dist/tui-v2/components/transcript/assistant-message.d.ts +2 -2
  517. package/dist/tui-v2/components/transcript/assistant-message.js +3 -2
  518. package/dist/tui-v2/components/transcript/assistant-message.js.map +1 -1
  519. package/dist/tui-v2/components/transcript/compacted-row.d.ts +3 -3
  520. package/dist/tui-v2/components/transcript/compacted-row.js +6 -5
  521. package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
  522. package/dist/tui-v2/components/transcript/file-diff-card.d.ts +1 -1
  523. package/dist/tui-v2/components/transcript/file-diff-card.js +1 -1
  524. package/dist/tui-v2/components/transcript/file-diff-card.js.map +1 -1
  525. package/dist/tui-v2/components/transcript/intro-card.d.ts +2 -2
  526. package/dist/tui-v2/components/transcript/intro-card.js +1 -1
  527. package/dist/tui-v2/components/transcript/intro-card.js.map +1 -1
  528. package/dist/tui-v2/components/transcript/linkable-text.d.ts +1 -1
  529. package/dist/tui-v2/components/transcript/linkable-text.js +1 -1
  530. package/dist/tui-v2/components/transcript/linkable-text.js.map +1 -1
  531. package/dist/tui-v2/components/transcript/notice-row.d.ts +2 -2
  532. package/dist/tui-v2/components/transcript/search-bar.d.ts +1 -1
  533. package/dist/tui-v2/components/transcript/thinking-block.d.ts +2 -2
  534. package/dist/tui-v2/components/transcript/thinking-block.js +3 -3
  535. package/dist/tui-v2/components/transcript/thinking-block.js.map +1 -1
  536. package/dist/tui-v2/components/transcript/tool-card.d.ts +3 -3
  537. package/dist/tui-v2/components/transcript/tool-card.js +7 -7
  538. package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
  539. package/dist/tui-v2/components/transcript/transcript-row.d.ts +4 -4
  540. package/dist/tui-v2/components/transcript/transcript-scrollbar.d.ts +1 -1
  541. package/dist/tui-v2/components/transcript/transcript-scrollbar.js +42 -9
  542. package/dist/tui-v2/components/transcript/transcript-scrollbar.js.map +1 -1
  543. package/dist/tui-v2/components/transcript/transcript-view.d.ts +3 -3
  544. package/dist/tui-v2/components/transcript/transcript-view.js +6 -6
  545. package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
  546. package/dist/tui-v2/components/transcript/use-native-selection-copy.d.ts +1 -1
  547. package/dist/tui-v2/components/transcript/use-transcript-selection.d.ts +2 -2
  548. package/dist/tui-v2/components/transcript/use-transcript-selection.js +3 -3
  549. package/dist/tui-v2/components/transcript/use-transcript-selection.js.map +1 -1
  550. package/dist/tui-v2/components/transcript/user-message.d.ts +2 -2
  551. package/dist/tui-v2/components/transcript/user-message.js +1 -1
  552. package/dist/tui-v2/components/transcript/user-message.js.map +1 -1
  553. package/dist/tui-v2/composer/composer-editor.d.ts +2 -2
  554. package/dist/tui-v2/composer/composer-editor.js +21 -20
  555. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  556. package/dist/tui-v2/composer/composer-image-paste.d.ts +1 -1
  557. package/dist/tui-v2/composer/composer-image-paste.js +1 -1
  558. package/dist/tui-v2/composer/composer-image-paste.js.map +1 -1
  559. package/dist/tui-v2/composer/use-draft-actions.d.ts +2 -2
  560. package/dist/tui-v2/composer/use-draft-actions.js +2 -2
  561. package/dist/tui-v2/composer/use-draft-actions.js.map +1 -1
  562. package/dist/tui-v2/input/chord-from-opentui-key.d.ts +20 -0
  563. package/dist/tui-v2/input/chord-from-opentui-key.js +51 -0
  564. package/dist/tui-v2/input/chord-from-opentui-key.js.map +1 -0
  565. package/dist/tui-v2/rendering/pager-markdown.d.ts +2 -22
  566. package/dist/tui-v2/rendering/pager-markdown.js +4 -103
  567. package/dist/tui-v2/rendering/pager-markdown.js.map +1 -1
  568. package/dist/tui-v2/rendering/styled-markdown.d.ts +20 -0
  569. package/dist/tui-v2/rendering/styled-markdown.js +35 -0
  570. package/dist/tui-v2/rendering/styled-markdown.js.map +1 -0
  571. package/dist/types.d.ts +2 -0
  572. package/dist/ui/mentions.d.ts +5 -8
  573. package/dist/ui/mentions.js +26 -8
  574. package/dist/ui/mentions.js.map +1 -1
  575. package/dist/ui/warn-once.d.ts +2 -0
  576. package/dist/ui/warn-once.js +13 -0
  577. package/dist/ui/warn-once.js.map +1 -0
  578. package/dist/ui-core/actions/action-id.d.ts +14 -0
  579. package/dist/ui-core/actions/action-id.js +123 -0
  580. package/dist/ui-core/actions/action-id.js.map +1 -0
  581. package/dist/ui-core/actions/action-router.js.map +1 -0
  582. package/dist/ui-core/actions/chord.d.ts +20 -0
  583. package/dist/ui-core/actions/chord.js +28 -0
  584. package/dist/ui-core/actions/chord.js.map +1 -0
  585. package/dist/ui-core/actions/format-shortcuts.js +267 -0
  586. package/dist/ui-core/actions/format-shortcuts.js.map +1 -0
  587. package/dist/ui-core/actions/keymap.d.ts +23 -0
  588. package/dist/ui-core/actions/keymap.js +147 -0
  589. package/dist/ui-core/actions/keymap.js.map +1 -0
  590. package/dist/ui-core/actions/mode-cycle.js.map +1 -0
  591. package/dist/ui-core/bootstrap/can-use-tui.js.map +1 -0
  592. package/dist/ui-core/bootstrap/capabilities.js +96 -0
  593. package/dist/ui-core/bootstrap/capabilities.js.map +1 -0
  594. package/dist/ui-core/bootstrap/composition-root.d.ts +92 -0
  595. package/dist/ui-core/bootstrap/composition-root.js.map +1 -0
  596. package/dist/ui-core/bootstrap/console-guard.js.map +1 -0
  597. package/dist/ui-core/bootstrap/console-suppress.js.map +1 -0
  598. package/dist/ui-core/bootstrap/lifecycle.js.map +1 -0
  599. package/dist/ui-core/bootstrap/overlay-ports.js +92 -0
  600. package/dist/ui-core/bootstrap/overlay-ports.js.map +1 -0
  601. package/dist/ui-core/bootstrap/ui-selection.d.ts +27 -0
  602. package/dist/ui-core/bootstrap/ui-selection.js +109 -0
  603. package/dist/ui-core/bootstrap/ui-selection.js.map +1 -0
  604. package/dist/ui-core/commands/command-handlers.js +86 -0
  605. package/dist/ui-core/commands/command-handlers.js.map +1 -0
  606. package/dist/ui-core/commands/config-commands.d.ts +14 -0
  607. package/dist/ui-core/commands/config-commands.js +315 -0
  608. package/dist/ui-core/commands/config-commands.js.map +1 -0
  609. package/dist/ui-core/commands/key-commands.d.ts +9 -0
  610. package/dist/ui-core/commands/key-commands.js +532 -0
  611. package/dist/ui-core/commands/key-commands.js.map +1 -0
  612. package/dist/ui-core/commands/picker-commands.d.ts +25 -0
  613. package/dist/ui-core/commands/picker-commands.js +1045 -0
  614. package/dist/ui-core/commands/picker-commands.js.map +1 -0
  615. package/dist/ui-core/commands/session-commands.d.ts +19 -0
  616. package/dist/ui-core/commands/session-commands.js +183 -0
  617. package/dist/ui-core/commands/session-commands.js.map +1 -0
  618. package/dist/ui-core/commands/startup-update.js.map +1 -0
  619. package/dist/ui-core/composer/arrow-intent.js.map +1 -0
  620. package/dist/ui-core/composer/completion.js.map +1 -0
  621. package/dist/ui-core/composer/composer-action-port.js.map +1 -0
  622. package/dist/ui-core/composer/composer-height.js +29 -0
  623. package/dist/ui-core/composer/composer-height.js.map +1 -0
  624. package/dist/ui-core/composer/composer-image-paste.d.ts +20 -0
  625. package/dist/ui-core/composer/composer-image-paste.js +77 -0
  626. package/dist/ui-core/composer/composer-image-paste.js.map +1 -0
  627. package/dist/ui-core/composer/composer-meta.d.ts +2 -0
  628. package/dist/ui-core/composer/composer-meta.js +31 -0
  629. package/dist/ui-core/composer/composer-meta.js.map +1 -0
  630. package/dist/ui-core/composer/composer-wheel.d.ts +58 -0
  631. package/dist/ui-core/composer/composer-wheel.js +108 -0
  632. package/dist/ui-core/composer/composer-wheel.js.map +1 -0
  633. package/dist/ui-core/composer/draft-actions.d.ts +31 -0
  634. package/dist/ui-core/composer/draft-actions.js +45 -0
  635. package/dist/ui-core/composer/draft-actions.js.map +1 -0
  636. package/dist/ui-core/composer/history-nav.js.map +1 -0
  637. package/dist/ui-core/composer/input-history.js +9 -0
  638. package/dist/ui-core/composer/input-history.js.map +1 -0
  639. package/dist/ui-core/composer/newline-hint.d.ts +13 -0
  640. package/dist/ui-core/composer/newline-hint.js.map +1 -0
  641. package/dist/ui-core/composer/paste-placeholder.js.map +1 -0
  642. package/dist/ui-core/composer/prompt-history.js.map +1 -0
  643. package/dist/ui-core/composer/secret-buffer.js.map +1 -0
  644. package/dist/ui-core/composer/textarea-keybindings.d.ts +25 -0
  645. package/dist/ui-core/composer/textarea-keybindings.js +84 -0
  646. package/dist/ui-core/composer/textarea-keybindings.js.map +1 -0
  647. package/dist/ui-core/controllers/focus-controller.js.map +1 -0
  648. package/dist/ui-core/controllers/interruptible-controller.js.map +1 -0
  649. package/dist/ui-core/controllers/overlay-controller.d.ts +211 -0
  650. package/dist/ui-core/controllers/overlay-controller.js.map +1 -0
  651. package/dist/ui-core/controllers/selection-controller.js.map +1 -0
  652. package/dist/ui-core/controllers/toast-controller.js.map +1 -0
  653. package/dist/ui-core/layout/compute-layout.js.map +1 -0
  654. package/dist/ui-core/motion/ease.js.map +1 -0
  655. package/dist/ui-core/notify.js.map +1 -0
  656. package/dist/ui-core/plan/plan-lifecycle.js.map +1 -0
  657. package/dist/ui-core/ports/clipboard-osc52.js +44 -0
  658. package/dist/ui-core/ports/clipboard-osc52.js.map +1 -0
  659. package/dist/ui-core/ports/pager-export-port.d.ts +16 -0
  660. package/dist/ui-core/ports/pager-export-port.js +70 -0
  661. package/dist/ui-core/ports/pager-export-port.js.map +1 -0
  662. package/dist/ui-core/ports/renderer-port.d.ts +10 -0
  663. package/dist/ui-core/ports/renderer-port.js +2 -0
  664. package/dist/ui-core/ports/renderer-port.js.map +1 -0
  665. package/dist/ui-core/react/providers.d.ts +16 -0
  666. package/dist/ui-core/react/providers.js +31 -0
  667. package/dist/ui-core/react/providers.js.map +1 -0
  668. package/dist/ui-core/react/use-has-draft.js.map +1 -0
  669. package/dist/ui-core/react/use-overlay.js.map +1 -0
  670. package/dist/ui-core/react/use-plan.js.map +1 -0
  671. package/dist/ui-core/react/use-session-state.js.map +1 -0
  672. package/dist/ui-core/react/use-toast.js.map +1 -0
  673. package/dist/ui-core/react/use-transcript-store.d.ts +10 -0
  674. package/dist/ui-core/react/use-transcript-store.js.map +1 -0
  675. package/dist/ui-core/rendering/artifact-pager-source.js.map +1 -0
  676. package/dist/ui-core/rendering/batch-sections.js.map +1 -0
  677. package/dist/ui-core/rendering/code-block.d.ts +48 -0
  678. package/dist/ui-core/rendering/code-block.js +407 -0
  679. package/dist/ui-core/rendering/code-block.js.map +1 -0
  680. package/dist/ui-core/rendering/context-limit.d.ts +8 -0
  681. package/dist/ui-core/rendering/context-limit.js +49 -0
  682. package/dist/ui-core/rendering/context-limit.js.map +1 -0
  683. package/dist/ui-core/rendering/file-diff-view.js.map +1 -0
  684. package/dist/ui-core/rendering/format-help.js.map +1 -0
  685. package/dist/ui-core/rendering/format-keys.d.ts +14 -0
  686. package/dist/ui-core/rendering/format-keys.js +78 -0
  687. package/dist/ui-core/rendering/format-keys.js.map +1 -0
  688. package/dist/ui-core/rendering/incremental-strip.js.map +1 -0
  689. package/dist/ui-core/rendering/intro-header.d.ts +11 -0
  690. package/dist/ui-core/rendering/intro-header.js +208 -0
  691. package/dist/ui-core/rendering/intro-header.js.map +1 -0
  692. package/dist/ui-core/rendering/job-tail-source.js.map +1 -0
  693. package/dist/ui-core/rendering/link-detector.js.map +1 -0
  694. package/dist/ui-core/rendering/markdown.js.map +1 -0
  695. package/dist/ui-core/rendering/open-tool-output.js +346 -0
  696. package/dist/ui-core/rendering/open-tool-output.js.map +1 -0
  697. package/dist/ui-core/rendering/pager-chrome.js +119 -0
  698. package/dist/ui-core/rendering/pager-chrome.js.map +1 -0
  699. package/dist/ui-core/rendering/pager-source.d.ts +20 -0
  700. package/dist/ui-core/rendering/pager-source.js +101 -0
  701. package/dist/ui-core/rendering/pager-source.js.map +1 -0
  702. package/dist/ui-core/rendering/pager-text.d.ts +24 -0
  703. package/dist/ui-core/rendering/pager-text.js +105 -0
  704. package/dist/ui-core/rendering/pager-text.js.map +1 -0
  705. package/dist/ui-core/rendering/pager-view-policy.js +98 -0
  706. package/dist/ui-core/rendering/pager-view-policy.js.map +1 -0
  707. package/dist/ui-core/rendering/picker-filter.js.map +1 -0
  708. package/dist/ui-core/rendering/plan-view.js.map +1 -0
  709. package/dist/ui-core/rendering/prompt-preview.js.map +1 -0
  710. package/dist/ui-core/rendering/render-markdown-lines.d.ts +7 -0
  711. package/dist/ui-core/rendering/render-markdown-lines.js +26 -0
  712. package/dist/ui-core/rendering/render-markdown-lines.js.map +1 -0
  713. package/dist/ui-core/rendering/sanitize-display.js.map +1 -0
  714. package/dist/ui-core/rendering/status-segments.d.ts +25 -0
  715. package/dist/ui-core/rendering/status-segments.js +88 -0
  716. package/dist/ui-core/rendering/status-segments.js.map +1 -0
  717. package/dist/ui-core/rendering/streaming-markdown.d.ts +23 -0
  718. package/dist/ui-core/rendering/streaming-markdown.js +118 -0
  719. package/dist/ui-core/rendering/streaming-markdown.js.map +1 -0
  720. package/dist/ui-core/rendering/strip-tool-surfaces.js.map +1 -0
  721. package/dist/ui-core/rendering/syntax-highlight.js.map +1 -0
  722. package/dist/ui-core/rendering/text-format.js.map +1 -0
  723. package/dist/ui-core/rendering/text-width.js.map +1 -0
  724. package/dist/ui-core/rendering/theme.js.map +1 -0
  725. package/dist/ui-core/rendering/thinking-tail.js.map +1 -0
  726. package/dist/ui-core/rendering/tool-presenter.d.ts +68 -0
  727. package/dist/ui-core/rendering/tool-presenter.js +371 -0
  728. package/dist/ui-core/rendering/tool-presenter.js.map +1 -0
  729. package/dist/ui-core/rendering/transcript-export.d.ts +11 -0
  730. package/dist/ui-core/rendering/transcript-export.js +18 -0
  731. package/dist/ui-core/rendering/transcript-export.js.map +1 -0
  732. package/dist/ui-core/rendering/transcript-semantic.js.map +1 -0
  733. package/dist/ui-core/rendering/user-message-wrap.d.ts +18 -0
  734. package/dist/ui-core/rendering/user-message-wrap.js +23 -0
  735. package/dist/ui-core/rendering/user-message-wrap.js.map +1 -0
  736. package/dist/ui-core/rendering/wordmark.js.map +1 -0
  737. package/dist/ui-core/state/pager-search.js.map +1 -0
  738. package/dist/ui-core/state/semantic-document.js.map +1 -0
  739. package/dist/ui-core/state/transcript-compaction.js.map +1 -0
  740. package/dist/ui-core/state/transcript-hydrate.d.ts +67 -0
  741. package/dist/ui-core/state/transcript-hydrate.js +665 -0
  742. package/dist/ui-core/state/transcript-hydrate.js.map +1 -0
  743. package/dist/ui-core/state/transcript-reducer.js +484 -0
  744. package/dist/ui-core/state/transcript-reducer.js.map +1 -0
  745. package/dist/ui-core/state/transcript-search.js.map +1 -0
  746. package/dist/ui-core/state/transcript-store.js.map +1 -0
  747. package/dist/ui-core/state/transcript-struct.js.map +1 -0
  748. package/dist/ui-core/state/transcript-types.d.ts +103 -0
  749. package/dist/ui-core/state/transcript-types.js.map +1 -0
  750. package/dist/version.generated.d.ts +2 -2
  751. package/dist/version.generated.js +2 -2
  752. package/dist/version.generated.js.map +1 -1
  753. package/package.json +17 -13
  754. package/dist/agent/classic-renderer.d.ts +0 -5
  755. package/dist/agent/classic-renderer.js +0 -136
  756. package/dist/agent/classic-renderer.js.map +0 -1
  757. package/dist/app/adapters/current-terminal-adapter.d.ts +0 -2
  758. package/dist/app/adapters/current-terminal-adapter.js +0 -24
  759. package/dist/app/adapters/current-terminal-adapter.js.map +0 -1
  760. package/dist/app/controllers/job-controller.d.ts +0 -28
  761. package/dist/app/controllers/job-controller.js +0 -70
  762. package/dist/app/controllers/job-controller.js.map +0 -1
  763. package/dist/repl/prompt-line.d.ts +0 -24
  764. package/dist/repl/prompt-line.js +0 -558
  765. package/dist/repl/prompt-line.js.map +0 -1
  766. package/dist/repl/slash-commands.js +0 -392
  767. package/dist/repl/slash-commands.js.map +0 -1
  768. package/dist/repl.d.ts +0 -18
  769. package/dist/repl.js +0 -1868
  770. package/dist/repl.js.map +0 -1
  771. package/dist/safety/path-permissions.d.ts +0 -14
  772. package/dist/safety/path-permissions.js +0 -43
  773. package/dist/safety/path-permissions.js.map +0 -1
  774. package/dist/tools/reducers/generic.d.ts +0 -14
  775. package/dist/tools/reducers/generic.js +0 -5
  776. package/dist/tools/reducers/generic.js.map +0 -1
  777. package/dist/tui/can-use-tui.js.map +0 -1
  778. package/dist/tui/format-keys.d.ts +0 -13
  779. package/dist/tui/format-keys.js +0 -78
  780. package/dist/tui/format-keys.js.map +0 -1
  781. package/dist/tui/input-history.js +0 -9
  782. package/dist/tui/input-history.js.map +0 -1
  783. package/dist/tui/runtime.js +0 -207
  784. package/dist/tui/runtime.js.map +0 -1
  785. package/dist/tui/state.d.ts +0 -124
  786. package/dist/tui/state.js +0 -496
  787. package/dist/tui/state.js.map +0 -1
  788. package/dist/tui/text-format.js.map +0 -1
  789. package/dist/tui-v2/actions/action-id.d.ts +0 -14
  790. package/dist/tui-v2/actions/action-id.js +0 -117
  791. package/dist/tui-v2/actions/action-id.js.map +0 -1
  792. package/dist/tui-v2/actions/action-router.js.map +0 -1
  793. package/dist/tui-v2/actions/chord-from-key.d.ts +0 -26
  794. package/dist/tui-v2/actions/chord-from-key.js +0 -47
  795. package/dist/tui-v2/actions/chord-from-key.js.map +0 -1
  796. package/dist/tui-v2/actions/format-shortcuts.js +0 -267
  797. package/dist/tui-v2/actions/format-shortcuts.js.map +0 -1
  798. package/dist/tui-v2/actions/keymap.d.ts +0 -24
  799. package/dist/tui-v2/actions/keymap.js +0 -151
  800. package/dist/tui-v2/actions/keymap.js.map +0 -1
  801. package/dist/tui-v2/app/command-handlers.js +0 -86
  802. package/dist/tui-v2/app/command-handlers.js.map +0 -1
  803. package/dist/tui-v2/app/commands/config-commands.d.ts +0 -14
  804. package/dist/tui-v2/app/commands/config-commands.js +0 -315
  805. package/dist/tui-v2/app/commands/config-commands.js.map +0 -1
  806. package/dist/tui-v2/app/commands/key-commands.d.ts +0 -9
  807. package/dist/tui-v2/app/commands/key-commands.js +0 -496
  808. package/dist/tui-v2/app/commands/key-commands.js.map +0 -1
  809. package/dist/tui-v2/app/commands/picker-commands.d.ts +0 -25
  810. package/dist/tui-v2/app/commands/picker-commands.js +0 -1006
  811. package/dist/tui-v2/app/commands/picker-commands.js.map +0 -1
  812. package/dist/tui-v2/app/commands/session-commands.d.ts +0 -19
  813. package/dist/tui-v2/app/commands/session-commands.js +0 -183
  814. package/dist/tui-v2/app/commands/session-commands.js.map +0 -1
  815. package/dist/tui-v2/app/mode-cycle.js.map +0 -1
  816. package/dist/tui-v2/app/plan-lifecycle.js.map +0 -1
  817. package/dist/tui-v2/app/providers.d.ts +0 -17
  818. package/dist/tui-v2/app/providers.js +0 -32
  819. package/dist/tui-v2/app/providers.js.map +0 -1
  820. package/dist/tui-v2/app/startup-update.js.map +0 -1
  821. package/dist/tui-v2/bootstrap/capabilities.js +0 -93
  822. package/dist/tui-v2/bootstrap/capabilities.js.map +0 -1
  823. package/dist/tui-v2/bootstrap/composition-root.d.ts +0 -92
  824. package/dist/tui-v2/bootstrap/composition-root.js.map +0 -1
  825. package/dist/tui-v2/bootstrap/console-guard.js.map +0 -1
  826. package/dist/tui-v2/bootstrap/console-suppress.js.map +0 -1
  827. package/dist/tui-v2/bootstrap/disable-native-selection.d.ts +0 -11
  828. package/dist/tui-v2/bootstrap/disable-native-selection.js +0 -13
  829. package/dist/tui-v2/bootstrap/disable-native-selection.js.map +0 -1
  830. package/dist/tui-v2/bootstrap/lifecycle.js.map +0 -1
  831. package/dist/tui-v2/bootstrap/osc52-clipboard.js +0 -44
  832. package/dist/tui-v2/bootstrap/osc52-clipboard.js.map +0 -1
  833. package/dist/tui-v2/bootstrap/overlay-ports.js +0 -114
  834. package/dist/tui-v2/bootstrap/overlay-ports.js.map +0 -1
  835. package/dist/tui-v2/bootstrap/ui-selection.d.ts +0 -30
  836. package/dist/tui-v2/bootstrap/ui-selection.js +0 -59
  837. package/dist/tui-v2/bootstrap/ui-selection.js.map +0 -1
  838. package/dist/tui-v2/composer/arrow-intent.js.map +0 -1
  839. package/dist/tui-v2/composer/completion.js.map +0 -1
  840. package/dist/tui-v2/composer/composer-action-port.js.map +0 -1
  841. package/dist/tui-v2/composer/composer-height.js +0 -29
  842. package/dist/tui-v2/composer/composer-height.js.map +0 -1
  843. package/dist/tui-v2/composer/composer-meta.d.ts +0 -9
  844. package/dist/tui-v2/composer/composer-meta.js +0 -38
  845. package/dist/tui-v2/composer/composer-meta.js.map +0 -1
  846. package/dist/tui-v2/composer/draft-actions.d.ts +0 -31
  847. package/dist/tui-v2/composer/draft-actions.js +0 -45
  848. package/dist/tui-v2/composer/draft-actions.js.map +0 -1
  849. package/dist/tui-v2/composer/history-nav.js.map +0 -1
  850. package/dist/tui-v2/composer/newline-hint.d.ts +0 -13
  851. package/dist/tui-v2/composer/newline-hint.js.map +0 -1
  852. package/dist/tui-v2/composer/paste-placeholder.js.map +0 -1
  853. package/dist/tui-v2/composer/prompt-history.js.map +0 -1
  854. package/dist/tui-v2/composer/secret-buffer.js.map +0 -1
  855. package/dist/tui-v2/controllers/focus-controller.js.map +0 -1
  856. package/dist/tui-v2/controllers/interruptible-controller.js.map +0 -1
  857. package/dist/tui-v2/controllers/overlay-controller.d.ts +0 -209
  858. package/dist/tui-v2/controllers/overlay-controller.js.map +0 -1
  859. package/dist/tui-v2/controllers/selection-controller.js.map +0 -1
  860. package/dist/tui-v2/controllers/toast-controller.js.map +0 -1
  861. package/dist/tui-v2/layout/compute-layout.js.map +0 -1
  862. package/dist/tui-v2/motion/ease.js.map +0 -1
  863. package/dist/tui-v2/notify.js.map +0 -1
  864. package/dist/tui-v2/rendering/artifact-pager-source.js.map +0 -1
  865. package/dist/tui-v2/rendering/batch-sections.js.map +0 -1
  866. package/dist/tui-v2/rendering/file-diff-view.js.map +0 -1
  867. package/dist/tui-v2/rendering/format-help.js.map +0 -1
  868. package/dist/tui-v2/rendering/incremental-strip.js.map +0 -1
  869. package/dist/tui-v2/rendering/job-tail-source.js.map +0 -1
  870. package/dist/tui-v2/rendering/link-detector.js.map +0 -1
  871. package/dist/tui-v2/rendering/open-tool-output.js +0 -346
  872. package/dist/tui-v2/rendering/open-tool-output.js.map +0 -1
  873. package/dist/tui-v2/rendering/pager-chrome.js +0 -119
  874. package/dist/tui-v2/rendering/pager-chrome.js.map +0 -1
  875. package/dist/tui-v2/rendering/pager-view-policy.js +0 -98
  876. package/dist/tui-v2/rendering/pager-view-policy.js.map +0 -1
  877. package/dist/tui-v2/rendering/picker-filter.js.map +0 -1
  878. package/dist/tui-v2/rendering/plan-view.js.map +0 -1
  879. package/dist/tui-v2/rendering/prompt-preview.js.map +0 -1
  880. package/dist/tui-v2/rendering/render-markdown-lines.d.ts +0 -29
  881. package/dist/tui-v2/rendering/render-markdown-lines.js +0 -46
  882. package/dist/tui-v2/rendering/render-markdown-lines.js.map +0 -1
  883. package/dist/tui-v2/rendering/sanitize-display.js.map +0 -1
  884. package/dist/tui-v2/rendering/streaming-markdown.d.ts +0 -25
  885. package/dist/tui-v2/rendering/streaming-markdown.js +0 -117
  886. package/dist/tui-v2/rendering/streaming-markdown.js.map +0 -1
  887. package/dist/tui-v2/rendering/strip-tool-surfaces.js.map +0 -1
  888. package/dist/tui-v2/rendering/syntax-highlight.js.map +0 -1
  889. package/dist/tui-v2/rendering/theme.js.map +0 -1
  890. package/dist/tui-v2/rendering/thinking-tail.js.map +0 -1
  891. package/dist/tui-v2/rendering/tool-presenter.d.ts +0 -63
  892. package/dist/tui-v2/rendering/tool-presenter.js +0 -376
  893. package/dist/tui-v2/rendering/tool-presenter.js.map +0 -1
  894. package/dist/tui-v2/rendering/transcript-export.d.ts +0 -11
  895. package/dist/tui-v2/rendering/transcript-export.js +0 -18
  896. package/dist/tui-v2/rendering/transcript-export.js.map +0 -1
  897. package/dist/tui-v2/rendering/transcript-semantic.js.map +0 -1
  898. package/dist/tui-v2/rendering/user-message-wrap.d.ts +0 -16
  899. package/dist/tui-v2/rendering/user-message-wrap.js +0 -21
  900. package/dist/tui-v2/rendering/user-message-wrap.js.map +0 -1
  901. package/dist/tui-v2/state/pager-search.js.map +0 -1
  902. package/dist/tui-v2/state/semantic-document.js.map +0 -1
  903. package/dist/tui-v2/state/transcript-compaction.js.map +0 -1
  904. package/dist/tui-v2/state/transcript-hydrate.d.ts +0 -67
  905. package/dist/tui-v2/state/transcript-hydrate.js +0 -648
  906. package/dist/tui-v2/state/transcript-hydrate.js.map +0 -1
  907. package/dist/tui-v2/state/transcript-reducer.js +0 -482
  908. package/dist/tui-v2/state/transcript-reducer.js.map +0 -1
  909. package/dist/tui-v2/state/transcript-search.js.map +0 -1
  910. package/dist/tui-v2/state/transcript-store.js.map +0 -1
  911. package/dist/tui-v2/state/transcript-struct.js.map +0 -1
  912. package/dist/tui-v2/state/transcript-types.d.ts +0 -101
  913. package/dist/tui-v2/state/transcript-types.js.map +0 -1
  914. package/dist/tui-v2/state/use-has-draft.js.map +0 -1
  915. package/dist/tui-v2/state/use-overlay.js.map +0 -1
  916. package/dist/tui-v2/state/use-plan.js.map +0 -1
  917. package/dist/tui-v2/state/use-session-state.js.map +0 -1
  918. package/dist/tui-v2/state/use-toast.js.map +0 -1
  919. package/dist/tui-v2/state/use-transcript-store.d.ts +0 -10
  920. package/dist/tui-v2/state/use-transcript-store.js.map +0 -1
  921. package/dist/ui/ansi-box.d.ts +0 -9
  922. package/dist/ui/ansi-box.js +0 -25
  923. package/dist/ui/ansi-box.js.map +0 -1
  924. package/dist/ui/banner.d.ts +0 -3
  925. package/dist/ui/banner.js +0 -13
  926. package/dist/ui/banner.js.map +0 -1
  927. package/dist/ui/code-block.d.ts +0 -48
  928. package/dist/ui/code-block.js +0 -407
  929. package/dist/ui/code-block.js.map +0 -1
  930. package/dist/ui/intro-card.d.ts +0 -11
  931. package/dist/ui/intro-card.js +0 -74
  932. package/dist/ui/intro-card.js.map +0 -1
  933. package/dist/ui/intro-header.d.ts +0 -24
  934. package/dist/ui/intro-header.js +0 -233
  935. package/dist/ui/intro-header.js.map +0 -1
  936. package/dist/ui/keys.d.ts +0 -23
  937. package/dist/ui/keys.js +0 -23
  938. package/dist/ui/keys.js.map +0 -1
  939. package/dist/ui/markdown.js.map +0 -1
  940. package/dist/ui/output-pane.d.ts +0 -59
  941. package/dist/ui/output-pane.js +0 -398
  942. package/dist/ui/output-pane.js.map +0 -1
  943. package/dist/ui/spinner.d.ts +0 -8
  944. package/dist/ui/spinner.js +0 -185
  945. package/dist/ui/spinner.js.map +0 -1
  946. package/dist/ui/task-pane.d.ts +0 -17
  947. package/dist/ui/task-pane.js +0 -80
  948. package/dist/ui/task-pane.js.map +0 -1
  949. package/dist/ui/text-width.js.map +0 -1
  950. package/dist/ui/wordmark.js.map +0 -1
  951. /package/dist/{repl/slash-commands.d.ts → app/commands/catalog.d.ts} +0 -0
  952. /package/dist/{tui/runtime.d.ts → os/bun-runtime.d.ts} +0 -0
  953. /package/dist/{tui-v2 → ui-core}/actions/action-router.d.ts +0 -0
  954. /package/dist/{tui-v2 → ui-core}/actions/action-router.js +0 -0
  955. /package/dist/{tui-v2 → ui-core}/actions/format-shortcuts.d.ts +0 -0
  956. /package/dist/{tui-v2/app → ui-core/actions}/mode-cycle.d.ts +0 -0
  957. /package/dist/{tui-v2/app → ui-core/actions}/mode-cycle.js +0 -0
  958. /package/dist/{tui → ui-core/bootstrap}/can-use-tui.d.ts +0 -0
  959. /package/dist/{tui → ui-core/bootstrap}/can-use-tui.js +0 -0
  960. /package/dist/{tui-v2 → ui-core}/bootstrap/capabilities.d.ts +0 -0
  961. /package/dist/{tui-v2 → ui-core}/bootstrap/composition-root.js +0 -0
  962. /package/dist/{tui-v2 → ui-core}/bootstrap/console-guard.d.ts +0 -0
  963. /package/dist/{tui-v2 → ui-core}/bootstrap/console-guard.js +0 -0
  964. /package/dist/{tui-v2 → ui-core}/bootstrap/console-suppress.d.ts +0 -0
  965. /package/dist/{tui-v2 → ui-core}/bootstrap/console-suppress.js +0 -0
  966. /package/dist/{tui-v2 → ui-core}/bootstrap/lifecycle.d.ts +0 -0
  967. /package/dist/{tui-v2 → ui-core}/bootstrap/lifecycle.js +0 -0
  968. /package/dist/{tui-v2 → ui-core}/bootstrap/overlay-ports.d.ts +0 -0
  969. /package/dist/{tui-v2/app → ui-core/commands}/command-handlers.d.ts +0 -0
  970. /package/dist/{tui-v2/app → ui-core/commands}/startup-update.d.ts +0 -0
  971. /package/dist/{tui-v2/app → ui-core/commands}/startup-update.js +0 -0
  972. /package/dist/{tui-v2 → ui-core}/composer/arrow-intent.d.ts +0 -0
  973. /package/dist/{tui-v2 → ui-core}/composer/arrow-intent.js +0 -0
  974. /package/dist/{tui-v2 → ui-core}/composer/completion.d.ts +0 -0
  975. /package/dist/{tui-v2 → ui-core}/composer/completion.js +0 -0
  976. /package/dist/{tui-v2 → ui-core}/composer/composer-action-port.d.ts +0 -0
  977. /package/dist/{tui-v2 → ui-core}/composer/composer-action-port.js +0 -0
  978. /package/dist/{tui-v2 → ui-core}/composer/composer-height.d.ts +0 -0
  979. /package/dist/{tui-v2 → ui-core}/composer/history-nav.d.ts +0 -0
  980. /package/dist/{tui-v2 → ui-core}/composer/history-nav.js +0 -0
  981. /package/dist/{tui → ui-core/composer}/input-history.d.ts +0 -0
  982. /package/dist/{tui-v2 → ui-core}/composer/newline-hint.js +0 -0
  983. /package/dist/{tui-v2 → ui-core}/composer/paste-placeholder.d.ts +0 -0
  984. /package/dist/{tui-v2 → ui-core}/composer/paste-placeholder.js +0 -0
  985. /package/dist/{tui-v2 → ui-core}/composer/prompt-history.d.ts +0 -0
  986. /package/dist/{tui-v2 → ui-core}/composer/prompt-history.js +0 -0
  987. /package/dist/{tui-v2 → ui-core}/composer/secret-buffer.d.ts +0 -0
  988. /package/dist/{tui-v2 → ui-core}/composer/secret-buffer.js +0 -0
  989. /package/dist/{tui-v2 → ui-core}/controllers/focus-controller.d.ts +0 -0
  990. /package/dist/{tui-v2 → ui-core}/controllers/focus-controller.js +0 -0
  991. /package/dist/{tui-v2 → ui-core}/controllers/interruptible-controller.d.ts +0 -0
  992. /package/dist/{tui-v2 → ui-core}/controllers/interruptible-controller.js +0 -0
  993. /package/dist/{tui-v2 → ui-core}/controllers/overlay-controller.js +0 -0
  994. /package/dist/{tui-v2 → ui-core}/controllers/selection-controller.d.ts +0 -0
  995. /package/dist/{tui-v2 → ui-core}/controllers/selection-controller.js +0 -0
  996. /package/dist/{tui-v2 → ui-core}/controllers/toast-controller.d.ts +0 -0
  997. /package/dist/{tui-v2 → ui-core}/controllers/toast-controller.js +0 -0
  998. /package/dist/{tui-v2 → ui-core}/layout/compute-layout.d.ts +0 -0
  999. /package/dist/{tui-v2 → ui-core}/layout/compute-layout.js +0 -0
  1000. /package/dist/{tui-v2 → ui-core}/motion/ease.d.ts +0 -0
  1001. /package/dist/{tui-v2 → ui-core}/motion/ease.js +0 -0
  1002. /package/dist/{tui-v2 → ui-core}/notify.d.ts +0 -0
  1003. /package/dist/{tui-v2 → ui-core}/notify.js +0 -0
  1004. /package/dist/{tui-v2/app → ui-core/plan}/plan-lifecycle.d.ts +0 -0
  1005. /package/dist/{tui-v2/app → ui-core/plan}/plan-lifecycle.js +0 -0
  1006. /package/dist/{tui-v2/bootstrap/osc52-clipboard.d.ts → ui-core/ports/clipboard-osc52.d.ts} +0 -0
  1007. /package/dist/{tui-v2/state → ui-core/react}/use-has-draft.d.ts +0 -0
  1008. /package/dist/{tui-v2/state → ui-core/react}/use-has-draft.js +0 -0
  1009. /package/dist/{tui-v2/state → ui-core/react}/use-overlay.d.ts +0 -0
  1010. /package/dist/{tui-v2/state → ui-core/react}/use-overlay.js +0 -0
  1011. /package/dist/{tui-v2/state → ui-core/react}/use-plan.d.ts +0 -0
  1012. /package/dist/{tui-v2/state → ui-core/react}/use-plan.js +0 -0
  1013. /package/dist/{tui-v2/state → ui-core/react}/use-session-state.d.ts +0 -0
  1014. /package/dist/{tui-v2/state → ui-core/react}/use-session-state.js +0 -0
  1015. /package/dist/{tui-v2/state → ui-core/react}/use-toast.d.ts +0 -0
  1016. /package/dist/{tui-v2/state → ui-core/react}/use-toast.js +0 -0
  1017. /package/dist/{tui-v2/state → ui-core/react}/use-transcript-store.js +0 -0
  1018. /package/dist/{tui-v2 → ui-core}/rendering/artifact-pager-source.d.ts +0 -0
  1019. /package/dist/{tui-v2 → ui-core}/rendering/artifact-pager-source.js +0 -0
  1020. /package/dist/{tui-v2 → ui-core}/rendering/batch-sections.d.ts +0 -0
  1021. /package/dist/{tui-v2 → ui-core}/rendering/batch-sections.js +0 -0
  1022. /package/dist/{tui-v2 → ui-core}/rendering/file-diff-view.d.ts +0 -0
  1023. /package/dist/{tui-v2 → ui-core}/rendering/file-diff-view.js +0 -0
  1024. /package/dist/{tui-v2 → ui-core}/rendering/format-help.d.ts +0 -0
  1025. /package/dist/{tui-v2 → ui-core}/rendering/format-help.js +0 -0
  1026. /package/dist/{tui-v2 → ui-core}/rendering/incremental-strip.d.ts +0 -0
  1027. /package/dist/{tui-v2 → ui-core}/rendering/incremental-strip.js +0 -0
  1028. /package/dist/{tui-v2 → ui-core}/rendering/job-tail-source.d.ts +0 -0
  1029. /package/dist/{tui-v2 → ui-core}/rendering/job-tail-source.js +0 -0
  1030. /package/dist/{tui-v2 → ui-core}/rendering/link-detector.d.ts +0 -0
  1031. /package/dist/{tui-v2 → ui-core}/rendering/link-detector.js +0 -0
  1032. /package/dist/{ui → ui-core/rendering}/markdown.d.ts +0 -0
  1033. /package/dist/{ui → ui-core/rendering}/markdown.js +0 -0
  1034. /package/dist/{tui-v2 → ui-core}/rendering/open-tool-output.d.ts +0 -0
  1035. /package/dist/{tui-v2 → ui-core}/rendering/pager-chrome.d.ts +0 -0
  1036. /package/dist/{tui-v2 → ui-core}/rendering/pager-view-policy.d.ts +0 -0
  1037. /package/dist/{tui-v2 → ui-core}/rendering/picker-filter.d.ts +0 -0
  1038. /package/dist/{tui-v2 → ui-core}/rendering/picker-filter.js +0 -0
  1039. /package/dist/{tui-v2 → ui-core}/rendering/plan-view.d.ts +0 -0
  1040. /package/dist/{tui-v2 → ui-core}/rendering/plan-view.js +0 -0
  1041. /package/dist/{tui-v2 → ui-core}/rendering/prompt-preview.d.ts +0 -0
  1042. /package/dist/{tui-v2 → ui-core}/rendering/prompt-preview.js +0 -0
  1043. /package/dist/{tui-v2 → ui-core}/rendering/sanitize-display.d.ts +0 -0
  1044. /package/dist/{tui-v2 → ui-core}/rendering/sanitize-display.js +0 -0
  1045. /package/dist/{tui-v2 → ui-core}/rendering/strip-tool-surfaces.d.ts +0 -0
  1046. /package/dist/{tui-v2 → ui-core}/rendering/strip-tool-surfaces.js +0 -0
  1047. /package/dist/{tui-v2 → ui-core}/rendering/syntax-highlight.d.ts +0 -0
  1048. /package/dist/{tui-v2 → ui-core}/rendering/syntax-highlight.js +0 -0
  1049. /package/dist/{tui → ui-core/rendering}/text-format.d.ts +0 -0
  1050. /package/dist/{tui → ui-core/rendering}/text-format.js +0 -0
  1051. /package/dist/{ui → ui-core/rendering}/text-width.d.ts +0 -0
  1052. /package/dist/{ui → ui-core/rendering}/text-width.js +0 -0
  1053. /package/dist/{tui-v2 → ui-core}/rendering/theme.d.ts +0 -0
  1054. /package/dist/{tui-v2 → ui-core}/rendering/theme.js +0 -0
  1055. /package/dist/{tui-v2 → ui-core}/rendering/thinking-tail.d.ts +0 -0
  1056. /package/dist/{tui-v2 → ui-core}/rendering/thinking-tail.js +0 -0
  1057. /package/dist/{tui-v2 → ui-core}/rendering/transcript-semantic.d.ts +0 -0
  1058. /package/dist/{tui-v2 → ui-core}/rendering/transcript-semantic.js +0 -0
  1059. /package/dist/{ui → ui-core/rendering}/wordmark.d.ts +0 -0
  1060. /package/dist/{ui → ui-core/rendering}/wordmark.js +0 -0
  1061. /package/dist/{tui-v2 → ui-core}/state/pager-search.d.ts +0 -0
  1062. /package/dist/{tui-v2 → ui-core}/state/pager-search.js +0 -0
  1063. /package/dist/{tui-v2 → ui-core}/state/semantic-document.d.ts +0 -0
  1064. /package/dist/{tui-v2 → ui-core}/state/semantic-document.js +0 -0
  1065. /package/dist/{tui-v2 → ui-core}/state/transcript-compaction.d.ts +0 -0
  1066. /package/dist/{tui-v2 → ui-core}/state/transcript-compaction.js +0 -0
  1067. /package/dist/{tui-v2 → ui-core}/state/transcript-reducer.d.ts +0 -0
  1068. /package/dist/{tui-v2 → ui-core}/state/transcript-search.d.ts +0 -0
  1069. /package/dist/{tui-v2 → ui-core}/state/transcript-search.js +0 -0
  1070. /package/dist/{tui-v2 → ui-core}/state/transcript-store.d.ts +0 -0
  1071. /package/dist/{tui-v2 → ui-core}/state/transcript-store.js +0 -0
  1072. /package/dist/{tui-v2 → ui-core}/state/transcript-struct.d.ts +0 -0
  1073. /package/dist/{tui-v2 → ui-core}/state/transcript-struct.js +0 -0
  1074. /package/dist/{tui-v2 → ui-core}/state/transcript-types.js +0 -0
package/dist/repl.js DELETED
@@ -1,1868 +0,0 @@
1
- import { clearLine, cursorTo, emitKeypressEvents, moveCursor } from "node:readline";
2
- import { stdin as input, stdout as output } from "node:process";
3
- import chalk from "chalk";
4
- import { confirm } from "@inquirer/prompts";
5
- import { runAskStream } from "./modes/ask.js";
6
- import { resolveTurnInput, shouldRunImageOcr } from "./attachments/service.js";
7
- import { runAgent, createSessionPolicy, } from "./modes/agent.js";
8
- import { attachClassicRenderer } from "./agent/classic-renderer.js";
9
- import { clearActiveProjectRoot } from "./agent/project-root.js";
10
- import { providerSwitcher, printProviderKeys, setKeyPicker, unsetKeyPicker, } from "./commands/providers.js";
11
- import { printSearchProviderKeys, useSearchProvider, } from "./commands/search-providers.js";
12
- import { getActiveProviderEndpoint, getConfig, getCustomProviders, getProviderModel, setDefaultMode, setProviderModel, setThinking, updateConfig, } from "./store/config.js";
13
- import { envValue, getProviderSecret } from "./store/keys.js";
14
- import { listSessionSummaries, upsertSession, clearAllHistory, deleteSession, getSession, } from "./store/history.js";
15
- import { beginSessionWorkspace } from "./store/session-workspace.js";
16
- import { assertProvider, defaultModels, getProviderInfoText, redactSecrets, } from "./llm/provider.js";
17
- import { getProvider, providerAuth } from "./llm/router.js";
18
- import { clearTextOnlyModels } from "./llm/tool-protocol.js";
19
- import { providerIds } from "./types.js";
20
- import { runUpdate, checkForUpdateSilent, getCurrentVersion, } from "./commands/update.js";
21
- import { renderModeSwitch, renderProviderSwitch, PROMPT, } from "./ui/banner.js";
22
- import { renderIntroCard } from "./ui/intro-card.js";
23
- import { clearThinking, createThinkingStreamParser, getLastThinking, rememberThinkingFromText, renderAllThinking, renderThinkingSummary, renderThinkingToggleMessage, } from "./ui/thinking.js";
24
- import { createMarkdownStreamWriter, renderMarkdown } from "./ui/markdown.js";
25
- import { startThinkingSpinner } from "./ui/spinner.js";
26
- import { modelSupportsThinking } from "./llm/capabilities.js";
27
- import { clearViewports, getLastViewport, getViewport, isPagerActive, listViewports, openPager, openViewportPager, toggleViewport, } from "./ui/output-pane.js";
28
- import { loadPlan, mutatePlan, deletePlan, isPlanSuccessful, } from "./store/plan.js";
29
- import { renderPlanDocument, renderPlanChecklist } from "./ui/plan-pane.js";
30
- import { safeCwd, cwdIsBroken, recoverCwd } from "./os/cwd.js";
31
- import { compactMessages, estimateMessagesTokens, } from "./agent/context-manager.js";
32
- import { isCtrlC, isCtrlO, isCtrlP, isCtrlT, isEscape } from "./ui/keys.js";
33
- import { imageAttachmentPaths } from "./ui/mentions.js";
34
- import { meaningfulCharCount, runOcr } from "./tools/ocr.js";
35
- import { jobManager } from "./tools/jobs.js";
36
- import { interactiveSessionManager } from "./interactive-session/manager.js";
37
- import { handleDraftPlanDecision, IMPLEMENT_DIRECTIVE, } from "./agent/plan-decision.js";
38
- import { readPromptLine, PROMPT_EXIT_INTENT, stripAnsi, isPrintableSequence, } from "./repl/prompt-line.js";
39
- import { slashCommands, knownModels, looksLikeSlashCommand, slashCommandLabel, } from "./repl/slash-commands.js";
40
- // Re-exported so existing imports of these names from "./repl.js" keep
41
- // working unchanged — the command catalogue, model lists, and the line
42
- // editor now live in their own modules under "./repl/".
43
- export { slashCommands, knownModels, getKnownModels, inferProviderForModel, looksLikeSlashCommand, getSlashCommandSuggestions, isKnownSlashCommand, } from "./repl/slash-commands.js";
44
- export { renderSlashCommandMenu, renderFileMentionMenu, } from "./repl/prompt-line.js";
45
- /** Reset process-global project routing and rotate/adopt classic session identity together. */
46
- export function resetClassicSessionContext(state, sessionId, workspace) {
47
- const previousSessionId = state.session.sessionId;
48
- if (!sessionId || sessionId !== previousSessionId) {
49
- void interactiveSessionManager
50
- .beginCloseOwner(previousSessionId, "conversation-teardown")
51
- .catch(() => undefined);
52
- }
53
- clearActiveProjectRoot();
54
- state.session = createSessionPolicy(sessionId);
55
- void interactiveSessionManager.activateOwner(state.session.sessionId).catch(() => undefined);
56
- // Isolate scratch + tool outputs per session (restore on history resume).
57
- beginSessionWorkspace(workspace?.folderName
58
- ? { folderName: workspace.folderName, code: workspace.code }
59
- : undefined);
60
- }
61
- function splitCommand(line) {
62
- return (line
63
- .match(/(?:[^\s"]+|"[^"]*")+/g)
64
- ?.map((part) => part.replace(/^"|"$/g, "")) ?? []);
65
- }
66
- function isAbortLikeError(error) {
67
- if (!error)
68
- return false;
69
- if (typeof error === "object") {
70
- const err = error;
71
- if (err.name === "AbortError")
72
- return true;
73
- if (err.code === "ABORT_ERR")
74
- return true;
75
- if (typeof err.message === "string" && /abort/i.test(err.message))
76
- return true;
77
- }
78
- return false;
79
- }
80
- async function buildImageOcrGrounding(line, baseDir) {
81
- const paths = imageAttachmentPaths(line, baseDir);
82
- if (paths.length === 0)
83
- return "";
84
- const sections = [];
85
- for (const path of paths) {
86
- try {
87
- const result = await runOcr({
88
- path,
89
- lang: "eng",
90
- psmCandidates: [6, 3, 11],
91
- timeoutMs: 60_000,
92
- });
93
- const text = result.text.trim();
94
- if (result.ok && result.reliable && meaningfulCharCount(text) >= 8) {
95
- sections.push(`----- OCR of ${path} -----\n${text}\n----- end OCR -----`);
96
- }
97
- }
98
- catch {
99
- // tesseract missing or failed — skip silently; vision bytes still sent.
100
- }
101
- }
102
- if (sections.length === 0)
103
- return "";
104
- return ('<image-ocr note="Text extracted locally from the attached image(s) via OCR, in case the model cannot see the image bytes directly. Use it to ground your answer; if you CAN see the image, prefer your own visual reading and use this only to confirm text.">\n' +
105
- sections.join("\n\n") +
106
- "\n</image-ocr>");
107
- }
108
- // Abort controller for streaming cancellation
109
- let currentAbortController = null;
110
- class AbortRunError extends Error {
111
- constructor() {
112
- super("Aborted.");
113
- this.name = "AbortRunError";
114
- }
115
- }
116
- // Build a concise, width-bounded spinner label for ask-mode research so the
117
- // user sees what's being searched/fetched without the line overflowing.
118
- function askResearchLabel(name, argsDisplay) {
119
- const verb = name === "web.search"
120
- ? "searching the web"
121
- : name === "web.fetch"
122
- ? "fetching"
123
- : name === "tool.batch"
124
- ? "researching"
125
- : name === "fs.read"
126
- ? "reading"
127
- : name === "fs.list"
128
- ? "listing"
129
- : name === "fs.search"
130
- ? "searching files"
131
- : name;
132
- const detail = argsDisplay.trim().replace(/\s+/g, " ");
133
- const full = detail ? `${verb}: ${detail}` : verb;
134
- // Leave room for the spinner frame, elapsed time, and padding so the head
135
- // line never wraps. Columns can be undefined on non-TTY; default to 80.
136
- const cols = Math.max(40, process.stdout.columns ?? 80);
137
- const max = Math.max(20, cols - 18);
138
- return full.length > max ? `${full.slice(0, max - 1)}…` : full;
139
- }
140
- // Stream a response while hiding <think> blocks and handling ESC abort
141
- async function streamWithAbort(run, signal) {
142
- let sawToken = false;
143
- const spinner = startThinkingSpinner("waiting for model", signal);
144
- // Lets the run function surface progress (e.g. ask-mode research activity)
145
- // on the spinner's label line. Ignored once visible tokens have started
146
- // since the spinner is stopped at that point.
147
- const setStatus = (label) => {
148
- if (!sawToken && label)
149
- spinner.setLabel(label);
150
- };
151
- const markdown = createMarkdownStreamWriter((chunk) => process.stdout.write(chunk));
152
- const parser = createThinkingStreamParser((text) => {
153
- // Visible content arriving — drop the spinner so output isn't stomped on.
154
- spinner.stop();
155
- markdown.push(text);
156
- }, (reasoning) => {
157
- // Reasoning tokens are hidden by default; show progress so users see
158
- // something is happening even when the model spends a minute thinking.
159
- spinner.setLabel("thinking");
160
- spinner.pushPreview(reasoning);
161
- const approx = reasoning.split(/\s+/).filter(Boolean).length;
162
- if (approx > 0)
163
- spinner.bumpReasoning(approx);
164
- });
165
- const onToken = (token) => {
166
- if (!sawToken) {
167
- // First raw token from the provider — still hold the spinner if it
168
- // turns out to be a reasoning token; the parser's callbacks above
169
- // decide which label to show.
170
- sawToken = true;
171
- }
172
- parser.push(token);
173
- };
174
- try {
175
- const raw = await run(signal, onToken, setStatus);
176
- spinner.stop();
177
- parser.finish();
178
- const result = rememberThinkingFromText(raw);
179
- if (sawToken) {
180
- markdown.finish();
181
- }
182
- else if (result.visible) {
183
- process.stdout.write(renderMarkdown(result.visible));
184
- }
185
- if (result.hasThinking) {
186
- const prefix = result.visible && !result.visible.endsWith("\n") ? "\n" : "";
187
- process.stdout.write(`${prefix}${renderThinkingSummary(result.thinkContent)}\n`);
188
- }
189
- return result.visible;
190
- }
191
- catch (err) {
192
- const result = parser.finish();
193
- if (sawToken)
194
- markdown.finish();
195
- if (signal.aborted) {
196
- spinner.stop();
197
- process.stdout.write(chalk.yellow("\n ⏹ Aborted.\n"));
198
- return result.visible;
199
- }
200
- throw err;
201
- }
202
- finally {
203
- // Belt and braces: spinner already self-stops on abort, but make sure
204
- // any other exit path (success, network error) clears it too.
205
- spinner.stop();
206
- }
207
- }
208
- async function withAbortableInput(run) {
209
- const ac = new AbortController();
210
- const abortFromRawData = (chunk) => {
211
- const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
212
- if (text.includes("\x03"))
213
- ac.abort();
214
- };
215
- currentAbortController = ac;
216
- if (input.isTTY)
217
- input.setRawMode(true);
218
- input.resume();
219
- // Raw Ctrl+C fallback for terminals whose keypress normalization is
220
- // unreliable. Escape is handled by the REPL keypress double-press gate.
221
- input.on("data", abortFromRawData);
222
- try {
223
- return await run(ac.signal);
224
- }
225
- catch (error) {
226
- if (ac.signal.aborted ||
227
- (error instanceof Error && error.name === "AbortError")) {
228
- throw new AbortRunError();
229
- }
230
- throw error;
231
- }
232
- finally {
233
- input.off("data", abortFromRawData);
234
- currentAbortController = null;
235
- if (input.isTTY)
236
- input.setRawMode(true);
237
- input.resume();
238
- }
239
- }
240
- function help() {
241
- const maxCmd = Math.max(...slashCommands.map((command) => slashCommandLabel(command).length));
242
- const lines = slashCommands
243
- .map((command) => {
244
- const label = slashCommandLabel(command).padEnd(maxCmd + 2);
245
- return ` ${chalk.cyan(label)}${chalk.dim(command.description)}`;
246
- })
247
- .join("\n");
248
- return (lines +
249
- chalk.dim("\n\n ESC twice cancels turn + jobs │ Ctrl+C clears input (twice to exit) │ Ctrl+T toggle thinking │ Ctrl+O opens tool output pager (q to close)"));
250
- }
251
- async function pickInline(options) {
252
- const { items, header, pageSize = 15 } = options;
253
- if (items.length === 0)
254
- return undefined;
255
- return new Promise((resolve) => {
256
- let filter = "";
257
- let filterCursor = 0;
258
- let selectedIndex = 0;
259
- let renderedLines = 0;
260
- const promptLabel = chalk.dim(" filter: ");
261
- const promptLabelLen = stripAnsi(promptLabel).length;
262
- const getFiltered = () => {
263
- const needle = filter.trim().toLowerCase();
264
- if (!needle)
265
- return items;
266
- return items.filter((item) => item.filterText.toLowerCase().includes(needle));
267
- };
268
- const renderMenu = () => {
269
- const filtered = getFiltered();
270
- if (selectedIndex >= filtered.length)
271
- selectedIndex = Math.max(0, filtered.length - 1);
272
- const cols = process.stdout.columns || 80;
273
- // Scroll the visible window so the selected item is always shown
274
- let start = 0;
275
- if (filtered.length > pageSize) {
276
- start = Math.max(0, selectedIndex - Math.floor(pageSize / 2));
277
- start = Math.min(start, filtered.length - pageSize);
278
- }
279
- const visible = filtered.slice(start, start + pageSize);
280
- const lines = [];
281
- for (let i = 0; i < visible.length; i++) {
282
- const marker = start + i === selectedIndex ? chalk.magenta("›") : " ";
283
- let full = ` ${marker} ${visible[i].label}`;
284
- const stripped = stripAnsi(full);
285
- if (stripped.length > cols - 1) {
286
- full = full.slice(0, cols - 1) + chalk.dim("…");
287
- }
288
- lines.push(full);
289
- }
290
- if (filtered.length > pageSize) {
291
- const prefix = start > 0 ? `… ${start} above · ` : "";
292
- const suffix = start + pageSize < filtered.length
293
- ? ` · ${filtered.length - start - pageSize} below`
294
- : "";
295
- lines.push(chalk.dim(` ${prefix}${visible.length} shown${suffix}`));
296
- }
297
- if (filtered.length === 0) {
298
- lines.push(chalk.dim(" no matches"));
299
- }
300
- // Clear old menu
301
- const toClear = Math.max(renderedLines, lines.length + 1); // +1 for filter line
302
- cursorTo(output, 0);
303
- clearLine(output, 0);
304
- output.write(`${promptLabel}${filter}`);
305
- if (toClear > 0) {
306
- // Reserve space
307
- if (renderedLines === 0 && lines.length > 0) {
308
- output.write("\n".repeat(lines.length));
309
- moveCursor(output, 0, -lines.length);
310
- }
311
- for (let i = 0; i < toClear; i++) {
312
- output.write("\x1b[B");
313
- cursorTo(output, 0);
314
- clearLine(output, 0);
315
- if (i < lines.length)
316
- output.write(lines[i]);
317
- }
318
- moveCursor(output, 0, -toClear);
319
- }
320
- cursorTo(output, promptLabelLen + filterCursor);
321
- renderedLines = lines.length;
322
- };
323
- const cleanup = () => {
324
- input.off("keypress", handleKeypress);
325
- // Clear menu from screen
326
- cursorTo(output, 0);
327
- clearLine(output, 0);
328
- for (let i = 0; i < renderedLines; i++) {
329
- output.write("\x1b[B");
330
- cursorTo(output, 0);
331
- clearLine(output, 0);
332
- }
333
- if (renderedLines > 0)
334
- moveCursor(output, 0, -renderedLines);
335
- renderedLines = 0;
336
- // Restore terminal state to what readPromptLine expects:
337
- // raw mode off, input paused.
338
- input.pause();
339
- if (input.isTTY)
340
- input.setRawMode(false);
341
- output.write("\n");
342
- };
343
- function handleKeypress(sequence, key) {
344
- if (isPagerActive())
345
- return;
346
- if (isCtrlC(key) || isEscape(key)) {
347
- cleanup();
348
- resolve(undefined);
349
- return;
350
- }
351
- if (key.name === "return" || key.name === "enter") {
352
- const filtered = getFiltered();
353
- const picked = filtered[selectedIndex];
354
- cleanup();
355
- resolve(picked?.value);
356
- return;
357
- }
358
- if (key.name === "tab") {
359
- const filtered = getFiltered();
360
- const picked = filtered[selectedIndex];
361
- if (picked) {
362
- filter = picked.filterText;
363
- filterCursor = filter.length;
364
- selectedIndex = 0;
365
- renderMenu();
366
- }
367
- return;
368
- }
369
- if (key.name === "up") {
370
- const filtered = getFiltered();
371
- if (filtered.length > 0) {
372
- selectedIndex =
373
- (selectedIndex - 1 + filtered.length) % filtered.length;
374
- renderMenu();
375
- }
376
- return;
377
- }
378
- if (key.name === "down") {
379
- const filtered = getFiltered();
380
- if (filtered.length > 0) {
381
- selectedIndex = (selectedIndex + 1) % filtered.length;
382
- renderMenu();
383
- }
384
- return;
385
- }
386
- if (key.name === "backspace") {
387
- if (filterCursor > 0) {
388
- filter =
389
- filter.slice(0, filterCursor - 1) + filter.slice(filterCursor);
390
- filterCursor -= 1;
391
- selectedIndex = 0;
392
- renderMenu();
393
- }
394
- return;
395
- }
396
- if (key.name === "delete") {
397
- if (filterCursor < filter.length) {
398
- filter =
399
- filter.slice(0, filterCursor) + filter.slice(filterCursor + 1);
400
- selectedIndex = 0;
401
- renderMenu();
402
- }
403
- return;
404
- }
405
- if (key.name === "left") {
406
- if (filterCursor > 0) {
407
- filterCursor -= 1;
408
- renderMenu();
409
- }
410
- return;
411
- }
412
- if (key.name === "right") {
413
- if (filterCursor < filter.length) {
414
- filterCursor += 1;
415
- renderMenu();
416
- }
417
- return;
418
- }
419
- if (isPrintableSequence(sequence) && !key.ctrl && !key.meta) {
420
- filter =
421
- filter.slice(0, filterCursor) + sequence + filter.slice(filterCursor);
422
- filterCursor += sequence.length;
423
- selectedIndex = 0;
424
- renderMenu();
425
- }
426
- }
427
- if (header) {
428
- console.log(header);
429
- }
430
- if (input.isTTY)
431
- input.setRawMode(true);
432
- input.resume();
433
- input.on("keypress", handleKeypress);
434
- renderMenu();
435
- });
436
- }
437
- async function pickModelInteractively(provider, currentModel) {
438
- let models = [];
439
- let fetchedDynamically = false;
440
- const def = defaultModels[provider] ?? "";
441
- const providerImpl = getProvider(provider);
442
- if (providerImpl.listModels) {
443
- try {
444
- const auth = await providerAuth(provider);
445
- models = await providerImpl.listModels(auth);
446
- fetchedDynamically = models.length > 0;
447
- }
448
- catch (error) {
449
- console.warn(chalk.yellow(` Warning: Could not fetch models from ${provider}: ${error instanceof Error ? error.message : String(error)}`));
450
- }
451
- }
452
- if (models.length === 0) {
453
- models = knownModels[provider] ?? [];
454
- if (models.length > 0 && providerImpl.listModels) {
455
- console.warn(chalk.yellow(` Warning: ${provider} model list could not be refreshed; showing known models.`));
456
- }
457
- }
458
- if (models.length === 0) {
459
- console.log(chalk.dim(" No known models for this provider. Type /model <name> to set manually."));
460
- return undefined;
461
- }
462
- const header = fetchedDynamically
463
- ? chalk.dim(` ↑↓:navigate · type:filter · tab:fill · enter:select · esc:cancel`)
464
- : chalk.dim(` ↑↓:navigate · type:filter · tab:fill · enter:select · esc:cancel`);
465
- const items = models.map((model, index) => {
466
- const tags = [];
467
- if (model === currentModel)
468
- tags.push(chalk.green("active"));
469
- if (model === def)
470
- tags.push(chalk.yellow("default"));
471
- const suffix = tags.length > 0 ? ` ${chalk.dim(tags.join(" · "))}` : "";
472
- const label = `${chalk.dim(`${(index + 1).toString().padStart(2)}.`)} ${model}${suffix}`;
473
- return { label, value: model, filterText: model };
474
- });
475
- return pickInline({
476
- items,
477
- header,
478
- pageSize: Math.min(15, models.length),
479
- });
480
- }
481
- async function showModelList(provider, currentModel) {
482
- let models = [];
483
- let fetchedDynamically = false;
484
- const def = defaultModels[provider] ?? "";
485
- const providerImpl = getProvider(provider);
486
- if (providerImpl.listModels) {
487
- try {
488
- const auth = await providerAuth(provider);
489
- models = await providerImpl.listModels(auth);
490
- fetchedDynamically = models.length > 0;
491
- }
492
- catch {
493
- // Silently fall back to empty array on error
494
- }
495
- }
496
- if (models.length === 0) {
497
- models = knownModels[provider] ?? [];
498
- if (models.length > 0 && providerImpl.listModels) {
499
- console.warn(chalk.yellow(` Warning: ${provider} model list could not be refreshed; showing known models.`));
500
- }
501
- }
502
- if (models.length === 0) {
503
- console.log(chalk.dim(" No known models for this provider. Type /model <name> to set manually."));
504
- return;
505
- }
506
- const sourceSuffix = fetchedDynamically
507
- ? chalk.dim(" (fetched live)")
508
- : chalk.dim(" (known models)");
509
- console.log(chalk.dim(` Available models for ${chalk.cyan(provider)}:${sourceSuffix}`));
510
- models.forEach((m, i) => {
511
- const tags = [];
512
- if (m === currentModel)
513
- tags.push("active");
514
- if (m === def)
515
- tags.push("default");
516
- const tag = tags.length > 0 ? chalk.dim(` (${tags.join(" · ")})`) : "";
517
- console.log(` ${chalk.dim(`${i + 1}.`)} ${chalk.white(m)}${tag}`);
518
- });
519
- console.log(chalk.dim(" Use /model <name> or /model <#> to select."));
520
- }
521
- async function showAllProviderModels(filter) {
522
- const custom = getCustomProviders().map((def) => def.id);
523
- const candidates = [...providerIds, ...custom];
524
- const configured = [];
525
- for (const provider of candidates) {
526
- if (provider === "ollama" || provider === "free") {
527
- configured.push(provider);
528
- continue;
529
- }
530
- const hasKey = Boolean(envValue(provider)) ||
531
- Boolean((await getProviderSecret(provider)).value);
532
- if (!hasKey)
533
- continue;
534
- if (provider === "modal" && !getActiveProviderEndpoint("modal"))
535
- continue;
536
- configured.push(provider);
537
- }
538
- if (configured.length === 0) {
539
- console.log(chalk.dim(" No providers configured. Add a key with: clai set <provider>"));
540
- return;
541
- }
542
- const needle = filter.trim().toLowerCase().replace(/\s+/g, "/");
543
- const results = await Promise.all(configured.map(async (provider) => {
544
- const providerImpl = getProvider(provider);
545
- let models = [];
546
- let live = false;
547
- if (providerImpl.listModels) {
548
- try {
549
- models = await providerImpl.listModels(await providerAuth(provider));
550
- live = models.length > 0;
551
- }
552
- catch {
553
- models = [];
554
- }
555
- }
556
- if (models.length === 0)
557
- models = knownModels[provider] ?? [];
558
- return { provider, models, live };
559
- }));
560
- let total = 0;
561
- const lines = [];
562
- for (const { provider, models, live } of results) {
563
- const matching = needle
564
- ? models.filter((model) => `${provider}/${model}`.toLowerCase().includes(needle))
565
- : models;
566
- if (matching.length === 0)
567
- continue;
568
- lines.push(` ${chalk.cyan(provider)}${chalk.dim(live ? " · live" : " · known")}`);
569
- for (const model of matching) {
570
- total += 1;
571
- lines.push(` ${chalk.white(`${provider}/${model}`)}`);
572
- }
573
- }
574
- if (total === 0) {
575
- console.log(chalk.dim(` No model matches "${filter.trim()}".`));
576
- return;
577
- }
578
- console.log(chalk.dim(` ${total} models across ${configured.length} configured provider${configured.length === 1 ? "" : "s"}:`));
579
- for (const line of lines)
580
- console.log(line);
581
- console.log(chalk.dim(" Use /provider <name> then /model <name> to switch."));
582
- }
583
- function maybePrintThinkingTip(provider, model) {
584
- if (getConfig().thinking.enabled)
585
- return;
586
- if (!modelSupportsThinking(provider, model))
587
- return;
588
- console.log(chalk.dim(" 💡 ") +
589
- chalk.dim(`${model} supports reasoning. Run `) +
590
- chalk.cyan("/effort") +
591
- chalk.dim(" to pick an effort level or ") +
592
- chalk.cyan("/effort high") +
593
- chalk.dim(" to enable directly."));
594
- }
595
- async function offerAgentSwitch(info, state, requestModel, images) {
596
- if (info.preamble) {
597
- process.stdout.write(`${renderMarkdown(info.preamble)}\n`);
598
- }
599
- const toolsNote = info.tools.length > 0 ? ` (${info.tools.join(", ")})` : "";
600
- console.log(chalk.yellow(` This needs to take actions${toolsNote}, which ask mode can't do — it's read-only.`));
601
- // inquirer expects cooked mode; mirror the slash-command path so the
602
- // prompt reads cleanly, then restore raw mode for the next run/prompt.
603
- input.pause();
604
- if (input.isTTY)
605
- input.setRawMode(false);
606
- let switchNow = false;
607
- try {
608
- switchNow = await confirm({
609
- message: chalk.yellow("switch to agent mode and run it?"),
610
- default: true,
611
- });
612
- }
613
- catch {
614
- // Treat an aborted/failed prompt as "no".
615
- switchNow = false;
616
- }
617
- finally {
618
- if (input.isTTY)
619
- input.setRawMode(true);
620
- input.resume();
621
- }
622
- if (!switchNow) {
623
- console.log(chalk.dim(" Staying in ask mode."));
624
- return "Staying in ask mode; the task wasn't run. Use /agent to run tasks that take actions.";
625
- }
626
- state.mode = "agent";
627
- setDefaultMode("agent");
628
- console.log(renderModeSwitch("agent"));
629
- const classicRenderer = attachClassicRenderer();
630
- return withAbortableInput(async (signal) => runAgent(info.prompt, {
631
- provider: state.provider,
632
- model: requestModel,
633
- history: state.messages,
634
- signal,
635
- session: state.session,
636
- images,
637
- onEvent: classicRenderer.onEvent,
638
- }));
639
- }
640
- async function persistSession(state, name) {
641
- const id = state.historyId ?? state.session.sessionId;
642
- const record = await upsertSession(id, state.messages, name);
643
- state.historyId = record.id;
644
- }
645
- async function handleSlash(line, state) {
646
- const [command, ...args] = splitCommand(line);
647
- switch (command) {
648
- case "/ask":
649
- state.mode = "ask";
650
- setDefaultMode("ask");
651
- console.log(renderModeSwitch("ask"));
652
- return true;
653
- case "/agent":
654
- state.mode = "agent";
655
- setDefaultMode("agent");
656
- console.log(renderModeSwitch("agent"));
657
- return true;
658
- case "/model": {
659
- const arg = args.join(" ").trim();
660
- if (!arg) {
661
- // No arg → interactive picker (up/down, Enter to select)
662
- const picked = await pickModelInteractively(state.provider, state.model);
663
- if (!picked) {
664
- console.log(chalk.dim(" model unchanged"));
665
- return true;
666
- }
667
- state.model = picked;
668
- setProviderModel(state.provider, picked);
669
- // Sticky text-only from a prior tools-unsupported 400 should not
670
- // permanently disable native tools after the user switches models.
671
- clearTextOnlyModels();
672
- console.log(renderProviderSwitch(state.provider, picked));
673
- maybePrintThinkingTip(state.provider, picked);
674
- return true;
675
- }
676
- if (arg === "list" || arg === "ls") {
677
- await showModelList(state.provider, state.model);
678
- return true;
679
- }
680
- // Numeric → pick from known list
681
- const num = parseInt(arg, 10);
682
- const models = knownModels[state.provider] ?? [];
683
- if (!isNaN(num) && num >= 1 && num <= models.length) {
684
- const picked = models[num - 1];
685
- state.model = picked;
686
- setProviderModel(state.provider, picked);
687
- clearTextOnlyModels();
688
- console.log(renderProviderSwitch(state.provider, picked));
689
- maybePrintThinkingTip(state.provider, picked);
690
- }
691
- else {
692
- // Name → set directly
693
- state.model = arg;
694
- setProviderModel(state.provider, arg);
695
- clearTextOnlyModels();
696
- console.log(renderProviderSwitch(state.provider, arg));
697
- maybePrintThinkingTip(state.provider, arg);
698
- }
699
- return true;
700
- }
701
- case "/models": {
702
- await showAllProviderModels(args.join(" ").trim());
703
- return true;
704
- }
705
- case "/provider":
706
- case "/use": {
707
- await providerSwitcher(args[0]);
708
- const config = getConfig();
709
- state.provider = config.defaultProvider;
710
- state.model = getProviderModel(state.provider);
711
- clearTextOnlyModels();
712
- console.log(renderProviderSwitch(state.provider, state.model));
713
- maybePrintThinkingTip(state.provider, state.model);
714
- return true;
715
- }
716
- case "/set": {
717
- await setKeyPicker(args[0], args[1]);
718
- return true;
719
- }
720
- case "/unset": {
721
- await unsetKeyPicker(args[0]);
722
- return true;
723
- }
724
- case "/keys":
725
- await printProviderKeys();
726
- return true;
727
- case "/info": {
728
- const providerVal = args.join(" ").trim().toLowerCase();
729
- let targetProvider = state.provider;
730
- if (providerVal) {
731
- try {
732
- targetProvider = assertProvider(providerVal);
733
- }
734
- catch {
735
- console.log(chalk.dim(` unknown provider: ${providerVal}`));
736
- return true;
737
- }
738
- }
739
- const infoText = getProviderInfoText(targetProvider);
740
- console.log(infoText);
741
- return true;
742
- }
743
- case "/search":
744
- case "/search-provider":
745
- if (!args[0] || args[0] === "list" || args[0] === "ls") {
746
- await printSearchProviderKeys();
747
- }
748
- else {
749
- await useSearchProvider(args[0]);
750
- }
751
- return true;
752
- case "/effort":
753
- case "/reasoning": {
754
- const arg = (args[0] ?? "").toLowerCase().trim();
755
- const current = getConfig().thinking;
756
- const supported = modelSupportsThinking(state.provider, state.model);
757
- const allEfforts = [
758
- { value: "off", label: "off", desc: "disable thinking entirely" },
759
- { value: "none", label: "none", desc: "no reasoning tokens (fastest)" },
760
- { value: "minimal", label: "minimal", desc: "bare minimum reasoning" },
761
- { value: "low", label: "low", desc: "modest reasoning, optimized for speed" },
762
- { value: "medium", label: "medium", desc: "balanced quality and latency (default)" },
763
- { value: "high", label: "high", desc: "deep reasoning for complex tasks" },
764
- { value: "xhigh", label: "xhigh", desc: "maximum reasoning depth (highest latency)" },
765
- { value: "max", label: "max", desc: "highest supported reasoning depth for the model" },
766
- ];
767
- if (!arg) {
768
- // Show current status
769
- const status = current.enabled ? chalk.green("on") : chalk.dim("off");
770
- const support = supported
771
- ? chalk.green("supported")
772
- : chalk.yellow("not advertised by this model");
773
- console.log(chalk.dim(" thinking: ") +
774
- status +
775
- chalk.dim(" effort: ") +
776
- chalk.cyan(current.effort) +
777
- chalk.dim(" · ") +
778
- support);
779
- // Interactive picker for effort levels
780
- const items = allEfforts.map((e) => {
781
- const isActive = (e.value === "off" && !current.enabled) ||
782
- (e.value !== "off" && current.enabled && current.effort === e.value);
783
- const activeTag = isActive ? chalk.green(" (active)") : "";
784
- const label = ` ${chalk.cyan(e.label.padEnd(8))} ${chalk.dim(e.desc)}${activeTag}`;
785
- return { label, value: e.value, filterText: e.label };
786
- });
787
- const picked = await pickInline({
788
- items,
789
- header: chalk.dim(" ↑↓:navigate · enter:select · esc:cancel"),
790
- pageSize: allEfforts.length,
791
- });
792
- if (!picked) {
793
- console.log(chalk.dim(" effort unchanged"));
794
- return true;
795
- }
796
- if (picked === "off") {
797
- setThinking({ enabled: false });
798
- console.log(chalk.dim(` thinking: ${chalk.dim("off")}`));
799
- }
800
- else {
801
- setThinking({ enabled: true, effort: picked });
802
- console.log(chalk.dim(` thinking: ${chalk.green("on")} effort: ${chalk.cyan(picked)}`));
803
- if (!supported) {
804
- console.log(chalk.yellow(" note: current model may ignore the thinking flag."));
805
- }
806
- }
807
- return true;
808
- }
809
- if (arg === "on" || arg === "enable" || arg === "true") {
810
- setThinking({ enabled: true });
811
- console.log(chalk.dim(` thinking: ${chalk.green("on")} (effort=${getConfig().thinking.effort})`));
812
- if (!supported) {
813
- console.log(chalk.yellow(" note: current model may ignore the thinking flag."));
814
- }
815
- return true;
816
- }
817
- if (arg === "off" || arg === "disable" || arg === "false" || arg === "none") {
818
- setThinking({ enabled: false });
819
- console.log(chalk.dim(` thinking: ${chalk.dim("off")}`));
820
- return true;
821
- }
822
- const validEfforts = ["minimal", "low", "medium", "high", "xhigh", "max"];
823
- if (validEfforts.includes(arg)) {
824
- setThinking({ enabled: true, effort: arg });
825
- console.log(chalk.dim(` thinking: ${chalk.green("on")} effort: ${chalk.cyan(arg)}`));
826
- if (!supported) {
827
- console.log(chalk.yellow(" note: current model may ignore the thinking flag."));
828
- }
829
- return true;
830
- }
831
- console.log(chalk.dim(" usage: /effort on|off|none|minimal|low|medium|high|xhigh|max"));
832
- return true;
833
- }
834
- case "/clear":
835
- state.messages.length = 0;
836
- state.resumedMessageCount = 0;
837
- state.session.planApproved.value = false;
838
- console.log(chalk.dim(" context cleared"));
839
- return true;
840
- case "/new": {
841
- // Save the current session if it has new messages, then start fresh
842
- if (state.messages.length > state.resumedMessageCount) {
843
- if (!getConfig().privateMode) {
844
- await persistSession(state);
845
- console.log(chalk.dim(" current session saved"));
846
- }
847
- }
848
- resetClassicSessionContext(state);
849
- state.messages.length = 0;
850
- state.resumedMessageCount = 0;
851
- state.historyId = undefined;
852
- console.log(chalk.dim(" ✦ fresh session started"));
853
- return true;
854
- }
855
- case "/history": {
856
- if (args[0] && ["delete", "remove", "rm", "del"].includes(args[0].toLowerCase())) {
857
- const targetId = args[1]?.trim() ?? args.slice(1).join(" ").trim();
858
- if (!targetId) {
859
- console.log(chalk.dim(" usage: /history delete <session-id>"));
860
- return true;
861
- }
862
- const result = await deleteSession(targetId);
863
- console.log(result.deleted ? chalk.green(` deleted ${targetId}`) : chalk.yellow(` ${result.detail}`));
864
- return true;
865
- }
866
- const sessions = await listSessionSummaries(50, { recovery: "background" });
867
- if (sessions.length === 0) {
868
- console.log(chalk.dim(" no saved sessions"));
869
- return true;
870
- }
871
- const sessionLabel = (s) => s.name?.trim() || s.id;
872
- const items = sessions.map((s) => {
873
- const name = sessionLabel(s);
874
- const date = chalk.dim(s.createdAt.replace("T", " ").slice(0, 19));
875
- const msgs = chalk.dim(`(${s.messageCount} msgs)`);
876
- const label = `${date} ${chalk.white(name)} ${msgs}`;
877
- return { label, value: s.id, filterText: `${name} ${s.createdAt}` };
878
- });
879
- const selectedId = await pickInline({
880
- items,
881
- header: chalk.dim(` ↑↓:navigate · type:filter · enter:resume · esc:cancel`),
882
- pageSize: Math.min(15, items.length),
883
- });
884
- if (!selectedId) {
885
- console.log(chalk.dim(" cancelled"));
886
- return true;
887
- }
888
- clearActiveProjectRoot();
889
- // Load the selected session
890
- const session = await getSession(selectedId);
891
- if (!session) {
892
- console.log(chalk.red(" session not found"));
893
- return true;
894
- }
895
- // Save current session first if it has new messages
896
- if (state.messages.length > state.resumedMessageCount) {
897
- if (!getConfig().privateMode) {
898
- await persistSession(state);
899
- }
900
- }
901
- resetClassicSessionContext(state, session.id, {
902
- folderName: session.workspaceFolder,
903
- code: session.workspaceCode,
904
- });
905
- // Replay only a recent visual tail; the full path-backed model history is
906
- // installed below for an explicit continuation.
907
- console.log(chalk.dim(`\n ── resuming session ──\n`));
908
- const displayMessages = session.messages
909
- .filter((message) => message.role === "user" || message.role === "assistant")
910
- .slice(-120);
911
- const omittedDisplay = session.messages.filter((message) => message.role === "user" || message.role === "assistant").length - displayMessages.length;
912
- if (omittedDisplay > 0) {
913
- console.log(chalk.dim(` … ${omittedDisplay} older messages omitted from initial display …\n`));
914
- }
915
- for (const msg of displayMessages) {
916
- if (msg.role === "user") {
917
- console.log(`${PROMPT}${chalk.white(msg.content)}`);
918
- }
919
- else if (msg.role === "assistant") {
920
- process.stdout.write(renderMarkdown(msg.content));
921
- process.stdout.write("\n");
922
- }
923
- }
924
- console.log(chalk.dim(` ── end of history · continue below ──\n`));
925
- // Load into state so the user can continue. Adopt the resumed record's
926
- // id so continuing the conversation updates that same row instead of
927
- // minting a new, unnamed duplicate on the next save/exit.
928
- state.messages.splice(0, state.messages.length, ...session.messages);
929
- state.resumedMessageCount = session.messages.length;
930
- state.historyId = session.id;
931
- return true;
932
- }
933
- case "/save": {
934
- const name = args.join(" ") || undefined;
935
- if (state.historyId) {
936
- await upsertSession(state.historyId, state.messages, name);
937
- console.log(chalk.dim(` saved session ${state.historyId}`));
938
- return true;
939
- }
940
- const record = await upsertSession(state.session.sessionId, state.messages, name);
941
- state.historyId = record.id;
942
- console.log(chalk.dim(` saved session ${record.id}`));
943
- return true;
944
- }
945
- case "/reset": {
946
- const result = await clearAllHistory();
947
- console.log(chalk.dim(` all history cleared (${result.detail || "ok"})`));
948
- return true;
949
- }
950
- case "/cwd": {
951
- const dir = args.join(" ");
952
- if (!dir) {
953
- if (cwdIsBroken()) {
954
- const recovered = recoverCwd();
955
- console.log(chalk.yellow(` ⚠ the previous working directory no longer exists — moved to ${recovered}`));
956
- }
957
- else {
958
- console.log(chalk.dim(` ${safeCwd()}`));
959
- }
960
- }
961
- else {
962
- try {
963
- process.chdir(dir);
964
- }
965
- catch (error) {
966
- console.log(chalk.red(` ✗ cannot change to ${dir}: ${error instanceof Error ? error.message : String(error)}`));
967
- return true;
968
- }
969
- const config = getConfig();
970
- updateConfig({
971
- sandboxRoots: Array.from(new Set([...config.sandboxRoots, safeCwd()])),
972
- });
973
- console.log(chalk.dim(` cwd → ${safeCwd()}`));
974
- }
975
- return true;
976
- }
977
- case "/allow": {
978
- const tool = args[0];
979
- if (!tool) {
980
- console.log(chalk.dim("usage: /allow <tool>|list"));
981
- return true;
982
- }
983
- if (tool === "list" || tool === "ls") {
984
- if (state.session.allow.size === 0) {
985
- console.log(chalk.dim(" no session allows"));
986
- }
987
- else {
988
- for (const allowed of state.session.allow) {
989
- console.log(chalk.dim(` ✓ ${allowed}`));
990
- }
991
- }
992
- return true;
993
- }
994
- state.session.allow.add(tool);
995
- console.log(chalk.dim(` allowed ${tool} for this session only ✓`));
996
- return true;
997
- }
998
- case "/disallow": {
999
- const tool = args[0];
1000
- if (!tool) {
1001
- console.log(chalk.dim("usage: /disallow <tool>"));
1002
- return true;
1003
- }
1004
- if (state.session.allow.delete(tool)) {
1005
- console.log(chalk.dim(` revoked ${tool} ✓`));
1006
- }
1007
- else {
1008
- console.log(chalk.dim(` ${tool} was not in the session allow list`));
1009
- }
1010
- return true;
1011
- }
1012
- case "/context": {
1013
- const tokens = estimateMessagesTokens(state.messages);
1014
- console.log(chalk.dim(` ${state.messages.length} message(s), ~${tokens.toLocaleString()} tokens estimated`));
1015
- return true;
1016
- }
1017
- case "/plan": {
1018
- const sub = (args[0] ?? "").toLowerCase();
1019
- if (!sub || sub === "mode" || sub === "on" || sub === "enter") {
1020
- state.mode = "plan";
1021
- setDefaultMode("plan");
1022
- console.log(renderModeSwitch("plan"));
1023
- console.log(chalk.dim(" plan mode on — describe the multi-step task you want to plan.\n"));
1024
- return true;
1025
- }
1026
- if (sub === "off" || sub === "agent") {
1027
- state.mode = "agent";
1028
- setDefaultMode("agent");
1029
- console.log(renderModeSwitch("agent"));
1030
- return true;
1031
- }
1032
- if (sub === "view" || sub === "show") {
1033
- const plan = await loadPlan(state.session.sessionId).catch(() => undefined);
1034
- if (!plan) {
1035
- console.log(chalk.dim(" no active plan to view"));
1036
- return true;
1037
- }
1038
- if (process.stdout.isTTY && input.isTTY) {
1039
- await openPager({
1040
- title: `plan · ${plan.goal}`,
1041
- body: renderPlanDocument(plan),
1042
- });
1043
- }
1044
- else {
1045
- console.log(renderPlanDocument(plan));
1046
- }
1047
- return true;
1048
- }
1049
- console.log(chalk.dim(" usage: /plan [view|off]"));
1050
- return true;
1051
- }
1052
- case "/discard": {
1053
- const plan = await loadPlan(state.session.sessionId).catch(() => undefined);
1054
- if (!plan) {
1055
- console.log(chalk.dim(" no active plan to discard"));
1056
- return true;
1057
- }
1058
- await deletePlan(state.session.sessionId).catch(() => undefined);
1059
- state.session.planApproved.value = false;
1060
- console.log(chalk.yellow(` ✗ plan discarded — "${plan.goal}"`) +
1061
- chalk.dim("\n later messages are now independent of it.\n"));
1062
- return true;
1063
- }
1064
- case "/compact": {
1065
- const before = state.messages.length;
1066
- const compacted = compactMessages(state.messages, { budgetTokens: 0 });
1067
- state.messages.splice(0, state.messages.length, ...compacted);
1068
- console.log(chalk.dim(` compacted ${before} → ${state.messages.length} messages (~${estimateMessagesTokens(state.messages).toLocaleString()} tokens)`));
1069
- return true;
1070
- }
1071
- case "/scope": {
1072
- const sub = (args[0] ?? "show").toLowerCase();
1073
- const { loadScope, saveScope, addScopeTargets, clearScope, isScopeActive, getScopePath, resetScopeCache, } = await import("./store/scope.js");
1074
- if (sub === "show" || sub === "ls" || sub === "list") {
1075
- resetScopeCache();
1076
- const scope = await loadScope();
1077
- if (!scope) {
1078
- console.log(chalk.dim(" no engagement scope configured"));
1079
- console.log(chalk.dim(` expected at: ${getScopePath()}`));
1080
- console.log(chalk.dim(" create one with: /scope add domain1,domain2 or `clai scope add --targets ...`"));
1081
- return true;
1082
- }
1083
- const status = isScopeActive(scope)
1084
- ? chalk.green("active")
1085
- : chalk.yellow("expired or empty");
1086
- console.log(chalk.dim(` scope: ${scope.name ?? "(unnamed)"} [${status}]`));
1087
- console.log(chalk.dim(` authorized: ${scope.authorizedTargets.join(", ")}`));
1088
- if (scope.excludedTargets && scope.excludedTargets.length > 0) {
1089
- console.log(chalk.dim(` excluded: ${scope.excludedTargets.join(", ")}`));
1090
- }
1091
- if (scope.expiresAt) {
1092
- console.log(chalk.dim(` expires: ${scope.expiresAt}`));
1093
- }
1094
- return true;
1095
- }
1096
- if (sub === "clear" || sub === "reset" || sub === "off") {
1097
- await clearScope();
1098
- console.log(chalk.dim(" engagement scope cleared"));
1099
- return true;
1100
- }
1101
- if (sub === "add") {
1102
- const rest = args.slice(1).join(" ").trim();
1103
- if (!rest) {
1104
- console.log(chalk.dim(" usage: /scope add <target1,target2,...>"));
1105
- return true;
1106
- }
1107
- const targets = rest
1108
- .split(/\s+/)[0]
1109
- .split(",")
1110
- .map((t) => t.trim())
1111
- .filter(Boolean);
1112
- if (targets.length === 0) {
1113
- console.log(chalk.dim(" no targets parsed"));
1114
- return true;
1115
- }
1116
- const scope = await addScopeTargets(targets);
1117
- console.log(chalk.dim(` added ${targets.length} target(s); scope now has ${scope.authorizedTargets.length}`));
1118
- return true;
1119
- }
1120
- if (sub === "new" || sub === "set") {
1121
- const rest = args.slice(1).join(" ").trim();
1122
- if (!rest) {
1123
- console.log(chalk.dim(" usage: /scope new <target1,target2,...> [name=<engagement>] [expires=<iso>]"));
1124
- return true;
1125
- }
1126
- // Parse: first whitespace-delimited token is the targets list,
1127
- // remaining `key=value` pairs configure name/expires/note.
1128
- const tokens = rest.split(/\s+/);
1129
- const targetsRaw = tokens[0] ?? "";
1130
- const targets = targetsRaw
1131
- .split(",")
1132
- .map((t) => t.trim())
1133
- .filter(Boolean);
1134
- if (targets.length === 0) {
1135
- console.log(chalk.dim(" no targets parsed"));
1136
- return true;
1137
- }
1138
- let name;
1139
- let expires;
1140
- let note;
1141
- let exclude;
1142
- for (const token of tokens.slice(1)) {
1143
- const eq = token.indexOf("=");
1144
- if (eq < 0)
1145
- continue;
1146
- const key = token.slice(0, eq).toLowerCase();
1147
- const value = token.slice(eq + 1);
1148
- if (key === "name")
1149
- name = value;
1150
- else if (key === "expires")
1151
- expires = value;
1152
- else if (key === "note")
1153
- note = value;
1154
- else if (key === "exclude")
1155
- exclude = value
1156
- .split(",")
1157
- .map((t) => t.trim())
1158
- .filter(Boolean);
1159
- }
1160
- const scope = {
1161
- name,
1162
- authorizedTargets: targets,
1163
- excludedTargets: exclude,
1164
- authorizationNote: note,
1165
- createdAt: new Date().toISOString(),
1166
- expiresAt: expires,
1167
- };
1168
- await saveScope(scope);
1169
- console.log(chalk.dim(` saved scope${name ? ` "${name}"` : ""} with ${targets.length} target(s)`));
1170
- return true;
1171
- }
1172
- console.log(chalk.dim(" usage: /scope [show|clear|new <targets>|add <targets> [key=value]...]"));
1173
- return true;
1174
- }
1175
- case "/privacy": {
1176
- const sub = (args[0] ?? "status").toLowerCase();
1177
- if (sub === "on" || sub === "enable") {
1178
- updateConfig({ privateMode: true });
1179
- console.log(chalk.dim(" privateMode: " +
1180
- chalk.green("on") +
1181
- " (history not written; in-memory only)"));
1182
- return true;
1183
- }
1184
- if (sub === "off" || sub === "disable") {
1185
- updateConfig({ privateMode: false });
1186
- console.log(chalk.dim(" privateMode: " + chalk.dim("off")));
1187
- return true;
1188
- }
1189
- if (sub === "status" || sub === "show") {
1190
- const cfg = getConfig();
1191
- console.log(chalk.dim(` privateMode: ${cfg.privateMode ? chalk.green("on") : chalk.dim("off")} retention: ${cfg.historyRetentionLimit || "unlimited"}`));
1192
- return true;
1193
- }
1194
- const { clearAllHistory } = await import("./store/history.js");
1195
- const { clearAuditLogs, clearArtifacts } = await import("./store/logs.js");
1196
- if (sub === "clear-history") {
1197
- const r = await clearAllHistory();
1198
- console.log(chalk.dim(` history cleared (${r.detail || "ok"})`));
1199
- return true;
1200
- }
1201
- if (sub === "clear-logs") {
1202
- const r = await clearAuditLogs();
1203
- console.log(chalk.dim(` audit logs cleared (${r.removed} files)`));
1204
- return true;
1205
- }
1206
- if (sub === "clear-artifacts") {
1207
- const r = await clearArtifacts();
1208
- console.log(chalk.dim(` artifacts cleared (${r.removed} files)`));
1209
- return true;
1210
- }
1211
- if (sub === "clear-all") {
1212
- const a = await clearAllHistory();
1213
- const b = await clearAuditLogs();
1214
- const c = await clearArtifacts();
1215
- console.log(chalk.dim(` history (${a.detail || "ok"}); logs (${b.removed}); artifacts (${c.removed})`));
1216
- return true;
1217
- }
1218
- console.log(chalk.dim(" usage: /privacy [status|on|off|clear-history|clear-logs|clear-artifacts|clear-all]"));
1219
- return true;
1220
- }
1221
- case "/freeonly": {
1222
- const arg = (args[0] ?? "").toLowerCase().trim();
1223
- if (!arg) {
1224
- const value = getConfig().freeOnly;
1225
- console.log(chalk.dim(` freeOnly: ${value ? chalk.green("on") : chalk.dim("off")} (applies when /fallback is on)`));
1226
- return true;
1227
- }
1228
- if (arg === "on" || arg === "true" || arg === "enable") {
1229
- updateConfig({ freeOnly: true });
1230
- console.log(chalk.dim(" freeOnly: " + chalk.green("on")));
1231
- return true;
1232
- }
1233
- if (arg === "off" || arg === "false" || arg === "disable") {
1234
- updateConfig({ freeOnly: false });
1235
- console.log(chalk.dim(" freeOnly: " + chalk.dim("off")));
1236
- return true;
1237
- }
1238
- console.log(chalk.dim(" usage: /freeonly [on|off]"));
1239
- return true;
1240
- }
1241
- case "/fallback": {
1242
- const arg = (args[0] ?? "").toLowerCase().trim();
1243
- if (!arg) {
1244
- const value = getConfig().providerFallback;
1245
- console.log(chalk.dim(` fallback: ${value ? chalk.green("on") : chalk.dim("off")} (selected provider/model only when off)`));
1246
- return true;
1247
- }
1248
- if (arg === "on" || arg === "true" || arg === "enable") {
1249
- updateConfig({ providerFallback: true });
1250
- console.log(chalk.dim(" fallback: " + chalk.green("on")));
1251
- return true;
1252
- }
1253
- if (arg === "off" || arg === "false" || arg === "disable") {
1254
- updateConfig({ providerFallback: false });
1255
- console.log(chalk.dim(" fallback: " + chalk.dim("off")));
1256
- return true;
1257
- }
1258
- console.log(chalk.dim(" usage: /fallback [on|off]"));
1259
- return true;
1260
- }
1261
- case "/output": {
1262
- const target = args[0] ?? "last";
1263
- if (target === "list" || target === "ls") {
1264
- const all = listViewports();
1265
- if (all.length === 0) {
1266
- console.log(chalk.dim(" no tool outputs recorded yet"));
1267
- }
1268
- else {
1269
- for (const v of all) {
1270
- console.log(chalk.dim(` ${v.id} — ${v.toolName} ${v.argsDisplay}${v.artifactPath ? ` (${v.artifactPath})` : ""}`));
1271
- }
1272
- }
1273
- return true;
1274
- }
1275
- const viewport = target === "last" ? getLastViewport() : getViewport(target);
1276
- if (!viewport) {
1277
- console.log(chalk.dim(` no viewport: ${target}`));
1278
- return true;
1279
- }
1280
- // On a TTY, open the alternate-screen pager so users can scroll long
1281
- // outputs and close with q / Ctrl+O. In non-TTY contexts (piped or
1282
- // CI), fall back to the inline toggle so the artifact still lands in
1283
- // the captured stdout.
1284
- if (process.stdout.isTTY) {
1285
- await openViewportPager(viewport.id);
1286
- }
1287
- else {
1288
- await toggleViewport(viewport.id);
1289
- }
1290
- return true;
1291
- }
1292
- case "/think":
1293
- case "/thinking": {
1294
- if (getLastThinking()) {
1295
- console.log(renderAllThinking());
1296
- }
1297
- else {
1298
- console.log(chalk.dim(" No thinking from last response."));
1299
- }
1300
- return true;
1301
- }
1302
- case "/exit":
1303
- case "/quit":
1304
- process.stdout.write(chalk.dim(" Goodbye!\n"));
1305
- return false;
1306
- case "/clean": {
1307
- // A fresh session, not just a cleared screen: new identity, policy,
1308
- // plan approval, allowances and scratch workspace.
1309
- state.messages.length = 0;
1310
- state.resumedMessageCount = 0;
1311
- state.historyId = undefined;
1312
- resetClassicSessionContext(state);
1313
- clearViewports();
1314
- clearThinking();
1315
- // Clear the entire screen and move cursor to top
1316
- process.stdout.write("\x1b[2J\x1b[3J\x1b[H");
1317
- // Re-render the startup intro card
1318
- console.log(renderIntroCard({
1319
- version: getCurrentVersion(),
1320
- workdir: safeCwd(),
1321
- model: state.model,
1322
- provider: state.provider,
1323
- mode: state.mode,
1324
- permissions: getConfig().permissions ?? "default",
1325
- }));
1326
- console.log();
1327
- return true;
1328
- }
1329
- case "/update":
1330
- await runUpdate();
1331
- return true;
1332
- case "/help":
1333
- console.log(help());
1334
- return true;
1335
- default:
1336
- console.log(chalk.dim(` unknown command: ${command}. Try /help`));
1337
- return true;
1338
- }
1339
- }
1340
- export async function startRepl(options = {}) {
1341
- const config = getConfig();
1342
- const provider = options.provider
1343
- ? assertProvider(options.provider)
1344
- : config.defaultProvider;
1345
- // Bind a unique session workspace before any tool/scratch path is resolved.
1346
- beginSessionWorkspace();
1347
- const state = {
1348
- mode: options.mode ?? config.defaultMode,
1349
- provider,
1350
- model: options.model ?? getProviderModel(provider),
1351
- messages: [],
1352
- session: createSessionPolicy(),
1353
- resumedMessageCount: 0,
1354
- historyId: undefined,
1355
- };
1356
- const promptHistory = [];
1357
- let isReadingPrompt = false;
1358
- let outputShortcutBusy = false;
1359
- let lastOutputShortcutAt = 0;
1360
- let abortPressCount = 0;
1361
- let lastEscapeAt = 0;
1362
- emitKeypressEvents(input);
1363
- // Only expected abort noise is tolerated. Anything else leaves the process
1364
- // with unknown invariants, so it shuts down through the same boundary.
1365
- const handleFatal = (kind, cause) => {
1366
- if (isAbortLikeError(cause))
1367
- return;
1368
- const message = cause instanceof Error ? cause.message : String(cause);
1369
- process.stderr.write(chalk.red(`\n ✖ fatal ${kind}: ${redactSecrets(message)}\n`));
1370
- void shutdown(1);
1371
- };
1372
- const handleUnhandledRejection = (reason) => handleFatal("rejection", reason);
1373
- const handleUncaughtException = (error) => handleFatal("exception", error);
1374
- process.on("unhandledRejection", handleUnhandledRejection);
1375
- process.on("uncaughtException", handleUncaughtException);
1376
- // Double Esc cancels the turn + jobs; Ctrl+C aborts; Ctrl+T toggles thinking
1377
- if (process.stdin.isTTY) {
1378
- process.stdin.setRawMode(false);
1379
- }
1380
- const handleThinkingShortcut = () => {
1381
- process.stdout.write(`\n${renderThinkingToggleMessage()}\n`);
1382
- };
1383
- const handleOutputShortcut = async () => {
1384
- if (outputShortcutBusy)
1385
- return;
1386
- const now = Date.now();
1387
- if (now - lastOutputShortcutAt < 400)
1388
- return;
1389
- lastOutputShortcutAt = now;
1390
- outputShortcutBusy = true;
1391
- try {
1392
- const v = getLastViewport();
1393
- if (!v) {
1394
- process.stdout.write(chalk.dim("\n (no tool output to expand yet)\n"));
1395
- return;
1396
- }
1397
- if (currentAbortController || !isReadingPrompt) {
1398
- if (v.artifactPath) {
1399
- process.stdout.write(chalk.dim(`\n ▸ ${v.toolName} output is streaming to:\n ${v.artifactPath}\n` +
1400
- ` (tail it in another terminal now, or press Ctrl+O here after it finishes)\n`));
1401
- }
1402
- else {
1403
- process.stdout.write(chalk.dim(`\n (press Ctrl+O at the prompt after it finishes to open ${v.toolName})\n`));
1404
- }
1405
- return;
1406
- }
1407
- // Idle path: open the full output in the alternate-screen pager.
1408
- // Keys (q / ESC / Ctrl+O) inside the pager close it and return here.
1409
- await openViewportPager(v.id);
1410
- }
1411
- finally {
1412
- outputShortcutBusy = false;
1413
- }
1414
- };
1415
- let planShortcutBusy = false;
1416
- const handlePlanShortcut = async () => {
1417
- if (planShortcutBusy)
1418
- return;
1419
- planShortcutBusy = true;
1420
- try {
1421
- // Only open the pager when idle (same reasoning as Ctrl+O).
1422
- if (currentAbortController || !isReadingPrompt) {
1423
- process.stdout.write(chalk.dim("\n (press Ctrl+P at the prompt when idle to view the plan)\n"));
1424
- return;
1425
- }
1426
- const plan = await loadPlan(state.session.sessionId).catch(() => undefined);
1427
- if (!plan) {
1428
- process.stdout.write(chalk.dim('\n (no plan yet — ask clai to plan a multi-step task, e.g. "build a react blog app")\n'));
1429
- return;
1430
- }
1431
- await openPager({
1432
- title: `plan · ${plan.goal}`,
1433
- body: renderPlanDocument(plan),
1434
- });
1435
- }
1436
- finally {
1437
- planShortcutBusy = false;
1438
- }
1439
- };
1440
- const handleKeypress = (_sequence, key) => {
1441
- if (isPagerActive())
1442
- return;
1443
- if (isCtrlT(key) && !isReadingPrompt)
1444
- handleThinkingShortcut();
1445
- if (isCtrlO(key) && !isReadingPrompt) {
1446
- void handleOutputShortcut();
1447
- }
1448
- if (isCtrlP(key) && !isReadingPrompt) {
1449
- void handlePlanShortcut();
1450
- }
1451
- if (isEscape(key) && currentAbortController) {
1452
- const now = Date.now();
1453
- if (lastEscapeAt > 0 && now - lastEscapeAt < 1_500) {
1454
- lastEscapeAt = 0;
1455
- abortPressCount += 1;
1456
- currentAbortController.abort();
1457
- void jobManager.cancelAll(state.session.sessionId);
1458
- void interactiveSessionManager.cancelOwner(state.session.sessionId);
1459
- process.stdout.write(chalk.yellow("\n ⏹ cancelling turn + session processes…\n"));
1460
- }
1461
- else {
1462
- lastEscapeAt = now;
1463
- process.stdout.write(chalk.dim("\n (press Esc again to cancel turn + session jobs)\n"));
1464
- }
1465
- }
1466
- else if (isCtrlC(key) && currentAbortController) {
1467
- abortPressCount += 1;
1468
- currentAbortController.abort();
1469
- if (abortPressCount === 1) {
1470
- process.stdout.write(chalk.yellow("\n ⏹ aborting…\n"));
1471
- }
1472
- else {
1473
- process.stdout.write(chalk.yellow(" ⏹ force-killing…\n"));
1474
- }
1475
- }
1476
- };
1477
- input.on("keypress", handleKeypress);
1478
- const siginfo = "SIGINFO";
1479
- let siginfoRegistered = false;
1480
- try {
1481
- process.on(siginfo, handleThinkingShortcut);
1482
- siginfoRegistered = true;
1483
- }
1484
- catch {
1485
- // SIGINFO is macOS/BSD-specific; other platforms can still use /think.
1486
- }
1487
- let lastSigintAt = 0;
1488
- let shuttingDown = false;
1489
- /** One shutdown boundary for normal quit, signals and fatal errors. */
1490
- const finalizeSession = async () => {
1491
- isReadingPrompt = false;
1492
- input.off("keypress", handleKeypress);
1493
- process.off("SIGINT", handleSigint);
1494
- process.off("unhandledRejection", handleUnhandledRejection);
1495
- process.off("uncaughtException", handleUncaughtException);
1496
- if (siginfoRegistered)
1497
- process.off(siginfo, handleThinkingShortcut);
1498
- if (state.messages.length > state.resumedMessageCount) {
1499
- // Honor `--no-history` and the persistent privateMode setting.
1500
- if (!options.noHistory && !getConfig().privateMode) {
1501
- await persistSession(state).catch(() => undefined);
1502
- }
1503
- }
1504
- if (input.isTTY)
1505
- input.setRawMode(false);
1506
- };
1507
- const shutdown = async (code) => {
1508
- if (shuttingDown)
1509
- return;
1510
- shuttingDown = true;
1511
- const cleanup = await interactiveSessionManager
1512
- .closeAll("app-shutdown")
1513
- .catch(() => undefined);
1514
- for (const failure of cleanup?.failures ?? []) {
1515
- process.stderr.write(`clai interactive-session cleanup: [${failure.code}] ${failure.message}\n`);
1516
- }
1517
- await finalizeSession();
1518
- // Force exit so lingering handles (timers, watchers, bg jobs) don't keep
1519
- // the process alive after the user chose to quit.
1520
- process.exitCode = code;
1521
- process.exit(code);
1522
- };
1523
- const handleSigint = () => {
1524
- if (currentAbortController) {
1525
- currentAbortController.abort();
1526
- return;
1527
- }
1528
- if (isReadingPrompt) {
1529
- // readPromptLine's keypress handler owns the prompt-level Ctrl+C
1530
- // semantics; do nothing here so the two paths never fight.
1531
- return;
1532
- }
1533
- const now = Date.now();
1534
- if (now - lastSigintAt < 1_000) {
1535
- console.log();
1536
- void shutdown(0);
1537
- return;
1538
- }
1539
- lastSigintAt = now;
1540
- console.log(chalk.dim("\n (press Ctrl+C again to exit)"));
1541
- };
1542
- process.on("SIGINT", handleSigint);
1543
- // Startup intro card
1544
- console.log(renderIntroCard({
1545
- version: getCurrentVersion(),
1546
- workdir: safeCwd(),
1547
- model: state.model,
1548
- provider: state.provider,
1549
- mode: state.mode,
1550
- permissions: getConfig().permissions ?? "default",
1551
- }));
1552
- console.log();
1553
- // Hint thinking-capable users that the toggle exists. We default it to
1554
- // off for speed, since on NIM many models route through a much slower
1555
- // chat-template path when reasoning is enabled.
1556
- if (!getConfig().thinking.enabled &&
1557
- modelSupportsThinking(state.provider, state.model)) {
1558
- console.log(chalk.dim(" 💡 ") +
1559
- chalk.dim(`${state.model} supports reasoning. Run `) +
1560
- chalk.cyan("/effort") +
1561
- chalk.dim(" to pick an effort level or ") +
1562
- chalk.cyan("/effort high") +
1563
- chalk.dim(" to enable directly.\n"));
1564
- }
1565
- // Non-blocking update check
1566
- checkForUpdateSilent();
1567
- try {
1568
- while (true) {
1569
- isReadingPrompt = true;
1570
- const rawLine = await readPromptLine({
1571
- history: promptHistory,
1572
- onThinkingShortcut: handleThinkingShortcut,
1573
- onOutputShortcut: handleOutputShortcut,
1574
- onPlanShortcut: handlePlanShortcut,
1575
- });
1576
- isReadingPrompt = false;
1577
- if (rawLine === PROMPT_EXIT_INTENT)
1578
- break;
1579
- const line = rawLine.trim();
1580
- if (!line)
1581
- continue;
1582
- // /implement — approve the active plan and execute it
1583
- // Handled here (not in handleSlash) because it must trigger a full
1584
- // agent run with the plan marked approved, not just print something.
1585
- let implementApproved = false;
1586
- let effectiveLine = line;
1587
- if (line === "/implement" || line.startsWith("/implement ")) {
1588
- const plan = await loadPlan(state.session.sessionId).catch(() => undefined);
1589
- if (!plan) {
1590
- console.log(chalk.dim(" no plan to implement — ask clai to plan a multi-step task first"));
1591
- continue;
1592
- }
1593
- if (isPlanSuccessful(plan)) {
1594
- console.log(chalk.dim(" this plan is already complete ✓"));
1595
- continue;
1596
- }
1597
- plan.status = "approved";
1598
- await mutatePlan(plan.sessionId, (draft) => {
1599
- if (draft.status === "approved")
1600
- return false;
1601
- draft.status = "approved";
1602
- return true;
1603
- }).catch(() => undefined);
1604
- state.session.planApproved.value = true;
1605
- console.log(chalk.cyan(" ✦ plan approved — clai will now execute it\n"));
1606
- console.log(renderPlanChecklist(plan) + "\n");
1607
- implementApproved = true;
1608
- if (state.mode === "plan") {
1609
- state.mode = "agent";
1610
- setDefaultMode("agent");
1611
- console.log(renderModeSwitch("agent"));
1612
- }
1613
- effectiveLine = IMPLEMENT_DIRECTIVE;
1614
- }
1615
- // Continuation detection
1616
- // When the user types "continue" after the agent paused at a step limit,
1617
- // augment the bare keyword with rich resumption context so the model
1618
- // picks up from where it left off instead of restarting.
1619
- const REPL_CONTINUE_RE = /^(?:continue|proceed|keep\s+going|go\s+on|resume|finish\s+it|next)$/i;
1620
- if (REPL_CONTINUE_RE.test(line) &&
1621
- !implementApproved &&
1622
- state.messages.length > 0) {
1623
- const lastMsg = state.messages[state.messages.length - 1];
1624
- if (lastMsg?.role === "assistant" &&
1625
- /Session paused after \d+ steps/i.test(lastMsg.content)) {
1626
- effectiveLine =
1627
- "Continue from where you left off. " +
1628
- "The previous session summary is in your context — review it and resume the next pending task. " +
1629
- "Do NOT repeat completed work. Do NOT re-fetch data you already have.";
1630
- }
1631
- }
1632
- // Only remember real prompts in the history ring. Slash commands
1633
- // are operational toggles (eg /model, /provider) and surfacing them
1634
- // when the user presses ↑ to recall a past prompt is just noise.
1635
- if (!looksLikeSlashCommand(line) &&
1636
- promptHistory[promptHistory.length - 1] !== line) {
1637
- promptHistory.push(line);
1638
- }
1639
- if (looksLikeSlashCommand(line) && !implementApproved) {
1640
- // Slash commands may call inquirer/password prompts, which expect the
1641
- // terminal in cooked mode. Normal model runs keep raw mode enabled so
1642
- // ESC/Ctrl+C can abort while streaming.
1643
- input.pause();
1644
- if (input.isTTY)
1645
- input.setRawMode(false);
1646
- const shouldContinue = await handleSlash(line, state);
1647
- if (!shouldContinue)
1648
- break;
1649
- continue;
1650
- }
1651
- try {
1652
- clearThinking();
1653
- abortPressCount = 0;
1654
- lastEscapeAt = 0;
1655
- let assistantContent = "";
1656
- // Expand @file mentions and drag-and-dropped paths into real context.
1657
- // The user-visible `line` stays readable in history; the model gets
1658
- // the line plus an appended block of file contents / path notes.
1659
- const resolvedInput = resolveTurnInput({
1660
- prompt: effectiveLine,
1661
- mode: state.mode,
1662
- provider: state.provider,
1663
- model: state.model,
1664
- baseDir: safeCwd(),
1665
- });
1666
- const requestModel = resolvedInput.model;
1667
- const visionCapable = resolvedInput.capability.vision;
1668
- const expansion = { attachments: resolvedInput.attachments };
1669
- const images = [...resolvedInput.images];
1670
- if (resolvedInput.fallbackReason) {
1671
- console.log(chalk.dim(` ↳ ${resolvedInput.fallbackReason}`));
1672
- }
1673
- for (const issue of resolvedInput.imageIssues) {
1674
- console.log(chalk.yellow(` ↳ ${issue}`));
1675
- }
1676
- const hasImageAttachment = expansion.attachments.some((att) => att.kind === "image" && att.sendable !== false);
1677
- const sentImagePaths = new Set(images.map((img) => img.path).filter((p) => Boolean(p)));
1678
- // Vision is authoritative for visual analysis. OCR is opt-in when the
1679
- // selected model cannot see the image and the user specifically asks
1680
- // for text extraction; it is never treated as layout/color evidence.
1681
- const shouldOcr = shouldRunImageOcr({
1682
- hasImage: hasImageAttachment,
1683
- visionCapable,
1684
- support: resolvedInput.capability.support,
1685
- prompt: effectiveLine,
1686
- });
1687
- const ocrGrounding = shouldOcr
1688
- ? await buildImageOcrGrounding(effectiveLine, safeCwd())
1689
- : "";
1690
- const modelInput = ocrGrounding
1691
- ? `${resolvedInput.prompt}\n\n${ocrGrounding}`
1692
- : resolvedInput.prompt;
1693
- if (expansion.attachments.length > 0) {
1694
- for (const att of expansion.attachments) {
1695
- const tag = att.kind === "text"
1696
- ? chalk.green("attached")
1697
- : att.kind === "missing"
1698
- ? chalk.red("not found")
1699
- : att.kind === "image" && sentImagePaths.has(att.path)
1700
- ? chalk.green("image (sent to model)")
1701
- : att.kind === "image" && visionCapable
1702
- ? chalk.yellow("image (not sent)")
1703
- : chalk.yellow(att.kind);
1704
- console.log(chalk.dim(` ↳ ${tag}: `) + chalk.dim(att.path));
1705
- }
1706
- }
1707
- if (state.mode === "ask") {
1708
- let actionRequired;
1709
- assistantContent = await withAbortableInput(async (signal) => streamWithAbort(async (runSignal, onToken, setStatus) => {
1710
- return await runAskStream(modelInput, onToken, {
1711
- provider: state.provider,
1712
- model: requestModel,
1713
- history: state.messages,
1714
- signal: runSignal,
1715
- images,
1716
- onActionRequired: (info) => {
1717
- actionRequired = info;
1718
- },
1719
- onEvent: (event) => {
1720
- if (event.type === "tool-call") {
1721
- setStatus(askResearchLabel(event.name, event.argsDisplay));
1722
- }
1723
- },
1724
- });
1725
- }, signal));
1726
- process.stdout.write("\n");
1727
- if (actionRequired) {
1728
- // The task needs actions ask mode can't perform. Offer to switch
1729
- // into agent mode and run it there. On confirm, state.mode flips
1730
- // so subsequent turns stay in agent mode too.
1731
- assistantContent = await offerAgentSwitch(actionRequired, state, requestModel, images);
1732
- }
1733
- }
1734
- else {
1735
- const classicRenderer = attachClassicRenderer();
1736
- assistantContent = await withAbortableInput(async (signal) => runAgent(modelInput, {
1737
- provider: state.provider,
1738
- model: requestModel,
1739
- history: state.messages,
1740
- signal,
1741
- session: state.session,
1742
- images,
1743
- visionProven: resolvedInput.capability.support === "yes",
1744
- mode: state.mode === "plan" ? "plan" : "agent",
1745
- onEvent: classicRenderer.onEvent,
1746
- }));
1747
- }
1748
- console.log();
1749
- const userHistoryMessage = {
1750
- role: "user",
1751
- content: modelInput,
1752
- };
1753
- if (images.length > 0)
1754
- userHistoryMessage.images = images;
1755
- state.messages.push(userHistoryMessage, {
1756
- role: "assistant",
1757
- content: assistantContent,
1758
- });
1759
- // After plan mode (or any draft plan), offer Accept / Discard / View / Suggest.
1760
- if (state.mode === "plan" || !state.session.planApproved.value) {
1761
- const draft = await loadPlan(state.session.sessionId).catch(() => undefined);
1762
- if (draft && draft.status === "draft") {
1763
- input.pause();
1764
- if (input.isTTY)
1765
- input.setRawMode(false);
1766
- try {
1767
- const decision = await handleDraftPlanDecision({
1768
- plan: draft,
1769
- sessionId: state.session.sessionId,
1770
- planApproved: state.session.planApproved,
1771
- setModeAgent: () => {
1772
- state.mode = "agent";
1773
- setDefaultMode("agent");
1774
- console.log(renderModeSwitch("agent"));
1775
- },
1776
- });
1777
- if (decision.action === "implement") {
1778
- const classicRenderer = attachClassicRenderer();
1779
- const followUp = await withAbortableInput(async (signal) => runAgent(decision.line, {
1780
- provider: state.provider,
1781
- model: requestModel,
1782
- history: state.messages,
1783
- signal,
1784
- session: state.session,
1785
- mode: "agent",
1786
- onEvent: classicRenderer.onEvent,
1787
- }));
1788
- console.log();
1789
- state.messages.push({ role: "user", content: decision.line }, { role: "assistant", content: followUp });
1790
- }
1791
- else if (decision.action === "suggest") {
1792
- state.mode = "plan";
1793
- setDefaultMode("plan");
1794
- const classicRenderer = attachClassicRenderer();
1795
- const revision = await withAbortableInput(async (signal) => runAgent(decision.line, {
1796
- provider: state.provider,
1797
- model: requestModel,
1798
- history: state.messages,
1799
- signal,
1800
- session: state.session,
1801
- mode: "plan",
1802
- onEvent: classicRenderer.onEvent,
1803
- }));
1804
- console.log();
1805
- state.messages.push({ role: "user", content: decision.line }, { role: "assistant", content: revision });
1806
- // Re-prompt if a new draft exists
1807
- const revised = await loadPlan(state.session.sessionId).catch(() => undefined);
1808
- if (revised && revised.status === "draft") {
1809
- const again = await handleDraftPlanDecision({
1810
- plan: revised,
1811
- sessionId: state.session.sessionId,
1812
- planApproved: state.session.planApproved,
1813
- setModeAgent: () => {
1814
- state.mode = "agent";
1815
- setDefaultMode("agent");
1816
- console.log(renderModeSwitch("agent"));
1817
- },
1818
- });
1819
- if (again.action === "implement") {
1820
- const classicRenderer2 = attachClassicRenderer();
1821
- const followUp2 = await withAbortableInput(async (signal) => runAgent(again.line, {
1822
- provider: state.provider,
1823
- model: requestModel,
1824
- history: state.messages,
1825
- signal,
1826
- session: state.session,
1827
- mode: "agent",
1828
- onEvent: classicRenderer2.onEvent,
1829
- }));
1830
- console.log();
1831
- state.messages.push({ role: "user", content: again.line }, { role: "assistant", content: followUp2 });
1832
- }
1833
- else if (again.action === "suggest") {
1834
- // Leave feedback in chat; next turn continues plan mode
1835
- state.messages.push({
1836
- role: "user",
1837
- content: again.line,
1838
- });
1839
- }
1840
- }
1841
- }
1842
- }
1843
- finally {
1844
- if (input.isTTY)
1845
- input.setRawMode(true);
1846
- input.resume();
1847
- }
1848
- }
1849
- }
1850
- }
1851
- catch (error) {
1852
- if (error instanceof AbortRunError) {
1853
- process.stdout.write(chalk.yellow("\n ⏹ Aborted.\n"));
1854
- continue;
1855
- }
1856
- // Still save the exchange so /history doesn't lose conversations
1857
- // that hit transient errors (e.g. "requires root", network timeout).
1858
- const errMsg = error instanceof Error ? error.message : String(error);
1859
- state.messages.push({ role: "user", content: line }, { role: "assistant", content: `[error: ${errMsg}]` });
1860
- console.error(chalk.red(errMsg));
1861
- }
1862
- }
1863
- }
1864
- finally {
1865
- await shutdown(0);
1866
- }
1867
- }
1868
- //# sourceMappingURL=repl.js.map