@songsid/agend 2.2.0-beta.2 → 2.2.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 (389) hide show
  1. package/README.md +40 -24
  2. package/README.zh-TW.md +40 -24
  3. package/dist/agent-cli-instructions.md +6 -2
  4. package/dist/agent-cli.js +15 -7
  5. package/dist/agent-cli.js.map +1 -1
  6. package/dist/agent-endpoint.js +3 -0
  7. package/dist/agent-endpoint.js.map +1 -1
  8. package/dist/agent-whats-new.js +16 -4
  9. package/dist/agent-whats-new.js.map +1 -1
  10. package/dist/auth-api.d.ts +3 -1
  11. package/dist/auth-api.js +17 -1
  12. package/dist/auth-api.js.map +1 -1
  13. package/dist/backend/antigravity.d.ts +33 -0
  14. package/dist/backend/antigravity.js +126 -18
  15. package/dist/backend/antigravity.js.map +1 -1
  16. package/dist/backend/claude-carry.d.ts +22 -0
  17. package/dist/backend/claude-carry.js +170 -0
  18. package/dist/backend/claude-carry.js.map +1 -0
  19. package/dist/backend/claude-code.d.ts +65 -2
  20. package/dist/backend/claude-code.js +226 -33
  21. package/dist/backend/claude-code.js.map +1 -1
  22. package/dist/backend/codex-metadata.d.ts +33 -0
  23. package/dist/backend/codex-metadata.js +122 -18
  24. package/dist/backend/codex-metadata.js.map +1 -1
  25. package/dist/backend/codex.d.ts +3 -0
  26. package/dist/backend/codex.js +17 -1
  27. package/dist/backend/codex.js.map +1 -1
  28. package/dist/backend/credential-profile.d.ts +40 -3
  29. package/dist/backend/credential-profile.js +113 -5
  30. package/dist/backend/credential-profile.js.map +1 -1
  31. package/dist/backend/effort-metadata.d.ts +37 -1
  32. package/dist/backend/effort-metadata.js +86 -15
  33. package/dist/backend/effort-metadata.js.map +1 -1
  34. package/dist/backend/grok.d.ts +4 -0
  35. package/dist/backend/grok.js +14 -0
  36. package/dist/backend/grok.js.map +1 -1
  37. package/dist/backend/kiro.d.ts +27 -1
  38. package/dist/backend/kiro.js +63 -10
  39. package/dist/backend/kiro.js.map +1 -1
  40. package/dist/backend/launch-effort.d.ts +61 -0
  41. package/dist/backend/launch-effort.js +170 -0
  42. package/dist/backend/launch-effort.js.map +1 -0
  43. package/dist/backend/muse.d.ts +84 -0
  44. package/dist/backend/muse.js +449 -53
  45. package/dist/backend/muse.js.map +1 -1
  46. package/dist/backend/types.d.ts +48 -2
  47. package/dist/backend/types.js +12 -1
  48. package/dist/backend/types.js.map +1 -1
  49. package/dist/backend-command.d.ts +91 -0
  50. package/dist/backend-command.js +122 -0
  51. package/dist/backend-command.js.map +1 -0
  52. package/dist/background-work-ended.d.ts +18 -0
  53. package/dist/background-work-ended.js +30 -0
  54. package/dist/background-work-ended.js.map +1 -0
  55. package/dist/cache-service.d.ts +2 -0
  56. package/dist/cache-service.js +2 -1
  57. package/dist/cache-service.js.map +1 -1
  58. package/dist/channel/adapters/discord.d.ts +26 -1
  59. package/dist/channel/adapters/discord.js +103 -3
  60. package/dist/channel/adapters/discord.js.map +1 -1
  61. package/dist/channel/adapters/telegram.d.ts +35 -3
  62. package/dist/channel/adapters/telegram.js +122 -23
  63. package/dist/channel/adapters/telegram.js.map +1 -1
  64. package/dist/channel/mcp-tools.js +5 -3
  65. package/dist/channel/mcp-tools.js.map +1 -1
  66. package/dist/channel/message-edit-errors.d.ts +5 -0
  67. package/dist/channel/message-edit-errors.js +24 -0
  68. package/dist/channel/message-edit-errors.js.map +1 -0
  69. package/dist/channel/telegram-markdown.d.ts +6 -0
  70. package/dist/channel/telegram-markdown.js +104 -0
  71. package/dist/channel/telegram-markdown.js.map +1 -0
  72. package/dist/channel/tool-router.d.ts +2 -0
  73. package/dist/channel/tool-router.js +6 -5
  74. package/dist/channel/tool-router.js.map +1 -1
  75. package/dist/channel/types.d.ts +46 -4
  76. package/dist/cli.js +184 -34
  77. package/dist/cli.js.map +1 -1
  78. package/dist/command-table.d.ts +2 -2
  79. package/dist/command-table.js +5 -2
  80. package/dist/command-table.js.map +1 -1
  81. package/dist/compact-watch.d.ts +86 -0
  82. package/dist/compact-watch.js +288 -0
  83. package/dist/compact-watch.js.map +1 -0
  84. package/dist/config-validator.js +55 -5
  85. package/dist/config-validator.js.map +1 -1
  86. package/dist/config.d.ts +1 -0
  87. package/dist/config.js +2 -1
  88. package/dist/config.js.map +1 -1
  89. package/dist/cross-instance-envelope.js +2 -0
  90. package/dist/cross-instance-envelope.js.map +1 -1
  91. package/dist/daemon.d.ts +129 -1
  92. package/dist/daemon.js +754 -94
  93. package/dist/daemon.js.map +1 -1
  94. package/dist/delivery-outbox.d.ts +64 -8
  95. package/dist/delivery-outbox.js +315 -24
  96. package/dist/delivery-outbox.js.map +1 -1
  97. package/dist/delivery-reconciliation.d.ts +18 -1
  98. package/dist/delivery-reconciliation.js +67 -2
  99. package/dist/delivery-reconciliation.js.map +1 -1
  100. package/dist/doctor.js +7 -0
  101. package/dist/doctor.js.map +1 -1
  102. package/dist/fleet-context.d.ts +12 -1
  103. package/dist/fleet-manager.d.ts +392 -19
  104. package/dist/fleet-manager.js +2030 -275
  105. package/dist/fleet-manager.js.map +1 -1
  106. package/dist/forged-envelope-scan.d.ts +4 -3
  107. package/dist/forged-envelope-scan.js +4 -3
  108. package/dist/forged-envelope-scan.js.map +1 -1
  109. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +84 -16
  110. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +16 -1
  111. package/dist/general-knowledge/skills/model-discovery/SKILL.md +4 -1
  112. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +4 -0
  113. package/dist/host-memory.d.ts +10 -0
  114. package/dist/host-memory.js +33 -1
  115. package/dist/host-memory.js.map +1 -1
  116. package/dist/human-delivery-receipts.d.ts +83 -0
  117. package/dist/human-delivery-receipts.js +194 -0
  118. package/dist/human-delivery-receipts.js.map +1 -0
  119. package/dist/install-lock.d.ts +18 -1
  120. package/dist/install-lock.js +30 -3
  121. package/dist/install-lock.js.map +1 -1
  122. package/dist/instance-avatar.d.ts +5 -4
  123. package/dist/instance-avatar.js +12 -8
  124. package/dist/instance-avatar.js.map +1 -1
  125. package/dist/instance-config-impact.js +1 -0
  126. package/dist/instance-config-impact.js.map +1 -1
  127. package/dist/instance-lifecycle.d.ts +25 -6
  128. package/dist/instance-lifecycle.js +76 -27
  129. package/dist/instance-lifecycle.js.map +1 -1
  130. package/dist/instructions.d.ts +1 -1
  131. package/dist/instructions.js +3 -3
  132. package/dist/instructions.js.map +1 -1
  133. package/dist/kiro-compact-pane.d.ts +38 -0
  134. package/dist/kiro-compact-pane.js +57 -0
  135. package/dist/kiro-compact-pane.js.map +1 -0
  136. package/dist/kiro-log-gate.d.ts +42 -0
  137. package/dist/kiro-log-gate.js +39 -0
  138. package/dist/kiro-log-gate.js.map +1 -0
  139. package/dist/launchd-handoff.d.ts +43 -0
  140. package/dist/launchd-handoff.js +56 -0
  141. package/dist/launchd-handoff.js.map +1 -0
  142. package/dist/locale.js +268 -42
  143. package/dist/locale.js.map +1 -1
  144. package/dist/log-service.d.ts +99 -0
  145. package/dist/log-service.js +243 -0
  146. package/dist/log-service.js.map +1 -0
  147. package/dist/log-steps.d.ts +169 -0
  148. package/dist/log-steps.js +858 -0
  149. package/dist/log-steps.js.map +1 -0
  150. package/dist/login-controller.d.ts +20 -3
  151. package/dist/login-controller.js +71 -19
  152. package/dist/login-controller.js.map +1 -1
  153. package/dist/login-flows.d.ts +5 -2
  154. package/dist/login-flows.js +5 -4
  155. package/dist/login-flows.js.map +1 -1
  156. package/dist/login-shell.d.ts +21 -0
  157. package/dist/login-shell.js +98 -0
  158. package/dist/login-shell.js.map +1 -0
  159. package/dist/memory-pressure.d.ts +13 -1
  160. package/dist/memory-pressure.js +50 -10
  161. package/dist/memory-pressure.js.map +1 -1
  162. package/dist/needs-you-hub.js +2 -0
  163. package/dist/needs-you-hub.js.map +1 -1
  164. package/dist/needs-you-live.d.ts +6 -0
  165. package/dist/needs-you-live.js +23 -3
  166. package/dist/needs-you-live.js.map +1 -1
  167. package/dist/outbound-handlers.d.ts +100 -0
  168. package/dist/outbound-handlers.js +277 -93
  169. package/dist/outbound-handlers.js.map +1 -1
  170. package/dist/outbound-schemas.d.ts +30 -15
  171. package/dist/outbound-schemas.js +23 -5
  172. package/dist/outbound-schemas.js.map +1 -1
  173. package/dist/provider-probe.d.ts +29 -0
  174. package/dist/provider-probe.js +198 -2
  175. package/dist/provider-probe.js.map +1 -1
  176. package/dist/public-link-progress.d.ts +1 -1
  177. package/dist/public-link-progress.js +8 -2
  178. package/dist/public-link-progress.js.map +1 -1
  179. package/dist/public-preview.d.ts +101 -0
  180. package/dist/public-preview.js +236 -0
  181. package/dist/public-preview.js.map +1 -0
  182. package/dist/public-web-gateway.d.ts +2 -0
  183. package/dist/public-web-gateway.js +20 -6
  184. package/dist/public-web-gateway.js.map +1 -1
  185. package/dist/public-web-link.d.ts +24 -1
  186. package/dist/public-web-link.js +63 -9
  187. package/dist/public-web-link.js.map +1 -1
  188. package/dist/quickstart-api.d.ts +1 -1
  189. package/dist/quickstart-api.js +8 -6
  190. package/dist/quickstart-api.js.map +1 -1
  191. package/dist/quickstart.d.ts +12 -0
  192. package/dist/quickstart.js +36 -6
  193. package/dist/quickstart.js.map +1 -1
  194. package/dist/reply-buttons-controller.d.ts +89 -5
  195. package/dist/reply-buttons-controller.js +273 -8
  196. package/dist/reply-buttons-controller.js.map +1 -1
  197. package/dist/reply-buttons.d.ts +48 -3
  198. package/dist/reply-buttons.js +105 -10
  199. package/dist/reply-buttons.js.map +1 -1
  200. package/dist/reply-polls.d.ts +85 -0
  201. package/dist/reply-polls.js +154 -0
  202. package/dist/reply-polls.js.map +1 -0
  203. package/dist/restart-guard.d.ts +6 -3
  204. package/dist/restart-guard.js +6 -3
  205. package/dist/restart-guard.js.map +1 -1
  206. package/dist/restart-progress.d.ts +33 -2
  207. package/dist/restart-progress.js +30 -2
  208. package/dist/restart-progress.js.map +1 -1
  209. package/dist/sd-notify.d.ts +22 -1
  210. package/dist/sd-notify.js +63 -10
  211. package/dist/sd-notify.js.map +1 -1
  212. package/dist/service-activation.d.ts +15 -7
  213. package/dist/service-activation.js +42 -26
  214. package/dist/service-activation.js.map +1 -1
  215. package/dist/service-installer.d.ts +55 -0
  216. package/dist/service-installer.js +90 -3
  217. package/dist/service-installer.js.map +1 -1
  218. package/dist/service-plan.d.ts +11 -0
  219. package/dist/service-plan.js +23 -0
  220. package/dist/service-plan.js.map +1 -1
  221. package/dist/settings-api.js +14 -4
  222. package/dist/settings-api.js.map +1 -1
  223. package/dist/settings-change.js +4 -2
  224. package/dist/settings-change.js.map +1 -1
  225. package/dist/settings-effect.js +2 -0
  226. package/dist/settings-effect.js.map +1 -1
  227. package/dist/spawn-gate.js +5 -1
  228. package/dist/spawn-gate.js.map +1 -1
  229. package/dist/spawn-hold-reply.d.ts +12 -0
  230. package/dist/spawn-hold-reply.js +39 -0
  231. package/dist/spawn-hold-reply.js.map +1 -0
  232. package/dist/systemd-peer-bus.d.ts +95 -0
  233. package/dist/systemd-peer-bus.js +430 -0
  234. package/dist/systemd-peer-bus.js.map +1 -0
  235. package/dist/systemd-runtime.d.ts +27 -1
  236. package/dist/systemd-runtime.js +69 -7
  237. package/dist/systemd-runtime.js.map +1 -1
  238. package/dist/tips.js +1 -1
  239. package/dist/tips.js.map +1 -1
  240. package/dist/tool-permissions.js +3 -3
  241. package/dist/tool-permissions.js.map +1 -1
  242. package/dist/tool-progress.js +3 -2
  243. package/dist/tool-progress.js.map +1 -1
  244. package/dist/topic-commands.d.ts +71 -4
  245. package/dist/topic-commands.js +167 -34
  246. package/dist/topic-commands.js.map +1 -1
  247. package/dist/transcript-delta-reader.d.ts +3 -3
  248. package/dist/transcript-delta-reader.js +8 -8
  249. package/dist/transcript-delta-reader.js.map +1 -1
  250. package/dist/transcript-jsonl.d.ts +85 -3
  251. package/dist/transcript-jsonl.js +156 -13
  252. package/dist/transcript-jsonl.js.map +1 -1
  253. package/dist/transcript-monitor.d.ts +11 -0
  254. package/dist/transcript-monitor.js +61 -13
  255. package/dist/transcript-monitor.js.map +1 -1
  256. package/dist/transcript-sources.d.ts +24 -0
  257. package/dist/transcript-sources.js +211 -56
  258. package/dist/transcript-sources.js.map +1 -1
  259. package/dist/tunnel/cloudflared.d.ts +7 -15
  260. package/dist/tunnel/cloudflared.js +36 -1
  261. package/dist/tunnel/cloudflared.js.map +1 -1
  262. package/dist/tunnel/purpose-lane.d.ts +5 -1
  263. package/dist/tunnel/purpose-lane.js +14 -7
  264. package/dist/tunnel/purpose-lane.js.map +1 -1
  265. package/dist/tunnel/types.d.ts +5 -1
  266. package/dist/tunnel/types.js.map +1 -1
  267. package/dist/turn-resume.d.ts +2 -0
  268. package/dist/turn-resume.js +1 -1
  269. package/dist/turn-resume.js.map +1 -1
  270. package/dist/types.d.ts +22 -0
  271. package/dist/ui/chat-commands.js +1 -0
  272. package/dist/ui/chat-mentions.js +63 -0
  273. package/dist/ui/chat-render.js +80 -10
  274. package/dist/ui/chat-store.js +70 -6
  275. package/dist/ui/chat-strings.js +62 -32
  276. package/dist/ui/chat-thread.js +199 -24
  277. package/dist/ui/chat-time.js +80 -0
  278. package/dist/ui/chat-tour.js +17 -14
  279. package/dist/ui/panel-chat.js +45 -21
  280. package/dist/ui/panel-details.js +2 -0
  281. package/dist/ui/panel-fleet.js +213 -58
  282. package/dist/ui/panel-log.js +428 -0
  283. package/dist/ui/panel-needs.js +14 -10
  284. package/dist/ui/panel-settings.js +82 -17
  285. package/dist/ui/preview-panel.js +55 -15
  286. package/dist/ui/preview-status.js +28 -0
  287. package/dist/ui/preview.js +44 -3
  288. package/dist/ui/settings-dialogs.js +11 -6
  289. package/dist/ui/settings-model.js +3 -1
  290. package/dist/ui/settings-strings.js +32 -12
  291. package/dist/ui/settings-token.js +8 -1
  292. package/dist/ui/settings-wizard.js +5 -3
  293. package/dist/ui/shared/app-i18n.js +41 -15
  294. package/dist/ui/shared/app-prefs.js +250 -0
  295. package/dist/ui/shared/app-route.js +6 -1
  296. package/dist/ui/shared/app-shell.js +165 -8
  297. package/dist/ui/shared/app-store.js +5 -1
  298. package/dist/ui/shared/app-stream.js +26 -5
  299. package/dist/ui/shared/app.css +170 -30
  300. package/dist/ui/shared/app.js +11 -1
  301. package/dist/ui/shared/fonts/README.md +1 -1
  302. package/dist/ui/shared/header-tools.js +83 -13
  303. package/dist/ui/shared/instance-nav.js +178 -51
  304. package/dist/ui/shared/instance-switch.js +8 -5
  305. package/dist/ui/shared/panel-view.js +21 -4
  306. package/dist/ui/shared/signin.js +15 -9
  307. package/dist/ui/shared/theme.js +39 -7
  308. package/dist/ui/shared/tokens.css +1 -1
  309. package/dist/ui/shared/ui-icons.js +2 -0
  310. package/dist/ui/shared/usage-dialog.js +23 -5
  311. package/dist/ui/shared/view-strings.js +40 -4
  312. package/dist/ui/signin.html +8 -3
  313. package/dist/unrecognised-prompt.d.ts +23 -0
  314. package/dist/unrecognised-prompt.js +74 -0
  315. package/dist/unrecognised-prompt.js.map +1 -0
  316. package/dist/update-check.d.ts +31 -0
  317. package/dist/update-check.js +47 -0
  318. package/dist/update-check.js.map +1 -1
  319. package/dist/update-install.d.ts +13 -1
  320. package/dist/update-install.js +16 -4
  321. package/dist/update-install.js.map +1 -1
  322. package/dist/update-launch.d.ts +48 -1
  323. package/dist/update-launch.js +159 -5
  324. package/dist/update-launch.js.map +1 -1
  325. package/dist/update-marker.d.ts +51 -0
  326. package/dist/update-marker.js +61 -0
  327. package/dist/update-marker.js.map +1 -1
  328. package/dist/usage/i18n-keys.d.ts +1 -1
  329. package/dist/usage/i18n-keys.js +1 -1
  330. package/dist/usage/i18n-keys.js.map +1 -1
  331. package/dist/usage/providers.d.ts +62 -13
  332. package/dist/usage/providers.js +256 -68
  333. package/dist/usage/providers.js.map +1 -1
  334. package/dist/usage/statusline-usage.d.ts +6 -2
  335. package/dist/usage/statusline-usage.js +10 -4
  336. package/dist/usage/statusline-usage.js.map +1 -1
  337. package/dist/view-api.js +31 -9
  338. package/dist/view-api.js.map +1 -1
  339. package/dist/web-api.d.ts +82 -4
  340. package/dist/web-api.js +632 -88
  341. package/dist/web-api.js.map +1 -1
  342. package/dist/web-auth.js +5 -2
  343. package/dist/web-auth.js.map +1 -1
  344. package/dist/web-chat-history.d.ts +26 -1
  345. package/dist/web-chat-history.js +47 -8
  346. package/dist/web-chat-history.js.map +1 -1
  347. package/dist/web-commands.d.ts +41 -5
  348. package/dist/web-commands.js +25 -7
  349. package/dist/web-commands.js.map +1 -1
  350. package/dist/web-login.d.ts +14 -0
  351. package/dist/web-login.js +4 -2
  352. package/dist/web-login.js.map +1 -1
  353. package/dist/web-mentions.d.ts +44 -0
  354. package/dist/web-mentions.js +75 -0
  355. package/dist/web-mentions.js.map +1 -0
  356. package/dist/web-prefs.d.ts +81 -0
  357. package/dist/web-prefs.js +297 -0
  358. package/dist/web-prefs.js.map +1 -0
  359. package/dist/web-preview.d.ts +14 -1
  360. package/dist/web-preview.js +35 -13
  361. package/dist/web-preview.js.map +1 -1
  362. package/dist/web-profile.d.ts +32 -0
  363. package/dist/web-profile.js +132 -0
  364. package/dist/web-profile.js.map +1 -0
  365. package/dist/web-reply-files.d.ts +45 -0
  366. package/dist/web-reply-files.js +223 -0
  367. package/dist/web-reply-files.js.map +1 -0
  368. package/dist/web-schedules.d.ts +12 -0
  369. package/dist/web-schedules.js +34 -0
  370. package/dist/web-schedules.js.map +1 -0
  371. package/dist/web-server-drain.d.ts +10 -0
  372. package/dist/web-server-drain.js +50 -0
  373. package/dist/web-server-drain.js.map +1 -0
  374. package/dist/web-session.d.ts +14 -0
  375. package/dist/web-session.js +11 -1
  376. package/dist/web-session.js.map +1 -1
  377. package/dist/web-settings-patch.d.ts +3 -1
  378. package/dist/web-settings-patch.js +4 -1
  379. package/dist/web-settings-patch.js.map +1 -1
  380. package/dist/web-shell-routes.d.ts +4 -0
  381. package/dist/web-shell-routes.js +9 -0
  382. package/dist/web-shell-routes.js.map +1 -1
  383. package/dist/web-upload.d.ts +135 -7
  384. package/dist/web-upload.js +315 -51
  385. package/dist/web-upload.js.map +1 -1
  386. package/launcher/install-admission.cjs +61 -6
  387. package/package.json +3 -3
  388. package/templates/launchd.plist.ejs +3 -1
  389. package/templates/systemd.service.ejs +2 -1
