@songsid/agend 2.3.4-beta.5 → 2.3.5-alpha.2

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 (386) hide show
  1. package/README.md +2 -0
  2. package/README.zh-TW.md +2 -0
  3. package/THIRD_PARTY_NOTICES.md +53 -0
  4. package/dist/agent-endpoint.d.ts +5 -1
  5. package/dist/agent-endpoint.js +12 -2
  6. package/dist/agent-endpoint.js.map +1 -1
  7. package/dist/backend/claude-code.d.ts +18 -12
  8. package/dist/backend/claude-code.js +225 -136
  9. package/dist/backend/claude-code.js.map +1 -1
  10. package/dist/backend/codex-package.d.ts +5 -2
  11. package/dist/backend/codex-package.js +1 -5
  12. package/dist/backend/codex-package.js.map +1 -1
  13. package/dist/backend/codex.d.ts +136 -113
  14. package/dist/backend/codex.js +1271 -1219
  15. package/dist/backend/codex.js.map +1 -1
  16. package/dist/backend/grok-model-cache.d.ts +7 -0
  17. package/dist/backend/grok-model-cache.js +65 -0
  18. package/dist/backend/grok-model-cache.js.map +1 -0
  19. package/dist/backend/grok.d.ts +2 -0
  20. package/dist/backend/grok.js +22 -0
  21. package/dist/backend/grok.js.map +1 -1
  22. package/dist/backend/native-pane.d.ts +9 -0
  23. package/dist/backend/native-pane.js +59 -0
  24. package/dist/backend/native-pane.js.map +1 -0
  25. package/dist/backend/types.d.ts +7 -0
  26. package/dist/backend/types.js.map +1 -1
  27. package/dist/channel/ipc-bridge.d.ts +2 -0
  28. package/dist/channel/mcp-tools.js +1 -1
  29. package/dist/channel/mcp-tools.js.map +1 -1
  30. package/dist/cli.js +6 -2
  31. package/dist/cli.js.map +1 -1
  32. package/dist/config-validator.js +59 -0
  33. package/dist/config-validator.js.map +1 -1
  34. package/dist/config.js +16 -0
  35. package/dist/config.js.map +1 -1
  36. package/dist/daemon.d.ts +62 -5
  37. package/dist/daemon.js +760 -240
  38. package/dist/daemon.js.map +1 -1
  39. package/dist/delivery-consumed-watch.d.ts +15 -3
  40. package/dist/delivery-consumed-watch.js +23 -1
  41. package/dist/delivery-consumed-watch.js.map +1 -1
  42. package/dist/delivery-outbox.d.ts +5 -0
  43. package/dist/delivery-outbox.js +32 -4
  44. package/dist/delivery-outbox.js.map +1 -1
  45. package/dist/delivery-reconciliation.d.ts +2 -35
  46. package/dist/delivery-reconciliation.js +2 -156
  47. package/dist/delivery-reconciliation.js.map +1 -1
  48. package/dist/fleet-context.d.ts +2 -2
  49. package/dist/fleet-level-config.d.ts +1 -1
  50. package/dist/fleet-level-config.js +2 -0
  51. package/dist/fleet-level-config.js.map +1 -1
  52. package/dist/fleet-manager.d.ts +125 -2
  53. package/dist/fleet-manager.js +1157 -27
  54. package/dist/fleet-manager.js.map +1 -1
  55. package/dist/fleet-windows-runtime.d.ts +92 -0
  56. package/dist/fleet-windows-runtime.js +373 -0
  57. package/dist/fleet-windows-runtime.js.map +1 -0
  58. package/dist/instance-config-impact.js +4 -0
  59. package/dist/instance-config-impact.js.map +1 -1
  60. package/dist/instance-lifecycle.d.ts +20 -3
  61. package/dist/instance-lifecycle.js +358 -156
  62. package/dist/instance-lifecycle.js.map +1 -1
  63. package/dist/local-pane-endpoint.d.ts +46 -0
  64. package/dist/local-pane-endpoint.js +189 -0
  65. package/dist/local-pane-endpoint.js.map +1 -0
  66. package/dist/local-pane-launcher.d.ts +2 -0
  67. package/dist/local-pane-launcher.js +38 -0
  68. package/dist/local-pane-launcher.js.map +1 -0
  69. package/dist/local-pane-stage.ps1 +101 -0
  70. package/dist/locale.js +34 -0
  71. package/dist/locale.js.map +1 -1
  72. package/dist/model-catalog-defaults.d.ts +14 -0
  73. package/dist/model-catalog-defaults.js +20 -0
  74. package/dist/model-catalog-defaults.js.map +1 -0
  75. package/dist/native-agent-admission.d.ts +7 -0
  76. package/dist/native-agent-admission.js +26 -0
  77. package/dist/native-agent-admission.js.map +1 -0
  78. package/dist/native-daemon-client.d.ts +13 -0
  79. package/dist/native-daemon-client.js +28 -0
  80. package/dist/native-daemon-client.js.map +1 -0
  81. package/dist/native-instance-api.d.ts +14 -0
  82. package/dist/native-instance-api.js +205 -0
  83. package/dist/native-instance-api.js.map +1 -0
  84. package/dist/native-instance-input.d.ts +84 -0
  85. package/dist/native-instance-input.js +54 -0
  86. package/dist/native-instance-input.js.map +1 -0
  87. package/dist/native-instance-registry.d.ts +32 -0
  88. package/dist/native-instance-registry.js +105 -0
  89. package/dist/native-instance-registry.js.map +1 -0
  90. package/dist/native-mcp.d.ts +40 -0
  91. package/dist/native-mcp.js +278 -0
  92. package/dist/native-mcp.js.map +1 -0
  93. package/dist/native-model-catalog.d.ts +5 -0
  94. package/dist/native-model-catalog.js +76 -0
  95. package/dist/native-model-catalog.js.map +1 -0
  96. package/dist/native-pane-crash-budget.d.ts +20 -0
  97. package/dist/native-pane-crash-budget.js +60 -0
  98. package/dist/native-pane-crash-budget.js.map +1 -0
  99. package/dist/native-pane-create.d.ts +26 -0
  100. package/dist/native-pane-create.js +53 -0
  101. package/dist/native-pane-create.js.map +1 -0
  102. package/dist/native-pane-lifecycle.d.ts +65 -0
  103. package/dist/native-pane-lifecycle.js +227 -0
  104. package/dist/native-pane-lifecycle.js.map +1 -0
  105. package/dist/native-pane-manager.d.ts +58 -0
  106. package/dist/native-pane-manager.js +563 -0
  107. package/dist/native-pane-manager.js.map +1 -0
  108. package/dist/native-pane-output-log.d.ts +15 -0
  109. package/dist/native-pane-output-log.js +108 -0
  110. package/dist/native-pane-output-log.js.map +1 -0
  111. package/dist/native-pane-reconciliation.d.ts +4 -0
  112. package/dist/native-pane-reconciliation.js +40 -0
  113. package/dist/native-pane-reconciliation.js.map +1 -0
  114. package/dist/native-pane-recovery.d.ts +12 -0
  115. package/dist/native-pane-recovery.js +10 -0
  116. package/dist/native-pane-recovery.js.map +1 -0
  117. package/dist/native-pane-tools.d.ts +2 -0
  118. package/dist/native-pane-tools.js +14 -0
  119. package/dist/native-pane-tools.js.map +1 -0
  120. package/dist/needs-you-hub.d.ts +2 -0
  121. package/dist/needs-you-hub.js +1 -0
  122. package/dist/needs-you-hub.js.map +1 -1
  123. package/dist/needs-you.d.ts +12 -1
  124. package/dist/needs-you.js +8 -1
  125. package/dist/needs-you.js.map +1 -1
  126. package/dist/outbound-handlers.d.ts +16 -2
  127. package/dist/outbound-handlers.js +67 -3
  128. package/dist/outbound-handlers.js.map +1 -1
  129. package/dist/outbound-schemas.d.ts +38 -0
  130. package/dist/outbound-schemas.js +12 -0
  131. package/dist/outbound-schemas.js.map +1 -1
  132. package/dist/pane-port.d.ts +107 -0
  133. package/dist/pane-port.js +2 -0
  134. package/dist/pane-port.js.map +1 -0
  135. package/dist/runtime-api.d.ts +8 -0
  136. package/dist/runtime-api.js +96 -0
  137. package/dist/runtime-api.js.map +1 -0
  138. package/dist/runtime-assets/@xterm/addon-serialize/LICENSE +21 -0
  139. package/dist/runtime-assets/@xterm/addon-serialize/lib/addon-serialize.js +2 -0
  140. package/dist/runtime-assets/@xterm/addon-serialize/lib/addon-serialize.mjs +19 -0
  141. package/dist/runtime-assets/@xterm/addon-serialize/package.json +29 -0
  142. package/dist/runtime-assets/@xterm/headless/LICENSE +21 -0
  143. package/dist/runtime-assets/@xterm/headless/lib-headless/xterm-headless.js +2 -0
  144. package/dist/runtime-assets/@xterm/headless/lib-headless/xterm-headless.mjs +46 -0
  145. package/dist/runtime-assets/@xterm/headless/package.json +29 -0
  146. package/dist/runtime-assets/node-pty/CONPTY-LICENSE +21 -0
  147. package/dist/runtime-assets/node-pty/CONPTY-NOTICE.md +503 -0
  148. package/dist/runtime-assets/node-pty/LICENSE +69 -0
  149. package/dist/runtime-assets/node-pty/lib/conpty_console_list_agent.js +16 -0
  150. package/dist/runtime-assets/node-pty/lib/eventEmitter2.js +47 -0
  151. package/dist/runtime-assets/node-pty/lib/index.js +52 -0
  152. package/dist/runtime-assets/node-pty/lib/interfaces.js +7 -0
  153. package/dist/runtime-assets/node-pty/lib/shared/conout.js +11 -0
  154. package/dist/runtime-assets/node-pty/lib/terminal.js +190 -0
  155. package/dist/runtime-assets/node-pty/lib/types.js +7 -0
  156. package/dist/runtime-assets/node-pty/lib/unixTerminal.js +346 -0
  157. package/dist/runtime-assets/node-pty/lib/utils.js +39 -0
  158. package/dist/runtime-assets/node-pty/lib/windowsConoutConnection.js +125 -0
  159. package/dist/runtime-assets/node-pty/lib/windowsPtyAgent.js +320 -0
  160. package/dist/runtime-assets/node-pty/lib/windowsTerminal.js +199 -0
  161. package/dist/runtime-assets/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  162. package/dist/runtime-assets/node-pty/package.json +64 -0
  163. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  164. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  165. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
  166. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  167. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  168. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  169. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty.node +0 -0
  170. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
  171. package/dist/runtime-bundle.d.ts +17 -0
  172. package/dist/runtime-bundle.js +147 -0
  173. package/dist/runtime-bundle.js.map +1 -0
  174. package/dist/runtime-cli.d.ts +2 -0
  175. package/dist/runtime-cli.js +117 -0
  176. package/dist/runtime-cli.js.map +1 -0
  177. package/dist/runtime-client-store.d.ts +49 -0
  178. package/dist/runtime-client-store.js +292 -0
  179. package/dist/runtime-client-store.js.map +1 -0
  180. package/dist/runtime-client.d.ts +100 -0
  181. package/dist/runtime-client.js +700 -0
  182. package/dist/runtime-client.js.map +1 -0
  183. package/dist/runtime-coordinator.d.ts +82 -0
  184. package/dist/runtime-coordinator.js +864 -0
  185. package/dist/runtime-coordinator.js.map +1 -0
  186. package/dist/runtime-pane-assets.d.ts +17 -0
  187. package/dist/runtime-pane-assets.js +23 -0
  188. package/dist/runtime-pane-assets.js.map +1 -0
  189. package/dist/runtime-pane-boot.d.ts +2 -0
  190. package/dist/runtime-pane-boot.js +24 -0
  191. package/dist/runtime-pane-boot.js.map +1 -0
  192. package/dist/runtime-pane-codex-index.d.ts +1 -0
  193. package/dist/runtime-pane-codex-index.js +47 -0
  194. package/dist/runtime-pane-codex-index.js.map +1 -0
  195. package/dist/runtime-pane-config.d.ts +16 -0
  196. package/dist/runtime-pane-config.js +54 -0
  197. package/dist/runtime-pane-config.js.map +1 -0
  198. package/dist/runtime-pane-host.d.ts +43 -0
  199. package/dist/runtime-pane-host.js +403 -0
  200. package/dist/runtime-pane-host.js.map +1 -0
  201. package/dist/runtime-pane-job-owner.d.ts +1 -0
  202. package/dist/runtime-pane-job-owner.js +29 -0
  203. package/dist/runtime-pane-job-owner.js.map +1 -0
  204. package/dist/runtime-pane-job.ps1 +116 -0
  205. package/dist/runtime-pane-link.d.ts +40 -0
  206. package/dist/runtime-pane-link.js +246 -0
  207. package/dist/runtime-pane-link.js.map +1 -0
  208. package/dist/runtime-pane-mcp-protocol.d.ts +32 -0
  209. package/dist/runtime-pane-mcp-protocol.js +39 -0
  210. package/dist/runtime-pane-mcp-protocol.js.map +1 -0
  211. package/dist/runtime-pane-mcp-relay.d.ts +17 -0
  212. package/dist/runtime-pane-mcp-relay.js +70 -0
  213. package/dist/runtime-pane-mcp-relay.js.map +1 -0
  214. package/dist/runtime-pane-mcp.d.ts +43 -0
  215. package/dist/runtime-pane-mcp.js +137 -0
  216. package/dist/runtime-pane-mcp.js.map +1 -0
  217. package/dist/runtime-pane-native.d.ts +45 -0
  218. package/dist/runtime-pane-native.js +65 -0
  219. package/dist/runtime-pane-native.js.map +1 -0
  220. package/dist/runtime-pane-output.d.ts +19 -0
  221. package/dist/runtime-pane-output.js +53 -0
  222. package/dist/runtime-pane-output.js.map +1 -0
  223. package/dist/runtime-pane-port.d.ts +134 -0
  224. package/dist/runtime-pane-port.js +537 -0
  225. package/dist/runtime-pane-port.js.map +1 -0
  226. package/dist/runtime-pane-private.d.ts +14 -0
  227. package/dist/runtime-pane-private.js +51 -0
  228. package/dist/runtime-pane-private.js.map +1 -0
  229. package/dist/runtime-pane-private.ps1 +14 -0
  230. package/dist/runtime-pane-process.d.ts +4 -0
  231. package/dist/runtime-pane-process.js +108 -0
  232. package/dist/runtime-pane-process.js.map +1 -0
  233. package/dist/runtime-pane-protocol.d.ts +169 -0
  234. package/dist/runtime-pane-protocol.js +189 -0
  235. package/dist/runtime-pane-protocol.js.map +1 -0
  236. package/dist/runtime-pane-screen.d.ts +19 -0
  237. package/dist/runtime-pane-screen.js +76 -0
  238. package/dist/runtime-pane-screen.js.map +1 -0
  239. package/dist/runtime-pane-service.d.ts +11 -0
  240. package/dist/runtime-pane-service.js +221 -0
  241. package/dist/runtime-pane-service.js.map +1 -0
  242. package/dist/runtime-pane-stdio-protocol.d.ts +54 -0
  243. package/dist/runtime-pane-stdio-protocol.js +94 -0
  244. package/dist/runtime-pane-stdio-protocol.js.map +1 -0
  245. package/dist/runtime-pane-stdio.d.ts +3 -0
  246. package/dist/runtime-pane-stdio.js +123 -0
  247. package/dist/runtime-pane-stdio.js.map +1 -0
  248. package/dist/runtime-pane-store.d.ts +33 -0
  249. package/dist/runtime-pane-store.js +164 -0
  250. package/dist/runtime-pane-store.js.map +1 -0
  251. package/dist/runtime-pane-transcript-protocol.d.ts +43 -0
  252. package/dist/runtime-pane-transcript-protocol.js +58 -0
  253. package/dist/runtime-pane-transcript-protocol.js.map +1 -0
  254. package/dist/runtime-pane-transcript.d.ts +45 -0
  255. package/dist/runtime-pane-transcript.js +605 -0
  256. package/dist/runtime-pane-transcript.js.map +1 -0
  257. package/dist/runtime-pane-worker.d.ts +1 -0
  258. package/dist/runtime-pane-worker.js +154 -0
  259. package/dist/runtime-pane-worker.js.map +1 -0
  260. package/dist/runtime-protocol.d.ts +149 -0
  261. package/dist/runtime-protocol.js +19 -0
  262. package/dist/runtime-protocol.js.map +1 -0
  263. package/dist/runtime-switches.d.ts +79 -0
  264. package/dist/runtime-switches.js +90 -0
  265. package/dist/runtime-switches.js.map +1 -0
  266. package/dist/runtime-transcript-delta-reader.d.ts +23 -0
  267. package/dist/runtime-transcript-delta-reader.js +74 -0
  268. package/dist/runtime-transcript-delta-reader.js.map +1 -0
  269. package/dist/runtime-transcript-source.d.ts +36 -0
  270. package/dist/runtime-transcript-source.js +189 -0
  271. package/dist/runtime-transcript-source.js.map +1 -0
  272. package/dist/runtime-windows-bridge.d.ts +41 -0
  273. package/dist/runtime-windows-bridge.js +157 -0
  274. package/dist/runtime-windows-bridge.js.map +1 -0
  275. package/dist/settings-api.js +58 -0
  276. package/dist/settings-api.js.map +1 -1
  277. package/dist/settings-change.js +28 -0
  278. package/dist/settings-change.js.map +1 -1
  279. package/dist/settings-confirmation.d.ts +15 -1
  280. package/dist/settings-confirmation.js +46 -9
  281. package/dist/settings-confirmation.js.map +1 -1
  282. package/dist/settings-effect.js +23 -1
  283. package/dist/settings-effect.js.map +1 -1
  284. package/dist/settings-http-confirmation.js +11 -2
  285. package/dist/settings-http-confirmation.js.map +1 -1
  286. package/dist/tmux-control.d.ts +2 -1
  287. package/dist/tmux-control.js.map +1 -1
  288. package/dist/tmux-manager.d.ts +2 -1
  289. package/dist/tmux-manager.js.map +1 -1
  290. package/dist/tmux-pane-host.d.ts +26 -0
  291. package/dist/tmux-pane-host.js +25 -0
  292. package/dist/tmux-pane-host.js.map +1 -0
  293. package/dist/topic-commands.js +3 -0
  294. package/dist/topic-commands.js.map +1 -1
  295. package/dist/transcript-delta-reader.d.ts +1 -1
  296. package/dist/transcript-delta-reader.js +1 -1
  297. package/dist/transcript-delta-reader.js.map +1 -1
  298. package/dist/transcript-monitor.d.ts +3 -0
  299. package/dist/transcript-monitor.js +22 -46
  300. package/dist/transcript-monitor.js.map +1 -1
  301. package/dist/transcript-needles.d.ts +35 -0
  302. package/dist/transcript-needles.js +158 -0
  303. package/dist/transcript-needles.js.map +1 -0
  304. package/dist/transcript-records.d.ts +21 -0
  305. package/dist/transcript-records.js +140 -0
  306. package/dist/transcript-records.js.map +1 -0
  307. package/dist/transcript-sources.d.ts +5 -0
  308. package/dist/transcript-sources.js +8 -79
  309. package/dist/transcript-sources.js.map +1 -1
  310. package/dist/types.d.ts +21 -0
  311. package/dist/ui/agent-proposals.js +90 -0
  312. package/dist/ui/agent-runtime.js +106 -0
  313. package/dist/ui/chat-store.js +13 -2
  314. package/dist/ui/chat-strings.js +48 -0
  315. package/dist/ui/cli-picker.js +42 -0
  316. package/dist/ui/native-instance-settings.js +47 -0
  317. package/dist/ui/native-pane-recovery.js +45 -0
  318. package/dist/ui/panel-chat.js +61 -32
  319. package/dist/ui/panel-details.js +2 -1
  320. package/dist/ui/panel-fleet.js +99 -18
  321. package/dist/ui/panel-needs.js +152 -3
  322. package/dist/ui/panel-runtimes.js +231 -0
  323. package/dist/ui/panel-settings.js +14 -8
  324. package/dist/ui/panel-windows-agent.js +86 -0
  325. package/dist/ui/panel-windows-cli.js +143 -0
  326. package/dist/ui/provider-marks.js +83 -0
  327. package/dist/ui/runtime-catalog.js +55 -0
  328. package/dist/ui/settings-catalog.js +37 -10
  329. package/dist/ui/settings-confirm.js +3 -1
  330. package/dist/ui/settings-dialogs.js +14 -5
  331. package/dist/ui/settings-registry.js +5 -0
  332. package/dist/ui/settings-strings.js +14 -0
  333. package/dist/ui/shared/app-i18n.js +2 -2
  334. package/dist/ui/shared/app-route.js +6 -2
  335. package/dist/ui/shared/app-shell.js +3 -2
  336. package/dist/ui/shared/app-store.js +1 -0
  337. package/dist/ui/shared/app-stream.js +3 -1
  338. package/dist/ui/shared/app.css +301 -0
  339. package/dist/ui/shared/app.js +4 -0
  340. package/dist/ui/shared/header-tools.js +6 -4
  341. package/dist/ui/shared/instance-nav.js +20 -4
  342. package/dist/ui/shared/instance-switch.js +4 -3
  343. package/dist/ui/shared/ui-menu.js +28 -8
  344. package/dist/ui/shared/view-strings.js +6 -0
  345. package/dist/ui/windows-agents-nav.js +2 -0
  346. package/dist/ui/windows-cli-catalog.js +79 -0
  347. package/dist/update-check.d.ts +8 -2
  348. package/dist/update-check.js +5 -2
  349. package/dist/update-check.js.map +1 -1
  350. package/dist/web-api.d.ts +25 -0
  351. package/dist/web-api.js +171 -6
  352. package/dist/web-api.js.map +1 -1
  353. package/dist/web-chat-history.d.ts +19 -2
  354. package/dist/web-chat-history.js +72 -3
  355. package/dist/web-chat-history.js.map +1 -1
  356. package/dist/web-shell-routes.d.ts +4 -1
  357. package/dist/web-shell-routes.js +7 -2
  358. package/dist/web-shell-routes.js.map +1 -1
  359. package/dist/windows-agents.d.ts +112 -0
  360. package/dist/windows-agents.js +463 -0
  361. package/dist/windows-agents.js.map +1 -0
  362. package/dist/windows-cli-api.d.ts +23 -0
  363. package/dist/windows-cli-api.js +158 -0
  364. package/dist/windows-cli-api.js.map +1 -0
  365. package/dist/windows-cli-providers.d.ts +115 -0
  366. package/dist/windows-cli-providers.js +429 -0
  367. package/dist/windows-cli-providers.js.map +1 -0
  368. package/dist/windows-cli-worker.d.ts +58 -0
  369. package/dist/windows-cli-worker.js +479 -0
  370. package/dist/windows-cli-worker.js.map +1 -0
  371. package/dist/windows-cli.d.ts +115 -0
  372. package/dist/windows-cli.js +402 -0
  373. package/dist/windows-cli.js.map +1 -0
  374. package/dist/windows-native-mcp.d.ts +19 -0
  375. package/dist/windows-native-mcp.js +143 -0
  376. package/dist/windows-native-mcp.js.map +1 -0
  377. package/dist/windows-pane-mcp.d.ts +26 -0
  378. package/dist/windows-pane-mcp.js +187 -0
  379. package/dist/windows-pane-mcp.js.map +1 -0
  380. package/package.json +9 -3
  381. package/templates/runtime-assets/conpty-LICENSE +21 -0
  382. package/templates/runtime-assets/conpty-NOTICE.md +503 -0
  383. package/templates/runtime-assets/local-pane-stage.ps1 +101 -0
  384. package/templates/runtime-assets/runtime-pane-job.ps1 +116 -0
  385. package/templates/runtime-assets/runtime-pane-private.ps1 +14 -0
  386. package/templates/runtime-assets/xterm-LICENSE +21 -0
