@songsid/agend 2.3.2 → 2.3.3-beta.10

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 (393) hide show
  1. package/dist/agent-cli-instructions.md +2 -2
  2. package/dist/agent-cli.js +13 -112
  3. package/dist/agent-cli.js.map +1 -1
  4. package/dist/agent-endpoint.d.ts +0 -1
  5. package/dist/agent-endpoint.js +1 -9
  6. package/dist/agent-endpoint.js.map +1 -1
  7. package/dist/agent-whats-new.d.ts +23 -5
  8. package/dist/agent-whats-new.js +58 -40
  9. package/dist/agent-whats-new.js.map +1 -1
  10. package/dist/auth-api.d.ts +0 -7
  11. package/dist/auth-api.js +1 -15
  12. package/dist/auth-api.js.map +1 -1
  13. package/dist/authority/authority-state.js +1 -1
  14. package/dist/authority/authority-state.js.map +1 -1
  15. package/dist/authority/web-authority.d.ts +9 -4
  16. package/dist/authority/web-authority.js +10 -5
  17. package/dist/authority/web-authority.js.map +1 -1
  18. package/dist/backend/antigravity.js +6 -1
  19. package/dist/backend/antigravity.js.map +1 -1
  20. package/dist/backend/claude-code.d.ts +20 -1
  21. package/dist/backend/claude-code.js +54 -29
  22. package/dist/backend/claude-code.js.map +1 -1
  23. package/dist/backend/claude-transcript-errors.d.ts +18 -0
  24. package/dist/backend/claude-transcript-errors.js +19 -0
  25. package/dist/backend/claude-transcript-errors.js.map +1 -0
  26. package/dist/backend/codex-session-lookup.d.ts +16 -3
  27. package/dist/backend/codex-session-lookup.js +45 -11
  28. package/dist/backend/codex-session-lookup.js.map +1 -1
  29. package/dist/backend/codex.d.ts +16 -0
  30. package/dist/backend/codex.js +184 -35
  31. package/dist/backend/codex.js.map +1 -1
  32. package/dist/backend/grok.js +58 -12
  33. package/dist/backend/grok.js.map +1 -1
  34. package/dist/backend/kiro-reconcile-store.js +8 -1
  35. package/dist/backend/kiro-reconcile-store.js.map +1 -1
  36. package/dist/backend/kiro.d.ts +0 -5
  37. package/dist/backend/kiro.js +2 -10
  38. package/dist/backend/kiro.js.map +1 -1
  39. package/dist/backend/muse.js +2 -1
  40. package/dist/backend/muse.js.map +1 -1
  41. package/dist/backend/types.d.ts +53 -4
  42. package/dist/backend/types.js.map +1 -1
  43. package/dist/bundled-skills.d.ts +4 -6
  44. package/dist/bundled-skills.js +10 -14
  45. package/dist/bundled-skills.js.map +1 -1
  46. package/dist/channel/adapters/discord.js +60 -17
  47. package/dist/channel/adapters/discord.js.map +1 -1
  48. package/dist/channel/mcp-server.js +5 -5
  49. package/dist/channel/mcp-server.js.map +1 -1
  50. package/dist/channel/mcp-tools.d.ts +1 -3
  51. package/dist/channel/mcp-tools.js +4 -58
  52. package/dist/channel/mcp-tools.js.map +1 -1
  53. package/dist/classic-channel-manager.d.ts +4 -1
  54. package/dist/classic-channel-manager.js +21 -7
  55. package/dist/classic-channel-manager.js.map +1 -1
  56. package/dist/cli.js +23 -6
  57. package/dist/cli.js.map +1 -1
  58. package/dist/config-history.d.ts +50 -0
  59. package/dist/config-history.js +263 -0
  60. package/dist/config-history.js.map +1 -0
  61. package/dist/config-validator.js +10 -8
  62. package/dist/config-validator.js.map +1 -1
  63. package/dist/config.d.ts +3 -0
  64. package/dist/config.js +11 -4
  65. package/dist/config.js.map +1 -1
  66. package/dist/cross-instance-envelope.d.ts +10 -5
  67. package/dist/cross-instance-envelope.js +20 -17
  68. package/dist/cross-instance-envelope.js.map +1 -1
  69. package/dist/daemon.d.ts +130 -64
  70. package/dist/daemon.js +603 -428
  71. package/dist/daemon.js.map +1 -1
  72. package/dist/daily-summary.d.ts +8 -1
  73. package/dist/daily-summary.js +8 -5
  74. package/dist/daily-summary.js.map +1 -1
  75. package/dist/dashboard-live.d.ts +1 -1
  76. package/dist/dashboard-live.js +3 -3
  77. package/dist/dashboard-live.js.map +1 -1
  78. package/dist/dashboard-permissions.d.ts +1 -1
  79. package/dist/dashboard-permissions.js +1 -3
  80. package/dist/dashboard-permissions.js.map +1 -1
  81. package/dist/delivery-outbox.d.ts +31 -22
  82. package/dist/delivery-outbox.js +119 -161
  83. package/dist/delivery-outbox.js.map +1 -1
  84. package/dist/delivery-outbox.test.js +10 -25
  85. package/dist/delivery-outbox.test.js.map +1 -1
  86. package/dist/doctor.d.ts +4 -0
  87. package/dist/doctor.js +16 -1
  88. package/dist/doctor.js.map +1 -1
  89. package/dist/fleet-level-config.js +1 -1
  90. package/dist/fleet-level-config.js.map +1 -1
  91. package/dist/fleet-manager.d.ts +74 -66
  92. package/dist/fleet-manager.js +285 -414
  93. package/dist/fleet-manager.js.map +1 -1
  94. package/dist/fleet-process-handlers.d.ts +5 -0
  95. package/dist/fleet-process-handlers.js +21 -0
  96. package/dist/fleet-process-handlers.js.map +1 -1
  97. package/dist/fleet-service-owner.d.ts +11 -0
  98. package/dist/fleet-service-owner.js +3 -0
  99. package/dist/fleet-service-owner.js.map +1 -0
  100. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +11 -1
  101. package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +1 -1
  102. package/dist/general-knowledge/skills/fleet-restart/SKILL.md +1 -1
  103. package/dist/general-knowledge/skills/session-management/SKILL.md +7 -1
  104. package/dist/general-knowledge/skills/web-appearance/SKILL.md +13 -204
  105. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +30 -68
  106. package/dist/instance-lifecycle.d.ts +19 -0
  107. package/dist/instance-lifecycle.js +73 -15
  108. package/dist/instance-lifecycle.js.map +1 -1
  109. package/dist/instructions.js +6 -7
  110. package/dist/instructions.js.map +1 -1
  111. package/dist/kiro-reconcile.js +3 -3
  112. package/dist/kiro-reconcile.js.map +1 -1
  113. package/dist/locale.js +96 -58
  114. package/dist/locale.js.map +1 -1
  115. package/dist/log-service.js +1 -1
  116. package/dist/log-service.js.map +1 -1
  117. package/dist/needs-you-hub.d.ts +1 -0
  118. package/dist/needs-you-hub.js +6 -3
  119. package/dist/needs-you-hub.js.map +1 -1
  120. package/dist/needs-you-live.d.ts +3 -1
  121. package/dist/needs-you-live.js +24 -2
  122. package/dist/needs-you-live.js.map +1 -1
  123. package/dist/needs-you.d.ts +13 -2
  124. package/dist/needs-you.js +11 -1
  125. package/dist/needs-you.js.map +1 -1
  126. package/dist/notify-socket.d.ts +10 -0
  127. package/dist/notify-socket.js +45 -0
  128. package/dist/notify-socket.js.map +1 -0
  129. package/dist/outbound-handlers.js +20 -8
  130. package/dist/outbound-handlers.js.map +1 -1
  131. package/dist/outbound-schemas.d.ts +0 -62
  132. package/dist/outbound-schemas.js +4 -43
  133. package/dist/outbound-schemas.js.map +1 -1
  134. package/dist/parked-notices.d.ts +87 -0
  135. package/dist/parked-notices.js +194 -0
  136. package/dist/parked-notices.js.map +1 -0
  137. package/dist/public-link-progress.d.ts +5 -2
  138. package/dist/public-link-progress.js +4 -3
  139. package/dist/public-link-progress.js.map +1 -1
  140. package/dist/public-web-gateway.js +0 -9
  141. package/dist/public-web-gateway.js.map +1 -1
  142. package/dist/public-web-link.d.ts +12 -0
  143. package/dist/public-web-link.js +29 -5
  144. package/dist/public-web-link.js.map +1 -1
  145. package/dist/quota-notice.d.ts +23 -0
  146. package/dist/quota-notice.js +22 -0
  147. package/dist/quota-notice.js.map +1 -0
  148. package/dist/scheduler/task-board.d.ts +17 -25
  149. package/dist/scheduler/task-board.js +29 -39
  150. package/dist/scheduler/task-board.js.map +1 -1
  151. package/dist/sd-notify.d.ts +23 -15
  152. package/dist/sd-notify.js +88 -29
  153. package/dist/sd-notify.js.map +1 -1
  154. package/dist/search/search-docs.d.ts +1 -1
  155. package/dist/search/search-docs.js +2 -2
  156. package/dist/search/search-docs.js.map +1 -1
  157. package/dist/settings-api.d.ts +16 -1
  158. package/dist/settings-api.js +56 -16
  159. package/dist/settings-api.js.map +1 -1
  160. package/dist/settings-change.js +3 -1
  161. package/dist/settings-change.js.map +1 -1
  162. package/dist/settings-confirmation.d.ts +17 -3
  163. package/dist/settings-confirmation.js +8 -5
  164. package/dist/settings-confirmation.js.map +1 -1
  165. package/dist/settings-effect.js +0 -2
  166. package/dist/settings-effect.js.map +1 -1
  167. package/dist/settings-http-confirmation.js +31 -1
  168. package/dist/settings-http-confirmation.js.map +1 -1
  169. package/dist/setup-wizard.d.ts +3 -0
  170. package/dist/setup-wizard.js +4 -2
  171. package/dist/setup-wizard.js.map +1 -1
  172. package/dist/task-board-waker.d.ts +43 -1
  173. package/dist/task-board-waker.js +121 -9
  174. package/dist/task-board-waker.js.map +1 -1
  175. package/dist/tmux-control.d.ts +1 -1
  176. package/dist/tmux-control.js +3 -2
  177. package/dist/tmux-control.js.map +1 -1
  178. package/dist/tmux-manager.js +18 -16
  179. package/dist/tmux-manager.js.map +1 -1
  180. package/dist/tmux-read.d.ts +2 -0
  181. package/dist/tmux-read.js +7 -1
  182. package/dist/tmux-read.js.map +1 -1
  183. package/dist/tool-permissions.js +3 -10
  184. package/dist/tool-permissions.js.map +1 -1
  185. package/dist/topic-commands.d.ts +29 -7
  186. package/dist/topic-commands.js +97 -37
  187. package/dist/topic-commands.js.map +1 -1
  188. package/dist/transcript-monitor.d.ts +7 -0
  189. package/dist/transcript-monitor.js +48 -3
  190. package/dist/transcript-monitor.js.map +1 -1
  191. package/dist/tunnel/cloudflared.d.ts +5 -0
  192. package/dist/tunnel/cloudflared.js +32 -1
  193. package/dist/tunnel/cloudflared.js.map +1 -1
  194. package/dist/tunnel/named-diagnostics.d.ts +2 -1
  195. package/dist/tunnel/named-diagnostics.js +4 -1
  196. package/dist/tunnel/named-diagnostics.js.map +1 -1
  197. package/dist/tunnel/named-link-test.d.ts +90 -0
  198. package/dist/tunnel/named-link-test.js +270 -0
  199. package/dist/tunnel/named-link-test.js.map +1 -0
  200. package/dist/tunnel/purpose-lane.d.ts +3 -1
  201. package/dist/tunnel/purpose-lane.js +2 -0
  202. package/dist/tunnel/purpose-lane.js.map +1 -1
  203. package/dist/types.d.ts +9 -11
  204. package/dist/ui/chat-ambient.js +4 -4
  205. package/dist/ui/chat-commands.js +3 -2
  206. package/dist/ui/chat-store.js +4 -1
  207. package/dist/ui/chat-strings.js +12 -46
  208. package/dist/ui/chat-thread.js +51 -59
  209. package/dist/ui/fleet-office-skin.js +37 -14
  210. package/dist/ui/fleet-office.js +31 -7
  211. package/dist/ui/html-attachment.js +22 -8
  212. package/dist/ui/panel-chat.js +21 -50
  213. package/dist/ui/panel-log.js +2 -2
  214. package/dist/ui/panel-needs.js +11 -9
  215. package/dist/ui/panel-settings.js +5 -3
  216. package/dist/ui/preview-panel.js +12 -21
  217. package/dist/ui/preview.js +10 -3
  218. package/dist/ui/search-dialog.js +30 -14
  219. package/dist/ui/settings-appearance.js +3 -37
  220. package/dist/ui/settings-confirm.js +18 -0
  221. package/dist/ui/settings-guests.js +13 -4
  222. package/dist/ui/settings-learn.js +1 -1
  223. package/dist/ui/settings-mods.js +5 -12
  224. package/dist/ui/settings-named-test.js +144 -0
  225. package/dist/ui/settings-registry.js +0 -2
  226. package/dist/ui/settings-strings.js +16 -16
  227. package/dist/ui/settings-web-authority.js +4 -3
  228. package/dist/ui/shared/app-i18n.js +15 -4
  229. package/dist/ui/shared/app-needs.js +5 -1
  230. package/dist/ui/shared/app-prefs.js +17 -17
  231. package/dist/ui/shared/app-shell.js +47 -9
  232. package/dist/ui/shared/app-store.js +6 -2
  233. package/dist/ui/shared/app.css +33 -39
  234. package/dist/ui/shared/app.js +5 -4
  235. package/dist/ui/shared/instance-nav.js +9 -9
  236. package/dist/ui/shared/instance-switch.js +8 -2
  237. package/dist/ui/shared/panel-view.js +22 -8
  238. package/dist/ui/shared/view-strings.js +6 -0
  239. package/dist/ui/shared/web-authorize.js +35 -13
  240. package/dist/update-check.d.ts +13 -4
  241. package/dist/update-check.js +17 -4
  242. package/dist/update-check.js.map +1 -1
  243. package/dist/usage/usage-api.d.ts +3 -0
  244. package/dist/usage/usage-api.js +5 -1
  245. package/dist/usage/usage-api.js.map +1 -1
  246. package/dist/view-api.d.ts +2 -0
  247. package/dist/view-api.js +64 -0
  248. package/dist/view-api.js.map +1 -1
  249. package/dist/web-api.d.ts +9 -17
  250. package/dist/web-api.js +257 -371
  251. package/dist/web-api.js.map +1 -1
  252. package/dist/web-appearance-tools.d.ts +0 -2
  253. package/dist/web-appearance-tools.js +2 -5
  254. package/dist/web-appearance-tools.js.map +1 -1
  255. package/dist/web-appearance-view.d.ts +0 -6
  256. package/dist/web-appearance-view.js +0 -1
  257. package/dist/web-appearance-view.js.map +1 -1
  258. package/dist/web-appearance.d.ts +14 -7
  259. package/dist/web-appearance.js +5 -6
  260. package/dist/web-appearance.js.map +1 -1
  261. package/dist/web-asset-parts.d.ts +1 -17
  262. package/dist/web-asset-parts.js +1 -15
  263. package/dist/web-asset-parts.js.map +1 -1
  264. package/dist/web-auth.js +1 -7
  265. package/dist/web-auth.js.map +1 -1
  266. package/dist/web-chat-history.d.ts +3 -7
  267. package/dist/web-chat-history.js +10 -17
  268. package/dist/web-chat-history.js.map +1 -1
  269. package/dist/web-commands.d.ts +9 -1
  270. package/dist/web-commands.js +13 -0
  271. package/dist/web-commands.js.map +1 -1
  272. package/dist/web-experimental.d.ts +3 -8
  273. package/dist/web-experimental.js +9 -33
  274. package/dist/web-experimental.js.map +1 -1
  275. package/dist/web-guest-access.d.ts +40 -2
  276. package/dist/web-guest-access.js +50 -14
  277. package/dist/web-guest-access.js.map +1 -1
  278. package/dist/web-mod-bundle.d.ts +2 -45
  279. package/dist/web-mod-bundle.js +15 -63
  280. package/dist/web-mod-bundle.js.map +1 -1
  281. package/dist/web-mod-store.d.ts +3 -48
  282. package/dist/web-mod-store.js +30 -97
  283. package/dist/web-mod-store.js.map +1 -1
  284. package/dist/web-prefs.d.ts +13 -0
  285. package/dist/web-prefs.js +38 -0
  286. package/dist/web-prefs.js.map +1 -1
  287. package/dist/web-preview.d.ts +6 -13
  288. package/dist/web-preview.js +12 -23
  289. package/dist/web-preview.js.map +1 -1
  290. package/dist/web-session.d.ts +11 -3
  291. package/dist/web-session.js +22 -11
  292. package/dist/web-session.js.map +1 -1
  293. package/dist/web-settings-patch.d.ts +1 -1
  294. package/dist/web-settings-patch.js +9 -7
  295. package/dist/web-settings-patch.js.map +1 -1
  296. package/dist/web-settings-tools.d.ts +0 -13
  297. package/dist/web-settings-tools.js +12 -84
  298. package/dist/web-settings-tools.js.map +1 -1
  299. package/dist/workflow-templates/default.md +2 -2
  300. package/dist/working-recovery.d.ts +0 -2
  301. package/dist/working-recovery.js +2 -23
  302. package/dist/working-recovery.js.map +1 -1
  303. package/launcher/agend-install.cjs +7 -1
  304. package/launcher/fleet-service-owner.cjs +150 -0
  305. package/package.json +1 -1
  306. package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +0 -376
  307. package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +0 -673
  308. package/dist/task-board-summary.d.ts +0 -101
  309. package/dist/task-board-summary.js +0 -177
  310. package/dist/task-board-summary.js.map +0 -1
  311. package/dist/ui/app-effects.js +0 -251
  312. package/dist/ui/chat-effect-posters.js +0 -42
  313. package/dist/ui/chat-effects.js +0 -167
  314. package/dist/ui/effect-trial-controller.js +0 -124
  315. package/dist/ui/effect-trial-offer.js +0 -2
  316. package/dist/ui/effect-trial-panel.js +0 -40
  317. package/dist/ui/effects-waker.js +0 -2
  318. package/dist/ui/settings-effects.js +0 -202
  319. package/dist/ui/settings-owner-effects.js +0 -82
  320. package/dist/ui/shared/effect-app-runtime.js +0 -299
  321. package/dist/ui/shared/effect-baseline.js +0 -64
  322. package/dist/ui/shared/effect-chat-runtime.js +0 -162
  323. package/dist/ui/shared/effect-cursor.js +0 -126
  324. package/dist/ui/shared/effect-display-metadata.js +0 -39
  325. package/dist/ui/shared/effect-frame.js +0 -146
  326. package/dist/ui/shared/effect-geometry.js +0 -137
  327. package/dist/ui/shared/effect-host-style.js +0 -10
  328. package/dist/ui/shared/effect-owner-regions.js +0 -74
  329. package/dist/ui/shared/effect-owner-source.js +0 -122
  330. package/dist/ui/shared/effect-policy.js +0 -151
  331. package/dist/ui/shared/effect-poster-reader.js +0 -98
  332. package/dist/ui/shared/effect-posters.js +0 -117
  333. package/dist/ui/shared/effect-profiler.js +0 -184
  334. package/dist/ui/shared/effect-profiles.js +0 -65
  335. package/dist/ui/shared/effect-registry.js +0 -545
  336. package/dist/ui/shared/effect-runtime-loader.js +0 -236
  337. package/dist/ui/shared/effect-safety.js +0 -153
  338. package/dist/ui/shared/effect-stock-snapshot.js +0 -43
  339. package/dist/ui/shared/effect-stock-trust.js +0 -217
  340. package/dist/ui/shared/effect-trial-shadow.js +0 -62
  341. package/dist/ui/shared/effect-trial-source.js +0 -103
  342. package/dist/ui/shared/effect-trial-stage.js +0 -170
  343. package/dist/ui/shared/effect-trial.css +0 -40
  344. package/dist/ui/shared/feature-flags.js +0 -127
  345. package/dist/ui/shared/owner-effect-prefs.js +0 -117
  346. package/dist/upgrade-notices.d.ts +0 -17
  347. package/dist/upgrade-notices.js +0 -93
  348. package/dist/upgrade-notices.js.map +0 -1
  349. package/dist/web-effect-bootstrap.d.ts +0 -12
  350. package/dist/web-effect-bootstrap.js +0 -49
  351. package/dist/web-effect-bootstrap.js.map +0 -1
  352. package/dist/web-effect-bundle.d.ts +0 -28
  353. package/dist/web-effect-bundle.js +0 -171
  354. package/dist/web-effect-bundle.js.map +0 -1
  355. package/dist/web-effect-canonical.d.ts +0 -8
  356. package/dist/web-effect-canonical.js +0 -27
  357. package/dist/web-effect-canonical.js.map +0 -1
  358. package/dist/web-effect-library.d.ts +0 -114
  359. package/dist/web-effect-library.js +0 -530
  360. package/dist/web-effect-library.js.map +0 -1
  361. package/dist/web-effect-playback.d.ts +0 -30
  362. package/dist/web-effect-playback.js +0 -71
  363. package/dist/web-effect-playback.js.map +0 -1
  364. package/dist/web-effect-poster.d.ts +0 -8
  365. package/dist/web-effect-poster.js +0 -52
  366. package/dist/web-effect-poster.js.map +0 -1
  367. package/dist/web-effect-profiles.d.ts +0 -118
  368. package/dist/web-effect-profiles.js +0 -181
  369. package/dist/web-effect-profiles.js.map +0 -1
  370. package/dist/web-effect-service.d.ts +0 -93
  371. package/dist/web-effect-service.js +0 -335
  372. package/dist/web-effect-service.js.map +0 -1
  373. package/dist/web-effect-tools.d.ts +0 -48
  374. package/dist/web-effect-tools.js +0 -129
  375. package/dist/web-effect-tools.js.map +0 -1
  376. package/dist/web-effect-trials.d.ts +0 -86
  377. package/dist/web-effect-trials.js +0 -204
  378. package/dist/web-effect-trials.js.map +0 -1
  379. package/dist/web-effect-upload.d.ts +0 -27
  380. package/dist/web-effect-upload.js +0 -185
  381. package/dist/web-effect-upload.js.map +0 -1
  382. package/dist/web-effect-worker.d.ts +0 -8
  383. package/dist/web-effect-worker.js +0 -170
  384. package/dist/web-effect-worker.js.map +0 -1
  385. package/dist/web-effect.d.ts +0 -103
  386. package/dist/web-effect.js +0 -153
  387. package/dist/web-effect.js.map +0 -1
  388. package/dist/web-experimental-http.d.ts +0 -2
  389. package/dist/web-experimental-http.js +0 -12
  390. package/dist/web-experimental-http.js.map +0 -1
  391. package/dist/web-mod-agent.d.ts +0 -50
  392. package/dist/web-mod-agent.js +0 -207
  393. package/dist/web-mod-agent.js.map +0 -1
