@songsid/agend 2.3.3 → 2.3.4-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 (368) hide show
  1. package/README.md +3 -3
  2. package/README.zh-TW.md +3 -3
  3. package/THIRD_PARTY_NOTICES.md +37 -0
  4. package/dist/agend-home.d.ts +13 -0
  5. package/dist/agend-home.js +42 -0
  6. package/dist/agend-home.js.map +1 -1
  7. package/dist/agent-cli-instructions.md +2 -2
  8. package/dist/agent-credentials.d.ts +24 -0
  9. package/dist/agent-credentials.js +66 -0
  10. package/dist/agent-credentials.js.map +1 -0
  11. package/dist/agent-endpoint.d.ts +3 -1
  12. package/dist/agent-endpoint.js +13 -0
  13. package/dist/agent-endpoint.js.map +1 -1
  14. package/dist/auth-api.d.ts +16 -3
  15. package/dist/auth-api.js +32 -8
  16. package/dist/auth-api.js.map +1 -1
  17. package/dist/authority/session-authorizations.d.ts +28 -4
  18. package/dist/authority/session-authorizations.js +63 -17
  19. package/dist/authority/session-authorizations.js.map +1 -1
  20. package/dist/authority/web-authority.d.ts +15 -1
  21. package/dist/authority/web-authority.js +27 -10
  22. package/dist/authority/web-authority.js.map +1 -1
  23. package/dist/backend/antigravity.js +3 -1
  24. package/dist/backend/antigravity.js.map +1 -1
  25. package/dist/backend/claude-code.d.ts +3 -0
  26. package/dist/backend/claude-code.js +100 -5
  27. package/dist/backend/claude-code.js.map +1 -1
  28. package/dist/backend/codex-footer-hints.d.ts +4 -0
  29. package/dist/backend/codex-footer-hints.js +27 -0
  30. package/dist/backend/codex-footer-hints.js.map +1 -0
  31. package/dist/backend/codex-session-lookup.d.ts +35 -0
  32. package/dist/backend/codex-session-lookup.js +93 -0
  33. package/dist/backend/codex-session-lookup.js.map +1 -1
  34. package/dist/backend/codex.d.ts +27 -0
  35. package/dist/backend/codex.js +136 -23
  36. package/dist/backend/codex.js.map +1 -1
  37. package/dist/backend/kiro-identity.d.ts +2 -0
  38. package/dist/backend/kiro-identity.js +13 -6
  39. package/dist/backend/kiro-identity.js.map +1 -1
  40. package/dist/backend/kiro.d.ts +3 -0
  41. package/dist/backend/kiro.js +68 -5
  42. package/dist/backend/kiro.js.map +1 -1
  43. package/dist/backend/muse.js +5 -3
  44. package/dist/backend/muse.js.map +1 -1
  45. package/dist/backend/types.d.ts +13 -1
  46. package/dist/backend/types.js +3 -0
  47. package/dist/backend/types.js.map +1 -1
  48. package/dist/backend-availability.d.ts +6 -0
  49. package/dist/backend-availability.js +13 -5
  50. package/dist/backend-availability.js.map +1 -1
  51. package/dist/cache-ledger.d.ts +85 -0
  52. package/dist/cache-ledger.js +236 -1
  53. package/dist/cache-ledger.js.map +1 -1
  54. package/dist/cache-service.d.ts +5 -0
  55. package/dist/cache-service.js +16 -4
  56. package/dist/cache-service.js.map +1 -1
  57. package/dist/channel/adapters/discord.js +27 -4
  58. package/dist/channel/adapters/discord.js.map +1 -1
  59. package/dist/channel/adapters/telegram.d.ts +51 -0
  60. package/dist/channel/adapters/telegram.js +238 -18
  61. package/dist/channel/adapters/telegram.js.map +1 -1
  62. package/dist/channel/inbox-temp-name.d.ts +9 -0
  63. package/dist/channel/inbox-temp-name.js +13 -0
  64. package/dist/channel/inbox-temp-name.js.map +1 -0
  65. package/dist/channel/mcp-tools.js +3 -3
  66. package/dist/channel/mcp-tools.js.map +1 -1
  67. package/dist/channel/types.d.ts +2 -0
  68. package/dist/chat-log-ids.d.ts +48 -0
  69. package/dist/chat-log-ids.js +182 -0
  70. package/dist/chat-log-ids.js.map +1 -0
  71. package/dist/classic-channel-manager.d.ts +8 -1
  72. package/dist/classic-channel-manager.js +24 -2
  73. package/dist/classic-channel-manager.js.map +1 -1
  74. package/dist/cli.js +4 -6
  75. package/dist/cli.js.map +1 -1
  76. package/dist/config-validator.js +18 -1
  77. package/dist/config-validator.js.map +1 -1
  78. package/dist/cross-instance-notice.d.ts +10 -0
  79. package/dist/cross-instance-notice.js +67 -5
  80. package/dist/cross-instance-notice.js.map +1 -1
  81. package/dist/daemon.d.ts +52 -0
  82. package/dist/daemon.js +538 -35
  83. package/dist/daemon.js.map +1 -1
  84. package/dist/delivery-consumed-watch.d.ts +23 -1
  85. package/dist/delivery-consumed-watch.js +30 -3
  86. package/dist/delivery-consumed-watch.js.map +1 -1
  87. package/dist/delivery-reconciliation.d.ts +7 -0
  88. package/dist/delivery-reconciliation.js +9 -1
  89. package/dist/delivery-reconciliation.js.map +1 -1
  90. package/dist/dialog-screen-text.d.ts +16 -0
  91. package/dist/dialog-screen-text.js +51 -0
  92. package/dist/dialog-screen-text.js.map +1 -0
  93. package/dist/env-file.d.ts +2 -0
  94. package/dist/env-file.js +13 -8
  95. package/dist/env-file.js.map +1 -1
  96. package/dist/export-import.d.ts +7 -0
  97. package/dist/export-import.js +44 -10
  98. package/dist/export-import.js.map +1 -1
  99. package/dist/fleet-context.d.ts +2 -0
  100. package/dist/fleet-manager.d.ts +172 -12
  101. package/dist/fleet-manager.js +897 -139
  102. package/dist/fleet-manager.js.map +1 -1
  103. package/dist/fleet-yaml-patch.d.ts +3 -0
  104. package/dist/fleet-yaml-patch.js +103 -0
  105. package/dist/fleet-yaml-patch.js.map +1 -0
  106. package/dist/general-knowledge/skills/concepts/SKILL.md +393 -0
  107. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +2 -1
  108. package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +3 -1
  109. package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +41 -4
  110. package/dist/general-knowledge/skills/model-discovery/SKILL.md +2 -0
  111. package/dist/general-knowledge/skills/web-appearance/SKILL.md +1 -1
  112. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +14 -4
  113. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
  114. package/dist/install-stream.d.ts +53 -0
  115. package/dist/install-stream.js +134 -0
  116. package/dist/install-stream.js.map +1 -0
  117. package/dist/instance-config-impact.js +1 -0
  118. package/dist/instance-config-impact.js.map +1 -1
  119. package/dist/instance-lifecycle.d.ts +22 -2
  120. package/dist/instance-lifecycle.js +103 -19
  121. package/dist/instance-lifecycle.js.map +1 -1
  122. package/dist/instance-topic-delete.d.ts +77 -0
  123. package/dist/instance-topic-delete.js +123 -0
  124. package/dist/instance-topic-delete.js.map +1 -0
  125. package/dist/instructions.d.ts +2 -2
  126. package/dist/instructions.js +2 -2
  127. package/dist/instructions.js.map +1 -1
  128. package/dist/interaction-observation.d.ts +1 -0
  129. package/dist/interaction-observation.js +1 -1
  130. package/dist/interaction-observation.js.map +1 -1
  131. package/dist/kiro-engine-status.d.ts +11 -0
  132. package/dist/kiro-engine-status.js +6 -0
  133. package/dist/kiro-engine-status.js.map +1 -1
  134. package/dist/kiro-resume-summary.d.ts +37 -0
  135. package/dist/kiro-resume-summary.js +85 -0
  136. package/dist/kiro-resume-summary.js.map +1 -0
  137. package/dist/locale.js +130 -6
  138. package/dist/locale.js.map +1 -1
  139. package/dist/log-service.d.ts +30 -0
  140. package/dist/log-service.js +36 -3
  141. package/dist/log-service.js.map +1 -1
  142. package/dist/log-steps.d.ts +4 -3
  143. package/dist/log-steps.js +32 -7
  144. package/dist/log-steps.js.map +1 -1
  145. package/dist/logger.d.ts +12 -0
  146. package/dist/logger.js +43 -1
  147. package/dist/logger.js.map +1 -1
  148. package/dist/login-controller.js +9 -1
  149. package/dist/login-controller.js.map +1 -1
  150. package/dist/login-flows.d.ts +2 -0
  151. package/dist/login-flows.js +5 -2
  152. package/dist/login-flows.js.map +1 -1
  153. package/dist/login-manager.d.ts +6 -0
  154. package/dist/login-manager.js +10 -1
  155. package/dist/login-manager.js.map +1 -1
  156. package/dist/missed-offline.d.ts +25 -0
  157. package/dist/missed-offline.js +79 -0
  158. package/dist/missed-offline.js.map +1 -0
  159. package/dist/needs-you-hub.d.ts +6 -1
  160. package/dist/needs-you-hub.js +31 -8
  161. package/dist/needs-you-hub.js.map +1 -1
  162. package/dist/needs-you.d.ts +22 -2
  163. package/dist/needs-you.js +17 -3
  164. package/dist/needs-you.js.map +1 -1
  165. package/dist/next-steps.d.ts +12 -2
  166. package/dist/next-steps.js +19 -3
  167. package/dist/next-steps.js.map +1 -1
  168. package/dist/office-share-page.d.ts +1 -1
  169. package/dist/office-share-page.js +6 -2
  170. package/dist/office-share-page.js.map +1 -1
  171. package/dist/office-share-service.d.ts +57 -0
  172. package/dist/office-share-service.js +76 -11
  173. package/dist/office-share-service.js.map +1 -1
  174. package/dist/office-share.d.ts +8 -0
  175. package/dist/office-share.js +34 -0
  176. package/dist/office-share.js.map +1 -1
  177. package/dist/outbound-handlers.js +59 -3
  178. package/dist/outbound-handlers.js.map +1 -1
  179. package/dist/outbound-schemas.d.ts +1 -0
  180. package/dist/outbound-schemas.js +10 -4
  181. package/dist/outbound-schemas.js.map +1 -1
  182. package/dist/package-preimage.js +27 -2
  183. package/dist/package-preimage.js.map +1 -1
  184. package/dist/page-share.d.ts +122 -0
  185. package/dist/page-share.js +199 -0
  186. package/dist/page-share.js.map +1 -0
  187. package/dist/public-preview.d.ts +4 -0
  188. package/dist/public-preview.js +5 -4
  189. package/dist/public-preview.js.map +1 -1
  190. package/dist/public-web-gateway.js +5 -0
  191. package/dist/public-web-gateway.js.map +1 -1
  192. package/dist/queued-handoffs.d.ts +33 -0
  193. package/dist/queued-handoffs.js +75 -0
  194. package/dist/queued-handoffs.js.map +1 -0
  195. package/dist/quickstart-api.d.ts +5 -0
  196. package/dist/quickstart-api.js +1 -1
  197. package/dist/quickstart-api.js.map +1 -1
  198. package/dist/quickstart.d.ts +40 -0
  199. package/dist/quickstart.js +174 -28
  200. package/dist/quickstart.js.map +1 -1
  201. package/dist/remote-card-answer.js +2 -0
  202. package/dist/remote-card-answer.js.map +1 -1
  203. package/dist/remote-card-prompt.js +4 -2
  204. package/dist/remote-card-prompt.js.map +1 -1
  205. package/dist/reply-buttons-controller.js +10 -0
  206. package/dist/reply-buttons-controller.js.map +1 -1
  207. package/dist/scheduler/db.d.ts +2 -1
  208. package/dist/scheduler/db.js +23 -9
  209. package/dist/scheduler/db.js.map +1 -1
  210. package/dist/selection-card.d.ts +20 -0
  211. package/dist/selection-card.js +202 -0
  212. package/dist/selection-card.js.map +1 -0
  213. package/dist/settings-api.d.ts +13 -0
  214. package/dist/settings-api.js +16 -1
  215. package/dist/settings-api.js.map +1 -1
  216. package/dist/settings-change.js +5 -0
  217. package/dist/settings-change.js.map +1 -1
  218. package/dist/settings-effect.js +2 -0
  219. package/dist/settings-effect.js.map +1 -1
  220. package/dist/setup-host.js +2 -2
  221. package/dist/setup-host.js.map +1 -1
  222. package/dist/setup-wizard.js +2 -2
  223. package/dist/setup-wizard.js.map +1 -1
  224. package/dist/stall-reporter.d.ts +21 -0
  225. package/dist/stall-reporter.js +82 -0
  226. package/dist/stall-reporter.js.map +1 -0
  227. package/dist/tmux-control.d.ts +2 -2
  228. package/dist/tmux-control.js +4 -2
  229. package/dist/tmux-control.js.map +1 -1
  230. package/dist/tmux-exec-helper.d.ts +6 -3
  231. package/dist/tmux-exec-helper.js +115 -53
  232. package/dist/tmux-exec-helper.js.map +1 -1
  233. package/dist/tmux-manager.d.ts +6 -0
  234. package/dist/tmux-manager.js +17 -0
  235. package/dist/tmux-manager.js.map +1 -1
  236. package/dist/tool-permissions.d.ts +5 -2
  237. package/dist/tool-permissions.js +6 -5
  238. package/dist/tool-permissions.js.map +1 -1
  239. package/dist/tool-progress.d.ts +2 -0
  240. package/dist/tool-progress.js +19 -3
  241. package/dist/tool-progress.js.map +1 -1
  242. package/dist/topic-commands.js +4 -0
  243. package/dist/topic-commands.js.map +1 -1
  244. package/dist/tunnel/cloudflared-install.d.ts +4 -0
  245. package/dist/tunnel/cloudflared-install.js +20 -1
  246. package/dist/tunnel/cloudflared-install.js.map +1 -1
  247. package/dist/tunnel/cloudflared.d.ts +8 -1
  248. package/dist/tunnel/cloudflared.js +34 -6
  249. package/dist/tunnel/cloudflared.js.map +1 -1
  250. package/dist/tunnel/lease.d.ts +3 -3
  251. package/dist/tunnel/lease.js +23 -19
  252. package/dist/tunnel/lease.js.map +1 -1
  253. package/dist/tunnel/manager.js +6 -7
  254. package/dist/tunnel/manager.js.map +1 -1
  255. package/dist/types.d.ts +10 -0
  256. package/dist/ui/chat-store.js +28 -4
  257. package/dist/ui/chat-strings.js +40 -4
  258. package/dist/ui/chat-thread.js +52 -10
  259. package/dist/ui/fleet-canvas.js +4 -3
  260. package/dist/ui/fleet-office-model.js +55 -22
  261. package/dist/ui/fleet-office-overview.js +6 -38
  262. package/dist/ui/fleet-office-pack.js +4 -3
  263. package/dist/ui/fleet-office-skin.js +114 -21
  264. package/dist/ui/fleet-office-store.js +5 -0
  265. package/dist/ui/fleet-office-zones.js +2 -2
  266. package/dist/ui/fleet-office.js +41 -9
  267. package/dist/ui/fleet-usage.js +90 -27
  268. package/dist/ui/page-share-dialog.js +191 -0
  269. package/dist/ui/panel-chat.js +16 -0
  270. package/dist/ui/panel-log.js +7 -1
  271. package/dist/ui/panel-needs.js +17 -8
  272. package/dist/ui/panel-notices.js +98 -0
  273. package/dist/ui/panel-settings.js +9 -2
  274. package/dist/ui/preview-pages.js +41 -0
  275. package/dist/ui/preview-panel-actions.js +161 -0
  276. package/dist/ui/preview-panel.js +209 -28
  277. package/dist/ui/preview-versions.js +155 -0
  278. package/dist/ui/preview.js +88 -3
  279. package/dist/ui/settings-registry.js +1 -0
  280. package/dist/ui/settings-strings.js +6 -2
  281. package/dist/ui/shared/app-i18n.js +6 -6
  282. package/dist/ui/shared/app-needs.js +1 -1
  283. package/dist/ui/shared/app-route.js +4 -0
  284. package/dist/ui/shared/app-shell.js +9 -5
  285. package/dist/ui/shared/app-store.js +71 -1
  286. package/dist/ui/shared/app-stream.js +27 -1
  287. package/dist/ui/shared/app.css +94 -4
  288. package/dist/ui/shared/app.js +22 -1
  289. package/dist/ui/shared/office/guild.png +0 -0
  290. package/dist/ui/shared/office/school.png +0 -0
  291. package/dist/ui/shared/panel-view.js +339 -17
  292. package/dist/ui/shared/signin.js +12 -1
  293. package/dist/ui/shared/ui-icons.js +3 -0
  294. package/dist/ui/shared/usage-dialog.js +18 -1
  295. package/dist/ui/shared/view-history.css +17 -0
  296. package/dist/ui/shared/view-history.js +438 -0
  297. package/dist/ui/shared/view-strings.js +42 -0
  298. package/dist/ui/shared/web-authorize.js +3 -1
  299. package/dist/unattended-install.d.ts +6 -0
  300. package/dist/unattended-install.js +79 -0
  301. package/dist/unattended-install.js.map +1 -0
  302. package/dist/usage/capacity.d.ts +69 -0
  303. package/dist/usage/capacity.js +119 -0
  304. package/dist/usage/capacity.js.map +1 -0
  305. package/dist/usage/i18n-keys.d.ts +1 -1
  306. package/dist/usage/i18n-keys.js +3 -0
  307. package/dist/usage/i18n-keys.js.map +1 -1
  308. package/dist/usage/profile-timeline.d.ts +16 -0
  309. package/dist/usage/profile-timeline.js +58 -0
  310. package/dist/usage/profile-timeline.js.map +1 -0
  311. package/dist/usage/quota-history.d.ts +43 -0
  312. package/dist/usage/quota-history.js +168 -0
  313. package/dist/usage/quota-history.js.map +1 -0
  314. package/dist/usage/usage-api.d.ts +31 -0
  315. package/dist/usage/usage-api.js +80 -1
  316. package/dist/usage/usage-api.js.map +1 -1
  317. package/dist/usage-report.d.ts +25 -1
  318. package/dist/usage-report.js +55 -4
  319. package/dist/usage-report.js.map +1 -1
  320. package/dist/usage-rollup.d.ts +4 -1
  321. package/dist/usage-rollup.js +12 -3
  322. package/dist/usage-rollup.js.map +1 -1
  323. package/dist/view-api.d.ts +31 -0
  324. package/dist/view-api.js +186 -41
  325. package/dist/view-api.js.map +1 -1
  326. package/dist/view-history.d.ts +84 -0
  327. package/dist/view-history.js +116 -0
  328. package/dist/view-history.js.map +1 -0
  329. package/dist/web-api.d.ts +32 -0
  330. package/dist/web-api.js +195 -5
  331. package/dist/web-api.js.map +1 -1
  332. package/dist/web-auth.js +7 -1
  333. package/dist/web-auth.js.map +1 -1
  334. package/dist/web-chat-history.d.ts +20 -0
  335. package/dist/web-chat-history.js +21 -0
  336. package/dist/web-chat-history.js.map +1 -1
  337. package/dist/web-guest-access.js +5 -1
  338. package/dist/web-guest-access.js.map +1 -1
  339. package/dist/web-login.d.ts +6 -3
  340. package/dist/web-login.js +26 -15
  341. package/dist/web-login.js.map +1 -1
  342. package/dist/web-notices.d.ts +51 -0
  343. package/dist/web-notices.js +118 -0
  344. package/dist/web-notices.js.map +1 -0
  345. package/dist/web-office-pack-tools.d.ts +1 -1
  346. package/dist/web-office-pack-tools.js +1 -1
  347. package/dist/web-office-pack-tools.js.map +1 -1
  348. package/dist/web-only-fleet.d.ts +22 -0
  349. package/dist/web-only-fleet.js +13 -0
  350. package/dist/web-only-fleet.js.map +1 -0
  351. package/dist/web-preview.d.ts +32 -3
  352. package/dist/web-preview.js +52 -19
  353. package/dist/web-preview.js.map +1 -1
  354. package/dist/web-session-authorization.d.ts +13 -2
  355. package/dist/web-session-authorization.js +10 -3
  356. package/dist/web-session-authorization.js.map +1 -1
  357. package/dist/web-session.d.ts +12 -0
  358. package/dist/web-session.js +22 -8
  359. package/dist/web-session.js.map +1 -1
  360. package/dist/web-settings-patch.d.ts +3 -1
  361. package/dist/web-settings-patch.js +4 -1
  362. package/dist/web-settings-patch.js.map +1 -1
  363. package/dist/web-shell-routes.d.ts +2 -0
  364. package/dist/web-shell-routes.js +3 -0
  365. package/dist/web-shell-routes.js.map +1 -1
  366. package/launcher/agend-install.cjs +16 -2
  367. package/launcher/private-home.cjs +1 -1
  368. package/package.json +1 -1
