@pentoshi/clai 4.8.4 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. package/README.md +91 -4
  2. package/dist/agent/compaction-executor.d.ts +3 -5
  3. package/dist/agent/compaction-executor.js +165 -28
  4. package/dist/agent/compaction-executor.js.map +1 -1
  5. package/dist/agent/finalize-gate.js +0 -9
  6. package/dist/agent/finalize-gate.js.map +1 -1
  7. package/dist/agent/plan-mode-reminders.js +5 -5
  8. package/dist/agent/plan-mode-reminders.js.map +1 -1
  9. package/dist/agent/plan-tool.d.ts +1 -0
  10. package/dist/agent/plan-tool.js +50 -21
  11. package/dist/agent/plan-tool.js.map +1 -1
  12. package/dist/agent/reliability-policy.d.ts +9 -0
  13. package/dist/agent/reliability-policy.js +36 -1
  14. package/dist/agent/reliability-policy.js.map +1 -1
  15. package/dist/agent/runner.d.ts +4 -0
  16. package/dist/agent/runner.js +193 -116
  17. package/dist/agent/runner.js.map +1 -1
  18. package/dist/agent/task-analyzer.d.ts +8 -18
  19. package/dist/agent/task-analyzer.js +75 -182
  20. package/dist/agent/task-analyzer.js.map +1 -1
  21. package/dist/agent/task-evidence.js +10 -0
  22. package/dist/agent/task-evidence.js.map +1 -1
  23. package/dist/agent/tool-call-parser.js +14 -13
  24. package/dist/agent/tool-call-parser.js.map +1 -1
  25. package/dist/app/adapters/current-agent-adapter.d.ts +5 -1
  26. package/dist/app/adapters/current-agent-adapter.js +2 -1
  27. package/dist/app/adapters/current-agent-adapter.js.map +1 -1
  28. package/dist/app/commands/catalog.js +10 -0
  29. package/dist/app/commands/catalog.js.map +1 -1
  30. package/dist/app/commands/registry.js +1 -0
  31. package/dist/app/commands/registry.js.map +1 -1
  32. package/dist/app/controllers/session-compact-helper.js +3 -6
  33. package/dist/app/controllers/session-compact-helper.js.map +1 -1
  34. package/dist/app/ports/transcript-item.d.ts +4 -0
  35. package/dist/classic/app/ClassicApp.js +1 -1
  36. package/dist/classic/app/ClassicApp.js.map +1 -1
  37. package/dist/classic/app/action-handlers.js +4 -0
  38. package/dist/classic/app/action-handlers.js.map +1 -1
  39. package/dist/classic/app/app-wiring.js +1 -0
  40. package/dist/classic/app/app-wiring.js.map +1 -1
  41. package/dist/classic/app/wiring-lifecycle.js +1 -0
  42. package/dist/classic/app/wiring-lifecycle.js.map +1 -1
  43. package/dist/classic/blocks/compacted-lines.js +3 -0
  44. package/dist/classic/blocks/compacted-lines.js.map +1 -1
  45. package/dist/classic/blocks/thinking-lines.js +11 -2
  46. package/dist/classic/blocks/thinking-lines.js.map +1 -1
  47. package/dist/classic/bootstrap/start-classic.d.ts +1 -0
  48. package/dist/classic/bootstrap/start-classic.js +16 -0
  49. package/dist/classic/bootstrap/start-classic.js.map +1 -1
  50. package/dist/classic/chrome/Composer.d.ts +6 -0
  51. package/dist/classic/chrome/Composer.js +2 -3
  52. package/dist/classic/chrome/Composer.js.map +1 -1
  53. package/dist/classic/chrome/composer-controller.d.ts +6 -1
  54. package/dist/classic/chrome/composer-controller.js +18 -8
  55. package/dist/classic/chrome/composer-controller.js.map +1 -1
  56. package/dist/classic/chrome/editor-view.d.ts +2 -1
  57. package/dist/classic/chrome/editor-view.js +1 -1
  58. package/dist/classic/chrome/editor-view.js.map +1 -1
  59. package/dist/classic/chrome/status-rows.js +3 -2
  60. package/dist/classic/chrome/status-rows.js.map +1 -1
  61. package/dist/classic/panels/TextEditorPanel.d.ts +3 -0
  62. package/dist/classic/panels/TextEditorPanel.js +7 -0
  63. package/dist/classic/panels/TextEditorPanel.js.map +1 -0
  64. package/dist/classic/panels/panel-controller.js +28 -1
  65. package/dist/classic/panels/panel-controller.js.map +1 -1
  66. package/dist/classic/panels/panel-effect.d.ts +3 -0
  67. package/dist/classic/panels/panel-effect.js.map +1 -1
  68. package/dist/classic/panels/panel-effects.js +3 -0
  69. package/dist/classic/panels/panel-effects.js.map +1 -1
  70. package/dist/classic/panels/panel-host.js +3 -0
  71. package/dist/classic/panels/panel-host.js.map +1 -1
  72. package/dist/classic/panels/panel-types.d.ts +2 -0
  73. package/dist/classic/panels/secret-panel.d.ts +1 -1
  74. package/dist/classic/panels/secret-panel.js +4 -2
  75. package/dist/classic/panels/secret-panel.js.map +1 -1
  76. package/dist/classic/panels/text-editor-panel.d.ts +33 -0
  77. package/dist/classic/panels/text-editor-panel.js +101 -0
  78. package/dist/classic/panels/text-editor-panel.js.map +1 -0
  79. package/dist/index.js +60 -7
  80. package/dist/index.js.map +1 -1
  81. package/dist/interactive-session/transport-node-pty.d.ts +10 -1
  82. package/dist/interactive-session/transport-node-pty.js +36 -12
  83. package/dist/interactive-session/transport-node-pty.js.map +1 -1
  84. package/dist/llm/adapters/anthropic-tools.d.ts +2 -1
  85. package/dist/llm/adapters/anthropic-tools.js +55 -4
  86. package/dist/llm/adapters/anthropic-tools.js.map +1 -1
  87. package/dist/llm/anthropic.js +1 -1
  88. package/dist/llm/anthropic.js.map +1 -1
  89. package/dist/llm/aws-mantle.js +2 -0
  90. package/dist/llm/aws-mantle.js.map +1 -1
  91. package/dist/llm/meta.js +62 -68
  92. package/dist/llm/meta.js.map +1 -1
  93. package/dist/llm/operation-ledger.js +6 -2
  94. package/dist/llm/operation-ledger.js.map +1 -1
  95. package/dist/llm/provider.js +7 -7
  96. package/dist/llm/request-plan.js +7 -2
  97. package/dist/llm/request-plan.js.map +1 -1
  98. package/dist/llm/tool-protocol.d.ts +1 -0
  99. package/dist/llm/tool-protocol.js +7 -0
  100. package/dist/llm/tool-protocol.js.map +1 -1
  101. package/dist/mcp/client.d.ts +27 -0
  102. package/dist/mcp/client.js +119 -0
  103. package/dist/mcp/client.js.map +1 -0
  104. package/dist/mcp/config-file.d.ts +35 -0
  105. package/dist/mcp/config-file.js +217 -0
  106. package/dist/mcp/config-file.js.map +1 -0
  107. package/dist/mcp/discovery.d.ts +4 -0
  108. package/dist/mcp/discovery.js +409 -0
  109. package/dist/mcp/discovery.js.map +1 -0
  110. package/dist/mcp/format.d.ts +17 -0
  111. package/dist/mcp/format.js +122 -0
  112. package/dist/mcp/format.js.map +1 -0
  113. package/dist/mcp/index.d.ts +15 -0
  114. package/dist/mcp/index.js +16 -0
  115. package/dist/mcp/index.js.map +1 -0
  116. package/dist/mcp/jsonrpc.d.ts +40 -0
  117. package/dist/mcp/jsonrpc.js +175 -0
  118. package/dist/mcp/jsonrpc.js.map +1 -0
  119. package/dist/mcp/manager.d.ts +36 -0
  120. package/dist/mcp/manager.js +300 -0
  121. package/dist/mcp/manager.js.map +1 -0
  122. package/dist/mcp/mentions.d.ts +9 -0
  123. package/dist/mcp/mentions.js +44 -0
  124. package/dist/mcp/mentions.js.map +1 -0
  125. package/dist/mcp/names.d.ts +15 -0
  126. package/dist/mcp/names.js +59 -0
  127. package/dist/mcp/names.js.map +1 -0
  128. package/dist/mcp/results.d.ts +6 -0
  129. package/dist/mcp/results.js +182 -0
  130. package/dist/mcp/results.js.map +1 -0
  131. package/dist/mcp/runtime.d.ts +107 -0
  132. package/dist/mcp/runtime.js +505 -0
  133. package/dist/mcp/runtime.js.map +1 -0
  134. package/dist/mcp/substitution.d.ts +13 -0
  135. package/dist/mcp/substitution.js +74 -0
  136. package/dist/mcp/substitution.js.map +1 -0
  137. package/dist/mcp/transport-http.d.ts +53 -0
  138. package/dist/mcp/transport-http.js +433 -0
  139. package/dist/mcp/transport-http.js.map +1 -0
  140. package/dist/mcp/transport-stdio.d.ts +39 -0
  141. package/dist/mcp/transport-stdio.js +268 -0
  142. package/dist/mcp/transport-stdio.js.map +1 -0
  143. package/dist/mcp/transport.d.ts +20 -0
  144. package/dist/mcp/transport.js +44 -0
  145. package/dist/mcp/transport.js.map +1 -0
  146. package/dist/mcp/types.d.ts +179 -0
  147. package/dist/mcp/types.js +30 -0
  148. package/dist/mcp/types.js.map +1 -0
  149. package/dist/mcp/validation.d.ts +16 -0
  150. package/dist/mcp/validation.js +222 -0
  151. package/dist/mcp/validation.js.map +1 -0
  152. package/dist/modes/agent.d.ts +2 -0
  153. package/dist/modes/agent.js.map +1 -1
  154. package/dist/noninteractive/start-noninteractive.js +4 -0
  155. package/dist/noninteractive/start-noninteractive.js.map +1 -1
  156. package/dist/prompts/embedded.js +2 -2
  157. package/dist/prompts/embedded.js.map +1 -1
  158. package/dist/prompts/index.d.ts +3 -0
  159. package/dist/prompts/index.js +70 -55
  160. package/dist/prompts/index.js.map +1 -1
  161. package/dist/prompts/system.agent.md +34 -10
  162. package/dist/prompts/system.ask.md +8 -0
  163. package/dist/safety/classifier.js +4 -0
  164. package/dist/safety/classifier.js.map +1 -1
  165. package/dist/session-runtime/binding.d.ts +5 -0
  166. package/dist/session-runtime/binding.js +28 -0
  167. package/dist/session-runtime/binding.js.map +1 -0
  168. package/dist/session-runtime/child-bridge.d.ts +31 -0
  169. package/dist/session-runtime/child-bridge.js +169 -0
  170. package/dist/session-runtime/child-bridge.js.map +1 -0
  171. package/dist/session-runtime/client.d.ts +8 -0
  172. package/dist/session-runtime/client.js +448 -0
  173. package/dist/session-runtime/client.js.map +1 -0
  174. package/dist/session-runtime/discovery.d.ts +6 -0
  175. package/dist/session-runtime/discovery.js +100 -0
  176. package/dist/session-runtime/discovery.js.map +1 -0
  177. package/dist/session-runtime/host.d.ts +77 -0
  178. package/dist/session-runtime/host.js +758 -0
  179. package/dist/session-runtime/host.js.map +1 -0
  180. package/dist/session-runtime/launch.d.ts +11 -0
  181. package/dist/session-runtime/launch.js +68 -0
  182. package/dist/session-runtime/launch.js.map +1 -0
  183. package/dist/session-runtime/paths.d.ts +8 -0
  184. package/dist/session-runtime/paths.js +92 -0
  185. package/dist/session-runtime/paths.js.map +1 -0
  186. package/dist/session-runtime/protocol.d.ts +22 -0
  187. package/dist/session-runtime/protocol.js +149 -0
  188. package/dist/session-runtime/protocol.js.map +1 -0
  189. package/dist/session-runtime/replay-buffer.d.ts +12 -0
  190. package/dist/session-runtime/replay-buffer.js +50 -0
  191. package/dist/session-runtime/replay-buffer.js.map +1 -0
  192. package/dist/session-runtime/store.d.ts +14 -0
  193. package/dist/session-runtime/store.js +143 -0
  194. package/dist/session-runtime/store.js.map +1 -0
  195. package/dist/session-runtime/types.d.ts +102 -0
  196. package/dist/session-runtime/types.js +2 -0
  197. package/dist/session-runtime/types.js.map +1 -0
  198. package/dist/store/logs.js +17 -6
  199. package/dist/store/logs.js.map +1 -1
  200. package/dist/store/plan.d.ts +2 -0
  201. package/dist/store/plan.js.map +1 -1
  202. package/dist/store/session-workspace.js +2 -1
  203. package/dist/store/session-workspace.js.map +1 -1
  204. package/dist/tools/definitions.js +18 -0
  205. package/dist/tools/definitions.js.map +1 -1
  206. package/dist/tools/external-tools.d.ts +30 -0
  207. package/dist/tools/external-tools.js +52 -0
  208. package/dist/tools/external-tools.js.map +1 -0
  209. package/dist/tools/registry.js +36 -5
  210. package/dist/tools/registry.js.map +1 -1
  211. package/dist/tui-v2/bootstrap/start-tui-v2.d.ts +1 -0
  212. package/dist/tui-v2/bootstrap/start-tui-v2.js +16 -0
  213. package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
  214. package/dist/tui-v2/components/completion/completion-menu.d.ts +4 -6
  215. package/dist/tui-v2/components/completion/completion-menu.js +34 -16
  216. package/dist/tui-v2/components/completion/completion-menu.js.map +1 -1
  217. package/dist/tui-v2/components/composer/composer-input-box.js +3 -1
  218. package/dist/tui-v2/components/composer/composer-input-box.js.map +1 -1
  219. package/dist/tui-v2/components/modal/secret-modal.js +6 -4
  220. package/dist/tui-v2/components/modal/secret-modal.js.map +1 -1
  221. package/dist/tui-v2/components/modal/text-editor-modal.d.ts +19 -0
  222. package/dist/tui-v2/components/modal/text-editor-modal.js +85 -0
  223. package/dist/tui-v2/components/modal/text-editor-modal.js.map +1 -0
  224. package/dist/tui-v2/components/overlay/overlay-host.js +2 -1
  225. package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
  226. package/dist/tui-v2/components/transcript/compacted-row.js +12 -3
  227. package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
  228. package/dist/tui-v2/components/transcript/thinking-block.d.ts +9 -1
  229. package/dist/tui-v2/components/transcript/thinking-block.js +253 -49
  230. package/dist/tui-v2/components/transcript/thinking-block.js.map +1 -1
  231. package/dist/tui-v2/components/transcript/thinking-presentation.d.ts +46 -0
  232. package/dist/tui-v2/components/transcript/thinking-presentation.js +84 -0
  233. package/dist/tui-v2/components/transcript/thinking-presentation.js.map +1 -0
  234. package/dist/tui-v2/components/transcript/transcript-row.d.ts +2 -0
  235. package/dist/tui-v2/components/transcript/transcript-row.js +7 -2
  236. package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
  237. package/dist/tui-v2/components/transcript/transcript-view.js +195 -83
  238. package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
  239. package/dist/tui-v2/composer/composer-editor.js +54 -39
  240. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  241. package/dist/tui-v2/composer/composer-highlight.d.ts +20 -0
  242. package/dist/tui-v2/composer/composer-highlight.js +97 -0
  243. package/dist/tui-v2/composer/composer-highlight.js.map +1 -0
  244. package/dist/tui-v2/composer/textarea-keybindings.d.ts +5 -0
  245. package/dist/tui-v2/composer/textarea-keybindings.js +12 -0
  246. package/dist/tui-v2/composer/textarea-keybindings.js.map +1 -1
  247. package/dist/ui/mentions.js +4 -1
  248. package/dist/ui/mentions.js.map +1 -1
  249. package/dist/ui-core/actions/action-id.d.ts +1 -1
  250. package/dist/ui-core/actions/action-id.js +1 -0
  251. package/dist/ui-core/actions/action-id.js.map +1 -1
  252. package/dist/ui-core/actions/format-shortcuts.js +5 -0
  253. package/dist/ui-core/actions/format-shortcuts.js.map +1 -1
  254. package/dist/ui-core/actions/keymap.js +3 -0
  255. package/dist/ui-core/actions/keymap.js.map +1 -1
  256. package/dist/ui-core/bootstrap/composition-root.d.ts +7 -0
  257. package/dist/ui-core/bootstrap/composition-root.js +7 -1
  258. package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
  259. package/dist/ui-core/commands/command-handlers.js +5 -2
  260. package/dist/ui-core/commands/command-handlers.js.map +1 -1
  261. package/dist/ui-core/commands/config-commands.d.ts +1 -0
  262. package/dist/ui-core/commands/config-commands.js +6 -0
  263. package/dist/ui-core/commands/config-commands.js.map +1 -1
  264. package/dist/ui-core/commands/mcp-commands.d.ts +3 -0
  265. package/dist/ui-core/commands/mcp-commands.js +310 -0
  266. package/dist/ui-core/commands/mcp-commands.js.map +1 -0
  267. package/dist/ui-core/commands/picker-commands.d.ts +1 -1
  268. package/dist/ui-core/commands/picker-commands.js +70 -27
  269. package/dist/ui-core/commands/picker-commands.js.map +1 -1
  270. package/dist/ui-core/commands/session-commands.js +1 -0
  271. package/dist/ui-core/commands/session-commands.js.map +1 -1
  272. package/dist/ui-core/composer/completion-viewport.d.ts +40 -0
  273. package/dist/ui-core/composer/completion-viewport.js +105 -0
  274. package/dist/ui-core/composer/completion-viewport.js.map +1 -0
  275. package/dist/ui-core/controllers/overlay-controller.d.ts +24 -3
  276. package/dist/ui-core/controllers/overlay-controller.js +35 -4
  277. package/dist/ui-core/controllers/overlay-controller.js.map +1 -1
  278. package/dist/ui-core/rendering/artifact-pager-source.d.ts +1 -0
  279. package/dist/ui-core/rendering/artifact-pager-source.js +67 -1
  280. package/dist/ui-core/rendering/artifact-pager-source.js.map +1 -1
  281. package/dist/ui-core/rendering/duration.d.ts +3 -1
  282. package/dist/ui-core/rendering/duration.js +14 -0
  283. package/dist/ui-core/rendering/duration.js.map +1 -1
  284. package/dist/ui-core/rendering/exit-summary.js +4 -4
  285. package/dist/ui-core/rendering/format-help.js +4 -0
  286. package/dist/ui-core/rendering/format-help.js.map +1 -1
  287. package/dist/ui-core/rendering/intro-header.js +4 -4
  288. package/dist/ui-core/rendering/open-tool-output.js +90 -32
  289. package/dist/ui-core/rendering/open-tool-output.js.map +1 -1
  290. package/dist/ui-core/rendering/theme.d.ts +5 -3
  291. package/dist/ui-core/rendering/theme.js +8 -4
  292. package/dist/ui-core/rendering/theme.js.map +1 -1
  293. package/dist/ui-core/rendering/wordmark.d.ts +2 -2
  294. package/dist/ui-core/rendering/wordmark.js +62 -62
  295. package/dist/ui-core/rendering/wordmark.js.map +1 -1
  296. package/dist/ui-core/state/thinking-copy.d.ts +13 -0
  297. package/dist/ui-core/state/thinking-copy.js +33 -0
  298. package/dist/ui-core/state/thinking-copy.js.map +1 -0
  299. package/dist/ui-core/state/transcript-hydrate.js +20 -0
  300. package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
  301. package/dist/ui-core/state/transcript-reducer.js +140 -62
  302. package/dist/ui-core/state/transcript-reducer.js.map +1 -1
  303. package/dist/ui-core/state/transcript-store.d.ts +10 -0
  304. package/dist/ui-core/state/transcript-store.js +235 -31
  305. package/dist/ui-core/state/transcript-store.js.map +1 -1
  306. package/dist/ui-core/state/transcript-types.d.ts +10 -0
  307. package/dist/ui-core/state/transcript-types.js +1 -0
  308. package/dist/ui-core/state/transcript-types.js.map +1 -1
  309. package/dist/ui-core/state/transcript-window.d.ts +32 -0
  310. package/dist/ui-core/state/transcript-window.js +63 -0
  311. package/dist/ui-core/state/transcript-window.js.map +1 -0
  312. package/dist/version.generated.d.ts +2 -2
  313. package/dist/version.generated.js +2 -2
  314. package/dist/version.generated.js.map +1 -1
  315. package/package.json +1 -1
  316. package/dist/tui-v2/composer/skill-highlight.d.ts +0 -3
  317. package/dist/tui-v2/composer/skill-highlight.js +0 -63
  318. package/dist/tui-v2/composer/skill-highlight.js.map +0 -1
