@songsid/agend 2.3.0-beta.9 → 2.3.1

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 (743) hide show
  1. package/README.md +16 -8
  2. package/README.zh-TW.md +16 -8
  3. package/dist/adapter-world.js.map +1 -1
  4. package/dist/agend-home.d.ts +5 -0
  5. package/dist/agend-home.js +7 -0
  6. package/dist/agend-home.js.map +1 -0
  7. package/dist/agent-cli-instructions.md +7 -1
  8. package/dist/agent-cli.js +41 -0
  9. package/dist/agent-cli.js.map +1 -1
  10. package/dist/agent-endpoint.d.ts +9 -0
  11. package/dist/agent-endpoint.js +23 -0
  12. package/dist/agent-endpoint.js.map +1 -1
  13. package/dist/agent-file-read.js +1 -1
  14. package/dist/agent-file-read.js.map +1 -1
  15. package/dist/agent-whats-new.d.ts +16 -0
  16. package/dist/agent-whats-new.js +53 -12
  17. package/dist/agent-whats-new.js.map +1 -1
  18. package/dist/apply-job.js.map +1 -1
  19. package/dist/atomic-write.js.map +1 -1
  20. package/dist/auth-api.d.ts +12 -0
  21. package/dist/auth-api.js +77 -22
  22. package/dist/auth-api.js.map +1 -1
  23. package/dist/authority/authority-state.d.ts +4 -0
  24. package/dist/authority/authority-state.js +17 -8
  25. package/dist/authority/authority-state.js.map +1 -1
  26. package/dist/authority/session-authorizations.js.map +1 -1
  27. package/dist/authority/web-authority.d.ts +16 -8
  28. package/dist/authority/web-authority.js +19 -5
  29. package/dist/authority/web-authority.js.map +1 -1
  30. package/dist/backend/antigravity.d.ts +2 -2
  31. package/dist/backend/antigravity.js +2 -1
  32. package/dist/backend/antigravity.js.map +1 -1
  33. package/dist/backend/claude-code.js +13 -4
  34. package/dist/backend/claude-code.js.map +1 -1
  35. package/dist/backend/codex-metadata.d.ts +8 -0
  36. package/dist/backend/codex-metadata.js +74 -17
  37. package/dist/backend/codex-metadata.js.map +1 -1
  38. package/dist/backend/codex-package.d.ts +30 -0
  39. package/dist/backend/codex-package.js +133 -0
  40. package/dist/backend/codex-package.js.map +1 -0
  41. package/dist/backend/codex-session-lookup.js.map +1 -1
  42. package/dist/backend/codex.d.ts +2 -0
  43. package/dist/backend/codex.js +25 -5
  44. package/dist/backend/codex.js.map +1 -1
  45. package/dist/backend/credential-profile.d.ts +2 -0
  46. package/dist/backend/credential-profile.js +2 -0
  47. package/dist/backend/credential-profile.js.map +1 -1
  48. package/dist/backend/effort-metadata.js.map +1 -1
  49. package/dist/backend/grok.js +58 -3
  50. package/dist/backend/grok.js.map +1 -1
  51. package/dist/backend/kiro-engine-ledger.js.map +1 -1
  52. package/dist/backend/kiro-kas-store.js.map +1 -1
  53. package/dist/backend/kiro-v2-store.js.map +1 -1
  54. package/dist/backend/kiro-v3-identity.js.map +1 -1
  55. package/dist/backend/kiro.d.ts +9 -1
  56. package/dist/backend/kiro.js +102 -1
  57. package/dist/backend/kiro.js.map +1 -1
  58. package/dist/backend/launch-effort.js.map +1 -1
  59. package/dist/backend/mock.js.map +1 -1
  60. package/dist/backend/muse.d.ts +20 -2
  61. package/dist/backend/muse.js +154 -16
  62. package/dist/backend/muse.js.map +1 -1
  63. package/dist/backend/opencode-permission.js +1 -1
  64. package/dist/backend/opencode-permission.js.map +1 -1
  65. package/dist/backend/opencode.js +2 -1
  66. package/dist/backend/opencode.js.map +1 -1
  67. package/dist/backend/session-signals.js.map +1 -1
  68. package/dist/backend-availability.js.map +1 -1
  69. package/dist/backend-command.d.ts +2 -0
  70. package/dist/backend-command.js +3 -1
  71. package/dist/backend-command.js.map +1 -1
  72. package/dist/backend-outage.js.map +1 -1
  73. package/dist/binary-probe.js +1 -1
  74. package/dist/binary-probe.js.map +1 -1
  75. package/dist/bug-report-cli.d.ts +30 -0
  76. package/dist/bug-report-cli.js +139 -0
  77. package/dist/bug-report-cli.js.map +1 -0
  78. package/dist/bug-report.d.ts +47 -0
  79. package/dist/bug-report.js +137 -0
  80. package/dist/bug-report.js.map +1 -0
  81. package/dist/bundled-skills.d.ts +18 -0
  82. package/dist/bundled-skills.js +38 -0
  83. package/dist/bundled-skills.js.map +1 -0
  84. package/dist/cache-service.js +1 -1
  85. package/dist/cache-service.js.map +1 -1
  86. package/dist/channel/adapters/discord-client-retirement.d.ts +5 -0
  87. package/dist/channel/adapters/discord-client-retirement.js +57 -0
  88. package/dist/channel/adapters/discord-client-retirement.js.map +1 -0
  89. package/dist/channel/adapters/discord.d.ts +4 -0
  90. package/dist/channel/adapters/discord.js +57 -12
  91. package/dist/channel/adapters/discord.js.map +1 -1
  92. package/dist/channel/adapters/telegram.d.ts +7 -1
  93. package/dist/channel/adapters/telegram.js +57 -49
  94. package/dist/channel/adapters/telegram.js.map +1 -1
  95. package/dist/channel/mcp-server.js +21 -4
  96. package/dist/channel/mcp-server.js.map +1 -1
  97. package/dist/channel/mcp-tools.d.ts +3 -1
  98. package/dist/channel/mcp-tools.js +41 -4
  99. package/dist/channel/mcp-tools.js.map +1 -1
  100. package/dist/channel/message-queue.js.map +1 -1
  101. package/dist/channel/sticker-download.js.map +1 -1
  102. package/dist/channel/tool-router.js.map +1 -1
  103. package/dist/child-process.d.ts +21 -0
  104. package/dist/child-process.js +54 -0
  105. package/dist/child-process.js.map +1 -0
  106. package/dist/classic-channel-manager.js +3 -2
  107. package/dist/classic-channel-manager.js.map +1 -1
  108. package/dist/cli-entry.js.map +1 -1
  109. package/dist/cli-flags.js.map +1 -1
  110. package/dist/cli.d.ts +1 -0
  111. package/dist/cli.js +448 -313
  112. package/dist/cli.js.map +1 -1
  113. package/dist/command-table.d.ts +1 -1
  114. package/dist/command-table.js +1 -1
  115. package/dist/command-table.js.map +1 -1
  116. package/dist/compact-watch.js.map +1 -1
  117. package/dist/completion-install.js.map +1 -1
  118. package/dist/completion.js.map +1 -1
  119. package/dist/config-validator.d.ts +6 -0
  120. package/dist/config-validator.js +81 -8
  121. package/dist/config-validator.js.map +1 -1
  122. package/dist/config.d.ts +15 -3
  123. package/dist/config.js +41 -10
  124. package/dist/config.js.map +1 -1
  125. package/dist/connection-secrets.js.map +1 -1
  126. package/dist/context-guardian.js.map +1 -1
  127. package/dist/coredump-filter.js.map +1 -1
  128. package/dist/cpu-profile.js.map +1 -1
  129. package/dist/cross-instance-envelope.js.map +1 -1
  130. package/dist/cross-instance-notice.d.ts +7 -0
  131. package/dist/cross-instance-notice.js +10 -0
  132. package/dist/cross-instance-notice.js.map +1 -1
  133. package/dist/daemon.d.ts +52 -1
  134. package/dist/daemon.js +385 -27
  135. package/dist/daemon.js.map +1 -1
  136. package/dist/daily-summary.js.map +1 -1
  137. package/dist/darwin-memory.js +1 -1
  138. package/dist/darwin-memory.js.map +1 -1
  139. package/dist/dashboard-live.d.ts +8 -0
  140. package/dist/dashboard-live.js +35 -0
  141. package/dist/dashboard-live.js.map +1 -0
  142. package/dist/dashboard-permissions.d.ts +69 -0
  143. package/dist/dashboard-permissions.js +138 -0
  144. package/dist/dashboard-permissions.js.map +1 -0
  145. package/dist/decision-list.js.map +1 -1
  146. package/dist/delivery-consumed-watch.js.map +1 -1
  147. package/dist/delivery-outbox.d.ts +11 -0
  148. package/dist/delivery-outbox.js +52 -2
  149. package/dist/delivery-outbox.js.map +1 -1
  150. package/dist/delivery-outbox.test.js.map +1 -1
  151. package/dist/delivery-reconciliation.test.js.map +1 -1
  152. package/dist/diagnostic-redaction.d.ts +10 -0
  153. package/dist/diagnostic-redaction.js +167 -0
  154. package/dist/diagnostic-redaction.js.map +1 -0
  155. package/dist/doctor.d.ts +8 -0
  156. package/dist/doctor.js +52 -0
  157. package/dist/doctor.js.map +1 -1
  158. package/dist/e2e-isolation.js.map +1 -1
  159. package/dist/event-log.js.map +1 -1
  160. package/dist/export-import.js +7 -5
  161. package/dist/export-import.js.map +1 -1
  162. package/dist/fleet-context.d.ts +1 -1
  163. package/dist/fleet-control-audit.js.map +1 -1
  164. package/dist/fleet-label.js.map +1 -1
  165. package/dist/fleet-level-config.d.ts +1 -1
  166. package/dist/fleet-level-config.js +2 -0
  167. package/dist/fleet-level-config.js.map +1 -1
  168. package/dist/fleet-lock.d.ts +6 -0
  169. package/dist/fleet-lock.js +22 -2
  170. package/dist/fleet-lock.js.map +1 -1
  171. package/dist/fleet-manager.d.ts +283 -15
  172. package/dist/fleet-manager.js +1825 -331
  173. package/dist/fleet-manager.js.map +1 -1
  174. package/dist/fleet-process-handlers.d.ts +18 -0
  175. package/dist/fleet-process-handlers.js +70 -0
  176. package/dist/fleet-process-handlers.js.map +1 -0
  177. package/dist/fleet-startup.d.ts +14 -0
  178. package/dist/fleet-startup.js +30 -0
  179. package/dist/fleet-startup.js.map +1 -0
  180. package/dist/fleet-traffic.js.map +1 -1
  181. package/dist/forged-envelope-scan.d.ts +0 -20
  182. package/dist/forged-envelope-scan.js +3 -2
  183. package/dist/forged-envelope-scan.js.map +1 -1
  184. package/dist/full-restart.d.ts +5 -5
  185. package/dist/full-restart.js +5 -5
  186. package/dist/full-restart.js.map +1 -1
  187. package/dist/general-knowledge/skills/bug-report/SKILL.md +31 -0
  188. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +52 -11
  189. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +5 -1
  190. package/dist/general-knowledge/skills/fleet-config/SKILL.md +3 -1
  191. package/dist/general-knowledge/skills/fleet-restart/SKILL.md +8 -9
  192. package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +11 -0
  193. package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -1
  194. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
  195. package/dist/general-knowledge/skills/scheduling/SKILL.md +4 -0
  196. package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +321 -0
  197. package/dist/general-knowledge/skills/web-appearance/SKILL.md +24 -4
  198. package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +554 -0
  199. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +156 -32
  200. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
  201. package/dist/general-knowledge/steering/core-rules.md +1 -1
  202. package/dist/host-memory.js.map +1 -1
  203. package/dist/idle-gate-log.d.ts +19 -0
  204. package/dist/idle-gate-log.js +15 -0
  205. package/dist/idle-gate-log.js.map +1 -0
  206. package/dist/instance-config-impact.js +25 -4
  207. package/dist/instance-config-impact.js.map +1 -1
  208. package/dist/instance-lifecycle.d.ts +11 -1
  209. package/dist/instance-lifecycle.js +97 -25
  210. package/dist/instance-lifecycle.js.map +1 -1
  211. package/dist/instructions.d.ts +12 -6
  212. package/dist/instructions.js +19 -10
  213. package/dist/instructions.js.map +1 -1
  214. package/dist/kiro-compact-pane.js.map +1 -1
  215. package/dist/kiro-db-reader.js.map +1 -1
  216. package/dist/kiro-engine-status.js.map +1 -1
  217. package/dist/kiro-log-gate.js.map +1 -1
  218. package/dist/kiro-transcript-lane.js.map +1 -1
  219. package/dist/locale.js +450 -20
  220. package/dist/locale.js.map +1 -1
  221. package/dist/log-service.js +1 -0
  222. package/dist/log-service.js.map +1 -1
  223. package/dist/log-steps.d.ts +1 -0
  224. package/dist/log-steps.js +15 -0
  225. package/dist/log-steps.js.map +1 -1
  226. package/dist/logger.js +3 -2
  227. package/dist/logger.js.map +1 -1
  228. package/dist/login-controller.d.ts +45 -0
  229. package/dist/login-controller.js +101 -5
  230. package/dist/login-controller.js.map +1 -1
  231. package/dist/login-flows.js +1 -1
  232. package/dist/login-manager.js.map +1 -1
  233. package/dist/login-shell.js +3 -1
  234. package/dist/login-shell.js.map +1 -1
  235. package/dist/ls-attach-resolve.d.ts +96 -0
  236. package/dist/ls-attach-resolve.js +180 -0
  237. package/dist/ls-attach-resolve.js.map +1 -0
  238. package/dist/ls-rows.d.ts +12 -0
  239. package/dist/ls-rows.js +83 -4
  240. package/dist/ls-rows.js.map +1 -1
  241. package/dist/memory-pressure.js.map +1 -1
  242. package/dist/muse-usage-relay.js.map +1 -1
  243. package/dist/needs-you-hub.d.ts +98 -1
  244. package/dist/needs-you-hub.js +313 -44
  245. package/dist/needs-you-hub.js.map +1 -1
  246. package/dist/needs-you-live.d.ts +5 -2
  247. package/dist/needs-you-live.js +6 -3
  248. package/dist/needs-you-live.js.map +1 -1
  249. package/dist/needs-you.d.ts +68 -3
  250. package/dist/needs-you.js +39 -4
  251. package/dist/needs-you.js.map +1 -1
  252. package/dist/network-family.js.map +1 -1
  253. package/dist/operator-control-paths.js +3 -4
  254. package/dist/operator-control-paths.js.map +1 -1
  255. package/dist/outbound-handlers.d.ts +5 -2
  256. package/dist/outbound-handlers.js +81 -24
  257. package/dist/outbound-handlers.js.map +1 -1
  258. package/dist/outbound-schemas.d.ts +106 -60
  259. package/dist/outbound-schemas.js +33 -10
  260. package/dist/outbound-schemas.js.map +1 -1
  261. package/dist/outbox-open-error.js.map +1 -1
  262. package/dist/pane-context-cache.js.map +1 -1
  263. package/dist/paths.js.map +1 -1
  264. package/dist/private-dir.js.map +1 -1
  265. package/dist/probe-worker-pool.js.map +1 -1
  266. package/dist/profile-control.js.map +1 -1
  267. package/dist/prompt-file-ref.js.map +1 -1
  268. package/dist/provider-probe.js.map +1 -1
  269. package/dist/provider-secret-registry.d.ts +5 -3
  270. package/dist/provider-secret-registry.js +8 -2
  271. package/dist/provider-secret-registry.js.map +1 -1
  272. package/dist/public-link-auto-open.d.ts +32 -0
  273. package/dist/public-link-auto-open.js +86 -0
  274. package/dist/public-link-auto-open.js.map +1 -0
  275. package/dist/public-link-owner.d.ts +10 -0
  276. package/dist/public-link-owner.js +36 -0
  277. package/dist/public-link-owner.js.map +1 -0
  278. package/dist/public-link-progress.d.ts +12 -1
  279. package/dist/public-link-progress.js +5 -10
  280. package/dist/public-link-progress.js.map +1 -1
  281. package/dist/public-preview.js.map +1 -1
  282. package/dist/public-tunnel-config.d.ts +11 -0
  283. package/dist/public-tunnel-config.js +68 -0
  284. package/dist/public-tunnel-config.js.map +1 -0
  285. package/dist/public-web-gateway.d.ts +2 -0
  286. package/dist/public-web-gateway.js +19 -6
  287. package/dist/public-web-gateway.js.map +1 -1
  288. package/dist/public-web-link.d.ts +48 -3
  289. package/dist/public-web-link.js +177 -51
  290. package/dist/public-web-link.js.map +1 -1
  291. package/dist/quickstart-api.d.ts +9 -0
  292. package/dist/quickstart-api.js +82 -0
  293. package/dist/quickstart-api.js.map +1 -1
  294. package/dist/quickstart.d.ts +5 -0
  295. package/dist/quickstart.js +40 -25
  296. package/dist/quickstart.js.map +1 -1
  297. package/dist/reply-buttons-controller.js.map +1 -1
  298. package/dist/reply-dedup.js.map +1 -1
  299. package/dist/resource-report.js +1 -1
  300. package/dist/resource-report.js.map +1 -1
  301. package/dist/restart-guard.js.map +1 -1
  302. package/dist/restart-progress.d.ts +80 -1
  303. package/dist/restart-progress.js +306 -21
  304. package/dist/restart-progress.js.map +1 -1
  305. package/dist/rollout-index.js.map +1 -1
  306. package/dist/runtime-cpu-profile.js.map +1 -1
  307. package/dist/scheduler/db.d.ts +40 -13
  308. package/dist/scheduler/db.js +123 -89
  309. package/dist/scheduler/db.js.map +1 -1
  310. package/dist/scheduler/scheduler.js.map +1 -1
  311. package/dist/scheduler/task-board-text.d.ts +26 -0
  312. package/dist/scheduler/task-board-text.js +140 -0
  313. package/dist/scheduler/task-board-text.js.map +1 -0
  314. package/dist/scheduler/task-board.d.ts +730 -0
  315. package/dist/scheduler/task-board.js +2179 -0
  316. package/dist/scheduler/task-board.js.map +1 -0
  317. package/dist/scheduler/types.d.ts +6 -1
  318. package/dist/sd-notify.js +2 -1
  319. package/dist/sd-notify.js.map +1 -1
  320. package/dist/search/search-docs.d.ts +58 -0
  321. package/dist/search/search-docs.js +63 -0
  322. package/dist/search/search-docs.js.map +1 -0
  323. package/dist/search/search-index.d.ts +149 -0
  324. package/dist/search/search-index.js +453 -0
  325. package/dist/search/search-index.js.map +1 -0
  326. package/dist/search/search-store.d.ts +122 -0
  327. package/dist/search/search-store.js +236 -0
  328. package/dist/search/search-store.js.map +1 -0
  329. package/dist/search/search-worker.d.ts +1 -0
  330. package/dist/search/search-worker.js +163 -0
  331. package/dist/search/search-worker.js.map +1 -0
  332. package/dist/secret-file.js.map +1 -1
  333. package/dist/secret-store.d.ts +2 -0
  334. package/dist/secret-store.js +21 -0
  335. package/dist/secret-store.js.map +1 -1
  336. package/dist/service-installer.d.ts +98 -1
  337. package/dist/service-installer.js +246 -11
  338. package/dist/service-installer.js.map +1 -1
  339. package/dist/service-owner.d.ts +44 -0
  340. package/dist/service-owner.js +48 -0
  341. package/dist/service-owner.js.map +1 -0
  342. package/dist/service-plan.d.ts +39 -2
  343. package/dist/service-plan.js +188 -6
  344. package/dist/service-plan.js.map +1 -1
  345. package/dist/session-oom-stop.d.ts +45 -0
  346. package/dist/session-oom-stop.js +259 -0
  347. package/dist/session-oom-stop.js.map +1 -0
  348. package/dist/session-oom.d.ts +34 -0
  349. package/dist/session-oom.js +251 -0
  350. package/dist/session-oom.js.map +1 -0
  351. package/dist/settings-api.d.ts +14 -1
  352. package/dist/settings-api.js +74 -13
  353. package/dist/settings-api.js.map +1 -1
  354. package/dist/settings-baseline.js.map +1 -1
  355. package/dist/settings-change.d.ts +5 -0
  356. package/dist/settings-change.js +167 -6
  357. package/dist/settings-change.js.map +1 -1
  358. package/dist/settings-confirmation.d.ts +9 -1
  359. package/dist/settings-confirmation.js +18 -8
  360. package/dist/settings-confirmation.js.map +1 -1
  361. package/dist/settings-control.js +2 -1
  362. package/dist/settings-control.js.map +1 -1
  363. package/dist/settings-effect.js +29 -4
  364. package/dist/settings-effect.js.map +1 -1
  365. package/dist/settings-http-confirmation.d.ts +13 -0
  366. package/dist/settings-http-confirmation.js +15 -3
  367. package/dist/settings-http-confirmation.js.map +1 -1
  368. package/dist/settings-instance-patch.js +13 -1
  369. package/dist/settings-instance-patch.js.map +1 -1
  370. package/dist/settings-request-capability.d.ts +4 -1
  371. package/dist/settings-request-capability.js +11 -3
  372. package/dist/settings-request-capability.js.map +1 -1
  373. package/dist/settings-transaction.js.map +1 -1
  374. package/dist/setup-auth.d.ts +1 -0
  375. package/dist/setup-auth.js +2 -1
  376. package/dist/setup-auth.js.map +1 -1
  377. package/dist/setup-form.d.ts +1 -1
  378. package/dist/setup-form.js +23 -7
  379. package/dist/setup-form.js.map +1 -1
  380. package/dist/setup-host.d.ts +6 -1
  381. package/dist/setup-host.js +15 -4
  382. package/dist/setup-host.js.map +1 -1
  383. package/dist/setup-wizard.js +6 -3
  384. package/dist/setup-wizard.js.map +1 -1
  385. package/dist/spawn-gate.d.ts +7 -0
  386. package/dist/spawn-gate.js +45 -12
  387. package/dist/spawn-gate.js.map +1 -1
  388. package/dist/start-attempt.d.ts +11 -0
  389. package/dist/start-attempt.js +29 -0
  390. package/dist/start-attempt.js.map +1 -0
  391. package/dist/start-failure-chat.d.ts +37 -0
  392. package/dist/start-failure-chat.js +142 -0
  393. package/dist/start-failure-chat.js.map +1 -0
  394. package/dist/start-failure-notice.d.ts +4 -0
  395. package/dist/start-failure-notice.js +20 -0
  396. package/dist/start-failure-notice.js.map +1 -0
  397. package/dist/start-failure.d.ts +171 -0
  398. package/dist/start-failure.js +348 -0
  399. package/dist/start-failure.js.map +1 -0
  400. package/dist/startup-memory-deadline.d.ts +23 -0
  401. package/dist/startup-memory-deadline.js +55 -0
  402. package/dist/startup-memory-deadline.js.map +1 -0
  403. package/dist/statusline-watcher.js.map +1 -1
  404. package/dist/storm-window.js.map +1 -1
  405. package/dist/systemd-peer-bus.js.map +1 -1
  406. package/dist/target-queue-worker.js.map +1 -1
  407. package/dist/task-board-summary.d.ts +101 -0
  408. package/dist/task-board-summary.js +177 -0
  409. package/dist/task-board-summary.js.map +1 -0
  410. package/dist/task-board-tool.d.ts +25 -0
  411. package/dist/task-board-tool.js +155 -0
  412. package/dist/task-board-tool.js.map +1 -0
  413. package/dist/task-board-waker.d.ts +51 -0
  414. package/dist/task-board-waker.js +141 -0
  415. package/dist/task-board-waker.js.map +1 -0
  416. package/dist/telegram-api-root.d.ts +1 -0
  417. package/dist/telegram-api-root.js +40 -0
  418. package/dist/telegram-api-root.js.map +1 -0
  419. package/dist/tips.js.map +1 -1
  420. package/dist/tmux-control.js +1 -1
  421. package/dist/tmux-control.js.map +1 -1
  422. package/dist/tmux-exec-helper.d.ts +104 -0
  423. package/dist/tmux-exec-helper.js +412 -0
  424. package/dist/tmux-exec-helper.js.map +1 -0
  425. package/dist/tmux-manager.d.ts +1 -0
  426. package/dist/tmux-manager.js +29 -13
  427. package/dist/tmux-manager.js.map +1 -1
  428. package/dist/tmux-read.js +2 -2
  429. package/dist/tmux-read.js.map +1 -1
  430. package/dist/tool-permissions.js.map +1 -1
  431. package/dist/tool-progress.js.map +1 -1
  432. package/dist/topic-archiver.js.map +1 -1
  433. package/dist/topic-commands.d.ts +13 -0
  434. package/dist/topic-commands.js +56 -33
  435. package/dist/topic-commands.js.map +1 -1
  436. package/dist/topic-link.js.map +1 -1
  437. package/dist/transcript-delta-reader.js.map +1 -1
  438. package/dist/transcript-jsonl.js.map +1 -1
  439. package/dist/transcript-monitor.js +5 -0
  440. package/dist/transcript-monitor.js.map +1 -1
  441. package/dist/transcript-sources.d.ts +2 -0
  442. package/dist/transcript-sources.js +4 -0
  443. package/dist/transcript-sources.js.map +1 -1
  444. package/dist/tunnel/cloudflared-install.js +3 -1
  445. package/dist/tunnel/cloudflared-install.js.map +1 -1
  446. package/dist/tunnel/cloudflared.d.ts +7 -16
  447. package/dist/tunnel/cloudflared.js +100 -13
  448. package/dist/tunnel/cloudflared.js.map +1 -1
  449. package/dist/tunnel/lease.js +3 -2
  450. package/dist/tunnel/lease.js.map +1 -1
  451. package/dist/tunnel/manager.js.map +1 -1
  452. package/dist/tunnel/named-diagnostics.d.ts +13 -0
  453. package/dist/tunnel/named-diagnostics.js +52 -0
  454. package/dist/tunnel/named-diagnostics.js.map +1 -0
  455. package/dist/tunnel/public-fetch.js.map +1 -1
  456. package/dist/tunnel/purpose-lane.js.map +1 -1
  457. package/dist/tunnel/types.d.ts +4 -1
  458. package/dist/tunnel/types.js.map +1 -1
  459. package/dist/types.d.ts +56 -2
  460. package/dist/ui/app-effects.js +23 -5
  461. package/dist/ui/app.html +2 -0
  462. package/dist/ui/backend-signin.js +297 -0
  463. package/dist/ui/chat-effects.js +10 -3
  464. package/dist/ui/chat-msg-actions.js +176 -0
  465. package/dist/ui/chat-render.js +62 -18
  466. package/dist/ui/chat-store.js +218 -48
  467. package/dist/ui/chat-strings.js +40 -8
  468. package/dist/ui/chat-thread.js +119 -10
  469. package/dist/ui/effect-trial-offer.js +2 -31
  470. package/dist/ui/effects-waker.js +2 -0
  471. package/dist/ui/fleet-canvas-layout.js +13 -4
  472. package/dist/ui/fleet-canvas.js +69 -28
  473. package/dist/ui/fleet-office-editor.js +149 -0
  474. package/dist/ui/fleet-office-model.js +358 -0
  475. package/dist/ui/fleet-office-pack.js +199 -0
  476. package/dist/ui/fleet-office-skin.js +474 -0
  477. package/dist/ui/fleet-office-store.js +49 -0
  478. package/dist/ui/fleet-office-zones.js +177 -0
  479. package/dist/ui/fleet-office.js +434 -0
  480. package/dist/ui/fleet-org.js +18 -5
  481. package/dist/ui/fleet-route-scene.js +272 -0
  482. package/dist/ui/fleet-route-worker.js +21 -0
  483. package/dist/ui/fleet-route.js +88 -0
  484. package/dist/ui/fleet-task-card.js +436 -0
  485. package/dist/ui/fleet-task-common.js +482 -0
  486. package/dist/ui/fleet-task-work.js +107 -0
  487. package/dist/ui/fleet-tasks.js +569 -0
  488. package/dist/ui/fleet-traffic.js +81 -18
  489. package/dist/ui/fleet-usage.js +36 -2
  490. package/dist/ui/guest-refused.html +41 -0
  491. package/dist/ui/icons/icon-192.png +0 -0
  492. package/dist/ui/icons/icon-512.png +0 -0
  493. package/dist/ui/image-lightbox.js +45 -1
  494. package/dist/ui/image-zoom.js +242 -0
  495. package/dist/ui/panel-chat.js +214 -57
  496. package/dist/ui/panel-details.js +2 -0
  497. package/dist/ui/panel-fleet.js +32 -71
  498. package/dist/ui/panel-log.js +3 -3
  499. package/dist/ui/panel-needs.js +23 -6
  500. package/dist/ui/panel-settings.js +166 -33
  501. package/dist/ui/preview-panel.js +2 -1
  502. package/dist/ui/search-dialog.js +350 -0
  503. package/dist/ui/settings-appearance.js +170 -10
  504. package/dist/ui/settings-apply.js +3 -3
  505. package/dist/ui/settings-confirm.js +7 -2
  506. package/dist/ui/settings-dialogs.js +46 -21
  507. package/dist/ui/settings-discord.js +6 -2
  508. package/dist/ui/settings-guests.js +2 -1
  509. package/dist/ui/settings-learn.js +1 -0
  510. package/dist/ui/settings-model.js +51 -18
  511. package/dist/ui/settings-mods.js +8 -3
  512. package/dist/ui/settings-owner-effects.js +6 -4
  513. package/dist/ui/settings-strings.js +186 -6
  514. package/dist/ui/settings-token.js +3 -1
  515. package/dist/ui/settings-web-authority.js +13 -5
  516. package/dist/ui/settings-wizard.js +13 -7
  517. package/dist/ui/shared/agend-auth.js +2 -0
  518. package/dist/ui/shared/app-i18n.js +12 -5
  519. package/dist/ui/shared/app-needs.js +2 -2
  520. package/dist/ui/shared/app-prefs.js +15 -0
  521. package/dist/ui/shared/app-route.js +18 -0
  522. package/dist/ui/shared/app-shell.js +189 -28
  523. package/dist/ui/shared/app-store.js +3 -2
  524. package/dist/ui/shared/app-stream.js +5 -1
  525. package/dist/ui/shared/app-themes.js +116 -1
  526. package/dist/ui/shared/app.css +668 -48
  527. package/dist/ui/shared/app.js +9 -1
  528. package/dist/ui/shared/card-strings.js +4 -0
  529. package/dist/ui/shared/effect-app-runtime.js +7 -5
  530. package/dist/ui/shared/effect-chat-runtime.js +2 -7
  531. package/dist/ui/shared/effect-cursor.js +3 -2
  532. package/dist/ui/shared/effect-display-metadata.js +39 -0
  533. package/dist/ui/shared/effect-owner-source.js +8 -1
  534. package/dist/ui/shared/effect-registry.js +14 -4
  535. package/dist/ui/shared/effect-runtime-loader.js +3 -1
  536. package/dist/ui/shared/effect-stock-trust.js +5 -5
  537. package/dist/ui/shared/feature-flags.js +127 -0
  538. package/dist/ui/shared/guest-refused.js +35 -0
  539. package/dist/ui/shared/header-tools.js +2 -2
  540. package/dist/ui/shared/identity-card.js +26 -8
  541. package/dist/ui/shared/identity-color.js +17 -10
  542. package/dist/ui/shared/instance-nav.js +183 -28
  543. package/dist/ui/shared/owner-css.js +30 -1
  544. package/dist/ui/shared/panel-view.js +14 -29
  545. package/dist/ui/shared/text-undo.js +210 -0
  546. package/dist/ui/shared/tokens.css +4 -0
  547. package/dist/ui/shared/ui-dialog.js +5 -4
  548. package/dist/ui/shared/ui-icons.js +4 -0
  549. package/dist/ui/shared/ui-menu.js +20 -7
  550. package/dist/ui/shared/ui-toast.js +16 -3
  551. package/dist/ui/shared/usage-dialog.js +216 -16
  552. package/dist/ui/shared/view-strings.js +70 -4
  553. package/dist/ui/shared/web-authorize.js +50 -1
  554. package/dist/ui/signin.html +2 -0
  555. package/dist/ui/web-terminal/terminal.html +10 -10
  556. package/dist/ui/web-terminal/terminal.js +58 -12
  557. package/dist/update-check.js.map +1 -1
  558. package/dist/update-dispatch.js +1 -1
  559. package/dist/update-dispatch.js.map +1 -1
  560. package/dist/update-install.js.map +1 -1
  561. package/dist/update-launch.d.ts +10 -1
  562. package/dist/update-launch.js +39 -14
  563. package/dist/update-launch.js.map +1 -1
  564. package/dist/update-marker.js.map +1 -1
  565. package/dist/update-preflight.js +1 -1
  566. package/dist/update-preflight.js.map +1 -1
  567. package/dist/update-progress.d.ts +3 -1
  568. package/dist/update-progress.js +3 -1
  569. package/dist/update-progress.js.map +1 -1
  570. package/dist/usage/format-rich.js +6 -3
  571. package/dist/usage/format-rich.js.map +1 -1
  572. package/dist/usage/i18n-keys.d.ts +1 -1
  573. package/dist/usage/i18n-keys.js +2 -1
  574. package/dist/usage/i18n-keys.js.map +1 -1
  575. package/dist/usage/i18n.d.ts +13 -1
  576. package/dist/usage/i18n.js +29 -0
  577. package/dist/usage/i18n.js.map +1 -1
  578. package/dist/usage/providers.d.ts +89 -2
  579. package/dist/usage/providers.js +247 -41
  580. package/dist/usage/providers.js.map +1 -1
  581. package/dist/usage/statusline-usage.js.map +1 -1
  582. package/dist/usage/usage-api.d.ts +5 -1
  583. package/dist/usage/usage-api.js +185 -58
  584. package/dist/usage/usage-api.js.map +1 -1
  585. package/dist/usage-report.js.map +1 -1
  586. package/dist/usage-rollup.js +1 -1
  587. package/dist/usage-rollup.js.map +1 -1
  588. package/dist/user-systemd.d.ts +24 -0
  589. package/dist/user-systemd.js +75 -0
  590. package/dist/user-systemd.js.map +1 -0
  591. package/dist/view-api.d.ts +7 -0
  592. package/dist/view-api.js +16 -4
  593. package/dist/view-api.js.map +1 -1
  594. package/dist/wake-coordinator.js.map +1 -1
  595. package/dist/web-ambient.js.map +1 -1
  596. package/dist/web-api.d.ts +58 -11
  597. package/dist/web-api.js +1104 -71
  598. package/dist/web-api.js.map +1 -1
  599. package/dist/web-app-icon-worker.d.ts +1 -0
  600. package/dist/web-app-icon-worker.js +16 -0
  601. package/dist/web-app-icon-worker.js.map +1 -0
  602. package/dist/web-app-icon.d.ts +109 -0
  603. package/dist/web-app-icon.js +257 -0
  604. package/dist/web-app-icon.js.map +1 -0
  605. package/dist/web-appearance-policy.js.map +1 -1
  606. package/dist/web-appearance-tools.d.ts +1 -0
  607. package/dist/web-appearance-tools.js +7 -3
  608. package/dist/web-appearance-tools.js.map +1 -1
  609. package/dist/web-appearance-view.js.map +1 -1
  610. package/dist/web-appearance.d.ts +4 -10
  611. package/dist/web-appearance.js +7 -4
  612. package/dist/web-appearance.js.map +1 -1
  613. package/dist/web-auth.d.ts +8 -4
  614. package/dist/web-auth.js +33 -21
  615. package/dist/web-auth.js.map +1 -1
  616. package/dist/web-backend-login.d.ts +130 -0
  617. package/dist/web-backend-login.js +225 -0
  618. package/dist/web-backend-login.js.map +1 -0
  619. package/dist/web-card.js.map +1 -1
  620. package/dist/web-channel-echo.js.map +1 -1
  621. package/dist/web-chat-history.d.ts +118 -8
  622. package/dist/web-chat-history.js +220 -25
  623. package/dist/web-chat-history.js.map +1 -1
  624. package/dist/web-commands.d.ts +5 -1
  625. package/dist/web-commands.js +1 -1
  626. package/dist/web-commands.js.map +1 -1
  627. package/dist/web-cookie-names.d.ts +5 -0
  628. package/dist/web-cookie-names.js +12 -0
  629. package/dist/web-cookie-names.js.map +1 -0
  630. package/dist/web-effect-bundle.d.ts +2 -2
  631. package/dist/web-effect-library.js.map +1 -1
  632. package/dist/web-effect-playback.js.map +1 -1
  633. package/dist/web-effect-profiles.d.ts +16 -16
  634. package/dist/web-effect-profiles.js +3 -2
  635. package/dist/web-effect-profiles.js.map +1 -1
  636. package/dist/web-effect-service.js.map +1 -1
  637. package/dist/web-effect-tools.js.map +1 -1
  638. package/dist/web-effect-trials.js.map +1 -1
  639. package/dist/web-effect-upload.js.map +1 -1
  640. package/dist/web-effect.d.ts +6 -6
  641. package/dist/web-effect.js.map +1 -1
  642. package/dist/web-experimental-http.d.ts +2 -0
  643. package/dist/web-experimental-http.js +12 -0
  644. package/dist/web-experimental-http.js.map +1 -0
  645. package/dist/web-experimental.d.ts +11 -0
  646. package/dist/web-experimental.js +49 -0
  647. package/dist/web-experimental.js.map +1 -0
  648. package/dist/web-guest-access.d.ts +4 -2
  649. package/dist/web-guest-access.js +22 -10
  650. package/dist/web-guest-access.js.map +1 -1
  651. package/dist/web-guest-rooms.js.map +1 -1
  652. package/dist/web-host-guard.d.ts +11 -0
  653. package/dist/web-host-guard.js +11 -0
  654. package/dist/web-host-guard.js.map +1 -1
  655. package/dist/web-icons.d.ts +33 -1
  656. package/dist/web-icons.js +83 -11
  657. package/dist/web-icons.js.map +1 -1
  658. package/dist/web-identity-color.js.map +1 -1
  659. package/dist/web-image-meta.d.ts +13 -0
  660. package/dist/web-image-meta.js +62 -0
  661. package/dist/web-image-meta.js.map +1 -1
  662. package/dist/web-images.js.map +1 -1
  663. package/dist/web-libavoid.d.ts +14 -0
  664. package/dist/web-libavoid.js +46 -0
  665. package/dist/web-libavoid.js.map +1 -0
  666. package/dist/web-login.js.map +1 -1
  667. package/dist/web-mentions.js.map +1 -1
  668. package/dist/web-mod-agent.js.map +1 -1
  669. package/dist/web-mod-store.d.ts +2 -0
  670. package/dist/web-mod-store.js +10 -0
  671. package/dist/web-mod-store.js.map +1 -1
  672. package/dist/web-office-store.d.ts +104 -0
  673. package/dist/web-office-store.js +236 -0
  674. package/dist/web-office-store.js.map +1 -0
  675. package/dist/web-owner-css-store.d.ts +44 -1
  676. package/dist/web-owner-css-store.js +70 -9
  677. package/dist/web-owner-css-store.js.map +1 -1
  678. package/dist/web-owner-css.js.map +1 -1
  679. package/dist/web-png.d.ts +33 -0
  680. package/dist/web-png.js +329 -0
  681. package/dist/web-png.js.map +1 -0
  682. package/dist/web-prefs.d.ts +6 -0
  683. package/dist/web-prefs.js +29 -3
  684. package/dist/web-prefs.js.map +1 -1
  685. package/dist/web-preview.d.ts +2 -0
  686. package/dist/web-preview.js +2 -0
  687. package/dist/web-preview.js.map +1 -1
  688. package/dist/web-profile.js.map +1 -1
  689. package/dist/web-reactions.d.ts +35 -0
  690. package/dist/web-reactions.js +47 -0
  691. package/dist/web-reactions.js.map +1 -0
  692. package/dist/web-request-context.d.ts +5 -0
  693. package/dist/web-request-context.js.map +1 -1
  694. package/dist/web-returning-device.d.ts +4 -2
  695. package/dist/web-returning-device.js +13 -6
  696. package/dist/web-returning-device.js.map +1 -1
  697. package/dist/web-schedules.js.map +1 -1
  698. package/dist/web-send-dedupe.d.ts +36 -0
  699. package/dist/web-send-dedupe.js +69 -0
  700. package/dist/web-send-dedupe.js.map +1 -0
  701. package/dist/web-session-authorization.js.map +1 -1
  702. package/dist/web-session.js +1 -1
  703. package/dist/web-session.js.map +1 -1
  704. package/dist/web-settings-patch.d.ts +3 -1
  705. package/dist/web-settings-patch.js +11 -5
  706. package/dist/web-settings-patch.js.map +1 -1
  707. package/dist/web-settings-tools.d.ts +6 -0
  708. package/dist/web-settings-tools.js +52 -17
  709. package/dist/web-settings-tools.js.map +1 -1
  710. package/dist/web-terminal-http.js +15 -2
  711. package/dist/web-terminal-http.js.map +1 -1
  712. package/dist/web-terminal.js +1 -1
  713. package/dist/web-terminal.js.map +1 -1
  714. package/dist/web-theme-store.d.ts +2 -2
  715. package/dist/web-theme-store.js +6 -3
  716. package/dist/web-theme-store.js.map +1 -1
  717. package/dist/web-theme.d.ts +29 -0
  718. package/dist/web-theme.js +89 -1
  719. package/dist/web-theme.js.map +1 -1
  720. package/dist/web-upload.d.ts +18 -1
  721. package/dist/web-upload.js +45 -7
  722. package/dist/web-upload.js.map +1 -1
  723. package/dist/web-widget.js.map +1 -1
  724. package/dist/webhook-emitter.js.map +1 -1
  725. package/dist/windows-shortcuts.d.ts +78 -0
  726. package/dist/windows-shortcuts.js +203 -0
  727. package/dist/windows-shortcuts.js.map +1 -0
  728. package/dist/workflow-templates/default.md +3 -0
  729. package/dist/working-state-journal.d.ts +68 -0
  730. package/dist/working-state-journal.js +93 -0
  731. package/dist/working-state-journal.js.map +1 -0
  732. package/dist/ws-server.js.map +1 -1
  733. package/dist/yaml-shared-nodes.d.ts +25 -0
  734. package/dist/yaml-shared-nodes.js +185 -0
  735. package/dist/yaml-shared-nodes.js.map +1 -0
  736. package/launcher/agend-install.cjs +828 -0
  737. package/launcher/install-admission.cjs +4 -39
  738. package/launcher/postinstall.cjs +14 -12
  739. package/launcher/private-home.cjs +43 -0
  740. package/package.json +16 -13
  741. package/scripts/preinstall-guard.cjs +2 -5
  742. package/templates/windows-shortcuts.ps1 +181 -0
  743. package/launcher/old-updater-note.cjs +0 -48