@@ -27,6 +27,9 @@
27
27
  // - every reconnect catches up once the new stream speaks (catchUp(), with the page's cursor — #1566/#1578), so what
28
28
  // was said meanwhile is shown, once.
29
29
  // - a 401 is the session ending: nothing is retried (agend-auth.js says so).
30
+ // - M-2260: a catch-up after a long absence carries only the newest messages (the server's budget) and says so
31
+ // (`truncated`): "gap" tells the chats to read their newest history again — it converges like a reload, never by
32
+ // asking a slow link for hours of replies in one answer.
30
33
  // - suspend()/resume(): the page is leaving (pagehide) / came back from the back-forward cache.
31
34
 
32
35
  // #1218: steps_tick — an instance's transcript moved while a Log watches it (SSE only: a poll page asks the Log itself).
@@ -37,7 +40,7 @@
37
40
  // offices — the stored offices changed ({ rev }; SSE only: the Office view reads /ui/offices again).
38
41
  // office_skins — a skin pack was uploaded or deleted ({ rev }; SSE only: the Office view reads /ui/office-skins again).
39
42
  // office_acts — the agents' live acts in the Office view changed ({ acts }, #2578; a poll page reads /ui/office-acts).
40
- const EVENTS = ["status", "message", "agent_reply_live", "delivery", "deliveries", "prompt", "prompts", "prompt_resolved", "activity", "needs", "reply_buttons", "reactions", "steps_tick", "clock", "traffic", "delegation", "backend_login", "tasks", "offices", "office_skins", "office_acts", "office_pack_changes"];
43
+ const EVENTS = ["status", "message", "agent_reply_live", "delivery", "deliveries", "prompt", "prompts", "prompt_resolved", "activity", "needs", "reply_buttons", "reactions", "steps_tick", "clock", "traffic", "delegation", "backend_login", "tasks", "offices", "office_skins", "office_acts", "office_pack_changes", "notice"];
41
44
  const MAX_HELD = 1000; // live events held during one catch-up read; more → read again afterwards