@@ -1,8 +1,9 @@
1
1
  import { PaneContextCache } from "./pane-context-cache.js";
2
+ import { LOGIN_BACKEND_ALIASES } from "./login-flows.js";
2
3
  import { measureSyncWork } from "./sync-work-attribution.js";
3
4
  import { LOOPBACK_HOST_NAMES } from "./web-host-guard.js";
4
5
  import { WEB_REMOTE_DOCS_URL } from "./upgrade-notices.js";
5
- import { readFileSync, existsSync } from "node:fs";
6
+ import { closeSync, readFileSync, existsSync } from "node:fs";
6
7
  import { exec, execFileSync } from "node:child_process";
7
8
  import { promisify } from "node:util";
8
9
  import { join, basename } from "node:path";
@@ -20,10 +21,11 @@ import { runVisibilityCommand } from "./cross-instance-notice.js";
20
21
  import { clampContextPercent, parseContextPercent, parseTokenContextRatio, } from "./context-percent.js";
21
22
  import { isGeneralInstance } from "./general-instance.js";
22
23
  import { instanceSupportsSteer } from "./steer-capability.js";
24
+ import { compareSemver } from "./update-check.js";
23
25
  import { SYSINFO_BACKEND_IDS } from "./backend/types.js";
24
26
  import { recordInternalRequest, withOrigin } from "./fleet-control-audit.js";
