@songsid/agend 2.3.0-beta.1 → 2.3.0-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 (351) hide show
  1. package/dist/agent-cli-instructions.md +5 -2
  2. package/dist/agent-cli.js +43 -7
  3. package/dist/agent-cli.js.map +1 -1
  4. package/dist/agent-endpoint.js +4 -0
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/agent-file-read.d.ts +14 -6
  7. package/dist/agent-file-read.js +207 -19
  8. package/dist/agent-file-read.js.map +1 -1
  9. package/dist/agent-whats-new.d.ts +11 -0
  10. package/dist/agent-whats-new.js +29 -15
  11. package/dist/agent-whats-new.js.map +1 -1
  12. package/dist/auth-api.d.ts +30 -1
  13. package/dist/auth-api.js +45 -13
  14. package/dist/auth-api.js.map +1 -1
  15. package/dist/authority/authority-state.d.ts +38 -0
  16. package/dist/authority/authority-state.js +114 -0
  17. package/dist/authority/authority-state.js.map +1 -0
  18. package/dist/authority/session-authorizations.d.ts +43 -0
  19. package/dist/authority/session-authorizations.js +102 -0
  20. package/dist/authority/session-authorizations.js.map +1 -0
  21. package/dist/authority/web-authority.d.ts +120 -0
  22. package/dist/authority/web-authority.js +157 -0
  23. package/dist/authority/web-authority.js.map +1 -0
  24. package/dist/backend/claude-code.d.ts +2 -2
  25. package/dist/backend/claude-code.js +10 -5
  26. package/dist/backend/claude-code.js.map +1 -1
  27. package/dist/backend/types.d.ts +14 -0
  28. package/dist/backend/types.js +25 -0
  29. package/dist/backend/types.js.map +1 -1
  30. package/dist/backend-availability.d.ts +120 -0
  31. package/dist/backend-availability.js +396 -0
  32. package/dist/backend-availability.js.map +1 -0
  33. package/dist/backend-command.d.ts +21 -3
  34. package/dist/backend-command.js +23 -4
  35. package/dist/backend-command.js.map +1 -1
  36. package/dist/bundled-skills.d.ts +14 -0
  37. package/dist/bundled-skills.js +29 -0
  38. package/dist/bundled-skills.js.map +1 -0
  39. package/dist/cache-analysis.d.ts +47 -1
  40. package/dist/cache-analysis.js +68 -8
  41. package/dist/cache-analysis.js.map +1 -1
  42. package/dist/cache-ledger.d.ts +16 -3
  43. package/dist/cache-ledger.js +33 -13
  44. package/dist/cache-ledger.js.map +1 -1
  45. package/dist/cache-report-tool.d.ts +17 -0
  46. package/dist/cache-report-tool.js +40 -0
  47. package/dist/cache-report-tool.js.map +1 -0
  48. package/dist/cache-service.d.ts +70 -3
  49. package/dist/cache-service.js +178 -17
  50. package/dist/cache-service.js.map +1 -1
  51. package/dist/channel/adapters/discord.d.ts +7 -0
  52. package/dist/channel/adapters/discord.js +35 -0
  53. package/dist/channel/adapters/discord.js.map +1 -1
  54. package/dist/channel/mcp-tools.js +22 -10
  55. package/dist/channel/mcp-tools.js.map +1 -1
  56. package/dist/channel/types.d.ts +6 -0
  57. package/dist/classic-channel-manager.d.ts +10 -5
  58. package/dist/classic-channel-manager.js +12 -9
  59. package/dist/classic-channel-manager.js.map +1 -1
  60. package/dist/cli.js +130 -31
  61. package/dist/cli.js.map +1 -1
  62. package/dist/config-validator.js +103 -4
  63. package/dist/config-validator.js.map +1 -1
  64. package/dist/daemon.d.ts +7 -0
  65. package/dist/daemon.js +63 -16
  66. package/dist/daemon.js.map +1 -1
  67. package/dist/decision-list.d.ts +25 -0
  68. package/dist/decision-list.js +30 -0
  69. package/dist/decision-list.js.map +1 -0
  70. package/dist/delivery-outbox.d.ts +10 -0
  71. package/dist/delivery-outbox.js +12 -1
  72. package/dist/delivery-outbox.js.map +1 -1
  73. package/dist/fleet-context.d.ts +10 -0
  74. package/dist/fleet-manager.d.ts +417 -11
  75. package/dist/fleet-manager.js +1387 -109
  76. package/dist/fleet-manager.js.map +1 -1
  77. package/dist/fleet-traffic.d.ts +74 -0
  78. package/dist/fleet-traffic.js +196 -0
  79. package/dist/fleet-traffic.js.map +1 -0
  80. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +20 -5
  81. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +6 -1
  82. package/dist/general-knowledge/skills/multi-channel/SKILL.md +3 -2
  83. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
  84. package/dist/general-knowledge/skills/web-appearance/SKILL.md +257 -23
  85. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +476 -0
  86. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
  87. package/dist/human-delivery-receipts.d.ts +24 -1
  88. package/dist/human-delivery-receipts.js +64 -11
  89. package/dist/human-delivery-receipts.js.map +1 -1
  90. package/dist/instance-config-impact.js +3 -1
  91. package/dist/instance-config-impact.js.map +1 -1
  92. package/dist/instance-names.d.ts +4 -0
  93. package/dist/instance-names.js +12 -0
  94. package/dist/instance-names.js.map +1 -0
  95. package/dist/instructions.d.ts +12 -1
  96. package/dist/instructions.js +13 -2
  97. package/dist/instructions.js.map +1 -1
  98. package/dist/locale.js +100 -8
  99. package/dist/locale.js.map +1 -1
  100. package/dist/ls-attach-resolve.d.ts +95 -0
  101. package/dist/ls-attach-resolve.js +174 -0
  102. package/dist/ls-attach-resolve.js.map +1 -0
  103. package/dist/memory-hogs.d.ts +27 -0
  104. package/dist/memory-hogs.js +124 -0
  105. package/dist/memory-hogs.js.map +1 -0
  106. package/dist/outbound-handlers.d.ts +10 -0
  107. package/dist/outbound-handlers.js +122 -2
  108. package/dist/outbound-handlers.js.map +1 -1
  109. package/dist/outbound-schemas.d.ts +164 -4
  110. package/dist/outbound-schemas.js +99 -3
  111. package/dist/outbound-schemas.js.map +1 -1
  112. package/dist/public-web-gateway.js +8 -2
  113. package/dist/public-web-gateway.js.map +1 -1
  114. package/dist/public-web-link.d.ts +9 -0
  115. package/dist/public-web-link.js +8 -0
  116. package/dist/public-web-link.js.map +1 -1
  117. package/dist/quickstart-api.d.ts +10 -1
  118. package/dist/quickstart-api.js +12 -4
  119. package/dist/quickstart-api.js.map +1 -1
  120. package/dist/reply-buttons-controller.d.ts +4 -0
  121. package/dist/reply-buttons-controller.js +2 -2
  122. package/dist/reply-buttons-controller.js.map +1 -1
  123. package/dist/restart-progress.d.ts +65 -1
  124. package/dist/restart-progress.js +236 -10
  125. package/dist/restart-progress.js.map +1 -1
  126. package/dist/rollout-index.d.ts +5 -0
  127. package/dist/rollout-index.js +26 -5
  128. package/dist/rollout-index.js.map +1 -1
  129. package/dist/scheduler/scheduler.d.ts +12 -0
  130. package/dist/scheduler/scheduler.js +83 -10
  131. package/dist/scheduler/scheduler.js.map +1 -1
  132. package/dist/service-installer.d.ts +2 -1
  133. package/dist/service-installer.js +18 -3
  134. package/dist/service-installer.js.map +1 -1
  135. package/dist/settings-api.d.ts +19 -0
  136. package/dist/settings-api.js +137 -2
  137. package/dist/settings-api.js.map +1 -1
  138. package/dist/settings-change.js +104 -0
  139. package/dist/settings-change.js.map +1 -1
  140. package/dist/settings-effect.js +17 -1
  141. package/dist/settings-effect.js.map +1 -1
  142. package/dist/tmux-manager.d.ts +5 -0
  143. package/dist/tmux-manager.js +16 -0
  144. package/dist/tmux-manager.js.map +1 -1
  145. package/dist/tool-permissions.d.ts +4 -6
  146. package/dist/tool-permissions.js +53 -5
  147. package/dist/tool-permissions.js.map +1 -1
  148. package/dist/topic-commands.d.ts +7 -1
  149. package/dist/topic-commands.js +18 -4
  150. package/dist/topic-commands.js.map +1 -1
  151. package/dist/types.d.ts +48 -1
  152. package/dist/ui/app-effects.js +77 -31
  153. package/dist/ui/chat-ambient.js +307 -0
  154. package/dist/ui/chat-effect-posters.js +8 -8
  155. package/dist/ui/chat-effects.js +101 -13
  156. package/dist/ui/chat-render.js +5 -2
  157. package/dist/ui/chat-strings.js +59 -6
  158. package/dist/ui/chat-thread.js +149 -21
  159. package/dist/ui/effect-trial-controller.js +13 -8
  160. package/dist/ui/effect-trial-panel.js +19 -16
  161. package/dist/ui/fleet-cache.js +23 -1
  162. package/dist/ui/fleet-canvas-layout.js +111 -0
  163. package/dist/ui/fleet-canvas.js +525 -0
  164. package/dist/ui/fleet-org.js +27 -12
  165. package/dist/ui/fleet-traffic.js +343 -0
  166. package/dist/ui/fleet-usage.js +401 -0
  167. package/dist/ui/panel-chat.js +127 -49
  168. package/dist/ui/panel-details.js +2 -1
  169. package/dist/ui/panel-fleet.js +41 -16
  170. package/dist/ui/panel-settings.js +26 -8
  171. package/dist/ui/preview.js +3 -2
  172. package/dist/ui/settings-appearance.js +42 -18
  173. package/dist/ui/settings-catalog.js +92 -0
  174. package/dist/ui/settings-dialogs.js +40 -12
  175. package/dist/ui/settings-effects.js +4 -3
  176. package/dist/ui/settings-guests.js +117 -0
  177. package/dist/ui/settings-learn.js +25 -0
  178. package/dist/ui/settings-model.js +15 -6
  179. package/dist/ui/settings-mods.js +23 -9
  180. package/dist/ui/settings-owner-effects.js +9 -9
  181. package/dist/ui/settings-strings.js +120 -42
  182. package/dist/ui/settings-web-authority.js +91 -0
  183. package/dist/ui/shared/agend-auth.js +1 -1
  184. package/dist/ui/shared/app-i18n.js +4 -2
  185. package/dist/ui/shared/app-prefs.js +5 -4
  186. package/dist/ui/shared/app-route.js +1 -1
  187. package/dist/ui/shared/app-session.js +2 -0
  188. package/dist/ui/shared/app-shell.js +75 -9
  189. package/dist/ui/shared/app-store.js +26 -1
  190. package/dist/ui/shared/app-stream.js +3 -1
  191. package/dist/ui/shared/app-themes.js +24 -6
  192. package/dist/ui/shared/app.css +364 -16
  193. package/dist/ui/shared/app.js +21 -14
  194. package/dist/ui/shared/card-strings.js +4 -0
  195. package/dist/ui/shared/effect-app-runtime.js +68 -19
  196. package/dist/ui/shared/effect-chat-runtime.js +16 -3
  197. package/dist/ui/shared/effect-frame.js +26 -7
  198. package/dist/ui/shared/effect-geometry.js +24 -9
  199. package/dist/ui/shared/effect-policy.js +21 -7
  200. package/dist/ui/shared/effect-profiler.js +31 -9
  201. package/dist/ui/shared/effect-registry.js +87 -48
  202. package/dist/ui/shared/effect-stock-snapshot.js +9 -0
  203. package/dist/ui/shared/effect-stock-trust.js +62 -10
  204. package/dist/ui/shared/effect-trial-shadow.js +62 -0
  205. package/dist/ui/shared/effect-trial-source.js +1 -1
  206. package/dist/ui/shared/effect-trial-stage.js +54 -31
  207. package/dist/ui/shared/effect-trial.css +40 -0
  208. package/dist/ui/shared/fx-motion.js +67 -0
  209. package/dist/ui/shared/identity-card.js +75 -4
  210. package/dist/ui/shared/identity-color.js +3 -3
  211. package/dist/ui/shared/instance-nav.js +194 -28
  212. package/dist/ui/shared/panel-view.js +24 -4
  213. package/dist/ui/shared/tokens.css +9 -3
  214. package/dist/ui/shared/ui-icons.js +1 -0
  215. package/dist/ui/shared/usage-dialog.js +22 -2
  216. package/dist/ui/shared/view-strings.js +68 -2
  217. package/dist/ui/shared/web-authorize.js +151 -0
  218. package/dist/ui/signin.html +1 -1
  219. package/dist/ui/web-terminal/terminal.css +4 -4
  220. package/dist/usage/providers.d.ts +28 -0
  221. package/dist/usage/providers.js +126 -36
  222. package/dist/usage/providers.js.map +1 -1
  223. package/dist/usage-report.d.ts +158 -0
  224. package/dist/usage-report.js +226 -0
  225. package/dist/usage-report.js.map +1 -0
  226. package/dist/usage-rollup.d.ts +51 -0
  227. package/dist/usage-rollup.js +168 -0
  228. package/dist/usage-rollup.js.map +1 -0
  229. package/dist/view-api.d.ts +39 -0
  230. package/dist/view-api.js +65 -4
  231. package/dist/view-api.js.map +1 -1
  232. package/dist/web-ambient.d.ts +72 -0
  233. package/dist/web-ambient.js +161 -0
  234. package/dist/web-ambient.js.map +1 -0
  235. package/dist/web-api.d.ts +69 -5
  236. package/dist/web-api.js +362 -45
  237. package/dist/web-api.js.map +1 -1
  238. package/dist/web-appearance-policy.d.ts +4 -6
  239. package/dist/web-appearance-policy.js +5 -12
  240. package/dist/web-appearance-policy.js.map +1 -1
  241. package/dist/web-appearance-tools.d.ts +3 -0
  242. package/dist/web-appearance-tools.js +22 -3
  243. package/dist/web-appearance-tools.js.map +1 -1
  244. package/dist/web-appearance-view.d.ts +27 -2
  245. package/dist/web-appearance-view.js +129 -14
  246. package/dist/web-appearance-view.js.map +1 -1
  247. package/dist/web-appearance.d.ts +17 -3
  248. package/dist/web-appearance.js +82 -7
  249. package/dist/web-appearance.js.map +1 -1
  250. package/dist/web-asset-parts.d.ts +5 -10
  251. package/dist/web-asset-parts.js +3 -3
  252. package/dist/web-asset-parts.js.map +1 -1
  253. package/dist/web-auth.js +3 -1
  254. package/dist/web-auth.js.map +1 -1
  255. package/dist/web-card.d.ts +14 -0
  256. package/dist/web-card.js +40 -6
  257. package/dist/web-card.js.map +1 -1
  258. package/dist/web-channel-echo.d.ts +7 -1
  259. package/dist/web-channel-echo.js +6 -2
  260. package/dist/web-channel-echo.js.map +1 -1
  261. package/dist/web-chat-history.d.ts +46 -0
  262. package/dist/web-chat-history.js +80 -3
  263. package/dist/web-chat-history.js.map +1 -1
  264. package/dist/web-commands.d.ts +1 -0
  265. package/dist/web-effect-bootstrap.d.ts +12 -0
  266. package/dist/web-effect-bootstrap.js +49 -0
  267. package/dist/web-effect-bootstrap.js.map +1 -0
  268. package/dist/web-effect-bundle.js +46 -1
  269. package/dist/web-effect-bundle.js.map +1 -1
  270. package/dist/web-effect-playback.d.ts +30 -0
  271. package/dist/web-effect-playback.js +71 -0
  272. package/dist/web-effect-playback.js.map +1 -0
  273. package/dist/web-effect-profiles.d.ts +4 -4
  274. package/dist/web-effect-service.d.ts +11 -4
  275. package/dist/web-effect-service.js +28 -5
  276. package/dist/web-effect-service.js.map +1 -1
  277. package/dist/web-effect-tools.d.ts +1 -0
  278. package/dist/web-effect-tools.js +8 -5
  279. package/dist/web-effect-tools.js.map +1 -1
  280. package/dist/web-effect-trials.d.ts +4 -4
  281. package/dist/web-effect-trials.js +6 -6
  282. package/dist/web-effect-trials.js.map +1 -1
  283. package/dist/web-effect-upload.d.ts +2 -4
  284. package/dist/web-effect-upload.js +3 -8
  285. package/dist/web-effect-upload.js.map +1 -1
  286. package/dist/web-effect-worker.d.ts +1 -1
  287. package/dist/web-effect-worker.js +2 -2
  288. package/dist/web-effect-worker.js.map +1 -1
  289. package/dist/web-effect.d.ts +14 -0
  290. package/dist/web-effect.js +21 -0
  291. package/dist/web-effect.js.map +1 -1
  292. package/dist/web-guest-access.d.ts +125 -0
  293. package/dist/web-guest-access.js +234 -0
  294. package/dist/web-guest-access.js.map +1 -0
  295. package/dist/web-guest-rooms.d.ts +82 -0
  296. package/dist/web-guest-rooms.js +135 -0
  297. package/dist/web-guest-rooms.js.map +1 -0
  298. package/dist/web-identity-color.d.ts +1 -1
  299. package/dist/web-identity-color.js +2 -2
  300. package/dist/web-identity-color.js.map +1 -1
  301. package/dist/web-identity-palette.d.ts +1 -1
  302. package/dist/web-identity-palette.js +2 -2
  303. package/dist/web-identity-palette.js.map +1 -1
  304. package/dist/web-login.d.ts +47 -0
  305. package/dist/web-login.js +115 -0
  306. package/dist/web-login.js.map +1 -1
  307. package/dist/web-mod-agent.d.ts +1 -1
  308. package/dist/web-mod-agent.js +12 -8
  309. package/dist/web-mod-agent.js.map +1 -1
  310. package/dist/web-mod-bundle.d.ts +14 -1
  311. package/dist/web-mod-bundle.js +68 -3
  312. package/dist/web-mod-bundle.js.map +1 -1
  313. package/dist/web-mod-export.d.ts +9 -0
  314. package/dist/web-mod-export.js +21 -0
  315. package/dist/web-mod-export.js.map +1 -1
  316. package/dist/web-mod-store.d.ts +7 -1
  317. package/dist/web-mod-store.js +21 -7
  318. package/dist/web-mod-store.js.map +1 -1
  319. package/dist/web-prefs.d.ts +14 -0
  320. package/dist/web-prefs.js +24 -4
  321. package/dist/web-prefs.js.map +1 -1
  322. package/dist/web-preview.d.ts +6 -2
  323. package/dist/web-preview.js +4 -2
  324. package/dist/web-preview.js.map +1 -1
  325. package/dist/web-returning-device.d.ts +41 -0
  326. package/dist/web-returning-device.js +57 -5
  327. package/dist/web-returning-device.js.map +1 -1
  328. package/dist/web-session-authorization.d.ts +132 -0
  329. package/dist/web-session-authorization.js +193 -0
  330. package/dist/web-session-authorization.js.map +1 -0
  331. package/dist/web-session.d.ts +70 -10
  332. package/dist/web-session.js +137 -22
  333. package/dist/web-session.js.map +1 -1
  334. package/dist/web-settings-patch.d.ts +49 -2
  335. package/dist/web-settings-patch.js +145 -1
  336. package/dist/web-settings-patch.js.map +1 -1
  337. package/dist/web-settings-tools.d.ts +89 -0
  338. package/dist/web-settings-tools.js +270 -0
  339. package/dist/web-settings-tools.js.map +1 -0
  340. package/dist/web-shell-routes.d.ts +1 -1
  341. package/dist/web-shell-routes.js +1 -1
  342. package/dist/web-shell-routes.js.map +1 -1
  343. package/dist/web-theme-store.d.ts +39 -0
  344. package/dist/web-theme-store.js +122 -11
  345. package/dist/web-theme-store.js.map +1 -1
  346. package/dist/web-theme.d.ts +2 -0
  347. package/dist/web-theme.js +10 -1
  348. package/dist/web-theme.js.map +1 -1
  349. package/dist/workflow-templates/default.md +1 -1
  350. package/package.json +1 -1
  351. package/templates/systemd.service.ejs +8 -0