42
45
  const RETRY_DELAYS = [1000, 2000, 4000]; // after the first failed catch-up read; then it waits for Retry
43
46
  const POLL_LIMIT_MS = 10000; // a poll that has not answered by then counts as failed
@@ -79,6 +82,22 @@ export function createStream(opts) {
79
82
  try { return Object.freeze({ source: "sse", receivedAt: now() }); } catch { return undefined; }
80
83
  }
81
84
  function setConnection(c) { if (state.connection !== c) { state.connection = c; emit("connection", c); } }
85
+
86
+ // M-2260: a tab the browser froze for hours gets every heartbeat it missed at once when it wakes — thousands of status
87
+ // frames, each a whole snapshot, each redrawing the page (seconds of work before the newest message shows). A status
88
+ // that comes after a quiet moment is delivered at once, as before; more statuses before the next turn of the page's
89
+ // task loop replace the waiting one, delivered then — or before any other event, so the order of events never changes.
90
+ // The next turn is a 0 ms timer: in a hidden tab the browser may run it late (a minute when throttled) — a status
91
+ // then waits that long while nobody looks (Needs you, the title's count and notifications ride `needs`, never held).
92
+ let pendingStatus = null, statusBurst = false;
93
+ const turn = () => env.setTimeout(endBurst, 0);
94
+ function endBurst() { statusBurst = false; flushStatus(); }
95
+ function flushStatus() { const d = pendingStatus; pendingStatus = null; if (d !== null) live("status", d, null); }
96
+ function liveStatus(data) {
97
+ if (statusBurst) { pendingStatus = data; return; }
98
+ statusBurst = true; turn();
99
+ live("status", data, null);
100
+ }
82
101
  function setHydration(h) { if (state.hydration !== h) { state.hydration = h; emit("hydration", h); } }