25
27
  import { resolveInstalledAgend } from "./update-dispatch.js";
26
- import { resolveUpdateLaunch, watchUpdateLaunch } from "./update-launch.js";
28
+ import { resolveUpdateLaunch, openUpdateLog, updateLogPath, watchUpdateLaunch } from "./update-launch.js";
27
29
  import { selfCommand } from "./cli-entry.js";
28
30
  export { parseContextPercent, parseTokenContextRatio } from "./context-percent.js";
29
31
  /** Longest one setMyCommands call may take. */
@@ -159,6 +161,54 @@ function disambiguateLabel(name, explicit, base, used) {
159
161
  }
160
162
  /** Allowed filename for /save and /load (no path separators, no shell/inject chars). */
161
163
  export const SAVE_FILENAME_RE = /^[\w.-]+$/;
164
+ /**
165
+ * #1809: resolve a display label (as shown by `agend ls`) back to a real instance name.
166
+ * Returns the real name on a unique match, `null` when the query does not match any label,
167
+ * or `{ ambiguous: true, realNames }` when two labels are identical under case-folding
168
+ * (e.g. display_names "Prism" and "prism" both fold to "prism").
169
+ * Always case-insensitive. Real names are NOT resolved here — callers must try real names first.
170
+ */
171
+ export function resolveByLabel(query, entries) {
172
+ const labelMap = assignDisplayLabels(entries);
173
+ const q = query.toLowerCase();
174
+ const matches = [];
175
+ for (const [realName, label] of labelMap) {
176
+ if (label.toLowerCase() === q)
177
+ matches.push(realName);
178
+ }
179
+ if (matches.length === 0)
180
+ return null;
181
+ if (matches.length === 1)
182
+ return matches[0];
183
+ return { ambiguous: true, realNames: matches };
184
+ }
185
+ /**
186
+ * #1809: full label/name resolution pipeline without process.exit or readline — suitable for
187
+ * unit testing and for callers that want to decide what to do on each outcome.
188
+ *
189
+ * Resolution order:
190
+ * 1. Exact match on real name (case-insensitive) — always wins.
191
+ * 2. Exact match on the display label `agend ls` shows (via `resolveByLabel`).
192
+ * 3. No match → `{ kind: "none" }`.
193
+ *
194
+ * Returns `{ kind: "name", realName }` on success,
195
+ * `{ kind: "ambiguous", realNames }` when two labels are case-identical,
196
+ * or `{ kind: "none" }` when nothing matched.
197
+ */
198
+ export function resolveName(query, entries) {
199
+ // Step 1: exact real-name match wins.
200
+ const q = query.toLowerCase();
201
+ const exactReal = entries.find(e => e.name.toLowerCase() === q);
202
+ if (exactReal)
203
+ return { kind: "name", realName: exactReal.name };
204
+ // Step 2: label match.
205
+ const labelResult = resolveByLabel(query, entries);
206
+ if (labelResult === null)
207
+ return { kind: "none" };
208
+ if (typeof labelResult === "string")
209
+ return { kind: "name", realName: labelResult };
210
+ return { kind: "ambiguous", realNames: labelResult.realNames };
211
+ }
162
212
  /** Backends with a native side-question command that does not steer the active turn. */