@@ -943,17 +943,87 @@ function claudeCommandRequestIdentity(pane) {
943
943
  .filter(row => !CLAUDE_AUTO_DENY_COUNTDOWN.test(row))
944
944
  .map(row => row.trim()).filter(Boolean).join("\n");
945
945
  }
946
+ /**
947
+ * M-2296: Claude Code 2.1.317's connector file-send safety card (`circuitBreaker: "connectorFileSend"`): an MCP
948
+ * connector call (the email connector's attachments by reference) that would send files from this computer asks
949
+ * first. It is bypass-immune (`bypassImmune: true, waivableInBypass: false` in the bundle), so it appears under
950
+ * --dangerously-skip-permissions too, and its focus starts on "Yes" unless the request defaults to No — an Enter
951
+ * meant for a delivery would send the files. Never answered by AgEnD: held for a person, shown in Needs-you.
952
+ *
953
+ * Shape (2.1.317 bundle: TIe/Rwt/Njo/Ljo/Twt and the `* ` file gutter; chrome as captured from a real MCP card):
954
+ * the card's last question row is "Do you want to proceed?", or a refusal-only variant ending "…no files are sent."
955
+ * (a list too long to show, or a call that does not say which files) or "…or choose No." (a terminal too short to
956
+ * show every file); Yes / No options (numbered, or unnumbered when it defaults to No); the "Esc to cancel" footer
957
+ * last; and, between the card's top and its question, a file row `* "<path>"` / `* the file at "<path>"` or the
958
+ * `* Name may not be what it looks like.` warning — the marks of a file-send card that no other card carries. A
959
+ * question variant that only this card asks counts on its own. A Bash card (its own entry) never matches here.
960
+ */
961
+ const FILE_SEND_ONLY_QUESTION = /(?:Choose No, and no files are sent\.|or choose No\.)[ \t]*$/;
962
+ const FILE_SEND_QUESTION = /(?:Do you want to proceed\?|Choose No, and no files are sent\.|or choose No\.)[ \t]*$/;
963
+ /** Pre-filter only (anywhere in the pane); claudeFileSendCardActive decides. */
964
+ export const CLAUDE_FILE_SEND_PATTERN = /Do you want to proceed\?|Choose No, and no files are sent\.|or choose No\./;
965
+ const FILE_SEND_MARK = /^[ \t│┃]*\* (?:the file at )?"|^[ \t│┃]*\* Name may not be what it looks like\./;
966
+ const FILE_SEND_OPTION = /^[ \t]*[❯›]?[ \t]*(?:\d{1,2}\.[ \t]+)?(Yes|No)\b/;
967
+ export function claudeFileSendCardActive(pane) {
968
+ const rows = claudeRows(pane).filter(row => row.trim() !== "");
969
+ if (!rows.length || !/^[ \t]*Esc(?:ape)? to cancel\b/.test(rows[rows.length - 1]))
970
+ return false;
971
+ // The question and the menu above the footer, as one bounded run of rows. A narrow pane wraps the question
972
+ // (#2992 review, Prism P2: "…Choose" / "No, and no files are sent."), and a wrapped row can even look like an
973
+ // option, so every split is tried from the bottom: the menu is the rows below it, the question is what the rows
974
+ // above it read as one line; the first split whose menu parses and whose question is a file-send question wins.
975
+ const block = rows.slice(Math.max(0, rows.length - 1 - 16), rows.length - 1);
976
+ for (let k = 1; k < block.length; k++) {
977
+ const menu = block.slice(block.length - k), above = block.slice(0, block.length - k);
978
+ const titles = [];
979
+ // The menu's first row is an option. (A wrapped question row may begin "No," too: the split that makes it one
980
+ // leaves "…Choose" as the question, which is no file-send question, so that split never wins.)
981
+ let parses = FILE_SEND_OPTION.test(menu[0]) || /^[ \t]*[❯›]?[ \t]*\d{1,2}\.[ \t]/.test(menu[0]);
982
+ for (const row of menu) {
983
+ const option = FILE_SEND_OPTION.exec(row);
984
+ if (option) {
985
+ titles.push(option[1]);
986
+ continue;
987
+ }
988
+ if (/^[ \t]*[❯›]?[ \t]*\d{1,2}\.[ \t]/.test(row) || /^[ \t]{3,}\S/.test(row))
989
+ continue; // another option, or a wrapped one
990
+ parses = false;
991
+ break;
992
+ }
993
+ if (!parses || !titles.includes("No"))
994
+ continue;
995
+ // The question: the rows just above the menu, read as one line (at most six physical rows).
996
+ const question = above.slice(-6).map(row => row.trim()).join(" ");
997
+ if (!FILE_SEND_QUESTION.test(question))
998
+ continue;
999
+ const refusalOnly = FILE_SEND_ONLY_QUESTION.test(question);
1000
+ // A refusal-only variant may offer No alone; every other shape offers Yes as well.
1001
+ if (!titles.includes("Yes") && !refusalOnly)
1002
+ continue;
1003
+ // The card's own rows: up from the menu to the rule that opens it (or 40 rows at most).
1004
+ const card = [];
1005
+ for (let i = rows.length - 2 - k; i >= 0 && rows.length - 2 - k - i <= 40; i--) {
1006
+ if (/^[ \t]*─{20,}[ \t]*$/.test(rows[i]))
1007
+ break;
1008
+ card.push(rows[i]);
1009
+ }
1010
+ if (card.some(row => /^[ \t]*Bash command[ \t]*$/.test(row)))
1011
+ return false;
1012
+ return refusalOnly || card.some(row => FILE_SEND_MARK.test(row));
1013
+ }
1014
+ return false;
1015
+ }
946
1016
  const dangerPromptOnYes = (pane) => {
947
1017
  const state = claudeDangerousCommandPromptState(pane);
948
- return state.active && state.cursor === "yes";
1018
+ return state.active && state.cursor === "yes" && !claudeFileSendCardActive(pane);
949
1019
  };