83
102
 
84
103
  /** A live event: delivered now, or held (in order) while a catch-up snapshot is on its way. */
@@ -115,6 +134,7 @@ export function createStream(opts) {
115
134
  if (polling) { if (!opts.join) pollAgain = true; return polling; }
116
135
  const mine = ++pollSeq, ep = readEpoch;
117
136
  let status = 0; // this read's HTTP status — its own, never another read's
137
+ flushStatus(); // a status that came before this read is older than its snapshot
118
138
  if (sse && !held) held = [];
119
139
  let limit = null;
120
140
  const read = (async () => {
@@ -128,6 +148,9 @@ export function createStream(opts) {
128
148
  if (d.status) emit("status", d.status);
129
149
  for (const m of d.messages || []) emit("message", m, { source: "poll" });
130
150
  if (typeof d.cursor === "string") state.cursor = d.cursor;
151
+ // M-2260: the server sent only the newest messages of a long absence (its catch-up budget): the chats read their
152
+ // newest history again, as a reload would, instead of this read carrying everything that was missed.
153
+ if (d.truncated === true) emit("gap", {});
131
154
  if (Array.isArray(d.deliveries)) emit("deliveries", d.deliveries);
132
155
  if (Array.isArray(d.prompts)) emit("prompts", d.prompts);
133
156
  if (Array.isArray(d.reply_buttons)) for (const u of d.reply_buttons) emit("reply_buttons", u); // #1266
@@ -157,6 +180,7 @@ export function createStream(opts) {
157
180
  }
158
181
  /** #1580 review: the page lets go of everything in flight — reads, the queued poll, the catch-up and its retry wait. */
159
182
  function cancelWork() {
183
+ pendingStatus = null; // a page let go of (suspend, end, close) draws no waiting status
160
184
  readEpoch++; epoch++;
161
185
  pollSeq++; polling = null; pollAgain = false; held = null;
162
186
  env.clearTimeout(retryTimer); retryTimer = null;
@@ -225,6 +249,8 @@ export function createStream(opts) {
225
249
  else alive();
226
250
  // #1823: a clock reading is about now, not about order: it is never held behind a catch-up (it would be stale).
227
251
  if (name === "clock") { emit(name, data); return; }
252
+ if (name === "status") { liveStatus(data); return; }
253
+ flushStatus(); // a status waiting goes first: the order never changes
228
254
  live(name, data, name === "message" ? e.lastEventId : null, ingress);
229
255
  });
230
256
  }
@@ -623,9 +623,21 @@ html:has(.shell), html:has(.shell) body { overflow: hidden; }
623
623
  Its class is `status-line`, never `status`: that is the header's inline-flex badge class, and on a message it turned
624
624
  the meta, body and tools into one flex row. */
625
625
  .msg.status-line { align-self: stretch; font-size: var(--fs-sm); color: var(--text-3); }
626
- .msg.status-line .st-text { white-space: pre-wrap; border-left: 2px solid var(--border); padding-left: var(--s-3); }
627
- .msg.status-line.folded .st-text { max-height: 9em; overflow: hidden; mask-image: linear-gradient(to bottom, #000 60%, transparent); -webkit-mask-image: linear-gradient(to bottom, #000 60%, transparent); }
626
+ /* Each line is a row (.st-ln); the line breaks between rows are text for copying, not extra rows. */
627
+ .msg.status-line .st-text { border-left: 2px solid var(--border); padding-left: var(--s-3); }
628
+ .msg.status-line .st-ln { display: block; white-space: pre-wrap; overflow-wrap: anywhere; }
629
+ .msg.status-line .st-ln:empty::after { content: " "; }
630
+ /* Folded (the user, hmsg-d6ac6dfb): two lines — the header and the first line — each one row with an ellipsis; the
631
+ button sits at the end of line 2. The text opens it too. */
632
+ .msg.status-line.folded .body { display: flex; align-items: flex-end; gap: var(--s-2); }
633
+ .msg.status-line.folded .st-text { flex: 1 1 auto; min-width: 0; }
634
+ .msg.status-line.folded.overflows .st-text { cursor: pointer; }
635
+ /* Its control only while something is hidden (two short rows that fit: plain, no control). */
636
+ .msg.status-line.folded:not(.overflows) .st-more { display: none; }
637
+ .msg.status-line.folded .st-ln { white-space: pre; overflow: hidden; text-overflow: ellipsis; }
638
+ .msg.status-line.folded .st-ln:nth-child(n+3) { display: none; }
628
639
  .msg.status-line .st-more { border: 0; background: none; color: var(--text-2); cursor: pointer; font-size: var(--fs-xs); padding: var(--s-1) 0 0 var(--s-3); }
640
+ .msg.status-line.folded .st-more { flex: none; padding: 0 var(--s-2) 0 0; white-space: nowrap; }
629
641
  .msg.status-line .st-more:hover { color: var(--text); }
630
642
  .msg-tools { display: flex; gap: var(--s-1); margin-top: var(--s-1); opacity: 0; transition: opacity var(--t-fast); }
631
643
  /* #2147: bounded stock toolbar paint, including fixed descendants. Padding preserves focus outlines. */
@@ -807,6 +819,39 @@ img.amb-p { object-fit: contain; }
807
819
  .preview-frame.fill { flex: 1; height: 100%; min-height: 0; }
808
820
  .pv-code { flex: 1; min-height: 0; margin: 0; overflow: auto; font-family: var(--font-mono); font-size: var(--fs-xs); line-height: 1.5;
809
821
  background: var(--surface); border-radius: var(--r-sm); padding: var(--s-3); white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text); }
822
+ /* preview panel chrome (M-2216) — #2911: the version step and the Changes view. */
823
+ .pv-ver { display: inline-flex; align-items: center; gap: var(--s-1); font-size: var(--fs-xs); color: var(--text-2); }
824
+ .pv-ver-at { min-width: 6ch; text-align: center; font-variant-numeric: tabular-nums; }
825
+ .pv-panel > .pv-ver-note { margin: 0 var(--s-3) var(--s-2); }
826
+ .pv-diff-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: var(--s-2); }
827
+ .pv-diff-head { font-size: var(--fs-xs); color: var(--text-2); }
828
+ .pv-diff { white-space: pre; overflow-wrap: normal; }
829
+ .pv-diff > code > span { display: block; }
830
+ .pv-diff .d-add { background: var(--ok-bg); color: var(--ok); }
831
+ .pv-diff .d-del { background: var(--danger-bg); color: var(--danger); }
832
+ .pv-diff .d-hunk { color: var(--text-3); }
833
+ .pv-diff-note { margin: 0; }
834
+ /* #2911 (2): the page at a phone's or a tablet's width, centred; a panel narrower than that scrolls sideways. */
835
+ .pv-panel-body.w-phone, .pv-panel-body.w-tablet { overflow-x: auto; }
836
+ /* The frame keeps its 2px warning border (.preview-frame): the holder is that much wider, so the page itself lays out
837
+ at exactly 390 / 768 CSS px (its innerWidth, its min-width media queries) — #2918 review. */
838
+ .pv-panel-body.w-phone .pv-holder { flex: 1 0 auto; width: calc(390px + 2 * 2px); max-width: none; margin-inline: auto; }
839
+ .pv-panel-body.w-tablet .pv-holder { flex: 1 0 auto; width: calc(768px + 2 * 2px); max-width: none; margin-inline: auto; }
840
+ .pv-width { font: inherit; font-size: var(--fs-xs); padding: 2px var(--s-1); border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--bg); color: var(--text); }
841
+ /* Full screen: the API's (:fullscreen), or the panel over the whole window where the page may not use it. */
842
+ /* Three classes, so it wins over the desktop split's ".chat-split > .pv-panel { position: relative; z-index: 1 }" — #2918 review. */
843
+ .pv-panel.pv-fs.pv-fs-native, .pv-panel.pv-fs.pv-fs-immersive { width: auto; min-width: 0; max-width: none; }
844
+ .chat-split > .pv-panel.pv-fs-immersive, .pv-panel.pv-fs.pv-fs-immersive { position: fixed; inset: 0; z-index: 60; }
845
+ /* #2911 (6): the thread's pages. */
846
+ .pv-pages { list-style: none; margin: 0; padding: 0; overflow: auto; display: flex; flex-direction: column; gap: var(--s-1); }
847
+ .pv-page { width: 100%; display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2) var(--s-3); border: 1px solid var(--border);
848
+ border-radius: var(--r-sm); background: var(--surface); color: var(--text); font: inherit; font-size: var(--fs-sm); text-align: left; cursor: pointer; }
849
+ .pv-page.on { border-color: var(--accent); }
850
+ .pv-page-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
851
+ .pv-page-meta { flex: none; color: var(--text-3); font-size: var(--fs-xs); }
852
+ .pv-pages-toggle { flex: none; }
853
+ /* A narrow panel: two rows — versions and views; then the width, the run controls, the page's actions and Download. */
854
+ @container (max-width: 560px) { .pv-panel-bar .grow { flex-basis: 100%; height: 0; } }
810
855
  .msg.flash { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: var(--r-sm); transition: outline-color var(--t-med); }
811
856
  /* #2272: a message's reply action (top right, on hover or focus), the quote a reply shows, the message menu, a swipe. */
812
857
  .msg[data-key] { position: relative; }
@@ -837,6 +882,10 @@ img.amb-p { object-fit: contain; }
837
882
  @container (max-width: 560px) {
838
883
  .pv-panel-bar :not(.pv-panel-run) > .lbl { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
839
884
  }
885
+ /* preview feedback (M-2217, #2911): the errors chip — its count stays when a narrow bar hides the word. */
886
+ .pv-fb-errors { color: var(--warn); border-color: var(--warn-line); background: var(--warn-bg); }
887
+ .pv-fb-pick.on { color: var(--warn); border-color: var(--warn); }
888
+ .pv-fb-errors .pv-fb-n { font-variant-numeric: tabular-nums; font-weight: var(--fw-semibold); }
840
889
  /* #1266: an agent reply's buttons — choices under the text; one answers for everyone. */
841
890
  .rb-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); margin-top: var(--s-2); }