163
213
  export const BTW_SUPPORTED_BACKENDS = new Set(["claude-code"]);
164
214
  /**
@@ -240,10 +290,18 @@ function backendCliLines(versions) {
240
290
  }),
241
291
  ];
242
292
  }
243
- export function compactCommandForBackend(backend) {
244
- if (backend === "antigravity")
245
- return "/clear";
246
- return "/compact";
293
+ /**
294
+ * Board 0340ec89: agy's own `/compact` summarizes the conversation (verified on 1.3.6: "Conversation compacted · 5 steps
295
+ * summarized", tests/fixtures/agy-1.3.6-compact.pane.txt). AgEnD used to send `/clear` for an agy compact, which wiped
296
+ * the conversation instead. An agy known to be older than the version `/compact` was verified on is refused (null),
297
+ * never cleared; an agy whose version is not known yet gets `/compact` (a version without it ignores the line).
298
+ */
299
+ export const AGY_COMPACT_MIN_VERSION = "1.3.6";
300
+ export function compactCommandForBackend(backend, version) {
301
+ if (backend !== "antigravity")
302
+ return "/compact";
303
+ const v = typeof version === "string" ? version.match(/\d+\.\d+\.\d+/)?.[0] : undefined;
304
+ return v && (compareSemver(v, AGY_COMPACT_MIN_VERSION) ?? 0) < 0 ? null : "/compact";
247
305
  }