950
1020
  const dangerPromptOnNo = (pane) => {
951
1021
  const state = claudeDangerousCommandPromptState(pane);
952
- return state.active && state.cursor === "no";
1022
+ return state.active && state.cursor === "no" && !claudeFileSendCardActive(pane);
953
1023
  };
954
1024
  const dangerPromptUnknown = (pane) => {
955
1025
  const state = claudeDangerousCommandPromptState(pane);
956
- return state.active && state.cursor === "unknown";
1026
+ return state.active && state.cursor === "unknown" && !claudeFileSendCardActive(pane);
957
1027
  };
958
1028
  /** This text is code-owned and intentionally never includes the command. */
959
1029
  export const CLAUDE_DANGEROUS_COMMAND_BLOCKED_NOTICE = "[system:dangerous-command-blocked]\nThe previous command was classified as dangerous and was automatically denied. Do not retry it. Use a safe form instead (for example `${VAR:?}` validation, a literal path, or skip the destructive operation).";
@@ -1009,8 +1079,8 @@ const CLAUDE_BYPASS_ENTRIES = [
1009
1079
  ];
1010
1080
  /** Startup budget for a resuming claude-code launch (fresh starts keep the default). */
1011
1081
  export const CLAUDE_RESUME_STARTUP_BUDGET_MS = 60_000;