@@ -11,14 +11,7 @@ English UI labels (the page also has 中文). Before you state a value the user
11
11
  it: `get_fleet_config` shows fleet.yaml; this skill gives defaults. Never invent a control that is not listed here.
12
12
  Never tell anyone to kill `wslrelay` or run `wsl --shutdown` (see Troubleshooting).
13
13
 
14
- During a cold start/full restart, an already signed-in browser can open the dashboard while agents start. **Fleet
15
- starting N/M** counts successful starts among runnable instances (persisted pauses excluded); queued/starting labels
16
- are visible in the sidebar, chat header and Org chart. Reads remain available; messages and changes are refused with
17
- a retry hint until startup finishes. Returning guests may wait for their connection scope without being signed out.
18
- Needs you may still be empty while its hub initializes. A brief reconnect gap
19
- is normal while a full restart replaces the process; the starting banner then replaces the unreachable message.
20
-
21
- For how *you* look on the dashboard (theme, identity card, colour, widgets, ambient effects, effects, mods), load `web-appearance`.
14
+ For how *you* look on the dashboard (theme, identity card, colour, widgets and ambient effects), load `web-appearance`.
22
15
 
23
16
  ## Index
24
17
 
@@ -34,7 +27,7 @@ For how *you* look on the dashboard (theme, identity card, colour, widgets, ambi
34
27
  | subscription meters, plan badges, profiles, keep-warm, prompt cache | [Usage and the cache report](#usage-and-the-cache-report) |
35
28
  | what an agent did step by step | [The Log tab](#the-log-tab) |
36
29
  | any Settings control | [Settings](#settings) |
37
- | themes, cards, widgets, ambient effects (petals, click stars), effects, mods | [Look](#look) |
30
+ | themes, cards, widgets, ambient effects (petals, click stars) | [Look](#look) |
38
31
  | blank page, preview refused, link fails, signed out, "live" missing | [Troubleshooting](#troubleshooting) |
39
32
 
40
33
  Addresses: the dashboard is served on the host at `http://localhost:<health_port>` (default 19280), on 127.0.0.1
@@ -67,14 +60,14 @@ hostname (named tunnel, `web.public_link.hostname`) the minutes go up to 10080,
67
60
  still needs a code).
68
61
  Close it with **Close public link** → **Close link (signs public browsers out)**, `/web revoke`, or let it expire.
69
62
  A public link is limited on purpose: no live stream (the page polls), no custom CSS, and Settings → Access & security, Look,
70
- mods, effect-library/personal-selection management, schedule edits and preference writes are refused. Current in-scope
71
- Chat effect metadata/code reads are allowed, with session/epoch/exposure checks; the public viewer’s show switch is browser-local. HTML previews work over it through a second tunnel
63
+ schedule edits and preference writes are refused. HTML previews work over it through a second tunnel
72
64
  of their own (`web.preview_on_public_link`, default on).
73
65
 
74
66
  **Sessions.**
75
67
  - Local: 48 h from sign-in and 48 h unused (`web.session.local.absolute_hours` / `idle_hours`, 1–720). Background
76
68
  polling and the live stream don't count as use. Sessions survive a fleet restart.
77
- - Public link: always 4 h / 30 min unused, and they end when the link closes.
69
+ - Public link: as long as the link, at most 8 h (never longer than the account's own limit: `web.session.local` for
70
+ an admin, `web.guests.session` for a guest), 30 min unused, and they end when the link closes.
78
71
  - At most 8 sessions; the least recently used is dropped.
79
72
  - The session menu (sidebar): "Signed in · …", "Ends by <time> at the latest, or after <span> unused". With more than
80
73
  one session it lists **Signed-in devices** (this one marked "· This device", others with **Sign out**) and **Sign
@@ -100,8 +93,12 @@ as their own Discord or Telegram account. What a guest sees:
100
93
  ClassicBot room, and ClassicBot group rooms while their membership is verified, minus any `web.guests.narrow`.
101
94
  **Start from today's guests** turns that into grants.
102
95
 
103
- They can chat there unless `web.guests.chat` is false, never send a command (text starting with `/` is refused), and the
104
- agent sees them as `via web (guest)`. A guest's app has no Fleet, View, Settings or Needs you. To invite someone: turn it
96
+ They can chat there unless `web.guests.chat` is false, run only the commands the command table lets anyone run in that
97
+ agent's channel (on the web: `/ctx`, `/steer`, `/btw`, `/cancel`; anything else is refused), open the usage panel, and the
98
+ agent sees them as `via web (guest)`. A guest's app has no Fleet, Settings or Needs you. Each person is **Chat** (the
99
+ default) or **Trusted** (#2855, `level: trusted` on the grant; Chat → Trusted waits for a fleet admin): a Trusted guest
100
+ also gets a read-only **View** of those agents (no typing; 2 reads a second, 2 agents at once) and **search** of the chat
101
+ messages it can already see (6 a minute, 20 results; no messages between agents, tasks or settings). To invite someone: turn it
105
102
  on, grant them their agents in Settings → Access & security → Guests, and press **Send sign-in code** (or tell them to
106
103
  send `/web`). The Guests section is not in Settings over the public link.
107
104
 
@@ -115,8 +112,8 @@ just **✓ Verified**, with the until-when in its tooltip, its accessible name a
115
112
  browser's messages then carry the account's authority in their delivery receipt for `max_session_hours` (default 48).
116
113
  Not me signs that browser out, also after Confirm, from the same card. At most one card waits per browser, and 3 an hour
117
114
  per account. Never for a guest. Over the admin's own named link (#2453) only with **Also over my named link**
118
- (`named_link`, off by default); over the temporary public link `/web` opens only with **Also over the temporary public
119
- link** (`quick_link`, off by default, §0.3). That authority ends with the link, and the card says "over your named link"
115
+ (`named_link`, off by default); over the temporary public link `/web` opens while **Also over the temporary public
116
+ link** is on (`quick_link`, on by default since #2819, §0.3; `quick_link: false` turns it off). That authority ends with the link, and the card says "over your named link"
120
117
  or "over the temporary public link". When a browser can't be authorized, the line says why (with a link to Settings when the switch, "Only
121
118
  this computer" or the named-link option is the reason). Settings → Access & security → **Web authority** (`web.verified_authority`, on
122
119
  by default) has the switch, **Only this computer can authorize** (`loopback_only`), **Also over my named link** (shown
@@ -152,8 +149,7 @@ workspace `inbox/`; an unused upload is deleted after 30 minutes.
152
149
 
153
150
  **In replies.** Images inline; video and audio play inline; Markdown, CSV, JSON, code and text files get a **Show**
154
151
  card (200 lines, then "Show all … lines"); other files download. Code blocks have a language tag, **Wrap** and
155
- **Copy**, and fold after 30 lines. **⋯ → Full width** (desk only, off by default, this browser's choice) widens the
156
- thread and the composer to the whole chat panel for wide tables and code; a person's bubbles keep their size. Each reply has **Copy this reply**. Markdown: headings, lists, quotes, bold/italic/
152
+ **Copy**, and fold after 30 lines. Each reply has **Copy this reply**. Markdown: headings, lists, quotes, bold/italic/
157
153
  strike, links, and tables (header row plus separator, alignment, up to 20 columns). Discord mentions show as names;
158
154
  a Discord server emoji (`<:name:id>`) of the fleet's servers shows as its picture, and any other (or one whose picture
159
155
  can't load) as `:name:`. Unicode emoji are drawn by the system's colour emoji font under every theme font (boxes on
@@ -203,8 +199,7 @@ A prompt shows its own answer buttons (first answer wins); a delivery has **Ackn
203
199
  "Paused: sign-in needed" has **Sign in** when the dashboard can run that login (#2233); every item has **Open chat**. **Notify me on this device** (Turn on / Turn off) gives desktop notifications while the
204
200
  tab is hidden — per browser, not on phones or plain-HTTP addresses. Config: `needs_you.live_message` (default on),
205
201
  `needs_you.dm` (default off), `needs_you.task_board` (default off: the task board's cards waiting
206
- for you — set `true` to list them). The task board's daily summary is `defaults.task_board.summary_at` (off unless set,
207
- e.g. `"09:00"`).
202
+ for you — set `true` to list them).
208
203
 
209
204
  ## Search
210
205
 
@@ -216,7 +211,7 @@ Board tasks — never a CLI's own transcript (that is the Log). Results come as
216
211
  first, badged Chat / Message / Task; 1–2 character words work (alone: the newest 5,000 entries, said in the dialog).
217
212
  ↑↓ / Enter / Esc / click outside; **Filters**: agent, team, time, kinds, **Only mine**; recent searches when empty.
218
213
  A chat result opens the chat at the message (flashed); a message between agents, a task or a chat row the history no
219
- longer keeps opens as the index's copy. Admins only, over the temporary public link and on a phone too (no guests). Config: `web.search.enabled`
214
+ longer keeps opens as the index's copy. Admins, over the temporary public link and on a phone too; a Trusted guest (#2855) searches only its own agents' chat messages it can see. Config: `web.search.enabled`
220
215
  (default on, off everywhere), `web.search.public_link` (default on; false keeps it off the public link), `web.search.retention_days` (unset and 0 = no age limit; 1–3650 days; daily prune still caps at 300,000). Secrets are masked; a hidden `cross_instance_visibility`
221
216
  agent's messages are not found. "Search is off or not available": `web.search.enabled: false`, or the index could not
222
217
  open (the fleet log says why); "Still indexing": the first fill after an upgrade.
@@ -247,9 +242,7 @@ The sidebar's **Fleet** (zh "Fleet 概覽", at the top) and the phone's Fleet ta
247
242
  delete: cancel. Alt+arrows on a card's title move it (no drag needed; the card's Position row on a phone). A main
248
243
  task's tile shows the sub task at work and who is on it; a card waiting for review that is not wrapped up says
249
244
  **To fill in** and Confirm asks first. A card's **Dispatched by** row: who handed it out (a blocked question goes
250
- to them first). Read-only over the public link. The cards you handed out that wait for your confirmation, or are
251
- blocked, are also **Needs you** items: on the web they open the card; in each bot's live message in General they
252
- have **Confirm** / **Send back** / **Answer** (the words are a reply to the bot's prompt).
245
+ to them first). Read-only over the public link.
253
246
  - **Schedules** — every schedule (silent ones included): when it runs in words, "next …", the target. **New
254
247
  schedule** (Repeat with a cron expression, or Once at a date and time; message, target, label, timezone),
255
248
  **Edit** (with an **Enabled** box — that is how you pause one), **Delete**. There is no "run now", and silent can't
@@ -267,7 +260,7 @@ Telegram topic, and **Open chat**.
267
260
 
268
261
  **The Office guide** (`docs/office.md` in the AgEnD repository; `docs/office.zh-TW.md` in Traditional Chinese) is the one page for people: setting up offices, the
269
262
  skin-pack manifest format and its limits, Edit layout and seat reservations, bedtime, share links, agents' office and
270
- pack tools, and rolling back. Point people there for more than the summary below; it marks what is not released yet.
263
+ pack tools, and rolling back. Point people there for more than the summary below; it lists the version each feature came in.
271
264
 
272
265
  **Office** (the third view, remembered per device) draws the same fleet as a pixel office: a room per team, a desk
273
266
  per instance with a name tag, General and "Not in a team" in the **Lobby**. Each little person is its state: typing
@@ -281,8 +274,7 @@ activity line, **Find in office** and **Chat**. A double-click opens the chat di
281
274
  (lifetime work, docs/office.md § Levels; **Settings → Web dashboard → Office levels**, `web.office_levels`). **Find** dims
282
275
  the rest. **Show** picks a team or the Lobby and **People** pins chosen instances (both kept per browser); the
283
276
  **Office** switcher lists offices kept on the host (`web-offices.json`, `GET`/`PUT /ui/offices`). An admin session
284
- (never a read-only one, a guest or the public link) gets **Edit offices** (≥1200 px: a panel docked on the right in the
285
- usage rail's place, the Office in use beside it, × or Esc closes it and the rail returns; narrower: a centred dialog): add, rename and delete offices, pick who is
277
+ (never a read-only one, a guest or the public link) gets **Edit offices**: add, rename and delete offices, pick who is
286
278
  in each (Everyone, Picked: whole teams or single instances, or #2752 Nobody: its style's NPCs only; none picked = everyone) and its style, and upload or delete **skin packs** (an
287
279
  artist's pictures: `manifest.json` plus PNGs, format v1, kept in `web-office-skins/` in the AgEnD home; the host
288
280
  checks every rule — PNG only, each strip exactly frames·w × h, a 16:9 background, size caps — and never changes a
@@ -306,10 +298,7 @@ its own night place, **Back to the pack's night place** undoes it (#2665); a sel
306
298
  office's members, several allowed) and **Lend when away** (#2691) — whoever it is for sits there first when they come
307
299
  to its area, nobody else does unless it is lent while they are all away (a borrower moves off when one comes), and a
308
300
  reserved seat's handle is ringed; a pack can reserve seats as well; **Save layout** keeps the moves as that
309
- office's overrides (the pack stays as uploaded), **Reset** goes back to the pack's own. On a screen ≥1200 px its controls sit in the right-hand panel (the canvas whole for the
310
- handles); narrower, or in fullscreen, they are the bar along the canvas's bottom. Esc is Cancel. While either editor
311
- is docked the page beside it works, Ctrl+K search included; leaving the page with unsaved changes asks first
312
- ("Discard changes"). While it is open the office picker and Edit offices wait (**Cancel** closes it); if someone
301
+ office's overrides (the pack stays as uploaded), **Reset** goes back to the pack's own. While it is open the office picker and Edit offices wait (**Cancel** closes it); if someone
313
302
  saved the offices meanwhile, Save says so and keeps your layout — Save again puts it on the current list. A crowded area packs extra people into a tighter grid, then shows "+N" in its corner; there
314
303
  only calls and work get bubbles (a few at most) and name tags show on hover or focus. **Hide paused and stopped**
315
304
  (per browser, off by default) leaves the sleepers out. Now and then someone says a short line for their state in a
@@ -379,7 +368,8 @@ Each row (#2179): name and context % on the first line, the time of the agent's
379
368
  second ("2 min ago"; cross-instance messages don't count); a reply under 10 minutes old is highlighted, fading by itself
380
369
  (nothing to mark read). The sort button beside Edit: **Custom** (default; a reply never moves a row) or **Recent replies**
381
370
  (the rest by last reply, no groups, no dragging; favorites pinned in their order, or **Sorted by last reply too**); synced
382
- as `nav.sort`. Guests and the anonymous View reader: no times, no sort (always Custom).
371
+ as `nav.sort`. Guests sort, star and filter as their own preferences (kept on the host under their account; reply times
372
+ count only replies their channel showed; no dragging); the anonymous View reader: no times, no sort (always Custom).
383
373
  **Filter: name, model, backend** (Esc clears), facets **Status** and **CLI**, "N / M shown".
384
374
  While a filter is on, the instance you have open stays on top under **Current**. **Favorites**: the star on a row;
385
375
  **Edit** to reorder (at most 50; "Clear the filter to reorder favorites"). Drag to reorder the full list; groups fold.
@@ -556,11 +546,11 @@ ClassicBot (in **Chat & connections**, `/settings/chat#classicbot`) — per room
556
546
  Advanced **Context lines** (these restart the room's agent); Tool progress and Require a delivered reply (now).
557
547
 
558
548
  **Agent defaults** — **Project folders** (`project_roots`: where New agent may put an agent; empty = anywhere;
559
- changing it waits for a fleet admin's OK) and the fleet defaults (`defaults.*`): **Language (bot replies)** (`locale`: Auto / en / zh-TW; read at startup: restart AgEnD), default
549
+ changing it waits for a fleet admin's OK) and the fleet defaults (`defaults.*`): **Language (bot replies)** (`locale`: Auto / en / zh-TW), default
560
550
  backend and model, auto-pause, tool progress, bot-to-bot visibility, reply guard, **Native replies trigger ClassicBot**
561
551
  (`reply_triggers`: a native reply triggers a ClassicBot bot; off by default, #2576); Advanced: tool set, agent mode, log
562
552
  level, **Hang detector enabled** / **Stuck timeout** (`hang_detector.*`), **Startup concurrency** (1–20) and
563
- **Stagger delay** (`startup.*`, used from the next agent start, no restart). ClassicBot defaults (in Chat & connections; `classicBot.yaml defaults.*`): default backend, tool
553
+ **Stagger delay** (`startup.*`, restart AgEnD). ClassicBot defaults (in Chat & connections; `classicBot.yaml defaults.*`): default backend, tool
564
554
  progress, reply guard, **Native replies trigger ClassicBot** (`reply_triggers`, also per room), **ClassicBot admins**,
565
555
  **Allowed guilds**.
566
556
 
@@ -602,7 +592,7 @@ when the host confirms; a directory that is entered must be absolute.
602
592
  ## Look
603
593
 
604
594
  For an agent changing its *own* look, the `web-appearance` skill has the tools and limits. What a person sees in
605
- Settings → **Look**, card by card (the app icon, card upload limits and Canvas Worker effects are in **Web dashboard**; following reduced motion and custom CSS off here are in **Preferences**):
595
+ Settings → **Look**, card by card (the app icon and card upload limits are in **Web dashboard**; following reduced motion and custom CSS off here are in **Preferences**):
606
596
  - **Agents' themes** — **Show agents' themes, effects and widgets**; off, every chat looks the same and pictures and
607
597
  ring colours fall back to the bots' own (all devices).
608
598
  - **Ambient effects** — an agent's falling petals, snow, rising lanterns, twinkles or stars on a click, drawn behind
@@ -621,38 +611,21 @@ Settings → **Look**, card by card (the app icon, card upload limits and Canvas
621
611
  **Save and try**, then **Keep** within 15 s or it reverts; **Turn off (all devices)**; earlier versions **Use
622
612
  this**. If something is hidden or broken, open the page with `?safe=1`, or tick **Turn off custom CSS on this
623
613
  device** (in Preferences).
624
- - **Mods** — one `.agendmod.json` file carrying a look; importing shows everything first and applies only what you
625
- tick (custom CSS is never pre-ticked); agents can propose mods (**Review** / **Dismiss**); **Export a mod** writes one.
626
- Uninstalling removes the mod, not what it applied.
627
- - **Effects** — the effect library (upload a folder with `effect.json` and `worker.js`, up to 1 MiB), save one for a
628
- chat, share your copy; **Your effect choices** for Sidebar / Header / Page / Box (each with Pause / Resume and
629
- Clear) and a Cursor (its state, and Clear). CW uses the dashboard's opaque isolated document, independently of
630
- **Allow HTML previews**, its listener and port. Signed-in public/guest viewers can play current effects in chats they
631
- may see, without library, personal-slot, Trial or profile grants. Their Chat header offers a browser-local show/off
632
- switch and recovery, on desktop and phone; it never changes host preferences. A Try sample starts on a signed-in non-public admin's
633
- click, with no extra consent. The show switch, safe mode, hidden tab, browser support and live performance guard remain.
634
- No startup FPS calibration; data saver does not block. Reduced motion blocks only if this device chose to follow it.
635
- A blocked placement keeps an exact named notice. On ordinary dashboard sessions, Show/custom-CSS actions open
636
- **Look**. Public/guest Show-off has **Turn effects on here**; a guest CSS refusal offers Reload.
637
- An unavailable
638
- isolated transport offers Reload, never an HTML-preview setup step. A motion refusal offers **Play effects anyway**;
639
- safe mode offers **Leave safe mode**. The dialog names loading, safety and raw unknown codes. Codes stay local; agents get only closed recent blocked reasons without viewer identifiers or counts.
640
614
  - **Restore defaults** — resets this host's appearance settings (it lists what it resets first).
641
615
 
642
616
  Moved out of Look in 2.3.2 (#2347). **Preferences** (this device only): **Effects: follow the system's reduced-motion
643
- setting** (off by default): on, both ambient and Canvas Worker effects stay still while the system asks for reduced motion. Otherwise both play, with one shared one-time chat note and a local action to follow the system. And **Turn off custom CSS on this device**. **Web dashboard**: the **App icon**;
617
+ setting** (off by default): on, ambient effects stay still while the system asks for reduced motion. Otherwise they play, with one shared one-time chat note and a local action to follow the system. And **Turn off custom CSS on this device**. **Web dashboard**: the **App icon**;
644
618
  **Identity card upload limits** — portrait and banner size limits and per-agent picture quota (`web.appearance.*`);
645
- lowering applies at once, raising waits for an admin; and **Experimental: Canvas Worker effects**.
619
+ lowering applies at once, raising waits for an admin.
646
620
 
647
621
  **What an agent can change for the user.** A worker changes only its own look (the `web-appearance` tools); before
648
622
  #2064 everything on this page was the person's. Since #2064 (2.2.5) General, coordinators and
649
623
  full-profile instances get `get_web_settings` / `set_web_settings`, which go through the same checks as the page;
650
624
  workers don't. The `web-appearance` skill's **For the user** section has the details. In short: General can change
651
- the host's appearance settings, one agent's identity colour, mods (review, install, cancel, dismiss, uninstall),
652
- effects and the effect slots, and Restore defaults; for custom CSS it can save a version **on trial**, keep or revert
625
+ the host's appearance settings, one agent's identity colour, ambient effects and Restore defaults; for custom CSS it can save a version **on trial**, keep or revert
653
626
  the trial, switch to an earlier saved version, or turn CSS off — and it keeps a trial only once the user says they like
654
627
  it (the user's decision). Still the person's own click on the page: choosing files from their computer
655
- (import a mod, upload an effect folder or CSS assets), the per-browser switches (custom CSS off on this device, Pause/Resume), downloading an exported mod, and the
628
+ (upload CSS assets), the per-browser switches (custom CSS off on this device, Pause/Resume), and the
656
629
  card upload limits. The docs' "Asking General to change it for you" says the same for people.
657
630
 
658
631
  ## Troubleshooting
@@ -687,7 +660,7 @@ off).
687
660
  - "Cloudflare gave no public address in time" — only after a real 60 s wait;
688
661
  - no steps at all: `web.public_link.allow_public: false`, or the sender is not a fleet admin.
689
662
 
690
- **"Your session has ended."** It lasted its 48 h (or the idle limit), a public link closed or ran 4 h / 30 min idle,
663
+ **"Your session has ended."** It lasted its 48 h (or the idle limit), a public link closed or ran out (at most 8 h) or sat 30 min idle,
691
664
  or someone ran `/web revoke`, **Sign out everywhere** or `agend web-token rotate`. Get a new code: `/web`, **Send me
692
665
  a new code**, or `agend web` on the host. "No session — open the dashboard link again" means the browser keeps no
693
666
  cookies for the site.
@@ -703,14 +676,3 @@ no instance uses that provider.
703
676
  **Settings won't change something.** Over a public link, Web settings and appearance are read only; a loosening
704
677
  change waits for an admin's confirmation in General chat; a value in the "Set in fleet.yaml" list must be edited in
705
678
  fleet.yaml (Advanced, or the file) and `agend reload`.
706
-
707
- ### Canvas Worker playback diagnostics
708
-
709
- The effect player loads only when there is something to play: the open chat has a placed effect, the person chose a
710
- personal effect, or a Try card is shown (#2193). Before that, nothing of it is in the page, by design. Ambient effects
711
- and custom CSS never need it.
712
-
713
- If an effect cannot play, the Chat notice and Effects dialog show its local refusal code. A failed Try retains its stop
714
- code on the offer card; the browser console also names refusals. Include the code when reporting a problem. Long chat
715
- history is checked separately from the bounded set of current paint holes. Moving the pointer away does not stop Try;
716
- window blur, navigation, closing or loss of the verified stage does. Local raw codes are not sent in agent summaries.
@@ -149,6 +149,13 @@ export interface LifecycleContext {
149
149
  checkModelFailover(name: string, fiveHourPct: number): void;
150
150
  /** Retire (delete) any pending Cancel button for an instance. No-op if none. */
151
151
  clearCancelButton(name: string): void;
152
+ /**
153
+ * #2897: a held dialog's notices — the instance-topic one and the General one, each unless its text is null —
154
+ * edited in place on a re-report, never posted twice. Absent: each report is a fresh post (contexts without a ledger).
155
+ */
156
+ showParkedNotice?(name: string, topicText: string | null, generalText: string | null): void;
157
+ /** #2897: the held dialog is resolved, or the instance stopped/restarted: take its notices back. No-op if none. */
158
+ resolveParkedNotice?(name: string): void;
152
159
  /** Called after a replacement Daemon object is live, for generation fencing and post-resume notices. */
153
160
  onDaemonReady?(name: string, daemonBootId: string): void;
154
161
  /** Test/integration seam for the non-LLM Codex quota second opinion. */
@@ -255,6 +262,12 @@ export interface LifecycleReplaceArgs {
255
262
  name: string;
256
263
  reason?: string;
257
264
  }
265
+ /**
266
+ * #2872: a one-line notice ("⚠️ Grok weekly limit used up — paused") where it is posted. In the instance's own topic
267
+ * (`elsewhereName` null) as it is; anywhere else (General) it must say whose: "⚠️ <name>: Grok weekly limit used up —
268
+ * paused". A line without a leading emoji gets the name in front.
269
+ */
270
+ export declare function plainNoticeLine(line: string, elsewhereName: string | null): string;
258
271
  /**
259
272
  * What the live usage endpoint says about whether this Codex login can work:
260
273
  * available — no regular window is full: the usage-limit text is stale;
@@ -369,6 +382,12 @@ export declare class InstanceLifecycle {
369
382
  */
370
383
  /** @returns whether the notice was actually dispatched (false when suppressed). */
371
384
  private notifyIncident;
385
+ /**
386
+ * #2897: a held dialog's notice in the instance's topic and in General — through the fleet's notice ledger when it
387
+ * has one (one live message per place, edited in place, taken back on resolve), else as two fresh posts. The topic
388
+ * notice is suppressed as before; the General text skips notifyFleetError's text throttle, as the ledger keeps it to one.
389
+ */
390
+ private notifyParked;
372
391
  /**
373
392
  * Per-instance MCP incident fence. The mcp_died handler awaits an auth probe
374
393
  * (up to 5s) before it notifies; a recovery that lands inside that window
@@ -151,6 +151,17 @@ const AUTH_ALERT_COOLDOWN_MS = 5 * 60_000;
151
151
  * token-free check answers for all of them.
152
152
  */
153
153
  const AUTH_VERIFY_CACHE_MS = 60_000;
154
+ /**
155
+ * #2872: a one-line notice ("⚠️ Grok weekly limit used up — paused") where it is posted. In the instance's own topic
156
+ * (`elsewhereName` null) as it is; anywhere else (General) it must say whose: "⚠️ <name>: Grok weekly limit used up —
157
+ * paused". A line without a leading emoji gets the name in front.
158
+ */
159
+ export function plainNoticeLine(line, elsewhereName) {
160
+ if (!elsewhereName)
161
+ return line;
162
+ const m = /^(\p{Extended_Pictographic}\uFE0F?)\s*/u.exec(line);
163
+ return m ? t("inst.notice_named", m[1], elsewhereName, line.slice(m[0].length)) : t("inst.notice_named", "", elsewhereName, line).trimStart();
164
+ }
154
165
  const CODEX_QUOTA_VERIFY_TIMEOUT_MS = 5_000;
155
166
  const CLAUDE_QUOTA_VERIFY_TIMEOUT_MS = 5_000;
156
167
  /**
@@ -347,6 +358,27 @@ export class InstanceLifecycle {
347
358
  const dispatched = this.ctx.notifyInstanceTopic(name, text);
348
359
  return dispatched !== false;
349
360
  }
361
+ /**
362
+ * #2897: a held dialog's notice in the instance's topic and in General — through the fleet's notice ledger when it
363
+ * has one (one live message per place, edited in place, taken back on resolve), else as two fresh posts. The topic
364
+ * notice is suppressed as before; the General text skips notifyFleetError's text throttle, as the ledger keeps it to one.
365
+ */
366
+ notifyParked(name, kind, topicText, generalText) {
367
+ if (!this.ctx.showParkedNotice) {
368
+ this.notifyIncident(name, kind, topicText);
369
+ this.ctx.notifyFleetError?.(generalText);
370
+ return;
371
+ }
372
+ if (this.ctx.isPlannedRestart()) {
373
+ this.ctx.logger.info({ name, kind }, "Incident notification suppressed — planned restart in progress");
374
+ return;
375
+ }
376
+ // As before: a storm folds the topic notice into its summary; General's is not part of that.
377
+ const stormed = this.ctx.stormSuppressed?.(kind) === true;
378
+ if (stormed)
379
+ this.ctx.logger.info({ name, kind }, "Incident notification suppressed — included in tmux storm summary");
380
+ this.ctx.showParkedNotice(name, stormed ? null : topicText, generalText);
381
+ }
350
382
  /**
351
383
  * Per-instance MCP incident fence. The mcp_died handler awaits an auth probe
352
384
  * (up to 5s) before it notifies; a recovery that lands inside that window
@@ -603,6 +635,22 @@ export class InstanceLifecycle {
603
635
  else
604
636
  this.ctx.reactMessageStatus(name, data.chatId, data.messageId, "failed", data.threadId);
605
637
  }, this.ctx.logger, `daemon.message_failed[${name}]`));
638
+ // #2770: a cancel dropped these before they reached the CLI. Each is marked ❌ and the person is told once, instead of
639
+ // the messages quietly ending "uncertain".
640
+ daemon.on("human_messages_cancelled", safeHandler((data) => {
641
+ const messages = Array.isArray(data?.messages) ? data.messages : [];
642
+ if (!messages.length)
643
+ return;
644
+ this.ctx.eventLog?.insert(name, "messages_cancelled", { count: messages.length });
645
+ this.ctx.logger.info({ name, count: messages.length }, "Messages dropped by a cancel before delivery — telling the person");
646
+ for (const m of messages) {
647
+ if (this.ctx.finishDeliveryStatus)
648
+ this.ctx.finishDeliveryStatus(name, m.chatId, m.messageId, "failed", m.threadId);
649
+ else
650
+ this.ctx.reactMessageStatus(name, m.chatId, m.messageId, "failed", m.threadId);
651
+ }
652
+ this.ctx.notifyInstanceTopic(name, t("delivery.cancelled_unsent", messages.length, name));
653
+ }, this.ctx.logger, `daemon.human_messages_cancelled[${name}]`));
606
654
  }
607
655
  attachIncidentHandlers(name, daemon) {
608
656
  daemon.on("capacity_nudge_cancelled", safeHandler((data) => {
@@ -906,18 +954,19 @@ export class InstanceLifecycle {
906
954
  if (data.unrecognised) {
907
955
  // #1990: the question is a pane line — it may not name a place of its own.
908
956
  const asked = data.question ? t("inst.unrecognised_prompt_question", noPlaceMarkers(data.question)) : "";
909
- this.notifyIncident(name, "dialog_parked", t("inst.unrecognised_prompt", name, asked));
910
- this.ctx.notifyFleetError?.(t("fleet.unrecognised_prompt", instancePlace(name), asked));
957
+ this.notifyParked(name, "dialog_parked", t("inst.unrecognised_prompt", name, asked), t("fleet.unrecognised_prompt", instancePlace(name), asked));
911
958
  return;
912
959
  }
913
960
  const category = data.kind && data.kind !== "dialog" ? interactionCategory(data.kind, data.backend) : null;
914
961
  const text = category ? t("inst.interaction_parked", name, category) : data.holdOnly
915
- ? t("inst.dialog_parked_hold", name, data.description)
916
- : t("inst.dialog_parked_stuck", name, data.description);
917
- this.notifyIncident(name, "dialog_parked", text);
962
+ // #2872: the Claude session-resume advice only for that prompt (it read as nonsense under a grok or kiro dialog).
963
+ ? t("inst.dialog_parked_hold", name, data.description) + (data.advice === "claude-resume" ? " " + t("inst.dialog_parked_hold_claude_resume") : "")
964
+ : t("inst.dialog_parked_stuck", name, data.description) + (data.advice === "claude-resume" ? " " + t("inst.dialog_parked_stuck_claude_resume") : "");
918
965
  // #1990: in General, the instance's name links to its topic.
919
- this.ctx.notifyFleetError?.(category ? t("fleet.interaction_parked", instancePlace(name), category) : t("fleet.dialog_parked", instancePlace(name), data.description));
966
+ this.notifyParked(name, "dialog_parked", text, category ? t("fleet.interaction_parked", instancePlace(name), category) : t("fleet.dialog_parked", instancePlace(name), data.description));
920
967
  }, this.ctx.logger, `daemon.dialog_parked[${name}]`));
968
+ // #2897: the held dialog is gone (closed, answered, auto-answered) — its notices go with it.
969
+ daemon.on("dialog_unparked", safeHandler(() => this.ctx.resolveParkedNotice?.(name), this.ctx.logger, `daemon.dialog_unparked[${name}]`));
921
970
  daemon.on("dialog_answer_ignored", safeHandler((data) => {
922
971
  // A runtime dialog the daemon DID answer, that did not go away. Same rule as dialog_parked: no assist
923
972
  // buttons (a one-tap Enter is exactly what just failed, and may be the wrong choice), and nothing from the
@@ -927,10 +976,11 @@ export class InstanceLifecycle {
927
976
  if (this.ctx.isPlannedRestart())
928
977
  return;
929
978
  const text = t(data.holdsDeliveries ? "inst.dialog_answer_ignored_held" : "inst.dialog_answer_ignored", name, data.description, String(data.attempts));
930
- this.notifyIncident(name, "dialog_answer_ignored", text);
931
- this.ctx.notifyFleetError?.(t("fleet.dialog_answer_ignored", instancePlace(name), data.description, String(data.attempts)));
979
+ this.notifyParked(name, "dialog_answer_ignored", text, t("fleet.dialog_answer_ignored", instancePlace(name), data.description, String(data.attempts)));
932
980
  }, this.ctx.logger, `daemon.dialog_answer_ignored[${name}]`));
933
981
  daemon.on("instance_interaction", () => this.ctx.onAttentionChanged?.(name));
982
+ // #2822: a usage-limit hold began or ended — Needs you lists it while it lasts.
983
+ daemon.on("usage_hold", () => this.ctx.onAttentionChanged?.(name));
934
984
  daemon.on("interactive_prompt", safeHandler(async (data) => {
935
985
  this.ctx.eventLog?.insert(name, "interactive_prompt", { kind: data.kind });
936
986
  this.ctx.logger.warn({ name, kind: data.kind, prompt: data.prompt }, "Instance is waiting for interactive terminal input");
@@ -972,7 +1022,7 @@ export class InstanceLifecycle {
972
1022
  // ChatGPT-plan feature, so an account that cannot be asked is almost
973
1023
  // always a plain one, and a wrongly paused reserve wakes with /wake while
974
1024
  // a missed pause fails silently forever.
975
- if (data.type === "quota" && data.action === "pause" && this.backendOf(name) === "codex") {
1025
+ if (data.type === "quota" && data.action === "pause" && !data.skipUsageVerify && this.backendOf(name) === "codex") {
976
1026
  const verdict = await this.verifyCodexQuota();
977
1027
  this.ctx.logger.info({ name, backend: "codex", decision: verdict === "available" || verdict === "reserve" ? "ignore" : "pause", evidence: `usage-${verdict}` }, `codex usage-limit decision: decision=${verdict === "available" || verdict === "reserve" ? "ignore" : "pause"} evidence=usage-${verdict}`);
978
1028
  if (verdict === "available") {
@@ -1010,14 +1060,14 @@ export class InstanceLifecycle {
1010
1060
  if (data.type === "auth_error") {
1011
1061
  const verdict = authVerdict = await this.verifyAuthError(name);
1012
1062
  if (verdict === "valid") {
1013
- this.ctx.logger.info({ name, backend: this.backendOf(name) }, "auth-error pattern ignored — token-free auth check passed (likely conversation text)");
1014
- // Dropping the incident is not enough: the daemon armed its auth
1015
- // suspicion and recovery gate before emitting, and leaving those set
1016
- // would silently suppress hang notifications and MCP auto-restart for
1017
- // an instance whose credentials are demonstrably fine.
1063
+ this.ctx.logger.debug({ name, backend: this.backendOf(name) }, "auth-error pattern ignored — token-free auth check passed (likely conversation text)");
1064
+ // #2795: a pattern match armed nothing, so this only drops it. A login-screen report did arm the auth
1065
+ // suspicion, and leaving that set would suppress hang notifications and MCP auto-restart.
1018
1066
  this.daemons.get(name)?.clearSuspectedAuthFailure();
1019
1067
  return;
1020
1068
  }
1069
+ // #2795: not vouched for — only now is a pattern match an auth failure on the daemon.
1070
+ this.daemons.get(name)?.confirmAuthFailure?.();
1021
1071
  }
1022
1072
  // #2648: a kiro model error — the resumed conversation's saved model retired, or the instance's own model
1023
1073
  // unavailable. Restart once on kiro's default (no model of its own), else say it once; never on every start.
@@ -1058,7 +1108,11 @@ export class InstanceLifecycle {
1058
1108
  else if (notificationTarget && data.action !== "backoff_restart" && data.action !== "nudge_continue") {
1059
1109
  // backoff_restart / nudge_continue notifications are handled in the action branch below
1060
1110
  // with per-attempt context (attempt N/max, delay).
1061
- this.notifyIncident(notificationTarget, "pty_error", t("inst.notification", emoji, name, incidentMessage, data.action));
1111
+ // #2872: a notice the user asked to be one line (grok's weekly limit) is posted as it is: no "(action: …)", and no
1112
+ // name in the instance's own topic; elsewhere (a ClassicBot's go to General) the name follows its emoji.
1113
+ this.notifyIncident(notificationTarget, "pty_error", data.notice
1114
+ ? plainNoticeLine(data.notice, notificationTarget === name ? null : name)
1115
+ : t("inst.notification", emoji, name, incidentMessage, data.action));
1062
1116
  }
1063
1117
  this.ctx.webhookEmit("pty_error", name, { type: data.type, action: data.action, message: data.message });
1064
1118
  // The CLI interrupted itself on this error, so any pending Cancel button is
@@ -1489,6 +1543,8 @@ export class InstanceLifecycle {
1489
1543
  this.ctx.touchActivity(name);
1490
1544
  });
1491
1545
  this.attachIncidentHandlers(name, daemon);
1546
+ // #2897: a new daemon starts with no dialog held; a notice the last one left (a crash, a respawn) is out of date.
1547
+ this.ctx.resolveParkedNotice?.(name);
1492
1548
  daemon.on("pty_recovered", safeHandler((data) => {
1493
1549
  const mins = Math.floor(data.downtime_s / 60);
1494
1550
  const secs = data.downtime_s % 60;
@@ -1647,6 +1703,8 @@ export class InstanceLifecycle {
1647
1703
  this.invalidate(name);
1648
1704
  this.wokeAt.delete(name);
1649
1705
  this.ctx.setTopicIcon(name, "remove");
1706
+ // #2897: a stopped instance holds no dialog — its "needs a human" notices are out of date.
1707
+ this.ctx.resolveParkedNotice?.(name);
1650
1708
  // B1: cancel any pending capacity backoff timer so a stopped/removed
1651
1709
  // instance is not restarted behind the user's back.
1652
1710
  const pendingBackoff = this.capacityBackoffTimers.get(name);