@songsid/agend 2.3.0-beta.2 → 2.3.0-beta.20

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 (502) hide show
  1. package/README.md +7 -1
  2. package/README.zh-TW.md +7 -1
  3. package/dist/agent-cli-instructions.md +9 -2
  4. package/dist/agent-cli.js +63 -2
  5. package/dist/agent-cli.js.map +1 -1
  6. package/dist/agent-endpoint.js +4 -0
  7. package/dist/agent-endpoint.js.map +1 -1
  8. package/dist/agent-file-read.d.ts +4 -1
  9. package/dist/agent-file-read.js +189 -16
  10. package/dist/agent-file-read.js.map +1 -1
  11. package/dist/agent-whats-new.d.ts +11 -0
  12. package/dist/agent-whats-new.js +29 -5
  13. package/dist/agent-whats-new.js.map +1 -1
  14. package/dist/auth-api.d.ts +30 -1
  15. package/dist/auth-api.js +45 -13
  16. package/dist/auth-api.js.map +1 -1
  17. package/dist/authority/authority-state.d.ts +38 -0
  18. package/dist/authority/authority-state.js +114 -0
  19. package/dist/authority/authority-state.js.map +1 -0
  20. package/dist/authority/session-authorizations.d.ts +43 -0
  21. package/dist/authority/session-authorizations.js +102 -0
  22. package/dist/authority/session-authorizations.js.map +1 -0
  23. package/dist/authority/web-authority.d.ts +120 -0
  24. package/dist/authority/web-authority.js +157 -0
  25. package/dist/authority/web-authority.js.map +1 -0
  26. package/dist/backend/claude-code.d.ts +2 -2
  27. package/dist/backend/claude-code.js +18 -8
  28. package/dist/backend/claude-code.js.map +1 -1
  29. package/dist/backend/codex-metadata.d.ts +8 -0
  30. package/dist/backend/codex-metadata.js +74 -17
  31. package/dist/backend/codex-metadata.js.map +1 -1
  32. package/dist/backend/codex.js +15 -2
  33. package/dist/backend/codex.js.map +1 -1
  34. package/dist/backend/credential-profile.d.ts +2 -0
  35. package/dist/backend/credential-profile.js +2 -0
  36. package/dist/backend/credential-profile.js.map +1 -1
  37. package/dist/backend/types.d.ts +6 -0
  38. package/dist/backend/types.js +15 -0
  39. package/dist/backend/types.js.map +1 -1
  40. package/dist/backend-availability.d.ts +120 -0
  41. package/dist/backend-availability.js +396 -0
  42. package/dist/backend-availability.js.map +1 -0
  43. package/dist/backend-command.d.ts +23 -3
  44. package/dist/backend-command.js +25 -4
  45. package/dist/backend-command.js.map +1 -1
  46. package/dist/bug-report-cli.d.ts +30 -0
  47. package/dist/bug-report-cli.js +138 -0
  48. package/dist/bug-report-cli.js.map +1 -0
  49. package/dist/bug-report.d.ts +47 -0
  50. package/dist/bug-report.js +136 -0
  51. package/dist/bug-report.js.map +1 -0
  52. package/dist/bundled-skills.d.ts +14 -0
  53. package/dist/bundled-skills.js +29 -0
  54. package/dist/bundled-skills.js.map +1 -0
  55. package/dist/cache-ledger.d.ts +16 -3
  56. package/dist/cache-ledger.js +33 -13
  57. package/dist/cache-ledger.js.map +1 -1
  58. package/dist/cache-service.d.ts +55 -3
  59. package/dist/cache-service.js +152 -16
  60. package/dist/cache-service.js.map +1 -1
  61. package/dist/channel/adapters/discord-client-retirement.d.ts +5 -0
  62. package/dist/channel/adapters/discord-client-retirement.js +57 -0
  63. package/dist/channel/adapters/discord-client-retirement.js.map +1 -0
  64. package/dist/channel/adapters/discord.d.ts +9 -0
  65. package/dist/channel/adapters/discord.js +49 -4
  66. package/dist/channel/adapters/discord.js.map +1 -1
  67. package/dist/channel/mcp-tools.js +22 -11
  68. package/dist/channel/mcp-tools.js.map +1 -1
  69. package/dist/channel/types.d.ts +6 -0
  70. package/dist/classic-channel-manager.d.ts +10 -5
  71. package/dist/classic-channel-manager.js +12 -9
  72. package/dist/classic-channel-manager.js.map +1 -1
  73. package/dist/cli.js +224 -111
  74. package/dist/cli.js.map +1 -1
  75. package/dist/config-validator.d.ts +6 -0
  76. package/dist/config-validator.js +129 -3
  77. package/dist/config-validator.js.map +1 -1
  78. package/dist/config.d.ts +13 -1
  79. package/dist/config.js +14 -5
  80. package/dist/config.js.map +1 -1
  81. package/dist/cross-instance-notice.d.ts +7 -0
  82. package/dist/cross-instance-notice.js +10 -0
  83. package/dist/cross-instance-notice.js.map +1 -1
  84. package/dist/daemon.d.ts +24 -1
  85. package/dist/daemon.js +151 -19
  86. package/dist/daemon.js.map +1 -1
  87. package/dist/decision-list.d.ts +25 -0
  88. package/dist/decision-list.js +30 -0
  89. package/dist/decision-list.js.map +1 -0
  90. package/dist/delivery-outbox.d.ts +10 -0
  91. package/dist/delivery-outbox.js +17 -1
  92. package/dist/delivery-outbox.js.map +1 -1
  93. package/dist/diagnostic-redaction.d.ts +10 -0
  94. package/dist/diagnostic-redaction.js +167 -0
  95. package/dist/diagnostic-redaction.js.map +1 -0
  96. package/dist/fleet-context.d.ts +10 -0
  97. package/dist/fleet-manager.d.ts +505 -15
  98. package/dist/fleet-manager.js +1870 -204
  99. package/dist/fleet-manager.js.map +1 -1
  100. package/dist/fleet-process-handlers.d.ts +18 -0
  101. package/dist/fleet-process-handlers.js +69 -0
  102. package/dist/fleet-process-handlers.js.map +1 -0
  103. package/dist/fleet-traffic.d.ts +74 -0
  104. package/dist/fleet-traffic.js +196 -0
  105. package/dist/fleet-traffic.js.map +1 -0
  106. package/dist/general-knowledge/skills/bug-report/SKILL.md +31 -0
  107. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +17 -6
  108. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +6 -1
  109. package/dist/general-knowledge/skills/fleet-config/SKILL.md +2 -0
  110. package/dist/general-knowledge/skills/multi-channel/SKILL.md +3 -2
  111. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
  112. package/dist/general-knowledge/skills/scheduling/SKILL.md +4 -0
  113. package/dist/general-knowledge/skills/web-appearance/SKILL.md +190 -47
  114. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +545 -0
  115. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
  116. package/dist/human-delivery-receipts.d.ts +24 -1
  117. package/dist/human-delivery-receipts.js +64 -11
  118. package/dist/human-delivery-receipts.js.map +1 -1
  119. package/dist/instance-config-impact.js +7 -1
  120. package/dist/instance-config-impact.js.map +1 -1
  121. package/dist/instance-lifecycle.d.ts +10 -1
  122. package/dist/instance-lifecycle.js +79 -18
  123. package/dist/instance-lifecycle.js.map +1 -1
  124. package/dist/instance-names.d.ts +4 -0
  125. package/dist/instance-names.js +12 -0
  126. package/dist/instance-names.js.map +1 -0
  127. package/dist/instructions.d.ts +12 -1
  128. package/dist/instructions.js +13 -2
  129. package/dist/instructions.js.map +1 -1
  130. package/dist/locale.js +173 -12
  131. package/dist/locale.js.map +1 -1
  132. package/dist/log-steps.d.ts +1 -0
  133. package/dist/log-steps.js +15 -0
  134. package/dist/log-steps.js.map +1 -1
  135. package/dist/login-controller.d.ts +45 -0
  136. package/dist/login-controller.js +101 -5
  137. package/dist/login-controller.js.map +1 -1
  138. package/dist/ls-attach-resolve.d.ts +96 -0
  139. package/dist/ls-attach-resolve.js +180 -0
  140. package/dist/ls-attach-resolve.js.map +1 -0
  141. package/dist/ls-rows.d.ts +12 -0
  142. package/dist/ls-rows.js +82 -3
  143. package/dist/ls-rows.js.map +1 -1
  144. package/dist/memory-hogs.d.ts +27 -0
  145. package/dist/memory-hogs.js +124 -0
  146. package/dist/memory-hogs.js.map +1 -0
  147. package/dist/needs-you.d.ts +10 -0
  148. package/dist/needs-you.js +2 -1
  149. package/dist/needs-you.js.map +1 -1
  150. package/dist/outbound-handlers.d.ts +11 -0
  151. package/dist/outbound-handlers.js +139 -11
  152. package/dist/outbound-handlers.js.map +1 -1
  153. package/dist/outbound-schemas.d.ts +200 -4
  154. package/dist/outbound-schemas.js +124 -11
  155. package/dist/outbound-schemas.js.map +1 -1
  156. package/dist/public-web-gateway.js +17 -4
  157. package/dist/public-web-gateway.js.map +1 -1
  158. package/dist/public-web-link.d.ts +9 -0
  159. package/dist/public-web-link.js +8 -0
  160. package/dist/public-web-link.js.map +1 -1
  161. package/dist/quickstart-api.d.ts +19 -1
  162. package/dist/quickstart-api.js +94 -4
  163. package/dist/quickstart-api.js.map +1 -1
  164. package/dist/reply-buttons-controller.d.ts +4 -0
  165. package/dist/reply-buttons-controller.js +2 -2
  166. package/dist/reply-buttons-controller.js.map +1 -1
  167. package/dist/restart-progress.d.ts +80 -1
  168. package/dist/restart-progress.js +306 -21
  169. package/dist/restart-progress.js.map +1 -1
  170. package/dist/rollout-index.d.ts +5 -0
  171. package/dist/rollout-index.js +26 -5
  172. package/dist/rollout-index.js.map +1 -1
  173. package/dist/scheduler/db.d.ts +40 -13
  174. package/dist/scheduler/db.js +123 -89
  175. package/dist/scheduler/db.js.map +1 -1
  176. package/dist/scheduler/task-board-text.d.ts +26 -0
  177. package/dist/scheduler/task-board-text.js +135 -0
  178. package/dist/scheduler/task-board-text.js.map +1 -0
  179. package/dist/scheduler/task-board.d.ts +650 -0
  180. package/dist/scheduler/task-board.js +1938 -0
  181. package/dist/scheduler/task-board.js.map +1 -0
  182. package/dist/scheduler/types.d.ts +6 -1
  183. package/dist/search/search-docs.d.ts +58 -0
  184. package/dist/search/search-docs.js +63 -0
  185. package/dist/search/search-docs.js.map +1 -0
  186. package/dist/search/search-index.d.ts +141 -0
  187. package/dist/search/search-index.js +440 -0
  188. package/dist/search/search-index.js.map +1 -0
  189. package/dist/search/search-store.d.ts +122 -0
  190. package/dist/search/search-store.js +236 -0
  191. package/dist/search/search-store.js.map +1 -0
  192. package/dist/search/search-worker.d.ts +1 -0
  193. package/dist/search/search-worker.js +163 -0
  194. package/dist/search/search-worker.js.map +1 -0
  195. package/dist/service-installer.js +12 -0
  196. package/dist/service-installer.js.map +1 -1
  197. package/dist/settings-api.d.ts +23 -0
  198. package/dist/settings-api.js +164 -3
  199. package/dist/settings-api.js.map +1 -1
  200. package/dist/settings-change.js +104 -0
  201. package/dist/settings-change.js.map +1 -1
  202. package/dist/settings-confirmation.d.ts +3 -1
  203. package/dist/settings-confirmation.js +2 -0
  204. package/dist/settings-confirmation.js.map +1 -1
  205. package/dist/settings-effect.js +34 -3
  206. package/dist/settings-effect.js.map +1 -1
  207. package/dist/settings-http-confirmation.d.ts +11 -0
  208. package/dist/settings-http-confirmation.js +10 -0
  209. package/dist/settings-http-confirmation.js.map +1 -1
  210. package/dist/setup-form.d.ts +1 -1
  211. package/dist/setup-form.js +23 -7
  212. package/dist/setup-form.js.map +1 -1
  213. package/dist/spawn-gate.d.ts +1 -0
  214. package/dist/spawn-gate.js +13 -3
  215. package/dist/spawn-gate.js.map +1 -1
  216. package/dist/task-board-tool.d.ts +25 -0
  217. package/dist/task-board-tool.js +154 -0
  218. package/dist/task-board-tool.js.map +1 -0
  219. package/dist/task-board-waker.d.ts +44 -0
  220. package/dist/task-board-waker.js +128 -0
  221. package/dist/task-board-waker.js.map +1 -0
  222. package/dist/tmux-exec-helper.d.ts +94 -0
  223. package/dist/tmux-exec-helper.js +407 -0
  224. package/dist/tmux-exec-helper.js.map +1 -0
  225. package/dist/tmux-manager.d.ts +5 -0
  226. package/dist/tmux-manager.js +42 -11
  227. package/dist/tmux-manager.js.map +1 -1
  228. package/dist/tool-permissions.d.ts +0 -7
  229. package/dist/tool-permissions.js +44 -5
  230. package/dist/tool-permissions.js.map +1 -1
  231. package/dist/topic-commands.d.ts +17 -1
  232. package/dist/topic-commands.js +45 -19
  233. package/dist/topic-commands.js.map +1 -1
  234. package/dist/tunnel/cloudflared.js +37 -2
  235. package/dist/tunnel/cloudflared.js.map +1 -1
  236. package/dist/tunnel/types.d.ts +3 -1
  237. package/dist/tunnel/types.js.map +1 -1
  238. package/dist/types.d.ts +63 -1
  239. package/dist/ui/app-effects.js +90 -32
  240. package/dist/ui/backend-signin.js +297 -0
  241. package/dist/ui/chat-ambient.js +307 -0
  242. package/dist/ui/chat-effect-posters.js +8 -8
  243. package/dist/ui/chat-effects.js +110 -15
  244. package/dist/ui/chat-msg-actions.js +176 -0
  245. package/dist/ui/chat-render.js +21 -3
  246. package/dist/ui/chat-store.js +64 -12
  247. package/dist/ui/chat-strings.js +85 -8
  248. package/dist/ui/chat-thread.js +204 -21
  249. package/dist/ui/effect-trial-controller.js +13 -8
  250. package/dist/ui/effect-trial-panel.js +19 -16
  251. package/dist/ui/effects-waker.js +70 -0
  252. package/dist/ui/fleet-canvas-layout.js +117 -0
  253. package/dist/ui/fleet-canvas.js +555 -0
  254. package/dist/ui/fleet-org.js +27 -12
  255. package/dist/ui/fleet-route-scene.js +207 -0
  256. package/dist/ui/fleet-route-worker.js +21 -0
  257. package/dist/ui/fleet-route.js +88 -0
  258. package/dist/ui/fleet-task-card.js +436 -0
  259. package/dist/ui/fleet-task-common.js +448 -0
  260. package/dist/ui/fleet-tasks.js +535 -0
  261. package/dist/ui/fleet-traffic.js +359 -0
  262. package/dist/ui/fleet-usage.js +435 -0
  263. package/dist/ui/panel-chat.js +264 -66
  264. package/dist/ui/panel-details.js +2 -1
  265. package/dist/ui/panel-fleet.js +65 -83
  266. package/dist/ui/panel-needs.js +4 -2
  267. package/dist/ui/panel-settings.js +56 -11
  268. package/dist/ui/preview.js +3 -2
  269. package/dist/ui/search-dialog.js +349 -0
  270. package/dist/ui/settings-appearance.js +44 -19
  271. package/dist/ui/settings-apply.js +3 -3
  272. package/dist/ui/settings-catalog.js +92 -0
  273. package/dist/ui/settings-confirm.js +7 -2
  274. package/dist/ui/settings-dialogs.js +40 -12
  275. package/dist/ui/settings-effects.js +4 -3
  276. package/dist/ui/settings-guests.js +117 -0
  277. package/dist/ui/settings-learn.js +25 -0
  278. package/dist/ui/settings-model.js +15 -6
  279. package/dist/ui/settings-mods.js +23 -9
  280. package/dist/ui/settings-owner-effects.js +15 -13
  281. package/dist/ui/settings-strings.js +122 -42
  282. package/dist/ui/settings-web-authority.js +91 -0
  283. package/dist/ui/shared/agend-auth.js +1 -1
  284. package/dist/ui/shared/app-i18n.js +11 -2
  285. package/dist/ui/shared/app-prefs.js +17 -4
  286. package/dist/ui/shared/app-route.js +19 -1
  287. package/dist/ui/shared/app-session.js +2 -0
  288. package/dist/ui/shared/app-shell.js +174 -30
  289. package/dist/ui/shared/app-store.js +26 -1
  290. package/dist/ui/shared/app-stream.js +5 -1
  291. package/dist/ui/shared/app-themes.js +140 -7
  292. package/dist/ui/shared/app.css +704 -20
  293. package/dist/ui/shared/app.js +26 -15
  294. package/dist/ui/shared/card-strings.js +8 -0
  295. package/dist/ui/shared/effect-app-runtime.js +68 -19
  296. package/dist/ui/shared/effect-chat-runtime.js +16 -3
  297. package/dist/ui/shared/effect-frame.js +26 -7
  298. package/dist/ui/shared/effect-geometry.js +24 -9
  299. package/dist/ui/shared/effect-owner-source.js +8 -1
  300. package/dist/ui/shared/effect-policy.js +21 -7
  301. package/dist/ui/shared/effect-profiler.js +31 -9
  302. package/dist/ui/shared/effect-registry.js +97 -50
  303. package/dist/ui/shared/effect-stock-snapshot.js +9 -0
  304. package/dist/ui/shared/effect-stock-trust.js +62 -10
  305. package/dist/ui/shared/effect-trial-shadow.js +62 -0
  306. package/dist/ui/shared/effect-trial-source.js +1 -1
  307. package/dist/ui/shared/effect-trial-stage.js +54 -31
  308. package/dist/ui/shared/effect-trial.css +40 -0
  309. package/dist/ui/shared/fx-motion.js +67 -0
  310. package/dist/ui/shared/identity-card.js +100 -11
  311. package/dist/ui/shared/identity-color.js +14 -10
  312. package/dist/ui/shared/instance-nav.js +179 -23
  313. package/dist/ui/shared/owner-css.js +30 -1
  314. package/dist/ui/shared/panel-view.js +24 -4
  315. package/dist/ui/shared/tokens.css +9 -3
  316. package/dist/ui/shared/ui-icons.js +2 -0
  317. package/dist/ui/shared/ui-menu.js +20 -7
  318. package/dist/ui/shared/ui-toast.js +16 -3
  319. package/dist/ui/shared/usage-dialog.js +34 -3
  320. package/dist/ui/shared/view-strings.js +72 -0
  321. package/dist/ui/shared/web-authorize.js +198 -0
  322. package/dist/ui/web-terminal/terminal.css +4 -4
  323. package/dist/ui/web-terminal/terminal.html +1 -1
  324. package/dist/update-launch.d.ts +9 -0
  325. package/dist/update-launch.js +38 -12
  326. package/dist/update-launch.js.map +1 -1
  327. package/dist/usage/format-rich.js +6 -3
  328. package/dist/usage/format-rich.js.map +1 -1
  329. package/dist/usage/i18n-keys.d.ts +1 -1
  330. package/dist/usage/i18n-keys.js +2 -1
  331. package/dist/usage/i18n-keys.js.map +1 -1
  332. package/dist/usage/i18n.d.ts +13 -1
  333. package/dist/usage/i18n.js +29 -0
  334. package/dist/usage/i18n.js.map +1 -1
  335. package/dist/usage/providers.d.ts +81 -2
  336. package/dist/usage/providers.js +240 -38
  337. package/dist/usage/providers.js.map +1 -1
  338. package/dist/usage/usage-api.d.ts +5 -1
  339. package/dist/usage/usage-api.js +184 -58
  340. package/dist/usage/usage-api.js.map +1 -1
  341. package/dist/usage-report.d.ts +158 -0
  342. package/dist/usage-report.js +226 -0
  343. package/dist/usage-report.js.map +1 -0
  344. package/dist/usage-rollup.d.ts +51 -0
  345. package/dist/usage-rollup.js +168 -0
  346. package/dist/usage-rollup.js.map +1 -0
  347. package/dist/user-systemd.d.ts +24 -0
  348. package/dist/user-systemd.js +75 -0
  349. package/dist/user-systemd.js.map +1 -0
  350. package/dist/view-api.d.ts +39 -0
  351. package/dist/view-api.js +69 -6
  352. package/dist/view-api.js.map +1 -1
  353. package/dist/web-ambient.d.ts +72 -0
  354. package/dist/web-ambient.js +161 -0
  355. package/dist/web-ambient.js.map +1 -0
  356. package/dist/web-api.d.ts +98 -14
  357. package/dist/web-api.js +1027 -83
  358. package/dist/web-api.js.map +1 -1
  359. package/dist/web-appearance-policy.d.ts +4 -6
  360. package/dist/web-appearance-policy.js +5 -12
  361. package/dist/web-appearance-policy.js.map +1 -1
  362. package/dist/web-appearance-tools.d.ts +3 -0
  363. package/dist/web-appearance-tools.js +22 -3
  364. package/dist/web-appearance-tools.js.map +1 -1
  365. package/dist/web-appearance-view.d.ts +27 -2
  366. package/dist/web-appearance-view.js +129 -14
  367. package/dist/web-appearance-view.js.map +1 -1
  368. package/dist/web-appearance.d.ts +17 -3
  369. package/dist/web-appearance.js +85 -8
  370. package/dist/web-appearance.js.map +1 -1
  371. package/dist/web-asset-parts.d.ts +2 -2
  372. package/dist/web-asset-parts.js +3 -3
  373. package/dist/web-asset-parts.js.map +1 -1
  374. package/dist/web-auth.js +3 -1
  375. package/dist/web-auth.js.map +1 -1
  376. package/dist/web-backend-login.d.ts +130 -0
  377. package/dist/web-backend-login.js +225 -0
  378. package/dist/web-backend-login.js.map +1 -0
  379. package/dist/web-card.d.ts +14 -0
  380. package/dist/web-card.js +40 -6
  381. package/dist/web-card.js.map +1 -1
  382. package/dist/web-channel-echo.d.ts +7 -1
  383. package/dist/web-channel-echo.js +6 -2
  384. package/dist/web-channel-echo.js.map +1 -1
  385. package/dist/web-chat-history.d.ts +83 -0
  386. package/dist/web-chat-history.js +137 -5
  387. package/dist/web-chat-history.js.map +1 -1
  388. package/dist/web-commands.d.ts +6 -1
  389. package/dist/web-commands.js +1 -1
  390. package/dist/web-commands.js.map +1 -1
  391. package/dist/web-effect-bootstrap.d.ts +12 -0
  392. package/dist/web-effect-bootstrap.js +49 -0
  393. package/dist/web-effect-bootstrap.js.map +1 -0
  394. package/dist/web-effect-bundle.js +46 -1
  395. package/dist/web-effect-bundle.js.map +1 -1
  396. package/dist/web-effect-playback.d.ts +30 -0
  397. package/dist/web-effect-playback.js +71 -0
  398. package/dist/web-effect-playback.js.map +1 -0
  399. package/dist/web-effect-profiles.d.ts +4 -4
  400. package/dist/web-effect-service.d.ts +11 -4
  401. package/dist/web-effect-service.js +25 -4
  402. package/dist/web-effect-service.js.map +1 -1
  403. package/dist/web-effect-tools.d.ts +1 -0
  404. package/dist/web-effect-tools.js +4 -4
  405. package/dist/web-effect-tools.js.map +1 -1
  406. package/dist/web-effect-trials.d.ts +2 -2
  407. package/dist/web-effect-trials.js +3 -3
  408. package/dist/web-effect-trials.js.map +1 -1
  409. package/dist/web-effect-upload.js +1 -1
  410. package/dist/web-effect-upload.js.map +1 -1
  411. package/dist/web-effect-worker.d.ts +1 -1
  412. package/dist/web-effect-worker.js +2 -2
  413. package/dist/web-effect-worker.js.map +1 -1
  414. package/dist/web-effect.d.ts +1 -1
  415. package/dist/web-guest-access.d.ts +126 -0
  416. package/dist/web-guest-access.js +238 -0
  417. package/dist/web-guest-access.js.map +1 -0
  418. package/dist/web-guest-rooms.d.ts +82 -0
  419. package/dist/web-guest-rooms.js +135 -0
  420. package/dist/web-guest-rooms.js.map +1 -0
  421. package/dist/web-host-guard.d.ts +11 -0
  422. package/dist/web-host-guard.js +11 -0
  423. package/dist/web-host-guard.js.map +1 -1
  424. package/dist/web-identity-color.d.ts +1 -1
  425. package/dist/web-identity-color.js +2 -2
  426. package/dist/web-identity-color.js.map +1 -1
  427. package/dist/web-identity-palette.d.ts +1 -1
  428. package/dist/web-identity-palette.js +2 -2
  429. package/dist/web-identity-palette.js.map +1 -1
  430. package/dist/web-image-meta.d.ts +13 -0
  431. package/dist/web-image-meta.js +62 -0
  432. package/dist/web-image-meta.js.map +1 -1
  433. package/dist/web-libavoid.d.ts +14 -0
  434. package/dist/web-libavoid.js +46 -0
  435. package/dist/web-libavoid.js.map +1 -0
  436. package/dist/web-login.d.ts +47 -0
  437. package/dist/web-login.js +115 -0
  438. package/dist/web-login.js.map +1 -1
  439. package/dist/web-mod-agent.d.ts +1 -1
  440. package/dist/web-mod-agent.js +7 -5
  441. package/dist/web-mod-agent.js.map +1 -1
  442. package/dist/web-mod-bundle.d.ts +9 -1
  443. package/dist/web-mod-bundle.js +62 -3
  444. package/dist/web-mod-bundle.js.map +1 -1
  445. package/dist/web-mod-export.d.ts +9 -0
  446. package/dist/web-mod-export.js +21 -0
  447. package/dist/web-mod-export.js.map +1 -1
  448. package/dist/web-mod-store.d.ts +7 -1
  449. package/dist/web-mod-store.js +19 -6
  450. package/dist/web-mod-store.js.map +1 -1
  451. package/dist/web-owner-css-store.d.ts +44 -1
  452. package/dist/web-owner-css-store.js +70 -9
  453. package/dist/web-owner-css-store.js.map +1 -1
  454. package/dist/web-prefs.d.ts +14 -0
  455. package/dist/web-prefs.js +37 -4
  456. package/dist/web-prefs.js.map +1 -1
  457. package/dist/web-preview.d.ts +6 -2
  458. package/dist/web-preview.js +4 -2
  459. package/dist/web-preview.js.map +1 -1
  460. package/dist/web-returning-device.d.ts +41 -0
  461. package/dist/web-returning-device.js +57 -5
  462. package/dist/web-returning-device.js.map +1 -1
  463. package/dist/web-session-authorization.d.ts +132 -0
  464. package/dist/web-session-authorization.js +193 -0
  465. package/dist/web-session-authorization.js.map +1 -0
  466. package/dist/web-session.d.ts +70 -10
  467. package/dist/web-session.js +137 -22
  468. package/dist/web-session.js.map +1 -1
  469. package/dist/web-settings-patch.d.ts +49 -2
  470. package/dist/web-settings-patch.js +145 -1
  471. package/dist/web-settings-patch.js.map +1 -1
  472. package/dist/web-settings-tools.d.ts +94 -0
  473. package/dist/web-settings-tools.js +301 -0
  474. package/dist/web-settings-tools.js.map +1 -0
  475. package/dist/web-shell-routes.d.ts +1 -1
  476. package/dist/web-shell-routes.js +1 -1
  477. package/dist/web-shell-routes.js.map +1 -1
  478. package/dist/web-terminal-http.js +15 -2
  479. package/dist/web-terminal-http.js.map +1 -1
  480. package/dist/web-theme-store.d.ts +39 -0
  481. package/dist/web-theme-store.js +122 -11
  482. package/dist/web-theme-store.js.map +1 -1
  483. package/dist/web-theme.d.ts +31 -0
  484. package/dist/web-theme.js +99 -2
  485. package/dist/web-theme.js.map +1 -1
  486. package/dist/web-upload.d.ts +13 -0
  487. package/dist/web-upload.js +39 -3
  488. package/dist/web-upload.js.map +1 -1
  489. package/dist/windows-shortcuts.d.ts +78 -0
  490. package/dist/windows-shortcuts.js +203 -0
  491. package/dist/windows-shortcuts.js.map +1 -0
  492. package/dist/workflow-templates/default.md +4 -1
  493. package/dist/yaml-shared-nodes.d.ts +25 -0
  494. package/dist/yaml-shared-nodes.js +185 -0
  495. package/dist/yaml-shared-nodes.js.map +1 -0
  496. package/launcher/agend-install.cjs +553 -0
  497. package/launcher/install-admission.cjs +4 -39
  498. package/launcher/postinstall.cjs +14 -12
  499. package/package.json +4 -2
  500. package/scripts/preinstall-guard.cjs +2 -5
  501. package/templates/windows-shortcuts.ps1 +181 -0
  502. package/launcher/old-updater-note.cjs +0 -48
