@songsid/agend 2.1.12 → 2.2.0-alpha.2

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 (436) hide show
  1. package/README.md +4 -2
  2. package/README.zh-TW.md +4 -2
  3. package/dist/agent-cli.js +6 -1
  4. package/dist/agent-cli.js.map +1 -1
  5. package/dist/agent-endpoint.js +68 -12
  6. package/dist/agent-endpoint.js.map +1 -1
  7. package/dist/agent-token-header.d.ts +13 -0
  8. package/dist/agent-token-header.js +16 -0
  9. package/dist/agent-token-header.js.map +1 -0
  10. package/dist/auth/one-time-code.d.ts +19 -0
  11. package/dist/auth/one-time-code.js +49 -0
  12. package/dist/auth/one-time-code.js.map +1 -0
  13. package/dist/auth-api.d.ts +52 -0
  14. package/dist/auth-api.js +346 -0
  15. package/dist/auth-api.js.map +1 -0
  16. package/dist/backend/antigravity.js +4 -3
  17. package/dist/backend/antigravity.js.map +1 -1
  18. package/dist/backend/claude-code.d.ts +4 -0
  19. package/dist/backend/claude-code.js +97 -0
  20. package/dist/backend/claude-code.js.map +1 -1
  21. package/dist/backend/codex.js +59 -30
  22. package/dist/backend/codex.js.map +1 -1
  23. package/dist/backend/grok.js +1 -1
  24. package/dist/backend/grok.js.map +1 -1
  25. package/dist/backend/kiro-agent.d.ts +66 -0
  26. package/dist/backend/kiro-agent.js +302 -0
  27. package/dist/backend/kiro-agent.js.map +1 -0
  28. package/dist/backend/kiro-identity.d.ts +80 -0
  29. package/dist/backend/kiro-identity.js +537 -0
  30. package/dist/backend/kiro-identity.js.map +1 -0
  31. package/dist/backend/kiro-v2-store-worker.d.ts +1 -0
  32. package/dist/backend/kiro-v2-store-worker.js +87 -0
  33. package/dist/backend/kiro-v2-store-worker.js.map +1 -0
  34. package/dist/backend/kiro-v2-store.d.ts +54 -0
  35. package/dist/backend/kiro-v2-store.js +131 -0
  36. package/dist/backend/kiro-v2-store.js.map +1 -0
  37. package/dist/backend/kiro-v3-identity.d.ts +5 -0
  38. package/dist/backend/kiro-v3-identity.js +22 -0
  39. package/dist/backend/kiro-v3-identity.js.map +1 -1
  40. package/dist/backend/kiro.d.ts +90 -7
  41. package/dist/backend/kiro.js +500 -124
  42. package/dist/backend/kiro.js.map +1 -1
  43. package/dist/backend/muse.js +1 -1
  44. package/dist/backend/muse.js.map +1 -1
  45. package/dist/backend/types.d.ts +51 -3
  46. package/dist/backend/types.js.map +1 -1
  47. package/dist/cache-analysis.d.ts +92 -0
  48. package/dist/cache-analysis.js +147 -0
  49. package/dist/cache-analysis.js.map +1 -0
  50. package/dist/cache-ledger.d.ts +108 -0
  51. package/dist/cache-ledger.js +230 -0
  52. package/dist/cache-ledger.js.map +1 -0
  53. package/dist/cache-prices.d.ts +32 -0
  54. package/dist/cache-prices.js +73 -0
  55. package/dist/cache-prices.js.map +1 -0
  56. package/dist/cache-scan.d.ts +39 -0
  57. package/dist/cache-scan.js +115 -0
  58. package/dist/cache-scan.js.map +1 -0
  59. package/dist/cache-service.d.ts +115 -0
  60. package/dist/cache-service.js +417 -0
  61. package/dist/cache-service.js.map +1 -0
  62. package/dist/channel/adapters/discord.d.ts +1 -0
  63. package/dist/channel/adapters/discord.js +29 -10
  64. package/dist/channel/adapters/discord.js.map +1 -1
  65. package/dist/channel/adapters/telegram.d.ts +1 -0
  66. package/dist/channel/adapters/telegram.js +13 -1
  67. package/dist/channel/adapters/telegram.js.map +1 -1
  68. package/dist/channel/types.d.ts +9 -1
  69. package/dist/classic-channel-manager.d.ts +18 -10
  70. package/dist/classic-channel-manager.js +45 -18
  71. package/dist/classic-channel-manager.js.map +1 -1
  72. package/dist/cli-entry.d.ts +19 -0
  73. package/dist/cli-entry.js +36 -0
  74. package/dist/cli-entry.js.map +1 -0
  75. package/dist/cli.js +471 -146
  76. package/dist/cli.js.map +1 -1
  77. package/dist/command-table.d.ts +5 -3
  78. package/dist/command-table.js +29 -27
  79. package/dist/command-table.js.map +1 -1
  80. package/dist/config-validator.js +46 -0
  81. package/dist/config-validator.js.map +1 -1
  82. package/dist/config.js +12 -0
  83. package/dist/config.js.map +1 -1
  84. package/dist/connection-secrets.d.ts +6 -0
  85. package/dist/connection-secrets.js +4 -0
  86. package/dist/connection-secrets.js.map +1 -1
  87. package/dist/daemon.d.ts +95 -4
  88. package/dist/daemon.js +748 -111
  89. package/dist/daemon.js.map +1 -1
  90. package/dist/darwin-memory.d.ts +6 -1
  91. package/dist/darwin-memory.js +17 -6
  92. package/dist/darwin-memory.js.map +1 -1
  93. package/dist/delivery-consumed-watch.d.ts +85 -0
  94. package/dist/delivery-consumed-watch.js +244 -0
  95. package/dist/delivery-consumed-watch.js.map +1 -0
  96. package/dist/delivery-outbox.d.ts +61 -0
  97. package/dist/delivery-outbox.js +120 -2
  98. package/dist/delivery-outbox.js.map +1 -1
  99. package/dist/delivery-reconciliation.d.ts +14 -5
  100. package/dist/delivery-reconciliation.js +27 -4
  101. package/dist/delivery-reconciliation.js.map +1 -1
  102. package/dist/delivery-reconciliation.test.js +35 -1
  103. package/dist/delivery-reconciliation.test.js.map +1 -1
  104. package/dist/event-log.d.ts +4 -1
  105. package/dist/event-log.js +6 -3
  106. package/dist/event-log.js.map +1 -1
  107. package/dist/event-loop-watch.d.ts +28 -0
  108. package/dist/event-loop-watch.js +75 -3
  109. package/dist/event-loop-watch.js.map +1 -1
  110. package/dist/fleet-context.d.ts +22 -2
  111. package/dist/fleet-control-audit.d.ts +5 -0
  112. package/dist/fleet-control-audit.js +7 -0
  113. package/dist/fleet-control-audit.js.map +1 -1
  114. package/dist/fleet-level-config.d.ts +2 -2
  115. package/dist/fleet-level-config.js +28 -1
  116. package/dist/fleet-level-config.js.map +1 -1
  117. package/dist/fleet-manager.d.ts +339 -12
  118. package/dist/fleet-manager.js +2623 -461
  119. package/dist/fleet-manager.js.map +1 -1
  120. package/dist/full-restart.js +2 -3
  121. package/dist/full-restart.js.map +1 -1
  122. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +3 -1
  123. package/dist/host-memory.d.ts +4 -0
  124. package/dist/host-memory.js.map +1 -1
  125. package/dist/install-lock.d.ts +49 -0
  126. package/dist/install-lock.js +200 -0
  127. package/dist/install-lock.js.map +1 -0
  128. package/dist/instance-config-impact.js +8 -2
  129. package/dist/instance-config-impact.js.map +1 -1
  130. package/dist/instance-lifecycle.d.ts +10 -5
  131. package/dist/instance-lifecycle.js +162 -53
  132. package/dist/instance-lifecycle.js.map +1 -1
  133. package/dist/locale.js +164 -16
  134. package/dist/locale.js.map +1 -1
  135. package/dist/login-controller.d.ts +2 -0
  136. package/dist/login-controller.js +17 -5
  137. package/dist/login-controller.js.map +1 -1
  138. package/dist/memory-pressure.d.ts +7 -8
  139. package/dist/memory-pressure.js +76 -15
  140. package/dist/memory-pressure.js.map +1 -1
  141. package/dist/monotonic-budget.d.ts +2 -0
  142. package/dist/monotonic-budget.js +28 -0
  143. package/dist/monotonic-budget.js.map +1 -0
  144. package/dist/needs-you-hub.d.ts +114 -0
  145. package/dist/needs-you-hub.js +370 -0
  146. package/dist/needs-you-hub.js.map +1 -0
  147. package/dist/needs-you-live.d.ts +116 -0
  148. package/dist/needs-you-live.js +228 -0
  149. package/dist/needs-you-live.js.map +1 -0
  150. package/dist/needs-you.d.ts +132 -0
  151. package/dist/needs-you.js +164 -0
  152. package/dist/needs-you.js.map +1 -0
  153. package/dist/node-version-guard.d.ts +30 -0
  154. package/dist/node-version-guard.js +50 -0
  155. package/dist/node-version-guard.js.map +1 -0
  156. package/dist/operator-control-paths.d.ts +4 -0
  157. package/dist/operator-control-paths.js +24 -0
  158. package/dist/operator-control-paths.js.map +1 -0
  159. package/dist/outbound-handlers.d.ts +2 -0
  160. package/dist/outbound-handlers.js +9 -2
  161. package/dist/outbound-handlers.js.map +1 -1
  162. package/dist/outbound-schemas.d.ts +5 -5
  163. package/dist/outbound-schemas.js +1 -1
  164. package/dist/outbound-schemas.js.map +1 -1
  165. package/dist/package-preimage.d.ts +26 -0
  166. package/dist/package-preimage.js +96 -0
  167. package/dist/package-preimage.js.map +1 -0
  168. package/dist/profile-control.js +4 -20
  169. package/dist/profile-control.js.map +1 -1
  170. package/dist/public-web-gateway.d.ts +18 -0
  171. package/dist/public-web-gateway.js +141 -0
  172. package/dist/public-web-gateway.js.map +1 -0
  173. package/dist/public-web-link.d.ts +53 -0
  174. package/dist/public-web-link.js +175 -0
  175. package/dist/public-web-link.js.map +1 -0
  176. package/dist/quickstart-api.d.ts +8 -1
  177. package/dist/quickstart-api.js +86 -48
  178. package/dist/quickstart-api.js.map +1 -1
  179. package/dist/quickstart.d.ts +1 -0
  180. package/dist/quickstart.js +16 -6
  181. package/dist/quickstart.js.map +1 -1
  182. package/dist/restart-guard.d.ts +52 -0
  183. package/dist/restart-guard.js +109 -0
  184. package/dist/restart-guard.js.map +1 -0
  185. package/dist/scheduler/db.d.ts +7 -1
  186. package/dist/scheduler/db.js +44 -2
  187. package/dist/scheduler/db.js.map +1 -1
  188. package/dist/scheduler/index.d.ts +1 -1
  189. package/dist/scheduler/retry-label.d.ts +11 -0
  190. package/dist/scheduler/retry-label.js +24 -0
  191. package/dist/scheduler/retry-label.js.map +1 -0
  192. package/dist/scheduler/scheduler.d.ts +55 -2
  193. package/dist/scheduler/scheduler.js +220 -8
  194. package/dist/scheduler/scheduler.js.map +1 -1
  195. package/dist/scheduler/types.d.ts +22 -0
  196. package/dist/scheduler/types.js.map +1 -1
  197. package/dist/secret-store.d.ts +5 -0
  198. package/dist/secret-store.js +20 -0
  199. package/dist/secret-store.js.map +1 -1
  200. package/dist/service-activation.d.ts +152 -0
  201. package/dist/service-activation.js +407 -0
  202. package/dist/service-activation.js.map +1 -0
  203. package/dist/service-installer.d.ts +63 -1
  204. package/dist/service-installer.js +141 -16
  205. package/dist/service-installer.js.map +1 -1
  206. package/dist/service-plan.d.ts +65 -0
  207. package/dist/service-plan.js +108 -0
  208. package/dist/service-plan.js.map +1 -0
  209. package/dist/service-restart-selection.d.ts +6 -5
  210. package/dist/service-restart-selection.js +6 -5
  211. package/dist/service-restart-selection.js.map +1 -1
  212. package/dist/settings-api.d.ts +10 -2
  213. package/dist/settings-api.js +216 -72
  214. package/dist/settings-api.js.map +1 -1
  215. package/dist/settings-baseline.d.ts +20 -0
  216. package/dist/settings-baseline.js +104 -0
  217. package/dist/settings-baseline.js.map +1 -0
  218. package/dist/settings-change.d.ts +21 -0
  219. package/dist/settings-change.js +161 -0
  220. package/dist/settings-change.js.map +1 -0
  221. package/dist/settings-confirmation.d.ts +105 -0
  222. package/dist/settings-confirmation.js +232 -0
  223. package/dist/settings-confirmation.js.map +1 -0
  224. package/dist/settings-control.d.ts +41 -0
  225. package/dist/settings-control.js +294 -0
  226. package/dist/settings-control.js.map +1 -0
  227. package/dist/settings-effect.d.ts +24 -0
  228. package/dist/settings-effect.js +169 -0
  229. package/dist/settings-effect.js.map +1 -0
  230. package/dist/settings-http-confirmation.d.ts +29 -0
  231. package/dist/settings-http-confirmation.js +123 -0
  232. package/dist/settings-http-confirmation.js.map +1 -0
  233. package/dist/settings-instance-patch.d.ts +4 -0
  234. package/dist/settings-instance-patch.js +26 -0
  235. package/dist/settings-instance-patch.js.map +1 -0
  236. package/dist/settings-request-capability.d.ts +16 -0
  237. package/dist/settings-request-capability.js +32 -0
  238. package/dist/settings-request-capability.js.map +1 -0
  239. package/dist/settings-transaction.d.ts +65 -0
  240. package/dist/settings-transaction.js +223 -0
  241. package/dist/settings-transaction.js.map +1 -0
  242. package/dist/setup-auth.d.ts +10 -18
  243. package/dist/setup-auth.js +14 -38
  244. package/dist/setup-auth.js.map +1 -1
  245. package/dist/setup-form.d.ts +1 -1
  246. package/dist/setup-form.js +75 -18
  247. package/dist/setup-form.js.map +1 -1
  248. package/dist/setup-guide.d.ts +13 -0
  249. package/dist/setup-guide.js +25 -0
  250. package/dist/setup-guide.js.map +1 -0
  251. package/dist/setup-host.d.ts +16 -0
  252. package/dist/setup-host.js +199 -35
  253. package/dist/setup-host.js.map +1 -1
  254. package/dist/setup-wizard.js +5 -1
  255. package/dist/setup-wizard.js.map +1 -1
  256. package/dist/slash-authz.d.ts +17 -3
  257. package/dist/slash-authz.js +5 -0
  258. package/dist/slash-authz.js.map +1 -1
  259. package/dist/spawn-gate.js +3 -3
  260. package/dist/spawn-gate.js.map +1 -1
  261. package/dist/sqlite-open-errors.d.ts +12 -0
  262. package/dist/sqlite-open-errors.js +13 -0
  263. package/dist/sqlite-open-errors.js.map +1 -0
  264. package/dist/statusline-watcher.d.ts +5 -0
  265. package/dist/statusline-watcher.js +2 -0
  266. package/dist/statusline-watcher.js.map +1 -1
  267. package/dist/steer-capability.d.ts +6 -0
  268. package/dist/steer-capability.js +8 -0
  269. package/dist/steer-capability.js.map +1 -1
  270. package/dist/sync-work-attribution.d.ts +14 -0
  271. package/dist/sync-work-attribution.js +43 -8
  272. package/dist/sync-work-attribution.js.map +1 -1
  273. package/dist/tips.js +10 -5
  274. package/dist/tips.js.map +1 -1
  275. package/dist/tmux-control.d.ts +57 -5
  276. package/dist/tmux-control.js +379 -61
  277. package/dist/tmux-control.js.map +1 -1
  278. package/dist/tmux-manager.d.ts +20 -6
  279. package/dist/tmux-manager.js +90 -47
  280. package/dist/tmux-manager.js.map +1 -1
  281. package/dist/tmux-read.d.ts +59 -0
  282. package/dist/tmux-read.js +213 -0
  283. package/dist/tmux-read.js.map +1 -0
  284. package/dist/topic-commands.d.ts +21 -10
  285. package/dist/topic-commands.js +205 -63
  286. package/dist/topic-commands.js.map +1 -1
  287. package/dist/transcript-delta-reader.js +2 -1
  288. package/dist/transcript-delta-reader.js.map +1 -1
  289. package/dist/tunnel/cloudflared-install.d.ts +2 -0
  290. package/dist/tunnel/cloudflared-install.js +1 -1
  291. package/dist/tunnel/cloudflared-install.js.map +1 -1
  292. package/dist/tunnel/purpose-lane.d.ts +14 -0
  293. package/dist/tunnel/purpose-lane.js +43 -0
  294. package/dist/tunnel/purpose-lane.js.map +1 -0
  295. package/dist/turn-reply-guard.d.ts +2 -0
  296. package/dist/turn-reply-guard.js +10 -1
  297. package/dist/turn-reply-guard.js.map +1 -1
  298. package/dist/types.d.ts +33 -0
  299. package/dist/ui/app.html +18 -0
  300. package/dist/ui/chat-commands.js +43 -0
  301. package/dist/ui/chat-render.js +478 -0
  302. package/dist/ui/chat-store.js +318 -0
  303. package/dist/ui/chat-strings.js +89 -0
  304. package/dist/ui/chat-thread.js +246 -0
  305. package/dist/ui/chat-tour.js +116 -0
  306. package/dist/ui/fleet-cache.js +168 -0
  307. package/dist/ui/fleet-org.js +142 -0
  308. package/dist/ui/panel-chat.js +504 -0
  309. package/dist/ui/panel-fleet.js +427 -0
  310. package/dist/ui/panel-needs.js +202 -0
  311. package/dist/ui/panel-settings.js +754 -0
  312. package/dist/ui/preview-panel.js +202 -0
  313. package/dist/ui/preview.js +270 -0
  314. package/dist/ui/settings-apply.js +239 -0
  315. package/dist/ui/settings-confirm.js +186 -0
  316. package/dist/ui/settings-dialogs.js +546 -0
  317. package/dist/ui/settings-model.js +277 -0
  318. package/dist/ui/settings-strings.js +654 -0
  319. package/dist/ui/settings-wizard.js +140 -0
  320. package/dist/ui/shared/agend-auth.js +93 -0
  321. package/dist/ui/shared/app-ctx.js +80 -0
  322. package/dist/ui/shared/app-html.js +9 -0
  323. package/dist/ui/shared/app-i18n.js +95 -0
  324. package/dist/ui/shared/app-nav.js +73 -0
  325. package/dist/ui/shared/app-needs.js +114 -0
  326. package/dist/ui/shared/app-route.js +73 -0
  327. package/dist/ui/shared/app-session.js +66 -0
  328. package/dist/ui/shared/app-shell.js +346 -0
  329. package/dist/ui/shared/app-store.js +51 -0
  330. package/dist/ui/shared/app-stream.js +201 -0
  331. package/dist/ui/shared/app.css +820 -0
  332. package/dist/ui/shared/app.js +88 -0
  333. package/dist/ui/shared/fonts/OFL.txt +92 -0
  334. package/dist/ui/shared/fonts/README.md +21 -0
  335. package/dist/ui/shared/fonts/inter.woff2 +0 -0
  336. package/dist/ui/shared/htm.module.js +1 -0
  337. package/dist/ui/shared/panel-view.js +655 -0
  338. package/dist/ui/shared/preact-hooks.module.js +2 -0
  339. package/dist/ui/shared/preact.module.js +2 -0
  340. package/dist/ui/shared/signin.js +142 -0
  341. package/dist/ui/shared/theme.js +29 -0
  342. package/dist/ui/shared/tokens.css +153 -0
  343. package/dist/ui/shared/ui-confirm.js +43 -0
  344. package/dist/ui/shared/ui-dialog.js +45 -0
  345. package/dist/ui/shared/ui-icons.js +63 -0
  346. package/dist/ui/shared/ui-menu.js +39 -0
  347. package/dist/ui/shared/ui-states.js +20 -0
  348. package/dist/ui/shared/ui-toast.js +18 -0
  349. package/dist/ui/shared/vendor/htm.LICENSE +202 -0
  350. package/dist/ui/shared/vendor/preact.LICENSE +21 -0
  351. package/dist/ui/shared/vendor/vendor.json +39 -0
  352. package/dist/ui/shared/view-strings.js +309 -0
  353. package/dist/ui/signin.html +52 -0
  354. package/dist/update-check.d.ts +6 -2
  355. package/dist/update-check.js +12 -3
  356. package/dist/update-check.js.map +1 -1
  357. package/dist/update-dispatch.d.ts +28 -0
  358. package/dist/update-dispatch.js +73 -0
  359. package/dist/update-dispatch.js.map +1 -0
  360. package/dist/update-install.d.ts +129 -0
  361. package/dist/update-install.js +262 -0
  362. package/dist/update-install.js.map +1 -0
  363. package/dist/upgrade-notices.d.ts +17 -0
  364. package/dist/upgrade-notices.js +93 -0
  365. package/dist/upgrade-notices.js.map +1 -0
  366. package/dist/usage/statusline-usage.d.ts +2 -0
  367. package/dist/usage/statusline-usage.js +14 -10
  368. package/dist/usage/statusline-usage.js.map +1 -1
  369. package/dist/view-api.d.ts +6 -1
  370. package/dist/view-api.js +62 -51
  371. package/dist/view-api.js.map +1 -1
  372. package/dist/web-api.d.ts +85 -14
  373. package/dist/web-api.js +557 -77
  374. package/dist/web-api.js.map +1 -1
  375. package/dist/web-auth.d.ts +71 -27
  376. package/dist/web-auth.js +169 -69
  377. package/dist/web-auth.js.map +1 -1
  378. package/dist/web-body.d.ts +3 -0
  379. package/dist/web-body.js +55 -0
  380. package/dist/web-body.js.map +1 -0
  381. package/dist/web-channel-echo.d.ts +9 -0
  382. package/dist/web-channel-echo.js +55 -0
  383. package/dist/web-channel-echo.js.map +1 -0
  384. package/dist/web-chat-history.d.ts +125 -0
  385. package/dist/web-chat-history.js +184 -0
  386. package/dist/web-chat-history.js.map +1 -0
  387. package/dist/web-commands.d.ts +77 -0
  388. package/dist/web-commands.js +81 -0
  389. package/dist/web-commands.js.map +1 -0
  390. package/dist/web-continuation.d.ts +7 -0
  391. package/dist/web-continuation.js +22 -0
  392. package/dist/web-continuation.js.map +1 -0
  393. package/dist/web-host-guard.d.ts +34 -0
  394. package/dist/web-host-guard.js +57 -1
  395. package/dist/web-host-guard.js.map +1 -1
  396. package/dist/web-login.d.ts +72 -0
  397. package/dist/web-login.js +132 -0
  398. package/dist/web-login.js.map +1 -0
  399. package/dist/web-org.d.ts +55 -0
  400. package/dist/web-org.js +67 -0
  401. package/dist/web-org.js.map +1 -0
  402. package/dist/web-preview.d.ts +77 -0
  403. package/dist/web-preview.js +240 -0
  404. package/dist/web-preview.js.map +1 -0
  405. package/dist/web-request-context.d.ts +10 -0
  406. package/dist/web-request-context.js +13 -0
  407. package/dist/web-request-context.js.map +1 -0
  408. package/dist/web-session.d.ts +167 -0
  409. package/dist/web-session.js +389 -0
  410. package/dist/web-session.js.map +1 -0
  411. package/dist/web-shell-routes.d.ts +59 -0
  412. package/dist/web-shell-routes.js +96 -0
  413. package/dist/web-shell-routes.js.map +1 -0
  414. package/dist/web-upload.d.ts +183 -0
  415. package/dist/web-upload.js +468 -0
  416. package/dist/web-upload.js.map +1 -0
  417. package/dist/website-tips-renderer.d.ts +2 -2
  418. package/dist/website-tips-renderer.js +3 -3
  419. package/dist/website-tips-renderer.js.map +1 -1
  420. package/launcher/agend +110 -0
  421. package/launcher/agend-agent +110 -0
  422. package/launcher/agend-agent.cjs +4 -0
  423. package/launcher/agend.cjs +4 -0
  424. package/launcher/install-admission.cjs +105 -0
  425. package/launcher/launch.cjs +64 -0
  426. package/launcher/postinstall.cjs +114 -0
  427. package/launcher/run-in-process.cjs +13 -0
  428. package/launcher/runtime-platform.cjs +86 -0
  429. package/launcher/runtime-select.cjs +217 -0
  430. package/package.json +18 -7
  431. package/scripts/preinstall-guard.cjs +55 -0
  432. package/templates/launchd.plist.ejs +2 -2
  433. package/templates/systemd.service.ejs +1 -1
  434. package/dist/ui/dashboard.html +0 -774
  435. package/dist/ui/settings.html +0 -2165
  436. package/dist/ui/view.html +0 -1139