@@ -0,0 +1,476 @@
1
+ ---
2
+ name: web-dashboard
3
+ description: Where things are on the AgEnD web dashboard and what they do — signing in, the chat, Needs you, Fleet (org chart, live traffic), usage and the cache report, the Log, schedules, every Settings tab and control with its config key, and troubleshooting. Use it to answer "where is X / what does Y do / how do I Z" about the web.
4
+ roles: [general, worker, classic]
5
+ ---
6
+
7
+ ## How to use this skill
8
+
9
+ Look the question up in the index, then relay the short answer in the user's words. The labels below are the
10
+ English UI labels (the page also has 中文). Before you state a value the user configured (a limit, a switch), read
11
+ it: `get_fleet_config` shows fleet.yaml; this skill gives defaults. Never invent a control that is not listed here.
12
+ Never tell anyone to kill `wslrelay` or run `wsl --shutdown` (see Troubleshooting).
13
+
14
+ For how *you* look on the dashboard (theme, identity card, colour, widgets, ambient effects, effects, mods), load `web-appearance`.
15
+
16
+ ## Index
17
+
18
+ | The user asks about… | Section |
19
+ |---|---|
20
+ | getting in, `/web`, codes, "Send me a new code", the public link, sessions, signing out, `/view`, guests | [Sign-in and access](#sign-in-and-access) |
21
+ | sending, files, buttons, polls, HTML previews, code, tables, slash commands, Stop, history, copies in Discord/Telegram | [Chat](#chat) |
22
+ | the red badge, prompts, failed deliveries, desktop notifications | [Needs you](#needs-you) |
23
+ | tasks, schedules, teams, org chart, live traffic lines, cache, Config tab | [Fleet](#fleet) |
24
+ | the sidebar list, filters, favorites, Chat / View / Log / Details, the Details page | [Finding an instance](#finding-an-instance) |
25
+ | subscription meters, plan badges, profiles, keep-warm, prompt cache | [Usage and the cache report](#usage-and-the-cache-report) |
26
+ | what an agent did step by step | [The Log tab](#the-log-tab) |
27
+ | any Settings control | [Settings](#settings) |
28
+ | themes, cards, widgets, ambient effects (petals, click stars), effects, mods | [Web appearance](#web-appearance) |
29
+ | blank page, preview refused, link fails, signed out, "live" missing | [Troubleshooting](#troubleshooting) |
30
+
31
+ Addresses: the dashboard is served on the host at `http://localhost:<health_port>` (default 19280), on 127.0.0.1
32
+ only. Pages: `/ui` chat, `/ui/fleet`, `/ui/needs`, `/view`, `/settings`.
33
+
34
+ ## Sign-in and access
35
+
36
+ **Getting a code (`/web`).** Only a fleet admin can — someone in the bot connection's `access.allowed_users`.
37
+ - Discord: send `/web` (alias of `/dashboard`) in the General channel. A menu offers **💻 AgEnD computer: get a
38
+ code** and, when `web.public_link.allow_public` is not `false`, **🌐 Other device (temporary public)**. Sent
39
+ anywhere else, `/web` answers privately (DM, else an ephemeral reply) with the local link and a code only.
40
+ - Telegram: `/web` works only in the General topic ("/web works in the General topic — please use it there"). In a
41
+ DM with the bot, `/start web` opens the same menu when one General is configured.
42
+ - On the host: `agend web` prints a code and opens the browser; `agend web --code` only prints it.
43
+ - If the bot has no admins: "⛔ /web disabled — this bot has no fleet admins: … is empty."
44
+
45
+ **The code.** 8 characters shown as `ABCD-EFGH` (case and the dash don't matter), valid 5 minutes, single use; asking
46
+ again replaces it. 5 wrong tries use it up; 20 failures in 15 minutes pause sign-in for 5 minutes ("Too many wrong
47
+ codes — sign-in is paused for a few minutes."). The sign-in page is **Sign in to AgEnD**: field **One-time code**,
48
+ button **Sign in**.
49
+
50
+ **Send me a new code.** On the sign-in page, for a browser that signed in before with a `/web` code (remembered 90
51
+ days). The code arrives by DM. Limits: one a minute and five an hour per browser; fleet-wide one per 20 s, 20 an hour.
52
+
53
+ **Local vs public link.** Local: the dashboard on the host itself (127.0.0.1; the address cannot be changed, only
54
+ `health_port`). Public: **🌐 Other device (temporary public)** starts a Cloudflare quick tunnel (an address under
55
+ `trycloudflare.com`), default 120 minutes (`web.public_link.ttl_minutes`, at most 480; `protocol` http2/quic/auto).
56
+ Close it with **Close public link** → **Close link (signs public browsers out)**, `/web revoke`, or let it expire.
57
+ A public link is limited on purpose: no live stream (the page polls), no custom CSS, and Settings → Web, appearance,
58
+ mods, effect-library/personal-selection management, schedule edits and preference writes are refused. Current in-scope
59
+ 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
60
+ of their own (`web.preview_on_public_link`, default on).
61
+
62
+ **Sessions.**
63
+ - Local: 48 h from sign-in and 48 h unused (`web.session.local.absolute_hours` / `idle_hours`, 1–720). Background
64
+ polling and the live stream don't count as use. Sessions survive a fleet restart.
65
+ - Public link: always 4 h / 30 min unused, and they end when the link closes.
66
+ - At most 8 sessions; the least recently used is dropped.
67
+ - The session menu (sidebar): "Signed in · …", "Ends by <time> at the latest, or after <span> unused". With more than
68
+ one session it lists **Signed-in devices** (this one marked "· This device", others with **Sign out**) and **Sign
69
+ out everywhere**.
70
+ - `/web revoke` (in chat) signs every browser out, withdraws an unused code and closes the public link.
71
+
72
+ **`/view` without signing in.** `web.view_access`: `open` (default) or `session`. With `open`, anyone who can reach
73
+ the local address sees every instance's live terminal and the roster (status, context %, model, effort, backend,
74
+ tags, name, description, avatars, cards) and the usage meters — read only; editing says "Sign in to edit". Over a
75
+ public link `/view` always needs sign-in.
76
+
77
+ **Guests (#1920, 2.3 beta).** Off by default: `web.guests.enabled` (or Settings → Web → Guests). Then someone who is
78
+ not a fleet admin sends `/web` and gets a code privately, signing in as their own Discord or Telegram account. A guest
79
+ sees only the agents they can already use in chat: their connection's fleet topics and General (an `open` connection:
80
+ only `web.guests.open_instances`), their own Telegram private ClassicBot room, and ClassicBot group rooms while their
81
+ membership is verified, minus any `web.guests.narrow`. They can chat there unless `web.guests.chat` is false, never send
82
+ a command (text starting with `/` is refused), and the agent sees them as `via web (guest)`. A guest's app has no Fleet,
83
+ View, Settings or Needs you. To invite someone: turn it on, then tell them to send `/web`. The Guests card is not in
84
+ Settings over the public link.
85
+
86
+ **Web authority (#1939, 2.3 beta).** A signed-in fleet admin's browser can speak as their own Discord or Telegram
87
+ account. Under the composer (and in the session menu) the line says **Not verified · Authorize this browser**. Pressing it
88
+ sends a card to that account's DM, saying which browser (device, on this computer or the network, when, until when), with
89
+ **Confirm** and **Not me**. A card left for 5 minutes is marked expired on the card, and the line offers Authorize
90
+ again. Confirm within 5 minutes and the line says **Verified · speaks as you until …**. That
91
+ browser's messages then carry the account's authority in their delivery receipt for `max_session_hours` (default 48).
92
+ Not me signs that browser out, also after Confirm, from the same card. At most one card waits per browser, and 3 an hour
93
+ per account. Never on the public link or for a guest; when a browser can't be authorized, the line says why (with a
94
+ link to Settings when the switch or "Only this computer" is the reason). Settings → Web → **Web authority**
95
+ (`web.verified_authority`, on by default) has the switch, **Only this computer can authorize** (`loopback_only`), the
96
+ hours, the authorized sessions, and **Revoke web authority** (or `/web revoke`). Every change there applies at once.
97
+ Agents then see that browser's messages as `via web (verified)` and check their receipt like a Discord or Telegram message.
98
+
99
+ ## Chat
100
+
101
+ **Sending.** Type and press Enter. A message sent while the agent works waits its turn; `/steer <text>` goes into
102
+ the current turn, `/btw <question>` asks a side question. **Stop reply** (or Esc) interrupts the reply and drops
103
+ queued messages. Text is capped at 16,384 characters; a paste over 4,000 characters becomes a `pasted-….txt`
104
+ attachment (its chip has **As text** to undo that).
105
+
106
+ **Ticks** under your message: ◷ waiting behind another message · ✓ handed to the agent · ✓✓ the agent has it ·
107
+ ! not delivered · ⊘ dropped by Stop. There is no "read" tick.
108
+
109
+ **Files.** 📎, drag and drop ("Drop files to attach them") or paste. Up to 5 files, 50 MB each, 100 MB per message
110
+ (`web.upload_max_file_mb` / `web.upload_max_total_mb`, 1–500; over a public link at most 95 MB per file). The type is
111
+ read from the bytes: PNG/JPEG/GIF/WebP are photos, PDF a document, UTF-8 a text file; anything else (archives,
112
+ binaries, `.html`/`.svg` and other markup) is stored as **download-only**. The agent receives the path in its
113
+ workspace `inbox/`; an unused upload is deleted after 30 minutes.
114
+
115
+ **In replies.** Images inline; video and audio play inline; Markdown, CSV, JSON, code and text files get a **Show**
116
+ card (200 lines, then "Show all … lines"); other files download. Code blocks have a language tag, **Wrap** and
117
+ **Copy**, and fold after 30 lines. Each reply has **Copy this reply**. Markdown: headings, lists, quotes, bold/italic/
118
+ strike, links, and tables (header row plus separator, alignment, up to 20 columns). Discord mentions show as names;
119
+ a Discord server emoji (`<:name:id>`) of the fleet's servers shows as its picture, and any other (or one whose picture
120
+ can't load) as `:name:`. Unicode emoji are drawn by the system's colour emoji font under every theme font (boxes on
121
+ Linux mean no colour emoji font is installed). There is no @-autocomplete in the composer.
122
+
123
+ **Buttons and polls.** An agent's reply can carry up to 10 buttons ("Choices"); a click shows as a 🔘 chip and the
124
+ agent receives `[button] <label>` (with `(value: …)` when it differs). Buttons expire after 24 h ("Expired — reply in
125
+ text"). Polls show "Poll", "Time left", "🗳 N answered"; voter names only when it closes.
126
+
127
+ **HTML previews.** An agent's ` ```html ` block or `.html` file gets a card: **Preview**, **Stop**, **Download**,
128
+ **Open in panel** (side panel: **Page** / **Code** / **Reload** / **Close**). Previews need a one-time opt-in, **Allow
129
+ HTML previews** (also in Settings → Preferences); it is a host-wide preference, and you still press Preview each time.
130
+ The page runs in a sandboxed frame on a second port (`health_port + 1`, default 19281). "Never preview HTML on this
131
+ device" turns it off for this browser session. Cards are at most 1 MiB; a cut-off block says "Truncated — ask the
132
+ agent to send it as a .html file."
133
+
134
+ **Slash commands** (the **Commands** palette): `/ctx`, `/compact [instructions]`, `/clear` (asks first), `/model
135
+ [name]`, `/backend [backend] [model] [effort]` (asks first), `/effort [level]`, `/cancel`, `/btw`, `/steer`, `/pause`,
136
+ `/wake`, `/save <file>` (not on a public link). Anything else: "Not a command here — Enter sends it as a message."
137
+ At 70% context, quick actions **Compact** and **Clear…** appear. `/raw <text>` (local only) passes text to the CLI
138
+ unwrapped.
139
+
140
+ **History.** The server keeps the last 500 messages (about 1M characters) per instance in its workspace
141
+ `web-chat.json`; the page loads the last 200. There is no "load older". After a restart, buttons and ticks are not
142
+ restored; files that can't be served again show as unavailable.
143
+
144
+ **Copies in Discord/Telegram (web echo).** For a fleet topic instance, each web message is also posted to its topic as
145
+ `🌐 web · <name>: …` (the first 500 characters plus attachment names; longer text says "(full text in web chat)").
146
+ Turn it off with Settings → Web → **Web echo** (`web.echo_to_channel`). ClassicBot rooms: per room,
147
+ `classicBot.yaml` `channels.<key>.web_echo` (Settings → ClassicBot → the room → **Web echo**). From 2.3.0-beta.3
148
+ (#2054) a room echoes by default: an unset room follows `web.echo_to_channel`, `web_echo: false` keeps it off and
149
+ `web_echo: true` keeps it on. Before that, a room echoed only with `web_echo: true` — check the running version.
150
+
151
+ ## Needs you
152
+
153
+ `/ui/needs`, the sidebar row **Needs you** with a count, the phone tab of the same name, and "(N)" in the browser
154
+ tab title. Items, grouped by instance, oldest first:
155
+ - the CLI waiting: "Permission needed", "Dangerous command waiting", "Sign-in needed", "Waiting at a dialog", "May be
156
+ waiting for input", "Waiting at its terminal", "Not responding", "Exited";
157
+ - the instance: "Paused: sign-in needed", "Crashed";
158
+ - deliveries from the last 24 h: "Could not confirm delivery", "Delivery failed" (source → target · kind).
159
+
160
+ A prompt shows its own answer buttons (first answer wins); a delivery has **Acknowledge** (clears it everywhere);
161
+ every item has **Open chat**. **Notify me on this device** (Turn on / Turn off) gives desktop notifications while the
162
+ tab is hidden — per browser, not on phones or plain-HTTP addresses. Config: `needs_you.live_message` (default on),
163
+ `needs_you.dm` (default off).
164
+
165
+ ## Fleet
166
+
167
+ `/ui/fleet/<tab>`: **Tasks**, **Schedules**, **Teams**, **Org chart**, **Cache**, **Config**, plus a **Docs** link.
168
+ The sidebar's **Fleet overview** opens the Org chart.
169
+ - **Tasks** — the task board: **New task** (title, description, priority, assignee), **Claim**, **Done**. No delete.
170
+ - **Schedules** — every schedule (silent ones included): when it runs in words, "next …", the target. **New
171
+ schedule** (Repeat with a cron expression, or Once at a date and time; message, target, label, timezone),
172
+ **Edit** (with an **Enabled** box — that is how you pause one), **Delete**. There is no "run now", and silent can't
173
+ be set from the web. Read only on a public link.
174
+ - **Teams** — **New team**, **Edit** (members, description; no rename), **Delete**. Read only on a public link.
175
+ - **Org chart** — see below.
176
+ - **Cache** — see [the cache report](#usage-and-the-cache-report).
177
+ - **Config** — the main channel, access (Locked/Open, allowed users), default backend and project roots; **Save
178
+ changes** rewrites fleet.yaml (its comments are lost).
179
+
180
+ **Org chart (#1918).** **Canvas** or **List** (remembered per device). The canvas: General at the top, then teams in
181
+ fleet.yaml order, then "Not in a team". Drag to pan, wheel or pinch to zoom (0.2–2.5), **Zoom in / Zoom out / Fit to
182
+ screen**, keys `+` `-` `0` and arrows, Enter opens a chat. **Overview** (bottom right, desktop) — click to move there.
183
+ Click a team header to fold it. **Find** dims everything that doesn't match. A card shows the state dot, name, state
184
+ and backend; clicking it opens the chat. List mode adds the description, model, a link to the Discord thread or
185
+ Telegram topic, and **Open chat**.
186
+
187
+ **Live traffic** (**Live** switch, on by default; **Key** in the toolbar explains it, as a strip above the canvas): a line for each message between instances.
188
+ Colour by kind — task (delegate_task) purple, send/query/update teal, report pink, broadcast orange; between teams
189
+ (zoomed out) slate. Dotted = queued, dashed with a moving pulse = being delivered, grey fading for 12 s = delivered or
190
+ read. "×N" = several messages share a line; failed ones belong in Needs you. A `delegate_task` also draws the work: a
191
+ slow-moving purple line, delegator → worker, **in progress** until the worker's `report_result` with the same
192
+ correlation id comes back (then one pink line returns); none after 4 h fades as **no report yet**. Reloads and the
193
+ public link show the open ones. Every line ends on a card or a folded team's box. No message
194
+ text is ever shown; instances with `cross_instance_visibility: hidden` are left out. On a public link it refreshes
195
+ every 5 s.
196
+
197
+ ## Finding an instance
198
+
199
+ **The sidebar list.** Grouped by team (an instance in `teams.<name>.members` under its first team, whatever its tags), else by
200
+ its first tag ("#" before the heading), ClassicBot rooms under Classic, the rest under Other; Settings → Agents the same (#2172).
201
+ Each row (#2179): name and context % on the first line, the time of the agent's last reply to a person at the end of the
202
+ second ("2 min ago"; cross-instance messages don't count); a reply under 10 minutes old is highlighted, fading by itself
203
+ (nothing to mark read). The sort button beside Edit: **Custom** (default; a reply never moves a row) or **Recent replies**
204
+ (the rest by last reply, no groups, no dragging; favorites pinned in their order, or **Sorted by last reply too**); synced
205
+ as `nav.sort`. Guests and the anonymous View reader: no times, no sort (always Custom).
206
+ **Filter: name, model, backend** (Esc clears), facets **Status** and **CLI**, "N / M shown".
207
+ While a filter is on, the instance you have open stays on top under **Current**. **Favorites**: the star on a row;
208
+ **Edit** to reorder (at most 50; "Clear the filter to reorder favorites"). Drag to reorder the full list; groups fold.
209
+ Order, folding, filter and favorites follow you across devices. A row keeps you on the same kind of page (from a Log
210
+ to that instance's Log).
211
+
212
+ **Chat | View | Log | Details** switch at the top of an instance.
213
+ - **View** — the live terminal (read only).
214
+ - **Log** — [the Log tab](#the-log-tab).
215
+ - **Details** — Configuration (display name, description, directory, bound to, tags; "Read only — change it in
216
+ Settings." with **Edit in Settings**), Runtime (backend, model, effort, cost, context, 5 h and 7 d rate), Recent
217
+ activity, its identity card and widget. The ⋯ menu: Start / Restart / Stop instance, Pause / Wake, Colour…, and
218
+ the theme lock/reset.
219
+
220
+ Phone layout: bottom tabs Chat, Needs you, Fleet, View, Settings.
221
+
222
+ ## Usage and the cache report
223
+
224
+ **Usage.** The **Usage** header button: a right-hand rail at 1200 px or wider (shown/hidden per device; on Chat,
225
+ View, Log, Details and Fleet), otherwise a dialog — **AI Subscription Usage**. One row per provider in use (Claude,
226
+ Codex, Muse, Grok, Kiro, Antigravity): Claude's **Session** (5-hour window) and **Weekly** (7-day), per-model weekly
227
+ rows, "binding" on the window that will stop you, **Extra usage** in dollars. "high" at 70%, "near limit" at 90%.
228
+ Refreshes every 60 s while open; **Refresh** forces it (at most once per 30 s); **Move up / Move down** reorders rows.
229
+ `web.usage_panel: false` hides the rail and dialog (the `/usage` chat command and `get_usage` still work).
230
+
231
+ **Profiles and plan badges.** Each Claude credential profile has its own row: the card says "Claude" with the
232
+ profile on its own line (the API and chat call it "Claude (<profile>)"); a shared row appears only while some
233
+ instance uses the default login. The badge is the account's plan — e.g. **Pro**, **Max ×20**, **Team ×6.25** (the
234
+ multiplier is its rate-limit multiple; full name on hover). A setup-token login has no badge. A signed-out profile
235
+ says "Not logged in — sign in with /login claude-code <profile> …". More: the `credential-profiles` skill.
236
+
237
+ **The cache report** (Fleet → **Cache**; the `get_cache_report` tool). How often each instance's prompt cache
238
+ expires between turns and what that costs, read from transcripts (Claude Code, Codex; kiro is credit-billed: "Not
239
+ available"). Windows **24 h / 7 days / 30 days**. Fleet row: **Expiry cost**, **Keep-warm would save**,
240
+ **Recommended**, and **Switch to 1-hour cache** when an instance needs it. Per instance: requests, gaps past the TTL,
241
+ expired (rewrote), tokens rewritten, expiry cost, keep-warm pings and their cost, net, cache writes 5 min / 1 h, and
242
+ **Behaves as** — whether a "5m" cache really expires after 5 minutes (measured over 5–60 minute gaps of the last 7
243
+ days). Money is list price (date shown); quota effects are estimates. `get_cache_report` gives the fleet to General,
244
+ coordinators and full-profile instances, and each other instance only its own row.
245
+
246
+ **The usage report** (the `get_usage_report` tool, and Fleet → **Usage**, `/ui/fleet/usage`, #2122; the ◔ dialog's
247
+ **By agent →** opens it). Per instance (or backend,
248
+ model, credential profile, team): input, output, cache read and cache write tokens, requests, delivered messages,
249
+ and an amount, over today / 7d / month / all / custom days in the fleet's timezone. **Every amount is the
250
+ API-equivalent at list price — not money spent** (subscriptions aren't billed per token): say "API-equivalent", never
251
+ "spent". Measured for Claude Code and Codex. Marks to repeat in words:
252
+ - `cache_write_not_reported`: Codex records no cache writes, so they are neither shown as 0 nor priced.
253
+ - `not_priced`: the tokens are shown, the amount isn't.
254
+ - `source_unknown`: read before #2122, when which backend and profile read it was not recorded (backend and profile
255
+ "unknown" — never today's).
256
+
257
+ Each hour keeps the backend whose reader read it and the profile it was read under, so an instance that changes
258
+ backend or profile keeps its history as it was. `notMeasured` lists kiro and the other backends with their reason;
259
+ they are never a $0 row, and what such an instance measured before still shows. Messages are counted per instance, so
260
+ by backend they go under its backend now. Coverage only says "read" for a catch-up that listed and read every source
261
+ (an unreadable directory or transcript is not covered, never a 0). Scope as
262
+ `get_cache_report`. The dashboard reaches it over the public link only with `web.usage_report_on_public_link: true`
263
+ (Settings → Web → **Usage report over the public link**, applies at once; otherwise the page says "Not offered over
264
+ the public link" and links to that switch on the dashboard reached directly); guests never. The page adds a daily trend (top 5 and
265
+ others), a heatmap that tells a day read with nothing used from a day not collected, and **Download CSV** (the shown
266
+ answer's daily rows, with the basis). Claude subagent (sidechain) turns aren't counted yet. A long range whose daily rows
267
+ are too many says from which date the charts and the CSV start (the totals stay whole); a day used only by an unpriced
268
+ model is "used, not priced"; after a timezone change each day keeps the zone it was made in, and the page says so.
269
+
270
+ **Keep-warm** means sending a small turn before the cache expires so the next real turn reads it instead of
271
+ rewriting it. **Today it is only a simulation and a recommendation** — AgEnD sends no keep-warm pings (#1469 is
272
+ still being designed). If the report says **Switch to 1-hour cache**, the remedy is
273
+ `backend_options.claude-code.prompt_cache_ttl: "1h"` on that instance (takes effect on the next start).
274
+
275
+ ## The Log tab
276
+
277
+ What an agent was asked, its replies (never its thinking), each tool call (Read, Edit, Search, Run, Web, MCP,
278
+ Sub-agent…, with **Show output**), errors, turn ends, compactions and fleet events, on one timeline. Filters **All /
279
+ Tools / Errors**; **Live** while it updates. Opens with the newest 200 steps; **Load older steps** adds 100 at a time
280
+ (the page keeps 1000). Off by default: `web.log_tab` (Settings → Web → **Log tab: each agent's steps**; turning it on
281
+ from the tab itself needs a fleet admin's confirmation). Full for Claude Code (also after it stopped) and Codex while
282
+ running; kiro shows fleet events only; other backends say they have no readable transcript. Secrets are masked.
283
+
284
+ ## Settings
285
+
286
+ Tabs (`/settings/<tab>`): **Preferences**, **Web appearance**, **Agents**, **Connections**, **ClassicBot**,
287
+ **General**, **Web**, **Developer**. Header: version, **Setup wizard**, **Help**.
288
+
289
+ **How changes apply.** Agents, Connections, ClassicBot, General, Web and Developer edits are *staged*: a dialog's
290
+ **Stage change** (General/Web: **Review changes**) adds it to the bar **Changes not applied yet**, which shows the
291
+ cost — **Immediately**, **Restart this Agent** or **Restart AgEnD** — then **Apply changes** or **Discard**.
292
+ Confirmations (e.g. opening access) are asked at Apply. A change that loosens access waits for a fleet admin to confirm
293
+ in the General chat ("Waiting for confirmation", **Withdraw**). After a failure, unapplied changes are staged again
294
+ (secrets must be re-entered). **Restart AgEnD** restarts every agent. Preferences and Web appearance save directly.
295
+
296
+ **Preferences** — follows you across devices unless marked:
297
+ | Control | What it does | Stored |
298
+ |---|---|---|
299
+ | Your name (**Save**, **Use web-user** / **Use <account>**) | the name agents see on your web messages | your profile |
300
+ | Theme: System / Light / Dark | page theme | host prefs `theme` |
301
+ | Language: English / 中文 | page language (not the bots' replies — that is General → Language) | host prefs `lang` |
302
+ | Names: Nickname first / Real name first | sidebar names | host prefs `names.primary` |
303
+ | Allow HTML previews | the preview opt-in | host prefs `preview.optIn` |
304
+ | Chat tour (this device) | replays the chat tour | browser |
305
+
306
+ **Web appearance** — see [Web appearance](#web-appearance) for the cards and what they mean.
307
+
308
+ **Agents** — **New agent**; per agent **Settings**, **Pause / Wake**, **Start / Stop** (direct), ⋯ **Delete agent**
309
+ (staged; on Apply it waits for a fleet admin's confirmation in General, then the agent is stopped and removed, as
310
+ `delete_instance` does — no restart). The agent dialog writes `instances.<name>.*` (an "Inherit" box removes the key):
311
+ | Label | Key | Applies |
312
+ |---|---|---|
313
+ | Display name, Description | `display_name`, `description` | now |
314
+ | Backend, Model, Working directory | `backend`, `model`, `working_directory` | restarts the agent |
315
+ | Auto-pause after (minutes, 0 = off) | `auto_pause_after` | now |
316
+ | Channel binding | `channel_id` | restarts AgEnD |
317
+ | Stuck timeout (minutes) | `hang_detector.timeout_minutes` | agent |
318
+ | Agent mode, Tool set | `agent_mode`, `tool_set` | agent |
319
+ | Tool progress; Bot-to-bot messages in topics (full / summary / hidden); Log level | `tool_progress`, `cross_instance_visibility`, `log_level` | now |
320
+ | Require a delivered reply | `reply_completion_guard` | now |
321
+ | Lightweight mode, Fallback model | `lightweight`, `model_failover` | agent |
322
+ | System prompt | `systemPrompt` | agent |
323
+ | Tags | `tags` | now |
324
+ | General topic (fleet dispatcher) | `general_topic` | AgEnD |
325
+ | Status emojis (Received, Queued, Processing, Delivered, Failed, …) | `status_emojis` | agent |
326
+
327
+ **Connections** (the bots) — **New connection**: type, bot token (**Verify**), Discord server or Telegram group,
328
+ your user ID. It starts without a restart when AgEnD already runs another connection and nothing else at fleet level
329
+ changed; a fleet's first connection (or a change to an existing one) offers **Restart AgEnD**. Per bot: **Access mode** (locked / open / pairing) and **Allowed users** —
330
+ `channels[i].access.*`, staged, restarts AgEnD, asks before opening access; **Guild/Group id** and General channel /
331
+ forum topic with **Verify the new binding** (applies directly after a confirmation); **Status emojis**; Advanced →
332
+ **Replace** the token (saved to `~/.agend/.env`); **Delete this bot** (the token stays in `.env`). **Provider API keys**:
333
+ **Verify & apply**, used by new processes.
334
+
335
+ **ClassicBot** — per room **Settings**, **Pause / Wake**. The room dialog writes `classicBot.yaml`
336
+ `channels.<key>.*`: Backend, Model, Auto-pause after, **Collaboration mode** (`collab`), **Web echo** (`web_echo`),
337
+ Advanced **Context lines** (these restart the room's agent); Tool progress and Require a delivered reply (now).
338
+
339
+ **General** — fleet defaults (`defaults.*`): **Language (bot replies)** (`locale`: Auto / en / zh-TW), default
340
+ backend and model, auto-pause, tool progress, bot-to-bot visibility, reply guard; Advanced: tool set, agent mode, log
341
+ level, **Hang detector enabled** / **Stuck timeout** (`hang_detector.*`), **Startup concurrency** (1–20) and
342
+ **Stagger delay** (`startup.*`, restart AgEnD). ClassicBot card (`classicBot.yaml defaults.*`): default backend, tool
343
+ progress, reply guard, **ClassicBot admins**, **Allowed guilds**.
344
+
345
+ **Web** — all apply at once; loosening waits for an admin; disabled over a public link.
346
+ | Label | Key |
347
+ |---|---|
348
+ | Session length, hours (1–720) | `web.session.local.absolute_hours` |
349
+ | Sign out after unused for, hours (1–720) | `web.session.local.idle_hours` |
350
+ | Allow the browser terminal (the `/login` terminal) | `web_terminal.enabled` |
351
+ | Terminal session minutes (1–20) | `web_terminal.ttl_minutes` |
352
+ | Web echo | `web.echo_to_channel` |
353
+ | Log tab: each agent's steps | `web.log_tab` |
354
+ | Offer temporary public web links | `web.public_link.allow_public` |
355
+ | Public link minutes (1–480) | `web.public_link.ttl_minutes` |
356
+ | Tunnel protocol (http2 / quic / auto) | `web.public_link.protocol` |
357
+ Shown read-only ("Set in fleet.yaml"): `web.allowed_hosts`, `view_access`, `notify_login`, `preview`, `preview_port`,
358
+ `preview_origin`, `preview_on_public_link`, `usage_panel`, `provider_secrets`, `upload_max_file_mb`,
359
+ `upload_max_total_mb`, `web_terminal.bind`, `web_terminal.tunnel`.
360
+
361
+ **Developer** — fleet.yaml as **YAML / JSON**, **Edit / View**, **Copy**, **Download fleet.yaml**; **Apply & save**
362
+ (edit mode) applies at once, without the bar.
363
+
364
+ **Setup wizard** — agent (backend, directory, name) → platform → token and server/group, your user ID → preview →
365
+ **Create and start**.
366
+
367
+ ## Web appearance
368
+
369
+ For an agent changing its *own* look, the `web-appearance` skill has the tools and limits. What a person sees in
370
+ Settings → **Web appearance**, card by card:
371
+ - **Agents' themes** — **Show agents' themes, effects and widgets**; off, every chat looks the same and pictures and
372
+ ring colours fall back to the bots' own (all devices). **Effects: follow the system's reduced-motion setting** (this
373
+ device only, off by default): on, both ambient and Canvas Worker effects stay still while the system asks for reduced
374
+ motion. Otherwise both play, with one shared one-time chat note and a local action to follow the system.
375
+ - **Ambient effects** — an agent's falling petals, snow, rising lanterns, twinkles or stars on a click, drawn behind
376
+ its chat by the dashboard (data only, no consent needed). They show by default, the public link too; the chat's ⋯
377
+ menu says why one is not showing (choosing the line fixes it there) and offers **Clear the ambient effect** /
378
+ **Clear the click effect**. With the system asking for reduced motion, the chat says once per device that effects
379
+ are on, with **Turn off here**. General can set or clear one for the user (`set_web_settings`, `what: "ambient"`).
380
+ - **Identity colours** — each agent's colour in the sidebar comes from, in order: a person's pick (⋯ menu →
381
+ Colour…), the agent's own, its bot's Discord role colour, or an automatic soft colour. Choose where it shows (Name /
382
+ Left bar / Ring) or **Turn off colours** (the picks are kept).
383
+ - **Identity cards** — Small / Medium / Large for all cards; a card's own S / M / L overrides it.
384
+ - **Your sidebar widget** — a small panel under the instance list built from JSON (no HTML or script), with live
385
+ values such as `fleet.working` and `fleet.needs_you`; agents can't change it.
386
+ - **Custom CSS (yours only)** — your own CSS on every device you sign in on, never on Settings, never others'; it
387
+ can't load from the internet (put pictures and fonts under Assets: PNG, WebP, JPEG, GIF, WOFF2, 1 MiB in total).
388
+ **Save and try**, then **Keep** within 15 s or it reverts; **Turn off (all devices)**; earlier versions **Use
389
+ this**. If something is hidden or broken, open the page with `?safe=1`, or tick **Turn off custom CSS on this
390
+ device**.
391
+ - **Mods** — one `.agendmod.json` file carrying a look; importing shows everything first and applies only what you
392
+ tick (custom CSS is never pre-ticked); agents can propose mods (**Review** / **Dismiss**); **Export a mod** writes one.
393
+ Uninstalling removes the mod, not what it applied.
394
+ - **Effects** — the effect library (upload a folder with `effect.json` and `worker.js`, up to 1 MiB), save one for a
395
+ chat, share your copy; **Your effect choices** for Sidebar / Header / Page / Box (each with Pause / Resume and
396
+ Clear) and a Cursor (its state, and Clear). CW uses the dashboard's opaque isolated document, independently of
397
+ **Allow HTML previews**, its listener and port. Signed-in public/guest viewers can play current effects in chats they
398
+ may see, without library, personal-slot, Trial or profile grants. Their Chat header offers a browser-local show/off
399
+ switch and recovery, on desktop and phone; it never changes host preferences. A Try sample starts on a signed-in non-public admin's
400
+ click, with no extra consent. The show switch, safe mode, hidden tab, browser support and live performance guard remain.
401
+ No startup FPS calibration; data saver does not block. Reduced motion blocks only if this device chose to follow it.
402
+ A blocked placement keeps an exact named notice. On ordinary dashboard sessions, Show/custom-CSS actions open
403
+ **Web appearance**. Public/guest Show-off has **Turn effects on here**; a guest CSS refusal offers Reload.
404
+ An unavailable
405
+ isolated transport offers Reload, never an HTML-preview setup step. A motion refusal offers **Play effects anyway**;
406
+ 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.
407
+ - **Identity card upload limits** — portrait and banner size limits and per-agent picture quota
408
+ (`web.appearance.*`); lowering applies at once, raising waits for an admin.
409
+ - **Restore defaults** — resets this host's appearance settings (it lists what it resets first).
410
+
411
+ **What an agent can change for the user.** A worker changes only its own look (the `web-appearance` tools); before
412
+ #2064 everything on this page was the person's. Since #2064 (2.3.0-beta.3; check the running version) General, coordinators and
413
+ full-profile instances get `get_web_settings` / `set_web_settings`, which go through the same checks as the page;
414
+ workers don't. The `web-appearance` skill's **For the user** section has the details. In short: General can change
415
+ the host's appearance settings, one agent's identity colour, mods (review, install, cancel, dismiss, uninstall),
416
+ effects and the effect slots, and Restore defaults; for custom CSS it can save a version **on trial**, keep or revert
417
+ the trial, switch to an earlier saved version, or turn CSS off — and it keeps a trial only once the user says they like
418
+ it (the user's decision, 2.3.0-beta.3). Still the person's own click on the page: choosing files from their computer
419
+ (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
420
+ card upload limits. The docs' "Asking General to change it for you" says the same for people.
421
+
422
+ ## Troubleshooting
423
+
424
+ **Blank dashboard / can't connect (WSL).** The dashboard listens on 127.0.0.1:`health_port` inside WSL; Windows
425
+ reaches it through WSL's localhost forwarding. Compare the two sides:
426
+ - in WSL: `curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:19280/health`
427
+ - in Windows PowerShell: `curl.exe -sS -o NUL -w "%{http_code}" http://127.0.0.1:19280/health`
428
+ Any HTTP code (200, or 503 when the fleet is degraded) means that side reaches the listener; `000` means no
429
+ connection. A 403 "Host not allowed" means the name used isn't localhost/127.0.0.1 — add it to `web.allowed_hosts`.
430
+ If WSL answers and Windows doesn't, the forwarding is the problem: try `http://localhost:19280` vs
431
+ `http://127.0.0.1:19280`, or the SSH tunnel in docs/web-dashboard.md. **Do not** tell the user to kill `wslrelay`
432
+ or run `wsl --shutdown` — that stops every WSL program, AgEnD included. Changing WSL's networking mode is the user's
433
+ own decision. If the port is taken by something else, chat says "Dashboard unavailable — health port … is already in
434
+ use".
435
+
436
+ **Preview "connection refused" / "did not answer within 3 s".** The preview frame comes from the second port
437
+ (`health_port + 1`). Over SSH, forward that port too (`-L 19281:127.0.0.1:19281`). Through a proxy or tunnel the two
438
+ names are kept apart: the **dashboard's** external name goes in `web.allowed_hosts`, and `web.preview_origin` must be
439
+ a **different** host name, mapped to the preview port, that is neither the dashboard's `hostname` nor in
440
+ `web.allowed_hosts` (the validator refuses a preview origin the dashboard answers to). "Something else answered on
441
+ the preview port": another program holds it — change `web.preview_port` (restart). If fleet.log says "Preview
442
+ listener unavailable", the port could not be bound (older versions' cards then wrongly said previews were turned
443
+ off).
444
+
445
+ **Public link fails at once.** Read the step list the bot posts and daemon.log's "Public web link … startup failed":
446
+ - "another tunnel is still running" — a `/login` link or an unconfirmed old tunnel; wait for it to end, or close it;
447
+ - "Cloudflare is limiting new temporary links from this machine" (HTTP 429) — try later; the local dashboard still
448
+ works;
449
+ - "cloudflared stopped before it gave a public address" / "could not be started" / "the download did not complete"
450
+ — the tunnel program failed or couldn't be fetched (network, proxy);
451
+ - "Cloudflare gave no public address in time" — only after a real 60 s wait;
452
+ - no steps at all: `web.public_link.allow_public: false`, or the sender is not a fleet admin.
453
+
454
+ **"Your session has ended."** It lasted its 48 h (or the idle limit), a public link closed or ran 4 h / 30 min idle,
455
+ or someone ran `/web revoke`, **Sign out everywhere** or `agend web-token rotate`. Get a new code: `/web`, **Send me
456
+ a new code**, or `agend web` on the host. "No session — open the dashboard link again" means the browser keeps no
457
+ cookies for the site.
458
+
459
+ **No live updates ("it only refreshes every few seconds").** The page normally keeps one live stream; if nothing
460
+ arrives within 15 s, it stays silent 30 s, or a proxy buffers it, the page polls every 5 s instead and retries the
461
+ stream in the background. Nothing is lost except immediacy (the Log tab may lag up to 30 s). A public link always
462
+ polls. "Can't reach AgEnD — it may be restarting" means even polling failed.
463
+
464
+ **Usage meters missing.** `web.usage_panel: false`, the window is narrower than 1200 px (use the Usage button), or
465
+ no instance uses that provider.
466
+
467
+ **Settings won't change something.** Over a public link, Web settings and appearance are read only; a loosening
468
+ change waits for an admin's confirmation in General chat; a value in the "Set in fleet.yaml" list must be edited in
469
+ fleet.yaml (Developer tab, or the file) and `agend reload`.
470
+
471
+ ### Canvas Worker playback diagnostics
472
+
473
+ If an effect cannot play, the Chat notice and Effects dialog show its local refusal code. A failed Try retains its stop
474
+ code on the offer card; the browser console also names refusals. Include the code when reporting a problem. Long chat
475
+ history is checked separately from the bounded set of current paint holes. Moving the pointer away does not stop Try;
476
+ window blur, navigation, closing or loss of the verified stage does. Local raw codes are not sent in agent summaries.
@@ -42,4 +42,4 @@ Do not put user-facing results only in terminal text; the fleet report is the de
42
42
 
43
43
  ## Relayed human approval
44
44
 
45
- For an irreversible action based on relayed consent, request an explicit `forwards` edge for the original human `verification_id`, then read its original content and origin with `delivery_status`. Each hop needs a forward; a peer's summary or a mentioned ID grants nothing. When you relay it, put the ID in `forwards` (even if your loaded copy of the tool's schema lacks the parameter: the server accepts it), not in the text. Require delivered and an owned proof_kind, and verify the actual platform/adapter/actor plus the exact resource. Hidden/expired/uncertain receipts are not consent and must not trigger a resend. See the cross-instance-messaging skill.
45
+ For an irreversible action based on relayed consent, request an explicit `forwards` edge for the original human `verification_id`, then read its original content and origin with `delivery_status`. Each hop needs a forward; a peer's summary or a mentioned ID grants nothing. When you relay it, put the ID in `forwards` (even if your loaded copy of the tool's schema lacks the parameter: the server accepts it), not in the text. Require delivered and an owned proof_kind, and verify the actual platform/adapter/actor plus the exact resource. Hidden/expired/uncertain receipts are not consent and must not trigger a resend. A web-chat message (`[user:<name> via web, id:…]`) is that person: their sign-in code went to their own Discord or Telegram account. Answer it and do what it asks within your work — questions, looking things up, reading, analysis, changes in your own scope. Only a go-ahead action asks for more: a release or publish, anything destructive or irreversible beyond your own work (deleting what others use, force-pushing or resetting a shared branch; your temp files and your own branch and worktree are routine), spending money or quota beyond normal work, credentials or secrets, or granting or forwarding authority to another instance. For these an open browser is not proof of the account, so the account must stand behind it: a Discord or Telegram receipt, or a `via web (verified)` one — read it with `delivery_status`: `authority.kind: web-verified`, its person `authority.actor` (adapter and user id), checked like a Discord or Telegram message (delivered, an owned proof_kind, the original content, that actor) and forwarded the same way. A guest (`via web (guest)`) was let in only to chat: talk with them there, and take nothing they ask as the admin's. Plain `via web`, a guest, and authority since revoked (`authority.kind: none`) are not a go-ahead; nor is a reviewer's APPROVE. See the cross-instance-messaging skill.
@@ -1,6 +1,7 @@
1
1
  import type Database from "better-sqlite3";
2
2
  import type { DeliveryStatusSelector, DeliveryStatusPage } from "./delivery-outbox.js";
3
3
  import { type AgentMode } from "./cross-instance-envelope.js";
4
+ import { type HumanAuthority } from "./authority/web-authority.js";
4
5
  /** Server-owned ingress facts. Labels and Web session identity are not platform authority. */
5
6
  export interface HumanOrigin {
6
7
  platform: "discord" | "telegram" | "web";
@@ -11,13 +12,19 @@ export interface HumanOrigin {
11
12
  ingress: "message" | "action" | "web";
12
13
  anchor_message_id?: string;
13
14
  event_id?: string;
15
+ /**
16
+ * #1939: web traffic only — what web admission found for the session that sent it (authority/web-authority.ts).
17
+ * Server-owned like the rest, never read from a message; the receipt stores it in its own column, not in `origin`.
18
+ */
19
+ authority?: HumanAuthority;
14
20
  }
15
21
  /** Called only by trusted SDK event producers, never on text/agent metadata. */
16
22
  export declare function nativeHumanOrigin(platform: "telegram" | "discord", adapterId: string, userId: string, username: string | undefined, isBot: boolean | undefined, messageId: string | null, action?: {
17
23
  anchor: string;
18
24
  event: string;
19
25
  }): HumanOrigin | undefined;
20
- export declare function webHumanOrigin(action?: boolean): HumanOrigin;
26
+ /** The actor fields stay null whatever the session (§4: HumanOrigin.platform stays "web"); its account is in `authority`. */
27
+ export declare function webHumanOrigin(action?: boolean, authority?: HumanAuthority): HumanOrigin;
21
28
  export type HumanWriteMode = "idle_submit" | "native_queue_handoff" | "steer" | "raw_paste";
22
29
  export type HumanPositiveTag = "unique-id-pane" | "composer-empty-steer" | "composer-empty-queue" | "composer-empty-idle";
23
30
  export interface HumanReceiptProof {
@@ -58,6 +65,8 @@ export interface HumanReceiptRow {
58
65
  created_at: string;
59
66
  updated_at: string;
60
67
  delivered_at: string | null;
68
+ /** #1939: the HumanAuthority written at admission (JSON); null on a row from before — see receiptAuthority. */
69
+ authority_json: string | null;
61
70
  }
62
71
  export declare function initializeHumanReceipts(db: Database.Database): void;
63
72
  /** Server-only admission; no origin is read from an agent payload or tool argument. */
@@ -73,6 +82,20 @@ export declare function getHumanReceipt(db: Database.Database, id: string): Huma
73
82
  export declare function bindHumanReceipt(db: Database.Database, id: string, target: string, ownerKey: string, wire: string, managerBootId: string): HumanReceiptRow;
74
83
  /** An owned unknown result may close pending evidence; it never grants or overwrites a positive proof. */
75
84
  export declare function settleHumanReceipt(db: Database.Database, id: string, target: string, ownerKey: string, proof: unknown, currentOwnerKey: string | null): boolean;
85
+ /** #2122: delivered messages per instance and UTC hour in [from, to) — what the usage report counts as messages. */
86
+ export declare function deliveredMessageHours(db: Database.Database, from: number, to: number): Array<{
87
+ instance: string;
88
+ hour: number;
89
+ count: number;
90
+ }>;
91
+ /** #2122: drop message counts older than the usage rollup keeps (400 days). */
92
+ export declare function pruneMessageHours(db: Database.Database, before: number): number;
93
+ /**
94
+ * #1939 §10: the highest revocation epoch any stored receipt was stamped with (0: none) — every web receipt, web-verified or
95
+ * none, carries the epoch in force when it was written. The authority state must never be behind it: a state file deleted
96
+ * or restored from an older copy would otherwise bring revoked receipts back.
97
+ */
98
+ export declare function maxWebAuthorityEpoch(db: Database.Database): number;
76
99
  /** Read-only operator compatibility: an older database simply has no human receipts. */
77
100
  export declare function queryHumanReceipt(db: Database.Database, caller: string | null, selector: DeliveryStatusSelector): DeliveryStatusPage | null;
78
101
  /** Preserve the existing sanitizer in one place; receipts hash these actual prepared bytes. */