1012
- export class ClaudeCodeBackend {
1013
- instanceDir;
1082
+ /** Pane-only detectors: construction performs no provider, config or session discovery. */
1083
+ export class ClaudePaneDetectors {
1014
1084
  binaryName = "claude";
1015
1085
  replyCompletionGuard = true;
1016
1086
  /**
@@ -1022,116 +1092,6 @@ export class ClaudeCodeBackend {
1022
1092
  getStartupBudgetMs(ctx) {
1023
1093
  return ctx.resume ? CLAUDE_RESUME_STARTUP_BUDGET_MS : undefined;
1024
1094
  }
1025
- binaryPath;
1026
- constructor(instanceDir) {
1027
- this.instanceDir = instanceDir;
1028
- this.binaryPath = resolveBinary("claude");
1029
- }
1030
- /** #1811: what the last launch left out and why — the Log tab and daemon.log, never a channel. */
1031
- quietLaunchNotes = [];
1032
- consumeQuietLaunchNotes() { const notes = this.quietLaunchNotes; this.quietLaunchNotes = []; return notes; }
1033
- buildCommand(config) {
1034
- const settingsPath = join(this.instanceDir, "claude-settings.json");
1035
- const mcpConfigPath = join(this.instanceDir, "mcp-config.json");
1036
- const envPrefix = ["CMUX_CLAUDE_HOOKS_DISABLED=1", "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1"];
1037
- // #1699: a named credential profile is its own config dir — its login, account, trust and conversations. No profile:
1038
- // nothing added, nothing created (the command is exactly what it was).
1039
- const profileDir = claudeProfileConfigDir(config.backendOptions);
1040
- if (profileDir) {
1041
- prepareCredentialProfileHome(credentialHomeSpec("claude-code"), profileDir);
1042
- // #1754: the project's auto-memory is the shared one, as on the default login.
1043
- linkSharedClaudeMemory(profileDir, config.workingDirectory, credentialHomeSpec("claude-code").sharedRoot());
1044
- envPrefix.push(`CLAUDE_CONFIG_DIR=${shellQuote(profileDir)}`);
1045
- }
1046
- if (process.env.ANTHROPIC_BASE_URL)
1047
- envPrefix.push(`ANTHROPIC_BASE_URL=${shellQuote(process.env.ANTHROPIC_BASE_URL)}`);
1048
- // #2010: an opt-in prompt-cache TTL for the main thread and its subagents. Unset: nothing added, the CLI chooses.
1049
- const ttl = promptCacheTtl(config.backendOptions);
1050
- if (ttl)
1051
- envPrefix.push(`CLAUDE_CODE_PROMPT_CACHE_TTL=${ttl}`, `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL=${ttl}`);
1052
- // The fleet's API key only where this instance's own config dir has no OAuth login: a key in the environment wins
1053
- // over the login, so reading another dir here bills the wrong account (#1699).
1054
- if (process.env.ANTHROPIC_API_KEY && !this.hasOAuthSession(profileDir)) {
1055
- envPrefix.push(`ANTHROPIC_API_KEY=${shellQuote(process.env.ANTHROPIC_API_KEY)}`);
1056
- }
1057
- let cmd = `${envPrefix.join(" ")} ${this.binaryPath} --settings ${settingsPath} --mcp-config ${mcpConfigPath}`;
1058
- if (config.skipPermissions !== false)
1059
- cmd += " --dangerously-skip-permissions";
1060
- const sessionIdFile = join(this.instanceDir, "session-id");
1061
- // `session-id` belongs to the instance, not the backend. A ClassicBot can
1062
- // switch from Kiro (or another CLI) to Claude while retaining that marker.
1063
- // Claude's bare `--continue` then looks for a conversation in this cwd and
1064
- // exits when the workspace has never had a Claude session. Treat Claude's
1065
- // own project transcript as the source of truth instead of the generic
1066
- // marker alone. This also makes an empty/missing Classic workspace start
1067
- // fresh rather than entering a resume crash loop.
1068
- if (!config.skipResume && existsSync(sessionIdFile) && this.hasProjectSession(config.workingDirectory, profileDir)) {
1069
- cmd += " --continue";
1070
- }
1071
- if (config.model) {
1072
- const model = validateModel(config.model);
1073
- warnIfModelMismatch("claude-code", model);
1074
- cmd += ` --model ${shellQuote(model)}`;
1075
- }
1076
- // #1811: the configured effort, where this claude takes it (launch-effort.ts); else a quiet note.
1077
- const effort = flagEffort("claude-code", config.effort, this.binaryPath);
1078
- if (effort.arg)
1079
- cmd += effort.arg;
1080
- this.quietLaunchNotes = effort.note ? [effort.note] : [];
1081
- // Additive system prompt: append fleet instructions without overriding Claude's built-in prompt
1082
- const instrFile = join(this.instanceDir, "fleet-instructions.md");
1083
- if (existsSync(instrFile)) {
1084
- cmd += ` --append-system-prompt-file ${instrFile}`;
1085
- }
1086
- return cmd;
1087
- }
1088
- hasProjectSession(workingDirectory, profileDir) {
1089
- const cwd = workingDirectory.trim();
1090
- if (!cwd)
1091
- return false;
1092
- const configDir = claudeConfigDirFor(profileDir);
1093
- const encodedCwd = claudeProjectKey(cwd);
1094
- try {
1095
- return readdirSync(join(configDir, "projects", encodedCwd), { withFileTypes: true })
1096
- .some(entry => entry.isFile() && entry.name.endsWith(".jsonl"));
1097
- }
1098
- catch {
1099
- return false;
1100
- }
1101
- }
1102
- writeConfig(config) {
1103
- // 1. Write mcp-config.json to instance dir (loaded via --mcp-config)
1104
- const mcpConfigPath = join(this.instanceDir, "mcp-config.json");
1105
- const mcpConfig = { mcpServers: config.mcpServers };
1106
- writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
1107
- // 2. Write statusline script
1108
- const statusLineCommand = this.writeStatusLineScript();
1109
- // 3. Write claude-settings.json (permissions handled by --dangerously-skip-permissions)
1110
- const settings = {
1111
- statusLine: {
1112
- type: "command",
1113
- command: statusLineCommand,
1114
- },
1115
- };
1116
- // The Bypass Permissions warning appears on a first run (and whenever the
1117
- // user's own settings have not recorded the acceptance) for every launch
1118
- // with --dangerously-skip-permissions. AgEnD passes that flag deliberately,
1119
- // so record the acceptance in the flag-level settings this file is loaded as
1120
- // (--settings): claude 2.1.286 then never paints the dialog (verified live).
1121
- // Only when the flag is actually passed — see buildCommand.
1122
- if (config.skipPermissions !== false)
1123
- settings.skipDangerousModePermissionPrompt = true;
1124
- writeFileSync(join(this.instanceDir, "claude-settings.json"), JSON.stringify(settings));
1125
- // 4. Pre-approve API key to skip interactive prompt on startup
1126
- this.preApproveApiKey(config);
1127
- // 5. Write fleet instructions file (loaded via --append-system-prompt-file)
1128
- if (config.instructions) {
1129
- try {
1130
- writeFileSync(join(this.instanceDir, "fleet-instructions.md"), config.instructions);
1131
- }
1132
- catch { /* best effort */ }
1133
- }
1134
- }
1135
1095
  /**
1136
1096
  * `❯` is the input box, which Claude Code renders persistently — it is on screen
1137
1097
  * while the agent works, not only when it is waiting. So this marks "the TUI has
@@ -1242,27 +1202,6 @@ export class ClaudeCodeBackend {
1242
1202
  const box = readClaudeInputBox(pane);
1243
1203
  return box !== null && box.queued !== true && !this.getBusyPattern().test(pane);
1244
1204
  }
1245
- getContextUsage() {
1246
- try {
1247
- const sf = join(this.instanceDir, "statusline.json");
1248
- const data = JSON.parse(readFileSync(sf, "utf-8"));
1249
- return data.context_window?.used_percentage ?? null;
1250
- }
1251
- catch (err) {
1252
- // File may not exist yet during startup — return null to signal unavailable
1253
- return null;
1254
- }
1255
- }
1256
- getSessionId() {
1257
- try {
1258
- const sf = join(this.instanceDir, "statusline.json");
1259
- const data = JSON.parse(readFileSync(sf, "utf-8"));
1260
- return data.session_id ?? null;
1261
- }
1262
- catch {
1263
- return null;
1264
- }
1265
- }
1266
1205
  getErrorPatterns() {
1267
1206
  return [
1268
1207
  { pattern: /API Error: Rate limit/i, type: "rate_limit", action: "failover", message: "API rate limit reached" },
@@ -1441,6 +1380,21 @@ export class ClaudeCodeBackend {
1441
1380
  inputBlocked: true,
1442
1381
  description: COLD_RESUME_HOLD_DESCRIPTION,
1443
1382
  },
1383
+ // M-2296: the 2.1.317 connector file-send card — ahead of the dangerous-command entries, whose two-option
1384
+ // shape it can share: it is never auto-answered (not even "No", which would tell the agent its call was a
1385
+ // dangerous command) and never takes a delivery's keys.
1386
+ {
1387
+ pattern: CLAUDE_FILE_SEND_PATTERN,
1388
+ isActive: claudeFileSendCardActive,
1389
+ requestIdentity: pane => claudeSelectionCard(pane)?.identity ?? null,
1390
+ interactionKind: "permission",
1391
+ keys: [],
1392
+ holdOnly: true,
1393
+ blocksDelivery: true,
1394
+ inputBlocked: true,
1395
+ remoteCard: claudeSelectionCard,
1396
+ description: "Claude connector file-send approval — waiting for a human choice, never auto-approving",
1397
+ },
1444
1398
  // Claude's shell-command safety menu is the one runtime prompt AgEnD is
1445
1399
  // allowed to answer automatically. Keep cursor-known entries ahead of
1446
1400
  // the hold-only guard; unknown shapes are always held for a human.
@@ -1542,6 +1496,141 @@ export class ClaudeCodeBackend {
1542
1496
  getCompactCommand() { return "/compact"; }
1543
1497
  getClearCommand() { return "/clear"; }
1544
1498
  getCancelKey() { return "Escape"; }
1499
+ }
1500
+ export class ClaudeCodeBackend extends ClaudePaneDetectors {
1501
+ instanceDir;
1502
+ binaryPath;
1503
+ constructor(instanceDir) {
1504
+ super();
1505
+ this.instanceDir = instanceDir;
1506
+ this.binaryPath = resolveBinary("claude");
1507
+ }
1508
+ /** #1811: what the last launch left out and why — the Log tab and daemon.log, never a channel. */
1509
+ quietLaunchNotes = [];
1510
+ consumeQuietLaunchNotes() { const notes = this.quietLaunchNotes; this.quietLaunchNotes = []; return notes; }
1511
+ buildCommand(config) {
1512
+ const settingsPath = join(this.instanceDir, "claude-settings.json");
1513
+ const mcpConfigPath = join(this.instanceDir, "mcp-config.json");
1514
+ const envPrefix = ["CMUX_CLAUDE_HOOKS_DISABLED=1", "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1"];
1515
+ // #1699: a named credential profile is its own config dir — its login, account, trust and conversations. No profile:
1516
+ // nothing added, nothing created (the command is exactly what it was).
1517
+ const profileDir = claudeProfileConfigDir(config.backendOptions);
1518
+ if (profileDir) {
1519
+ prepareCredentialProfileHome(credentialHomeSpec("claude-code"), profileDir);
1520
+ // #1754: the project's auto-memory is the shared one, as on the default login.
1521
+ linkSharedClaudeMemory(profileDir, config.workingDirectory, credentialHomeSpec("claude-code").sharedRoot());
1522
+ envPrefix.push(`CLAUDE_CONFIG_DIR=${shellQuote(profileDir)}`);
1523
+ }
1524
+ if (process.env.ANTHROPIC_BASE_URL)
1525
+ envPrefix.push(`ANTHROPIC_BASE_URL=${shellQuote(process.env.ANTHROPIC_BASE_URL)}`);
1526
+ // #2010: an opt-in prompt-cache TTL for the main thread and its subagents. Unset: nothing added, the CLI chooses.
1527
+ const ttl = promptCacheTtl(config.backendOptions);
1528
+ if (ttl)
1529
+ envPrefix.push(`CLAUDE_CODE_PROMPT_CACHE_TTL=${ttl}`, `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL=${ttl}`);
1530
+ // The fleet's API key only where this instance's own config dir has no OAuth login: a key in the environment wins
1531
+ // over the login, so reading another dir here bills the wrong account (#1699).
1532
+ if (process.env.ANTHROPIC_API_KEY && !this.hasOAuthSession(profileDir)) {
1533
+ envPrefix.push(`ANTHROPIC_API_KEY=${shellQuote(process.env.ANTHROPIC_API_KEY)}`);
1534
+ }
1535
+ let cmd = `${envPrefix.join(" ")} ${this.binaryPath} --settings ${settingsPath} --mcp-config ${mcpConfigPath}`;
1536
+ if (config.skipPermissions !== false)
1537
+ cmd += " --dangerously-skip-permissions";
1538
+ const sessionIdFile = join(this.instanceDir, "session-id");
1539
+ // `session-id` belongs to the instance, not the backend. A ClassicBot can
1540
+ // switch from Kiro (or another CLI) to Claude while retaining that marker.
1541
+ // Claude's bare `--continue` then looks for a conversation in this cwd and
1542
+ // exits when the workspace has never had a Claude session. Treat Claude's
1543
+ // own project transcript as the source of truth instead of the generic
1544
+ // marker alone. This also makes an empty/missing Classic workspace start
1545
+ // fresh rather than entering a resume crash loop.
1546
+ if (!config.skipResume && existsSync(sessionIdFile) && this.hasProjectSession(config.workingDirectory, profileDir)) {
1547
+ cmd += " --continue";
1548
+ }
1549
+ if (config.model) {
1550
+ const model = validateModel(config.model);
1551
+ warnIfModelMismatch("claude-code", model);
1552
+ cmd += ` --model ${shellQuote(model)}`;
1553
+ }
1554
+ // #1811: the configured effort, where this claude takes it (launch-effort.ts); else a quiet note.
1555
+ const effort = flagEffort("claude-code", config.effort, this.binaryPath);
1556
+ if (effort.arg)
1557
+ cmd += effort.arg;
1558
+ this.quietLaunchNotes = effort.note ? [effort.note] : [];
1559
+ // Additive system prompt: append fleet instructions without overriding Claude's built-in prompt
1560
+ const instrFile = join(this.instanceDir, "fleet-instructions.md");
1561
+ if (existsSync(instrFile)) {
1562
+ cmd += ` --append-system-prompt-file ${instrFile}`;
1563
+ }
1564
+ return cmd;
1565
+ }
1566
+ hasProjectSession(workingDirectory, profileDir) {
1567
+ const cwd = workingDirectory.trim();
1568
+ if (!cwd)
1569
+ return false;
1570
+ const configDir = claudeConfigDirFor(profileDir);
1571
+ const encodedCwd = claudeProjectKey(cwd);
1572
+ try {
1573
+ return readdirSync(join(configDir, "projects", encodedCwd), { withFileTypes: true })
1574
+ .some(entry => entry.isFile() && entry.name.endsWith(".jsonl"));
1575
+ }
1576
+ catch {
1577
+ return false;
1578
+ }
1579
+ }
1580
+ writeConfig(config) {
1581
+ // 1. Write mcp-config.json to instance dir (loaded via --mcp-config)
1582
+ const mcpConfigPath = join(this.instanceDir, "mcp-config.json");
1583
+ const mcpConfig = { mcpServers: config.mcpServers };
1584
+ writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
1585
+ // 2. Write statusline script
1586
+ const statusLineCommand = this.writeStatusLineScript();
1587
+ // 3. Write claude-settings.json (permissions handled by --dangerously-skip-permissions)
1588
+ const settings = {
1589
+ statusLine: {
1590
+ type: "command",
1591
+ command: statusLineCommand,
1592
+ },
1593
+ };
1594
+ // The Bypass Permissions warning appears on a first run (and whenever the
1595
+ // user's own settings have not recorded the acceptance) for every launch
1596
+ // with --dangerously-skip-permissions. AgEnD passes that flag deliberately,
1597
+ // so record the acceptance in the flag-level settings this file is loaded as
1598
+ // (--settings): claude 2.1.286 then never paints the dialog (verified live).
1599
+ // Only when the flag is actually passed — see buildCommand.
1600
+ if (config.skipPermissions !== false)
1601
+ settings.skipDangerousModePermissionPrompt = true;
1602
+ writeFileSync(join(this.instanceDir, "claude-settings.json"), JSON.stringify(settings));
1603
+ // 4. Pre-approve API key to skip interactive prompt on startup
1604
+ this.preApproveApiKey(config);
1605
+ // 5. Write fleet instructions file (loaded via --append-system-prompt-file)
1606
+ if (config.instructions) {
1607
+ try {
1608
+ writeFileSync(join(this.instanceDir, "fleet-instructions.md"), config.instructions);
1609
+ }
1610
+ catch { /* best effort */ }
1611
+ }
1612
+ }
1613
+ getContextUsage() {
1614
+ try {
1615
+ const sf = join(this.instanceDir, "statusline.json");
1616
+ const data = JSON.parse(readFileSync(sf, "utf-8"));
1617
+ return data.context_window?.used_percentage ?? null;
1618
+ }
1619
+ catch (err) {
1620
+ // File may not exist yet during startup — return null to signal unavailable
1621
+ return null;
1622
+ }
1623
+ }
1624
+ getSessionId() {
1625
+ try {
1626
+ const sf = join(this.instanceDir, "statusline.json");
1627
+ const data = JSON.parse(readFileSync(sf, "utf-8"));
1628
+ return data.session_id ?? null;
1629
+ }
1630
+ catch {
1631
+ return null;
1632
+ }
1633
+ }
1545
1634
  /** #1217: Claude's own words for a session that is not there to resume. */
1546
1635
  resumeMissingPattern() {
1547
1636
  return /no conversation found|no conversation to (continue|resume)|no previous (session|conversation)/i;