@@ -0,0 +1,318 @@
1
+ // #1408 §5: the web chat's state, for the life of the page — every instance's messages, drafts, files waiting to go,
2
+ // failed sends, prompts and turn state. It is fed by the app's one stream from the first frame, whatever panel is on
3
+ // screen, so leaving the chat and coming back loses nothing (draft, scroll, files) and re-reads nothing.
4
+ //
5
+ // What it does is what the dashboard did (#1307, #1306, #1313, #1316, #1317); only where it lives changed. No DOM:
6
+ // the chat panel renders it; tests drive it directly.
7
+ //
8
+ // Requests and #1374: the history of an instance is read once per page, when a person first opens its chat (a
9
+ // navigation — it counts as use, as the old click did). Coming back to it reads nothing; the stream keeps it current.
10
+ import "./chat-render.js";
11
+
12
+ const R = () => globalThis.AgendChatRender;
13
+
14
+ /** Build a store. `deps` (fetch, toast, announce, t, now) are injected so tests can drive every path. */
15
+ export function createChatStore(deps) {
16
+ const s = {
17
+ msgs: {}, drafts: {}, failedSends: {}, pendingFiles: {}, sending: {}, inFlightFiles: {},
18
+ prompts: {}, workingSince: {}, stopping: {}, cancelling: {}, scrollMemo: {}, historyRead: new Set(),
19
+ exec: {}, awaiting: {}, current: null,
20
+ // #1269: the last chat command per instance — { command, busy, text?, error?, choices? } — shown above the composer.
21
+ commands: {},
22
+ };
23
+ const subs = new Set();
24
+ const pastedTexts = new WeakMap();
25
+ const now = deps.now || (() => (typeof performance !== "undefined" ? performance.now() : Date.now()));
26
+ const t = deps.t, tf = deps.t;
27
+
28
+ /** Tell subscribers what changed: `kind` "msgs" (the thread redraws) or "state" (everything else). */
29
+ function changed(instance, kind = "state") { for (const fn of [...subs]) fn(instance, kind); }
30
+ async function api(method, path, body) {
31
+ const o = { method, headers: { "Content-Type": "application/json" } };
32
+ if (body) o.body = JSON.stringify(body);
33
+ const r = await deps.fetch(path, o);
34
+ return r.json();
35
+ }
36
+ const isUser = (x, instance) => x.sender === "web-user" || (!x.sender.startsWith("agend") && x.sender !== instance && x.sender !== "general");
37
+
38
+ // ── The turn (#1307): when this page saw the agent start working (its own monotonic clock, so approximate), a Stop
39
+ // on its way, and an instance waiting on a terminal prompt.
40
+ function noteExec(name, state) {
41
+ const was = R().isBusy(s.exec[name]), busy = R().isBusy(state);
42
+ const known = Object.prototype.hasOwnProperty.call(s.exec, name);
43
+ s.exec[name] = state;
44
+ if (busy && !was) s.workingSince[name] = now();
45
+ if (!busy) { delete s.workingSince[name]; delete s.stopping[name]; }
46
+ if (known && name === s.current && busy !== was) deps.announce(tf(busy ? "chat.a11yWorking" : "chat.a11yIdle", name));
47
+ }
48
+ function applyStatus(d) {
49
+ if (!d || !Array.isArray(d.instances)) return;
50
+ for (const i of d.instances) {
51
+ noteExec(i.name, (i.execution_state !== undefined ? i.execution_state : i.state) ?? null);
52
+ const waits = i.state === "awaiting_input" ? (typeof i.interaction_summary === "string" ? i.interaction_summary : "") : null;
53
+ if (i.name === s.current && waits != null && s.awaiting[i.name] == null) deps.announce(tf("chat.awaiting", i.name));
54
+ s.awaiting[i.name] = waits;
55
+ }
56
+ changed(null);
57
+ }
58
+ function applyActivity(d) {
59
+ if (!d || typeof d.instance !== "string") return;
60
+ noteExec(d.instance, d.state ?? null);
61
+ changed(d.instance);
62
+ }
63
+
64
+ // ── Messages: one way in, from the stream, a poll or the history; one entry per boot+id.
65
+ function ingest(m) {
66
+ if (!m || typeof m.instance !== "string") return;
67
+ const before = s.msgs[m.instance];
68
+ s.msgs[m.instance] = R().mergeMessages(before, [m], 500);
69
+ if (m.instance === s.current && s.msgs[m.instance] !== before && !isUser(m, m.instance) && (s.msgs[m.instance] || []).length > (before || []).length) deps.announce(tf("chat.a11yReplied", m.sender));
70
+ if (s.msgs[m.instance] !== before) changed(m.instance, "msgs");
71
+ }
72
+ function applyDeliveries(list) {
73
+ if (!Array.isArray(list)) return;
74
+ const touched = new Set();
75
+ for (const d of list) {
76
+ if (!d || typeof d.instance !== "string") continue;
77
+ const before = s.msgs[d.instance];
78
+ s.msgs[d.instance] = R().applyDelivery(before, d.messageId, d.delivery);
79
+ if (s.msgs[d.instance] !== before) touched.add(d.instance);
80
+ }
81
+ for (const i of touched) changed(i, "msgs");
82
+ }
83
+ /** Read an instance's history once per page (the first time a person opens its chat). */
84
+ async function openHistory(name, lease) {
85
+ if (s.historyRead.has(name)) return false;
86
+ s.historyRead.add(name);
87
+ try {
88
+ const r = await api("GET", `/ui/history?instance=${encodeURIComponent(name)}&limit=200`);
89
+ if (!r || !Array.isArray(r.messages)) { s.historyRead.delete(name); return true; }
90
+ // Kept even when the person has moved on: the store is page-lived, and the answer belongs to `name`.
91
+ s.msgs[name] = R().mergeMessages(s.msgs[name], r.messages, 500);
92
+ changed(name, "msgs");
93
+ } catch { s.historyRead.delete(name); /* the live stream still works; the next visit tries again */ }
94
+ void lease;
95
+ return true;
96
+ }
97
+
98
+ // ── Prompts the fleet has open (hang / clean exit / interactive input): the same buttons the platform shows.
99
+ function onPrompt(p) {
100
+ if (!p || typeof p.nonce !== "string") return;
101
+ const had = s.prompts[p.nonce];
102
+ const fresh = !had;
103
+ // A prompt already held (being answered, or claimed from Needs you) keeps its busy/answered state: a repeat of it
104
+ // only refreshes its text and buttons (#1463 review).
105
+ if (!had) s.prompts[p.nonce] = { ...p, resolved: false, busy: false };
106
+ else if (!had.resolved) Object.assign(had, { text: p.text, actions: p.actions, expiresAt: p.expiresAt });
107
+ if (p.instance === s.current) changed(p.instance);
108
+ else if (fresh) deps.toast(tf("chat.promptFor", p.instance, p.text), false);
109
+ }
110
+ /** The open prompts, on every stream (re)connect and with every poll: a prompt answered or expired while this page
111
+ * was not listening is caught up here, and no timer ever re-reads anything. */
112
+ function applyPrompts(list) {
113
+ if (!Array.isArray(list)) return;
114
+ const open = new Set(list.map(p => p.nonce));
115
+ for (const p of list) {
116
+ const had = s.prompts[p.nonce];
117
+ if (!had) s.prompts[p.nonce] = { ...p, resolved: false, busy: false };
118
+ else if (!had.resolved) Object.assign(had, { text: p.text, actions: p.actions, expiresAt: p.expiresAt });
119
+ }
120
+ for (const n of Object.keys(s.prompts)) if (!s.prompts[n].resolved && !open.has(n)) s.prompts[n].resolved = true;
121
+ changed(null);
122
+ }
123
+ function resolvePrompt(d) {
124
+ const p = d && s.prompts[d.nonce];
125
+ if (!p) return;
126
+ p.resolved = true; p.busy = false;
127
+ if (d.outcome) p.outcome = d.outcome;
128
+ deps.setTimeout(() => { if (s.prompts[d.nonce] === p) { delete s.prompts[d.nonce]; changed(p.instance); } }, 60000);
129
+ changed(p.instance);
130
+ }
131
+ async function answerPrompt(p, action) {
132
+ if (p.busy || p.resolved) return;
133
+ p.busy = true; changed(p.instance);
134
+ let r;
135
+ try { r = await api("POST", "/ui/prompt", { instance: p.instance, nonce: p.nonce, action }); }
136
+ catch (err) { r = { error: err && err.message ? err.message : t("chat.disconnected") }; }
137
+ if (r && r.answered) return; // the outcome arrives as prompt_resolved
138
+ const latest = s.prompts[p.nonce];
139
+ for (const q of latest && latest !== p ? [p, latest] : [p]) { q.busy = false; if (r && r.gone) q.resolved = true; }
140
+ changed(p.instance);
141
+ deps.toast(r && r.error ? r.error : t("chat.disconnected"), false);
142
+ }
143
+ /**
144
+ * Answer a prompt known only by its nonce (Needs you, #1386): the page's one claim on it. A prompt this store does not
145
+ * hold yet is entered now, busy, so the chat, a second click and a later hydration all see the same claim; the next
146
+ * prompts list or prompt_resolved settles it, as for any prompt.
147
+ */
148
+ function answerByNonce(item, action) {
149
+ if (!item || typeof item.nonce !== "string") return Promise.resolve();
150
+ let p = s.prompts[item.nonce];
151
+ if (!p) p = s.prompts[item.nonce] = { instance: item.instance, nonce: item.nonce, text: item.text || item.detail || "", actions: item.actions || [], resolved: false, busy: false };
152
+ return answerPrompt(p, action);
153
+ }
154
+ /** A claim taken elsewhere before this store existed (Needs you, before Chat booted): held here from now on. */
155
+ function holdPrompt(item) {
156
+ if (!item || typeof item.nonce !== "string") return;
157
+ let p = s.prompts[item.nonce];
158
+ if (!p) p = s.prompts[item.nonce] = { instance: item.instance, nonce: item.nonce, text: item.text || item.detail || "", actions: item.actions || [], resolved: false, busy: false };
159
+ if (!p.resolved) { p.busy = true; changed(p.instance); }
160
+ }
161
+ /** That claim's answer was refused: the prompt can be answered again (unless it was settled meanwhile). */
162
+ function releasePrompt(nonce) {
163
+ const p = s.prompts[nonce];
164
+ if (p && !p.resolved) { p.busy = false; changed(p.instance); }
165
+ }
166
+ const promptsFor = (instance) => Object.values(s.prompts).filter(p => p.instance === instance);
167
+
168
+ // ── Sending. Never lose anything: a failed send's files go back to that chat's list and its text back into its own
169
+ // composer when that is empty, otherwise it is kept for its chat and offered back (Put back).
170
+ async function uploadFile(target, file) {
171
+ const r = await deps.fetch(`/ui/upload?instance=${encodeURIComponent(target)}`, {
172
+ method: "POST",
173
+ headers: { "Content-Type": file.type || "application/octet-stream", "X-Agend-Filename": encodeURIComponent(file.name || "file") },
174
+ body: file,
175
+ });
176
+ let body = {};
177
+ try { body = await r.json(); } catch { /* not JSON */ }
178
+ if (!r.ok || !body || typeof body.id !== "string") throw new Error(body && body.error ? `${file.name}: ${body.error}` : `${file.name}: upload failed (${r.status})`);
179
+ return body;
180
+ }
181
+ async function send(target) {
182
+ const txt = (s.drafts[target] || "").trim();
183
+ const files = (s.pendingFiles[target] || []).slice();
184
+ if ((!txt && !files.length) || !target || s.sending[target]) return;
185
+ s.sending[target] = true;
186
+ s.drafts[target] = "";
187
+ s.pendingFiles[target] = []; s.inFlightFiles[target] = files;
188
+ changed(target);
189
+ changed(target, "sent"); // your own message: the thread goes to the bottom
190
+ let r;
191
+ try {
192
+ const ids = [];
193
+ for (const f of files) ids.push((await uploadFile(target, f)).id);
194
+ r = await api("POST", "/ui/send", ids.length ? { instance: target, message: txt, attachments: ids } : { instance: target, message: txt });
195
+ } catch (err) { r = { error: err && err.message ? err.message : t("chat.disconnected") }; }
196
+ s.sending[target] = false;
197
+ delete s.inFlightFiles[target];
198
+ if (r && !r.error) { changed(target); return; }
199
+ if (files.length) s.pendingFiles[target] = R().checkFiles(files, s.pendingFiles[target] || []).kept;
200
+ if (txt) {
201
+ const shown = s.current === target;
202
+ if (R().settleFailedSend(target, s.current, shown, shown ? (s.drafts[target] || "") : "") === "restore") s.drafts[target] = txt;
203
+ else s.failedSends[target] = s.failedSends[target] ? `${s.failedSends[target]}\n${txt}` : txt;
204
+ }
205
+ changed(target);
206
+ deps.toast(r && r.error ? r.error : t("chat.disconnected"), false);
207
+ }
208
+ function addFiles(target, list) {
209
+ if (!target) return;
210
+ const inFlight = s.inFlightFiles[target] || [];
211
+ const res = R().checkFiles(inFlight.concat(s.pendingFiles[target] || []), [...(list || [])]);
212
+ s.pendingFiles[target] = res.kept.slice(inFlight.length);
213
+ for (const x of res.rejected) deps.toast(`${x.name}: ${t(`chat.file_${x.reason.replace(/-/g, "_")}`)}`, false);
214
+ changed(target);
215
+ }
216
+ function removeFile(target, index) { (s.pendingFiles[target] || []).splice(index, 1); changed(target); }
217
+ /** A long paste as a .txt file when it fits beside what is attached; true when it was attached. */
218
+ function attachPastedText(target, text) {
219
+ if (!target) return false;
220
+ const stamp = new Date().toISOString().slice(0, 19).replace(/[-:T]/g, "");
221
+ const f = new File([text], `pasted-${stamp}.txt`, { type: "text/plain" });
222
+ const taken = (s.inFlightFiles[target] || []).concat(s.pendingFiles[target] || []);
223
+ if (R().checkFiles(taken, [f]).rejected.length) { deps.toast(t("chat.pasteKeptAsText")); return false; }
224
+ pastedTexts.set(f, text);
225
+ addFiles(target, [f]);
226
+ deps.toast(tf("chat.pasteAttached", text.length.toLocaleString()));
227
+ return true;
228
+ }
229
+ /** A pasted file back into the composer as text. */
230
+ function fileBackAsText(target, index) {
231
+ const f = (s.pendingFiles[target] || [])[index];
232
+ if (!f || !pastedTexts.has(f)) return;
233
+ s.pendingFiles[target].splice(index, 1);
234
+ const draft = s.drafts[target] || "";
235
+ s.drafts[target] = draft ? `${draft}\n${pastedTexts.get(f)}` : pastedTexts.get(f);
236
+ changed(target);
237
+ }
238
+ const isPasted = (f) => pastedTexts.has(f);
239
+ function putBack(target) {
240
+ const kept = s.failedSends[target];
241
+ if (!kept) return;
242
+ s.drafts[target] = R().putBack(kept, s.drafts[target] || "");
243
+ delete s.failedSends[target];
244
+ changed(target);
245
+ }
246
+ function discardFailed(target) { delete s.failedSends[target]; changed(target); }
247
+ /** Typing: kept for its chat, no redraw (the composer already shows it). */
248
+ function setDraft(target, value) { s.drafts[target] = value; }
249
+
250
+ // ── Stop the reply under way (the composer's Stop, or Esc). Set before the request goes, so a held Esc or a second
251
+ // click sends nothing more (#1317); "Stopping…" until the agent goes idle, or a minute passes.
252
+ async function cancelReply(target) {
253
+ if (!target || s.cancelling[target]) return;
254
+ s.cancelling[target] = true;
255
+ changed(target);
256
+ let r;
257
+ try { r = await api("POST", `/ui/cancel/${encodeURIComponent(target)}`); }
258
+ catch (err) { r = { error: err && err.message ? err.message : t("chat.disconnected") }; }
259
+ delete s.cancelling[target];
260
+ if (r && !r.error) {
261
+ if (R().isBusy(s.exec[target])) {
262
+ s.stopping[target] = true;
263
+ deps.setTimeout(() => { if (s.stopping[target]) { delete s.stopping[target]; changed(target); } }, 60000);
264
+ }
265
+ deps.toast(`${target}: ${t("chat.stopSent")}`);
266
+ } else deps.toast(r && r.error ? r.error : t("chat.disconnected"), false);
267
+ changed(target);
268
+ }
269
+
270
+ // ── Chat commands (#1269): the instance's own /ctx, /compact, /clear, /model … through POST /ui/command. One command
271
+ // at a time per instance, claimed before the request goes (a double Enter sends nothing more). /clear answers with a
272
+ // confirmation first: asked in the app's dialog, and a yes counts only while `alive()` (the chat that asked is still
273
+ // the one on screen) — the token is the server's, used once, for the instance as it was when asked.
274
+ async function runCommand(target, command, args, opts = {}) {
275
+ if (!target || !commandFree(target)) return;
276
+ const alive = opts.alive || (() => true);
277
+ s.commands[target] = { command, busy: true };
278
+ changed(target);
279
+ const post = async (extra) => {
280
+ try { return await api("POST", "/ui/command", { instance: target, command, ...(args ? { args } : {}), ...extra }); }
281
+ catch (err) { return { error: err && err.message ? err.message : t("chat.disconnected") }; }
282
+ };
283
+ let r = await post({});
284
+ if (r && r.confirm) {
285
+ const yes = deps.confirm ? await deps.confirm({ title: `/${command}`, message: r.confirm.message, confirmLabel: t("chat.cmdConfirm"), danger: true }) : false;
286
+ if (!yes || !alive()) { delete s.commands[target]; changed(target); return; }
287
+ r = await post({ confirm: r.confirm.token });
288
+ }
289
+ s.commands[target] = r && r.choices ? { command, busy: false, choices: r.choices }
290
+ : r && r.error ? { command, busy: false, error: r.error } : { command, busy: false, text: (r && r.text) || "" };
291
+ changed(target);
292
+ }
293
+ function dismissCommand(target) { delete s.commands[target]; changed(target); }
294
+ /** Whether a command can start for `target` now (none is out): checked before a typed command line is consumed. */
295
+ const commandFree = (target) => !(s.commands[target] && s.commands[target].busy);
296
+
297
+ /** Wire the store to the app's stream, for the life of the page. */
298
+ function attach(stream) {
299
+ stream.on("status", applyStatus);
300
+ stream.on("activity", applyActivity);
301
+ stream.on("message", ingest);
302
+ stream.on("delivery", (d) => applyDeliveries([d]));
303
+ stream.on("deliveries", applyDeliveries);
304
+ stream.on("prompt", onPrompt);
305
+ stream.on("prompts", applyPrompts);
306
+ stream.on("prompt_resolved", resolvePrompt);
307
+ }
308
+
309
+ return {
310
+ state: s,
311
+ subscribe(fn) { subs.add(fn); return () => subs.delete(fn); },
312
+ setCurrent(name) { s.current = name; },
313
+ attach, applyStatus, applyActivity, ingest, applyDeliveries, openHistory,
314
+ onPrompt, applyPrompts, resolvePrompt, answerPrompt, answerByNonce, holdPrompt, releasePrompt, promptsFor,
315
+ uploadFile, send, addFiles, removeFile, attachPastedText, fileBackAsText, isPasted, putBack, discardFailed, setDraft,
316
+ cancelReply, isUser, runCommand, dismissCommand, commandFree,
317
+ };
318
+ }
@@ -0,0 +1,89 @@
1
+ // The chat's words (the chat.* namespace of the app's one dictionary, #1408 §4), in English and zh-TW.
2
+ import { register } from "/assets/app-i18n.js";
3
+
4
+ register("chat", {
5
+ en: {
6
+ cmdConfirm: "Clear", cmdRunning: "Running /{0}…", cmdNotCommand: "Not a command here — Enter sends it as a message.", cmdDismiss: "Dismiss", cmdCommands: "Commands",
7
+ cmdChoose: "Choose", cmdCurrent: "current", chipCompact: "Compact", chipClear: "Clear…", chipContext: "Context {0}% used",
8
+ chipModel: "Model: {0} — choose another", chipEffort: "Effort: {0} — choose another",
9
+ cmd_ctx: "Context use, model and effort", cmd_compact: "Compact the conversation", cmd_clear: "Clear the conversation (asks first)",
10
+ cmd_model: "Show or switch the model", cmd_effort: "Show or set the reasoning effort", cmd_cancel: "Stop the current reply",
11
+ cmd_btw: "A side question that does not interrupt", cmd_steer: "Send into the current turn", cmd_pause: "Pause the instance",
12
+ cmd_wake: "Wake a paused instance", cmd_save: "Save the conversation to a file",
13
+ tourTitle: "Welcome to web chat", tourStep: "{0} of {1}", tourBack: "Back", tourNext: "Next", tourDone: "Got it", tourSkip: "Skip",
14
+ tour1: "Pick an instance in the list to chat with it. On a phone, ☰ opens the list.",
15
+ tour2: "It is the same conversation as its Telegram or Discord chat: what you send here shows up there too, and the agent's replies show up in both.",
16
+ tour3: "Attach files and images with 📎, or paste or drop them on the chat.",
17
+ tour4: "While the agent works, Stop reply appears in the message box: it interrupts the current reply. The instance itself keeps running.",
18
+ tour5: "A “needs you” badge means the agent is waiting on its terminal, for example a permission question. Answer it from the buttons in its chat.",
19
+ a11yWorking: "{0} started working", a11yIdle: "{0} finished", a11yReplied: "{0} replied", conversationWith: "Conversation with {0}",
20
+ stopping: "Stopping {0}…", awaiting: "{0} is waiting for your input", approxNote: "Read from the terminal, so approximate", elapsedTitle: "Time since this page saw it start (approximate)",
21
+ dropHere: "Drop files to attach them", asText: "As text", pasteAttached: "A long paste ({0} characters) was attached as a text file", pasteKeptAsText: "No room for another attachment: the long paste stays as text",
22
+ send: "Send", composerPlaceholder: "Message {0}…", composerHint: "Enter to send · Shift+Enter for a new line · / for commands · Esc stops the reply", attachTitle: "Attach files (images, PDF, text — or paste / drop them)",
23
+ pvPreview: "Preview", pvStop: "Stop", pvDownload: "Download", pvMenu: "Preview options", pvHtml: "HTML",
24
+ pvAllowButton: "Allow previews", pvAllow: "Allow HTML previews on this device — they may be able to send data out", pvDisallow: "Stop allowing HTML previews on this device",
25
+ pvConfirm: "Allow HTML previews on this device?\n\nA preview runs the agent's HTML in an isolated frame. It cannot use your login, but it may be able to send data out, and it can slow or freeze this tab. You still click Preview each time.",
26
+ pvNever: "Never preview HTML on this device", pvNeverUndo: "Let this device preview HTML again", pvStarting: "Starting the preview…",
27
+ pvChanged: "Preview stopped — the message changed. Preview again.", pvTruncated: "Truncated — ask the agent to send it as a .html file.",
28
+ pvOpenPanel: "Open in panel", pvInPanel: "Shown in the panel.", pvPanel: "HTML preview", pvSource: "From {0}, {1} — show the message",
29
+ pvPage: "Page", pvCode: "Code", pvReload: "Reload", pvClose: "Close the panel", pvBack: "Back to the chat", pvResize: "Resize the preview panel",
30
+ pvNewer: "A newer version is in the reply from {0}.", pvNewerShow: "Show it", pvPanelIdle: "Click Preview to run it here.",
31
+ previews: "Allow HTML previews on this device",
32
+ copy: "Copy", copyMessage: "Copy this reply", copied: "Copied", copyFailed: "Copy failed", wrap: "Wrap", showAll: "Show all {0} lines", showLess: "Show less", jumpLatest: "Latest", newBelow: "{0} new",
33
+ disconnected: "disconnected", tick_queued: "Waiting behind another message", tick_processing: "Handed to the agent", tick_delivered: "The agent has it", tick_failed: "Not delivered", tick_cancelled: "Dropped by Stop",
34
+ promptAnswering: "Answering…", promptGone: "This prompt is no longer open", promptFor: "{0}: {1}",
35
+ working: "{0} is working…", stuck: "{0} looks stuck", stopReply: "Stop reply", stopReplyTitle: "Stop the current reply (like Esc) and drop the messages still waiting. The instance keeps running.", stopSent: "Stopped",
36
+ file_empty: "empty file", file_too_large: "over 10 MB", file_too_many: "at most 5 files per message", file_too_much: "the files together would be over 25 MB", removeFile: "Remove", notSent: "Not sent:", putBack: "Put back", discard: "Discard",
37
+ noMessages: "No messages yet", sendFirst: "Send a message to start the conversation",
38
+ pick: "Pick an instance to start", pickHint: "Choose one in the list, or create a new one.", notFound: "No instance called “{0}”", notFoundHint: "It may have been deleted or renamed.", backToList: "Open the instance list",
39
+ details: "Instance details", start: "Start instance", stopInstance: "Stop instance", restart: "Restart instance", delete: "Delete instance…",
40
+ started: "{0} started", stoppedInst: "{0} stopped", restarted: "{0} restarted", instanceDeleted: "{0} was deleted",
41
+ deleteTitle: "Delete {0}?", deleteHelp: "This removes the instance from the fleet and stops it. Its working directory is kept. Type “delete {0}” to confirm.", deleteGo: "Delete", cancel: "Cancel",
42
+ loadFailed: "Failed to load", tour: "Tour", tourBtnTitle: "Show the web chat tour again",
43
+ dName: "Name", dStatus: "Status", dDisplay: "Display name", dDescription: "Description", dDirectory: "Directory", dBackend: "Backend", dModel: "Model", dEffort: "Effort",
44
+ dCost: "Cost", dCostNote: "(session accumulated)", dContext: "Context", dRate5: "Rate 5h", dRate7: "Rate 7d", dActivity: "Recent activity", dInstance: "Instance", dRuntime: "Runtime",
45
+ configured: "(configured)", fleetDefault: "(fleet default)",
46
+ },
47
+ "zh-TW": {
48
+ cmdConfirm: "清空", cmdRunning: "執行 /{0} 中…", cmdNotCommand: "這裡沒有這個指令——按 Enter 會當成一般訊息送出。", cmdDismiss: "關閉", cmdCommands: "指令",
49
+ cmdChoose: "選擇", cmdCurrent: "目前", chipCompact: "壓縮", chipClear: "清空…", chipContext: "已用 {0}% 的 context",
50
+ chipModel: "模型:{0}——選擇其他", chipEffort: "推理強度:{0}——選擇其他",
51
+ cmd_ctx: "context 用量、模型與推理強度", cmd_compact: "壓縮對話", cmd_clear: "清空對話(會先確認)",
52
+ cmd_model: "查看或切換模型", cmd_effort: "查看或設定推理強度", cmd_cancel: "停止目前的回覆",
53
+ cmd_btw: "不打斷目前工作的旁問", cmd_steer: "送進目前這一輪", cmd_pause: "暫停 instance",
54
+ cmd_wake: "喚醒已暫停的 instance", cmd_save: "把對話存成檔案",
55
+ tourTitle: "歡迎使用網頁聊天", tourStep: "{0} / {1}", tourBack: "上一步", tourNext: "下一步", tourDone: "知道了", tourSkip: "略過",
56
+ tour1: "在清單裡選一個 instance,就能跟它對話。手機上請按 ☰ 打開清單。",
57
+ tour2: "這和它在 Telegram 或 Discord 上的是同一段對話:在這裡送出的訊息那邊也看得到,Agent 的回覆兩邊都會出現。",
58
+ tour3: "按 📎 附上檔案和圖片,也可以直接貼上或拖到聊天裡。",
59
+ tour4: "Agent 工作時,輸入框會出現「中止回覆」:中斷目前的回覆,instance 本身會繼續運行。",
60
+ tour5: "看到「等你回應」標記,表示 Agent 在終端機上等你,例如權限詢問。到它的聊天裡按按鈕回應即可。",
61
+ a11yWorking: "{0} 開始工作", a11yIdle: "{0} 已完成", a11yReplied: "{0} 已回覆", conversationWith: "與 {0} 的對話",
62
+ stopping: "正在中止 {0}…", awaiting: "{0} 正在等你回應", approxNote: "從終端畫面判讀,僅供參考", elapsedTitle: "從這個頁面看到它開始工作起算(約略)",
63
+ dropHere: "放開即可附加檔案", asText: "改為文字", pasteAttached: "貼上的長文字({0} 個字元)已改為文字檔附加", pasteKeptAsText: "附件已滿,貼上的長文字保留為一般文字",
64
+ send: "送出", composerPlaceholder: "傳訊息給 {0}…", composerHint: "Enter 送出 · Shift+Enter 換行 · / 叫出指令 · Esc 中止回覆", attachTitle: "附加檔案(圖片、PDF、文字檔,也可以貼上或拖曳)",
65
+ pvPreview: "預覽", pvStop: "停止", pvDownload: "下載", pvMenu: "預覽選項", pvHtml: "HTML",
66
+ pvAllowButton: "允許預覽", pvAllow: "允許這台裝置預覽 HTML(預覽可能把資料傳出去)", pvDisallow: "不再允許這台裝置預覽 HTML",
67
+ pvConfirm: "要允許這台裝置預覽 HTML 嗎?\n\n預覽會在隔離的框架裡執行 agent 的 HTML。它無法使用你的登入,但可能把資料傳出去,也可能讓這個分頁變慢或卡住。每次仍需要你按「預覽」。",
68
+ pvNever: "這台裝置永不預覽 HTML", pvNeverUndo: "讓這台裝置再次可以預覽 HTML", pvStarting: "正在啟動預覽…",
69
+ pvChanged: "預覽已停止——訊息內容變了。請再預覽一次。", pvTruncated: "內容被截斷——請 agent 改用 .html 檔案傳送。",
70
+ pvOpenPanel: "在面板中開啟", pvInPanel: "已在面板中顯示。", pvPanel: "HTML 預覽", pvSource: "來自 {0},{1}——顯示該訊息",
71
+ pvPage: "頁面", pvCode: "程式碼", pvReload: "重新載入", pvClose: "關閉面板", pvBack: "回到對話", pvResize: "調整預覽面板寬度",
72
+ pvNewer: "{0} 的回覆裡有較新的版本。", pvNewerShow: "顯示", pvPanelIdle: "按「預覽」在這裡執行。",
73
+ previews: "允許這台裝置預覽 HTML",
74
+ copy: "複製", copyMessage: "複製這則回覆", copied: "已複製", copyFailed: "複製失敗", wrap: "換行", showAll: "展開全部 {0} 行", showLess: "收合", jumpLatest: "最新", newBelow: "{0} 則新訊息",
75
+ disconnected: "已斷線", tick_queued: "排在前一則訊息之後", tick_processing: "已交給 agent", tick_delivered: "agent 已收到", tick_failed: "未送達", tick_cancelled: "已被中止取消",
76
+ promptAnswering: "回覆中…", promptGone: "這個提示已經結束", promptFor: "{0}:{1}",
77
+ working: "{0} 處理中…", stuck: "{0} 似乎卡住了", stopReply: "中止回覆", stopReplyTitle: "中止目前的回覆(同 Esc),並取消還在排隊的訊息。instance 會繼續運行。", stopSent: "已中止",
78
+ file_empty: "空檔案", file_too_large: "超過 10 MB", file_too_many: "每則訊息最多 5 個檔案", file_too_much: "檔案合計會超過 25 MB", removeFile: "移除", notSent: "未送出:", putBack: "放回輸入框", discard: "捨棄",
79
+ noMessages: "尚無訊息", sendFirst: "傳送訊息以開始對話",
80
+ pick: "選一個 instance 開始", pickHint: "在清單裡選一個,或建立新的。", notFound: "沒有叫「{0}」的 instance", notFoundHint: "它可能已被刪除或改名。", backToList: "打開 instance 清單",
81
+ details: "Instance 詳細資料", start: "啟動 instance", stopInstance: "停止 instance", restart: "重新啟動 instance", delete: "刪除 instance…",
82
+ started: "{0} 已啟動", stoppedInst: "{0} 已停止", restarted: "{0} 已重新啟動", instanceDeleted: "{0} 已刪除",
83
+ deleteTitle: "要刪除 {0} 嗎?", deleteHelp: "這會把 instance 從 fleet 移除並停止它,工作目錄會保留。請輸入「delete {0}」確認。", deleteGo: "刪除", cancel: "取消",
84
+ loadFailed: "載入失敗", tour: "導覽", tourBtnTitle: "再看一次網頁聊天導覽",
85
+ dName: "名稱", dStatus: "狀態", dDisplay: "顯示名稱", dDescription: "說明", dDirectory: "目錄", dBackend: "Backend", dModel: "模型", dEffort: "Effort",
86
+ dCost: "花費", dCostNote: "(本次 session 累計)", dContext: "Context", dRate5: "5 小時額度", dRate7: "7 天額度", dActivity: "最近活動", dInstance: "Instance", dRuntime: "執行環境",
87
+ configured: "(設定值)", fleetDefault: "(fleet 預設)",
88
+ },
89
+ });