248
306
  /**
249
307
  * Backends whose `/compact` verifiably takes custom summarization instructions
@@ -255,7 +313,7 @@ export function compactCommandForBackend(backend) {
255
313
  * compact into a prompt, so it must never be appended.
256
314
  * - grok 1.0.46: the binary answers "/compact takes no arguments."
257
315
  * - opencode 1.18: `/compact` calls session.summarize with no text.
258
- * - kiro-cli: takes none (audit); antigravity has no summarizing compact.
316
+ * - kiro-cli: takes none (audit); antigravity's own /compact (1.3.6+, board 0340ec89) takes none either.
259
317
  * - muse 1.4.2: accepts the line (empty session: "nothing to summarize") but
260
318
  * no use of the text is verifiable — unsupported until shown otherwise.
261
319
  */
@@ -446,6 +504,7 @@ const INSTANCE_FORMS = [
446
504
  ["collab", bare("collab")],
447
505
  ["effort", withArgs("effort")],
448
506
  ["model", withArgs("model")],
507
+ ["backend", withArgs("backend")],
449
508
  ["compact", text => parseCompactCommand(text) !== null],
450
509
  ["steer", withArgs("steer")],
451
510
  ["btw", withArgs("btw")],
@@ -488,8 +547,15 @@ export class TopicCommands {
488
547
  }, "telegram");