@@ -0,0 +1,310 @@
1
+ import { displayMcpConfigPath, projectMcpConfigPath, writeProjectMcpServer, } from "../../mcp/config-file.js";
2
+ import { formatCatalog, formatStatuses, formatToolLine } from "../../mcp/format.js";
3
+ import { formatMcpToken } from "../../mcp/mentions.js";
4
+ import { mcpSelectionLabel } from "../../mcp/runtime.js";
5
+ import { MCP_SOURCE_LABELS } from "../../mcp/types.js";
6
+ import { composerActionPort } from "../composer/composer-action-port.js";
7
+ const ADD_VALUE = "__mcp_add__";
8
+ const ALL_VALUE = "__mcp_all__";
9
+ const OFF_VALUE = "__mcp_off__";
10
+ function selectionText(services) {
11
+ return mcpSelectionLabel(services.mcp.getState().selection);
12
+ }
13
+ function statusDescription(status) {
14
+ const source = MCP_SOURCE_LABELS[status.source.kind];
15
+ const detail = status.detail ? ` · ${status.detail}` : "";
16
+ return `${status.status} · ${status.transport} · ${status.toolCount} tool${status.toolCount === 1 ? "" : "s"} · ${source} (${status.source.kind}) · ${status.source.path}${detail}`;
17
+ }
18
+ function resolveServer(statuses, query) {
19
+ const needle = query.trim().toLowerCase();
20
+ const exact = statuses.find((status) => status.name.toLowerCase() === needle);
21
+ if (exact)
22
+ return exact;
23
+ const partial = statuses.filter((status) => status.name.toLowerCase().includes(needle));
24
+ return partial.length === 1 ? partial[0] : undefined;
25
+ }
26
+ function selectServer(services, status) {
27
+ if (status.status !== "ready") {
28
+ services.session.notice("warn", `MCP server ${status.name} is ${status.status}${status.detail ? ` · ${status.detail}` : ""} · use /mcp reconnect ${status.name}`);
29
+ return;
30
+ }
31
+ const token = formatMcpToken(status.name);
32
+ if (composerActionPort.insert(`${token} `)) {
33
+ services.focus.focusRegion("composer");
34
+ return;
35
+ }
36
+ services.mcp.selectServer(status.name);
37
+ services.session.notice("info", `type ${token} in your prompt to use this server · ${status.toolCount} live tool${status.toolCount === 1 ? "" : "s"}`);
38
+ }
39
+ function locationLines(services) {
40
+ const target = projectMcpConfigPath();
41
+ const paths = new Set([
42
+ ...services.mcp.getState().snapshot.statuses.map((status) => status.source.path),
43
+ ...services.mcp.getState().snapshot.invalid.map((entry) => entry.source.path),
44
+ ]);
45
+ paths.delete(target);
46
+ return [
47
+ `Project config: ${displayMcpConfigPath(target)}`,
48
+ ...[...paths].sort().map((path) => `Inherited config: ${path}`),
49
+ ];
50
+ }
51
+ const ADD_TEMPLATE = `{
52
+ "docs": {
53
+ "command": "docs-server",
54
+ "args": []
55
+ }
56
+ }`;
57
+ async function addServer(services, supplied = "") {
58
+ const target = projectMcpConfigPath();
59
+ const displayPath = displayMcpConfigPath(target);
60
+ let draft = supplied.trim();
61
+ for (let attempt = 0; attempt < 5; attempt += 1) {
62
+ if (!draft) {
63
+ const input = await services.overlay.openTextEditor({
64
+ title: "Add MCP server",
65
+ prompt: `Paste one server JSON object for ${displayPath} — a named object, or a one-entry {"servers":{…}} fragment.`,
66
+ placeholder: ADD_TEMPLATE,
67
+ submitLabel: "add server",
68
+ ...(attempt > 0 ? { initialValue: draft } : {}),
69
+ });
70
+ if (input === undefined || input.trim() === "")
71
+ return;
72
+ draft = input;
73
+ }
74
+ const written = await writeProjectMcpServer(draft);
75
+ if (!written.ok) {
76
+ services.session.notice("warn", `MCP config not changed · ${written.displayPath} · ${written.error}`);
77
+ // Reopen with the text intact so a long paste is never retyped.
78
+ const retry = await services.overlay.openTextEditor({
79
+ title: "Add MCP server · fix and retry",
80
+ prompt: `${written.error}`,
81
+ initialValue: draft,
82
+ placeholder: ADD_TEMPLATE,
83
+ submitLabel: "add server",
84
+ });
85
+ if (retry === undefined || retry.trim() === "")
86
+ return;
87
+ draft = retry;
88
+ continue;
89
+ }
90
+ const state = await services.mcp.refresh({ force: true });
91
+ const status = state.snapshot.statuses.find((candidate) => candidate.name === written.serverName);
92
+ if (status?.status === "ready")
93
+ selectServer(services, status);
94
+ services.session.notice(status?.status === "ready" ? "info" : "warn", `${written.replaced ? "updated" : "added"} MCP server ${written.serverName} in ${written.displayPath}${status?.status === "ready" ? ` · use ${formatMcpToken(written.serverName)} in your prompt · ${status.toolCount} tool${status.toolCount === 1 ? "" : "s"}` : ` · ${status?.status ?? "not discovered"}${status?.detail ? ` · ${status.detail}` : ""}`}`);
95
+ return;
96
+ }
97
+ }
98
+ function pickerTitle(services) {
99
+ const state = services.mcp.getState();
100
+ const statuses = state.snapshot.statuses;
101
+ const ready = statuses.filter((status) => status.status === "ready").length;
102
+ const target = displayMcpConfigPath(projectMcpConfigPath());
103
+ const progress = state.refreshing
104
+ ? " · connecting…"
105
+ : state.snapshot.createdAt === 0
106
+ ? " · discovering…"
107
+ : "";
108
+ return `MCP · ${target} · ${ready}/${statuses.length} live · ${state.activeToolCount} active tools${progress}`;
109
+ }
110
+ function pickerOptions(services) {
111
+ const state = services.mcp.getState();
112
+ const target = displayMcpConfigPath(projectMcpConfigPath());
113
+ return [
114
+ {
115
+ value: ADD_VALUE,
116
+ label: "+ add MCP server",
117
+ description: `paste one JSON server object · merge into ${target}`,
118
+ },
119
+ {
120
+ value: OFF_VALUE,
121
+ label: "MCP tools off",
122
+ description: "default · hide MCP tools from agent requests for this session",
123
+ active: state.selection.mode === "off",
124
+ },
125
+ {
126
+ value: ALL_VALUE,
127
+ label: "all live servers",
128
+ description: "expose every ready MCP tool for this session",
129
+ active: state.selection.mode === "all",
130
+ },
131
+ ...state.snapshot.statuses.map((status) => ({
132
+ value: status.name,
133
+ label: `${status.status === "ready" ? "live" : status.status} · ${status.name}`,
134
+ description: statusDescription(status),
135
+ active: state.selection.mode === "servers" &&
136
+ state.selection.serverNames.includes(status.name),
137
+ })),
138
+ ];
139
+ }
140
+ /**
141
+ * Opens immediately from the current snapshot: a remote server can take up to
142
+ * the 30s connect timeout, and blocking the picker on that looked like a hang.
143
+ * Rows and title are replaced in place once discovery settles.
144
+ */
145
+ function openPicker(services) {
146
+ services.overlay.openPicker({
147
+ title: pickerTitle(services),
148
+ searchDescription: true,
149
+ twoLine: true,
150
+ options: pickerOptions(services),
151
+ }, (value) => {
152
+ const statuses = services.mcp.getState().snapshot.statuses;
153
+ services.overlay.close();
154
+ if (value === ADD_VALUE) {
155
+ void addServer(services);
156
+ return;
157
+ }
158
+ if (value === ALL_VALUE) {
159
+ services.mcp.selectAll();
160
+ services.session.notice("info", "MCP selection · all live servers · session only");
161
+ return;
162
+ }
163
+ if (value === OFF_VALUE) {
164
+ services.mcp.selectOff();
165
+ services.session.notice("info", "MCP tools off for this session");
166
+ return;
167
+ }
168
+ const status = statuses.find((candidate) => candidate.name === value);
169
+ if (status)
170
+ selectServer(services, status);
171
+ });
172
+ }
173
+ function refreshOpenPicker(services) {
174
+ if (services.overlay.getState().kind !== "picker")
175
+ return;
176
+ services.overlay.replacePickerOptions(pickerOptions(services), pickerTitle(services));
177
+ }
178
+ function catalogText(services) {
179
+ const state = services.mcp.getState();
180
+ const discovery = state.snapshot;
181
+ const warnings = services.mcp
182
+ .getState()
183
+ .snapshot.statuses.filter((status) => status.detail)
184
+ .map((status) => ` ${status.name}: ${status.detail}`);
185
+ return [
186
+ ...locationLines(services),
187
+ "",
188
+ `Selection: ${selectionText(services)} · active tools: ${state.activeToolCount} · catalog: ${state.catalogSignature}`,
189
+ state.refreshing ? "Refresh: in progress" : "Refresh: idle",
190
+ state.error ? `Runtime warning: ${state.error}` : "",
191
+ "",
192
+ formatCatalog(discovery),
193
+ ...(warnings.length > 0 ? ["", "Server details:", ...warnings] : []),
194
+ ]
195
+ .filter((line, index, lines) => line !== "" || lines[index - 1] !== "")
196
+ .join("\n")
197
+ .trim();
198
+ }
199
+ function toolText(services, serverName) {
200
+ const tools = services.mcp
201
+ .getState()
202
+ .snapshot.tools.filter((tool) => !serverName || tool.serverName === serverName);
203
+ if (tools.length === 0) {
204
+ return serverName
205
+ ? `No live tools are available from MCP server ${serverName}.`
206
+ : "No live MCP tools are available.";
207
+ }
208
+ return tools.map(formatToolLine).join("\n");
209
+ }
210
+ async function reconnect(services, query) {
211
+ const statuses = services.mcp.getState().snapshot.statuses;
212
+ const status = resolveServer(statuses, query);
213
+ if (!status) {
214
+ services.session.notice("warn", query
215
+ ? `no unique MCP server matching "${query}"`
216
+ : "usage: /mcp reconnect <server>");
217
+ return;
218
+ }
219
+ services.session.notice("info", `reconnecting MCP server ${status.name}…`);
220
+ const state = await services.mcp.reconnect(status.name);
221
+ const next = state.snapshot.statuses.find((candidate) => candidate.name === status.name);
222
+ if (next?.status === "ready") {
223
+ services.session.notice("info", `MCP server ${status.name} live · ${next.toolCount} tool${next.toolCount === 1 ? "" : "s"}`);
224
+ }
225
+ else {
226
+ services.session.notice("warn", `MCP server ${status.name} ${next?.status ?? "unavailable"}${next?.detail ? ` · ${next.detail}` : ""}`);
227
+ }
228
+ }
229
+ export async function handleMcp(services, invocation) {
230
+ const args = invocation.args.trim();
231
+ const [rawCommand = "", ...rest] = args.split(/\s+/);
232
+ const command = rawCommand.toLowerCase();
233
+ const tail = rest.join(" ").trim();
234
+ if (!command) {
235
+ openPicker(services);
236
+ await services.mcp.ensureReady();
237
+ refreshOpenPicker(services);
238
+ return;
239
+ }
240
+ await services.mcp.ensureReady();
241
+ if (command === "add" || command === "new") {
242
+ await addServer(services, tail);
243
+ return;
244
+ }
245
+ if (command === "locations" || command === "location" || command === "paths") {
246
+ services.overlay.openPager("MCP configuration locations", locationLines(services).join("\n"), undefined, undefined, "plain");
247
+ return;
248
+ }
249
+ if (command === "all" || command === "auto" || command === "on") {
250
+ services.mcp.selectAll();
251
+ services.session.notice("info", "MCP selection · all live servers · session only");
252
+ return;
253
+ }
254
+ if (command === "off" || command === "none") {
255
+ services.mcp.selectOff();
256
+ services.session.notice("info", "MCP tools off for this session");
257
+ return;
258
+ }
259
+ if (command === "list" || command === "catalog") {
260
+ services.overlay.openPager("MCP catalog", catalogText(services), undefined, undefined, "plain");
261
+ return;
262
+ }
263
+ if (command === "status") {
264
+ const state = services.mcp.getState();
265
+ services.overlay.openPager("MCP status", [
266
+ ...locationLines(services),
267
+ "",
268
+ `Selection: ${selectionText(services)} · ${state.activeToolCount} active tools`,
269
+ "",
270
+ formatStatuses(state.snapshot.statuses),
271
+ ...(state.snapshot.invalid.length > 0
272
+ ? [
273
+ "",
274
+ "Invalid configurations:",
275
+ ...state.snapshot.invalid.map((entry) => ` ${entry.name} · ${entry.source.path} · ${entry.errors.join("; ")}`),
276
+ ]
277
+ : []),
278
+ ].join("\n"), undefined, undefined, "plain");
279
+ return;
280
+ }
281
+ if (command === "tools") {
282
+ const server = tail
283
+ ? resolveServer(services.mcp.getState().snapshot.statuses, tail)
284
+ : undefined;
285
+ if (tail && !server) {
286
+ services.session.notice("warn", `no unique MCP server matching "${tail}"`);
287
+ return;
288
+ }
289
+ services.overlay.openPager(server ? `MCP tools · ${server.name}` : "MCP tools", toolText(services, server?.name), undefined, undefined, "plain");
290
+ return;
291
+ }
292
+ if (command === "refresh" || command === "reload") {
293
+ services.session.notice("info", "refreshing MCP configurations and live tools…");
294
+ const state = await services.mcp.refresh({ force: true });
295
+ const ready = state.snapshot.statuses.filter((status) => status.status === "ready").length;
296
+ services.session.notice(state.error ? "warn" : "info", `MCP refresh · ${ready}/${state.snapshot.statuses.length} live · ${state.activeToolCount} active tools${state.error ? ` · ${state.error}` : ""}`);
297
+ return;
298
+ }
299
+ if (command === "reconnect") {
300
+ await reconnect(services, tail);
301
+ return;
302
+ }
303
+ const status = resolveServer(services.mcp.getState().snapshot.statuses, args);
304
+ if (!status) {
305
+ services.session.notice("warn", `no unique MCP server matching "${args}" · use /mcp to browse or /mcp list for details`);
306
+ return;
307
+ }
308
+ selectServer(services, status);
309
+ }
310
+ //# sourceMappingURL=mcp-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-commands.js","sourceRoot":"","sources":["../../../src/ui-core/commands/mcp-commands.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAwB,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAEzE,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,SAAS,GAAG,aAAa,CAAC;AAEhC,SAAS,aAAa,CAAC,QAAqB;IAC1C,OAAO,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAuB;IAChD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,OAAO,GAAG,MAAM,CAAC,MAAM,MAAM,MAAM,CAAC,SAAS,MAAM,MAAM,CAAC,SAAS,QAAQ,MAAM,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC;AACtL,CAAC;AAED,SAAS,aAAa,CACpB,QAAoC,EACpC,KAAa;IAEb,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;IAC9E,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CACzC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC3C,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,QAAqB,EAAE,MAAuB;IAClE,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC9B,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EACN,cAAc,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,yBAAyB,MAAM,CAAC,IAAI,EAAE,CACjI,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,kBAAkB,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;QAC3C,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EACN,QAAQ,KAAK,wCAAwC,MAAM,CAAC,SAAS,aAAa,MAAM,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CACtH,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,QAAqB;IAC1C,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS;QAC5B,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;QAChF,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC;KAC9E,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO;QACL,mBAAmB,oBAAoB,CAAC,MAAM,CAAC,EAAE;QACjD,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,qBAAqB,IAAI,EAAE,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG;;;;;EAKnB,CAAC;AAEH,KAAK,UAAU,SAAS,CAAC,QAAqB,EAAE,QAAQ,GAAG,EAAE;IAC3D,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;IACtC,MAAM,WAAW,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC5B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC;gBAClD,KAAK,EAAE,gBAAgB;gBACvB,MAAM,EAAE,oCAAoC,WAAW,6DAA6D;gBACpH,WAAW,EAAE,YAAY;gBACzB,WAAW,EAAE,YAAY;gBACzB,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChD,CAAC,CAAC;YACH,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,OAAO;YACvD,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EACN,4BAA4B,OAAO,CAAC,WAAW,MAAM,OAAO,CAAC,KAAK,EAAE,CACrE,CAAC;YACF,gEAAgE;YAChE,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC;gBAClD,KAAK,EAAE,gCAAgC;gBACvC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE;gBAC1B,YAAY,EAAE,KAAK;gBACnB,WAAW,EAAE,YAAY;gBACzB,WAAW,EAAE,YAAY;aAC1B,CAAC,CAAC;YACH,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,OAAO;YACvD,KAAK,GAAG,KAAK,CAAC;YACd,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CACzC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,UAAU,CACrD,CAAC;QACF,IAAI,MAAM,EAAE,MAAM,KAAK,OAAO;YAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/D,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAC5C,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,eAAe,OAAO,CAAC,UAAU,OAAO,OAAO,CAAC,WAAW,GAAG,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,qBAAqB,MAAM,CAAC,SAAS,QAAQ,MAAM,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,MAAM,IAAI,gBAAgB,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAC9V,CAAC;QACF,OAAO;IACT,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAAqB;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IAC5E,MAAM,MAAM,GAAG,oBAAoB,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU;QAC/B,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,KAAK,CAAC;YAC9B,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,EAAE,CAAC;IACT,OAAO,SAAS,MAAM,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,WAAW,KAAK,CAAC,eAAe,gBAAgB,QAAQ,EAAE,CAAC;AACjH,CAAC;AAED,SAAS,aAAa,CAAC,QAAqB;IAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,oBAAoB,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC5D,OAAO;QACL;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,kBAAkB;YACzB,WAAW,EAAE,6CAA6C,MAAM,EAAE;SACnE;QACD;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,eAAe;YACtB,WAAW,EAAE,+DAA+D;YAC5E,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,KAAK;SACvC;QACD;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,kBAAkB;YACzB,WAAW,EAAE,8CAA8C;YAC3D,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,KAAK;SACvC;QACD,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC1C,KAAK,EAAE,MAAM,CAAC,IAAI;YAClB,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,MAAM,MAAM,CAAC,IAAI,EAAE;YAC/E,WAAW,EAAE,iBAAiB,CAAC,MAAM,CAAC;YACtC,MAAM,EACJ,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS;gBAClC,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;SACpD,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,QAAqB;IACvC,QAAQ,CAAC,OAAO,CAAC,UAAU,CACzB;QACE,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC;QAC5B,iBAAiB,EAAE,IAAI;QACvB,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC;KACjC,EACD,CAAC,KAAK,EAAE,EAAE;QACR,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC3D,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACzB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,iDAAiD,CAAC,CAAC;YACnF,OAAO;QACT,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACzB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAAC;YAClE,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;QACtE,IAAI,MAAM;YAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAqB;IAC9C,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO;IAC1D,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CACnC,aAAa,CAAC,QAAQ,CAAC,EACvB,WAAW,CAAC,QAAQ,CAAC,CACtB,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,QAAqB;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;IACtC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC;IACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG;SAC1B,QAAQ,EAAE;SACV,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;SACnD,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,OAAO;QACL,GAAG,aAAa,CAAC,QAAQ,CAAC;QAC1B,EAAE;QACF,cAAc,aAAa,CAAC,QAAQ,CAAC,oBAAoB,KAAK,CAAC,eAAe,eAAe,KAAK,CAAC,gBAAgB,EAAE;QACrH,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,eAAe;QAC3D,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAoB,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;QACpD,EAAE;QACF,aAAa,CAAC,SAAS,CAAC;QACxB,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE;SACE,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;SACtE,IAAI,CAAC,IAAI,CAAC;SACV,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,QAAQ,CAAC,QAAqB,EAAE,UAAmB;IAC1D,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG;SACvB,QAAQ,EAAE;SACV,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IAClF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,UAAU;YACf,CAAC,CAAC,+CAA+C,UAAU,GAAG;YAC9D,CAAC,CAAC,kCAAkC,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,QAAqB,EACrB,KAAa;IAEb,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAC3D,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EACN,KAAK;YACH,CAAC,CAAC,kCAAkC,KAAK,GAAG;YAC5C,CAAC,CAAC,gCAAgC,CACrC,CAAC;QACF,OAAO;IACT,CAAC;IACD,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,2BAA2B,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;IACzF,IAAI,IAAI,EAAE,MAAM,KAAK,OAAO,EAAE,CAAC;QAC7B,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EACN,cAAc,MAAM,CAAC,IAAI,WAAW,IAAI,CAAC,SAAS,QAAQ,IAAI,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAC5F,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EACN,cAAc,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,MAAM,IAAI,aAAa,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACvG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAqB,EACrB,UAA6B;IAE7B,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACpC,MAAM,CAAC,UAAU,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrB,MAAM,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACjC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;QAC3C,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,UAAU,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QAC7E,QAAQ,CAAC,OAAO,CAAC,SAAS,CACxB,6BAA6B,EAC7B,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAClC,SAAS,EACT,SAAS,EACT,OAAO,CACR,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAChE,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACzB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,iDAAiD,CAAC,CAAC;QACnF,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QAC5C,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACzB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gCAAgC,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAChD,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAChG,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACtC,QAAQ,CAAC,OAAO,CAAC,SAAS,CACxB,YAAY,EACZ;YACE,GAAG,aAAa,CAAC,QAAQ,CAAC;YAC1B,EAAE;YACF,cAAc,aAAa,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,eAAe,eAAe;YAC/E,EAAE;YACF,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACvC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBACnC,CAAC,CAAC;oBACE,EAAE;oBACF,yBAAyB;oBACzB,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAC3B,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxE;iBACF;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,SAAS,EACT,SAAS,EACT,OAAO,CACR,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,IAAI;YACjB,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;YAChE,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,kCAAkC,IAAI,GAAG,CAAC,CAAC;YAC3E,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,OAAO,CAAC,SAAS,CACxB,MAAM,CAAC,CAAC,CAAC,eAAe,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,EACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAChC,SAAS,EACT,SAAS,EACT,OAAO,CACR,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QAClD,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,+CAA+C,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;QAC3F,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAC7B,iBAAiB,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,WAAW,KAAK,CAAC,eAAe,gBAAgB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjJ,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChC,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC9E,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,MAAM,EACN,kCAAkC,IAAI,iDAAiD,CACxF,CAAC;QACF,OAAO;IACT,CAAC;IACD,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC"}
@@ -21,5 +21,5 @@ export declare function handleSearch(services: AppServices, invocation: CommandI
21
21
  export declare function handleReasoning(services: AppServices, invocation: CommandInvocation): void;
22
22
  export declare function handleHistory(services: AppServices, invocation?: CommandInvocation): Promise<void>;
23
23
  export declare function handlePermissions(services: AppServices, invocation: CommandInvocation): void;
24
- export declare function handleOutput(services: AppServices, invocation: CommandInvocation): void;
24
+ export declare function handleOutput(services: AppServices, invocation: CommandInvocation): Promise<void>;
25
25
  export declare function handlePlanPager(services: AppServices): void;
@@ -810,6 +810,9 @@ function warnUnacceptedEffort(services, effort) {
810
810
  }
811
811
  export async function handleHistory(services, invocation) {
812
812
  const rawArgs = invocation?.args?.trim() ?? "";
813
+ const { listLiveSessionRuntimes } = await import("../../session-runtime/discovery.js");
814
+ const runtimes = await listLiveSessionRuntimes().catch(() => []);
815
+ const runtimeById = new Map(runtimes.map((runtime) => [runtime.sessionId, runtime]));
813
816
  if (rawArgs) {
814
817
  const [sub, ...rest] = rawArgs.split(/\s+/);
815
818
  const subLower = sub?.toLowerCase() ?? "";
@@ -819,6 +822,10 @@ export async function handleHistory(services, invocation) {
819
822
  services.session.notice("warn", "usage: /history delete <session-id>");
820
823
  return;
821
824
  }
825
+ if (runtimeById.has(finalId)) {
826
+ services.session.notice("warn", "detach or exit the live session before deleting it");
827
+ return;
828
+ }
822
829
  const result = await deleteSession(finalId);
823
830
  services.session.notice(result.deleted ? "info" : "warn", result.deleted ? `deleted ${finalId}` : result.detail);
824
831
  return;
@@ -828,13 +835,15 @@ export async function handleHistory(services, invocation) {
828
835
  const currentMessages = services.session.messages;
829
836
  const currentId = services.session.sessionId;
830
837
  const currentTitle = services.session.getState().title;
831
- if (sessions.length === 0 && currentMessages.length === 0) {
838
+ if (sessions.length === 0 &&
839
+ runtimes.filter((runtime) => runtime.sessionId !== currentId).length === 0 &&
840
+ currentMessages.length === 0) {
832
841
  services.session.notice("info", "no session history yet — chat once and it will appear here with an AI title");
833
842
  return;
834
843
  }
835
- // Live session once at the top — never also list the same id below
836
- // (that looked like two copies of one chat with different item counts).
837
- const otherSessions = sessions.filter((s) => s.id !== currentId);
844
+ const otherSessions = sessions.filter((session) => session.id !== currentId);
845
+ const historyIds = new Set(sessions.map((session) => session.id));
846
+ const runtimeOnly = runtimes.filter((runtime) => runtime.sessionId !== currentId && !historyIds.has(runtime.sessionId));
838
847
  const liveVisualCount = conversationItemCount(services.transcript.getState());
839
848
  const options = [
840
849
  {
@@ -845,20 +854,36 @@ export async function handleHistory(services, invocation) {
845
854
  : `id ${currentId} · now · empty session · this window`,
846
855
  active: true,
847
856
  },
857
+ ...runtimeOnly.map((runtime) => ({
858
+ value: runtime.sessionId,
859
+ label: runtime.title?.trim() || "Live session",
860
+ description: [
861
+ `id ${runtime.sessionId}`,
862
+ runtime.busy ? "agent running" : "live",
863
+ runtime.attached ? "attached elsewhere" : "detached",
864
+ shortCwd(runtime.cwd) ? `in ${shortCwd(runtime.cwd)}` : "",
865
+ ]
866
+ .filter(Boolean)
867
+ .join(" · "),
868
+ active: false,
869
+ })),
848
870
  ...otherSessions.map((session) => {
871
+ const runtime = runtimeById.get(session.id);
849
872
  const count = session.itemCount;
850
873
  const date = session.updatedAt ?? session.createdAt;
851
- const when = relativeTime(date) || "some time ago";
852
- const stamp = date.slice(0, 16).replace("T", " ");
853
- const where = shortCwd(session.cwd);
854
874
  const title = (session.name && session.name.trim()) || "Untitled chat";
855
- // Two-line card: title on top; meta chips underneath (full session id).
856
875
  const meta = [
857
876
  `id ${session.id}`,
858
- when,
859
- stamp,
877
+ runtime
878
+ ? runtime.busy
879
+ ? "agent running"
880
+ : runtime.attached
881
+ ? "live · attached elsewhere"
882
+ : "live · detached"
883
+ : relativeTime(date) || "some time ago",
884
+ date.slice(0, 16).replace("T", " "),
860
885
  `${count} item${count === 1 ? "" : "s"}`,
861
- where ? `in ${where}` : "",
886
+ shortCwd(session.cwd) ? `in ${shortCwd(session.cwd)}` : "",
862
887
  ]
863
888
  .filter(Boolean)
864
889
  .join(" · ");
@@ -878,10 +903,17 @@ export async function handleHistory(services, invocation) {
878
903
  });
879
904
  return;
880
905
  }
906
+ if (runtimeById.has(value)) {
907
+ services.toast.warn("cannot delete a live session", {
908
+ key: "history-delete",
909
+ });
910
+ return;
911
+ }
881
912
  const index = liveOptions.findIndex((option) => option.value === value);
882
913
  if (index === -1)
883
914
  return;
884
- const label = liveOptions[index].label;
915
+ const option = liveOptions[index];
916
+ const label = option.label;
885
917
  liveOptions.splice(index, 1);
886
918
  services.overlay.replacePickerOptions([...liveOptions]);
887
919
  services.toast.info(`deleting ${label}…`, { key: "history-delete" });
@@ -893,6 +925,10 @@ export async function handleHistory(services, invocation) {
893
925
  });
894
926
  }
895
927
  else {
928
+ if (!liveOptions.some((candidate) => candidate.value === value)) {
929
+ liveOptions.splice(Math.min(index, liveOptions.length), 0, option);
930
+ services.overlay.replacePickerOptions([...liveOptions]);
931
+ }
896
932
  services.toast.error(`could not delete ${label} · ${result.detail}`, {
897
933
  key: "history-delete",
898
934
  });
@@ -913,29 +949,36 @@ export async function handleHistory(services, invocation) {
913
949
  services.overlay.close();
914
950
  return;
915
951
  }
916
- // Refresh only the selected record so a session changed by another
917
- // process while the picker was open cannot be resumed stale. This work
918
- // happens after selection and does not delay opening /history.
919
952
  const session = await getSession(value);
920
- if (!session) {
953
+ const runtime = runtimeById.get(value);
954
+ if (!session && !runtime) {
921
955
  services.session.notice("warn", "session not found");
922
956
  services.overlay.close();
923
957
  return;
924
958
  }
925
- if (session.id === currentId) {
959
+ if (value === currentId) {
926
960
  services.session.notice("info", "already on this session");
927
961
  services.overlay.close();
928
962
  return;
929
963
  }
930
- // Persist the outgoing live session before rebinding id, so work is not
931
- // lost and we don't orphan a half-saved row under the old id.
932
964
  if (currentMessages.length > 0) {
933
- try {
934
- await services.session.persistNow();
935
- }
936
- catch {
937
- /* best-effort */
938
- }
965
+ await services.session.persistNow().catch(() => undefined);
966
+ }
967
+ const state = services.session.getState();
968
+ const busy = state.running ||
969
+ state.compacting ||
970
+ state.queued.length > 0 ||
971
+ state.responder.running > 0 ||
972
+ state.responder.ready > 0 ||
973
+ state.responder.delivered > 0;
974
+ if (services.requestSessionSwitch(value, !busy)) {
975
+ services.overlay.close();
976
+ return;
977
+ }
978
+ if (!session) {
979
+ services.session.notice("warn", `session is live in another runtime · use clai --resume ${value}`);
980
+ services.overlay.close();
981
+ return;
939
982
  }
940
983
  const outcome = await applySessionResume(services, session);
941
984
  for (const entry of resumeNotices(outcome)) {
@@ -978,7 +1021,7 @@ export function handlePermissions(services, invocation) {
978
1021
  services.overlay.close();
979
1022
  });
980
1023
  }
981
- export function handleOutput(services, invocation) {
1024
+ export async function handleOutput(services, invocation) {
982
1025
  const state = services.transcript.getState();
983
1026
  const toolItems = [...state.byId.values()].filter((item) => item.kind === "tool");
984
1027
  if (toolItems.length === 0) {
@@ -1012,7 +1055,7 @@ export function handleOutput(services, invocation) {
1012
1055
  ? toolItems.find((t) => t.toolCallId === arg || t.id === arg)
1013
1056
  : toolItems.at(-1);
1014
1057
  if (target)
1015
- void openToolOutputPager(services, target);
1058
+ await openToolOutputPager(services, target);
1016
1059
  else
1017
1060
  services.session.notice("info", arg ? `no tool output: ${arg}` : "no tool output yet");
1018
1061
  }