@@ -4,7 +4,8 @@
4
4
  import { html, useEffect, useLayoutEffect, useMemo, useRef, useState } from "./app-html.js";
5
5
  import { t } from "./app-i18n.js";
6
6
  import { useLease } from "./app-ctx.js";
7
- import { guestPage } from "./app-store.js";
7
+ import { createStore, guestPage, useStore } from "./app-store.js";
8
+ import { onPrefsChanged, prefInForce, savePref } from "./app-prefs.js";
8
9
  import { readStream } from "./read-stream.js";
9
10
  import { Dialog } from "./ui-dialog.js";
10
11
  import { ErrorState, Skeleton } from "./ui-states.js";
@@ -39,6 +40,24 @@ function resetText(iso) {
39
40
  if (ms <= 0) return tn("usage.reset.soon");
40
41
  return usageText("", { key: "usage.reset.in", args: [usageDuration(ms)] });
41
42
  }
43
+ /** "14:05" today, "10/19 14:05" another day, in this browser's time: when last known numbers were read, a window reset. */
44
+ export function usageClock(iso, now = Date.now()) {
45
+ const at = new Date(iso || "");
46
+ if (Number.isNaN(at.getTime())) return "";
47
+ const hm = `${String(at.getHours()).padStart(2, "0")}:${String(at.getMinutes()).padStart(2, "0")}`;
48
+ return new Date(now).toDateString() === at.toDateString() ? hm : `${at.getMonth() + 1}/${at.getDate()} ${hm}`;
49
+ }
50
+ /**
51
+ * A row showing its last known numbers (the live read failed; #2236 follow-up): "已過期 · 快取於 14:05" and, for an expiry
52
+ * or another failure, what to do on a second line (its full text is the mark's tooltip too). A row from an older
53
+ * server (no `cachedAt`) says its hint, as before.
54
+ */
55
+ export function staleNote(p) {
56
+ if (!p.stale) return null;
57
+ if (!p.cachedAt || !p.staleCause) return { mark: usageText(p.hint || "", p.hintI18n), detail: "" };
58
+ const detail = p.staleCause !== "transient" && (p.hint || p.hintI18n) ? usageText(p.hint || "", p.hintI18n) : "";
59
+ return { mark: usageText("", { key: `usage.stale.${p.staleCause}`, args: [usageClock(p.cachedAt)] }), detail };
60
+ }
42
61
  function expiryText(iso) {
43
62
  if (!iso) return "";
44
63
  const at = new Date(iso), ms = at.getTime() - Date.now();
@@ -48,6 +67,8 @@ function expiryText(iso) {
48
67
  export function UsageMetric({ m }) {
49
68
  const bar = useRef(null);
50
69
  const label = usageText(m.label, m.labelI18n);
70
+ // Its window has reset since these numbers were read: no number and no bar — an old one is never shown as current.
71
+ if (m.resetPassed) return html`<div class="u-metric u-reset-since"><div class="u-row"><span class="u-label">${label}</span><span class="u-val">${usageText("", { key: "usage.metric.reset_since", args: [usageClock(m.resetsAt)] })}</span></div></div>`;
51
72
  const note = m.note ? usageText(m.note, m.noteI18n) : "";
52
73
  const pct = m.type === "percent" ? Math.min(100, Math.max(0, m.used ?? 0)) : 0;
53
74
  useLayoutEffect(() => { if (bar.current) bar.current.style.width = `${pct}%`; }, [pct]); // CSSOM (#1300)
@@ -70,10 +91,13 @@ export function UsageMetric({ m }) {
70
91
  /**
71
92
  * #2014: a row's title. A credential profile's row (`profile`; its API `name` is "Claude (<profile>)") shows the
72
93
  * provider name on the title line beside the plan badge, and the profile on its own full-width muted line under it;
73
- * the full name is the tooltip, and the dialog shows the profile unclipped. Any other row: its name.
94
+ * the full name is the tooltip, and the dialog shows the profile unclipped. The default login's row beside profiles
95
+ * (`defaultLogin`; "Claude (default)", #2236) does the same with "default" in the page's language, never a clipped
96
+ * "Claude (d…". Any other row: its name.
74
97
  */
75
98
  export function providerTitle(p) {
76
99
  const name = String((p && p.name) || ""), profile = p && typeof p.profile === "string" && p.profile ? p.profile : "";
100
+ if (!profile && p && p.defaultLogin === true && name.endsWith(" (default)")) return { base: name.slice(0, -" (default)".length), profile: tn("usage.default_login") };
77
101
  const suffix = ` (${profile})`;
78
102
  return profile && name.endsWith(suffix) ? { base: name.slice(0, -suffix.length), profile } : { base: name, profile };
79
103
  }
@@ -84,9 +108,20 @@ export function providerTitle(p) {
84
108
  * tooltip and for a screen reader.
85
109
  */
86
110
  export function planBadge(plan) {
87
- const m = /^(\S+)(?: [^()]+)? \((\d+(?:\.\d+)?)x\)$/i.exec(String(plan || "").trim());
88
- return m ? `${m[1]} ×${m[2]}` : String(plan || "");
111
+ const text = String(plan || "").trim();
112
+ const m = /^(\S+)(?: [^()]+)? \((\d+(?:\.\d+)?)x\)$/i.exec(text);
113
+ if (m) return `${m[1]} ×${m[2]}`;
114
+ // #2412: a long name ("Self Serve Business Usage Based", Codex's plan_type spelled out) says only its kind, so the badge
115
+ // never takes the row from the provider's name; the full name is the badge's tooltip.
116
+ if (text.length > PLAN_BADGE_MAX) {
117
+ for (const [word, short] of PLAN_KINDS) if (word.test(text)) return short;
118
+ }
119
+ return text;
89
120
  }
121
+ const PLAN_BADGE_MAX = 14;
122
+ /** The kinds a long plan name is shortened to, the most specific first. */
123
+ const PLAN_KINDS = [[/\benterprise\b/i, "Enterprise"], [/\bbusiness\b/i, "Business"], [/\bteam\b/i, "Team"], [/\bedu(?:cation)?\b/i, "Edu"],
124
+ [/\bpro\+/i, "Pro+"], [/\bpro\b/i, "Pro"], [/\bplus\b/i, "Plus"], [/\bmax\b/i, "Max"], [/\bfree\b/i, "Free"]];
90
125
  /** "Updated 3 min ago" (#1585): how old the numbers are — the panel may show the last snapshot while a fresh one comes. */
91
126
  export function updatedAgo(fetchedAt, now = Date.now()) {
92
127
  const ms = now - new Date(fetchedAt).getTime();
@@ -95,15 +130,169 @@ export function updatedAgo(fetchedAt, now = Date.now()) {
95
130
  return tn("usageUpdatedAgo", { age: min < 60 ? tn("usageMinutes", { n: min }) : tn("usageHours", { n: Math.floor(min / 60) }) });
96
131
  }
97
132
 
133
+ // ── Compact: one line per login (a synced preference, "usage.compact"; the dialog and the rail alike) ──
134
+ const COMPACT_KEY = "agend_usage_compact";
135
+ function readCompact() {
136
+ const p = prefInForce("usage.compact");
137
+ return (p ? p.value : stored(COMPACT_KEY) === "on" ? true : undefined) === true;
138
+ }
139
+ export const usageViewStore = createStore({ compact: readCompact() });
140
+ export function setUsageCompact(on) {
141
+ usageViewStore.set({ compact: !!on });
142
+ savePref("usage.compact", on ? true : null); // the full cards are the default: switching back clears it
143
+ }
144
+ onPrefsChanged((keys) => { if (keys.has("usage.compact")) usageViewStore.set({ compact: readCompact() }); });
145
+ /** The header's switch between one line per login and the full cards (beside the title: the dialog's and the rail's). */
146
+ export function UsageCompactToggle() {
147
+ const { compact } = useStore(usageViewStore);
148
+ const [label, title] = compact ? [tn("usageFull"), tn("usageFullTitle")] : [tn("usageCompact"), tn("usageCompactTitle")];
149
+ return html`<button type="button" class="btn btn-ghost btn-sm u-compact-toggle" aria-pressed=${compact ? "true" : "false"} title=${title}
150
+ onClick=${() => setUsageCompact(!compact)}>${label}</button>`;
151
+ }
152
+ const TWO_DAYS = 48 * 3_600_000;
153
+ /**
154
+ * A login's two columns on its compact line: `short`, its shortest percent window under two days (the session), and
155
+ * `long`, its longest of two days or more (the week, the month) — null when it has none (a dash in that column). A window
156
+ * that reset since the numbers were read is left out (its full card shows no number); one of unknown length is a long one.
157
+ */
158
+ export function compactSlots(p) {
159
+ const pct = ((p && p.metrics) || []).filter((m) => m && m.type === "percent" && !m.resetPassed);
160
+ const isShort = (m) => Number(m.windowMs) > 0 && m.windowMs < TWO_DAYS;
161
+ const short = pct.filter(isShort).sort((a, b) => a.windowMs - b.windowMs)[0] || null;
162
+ const long = pct.filter((m) => !isShort(m)).map((m, i) => ({ m, i }))
163
+ .sort((a, b) => ((Number(b.m.windowMs) || -1) - (Number(a.m.windowMs) || -1)) || a.i - b.i)[0]?.m || null;
164
+ return { short, long };
165
+ }
166
+ /** The windows a compact line shows, short first. */
167
+ export const compactMetrics = (p) => { const { short, long } = compactSlots(p); return [short, long].filter(Boolean); };
168
+ /** A window as a few characters ("5h", "7d"); one whose length is not known says its label. */
169
+ export function windowTag(m) {
170
+ const ms = Number(m && m.windowMs);
171
+ if (!(ms > 0)) return usageText(m.label, m.labelI18n);
172
+ const h = ms / 3_600_000;
173
+ return h < 48 ? tn("usageWindowHours", { n: Math.round(h) }) : tn("usageWindowDays", { n: Math.round(h / 24) });
174
+ }
175
+ /** A time ahead in one unit, for the narrow column: "45m", "3h", "4d" (rounded down past an hour; the tooltip is exact). */
176
+ function coarseDuration(ms) {
177
+ const min = Math.max(1, Math.ceil(ms / 60_000));
178
+ if (min < 60) return tn("usageWindowMinutes", { n: min });
179
+ const h = Math.floor(min / 60);
180
+ return h < 48 ? tn("usageWindowHours", { n: h }) : tn("usageWindowDays", { n: Math.floor(h / 24) });
181
+ }
182
+ /** The soonest reset still ahead among `metrics`: { short: "↻ 2h", full: "resets in 2h 5m" }, or null when none is known. */
183
+ export function soonestReset(metrics, now = Date.now()) {
184
+ const at = metrics.map((m) => new Date(m.resetsAt || "").getTime()).filter((t) => Number.isFinite(t) && t > now).sort((a, b) => a - b)[0];
185
+ return at === undefined ? null : { short: `↻ ${coarseDuration(at - now)}`, full: resetText(new Date(at).toISOString()) };
186
+ }
187
+ /**
188
+ * The logins grouped by provider for the compact view (nine logins, five of them Claude's: the provider once, then a
189
+ * line per login), in the order the person set (↑↓): a group where its first login is, its logins in their order.
190
+ */
191
+ export function compactGroups(providers) {
192
+ const groups = new Map();
193
+ providers.forEach((p, i) => {
194
+ const base = providerTitle(p).base;
195
+ if (!groups.has(base)) groups.set(base, { base, items: [] });
196
+ groups.get(base).items.push({ p, i });
197
+ });
198
+ return [...groups.values()];
199
+ }
200
+ const level = (pct) => (pct >= 90 ? "crit" : pct >= 70 ? "warn" : "");
201
+ /**
202
+ * #2240: an account whose percent windows come from several pools (agy: Gemini, Claude & others, Gemini 4 Argon) — each
203
+ * pool with its windows and the tighter one (the most used); null for an account of one pool (its 5h / 7d lines).
204
+ */
205
+ export function compactPools(p) {
206
+ const pct = ((p && p.metrics) || []).filter((m) => m && m.type === "percent" && !m.resetPassed);
207
+ const pools = new Map();
208
+ for (const m of pct) {
209
+ if (!m.pool || typeof m.pool.label !== "string") return null;
210
+ if (!pools.has(m.pool.label)) pools.set(m.pool.label, { pool: m.pool, metrics: [] });
211
+ pools.get(m.pool.label).metrics.push(m);
212
+ }
213
+ if (pools.size < 2) return null;
214
+ return [...pools.values()].map((x) => ({ ...x, worst: x.metrics.reduce((a, b) => ((b.used ?? 0) > (a.used ?? 0) ? b : a)) }));
215
+ }
216
+ const pctOf = (m) => Math.min(100, Math.max(0, m.used ?? 0));
217
+ /** When a window resets, at the clock ("14:05", "10/19 14:05"), for a tooltip; "" when unknown or already past. */
218
+ function resetClock(m, now = Date.now()) {
219
+ const at = new Date((m && m.resetsAt) || "").getTime();
220
+ return Number.isFinite(at) && at > now ? `↻ ${usageClock(m.resetsAt, now)}` : "";
221
+ }
222
+ /**
223
+ * One window on its own line: its few characters ("5h"), a full-width bar, the percent coloured as the full card, and
224
+ * when this window resets ("↻ 8m"; the user's ask, 2026-10-23: a week's reset was hidden behind the 5 h one's). A pool's
225
+ * line (#2240): the pool's name in place of the window, the reset of the window its percent is, every window (with its
226
+ * reset time) in the tooltip.
227
+ */
228
+ function CompactMeter({ m, tag, title }) {
229
+ const bar = useRef(null);
230
+ const pct = Math.min(100, Math.max(0, m.used ?? 0)), cls = level(pct);
231
+ useLayoutEffect(() => { if (bar.current) bar.current.style.width = `${pct}%`; }, [pct]); // CSSOM (#1300)
232
+ const word = cls === "crit" ? tn("usageNear") : cls === "warn" ? tn("usageHigh") : "";
233
+ const reset = soonestReset([m]), clock = resetClock(m);
234
+ return html`<span class="u-cm" title=${title || `${usageText(m.label, m.labelI18n)}: ${pct.toFixed(0)}%${word ? ` (${word})` : ""}${clock ? ` · ${clock}` : ""}`}>
235
+ <span class="u-cm-tag">${tag || windowTag(m)}</span><span class="u-cm-bar"><span ref=${bar} class=${`u-cm-fill ${cls}`}></span></span>
236
+ <span class=${`u-cm-pct ${cls}`}>${pct.toFixed(0)}%</span>
237
+ <span class="u-cm-reset">${reset ? html`${reset.short}<span class="sr-only"> (${reset.full})</span>` : null}</span></span>`;
238
+ }
239
+ /** What a login says instead of numbers (not logged in, an error), or "" when it has numbers. */
240
+ function rowNote(p) {
241
+ if (p.status === "error") return usageText(p.error || tn("usage.error_fallback"), p.errorI18n);
242
+ if (p.status === "no-credentials") return tn("usage.not_logged_in");
243
+ return "";
244
+ }
245
+ /**
246
+ * A login in three short lines, under its provider's name (the user's pick, 2026-10-22): its name and plan; then its
247
+ * short window and its long one, each a labelled full-width bar, the percent and that window's own reset.
248
+ * Numbers not current, a failed read or no login: one muted line in place of the bars, what is wrong as its tooltip.
249
+ * Pressed, it opens its full card.
250
+ */
251
+ export function CompactRow({ p, onExpand }) {
252
+ const title = providerTitle(p), failed = p.status === "error" || p.status === "no-credentials";
253
+ // Last known numbers (stale, e.g. an expired token) show as the others do (the user, 2026-10-23; the full card has since
254
+ // #2386), with a small "cached at 07:47" on the name line; a window that reset since is left out (compactSlots).
255
+ const pools = failed ? null : compactPools(p);
256
+ const metrics = failed ? [] : pools ? pools.flatMap((x) => x.metrics) : compactMetrics(p);
257
+ const note = rowNote(p), stale = p.stale ? staleNote(p) : null;
258
+ const say = stale ? stale.mark : note || tn("usage.no_data");
259
+ const detail = stale ? [stale.mark, stale.detail].filter(Boolean).join(" — ") : say;
260
+ const name = title.profile || title.base;
261
+ return html`<button type="button" class=${`u-crow${p.stale ? " is-stale" : ""}${pools ? " is-pooled" : ""}`} aria-expanded="false" title=${`${p.name} — ${tn("usageExpand")}`} onClick=${onExpand}>
262
+ <span class="u-crow-head"><span class="u-crow-name">${name}</span>
263
+ ${p.plan ? html`<span class="pill u-plan" title=${p.plan}><span aria-hidden="true">${planBadge(p.plan)}</span><span class="sr-only">${p.plan}</span></span>` : null}
264
+ ${stale && metrics.length ? html`<span class="u-crow-stale" title=${detail}>${p.cachedAt ? tn("usageCachedAt", { at: usageClock(p.cachedAt) }) : stale.mark}<span class="sr-only"> (${detail})</span></span>` : null}</span>
265
+ ${pools ? pools.map((x) => html`<${CompactMeter} key=${x.pool.label} m=${x.worst} tag=${usageText(x.pool.label, x.pool.labelI18n)}
266
+ title=${x.metrics.map((m) => { const c = resetClock(m); return `${usageText(m.label, m.labelI18n)}: ${pctOf(m).toFixed(0)}%${c ? ` (${c})` : ""}`; }).join(" · ")} />`)
267
+ : metrics.length ? metrics.map((m, j) => html`<${CompactMeter} key=${j} m=${m} />`)
268
+ : html`<span class=${`u-crow-note${(stale || (p.status === "error" && !p.transient)) ? " is-alert" : ""}`} title=${detail}>${say}</span>`}
269
+ </button>`;
270
+ }
271
+ /** A provider's logins: its name once (×N), in small capitals, then each login (or the full card of one opened). */
272
+ export function CompactGroup({ group, line }) {
273
+ return html`<section class="u-cgroup">
274
+ <div class="u-cg-head"><span class="u-cg-name" title=${group.base}>${group.base}</span>${group.items.length > 1 ? html`<span class="u-cg-count">×${group.items.length}</span>` : null}</div>
275
+ ${group.items.map(line)}
276
+ </section>`;
277
+ }
278
+
98
279
  /**
99
280
  * The usage read and its rows: the dialog's body and the rail's (#1673). `owner`: its lease's key — the reads and the
100
281
  * minute's timer live and end with it.
101
282
  */
102
283
  export function UsageBody({ owner }) {
103
284
  const lease = useLease(owner);
104
- const [data, setData] = useState(undefined); // undefined: loading; null: failed
285
+ const [data, setData] = useState(undefined); // undefined: loading; null: failed, with nothing read before
286
+ // The last read failed while numbers were already shown: they stay, with a quiet note (#2236/#2289 for the server's
287
+ // rows; here for the read itself — a dropped or failed read must not flash the error over numbers already on screen).
288
+ const [failed, setFailed] = useState(false);
105
289
  const [order, setOrder] = useState(() => { try { const a = JSON.parse(stored(USAGE_ORDER_KEY) || "[]"); return Array.isArray(a) ? a.filter((x) => typeof x === "string") : []; } catch { return []; } });
106
290
  const reads = useMemo(() => readStream(lease), [lease]);
291
+ // Compact (one line per login): a line pressed opens its full card here, until folded or the mode changes.
292
+ const { compact } = useStore(usageViewStore);
293
+ const [expanded, setExpanded] = useState(() => new Set());
294
+ useEffect(() => { setExpanded(new Set()); }, [compact]);
295
+ const toggleOne = (id) => setExpanded((was) => { const next = new Set(was); if (next.has(id)) next.delete(id); else next.add(id); return next; });
107
296
  // Refresh (force) supersedes a read on its way; the minute's tick waits for it.
108
297
  const load = async (force) => {
109
298
  const token = reads.begin(force);
@@ -111,19 +300,26 @@ export function UsageBody({ owner }) {
111
300
  try {
112
301
  const r = await lease.fetch(`/api/ai-usage${force ? "?force=1" : ""}`);
113
302
  if (!reads.live(token)) return;
303
+ // A refused or failed answer (a 500, a proxy's 502 page, a session that lapsed) is a failed read, not numbers.
304
+ if (!r.ok) throw new Error(`HTTP ${r.status}`);
114
305
  const d = await r.json();
115
- if (reads.live(token)) setData(d);
116
- } catch { if (reads.live(token)) setData(null); }
306
+ if (!d || !Array.isArray(d.providers)) throw new Error("no providers");
307
+ if (reads.live(token)) { setData(d); setFailed(false); }
308
+ } catch {
309
+ if (!reads.live(token)) return;
310
+ setData((had) => (had && Array.isArray(had.providers) ? had : null)); // the last numbers stay; none: the error
311
+ setFailed(true);
312
+ }
117
313
  finally { reads.end(token); }
118
314
  };
119
315
  useEffect(() => { load(false); lease.interval(() => load(false), 60_000); }, [lease]);
120
316
  // #1585: the server answered with the last snapshot while it fetches a fresh one — read again shortly (the same
121
317
  // cache: no vendor call of its own) so the fresh numbers replace it without waiting for the minute's tick.
122
318
  useEffect(() => {
123
- if (!data || !data.refreshing) return undefined;
319
+ if (!data || !data.refreshing || failed) return undefined;
124
320
  const timer = setTimeout(() => load(false), 4_000);
125
321
  return () => clearTimeout(timer);
126
- }, [data]);
322
+ }, [data, failed]);
127
323
  const key = (p) => String(p.id || p.name || "");
128
324
  const ordered = (providers) => {
129
325
  const rank = new Map(order.map((id, i) => [id, i]));
@@ -144,22 +340,26 @@ export function UsageBody({ owner }) {
144
340
  else if (!data || !Array.isArray(data.providers)) content = html`<${ErrorState} message=${tn("usageFail")} onRetry=${() => load(true)} />`;
145
341
  else {
146
342
  const providers = ordered(data.providers);
147
- content = html`${!providers.length ? html`<p class="note">${tn("usage.empty_active")}</p>` : null}
148
- ${providers.map((p, i) => html`<section key=${key(p)} class="u-provider">
343
+ const card = (p, i) => html`<section key=${key(p)} class=${p.stale ? "u-provider is-stale" : "u-provider"}>
149
344
  <div class="u-head"><strong title=${p.name}>${providerTitle(p).base}</strong>${p.plan ? html`<span class="pill u-plan" title=${p.plan}><span aria-hidden="true">${planBadge(p.plan)}</span><span class="sr-only">${p.plan}</span></span>` : null}
150
- <span class="u-order">
345
+ <span class="u-order">${compact ? html`<button type="button" class="icon-btn u-collapse" aria-expanded="true" aria-label=${tn("usageCollapse")} title=${tn("usageCollapse")}
346
+ onClick=${() => toggleOne(key(p))}><${Icon} name="minus" size=${14} /></button>` : null}
151
347
  <button type="button" class="icon-btn" disabled=${i === 0} aria-label=${tn("usageMoveUp")} title=${tn("usageMoveUp")} onClick=${() => move(key(p), -1, data.providers)}><${Icon} name="up" size=${14} /></button>
152
348
  <button type="button" class="icon-btn" disabled=${i === providers.length - 1} aria-label=${tn("usageMoveDown")} title=${tn("usageMoveDown")} onClick=${() => move(key(p), 1, data.providers)}><${Icon} name="down" size=${14} /></button>
153
349
  </span></div>
154
350
  ${providerTitle(p).profile ? html`<div class="u-profile" title=${p.name}>${providerTitle(p).profile}</div>` : null}
155
- ${p.stale ? html`<p class="note">${usageText(p.hint || "", p.hintI18n)}</p>` : null}
351
+ ${p.stale ? html`<p class="note u-stale" title=${staleNote(p).detail || null}>${staleNote(p).mark}</p>${staleNote(p).detail ? html`<p class="note u-stale-detail">${staleNote(p).detail}</p>` : null}` : null}
156
352
  ${p.status === "error" && !p.transient ? html`<p class="u-err">${usageText(p.error || tn("usage.error_fallback"), p.errorI18n)}</p>`
157
353
  : p.status === "error" && p.transient ? html`<p class="note">${usageText(p.error || tn("usage.error_fallback"), p.errorI18n)}</p>`
158
354
  : p.status === "no-credentials" ? html`<p class="note">${tn("usage.not_logged_in")}</p>${p.hint ? html`<p class="note">${usageText(p.hint, p.hintI18n)}</p>` : null}`
159
355
  : html`${(p.metrics || []).map((m, j) => html`<${UsageMetric} key=${j} m=${m} />`)}
160
356
  ${!p.stale && p.hint ? html`<p class="note">${usageText(p.hint, p.hintI18n)}</p>` : !(p.metrics || []).length ? html`<p class="note">${tn("usage.no_data")}</p>` : null}`}
161
- </section>`)}
162
- <div class="u-foot"><span class="note" title=${new Date(data.fetchedAt).toLocaleString()}>${updatedAgo(data.fetchedAt)}${data.refreshing ? html` · <span class="u-refreshing">${tn("usageRefreshing")}</span>` : null}</span>
357
+ </section>`;
358
+ content = html`${!providers.length ? html`<p class="note">${tn("usage.empty_active")}</p>` : null}
359
+ ${compact ? compactGroups(providers).map((g) => html`<${CompactGroup} key=${g.base} group=${g}
360
+ line=${({ p, i }) => (expanded.has(key(p)) ? card(p, i) : html`<${CompactRow} key=${key(p)} p=${p} onExpand=${() => toggleOne(key(p))} />`)} />`)
361
+ : providers.map((p, i) => card(p, i))}
362
+ <div class="u-foot"><span class="note" title=${new Date(data.fetchedAt).toLocaleString()}>${updatedAgo(data.fetchedAt)}${failed ? html` · <span class="u-refresh-failed" role="status">${tn("usageRefreshFailed")}</span>` : data.refreshing ? html` · <span class="u-refreshing">${tn("usageRefreshing")}</span>` : null}</span>
163
363
  ${byAgent() ? html`<a class="btn btn-ghost btn-sm u-by-agent" href="/ui/fleet/usage" title=${tn("usageByAgentTitle")}>${tn("usageByAgent")}</a>` : null}
164
364
  <button type="button" class="btn btn-sm" onClick=${() => load(true)}>${tn("usageRefresh")}</button></div>`;
165
365
  }
@@ -174,5 +374,5 @@ const byAgent = () => !guestPage() && typeof location !== "undefined" && locatio
174
374
 
175
375
  /** `owner`: the navigation that opened it — its reads and the minute's timer live and end with it. */
176
376
  export function UsageDialog({ onClose, owner = "" }) {
177
- return html`<${Dialog} title=${tn("usage.title")} onClose=${onClose} wide=${true}><${UsageBody} owner=${`usage-dialog:${owner}`} /></${Dialog}>`;
377
+ return html`<${Dialog} title=${tn("usage.title")} tools=${html`<${UsageCompactToggle} />`} onClose=${onClose} wide=${true}><${UsageBody} owner=${`usage-dialog:${owner}`} /></${Dialog}>`;
178
378
  }
@@ -37,6 +37,7 @@ register("view", {
37
37
  "usageUpdatedAgo": "Updated {age} ago",
38
38
  "usageUpdatedJustNow": "Updated just now",
39
39
  "usageRefreshing": "Refreshing…",
40
+ "usageRefreshFailed": "Couldn't refresh — showing the last numbers",
40
41
  "usageMinutes": "{n} min",
41
42
  "usageHours": "{n} h",
42
43
  "usageRefresh": "Refresh",
@@ -46,6 +47,17 @@ register("view", {
46
47
  "usageNear": "near limit",
47
48
  "usageMoveUp": "Move up",
48
49
  "usageMoveDown": "Move down",
50
+ "usageCompact": "Compact",
51
+ "usageCompactTitle": "One line per login",
52
+ "usageFull": "Full",
53
+ "usageFullTitle": "The full card for each login",
54
+ "usageExpand": "Show the full card",
55
+ "usageCachedAt": "cached at {at}",
56
+ "usageCollapse": "Back to one line",
57
+ "usageWindowHours": "{n}h",
58
+ "usageWindowDays": "{n}d",
59
+ "usageWindowMinutes": "{n}m",
60
+ "usageStaleMark": "Not current",
49
61
  "tooltipBackend": "Backend: {value}",
50
62
  "tooltipStatus": "Status: {value}",
51
63
  "tooltipContext": "Context: {value}",
@@ -61,6 +73,8 @@ register("view", {
61
73
  "modelWhyStart": "detected when it starts",
62
74
  "modelWhyCli": "this CLI does not report a default",
63
75
  "groupOther": "Other",
76
+ "groupTeam": "Team",
77
+ "groupTag": "Tag",
64
78
  "statusRunning": "Running",
65
79
  "statusPaused": "Paused",
66
80
  "statusStopped": "Stopped",
@@ -73,6 +87,7 @@ register("view", {
73
87
  "usage.title_plain": "AI subscription usage",
74
88
  "usage.empty_active": "No active backends with usage tracking",
75
89
  "usage.not_logged_in": "not logged in",
90
+ "usage.default_login": "default",
76
91
  "usage.error_fallback": "error",
77
92
  "usage.no_data": "no data",
78
93
  "usage.reset.in": "resets in {0}",
@@ -135,6 +150,10 @@ register("view", {
135
150
  "usage.error.rate_limited": "Rate limited by {0} — try again later.",
136
151
  "usage.error.rate_limited_transient": "{0}: can't fetch usage right now (rate limited). This does not affect your agents.",
137
152
  "usage.stale_rate_limited": "data from {0} min ago — can't refresh right now",
153
+ "usage.stale.expired": "expired · cached at {0}",
154
+ "usage.stale.transient": "not updated · cached at {0}",
155
+ "usage.stale.error": "couldn't read · cached at {0}",
156
+ "usage.metric.reset_since": "reset since {0}",
138
157
  "usage.error.http": "Usage request failed (HTTP {0}).",
139
158
  "usage.error.billing_http": "Billing request failed (HTTP {0}).",
140
159
  "usage.error.invalid_response": "Invalid response from usage endpoint.",
@@ -157,7 +176,6 @@ register("view", {
157
176
  "usageButton": "Usage",
158
177
  "helpButton": "Help",
159
178
  "close": "Close",
160
- "expandProfile": "Show the profile",
161
179
  "rosterFailed": "Failed to load roster: {error}\n(Is the fleet running?)",
162
180
  "paneFailed": "⚠ Could not load pane for {name} (HTTP {status}).",
163
181
  "signInToSave": "Sign in to save — your session may have ended.",
@@ -200,7 +218,6 @@ register("view", {
200
218
  "textSize": "Text size: {size}",
201
219
  "profileTitle": "Edit {name}'s profile",
202
220
  "avatar": "Avatar",
203
- "collapseProfile": "Hide the profile",
204
221
  "instancesLabel": "Instances",
205
222
  "favorites": "Favorites",
206
223
  "favAdd": "Add {name} to favorites",
@@ -211,6 +228,22 @@ register("view", {
211
228
  "favDown": "Move {name} down",
212
229
  "favFull": "Favorites are full ({max})",
213
230
  "favFiltered": "Clear the filter to reorder favorites",
231
+ "favSorted": "Favorites are sorted by last reply — set them back to your order to move them",
232
+ "replyJustNow": "just now",
233
+ "replyMinutes": "{n} min ago",
234
+ "replyHours": "{n} h ago",
235
+ "replyYesterday": "yesterday",
236
+ "replyDays": "{n} d ago",
237
+ "replyTitle": "Last replied: {time}",
238
+ "sortTitle": "Sort the list",
239
+ "sortCustom": "Custom",
240
+ "sortCustomHint": "Your own order (drag rows); replies never move them",
241
+ "sortRecent": "Recent replies",
242
+ "sortRecentHint": "No groups: the last reply first",
243
+ "sortFavs": "Favorites, in Recent replies",
244
+ "sortFavsFixed": "Pinned on top, in your order",
245
+ "sortFavsRecent": "Sorted by last reply too",
246
+ "recentOthers": "Recent replies first",
214
247
  "pinnedCurrent": "Current",
215
248
  "pinnedLabel": "The instance you have open"
216
249
  },
@@ -247,6 +280,7 @@ register("view", {
247
280
  "usageUpdatedAgo": "{age}前更新",
248
281
  "usageUpdatedJustNow": "剛剛更新",
249
282
  "usageRefreshing": "更新中…",
283
+ "usageRefreshFailed": "無法更新,顯示上次的數據",
250
284
  "usageMinutes": "{n} 分鐘",
251
285
  "usageHours": "{n} 小時",
252
286
  "usageRefresh": "重新整理",
@@ -256,6 +290,17 @@ register("view", {
256
290
  "usageNear": "接近上限",
257
291
  "usageMoveUp": "上移",
258
292
  "usageMoveDown": "下移",
293
+ "usageCompact": "精簡",
294
+ "usageCompactTitle": "每個登入一行",
295
+ "usageFull": "完整",
296
+ "usageFullTitle": "每個登入顯示完整卡片",
297
+ "usageExpand": "顯示完整卡片",
298
+ "usageCachedAt": "快取於 {at}",
299
+ "usageCollapse": "收回成一行",
300
+ "usageWindowHours": "{n}小時",
301
+ "usageWindowDays": "{n}天",
302
+ "usageWindowMinutes": "{n}分",
303
+ "usageStaleMark": "不是最新",
259
304
  "tooltipBackend": "後端:{value}",
260
305
  "tooltipStatus": "狀態:{value}",
261
306
  "tooltipContext": "上下文:{value}",
@@ -271,6 +316,8 @@ register("view", {
271
316
  "modelWhyStart": "啟動時偵測",
272
317
  "modelWhyCli": "這個 CLI 不提供預設值",
273
318
  "groupOther": "其他",
319
+ "groupTeam": "團隊",
320
+ "groupTag": "標籤",
274
321
  "statusRunning": "運行中",
275
322
  "statusPaused": "已暫停",
276
323
  "statusStopped": "已停止",
@@ -283,6 +330,7 @@ register("view", {
283
330
  "usage.title_plain": "AI 訂閱用量",
284
331
  "usage.empty_active": "沒有使用中且支援用量追蹤的 Backend",
285
332
  "usage.not_logged_in": "未登入",
333
+ "usage.default_login": "預設",
286
334
  "usage.error_fallback": "錯誤",
287
335
  "usage.no_data": "無資料",
288
336
  "usage.reset.in": "{0} 後重置",
@@ -345,6 +393,10 @@ register("view", {
345
393
  "usage.error.rate_limited": "{0} 暫時限制請求速率,請稍後再試。",
346
394
  "usage.error.rate_limited_transient": "暫時查不到 {0} 用量({0} 限制查詢頻率),不影響你的 agent。",
347
395
  "usage.stale_rate_limited": "{0} 分鐘前的資料,暫時無法更新",
396
+ "usage.stale.expired": "已過期 · 快取於 {0}",
397
+ "usage.stale.transient": "暫時無法更新 · 快取於 {0}",
398
+ "usage.stale.error": "讀取失敗 · 快取於 {0}",
399
+ "usage.metric.reset_since": "已於 {0} 重置",
348
400
  "usage.error.http": "用量請求失敗(HTTP {0})。",
349
401
  "usage.error.billing_http": "計費請求失敗(HTTP {0})。",
350
402
  "usage.error.invalid_response": "用量端點回傳了無效資料。",
@@ -367,7 +419,6 @@ register("view", {
367
419
  "usageButton": "用量",
368
420
  "helpButton": "說明",
369
421
  "close": "關閉",
370
- "expandProfile": "顯示個人資料",
371
422
  "rosterFailed": "載入 instance 清單失敗:{error}\n(Fleet 是否正在執行?)",
372
423
  "paneFailed": "⚠ 無法載入 {name} 的 pane(HTTP {status})。",
373
424
  "signInToSave": "請先登入才能儲存:你的 session 可能已結束。",
@@ -410,7 +461,6 @@ register("view", {
410
461
  "textSize": "字級:{size}",
411
462
  "profileTitle": "編輯 {name} 的個人資料",
412
463
  "avatar": "頭像",
413
- "collapseProfile": "隱藏個人資料",
414
464
  "instancesLabel": "Instances",
415
465
  "favorites": "最愛",
416
466
  "favAdd": "把 {name} 加入最愛",
@@ -421,6 +471,22 @@ register("view", {
421
471
  "favDown": "把 {name} 下移",
422
472
  "favFull": "最愛已滿({max} 個)",
423
473
  "favFiltered": "清除篩選後才能調整最愛順序",
474
+ "favSorted": "最愛目前依最近回覆排序;改回「照你的順序」才能移動",
475
+ "replyJustNow": "剛剛",
476
+ "replyMinutes": "{n} 分鐘前",
477
+ "replyHours": "{n} 小時前",
478
+ "replyYesterday": "昨天",
479
+ "replyDays": "{n} 天前",
480
+ "replyTitle": "最後回覆:{time}",
481
+ "sortTitle": "排序方式",
482
+ "sortCustom": "自訂",
483
+ "sortCustomHint": "你拖曳排好的順序,有回覆也不會跳動",
484
+ "sortRecent": "最近回覆",
485
+ "sortRecentHint": "不分組,最後回覆的在上面",
486
+ "sortFavs": "最愛(最近回覆模式時)",
487
+ "sortFavsFixed": "固定在最上面,照你的順序",
488
+ "sortFavsRecent": "也依最近回覆排序",
489
+ "recentOthers": "最近回覆在上",
424
490
  "pinnedCurrent": "目前",
425
491
  "pinnedLabel": "你目前開著的 instance"
426
492
  }
@@ -20,6 +20,7 @@ register("webauth", {
20
20
  reason_not_admin_session: "Guests can't authorize.",
21
21
  reason_token_rotated: "The dashboard's token changed: sign in again.",
22
22
  reason_public_link: "Not on the temporary public link.",
23
+ reason_named_link_off: "Over your named link: turn on \"Also over my named link\" in Settings → Web on this computer.",
23
24
  reason_not_session: "Sign in to authorize.",
24
25
  reason_other: "This browser can't be authorized here.",
25
26
  refusal_pending: "A request is already waiting in your DM.",
@@ -27,6 +28,10 @@ register("webauth", {
27
28
  refusal_dm_unavailable: "Couldn't send you a DM. Open your DMs with the bot, then try again.",
28
29
  refusal_other: "That didn't work: {0}",
29
30
  settings: "Settings",
31
+ verifiedShort: "Verified",
32
+ authorizeShort: "Authorize",
33
+ authorizeWhy: "Not verified: authorize this browser to speak as you",
34
+ waitingShort: "Waiting for your Confirm ({0})",
30
35
  },
31
36
  "zh-TW": {
32
37
  verified: "已驗證 · 以你的身分發言到 {0}",
@@ -42,6 +47,7 @@ register("webauth", {
42
47
  reason_not_admin_session: "訪客無法授權。",
43
48
  reason_token_rotated: "儀表板的 token 已變更:請重新登入。",
44
49
  reason_public_link: "臨時公開連結上無法授權。",
50
+ reason_named_link_off: "透過固定網域:請在這台電腦的 設定 → 網頁 開啟「也允許透過我的固定網域」。",
45
51
  reason_not_session: "登入後才能授權。",
46
52
  reason_other: "這個瀏覽器在這裡無法授權。",
47
53
  refusal_pending: "已經有一個請求在你的私訊中等待。",
@@ -49,10 +55,14 @@ register("webauth", {
49
55
  refusal_dm_unavailable: "無法私訊給你。請開放與 bot 的私訊後再試一次。",
50
56
  refusal_other: "沒有成功:{0}",
51
57
  settings: "設定",
58
+ verifiedShort: "已驗證",
59
+ authorizeShort: "授權",
60
+ authorizeWhy: "未驗證:授權這個瀏覽器以你的身分發言",
61
+ waitingShort: "等待確認({0})",
52
62
  },
53
63
  });
54
64
  const tn = (k, ...v) => t(`webauth.${k}`, ...v);
55
- const REASONS = ["disabled", "loopback_only", "no_account", "not_admin", "not_admin_session", "token_rotated", "public_link", "not_session"];
65
+ const REASONS = ["disabled", "loopback_only", "no_account", "not_admin", "not_admin_session", "token_rotated", "public_link", "named_link_off", "not_session"];
56
66
  // Until when: the time, with the day when it isn't today (an authorization lasts up to 48 h).
57
67
  const clock = (ms) => {
58
68
  const d = new Date(ms), today = new Date().toDateString() === d.toDateString();
@@ -139,6 +149,45 @@ export function AuthorizeChip() {
139
149
  return html`<div class="webauth-chip" data-state=${a.st.state}>${body(a)}${a.notice ? html` <span class="note" role="status">${a.notice}</span>` : null}</div>`;
140
150
  }
141
151
 
152
+ /**
153
+ * The composer's row (#2215, the user's request, 2026-10-19): the same states as AuthorizeChip, each kept to a few words so
154
+ * they share one row with the key hint. What a state would have said at length is in its tooltip and its accessible
155
+ * name: when "Verified" ends, why it can't be authorized, the countdown's ask. A tap on "✓ Verified" shows when it
156
+ * ends (touch has no hover) in a bubble above the row, until the next tap, a tap elsewhere or Escape. What pressing
157
+ * Authorize answered (sent, refused) is said in the row itself, in the hint's place (#2216 review: a bubble left over the
158
+ * composer covered Attach and what was being typed, with nothing to close it).
159
+ */
160
+ export function ComposerAuth() {
161
+ const a = useWebAuthorization();
162
+ const [open, setOpen] = useState(false);
163
+ const tip = useRef("wa-tip-" + Math.random().toString(36).slice(2, 8));
164
+ useEffect(() => { setOpen(false); }, [a.st && a.st.state]); // a new state closes the bubble
165
+ if (guestPage()) return null;
166
+ if (publicLink()) return html`<span class="webauth-row note" data-state="public" title=${tn("publicLink")}>${tn("publicLink")}</span>`;
167
+ if (!a.st) return null;
168
+ const st = a.st, id = tip.current;
169
+ const said = a.notice ? html`<span class="webauth-notice" role="status">${a.notice}</span>` : null;
170
+ if (st.state === "verified") {
171
+ const until = tn("verified", clock(st.until));
172
+ return html`<span class="webauth-row" data-state="verified">
173
+ <button type="button" class="webauth-ok" title=${until} aria-label=${`✓ ${until}`} aria-expanded=${open ? "true" : "false"}
174
+ aria-controls=${id} onClick=${() => setOpen((v) => !v)} onBlur=${() => setOpen(false)}
175
+ onKeyDown=${(e) => { if (e.key === "Escape" && open) { e.stopPropagation(); setOpen(false); } }}>✓ ${tn("verifiedShort")}</button><span
176
+ id=${id} class="webauth-tip" role="tooltip" hidden=${!open}>${until}</span>${said}</span>`;
177
+ }
178
+ if (st.state === "pending") {
179
+ const asks = tn("waiting", mmss(a.left));
180
+ return html`<span class="webauth-row" data-state="pending"><span class="note" title=${a.notice ? `${asks} — ${a.notice}` : asks}>${tn("waitingShort", mmss(a.left))}</span>${said}</span>`;
181
+ }
182
+ if (st.reason === "not_authorized" || st.reason === "authorization_expired") {
183
+ return html`<span class="webauth-row" data-state="none"><span class="note" aria-hidden="true">${tn("notVerified")} ·</span><button type="button" class="webauth-ask"
184
+ title=${tn("authorizeWhy")} aria-label=${tn("authorizeWhy")} onClick=${a.ask}>${tn("authorizeShort")}</button>${said}</span>`;
185
+ }
186
+ const why = REASONS.includes(st.reason) ? tn(`reason_${st.reason}`) : tn("reason_other");
187
+ return html`<span class="webauth-row" data-state="none"><span class="note" title=${why}>${tn("notVerified")}<span class="sr-only">: ${why}</span></span>${st.reason === "disabled" || st.reason === "loopback_only"
188
+ ? html` · <a href="/settings/web" title=${why}>${tn("settings")}</a>` : null}</span>`;
189
+ }
190
+
142
191
  function body(a) {
143
192
  const st = a.st;
144
193
  if (st.state === "verified") return html`<span class="webauth-ok">✓ ${tn("verified", clock(st.until))}</span>`;
@@ -6,9 +6,11 @@
6
6
  <meta name="referrer" content="no-referrer">
7
7
  <meta name="robots" content="noindex">
8
8
  <title>AgEnD — Sign in</title>
9
+ <!--app-icon-->
9
10
  <link rel="icon" href="/favicon.ico" sizes="16x16 32x32 64x64">
10
11
  <link rel="icon" href="/favicon.svg" type="image/svg+xml" sizes="any">
11
12
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
13
+ <!--/app-icon-->
12
14
  <script src="/assets/theme.js"></script>
13
15
  <link rel="stylesheet" href="/assets/tokens.css">
14
16
  <style>