package/dist/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import "./node-warnings.js";
3
+ import { installFleetProcessHandlers } from "./fleet-process-handlers.js";
3
4
  import { applyNetworkReliabilityDefaults } from "./network-family.js";
4
5
  // Preserve Node's dual-stack Happy Eyeballs behavior, but avoid its 250ms
5
6
  // premature-connect failure on WSL/VPN/high-load hosts (#658).
@@ -13,6 +14,7 @@ applyNetworkReliabilityDefaults();
13
14
  import { checkNodeVersion } from "./node-version-guard.js";
14
15
  checkNodeVersion();
15
16
  import { Command } from "commander";
17
+ import { registerBugReportCommand } from "./bug-report-cli.js";
16
18
  import { join, dirname } from "node:path";
17
19
  import { SchedulerDb } from "./scheduler/db.js";
18
20
  import { Cron } from "croner";
@@ -24,7 +26,7 @@ import { getAgendHome, getTmuxSocketName, isDefaultAgendHome } from "./paths.js"
24
26
  import { hasPausedMarker } from "./pause-marker.js";
25
27
  import { COMPLETION_SHELLS, completionScript } from "./completion.js";
26
28
  import { getUpdateSelector, isExactVersion, isUnrequestedDowngrade, lookupTargetVersion, reportUpdateRestart, shouldSkipUpdate, runningFleetPredatesInstall, fleetProvenStopped, readFleetPidEvidence, pidAlive, processStartMs, } from "./update-check.js";