489
548
  if (decision.allow || "passthrough" in decision)
490
549
  return null;
550
+ // A command off for want of fleet admins names where they go (`{0}` in its disabled reply).
551
+ if (decision.reply === spec.disabled)
552
+ return [...decision.reply, this.adminListKey(msg.adapterId)];
491
553
  return decision.reply;
492
554
  }
555
+ /** Where the adapter's fleet-admin list is in fleet.yaml (the fleet's answer; a bare key without it). */
556
+ adminListKey(adapterId) {
557
+ return this.ctx.adminListKey?.(adapterId) ?? "access.allowed_users";
558
+ }
493
559
  async sendRefusal(msg, [key, ...args]) {
494
560
  const adapter = this.getReplyAdapter(msg);
495
561
  if (adapter)
@@ -595,6 +661,13 @@ export class TopicCommands {
595
661
  }
596
662
  return false;
597
663
  }
664
+ /**
665
+ * General's action-first menu. The click owns private issuance; no URL or code exists in this copy.
666
+ */
667
+ getDashboardMenuText() {
668
+ const access = this.ctx.getDashboardAccess?.();
669
+ return access?.ready && access.token ? t("dashboard.menu_instruction") : t("dashboard.starting");
670
+ }
598
671
  /**
599
672
  * Pure, secret-free dashboard/menu copy. Issuance belongs to the private
600
673
  * delivery action; rendering or previewing this text cannot retire a code.
@@ -632,7 +705,7 @@ export class TopicCommands {
632
705
  const threadId = msg.threadId;
633
706
  // The caller's own adapter decides, and an empty list means the command is off for everyone.
634
707
  if (!this.ctx.hasFleetAdmins(msg.adapterId)) {
635
- await adapter.sendText(chatId, t("dashboard.disabled"), { threadId });
708
+ await adapter.sendText(chatId, t("dashboard.disabled", this.adminListKey(msg.adapterId)), { threadId });
636
709
  return;
637
710
  }
638
711
  if (!this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
@@ -769,6 +842,23 @@ export class TopicCommands {
769
842
  }
770
843
  return true;
771
844
  }
845
+ if (command === "backend") {
846
+ const adapter = this.getReplyAdapter(msg);
847
+ if (!adapter)
848
+ return false;
849
+ // #1806: the same gate as /model.
850
+ if (!this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
851
+ await adapter.sendText(msg.chatId, t("permission.denied"), { threadId: msg.threadId });
852
+ return true;
853
+ }
854
+ if (this.ctx.runBackendCommand) {
855
+ await this.ctx.runBackendCommand(instanceName, text, msg.userId, msg.threadId ?? msg.chatId, adapter, msg.chatId, msg.threadId, msg.adapterId);
856
+ }
857
+ else {
858
+ await adapter.sendText(msg.chatId, t("backend.usage"), { threadId: msg.threadId });
859
+ }
860
+ return true;
861
+ }
772
862
  if (command === "compact") {
773
863
  const compact = parseCompactCommand(text);
774
864
  const adapter = this.getReplyAdapter(msg);
@@ -989,6 +1079,14 @@ export class TopicCommands {
989
1079
  }
990
1080
  /** Send the backend-appropriate compact command to an instance's tmux pane */