842
891
  .rb-btn { max-width: 100%; white-space: normal; text-align: left; }
@@ -1286,6 +1335,21 @@ body.side-resizing, body.side-resizing * { cursor: col-resize !important; user-s
1286
1335
  /* #1844 Fleet overview → Docs: the arrow says "opens a new tab". */
1287
1336
  .hd-docs .hd-ext { color: var(--text-3); }
1288
1337
  .v-term { flex: 1; min-height: 0; overflow: auto; scrollbar-gutter: stable; padding: 5px 6px; background: #000000; position: relative; }
1338
+ /* M-2262: the terminal's box — the scrolling terminal, and its scrollback controls over it (they never scroll with it). */
1339
+ /* --v-term-rev: the View's mark (panel-view.js VIEW_REV): a tab still on an older stylesheet reads this one again. */
1340
+ .v-term-box { --v-term-rev: 2; flex: 1; min-height: 0; display: flex; flex-direction: column; position: relative; }
1341
+ .v-term:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
1342
+ .v-term-earlier, .v-term-latest { position: absolute; right: var(--s-4); z-index: 2; display: inline-flex; align-items: center; gap: 4px; opacity: .88; }
1343
+ .v-term-earlier { top: var(--s-2); }
1344
+ .v-term-latest { bottom: var(--s-3); opacity: 1; }
1345
+ .v-term-logbar { flex-shrink: 0; margin: 0; padding: var(--s-2) var(--s-4); background: #111111; border-bottom: 1px solid #2a2a2a; text-align: right; font-size: var(--fs-sm); }
1346
+ .v-term-logbar a { display: inline-flex; align-items: center; gap: 4px; color: #9cc8ff; text-decoration: underline; text-underline-offset: 2px; min-height: 28px; }
1347
+ @media (pointer: coarse) { .v-term-logbar a { min-height: 44px; } }
1348
+ .v-term-latest.has-new { background: var(--accent-fill); border-color: transparent; color: var(--on-accent); }
1349
+ .v-term-earlier:hover, .v-term-earlier:focus-visible { opacity: 1; }
1350
+ .v-term-history-note { position: absolute; left: var(--s-3); right: var(--s-3); bottom: var(--s-3); z-index: 2; margin: 0; padding: var(--s-1) var(--s-3); border-radius: var(--r-sm); background: rgba(20, 20, 20, .92); border: 1px solid #3a3a3a; color: #e0e0e0; font-size: var(--fs-sm); }
1351
+ @media (max-width: 600px) { .v-term-history-note { left: var(--s-4); right: var(--s-4); } }
1352
+ @media (pointer: coarse) { .v-term-earlier, .v-term-latest { min-height: 44px; padding-left: var(--s-3); padding-right: var(--s-3); } }
1289
1353
  .v-pre { margin: 0; min-width: 100%; min-height: 100%; font-family: var(--font-mono); line-height: 1.2; white-space: pre; color: #d0d0d0; }
1290
1354
  .v-pre .ansi[data-b] { font-weight: var(--fw-bold); }
1291
1355
  /* #1582: faint text (SGR 2) — a CLI's suggestion or placeholder, never input — stays faint here. */
@@ -1328,6 +1392,11 @@ body.side-resizing, body.side-resizing * { cursor: col-resize !important; user-s
1328
1392
  .u-stale { font-weight: var(--fw-semibold); }
1329
1393
  .u-stale-detail { color: var(--text-3); font-size: var(--fs-xs); }
1330
1394
  .u-sub { color: var(--text-3); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
1395
+ /* #3066 §1: a weekly quota's measured 100% under its bar, and its notes (the fleet-only limit always). */
1396
+ .u-cap { margin-top: 4px; font-size: var(--fs-xs); }
1397
+ .u-cap-line { color: var(--text-2); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1398
+ .u-cap-wait .u-cap-line { color: var(--text-3); }
1399
+ .u-cap-note { color: var(--text-3); overflow-wrap: anywhere; }
1331
1400
  .u-err { color: var(--warn); font-size: var(--fs-sm); }
1332
1401
  .u-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
1333
1402
  /* #1673: the usage rail beside the page on a wide screen (header-tools.js UsageRail; shown only at min-width 1200px). */
@@ -1595,6 +1664,11 @@ textarea.s-yaml { white-space: pre; overflow-x: auto; }
1595
1664
  .n-detail { color: var(--text-2); font-size: var(--fs-sm); overflow-wrap: anywhere; white-space: pre-wrap; }
1596
1665
  .n-actions { display: flex; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-1); }
1597
1666
  .n-notify { display: flex; flex-direction: column; gap: var(--s-1); }
1667
+ /* #2910 D2: Notices (a web-only fleet's General) — the Needs you rows; a new one has an accent edge and a "New" tag. */
1668
+ .n-item.notice.unread { box-shadow: inset 3px 0 0 var(--accent); }
1669
+ .n-item.notice:not(.bad) .n-icon { color: var(--text-2); }
1670
+ .notice-new { font-size: var(--fs-xs); color: var(--accent); font-weight: var(--fw-semibold); }
1671
+ .notice-sub { margin: 0 var(--s-1) var(--s-3); }
1598
1672
  .confirm-text { white-space: pre-wrap; font-size: var(--fs-sm); color: var(--text-2); }
1599
1673
 
1600
1674
  /* ── Org chart (#1389): General → teams → instances. Connectors are borders and pseudo-elements; no inline style.
@@ -1818,6 +1892,12 @@ strong.org-name { font-size: var(--fs-sm); color: var(--text); }
1818
1892
  .oo-canvas:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
1819
1893
  .oo-canvas.hot { cursor: pointer; }
1820
1894
  /* The canvas controls, as the org chart canvas's (.oc-zoom, .oc-mini): over the stage's corners. */
1895
+ /* #2946: the key to the items carried between desks — a strip under the bar, as the org chart's (.oc-legend). */
1896
+ .oo-key { font-size: var(--fs-xs); color: var(--text-2); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 4px 10px; }
1897
+ .oo-key-rows { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-4); margin: 0; padding: 0; list-style: none; }
1898
+ .oo-key-row { display: inline-flex; align-items: center; gap: 6px; }
1899
+ .oo-key-icon { width: 32px; height: 32px; flex: none; image-rendering: pixelated; }
1900
+ .oo-key-btn.on { border-color: var(--accent); }
1821
1901
  .oo-zoom { z-index: 6; }
1822
1902
  .oo-zoom .icon-btn { color: var(--text); }
1823
1903
  /* The overview's box (left, top, width, height) is set by the page, inside the stage and scaled to it (miniBox). */
@@ -2036,6 +2116,16 @@ html.oo-immersive .p-fleet > .panel-body { z-index: 50; }
2036
2116
  .us-meta { display: block; font-size: var(--fs-xs); color: var(--text-3); overflow-wrap: anywhere; }
2037
2117
  .us-est { display: block; font-size: var(--fs-xs); font-weight: var(--fw-regular); color: var(--text-3); }
2038
2118
  .us-flags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
2119
+ /* #3066 §3: a row's numbers carry small marks (◐ partly priced, † the CLI's amount, ≈ estimated) and "—" with a reason,
2120
+ each said in its tooltip; the key under the table names only the marks that appear. */
2121
+ .us-mark { margin-left: 2px; color: var(--text-3); font-size: var(--fs-xs); cursor: help; }
2122
+ .us-mark.us-approx { margin-left: 0; margin-right: 1px; }
2123
+ .us-none { cursor: help; }
2124
+ .us-key { margin-top: 6px; }
2125
+ /* #3066 §2: each model's speed after the first token. */
2126
+ .us-speed { margin-top: 12px; }
2127
+ .us-speed .row-item { gap: 8px; flex-wrap: wrap; }
2128
+ .us-speed .num { font-variant-numeric: tabular-nums; }
2039
2129
  .us-trend, .us-heat { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
2040
2130
  .us-trend h3, .us-heat h3, .us-rest h3 { font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
2041
2131
  .us-scroll { overflow-x: auto; max-width: 100%; }
@@ -2242,9 +2332,9 @@ html.oo-immersive .p-fleet > .panel-body { z-index: 50; }
2242
2332
  @media (min-width: 900px) { .chat-split > .pv-divider, .chat-split > .pv-panel { position: relative; z-index: 1; } }
2243
2333
  /* #1629: full-app bounded stock surfaces. Panel roots stay neutral; effects never raise the whole app. */
2244
2334
  .p-fleet > .seg, .p-settings > .seg,
2245
- .p-fleet > .panel-body, .p-needs > .panel-body, .p-settings > .panel-body,
2335
+ .p-fleet > .panel-body, .p-needs > .panel-body, .p-notices > .panel-body, .p-settings > .panel-body,
2246
2336
  .p-log > .panel-body, .p-details > .panel-body, .p-view > .panel-body,
2247
- .p-log > .log-bar, .p-view > .v-term, .p-view > .v-id, .p-view > .v-watching { position: relative; z-index: 1; }
2337
+ .p-log > .log-bar, .p-view > .v-term-box, .p-view > .v-id, .p-view > .v-watching { position: relative; z-index: 1; }
2248
2338
  /* Keep the existing Apply bar's sticky behavior, in its own bounded stock band. */
2249
2339
  .p-settings > .s-pending { z-index: 1; }
2250
2340
 
@@ -13,7 +13,7 @@ import { installSwipe } from "./app-swipe.js";
13
13
  import { installTextUndo } from "./text-undo.js";
14
14
  import { startRouter, navStore, navigate } from "./app-nav.js";
15
15
  import { createStream } from "./app-stream.js";
16
- import { appStore, applyStatus, applyActivity, guestPage, guestTrusted } from "./app-store.js";
16
+ import { appStore, applyStatus, applyActivity, guestPage, guestTrusted, addNotice, createNoticesSync } from "./app-store.js";
17
17
  import { chatPath } from "./app-route.js";
18
18
  import { startNeedsNotifier } from "./app-needs.js";
19
19
  import { toast } from "./ui-toast.js";
@@ -91,6 +91,27 @@ if (mode === "full") {
91
91
  const loadApply = retryable((a) => import(retryUrl("/ui/js/settings-apply.js", a)));
92
92
  appStore.set({ restartRunner: (jobId) => loadApply().then((m) => m.restartPendingChanges(jobId)) });
93
93
  panels.set("needs", { load: () => loadNeeds().then((m) => m.NeedsPanel) });
94
+ // #2910 D2: a web-only fleet's Notices (/ui/notices): read once the status says there is no chat connection (and
95
+ // again after a reconnect: a poll page hears no `notice`), then each new one from the stream.
96
+ const loadNotices = retryable((a) => import(retryUrl("/ui/js/panel-notices.js", a)));
97
+ panels.set("notices", { load: () => loadNotices().then((m) => m.NoticesPanel) });
98
+ // A list read and a live notice can cross: each is merged into what the page has (app-store.js mergeNoticeList); a
99
+ // read that leaves the page behind what the status frame names is asked again (createNoticesSync).
100
+ const notices = createNoticesSync({ store: appStore,
101
+ fetchList: () => fetch("/ui/notices/list", { credentials: "same-origin", cache: "no-store" }).then((r) => (r.ok ? r.json() : null)) });
102
+ const readNotices = () => notices.read();
103
+ appStore.set({ readNotices });
104
+ appStore.subscribe((s) => {
105
+ if (s.connections === 0) notices.start();
106
+ notices.recheck(); // a polling page hears no `notice`: the status frame's newest id is its catch-up
107
+ });
108
+ stream.on("connection", (c) => { if ((c === "live" || c === "polling") && notices.started()) readNotices(); });
109
+ stream.on("notice", (d) => {
110
+ const cur = appStore.get().notices;
111
+ if (!cur || !cur.enabled) { readNotices(); return; }
112
+ const next = addNotice(cur, d && d.notice);
113
+ if (next !== cur) appStore.set({ notices: next });
114
+ });
94
115
  // #1523 N2: one instance's Details (/ui/fleet/agent/<name>).
95
116
  panels.set("details", { load: () => loadDetails().then((m) => m.DetailsPanel) });
96
117
  // #1218: one instance's Log (/ui/log/<name>).
Binary file
Binary file