27
- import { clearUpdateMarker, markUpdateInProgress, setUpdateProgressStage } from "./update-marker.js";
29
+ import { clearUpdateMarker, markUpdateInProgress, readUpdateProgress, setUpdateProgressStage } from "./update-marker.js";
28
30
  import { describeSignalSource, forceAllowed, gateFleetControl, recordInstanceControl, withOrigin } from "./fleet-control-audit.js";
29
31
  import { FLEET_STOP_TIMEOUT_MS, stopDetachedOwner, systemdStopTimeoutMs, detachedProcessStart, detachedProcessExited } from "./fleet-stop-budget.js";
30
32
  import { acquireFleetLock, isFleetStartCommandLine, readProcessCommandLine, releaseProcessFleetLock, setProcessFleetLock } from "./fleet-lock.js";
@@ -144,6 +146,7 @@ program
144
146
  // The root's own options only before a subcommand: otherwise `agend update --version 2.1.9` is read as
145
147
  // `agend --version`, prints this version and installs nothing.
146
148
  .enablePositionalOptions();
149
+ registerBugReportCommand(program, pkgVersion);
147
150
  function signalFleetReload() {
148
151
  const pidPath = join(DATA_DIR, "fleet.pid");
149
152
  try {
@@ -275,67 +278,16 @@ fleet
275
278
  // without these a Ctrl-C or `systemctl stop` in that window got Node's default
276
279
  // behaviour: instant death with fleet.pid already written, databases unclosed,
277
280
  // and every tmux window orphaned.
278
- let stopping = false;
279
- const shutdown = async () => {
280
- if (stopping)
281
- return; // SIGINT and SIGTERM share this, and crash paths call stopAll too
282
- stopping = true;
283
- console.log("\nStopping fleet...");
284
- // stopAll fences new profile requests synchronously, before it awaits
285
- // the shared owner's stop/save. Stopping the env handle first would leave
286
- // the manager open to replacing that closed owner during the save.
287
- await fm.stopAll().catch(err => console.error("Shutdown error:", err));
288
- process.exit(0);
289
- };
290
- process.on("SIGINT", shutdown);
291
- process.on("SIGTERM", () => {
292
- // The restart that interrupted a fleet used to leave no trace of who asked.
293
- console.log(describeSignalSource(DATA_DIR, "SIGTERM"));
294
- void shutdown();
295
- });
296
- process.on("uncaughtException", (err) => {
297
- // An uncaught exception leaves unknown state — still the one case worth
298
- // tearing down for.
299
- console.error("Uncaught exception:", err);
300
- if (stopping)
301
- return;
302
- stopping = true;
303
- fm.stopAll().catch(() => { }).finally(() => process.exit(1));
304
- });
305
- process.on("unhandledRejection", (err) => {
306
- const msg = err instanceof Error ? err.message : String(err);
307
- // 409 = another bot poller exists — the adapter retries, don't crash.
308
- if (msg.includes("409") && msg.includes("getUpdates")) {
309
- console.error("Bot polling conflict (409) — retrying...");
310
- return;
311
- }
312
- // Do NOT take the fleet down. A rejected promise in one instance's tmux
313
- // call, health tick, or model switch used to stop every other working
314
- // instance and exit(1) — the widest blast radius in the process. The
315
- // per-instance health check and crash recovery handle a genuinely broken
316
- // instance on their own.
317
- //
318
- // Surviving quietly would be its own failure mode, so this reports to the
319
- // General topic as well as the log: the operator must not have to read
320
- // daemon.log to learn the fleet swallowed a fault. notifyFleetError()
321
- // throttles repeats, since these usually arrive from a loop.
322
- console.error("Unhandled rejection (fleet continues):", err);
323
- if (err instanceof Error && err.stack)
324
- console.error(err.stack);
325
- try {
326
- fm.notifyFleetError(`⚠️ Fleet caught an unhandled error and kept running:\n\`${msg}\`\nSee daemon.log for the stack trace.`);
327
- }
328
- catch (notifyErr) {
329
- // Never let the reporting path itself become an unhandled rejection.
330
- console.error("Failed to report unhandled rejection:", notifyErr);
331
- }
281
+ const handlers = installFleetProcessHandlers({
282
+ dataDir: DATA_DIR, manager: fm, runtime: process, console,
283
+ describeSignal: () => describeSignalSource(DATA_DIR, "SIGTERM"),
332
284
  });
333
285
  await fm.startCpuProfileControl().catch(err => console.warn(`Local profile control unavailable: ${String(err)}`));
334
286
  await fm.startSettingsConfirmationControl().catch(err => console.warn(`Local Settings confirmation unavailable: ${String(err)}`));
335
- if (stopping)
287
+ if (handlers.stopping)
336
288
  return;
337
289
  cpuProfile = await fm.startEnvironmentCpuProfile();
338
- if (stopping) {
290
+ if (handlers.stopping) {
339
291
  await cpuProfile?.stop("startup superseded by shutdown");
340
292
  return;
341
293
  }
@@ -559,31 +511,14 @@ fleet
559
511
  return;
560
512
  const { FleetManager } = await import("./fleet-manager.js");
561
513
  const fm = new FleetManager(DATA_DIR);
514
+ const handlers = installFleetProcessHandlers({
515
+ dataDir: DATA_DIR, manager: fm, runtime: process, console,
516
+ describeSignal: () => describeSignalSource(DATA_DIR, "SIGTERM"),
517
+ });
518
+ if (handlers.stopping)
519
+ return;
562
520
  await fm.startAll(FLEET_CONFIG_PATH);
563
521
  console.log("Fleet restarted with new code");
564
- // Keep process alive (same as fleet start)
565
- const shutdown = async () => {
566
- console.log("\nStopping fleet...");
567
- await fm.stopAll();
568
- process.exit(0);
569
- };
570
- process.on("SIGINT", shutdown);
571
- process.on("SIGTERM", shutdown);
572
- process.on("uncaughtException", async (err) => {
573
- console.error("Uncaught exception:", err);
574
- await fm.stopAll().catch(() => { });
575
- process.exit(1);
576
- });
577
- process.on("unhandledRejection", async (err) => {
578
- const msg = err instanceof Error ? err.message : String(err);
579
- if (msg.includes("409") && msg.includes("getUpdates")) {
580
- console.error("Bot polling conflict (409) — retrying...");
581
- return;
582
- }
583
- console.error("Unhandled rejection:", err);
584
- await fm.stopAll().catch(() => { });
585
- process.exit(1);
586
- });
587
522
  }
588
523
  else {
589
524
  // Instance-only restart (existing behavior)
@@ -1552,6 +1487,12 @@ program
1552
1487
  // the cleanup write later can prove it still owns the marker (checklist
1553
1488
  // 3/5). A missed capture only skips the marker write; retire still runs.
1554
1489
  let cleanupReceipt = null;
1490
+ // #2264 review: the old system copy is retired only for a confirmed 2.1-era layout — the copy this updater runs
1491
+ // from is a 2.1.x release (2.1's updater left it there). Never from "nvm" or "root" alone: a 2.2+ copy stays.
1492
+ if (verified.retireSystemCopy && !/^2\.1\./.test(pkgVersion)) {
1493
+ console.log(` Note: the system install (v${pkgVersion}) is kept; only a 2.1-era copy is retired after a move to nvm.`);
1494
+ delete verified.retireSystemCopy;
1495
+ }
1555
1496
  if (verified.retireSystemCopy) {
1556
1497
  try {
1557
1498
  const { markCleanupPending } = await import("./update-marker.js");
@@ -1664,6 +1605,9 @@ program
1664
1605
  const { planPath } = await import("./service-plan.js");
1665
1606
  planDeps().removeFile(planPath(DATA_DIR));
1666
1607
  }
1608
+ // #1853: in a WSL terminal without the Windows desktop shortcuts, say once how to make them (never makes them).
1609
+ if (outcome.ok)
1610
+ await import("./windows-shortcuts.js").then(m => m.printUpdateShortcutsHint(DATA_DIR)).catch(() => { });
1667
1611
  if (outcome.ok && outcome.via === "launchd-activation") {
1668
1612
  console.log(" ✓ Service restarted (launchd loaded the verified job)");
1669
1613
  // The new fleet clears the update marker once it is up.
@@ -1750,6 +1694,7 @@ program
1750
1694
  }
1751
1695
  console.log(`\n ✓ Already up to date (v${pkgVersion})\n`);
1752
1696
  setUpdateProgressStage(DATA_DIR, "complete", { version: pkgVersion });
1697
+ await import("./windows-shortcuts.js").then(m => m.printUpdateShortcutsHint(DATA_DIR)).catch(() => { });
1753
1698
  return;
1754
1699
  }
1755
1700
  if (isUnrequestedDowngrade(pkgVersion, targetVersion, opts)) {
@@ -1796,6 +1741,49 @@ program
1796
1741
  if (verdict.kind === "unknown")
1797
1742
  console.log(verdict.note);
1798
1743
  }
1744
+ // ── #2264: the target release installs itself ──
1745
+ // `agend update` only chooses the version; the install — repair, `npm install -g`, proof, service, restart, the
1746
+ // chat's progress — is that release's own installer (launcher/agend-install.cjs), fetched pinned by npm with its
1747
+ // integrity checks. So every update runs the NEWEST install logic, never this (possibly old) package's, and the
1748
+ // one-liner runs the same program. The code below this branch is the compatibility path, unchanged: for a prefix
1749
+ // that needs sudo (the nvm route), and for a target from before the installer.
1750
+ // Only a known target that ships the installer runs it: `npm exec --package <a release without agend-install>` would
1751
+ // run whatever agend-install PATH has (#2264 review). An older target, or one npm cannot describe, takes the
1752
+ // compatibility path below; `--target` makes any other installer refuse.
1753
+ const shipsInstaller = () => {
1754
+ const viewed = spawnSync("npm", ["view", pkg, "bin", "--json"], { encoding: "utf-8", timeout: 60_000, stdio: ["ignore", "pipe", "ignore"] });
1755
+ try {
1756
+ const parsed = JSON.parse(viewed.stdout || "null");
1757
+ const bin = Array.isArray(parsed) ? parsed[parsed.length - 1] : parsed;
1758
+ return viewed.status === 0 && !!bin && typeof bin === "object" && Object.hasOwn(bin, "agend-install");
1759
+ }
1760
+ catch {
1761
+ return false;
1762
+ }
1763
+ };
1764
+ const viaInstaller = !needsSudo && targetVersion !== null && shipsInstaller();
1765
+ if (!needsSudo && !viaInstaller)
1766
+ console.log(` ℹ ${pkg} has no installer of its own (a release from before #2264); this updater installs it.`);
1767
+ if (viaInstaller) {
1768
+ console.log(`\n Updating AgEnD v${pkgVersion} → v${targetVersion} (its own installer)...\n`);
1769
+ markUpdateInProgress(DATA_DIR);
1770
+ setUpdateProgressStage(DATA_DIR, "downloading", { version: targetVersion });
1771
+ // AGEND_UPDATE_OWNER_PID: the marker this process just wrote is the installer's to carry on (and no one else's).
1772
+ const installer = spawnSync("npm", ["exec", "--yes", "--package", pkg, "--", "agend-install", "--upgrade", "--target", targetVersion], {
1773
+ stdio: "inherit", env: { ...withOrigin("agend-update"), AGEND_UPDATE_OWNER_PID: String(process.pid) },
1774
+ });
1775
+ if (installer.status === 0 || installer.status === 75) {
1776
+ process.exitCode = installer.status ?? 0;
1777
+ return;
1778
+ }
1779
+ // The installer records its own failure; one that never started (npm could not fetch it) is recorded here.
1780
+ const progress = readUpdateProgress(DATA_DIR)?.progress;
1781
+ if (progress && progress.stage !== "failed" && progress.stage !== "complete") {
1782
+ setUpdateProgressStage(DATA_DIR, "failed", { error: `the installer for ${pkg} did not run (npm exec exited ${installer.status ?? installer.signal ?? installer.error?.message}); nothing was changed` });
1783
+ }
1784
+ process.exitCode = installer.status || 1;
1785
+ return;
1786
+ }
1799
1787
  if (targetVersion) {
1800
1788
  console.log(`\n Updating AgEnD v${pkgVersion} → v${targetVersion}...\n`);
1801
1789
  }
@@ -2013,6 +2001,19 @@ program
2013
2001
  console.log(t("install.updated"));
2014
2002
  }
2015
2003
  });
2004
+ program
2005
+ .command("shortcuts")
2006
+ .description("WSL: create or update the Windows desktop shortcuts (the dashboard and restart)")
2007
+ .action(async () => {
2008
+ // #1853: for an install that predates the installer's shortcuts, or that is only ever updated with `agend update`.
2009
+ const { runShortcuts, realShortcutsDeps } = await import("./windows-shortcuts.js");
2010
+ const { spawnSync } = await import("node:child_process");
2011
+ const { userInfo } = await import("node:os");
2012
+ process.exitCode = await runShortcuts(realShortcutsDeps(DATA_DIR, userInfo().username, (command, args) => {
2013
+ const r = spawnSync(command, args, { encoding: "utf-8", timeout: 120_000, stdio: ["ignore", "pipe", "pipe"] });
2014
+ return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "", error: r.error };
2015
+ }));
2016
+ });
2016
2017
  program
2017
2018
  .command("uninstall")
2018
2019
  .description("Remove the AgEnD system service")
@@ -2776,9 +2777,24 @@ program
2776
2777
  program
2777
2778
  .command("validate")
2778
2779
  .description("Validate fleet.yaml and classicBot.yaml")
2779
- .action(async () => {
2780
- const { validateFleetConfig, validateClassicBotConfig } = await import("./config-validator.js");
2780
+ .option("--connections", "Only print how many chat connections fleet.yaml has, as CONNECTIONS=<n> (for scripts; CONNECTIONS=unknown and exit 1 when it cannot be read)")
2781
+ .action(async (opts) => {
2782
+ const { validateFleetConfig, validateClassicBotConfig, configuredConnectionCount } = await import("./config-validator.js");
2781
2783
  const yaml = (await import("js-yaml")).default;
2784
+ if (opts.connections) {
2785
+ // #2233: the Windows installer's question — did the setup page make a web-only fleet? Parsed, never grepped.
2786
+ let count = null;
2787
+ try {
2788
+ count = configuredConnectionCount(yaml.load(readFileSync(FLEET_CONFIG_PATH, "utf-8")));
2789
+ }
2790
+ catch {
2791
+ count = null;
2792
+ }
2793
+ console.log(`CONNECTIONS=${count ?? "unknown"}`);
2794
+ if (count === null)
2795
+ process.exit(1);
2796
+ return;
2797
+ }
2782
2798
  const red = (s) => `\x1b[31m${s}\x1b[0m`;
2783
2799
  const green = (s) => `\x1b[32m${s}\x1b[0m`;
2784
2800
  const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
@@ -3081,26 +3097,88 @@ async function fuzzyMatch(query, names) {
3081
3097
  }
3082
3098
  async function resolveInstance(query, config) {
3083
3099
  const namesRaw = await listInstanceNames(config);
3084
- const names = [...new Set(namesRaw)]; // P3-3: deduplicate (a classicBot instanceName can equal a fleet name)
3085
- const { resolveName } = await import("./topic-commands.js");
3086
- const entries = names.map((name) => ({
3100
+ const names = [...new Set(namesRaw)];
3101
+ const { assignDisplayLabels } = await import("./topic-commands.js");
3102
+ const entries = names.map(name => ({
3087
3103
  name,
3088
- displayName: config.instances[name]?.display_name,
3104
+ displayName: config.instances[name]?.display_name ?? null,
3105
+ }));
3106
+ const labelMap = assignDisplayLabels(entries);
3107
+ // Build candidates with 1-based row index and status, matching ls order.
3108
+ const candidates = names.map((name, i) => ({
3109
+ idx: i + 1,
3110
+ realName: name,
3111
+ displayLabel: labelMap.get(name) ?? name,
3112
+ teams: getTeamsForInstance(config, name),
3113
+ status: getInstanceStatusStandalone(name),
3089
3114
  }));
3090
- const result = resolveName(query, entries);
3091
- if (result.kind === "name")
3092
- return result.realName;
3115
+ const { resolveCandidate } = await import("./ls-attach-resolve.js");
3116
+ // No argument on a TTY: show interactive picker.
3117
+ if (query === undefined) {
3118
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
3119
+ console.error("No instance specified.");
3120
+ process.exit(1);
3121
+ }
3122
+ return interactivePicker(candidates);
3123
+ }
3124
+ const result = resolveCandidate(query, candidates);
3125
+ if (result.kind === "exact")
3126
+ return result.candidate.realName;
3093
3127
  if (result.kind === "ambiguous") {
3094
- console.error(`"${query}" matches multiple instances: ${result.realNames.join(", ")}. Use the real name.`);
3128
+ if (process.stdin.isTTY && process.stdout.isTTY) {
3129
+ console.log(`"${query}" matches multiple instances:`);
3130
+ const { ambiguityLine } = await import("./ls-attach-resolve.js");
3131
+ const { computeLsNameWidth: cnw } = await import("./ls-rows.js");
3132
+ const maxNameW = cnw(result.candidates.map(c => c.realName), 0);
3133
+ for (const c of result.candidates) {
3134
+ console.log(ambiguityLine(c, maxNameW));
3135
+ }
3136
+ return interactivePicker(result.candidates);
3137
+ }
3138
+ const names2 = result.candidates.map(c => `${c.displayLabel} (${c.realName})`).join(", ");
3139
+ console.error(`"${query}" matches multiple instances: ${names2}. Use the real name.`);
3095
3140
  process.exit(1);
3096
3141
  }
3097
- // Fall through to the original fuzzy match on real names.
3098
- const match = await fuzzyMatch(query, names);
3099
- if (!match) {
3100
- console.error(`No instance matching "${query}". Available: ${names.join(", ")}`);
3101
- process.exit(1);
3142
+ // kind === "none" — show top-5 fuzzy suggestions, not the full list.
3143
+ const suggestions = result.suggestions;
3144
+ if (suggestions.length > 0) {
3145
+ console.error(`No instance matching "${query}". Did you mean:`);
3146
+ for (const c of suggestions) {
3147
+ console.error(` ${String(c.idx).padStart(2)}) ${c.displayLabel} (${c.realName})`);
3148
+ }
3102
3149
  }
3103
- return match;
3150
+ else {
3151
+ console.error(`No instance matching "${query}". Run "agend ls" to see all instances.`);
3152
+ }
3153
+ process.exit(1);
3154
+ }
3155
+ async function interactivePicker(candidates) {
3156
+ const running = candidates.filter(c => c.status === "running");
3157
+ const rest = candidates.filter(c => c.status !== "running");
3158
+ const ordered = [...running, ...rest];
3159
+ const { pickerDefaultIdx } = await import("./ls-attach-resolve.js");
3160
+ const defaultIdx = pickerDefaultIdx(ordered);
3161
+ const { pickerLine } = await import("./ls-attach-resolve.js");
3162
+ const { computeLsNameWidth: cnwPicker } = await import("./ls-rows.js");
3163
+ const maxNameW = cnwPicker(ordered.map(c => c.realName), 0);
3164
+ console.log("Select an instance:");
3165
+ for (const c of ordered) {
3166
+ console.log(pickerLine(c, maxNameW));
3167
+ }
3168
+ const { createInterface } = await import("node:readline");
3169
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
3170
+ // Use the unambiguous #N form so Enter always selects the displayed-first
3171
+ // row, even when its global idx matches a digit-string real name.
3172
+ const answer = await new Promise(resolve => rl.question(`\nRow number or name [#${defaultIdx}]: `, resolve));
3173
+ rl.close();
3174
+ const trimmed = answer.trim() || `#${defaultIdx}`;
3175
+ // Accept a number or re-run resolution.
3176
+ const { resolveCandidate } = await import("./ls-attach-resolve.js");
3177
+ const reResult = resolveCandidate(trimmed, candidates);
3178
+ if (reResult.kind === "exact")
3179
+ return reResult.candidate.realName;
3180
+ console.error(`Invalid selection "${trimmed}".`);
3181
+ process.exit(1);
3104
3182
  }
3105
3183
  function getInstanceStatusStandalone(name) {
3106
3184
  if (hasPausedMarker(join(DATA_DIR, "instances", name)))
@@ -3184,6 +3262,12 @@ async function lsAction(opts) {
3184
3262
  // status work (a tab press should not wait on the fleet) and must print
3185
3263
  // nothing but names — a "no instances" notice would become a candidate.
3186
3264
  if (opts.namesOnly) {
3265
+ const { validateNamesOnlyFilters } = await import("./ls-attach-resolve.js");
3266
+ const filterErr = validateNamesOnlyFilters(opts);
3267
+ if (filterErr) {
3268
+ console.error(filterErr);
3269
+ process.exit(1);
3270
+ }
3187
3271
  for (const n of await listInstanceNames(config))
3188
3272
  console.log(n);
3189
3273
  return;
@@ -3275,7 +3359,7 @@ async function lsAction(opts) {
3275
3359
  };
3276
3360
  // Row collection runs concurrently (see ls-rows.ts): the per-instance
3277
3361
  // tmux captures overlap instead of stacking their 2s bounds serially.
3278
- const { collectLsRows, capturePaneAsync, formatTimeSince, lsStatusIcon, lsStatusLabel, displayWidth } = await import("./ls-rows.js");
3362
+ const { collectLsRows, capturePaneAsync, formatTimeSince, lsStatusIcon, lsStatusLabel, displayWidth, computeLsNameWidth, padToDisplayWidth } = await import("./ls-rows.js");
3279
3363
  const { getTmuxSocketName } = await import("./paths.js");
3280
3364
  const socketName = getTmuxSocketName();
3281
3365
  const rows = await collectLsRows(allNames.map(name => {
@@ -3337,8 +3421,25 @@ async function lsAction(opts) {
3337
3421
  }
3338
3422
  }
3339
3423
  catch { /* fleet not running or API unreachable */ }
3424
+ // Assign stable global indices BEFORE any filtering (#P2-1 — filters must not
3425
+ // renumber rows, so `agend attach N` always resolves the same instance).
3426
+ const { applyLsFilters } = await import("./ls-attach-resolve.js");
3427
+ const allRowsIndexed = rows.map((r, i) => ({ ...r, globalIdx: i + 1 }));
3428
+ // Apply --running / --team / --backend CLI filters. Done before --json so
3429
+ // `ls --json --running` honours the flag (#P2-2).
3430
+ const filteredMeta = applyLsFilters(allRowsIndexed.map(r => ({
3431
+ globalIdx: r.globalIdx,
3432
+ realName: r.name,
3433
+ displayLabel: r.name,
3434
+ status: (r.status ?? "stopped"),
3435
+ teams: r.teams,
3436
+ backend: r.backend,
3437
+ })), { running: opts.running, team: opts.team, backend: opts.backend });
3438
+ const filteredNames = new Set(filteredMeta.map(m => m.realName));
3439
+ const displayRows = allRowsIndexed.filter(r => filteredNames.has(r.name));
3340
3440
  if (opts.json) {
3341
- console.log(JSON.stringify(rows, null, 2));
3441
+ // Strip internal globalIdx from JSON output to keep the schema stable.
3442
+ console.log(JSON.stringify(displayRows.map(({ globalIdx: _idx, ...rest }) => rest), null, 2));
3342
3443
  return;
3343
3444
  }
3344
3445
  // Merged State column (#1052): one glyph per lifecycle/execution state,
@@ -3350,19 +3451,24 @@ async function lsAction(opts) {
3350
3451
  // across the fleet (#1305 P2-1). --json and --names-only above keep the
3351
3452
  // real names (machine use + attach target).
3352
3453
  const { assignDisplayLabels } = await import("./topic-commands.js");
3353
- const lsLabels = assignDisplayLabels(rows.map((r) => ({
3454
+ const { lsDisplayAnnotation } = await import("./ls-attach-resolve.js");
3455
+ const lsLabels = assignDisplayLabels(displayRows.map((r) => ({
3354
3456
  name: r.name,
3355
3457
  displayName: config.instances[r.name]?.display_name,
3356
3458
  })));
3357
- const displayName = (row) => lsLabels.get(row.name) ?? row.name;
3358
- const nameW = Math.max(20, ...rows.map(r => displayWidth(displayName(r)) + 2));
3459
+ const displayLabel = (row) => lsLabels.get(row.name) ?? row.name;
3460
+ // Columns: # (global row number), Name (real, full, copyable), then the rest.
3461
+ // Display name (if set) appears at the end of the row as context — secondary.
3462
+ const numW = 3;
3463
+ const nameW = computeLsNameWidth(displayRows.map(r => r.name));
3359
3464
  const backendW = 14;
3360
3465
  const statusW = 12;
3361
3466
  const teamW = 20;
3362
3467
  const srcW = 4;
3363
3468
  const ctxW = 8;
3364
3469
  const memW = 8;
3365
- console.log("Name".padEnd(nameW) +
3470
+ console.log("#".padEnd(numW) +
3471
+ "Name".padEnd(nameW) +
3366
3472
  "Backend".padEnd(backendW) +
3367
3473
  "Status".padEnd(statusW) +
3368
3474
  "Team".padEnd(teamW) +
@@ -3370,25 +3476,28 @@ async function lsAction(opts) {
3370
3476
  "Ctx".padEnd(ctxW) +
3371
3477
  "Mem".padEnd(memW) +
3372
3478
  "Activity");
3373
- console.log("\u2500".repeat(nameW + backendW + statusW + teamW + srcW + ctxW + memW + 10));
3374
- for (const r of rows) {
3479
+ console.log("\u2500".repeat(numW + nameW + backendW + statusW + teamW + srcW + ctxW + memW + 10));
3480
+ for (const r of displayRows) {
3375
3481
  const teamStr = r.teams.length > 0 ? r.teams.join(",") : "-";
3376
3482
  const ctxStr = r.context != null ? `${Math.round(r.context)}%` : "-";
3377
3483
  const memStr = r.memMb != null ? `${r.memMb}MB` : "-";
3378
3484
  const actStr = r.lastActivity ?? "-";
3379
- console.log(padDisplay(displayName(r), nameW) +
3485
+ const dispAnnotation = lsDisplayAnnotation(r.name, displayLabel(r), opts.display ?? false);
3486
+ console.log(String(r.globalIdx).padEnd(numW) +
3487
+ padToDisplayWidth(r.name, nameW) +
3380
3488
  r.backend.padEnd(backendW) +
3381
3489
  statusIcon(r.status, r.idle, r.state) + " " + statusLabel(r.status, r.idle, r.state).padEnd(statusW - 2) +
3382
3490
  padDisplay(teamStr, teamW) +
3383
3491
  r.source.padEnd(srcW) +
3384
3492
  ctxStr.padEnd(ctxW) +
3385
3493
  memStr.padEnd(memW) +
3386
- actStr);
3494
+ actStr +
3495
+ dispAnnotation);
3387
3496
  }
3388
3497
  // System memory footer
3389
- const totalMemMb = rows.reduce((sum, r) => sum + (r.memMb ?? 0), 0);
3390
- const runningCount = rows.filter(r => r.status === "running").length;
3391
- const pausedCount = rows.filter(r => r.status === "paused").length;
3498
+ const totalMemMb = displayRows.reduce((sum, r) => sum + (r.memMb ?? 0), 0);
3499
+ const runningCount = displayRows.filter(r => r.status === "running").length;
3500
+ const pausedCount = displayRows.filter(r => r.status === "paused").length;
3392
3501
  const totalGB = totalmem() / (1024 ** 3);
3393
3502
  const usedGB = (totalmem() - freemem()) / (1024 ** 3);
3394
3503
  console.log(`\nInstances: ${runningCount} running, ${pausedCount} paused | Fleet Mem: ${(totalMemMb / 1024).toFixed(1)} GB | System Memory: ${usedGB.toFixed(1)} / ${totalGB.toFixed(1)} GB`);
@@ -3408,6 +3517,10 @@ program
3408
3517
  .option("--json", "Output as JSON")
3409
3518
  .option("--names-only", "Print instance names one per line (for shell completion)")
3410
3519
  .option("--resources", "Also report workspace disk usage, unregistered instance directories, and host memory/swap (text only)")
3520
+ .option("--running", "Show only running instances")
3521
+ .option("--team <name>", "Filter by team name")
3522
+ .option("--backend <name>", "Filter by backend (exact match)")
3523
+ .option("--display", "Show display names as last column")
3411
3524
  .action(async (opts) => {
3412
3525
  await lsAction(opts);
3413
3526
  });
@@ -3642,8 +3755,8 @@ program
3642
3755
  });
3643
3756
  program
3644
3757
  .command("attach")
3645
- .description("Attach to an instance's tmux window (fuzzy match)")
3646
- .argument("<name>", "Instance name (supports fuzzy matching)")
3758
+ .description("Attach to an instance's tmux window. Accepts display name, instance name, row number from ls, or a substring. No argument: interactive picker.")
3759
+ .argument("[name]", "Instance name, display name, row number, or substring (omit for interactive picker)")
3647
3760
  .action(async (query) => {
3648
3761
  const yaml = (await import("js-yaml")).default;
3649
3762
  const config = yaml.load(readFileSync(FLEET_CONFIG_PATH, "utf-8"));