991
1081
  async sendCompact(instanceName, instructions) {
1082
+ return this.compactInstance(instanceName, instructions).text;
1083
+ }
1084
+ /**
1085
+ * sendCompact, saying whether the command was handed to the daemon (the web chat follows a sent one to its end,
1086
+ * board 003648ac). `notify` runs only when it is about to be handed over; its id rides along so the daemon says when
1087
+ * the command reached the pane (`raw_paste_written`). A write the IPC refuses is not sent.
1088
+ */
1089
+ compactInstance(instanceName, instructions, notify) {
992
1090
  const ipc = this.ctx.instanceIpcClients.get(instanceName);
993
1091
  if (ipc?.connected) {
994
1092
  const classicBackend = this.ctx.classicChannels?.getChannelIdByInstance(instanceName)
@@ -997,26 +1095,34 @@ export class TopicCommands {
997
1095
  const backend = this.ctx.fleetConfig?.instances[instanceName]?.backend
998
1096
  ?? classicBackend
999
1097
  ?? this.ctx.fleetConfig?.defaults?.backend ?? "claude-code";
1000
- const base = compactCommandForBackend(backend);
1098
+ const agyVersion = backend === "antigravity" ? this.ctx.getBackendCliVersionSnapshot?.()?.antigravity?.version ?? null : null;
1099
+ const base = compactCommandForBackend(backend, agyVersion);
1100
+ if (base === null)
1101
+ return { sent: false, text: t("compact.unsupported_version", backend, agyVersion ?? "?", AGY_COMPACT_MIN_VERSION) };
1001
1102
  const custom = normalizeCompactInstructions(instructions);
1002
1103
  if (custom.length > COMPACT_INSTRUCTIONS_MAX) {
1003
1104
  // Refuse rather than cut: a truncated instruction is a different instruction.
1004
- return t("compact.instructions_too_long", String(COMPACT_INSTRUCTIONS_MAX));
1105
+ return { sent: false, text: t("compact.instructions_too_long", String(COMPACT_INSTRUCTIONS_MAX)) };
1005
1106
  }
1107
+ const id = notify?.() ?? null;
1108
+ const paste = (content) => ipc.send({ type: "raw_paste", content, ...(id ? { notify_written: id } : {}) }) !== false;
1006
1109
  if (!custom) {
1007
- ipc.send({ type: "raw_paste", content: base });
1008
- return t("compact.sent", base);
1110
+ if (!paste(base))
1111
+ return { sent: false, text: t("compact.not_connected") };
1112
+ return { sent: true, text: t("compact.sent", base) };
1009
1113
  }
1010
1114
  if (backendSupportsCompactInstructions(backend)) {
1011
- ipc.send({ type: "raw_paste", content: `${base} ${custom}` });
1012
- return t("compact.sent_with_instructions", base);
1115
+ if (!paste(`${base} ${custom}`))
1116
+ return { sent: false, text: t("compact.not_connected") };
1117
+ return { sent: true, text: t("compact.sent_with_instructions", base) };
1013
1118
  }
1014
1119
  // Compact as asked, without the text, and say so — never send it (codex
1015
1120
  // would take it for a chat message) and never drop it unannounced.
1016
- ipc.send({ type: "raw_paste", content: base });
1017
- return `${t("compact.sent", base)}\n${t("compact.instructions_ignored", backend)}`;
1121
+ if (!paste(base))
1122
+ return { sent: false, text: t("compact.not_connected") };
1123
+ return { sent: true, text: `${t("compact.sent", base)}\n${t("compact.instructions_ignored", backend)}` };
1018
1124
  }
1019
- return t("compact.not_connected");
1125
+ return { sent: false, text: t("compact.not_connected") };
1020
1126
  }
1021
1127
  /** Whether the instance backend exposes a verified full-reset command. */
1022
1128
  supportsClear(instanceName) {
@@ -1046,7 +1152,7 @@ export class TopicCommands {
1046
1152
  const ipc = this.ctx.instanceIpcClients.get(instanceName);
1047
1153
  if (!ipc?.connected)
1048
1154
  return t("steer.not_connected");
1049
- ipc.send({
1155
+ const payload = {
1050
1156
  type: "steer",
1051
1157
  content,
1052
1158
  delivery_epoch: this.ctx.getDeliveryEpoch?.(instanceName) ?? undefined,
@@ -1059,7 +1165,12 @@ export class TopicCommands {
1059
1165
  adapter_id: msg.adapterId ?? "",
1060
1166
  source: msg.source,
1061
1167
  },
1062
- });
1168
+ };
1169
+ const sent = this.ctx.sendHumanControl
1170
+ ? this.ctx.sendHumanControl(instanceName, payload, msg.humanOrigin, msg.humanOriginalBody ?? content)
1171
+ : ipc.send(payload) !== false;
1172
+ if (!sent)
1173
+ return t("steer.not_connected");
1063
1174
  return t("steer.sent", instanceName);
1064
1175
  }
1065
1176
  /** Ask a Claude Code side question without folding it into the active turn. */
@@ -1070,7 +1181,7 @@ export class TopicCommands {
1070
1181
  const ipc = this.ctx.instanceIpcClients.get(instanceName);
1071
1182
  if (!ipc?.connected)
1072
1183
  return t("btw.not_connected");
1073
- ipc.send({
1184
+ const payload = {
1074
1185
  type: "btw",
1075
1186
  content,
1076
1187
  delivery_epoch: this.ctx.getDeliveryEpoch?.(instanceName) ?? undefined,
@@ -1083,25 +1194,34 @@ export class TopicCommands {
1083
1194
  adapter_id: msg.adapterId ?? "",
1084
1195
  source: msg.source,
1085
1196
  },
1086
- });
1197
+ };
1198
+ const sent = this.ctx.sendHumanControl
1199
+ ? this.ctx.sendHumanControl(instanceName, payload, msg.humanOrigin, msg.humanOriginalBody ?? content)
1200
+ : ipc.send(payload) !== false;
1201
+ if (!sent)
1202
+ return t("btw.not_connected");
1087
1203
  return t("btw.sent", instanceName);
1088
1204
  }
1089
1205
  /** Send the backend-appropriate full conversation reset through raw_paste. */
1090
1206
  async sendClear(instanceName) {
1207
+ return this.clearInstance(instanceName).text;
1208
+ }
1209
+ /** sendClear, saying whether the command was handed to the daemon (board 003648ac: the web chat's card then leaves). */
1210
+ clearInstance(instanceName) {
1091
1211
  const backend = this.effectiveBackend(instanceName);
1092
1212
  const cmd = clearCommandForBackend(backend);
1093
1213
  if (!cmd)
1094
- return t("clear.unsupported");
1214
+ return { sent: false, text: t("clear.unsupported") };
1095
1215
  const ipc = this.ctx.instanceIpcClients.get(instanceName);
1096
1216
  if (ipc?.connected) {
1097
- ipc.send({
1217
+ const sent = ipc.send({
1098
1218
  type: "raw_paste",
1099
1219
  content: cmd,
1100
1220
  ...(backend === "kiro-cli" ? { confirm_clear: true } : {}),
1101
- });
1102
- return t("clear.sent", cmd);
1221
+ }) !== false;
1222
+ return sent ? { sent: true, text: t("clear.sent", cmd) } : { sent: false, text: t("clear.not_connected") };
1103
1223
  }
1104
- return t("clear.not_connected");
1224
+ return { sent: false, text: t("clear.not_connected") };
1105
1225
  }
1106
1226
  /** Send a backend-appropriate session-save command to a fleet-topic instance. */
1107
1227
  async sendSave(instanceName, filename) {
@@ -1212,11 +1332,17 @@ export class TopicCommands {
1212
1332
  await adapter.sendText(msg.chatId, await this.ctx.cancelLoginSession(), { threadId: msg.threadId });
1213
1333
  return;
1214
1334
  }
1215
- if (/\s/.test(arg)) {
1335
+ // `<backend> [profile]` (#1699 part 2): a second word is the credential profile to sign in; nothing more.
1336
+ const words = arg.split(/\s+/);
1337
+ // A profile only after a backend this fleet can sign in: `/login reinstall codex` stays a usage error (#1137).
1338
+ if (words.length > 2 || (words.length === 2 && !Object.hasOwn(LOGIN_BACKEND_ALIASES, words[0].toLowerCase()))) {
1216
1339
  await adapter.sendText(msg.chatId, t("login.usage"), { threadId: msg.threadId });
1217
1340
  return;
1218
1341
  }
1219
- const started = await this.ctx.startLoginSession(arg, chat);
1342
+ const [backend, profile] = words;
1343
+ const started = profile !== undefined
1344
+ ? await this.ctx.startLoginSession(backend, chat, { profile })
1345
+ : await this.ctx.startLoginSession(backend, chat);
1220
1346
  // null → the still-valid-auth confirmation prompt was posted instead.
1221
1347
  if (started)
1222
1348
  await adapter.sendText(msg.chatId, started, { threadId: msg.threadId });
@@ -1481,7 +1607,7 @@ export class TopicCommands {
1481
1607
  const threadId = msg.threadId;
1482
1608
  // Access control — only fleet admins of THIS adapter can trigger an update; empty = disabled
1483
1609
  if (!this.ctx.hasFleetAdmins(msg.adapterId)) {
1484
- await adapter.sendText(chatId, t("update.disabled"), { threadId });
1610
+ await adapter.sendText(chatId, t("update.disabled", this.adminListKey(msg.adapterId)), { threadId });
1485
1611
  return;
1486
1612
  }
1487
1613
  if (!this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
@@ -1494,7 +1620,7 @@ export class TopicCommands {
1494
1620
  // agend, verified by identity, by absolute path — or a refusal, never whatever `agend` is first on PATH.
1495
1621
  const installed = await resolveInstalledAgend();
1496
1622
  if (!installed.ok) {
1497
- this.ctx.failUpdateProgress?.(`/update cannot verify the installed AgEnD (${installed.reason}). Run \`agend update\` from a shell.`);
1623
+ this.ctx.failUpdateProgress?.(`${t("update.failure.shell")} ${t("update.failure.installed", installed.reason)}`);
1498
1624
  return;
1499
1625
  }
1500
1626
  const { spawn } = await import("node:child_process");
@@ -1502,17 +1628,22 @@ export class TopicCommands {
1502
1628
  recordInternalRequest(this.ctx.dataDir, "update", origin);
1503
1629
  const launch = await resolveUpdateLaunch(installed.agend);
1504
1630
  if (!launch.ok) {
1505
- this.ctx.failUpdateProgress?.(`/update cannot prepare an independent updater (${launch.reason}). Run ` + "`agend update` from a host shell.");
1631
+ this.ctx.failUpdateProgress?.(`${t("update.failure.shell")} ${t("update.failure.independent", launch.reason)}`);
1506
1632
  return;
1507
1633
  }
1508
1634
  if (!this.ctx.hasFleetAdmins(msg.adapterId) || !this.ctx.isFleetAdmin(msg.userId, msg.adapterId) || this.ctx.isFleetStopping()) {
1509
1635
  this.ctx.failUpdateProgress?.(t("not_authorized"));
1510
1636
  return;
1511
1637
  }
1638
+ const logPath = updateLogPath(this.ctx.dataDir);
1639
+ const ts = new Date().toISOString();
1640
+ const logFd = openUpdateLog(logPath, `--- /update ${ts} ---`);
1512
1641
  const child = spawn(launch.command, launch.args, {
1513
- detached: true, stdio: "ignore", env: withOrigin(origin),
1642
+ detached: true, stdio: ["ignore", logFd ? logFd.fd : "ignore", logFd ? logFd.fd : "ignore"], env: withOrigin(origin),
1514
1643
  });
1515
- watchUpdateLaunch(child, message => this.ctx.failUpdateProgress?.(message));
1644
+ if (logFd)
1645
+ closeSync(logFd.fd);
1646
+ watchUpdateLaunch(child, message => this.ctx.failUpdateProgress?.(message), logFd ? logPath : undefined, logFd?.offset, installed.agend);
1516
1647
  child.unref();
1517
1648
  }
1518
1649
  /** #1302: `/visibility [full|summary|hidden]` in the General topic. */
@@ -1704,6 +1835,8 @@ export class TopicCommands {
1704
1835
  this.ctx.logger.warn({ adapterId }, "Skipping Telegram bot-command registration — the bot token is not set");
1705
1836
  return;
1706
1837
  }
1838
+ // #1736: honour telegram_api_root the same way the adapter does.
1839
+ const apiRoot = (ch.telegram_api_root ?? "https://api.telegram.org").replace(/\/+$/, "");
1707
1840
  // Locks come from the command table's Telegram column (#1177), descriptions from the locale.
1708
1841
  const menu = (which) => telegramMenu(which).map(({ name, lock, argHint }) => ({
1709
1842
  command: name,
@@ -1712,7 +1845,7 @@ export class TopicCommands {
1712
1845
  const fleetCommands = menu("fleet");
1713
1846
  const classicCommands = menu("classic");
1714
1847
  const setCommands = async (commands, scope) => {
1715
- const response = await fetch(`https://api.telegram.org/bot${botToken}/setMyCommands`, {
1848
+ const response = await fetch(`${apiRoot}/bot${botToken}/setMyCommands`, {
1716
1849
  method: "POST",
1717
1850
  headers: { "Content-Type": "application/json" },
1718
1851
  body: JSON.stringify({ commands, scope }),