@songsid/agend 2.1.12-beta.9 → 2.2.0-alpha.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 (358) hide show
  1. package/README.md +2 -2
  2. package/README.zh-TW.md +2 -2
  3. package/dist/auth/one-time-code.d.ts +19 -0
  4. package/dist/auth/one-time-code.js +49 -0
  5. package/dist/auth/one-time-code.js.map +1 -0
  6. package/dist/auth-api.d.ts +52 -0
  7. package/dist/auth-api.js +346 -0
  8. package/dist/auth-api.js.map +1 -0
  9. package/dist/backend/claude-code.d.ts +4 -0
  10. package/dist/backend/claude-code.js +97 -0
  11. package/dist/backend/claude-code.js.map +1 -1
  12. package/dist/backend/codex.js +59 -30
  13. package/dist/backend/codex.js.map +1 -1
  14. package/dist/backend/kiro-agent.d.ts +66 -0
  15. package/dist/backend/kiro-agent.js +302 -0
  16. package/dist/backend/kiro-agent.js.map +1 -0
  17. package/dist/backend/kiro-identity.d.ts +80 -0
  18. package/dist/backend/kiro-identity.js +537 -0
  19. package/dist/backend/kiro-identity.js.map +1 -0
  20. package/dist/backend/kiro-v2-store-worker.d.ts +1 -0
  21. package/dist/backend/kiro-v2-store-worker.js +87 -0
  22. package/dist/backend/kiro-v2-store-worker.js.map +1 -0
  23. package/dist/backend/kiro-v2-store.d.ts +54 -0
  24. package/dist/backend/kiro-v2-store.js +131 -0
  25. package/dist/backend/kiro-v2-store.js.map +1 -0
  26. package/dist/backend/kiro-v3-identity.d.ts +5 -0
  27. package/dist/backend/kiro-v3-identity.js +22 -0
  28. package/dist/backend/kiro-v3-identity.js.map +1 -1
  29. package/dist/backend/kiro.d.ts +83 -7
  30. package/dist/backend/kiro.js +418 -91
  31. package/dist/backend/kiro.js.map +1 -1
  32. package/dist/backend/types.d.ts +45 -3
  33. package/dist/backend/types.js.map +1 -1
  34. package/dist/channel/adapters/discord.d.ts +1 -0
  35. package/dist/channel/adapters/discord.js +29 -10
  36. package/dist/channel/adapters/discord.js.map +1 -1
  37. package/dist/channel/adapters/telegram.d.ts +1 -0
  38. package/dist/channel/adapters/telegram.js +13 -1
  39. package/dist/channel/adapters/telegram.js.map +1 -1
  40. package/dist/channel/types.d.ts +9 -1
  41. package/dist/classic-channel-manager.d.ts +18 -10
  42. package/dist/classic-channel-manager.js +45 -18
  43. package/dist/classic-channel-manager.js.map +1 -1
  44. package/dist/cli.js +225 -127
  45. package/dist/cli.js.map +1 -1
  46. package/dist/command-table.d.ts +5 -3
  47. package/dist/command-table.js +29 -27
  48. package/dist/command-table.js.map +1 -1
  49. package/dist/config-validator.js +46 -0
  50. package/dist/config-validator.js.map +1 -1
  51. package/dist/config.js +12 -0
  52. package/dist/config.js.map +1 -1
  53. package/dist/connection-secrets.d.ts +6 -0
  54. package/dist/connection-secrets.js +4 -0
  55. package/dist/connection-secrets.js.map +1 -1
  56. package/dist/daemon.d.ts +89 -4
  57. package/dist/daemon.js +661 -77
  58. package/dist/daemon.js.map +1 -1
  59. package/dist/darwin-memory.d.ts +6 -1
  60. package/dist/darwin-memory.js +17 -6
  61. package/dist/darwin-memory.js.map +1 -1
  62. package/dist/delivery-consumed-watch.d.ts +85 -0
  63. package/dist/delivery-consumed-watch.js +244 -0
  64. package/dist/delivery-consumed-watch.js.map +1 -0
  65. package/dist/delivery-outbox.d.ts +61 -0
  66. package/dist/delivery-outbox.js +120 -2
  67. package/dist/delivery-outbox.js.map +1 -1
  68. package/dist/delivery-reconciliation.d.ts +14 -5
  69. package/dist/delivery-reconciliation.js +27 -4
  70. package/dist/delivery-reconciliation.js.map +1 -1
  71. package/dist/delivery-reconciliation.test.js +35 -1
  72. package/dist/delivery-reconciliation.test.js.map +1 -1
  73. package/dist/event-loop-watch.d.ts +28 -0
  74. package/dist/event-loop-watch.js +75 -3
  75. package/dist/event-loop-watch.js.map +1 -1
  76. package/dist/fleet-context.d.ts +22 -2
  77. package/dist/fleet-level-config.d.ts +2 -2
  78. package/dist/fleet-level-config.js +6 -1
  79. package/dist/fleet-level-config.js.map +1 -1
  80. package/dist/fleet-manager.d.ts +293 -12
  81. package/dist/fleet-manager.js +2364 -449
  82. package/dist/fleet-manager.js.map +1 -1
  83. package/dist/host-memory.d.ts +4 -0
  84. package/dist/host-memory.js.map +1 -1
  85. package/dist/instance-config-impact.js +5 -0
  86. package/dist/instance-config-impact.js.map +1 -1
  87. package/dist/instance-lifecycle.d.ts +10 -5
  88. package/dist/instance-lifecycle.js +162 -53
  89. package/dist/instance-lifecycle.js.map +1 -1
  90. package/dist/locale.js +150 -16
  91. package/dist/locale.js.map +1 -1
  92. package/dist/login-controller.d.ts +2 -0
  93. package/dist/login-controller.js +17 -5
  94. package/dist/login-controller.js.map +1 -1
  95. package/dist/memory-pressure.d.ts +7 -8
  96. package/dist/memory-pressure.js +76 -15
  97. package/dist/memory-pressure.js.map +1 -1
  98. package/dist/monotonic-budget.d.ts +2 -0
  99. package/dist/monotonic-budget.js +28 -0
  100. package/dist/monotonic-budget.js.map +1 -0
  101. package/dist/needs-you-hub.d.ts +114 -0
  102. package/dist/needs-you-hub.js +370 -0
  103. package/dist/needs-you-hub.js.map +1 -0
  104. package/dist/needs-you-live.d.ts +116 -0
  105. package/dist/needs-you-live.js +228 -0
  106. package/dist/needs-you-live.js.map +1 -0
  107. package/dist/needs-you.d.ts +132 -0
  108. package/dist/needs-you.js +164 -0
  109. package/dist/needs-you.js.map +1 -0
  110. package/dist/node-version-guard.d.ts +30 -0
  111. package/dist/node-version-guard.js +50 -0
  112. package/dist/node-version-guard.js.map +1 -0
  113. package/dist/operator-control-paths.d.ts +4 -0
  114. package/dist/operator-control-paths.js +24 -0
  115. package/dist/operator-control-paths.js.map +1 -0
  116. package/dist/outbound-handlers.d.ts +2 -0
  117. package/dist/outbound-handlers.js +9 -2
  118. package/dist/outbound-handlers.js.map +1 -1
  119. package/dist/outbound-schemas.d.ts +5 -5
  120. package/dist/profile-control.js +4 -20
  121. package/dist/profile-control.js.map +1 -1
  122. package/dist/public-web-gateway.d.ts +18 -0
  123. package/dist/public-web-gateway.js +141 -0
  124. package/dist/public-web-gateway.js.map +1 -0
  125. package/dist/public-web-link.d.ts +53 -0
  126. package/dist/public-web-link.js +175 -0
  127. package/dist/public-web-link.js.map +1 -0
  128. package/dist/quickstart-api.d.ts +8 -1
  129. package/dist/quickstart-api.js +86 -48
  130. package/dist/quickstart-api.js.map +1 -1
  131. package/dist/quickstart.d.ts +1 -0
  132. package/dist/quickstart.js +6 -2
  133. package/dist/quickstart.js.map +1 -1
  134. package/dist/scheduler/db.d.ts +7 -1
  135. package/dist/scheduler/db.js +38 -0
  136. package/dist/scheduler/db.js.map +1 -1
  137. package/dist/scheduler/index.d.ts +1 -1
  138. package/dist/scheduler/retry-label.d.ts +11 -0
  139. package/dist/scheduler/retry-label.js +24 -0
  140. package/dist/scheduler/retry-label.js.map +1 -0
  141. package/dist/scheduler/scheduler.d.ts +55 -2
  142. package/dist/scheduler/scheduler.js +220 -8
  143. package/dist/scheduler/scheduler.js.map +1 -1
  144. package/dist/scheduler/types.d.ts +22 -0
  145. package/dist/scheduler/types.js.map +1 -1
  146. package/dist/secret-store.d.ts +5 -0
  147. package/dist/secret-store.js +20 -0
  148. package/dist/secret-store.js.map +1 -1
  149. package/dist/service-activation.d.ts +110 -0
  150. package/dist/service-activation.js +302 -0
  151. package/dist/service-activation.js.map +1 -0
  152. package/dist/service-installer.d.ts +7 -0
  153. package/dist/service-installer.js +7 -4
  154. package/dist/service-installer.js.map +1 -1
  155. package/dist/service-restart-selection.d.ts +6 -5
  156. package/dist/service-restart-selection.js +6 -5
  157. package/dist/service-restart-selection.js.map +1 -1
  158. package/dist/settings-api.d.ts +10 -2
  159. package/dist/settings-api.js +175 -72
  160. package/dist/settings-api.js.map +1 -1
  161. package/dist/settings-baseline.d.ts +20 -0
  162. package/dist/settings-baseline.js +104 -0
  163. package/dist/settings-baseline.js.map +1 -0
  164. package/dist/settings-change.d.ts +21 -0
  165. package/dist/settings-change.js +133 -0
  166. package/dist/settings-change.js.map +1 -0
  167. package/dist/settings-confirmation.d.ts +105 -0
  168. package/dist/settings-confirmation.js +232 -0
  169. package/dist/settings-confirmation.js.map +1 -0
  170. package/dist/settings-control.d.ts +41 -0
  171. package/dist/settings-control.js +294 -0
  172. package/dist/settings-control.js.map +1 -0
  173. package/dist/settings-effect.d.ts +24 -0
  174. package/dist/settings-effect.js +169 -0
  175. package/dist/settings-effect.js.map +1 -0
  176. package/dist/settings-http-confirmation.d.ts +29 -0
  177. package/dist/settings-http-confirmation.js +123 -0
  178. package/dist/settings-http-confirmation.js.map +1 -0
  179. package/dist/settings-instance-patch.d.ts +4 -0
  180. package/dist/settings-instance-patch.js +26 -0
  181. package/dist/settings-instance-patch.js.map +1 -0
  182. package/dist/settings-request-capability.d.ts +16 -0
  183. package/dist/settings-request-capability.js +32 -0
  184. package/dist/settings-request-capability.js.map +1 -0
  185. package/dist/settings-transaction.d.ts +65 -0
  186. package/dist/settings-transaction.js +223 -0
  187. package/dist/settings-transaction.js.map +1 -0
  188. package/dist/setup-auth.d.ts +10 -18
  189. package/dist/setup-auth.js +14 -38
  190. package/dist/setup-auth.js.map +1 -1
  191. package/dist/setup-form.d.ts +1 -1
  192. package/dist/setup-form.js +75 -18
  193. package/dist/setup-form.js.map +1 -1
  194. package/dist/setup-guide.d.ts +13 -0
  195. package/dist/setup-guide.js +25 -0
  196. package/dist/setup-guide.js.map +1 -0
  197. package/dist/setup-host.d.ts +16 -0
  198. package/dist/setup-host.js +197 -32
  199. package/dist/setup-host.js.map +1 -1
  200. package/dist/setup-wizard.js +3 -0
  201. package/dist/setup-wizard.js.map +1 -1
  202. package/dist/slash-authz.d.ts +17 -3
  203. package/dist/slash-authz.js +5 -0
  204. package/dist/slash-authz.js.map +1 -1
  205. package/dist/spawn-gate.js +3 -3
  206. package/dist/spawn-gate.js.map +1 -1
  207. package/dist/statusline-watcher.d.ts +5 -0
  208. package/dist/statusline-watcher.js +2 -0
  209. package/dist/statusline-watcher.js.map +1 -1
  210. package/dist/steer-capability.d.ts +6 -0
  211. package/dist/steer-capability.js +8 -0
  212. package/dist/steer-capability.js.map +1 -1
  213. package/dist/sync-work-attribution.d.ts +14 -0
  214. package/dist/sync-work-attribution.js +43 -8
  215. package/dist/sync-work-attribution.js.map +1 -1
  216. package/dist/tips.js +10 -5
  217. package/dist/tips.js.map +1 -1
  218. package/dist/tmux-control.d.ts +35 -5
  219. package/dist/tmux-control.js +291 -57
  220. package/dist/tmux-control.js.map +1 -1
  221. package/dist/tmux-manager.d.ts +20 -6
  222. package/dist/tmux-manager.js +90 -47
  223. package/dist/tmux-manager.js.map +1 -1
  224. package/dist/tmux-read.d.ts +59 -0
  225. package/dist/tmux-read.js +213 -0
  226. package/dist/tmux-read.js.map +1 -0
  227. package/dist/topic-commands.d.ts +21 -10
  228. package/dist/topic-commands.js +191 -58
  229. package/dist/topic-commands.js.map +1 -1
  230. package/dist/transcript-delta-reader.js +2 -1
  231. package/dist/transcript-delta-reader.js.map +1 -1
  232. package/dist/tunnel/cloudflared-install.d.ts +2 -0
  233. package/dist/tunnel/cloudflared-install.js +1 -1
  234. package/dist/tunnel/cloudflared-install.js.map +1 -1
  235. package/dist/tunnel/purpose-lane.d.ts +14 -0
  236. package/dist/tunnel/purpose-lane.js +43 -0
  237. package/dist/tunnel/purpose-lane.js.map +1 -0
  238. package/dist/turn-reply-guard.d.ts +2 -0
  239. package/dist/turn-reply-guard.js +10 -1
  240. package/dist/turn-reply-guard.js.map +1 -1
  241. package/dist/types.d.ts +33 -0
  242. package/dist/ui/app.html +18 -0
  243. package/dist/ui/chat-render.js +478 -0
  244. package/dist/ui/chat-store.js +289 -0
  245. package/dist/ui/chat-strings.js +69 -0
  246. package/dist/ui/chat-thread.js +209 -0
  247. package/dist/ui/chat-tour.js +116 -0
  248. package/dist/ui/fleet-org.js +142 -0
  249. package/dist/ui/panel-chat.js +418 -0
  250. package/dist/ui/panel-fleet.js +413 -0
  251. package/dist/ui/panel-needs.js +202 -0
  252. package/dist/ui/panel-settings.js +750 -0
  253. package/dist/ui/preview.js +266 -0
  254. package/dist/ui/settings-apply.js +239 -0
  255. package/dist/ui/settings-confirm.js +186 -0
  256. package/dist/ui/settings-dialogs.js +546 -0
  257. package/dist/ui/settings-model.js +277 -0
  258. package/dist/ui/settings-strings.js +652 -0
  259. package/dist/ui/settings-wizard.js +140 -0
  260. package/dist/ui/shared/agend-auth.js +93 -0
  261. package/dist/ui/shared/app-ctx.js +80 -0
  262. package/dist/ui/shared/app-html.js +9 -0
  263. package/dist/ui/shared/app-i18n.js +95 -0
  264. package/dist/ui/shared/app-nav.js +73 -0
  265. package/dist/ui/shared/app-needs.js +114 -0
  266. package/dist/ui/shared/app-route.js +73 -0
  267. package/dist/ui/shared/app-session.js +66 -0
  268. package/dist/ui/shared/app-shell.js +344 -0
  269. package/dist/ui/shared/app-store.js +51 -0
  270. package/dist/ui/shared/app-stream.js +201 -0
  271. package/dist/ui/shared/app.css +676 -0
  272. package/dist/ui/shared/app.js +88 -0
  273. package/dist/ui/shared/fonts/OFL.txt +92 -0
  274. package/dist/ui/shared/fonts/README.md +21 -0
  275. package/dist/ui/shared/fonts/inter.woff2 +0 -0
  276. package/dist/ui/shared/htm.module.js +1 -0
  277. package/dist/ui/shared/panel-view.js +655 -0
  278. package/dist/ui/shared/preact-hooks.module.js +2 -0
  279. package/dist/ui/shared/preact.module.js +2 -0
  280. package/dist/ui/shared/signin.js +130 -0
  281. package/dist/ui/shared/theme.js +29 -0
  282. package/dist/ui/shared/tokens.css +153 -0
  283. package/dist/ui/shared/ui-confirm.js +43 -0
  284. package/dist/ui/shared/ui-dialog.js +45 -0
  285. package/dist/ui/shared/ui-icons.js +61 -0
  286. package/dist/ui/shared/ui-menu.js +39 -0
  287. package/dist/ui/shared/ui-states.js +20 -0
  288. package/dist/ui/shared/ui-toast.js +18 -0
  289. package/dist/ui/shared/vendor/htm.LICENSE +202 -0
  290. package/dist/ui/shared/vendor/preact.LICENSE +21 -0
  291. package/dist/ui/shared/vendor/vendor.json +39 -0
  292. package/dist/ui/shared/view-strings.js +309 -0
  293. package/dist/ui/signin.html +51 -0
  294. package/dist/update-check.d.ts +6 -2
  295. package/dist/update-check.js +12 -3
  296. package/dist/update-check.js.map +1 -1
  297. package/dist/update-install.d.ts +71 -0
  298. package/dist/update-install.js +162 -0
  299. package/dist/update-install.js.map +1 -0
  300. package/dist/upgrade-notices.d.ts +17 -0
  301. package/dist/upgrade-notices.js +93 -0
  302. package/dist/upgrade-notices.js.map +1 -0
  303. package/dist/usage/statusline-usage.d.ts +2 -0
  304. package/dist/usage/statusline-usage.js +14 -10
  305. package/dist/usage/statusline-usage.js.map +1 -1
  306. package/dist/view-api.d.ts +6 -1
  307. package/dist/view-api.js +62 -51
  308. package/dist/view-api.js.map +1 -1
  309. package/dist/web-api.d.ts +71 -14
  310. package/dist/web-api.js +492 -77
  311. package/dist/web-api.js.map +1 -1
  312. package/dist/web-auth.d.ts +71 -27
  313. package/dist/web-auth.js +169 -69
  314. package/dist/web-auth.js.map +1 -1
  315. package/dist/web-body.d.ts +3 -0
  316. package/dist/web-body.js +55 -0
  317. package/dist/web-body.js.map +1 -0
  318. package/dist/web-channel-echo.d.ts +9 -0
  319. package/dist/web-channel-echo.js +55 -0
  320. package/dist/web-channel-echo.js.map +1 -0
  321. package/dist/web-chat-history.d.ts +125 -0
  322. package/dist/web-chat-history.js +184 -0
  323. package/dist/web-chat-history.js.map +1 -0
  324. package/dist/web-continuation.d.ts +7 -0
  325. package/dist/web-continuation.js +22 -0
  326. package/dist/web-continuation.js.map +1 -0
  327. package/dist/web-host-guard.d.ts +34 -0
  328. package/dist/web-host-guard.js +57 -1
  329. package/dist/web-host-guard.js.map +1 -1
  330. package/dist/web-login.d.ts +72 -0
  331. package/dist/web-login.js +132 -0
  332. package/dist/web-login.js.map +1 -0
  333. package/dist/web-org.d.ts +55 -0
  334. package/dist/web-org.js +67 -0
  335. package/dist/web-org.js.map +1 -0
  336. package/dist/web-preview.d.ts +77 -0
  337. package/dist/web-preview.js +240 -0
  338. package/dist/web-preview.js.map +1 -0
  339. package/dist/web-request-context.d.ts +10 -0
  340. package/dist/web-request-context.js +13 -0
  341. package/dist/web-request-context.js.map +1 -0
  342. package/dist/web-session.d.ts +167 -0
  343. package/dist/web-session.js +389 -0
  344. package/dist/web-session.js.map +1 -0
  345. package/dist/web-shell-routes.d.ts +59 -0
  346. package/dist/web-shell-routes.js +96 -0
  347. package/dist/web-shell-routes.js.map +1 -0
  348. package/dist/web-upload.d.ts +183 -0
  349. package/dist/web-upload.js +468 -0
  350. package/dist/web-upload.js.map +1 -0
  351. package/dist/website-tips-renderer.d.ts +2 -2
  352. package/dist/website-tips-renderer.js +3 -3
  353. package/dist/website-tips-renderer.js.map +1 -1
  354. package/package.json +8 -5
  355. package/scripts/preinstall-guard.cjs +36 -0
  356. package/dist/ui/dashboard.html +0 -774
  357. package/dist/ui/settings.html +0 -2165
  358. package/dist/ui/view.html +0 -1139
@@ -0,0 +1,370 @@
1
+ /**
2
+ * #1386: the fleet side of "Needs you". One derivation (needs-you.ts), recomputed on change, rendered to:
3
+ * - each world's live message in its General and, optionally, its admins' DMs — only that world's items (§5.0, §5);
4
+ * - the web, globally: SSE `needs` and a `needs` field on /ui/poll (§6).
5
+ * Plus Acknowledge for delivery items, from a world's live message (its admins, its items) or from the web (any).
6
+ *
7
+ * The Acknowledge capabilities live in this hub's own registry, not in the fleet's prompt map: the map's walkers
8
+ * (per-instance clear, shutdown retire, prompt expiry) edit the message an entry points at, and the live message must
9
+ * only ever be edited by its own renderer. The checks are the same as every other button's: a 128-bit nonce, bound
10
+ * to the world, chat, thread and message that showed it, and fleet admin of that world.
11
+ */
12
+ import { randomBytes } from "node:crypto";
13
+ import { readFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { writeFileAtomic } from "./backend/kiro-engine-ledger.js";
16
+ import { deriveNeedsYou, itemsForWorld, renderLiveMessage, renderSignature, messageLink, instanceLink, } from "./needs-you.js";
17
+ import { NeedsYouLiveMessage, canonicalTarget } from "./needs-you-live.js";
18
+ export const NEEDS_ACK_PREFIX = "needs-ack:";
19
+ const ACK_RE = /^needs-ack:([0-9a-f]{32}):ack$/;
20
+ const BACKSTOP_MS = 10_000;
21
+ const ATTENTION_WINDOW_MS = 24 * 60 * 60_000;
22
+ /** awaiting_input pings (DM, browser) only once it has lasted this long; the list itself is never delayed (§6.3). */
23
+ export const AWAITING_PING_MIN_MS = 5_000;
24
+ const DM_MIN_MS = 60_000;
25
+ /** An Acknowledge button's capability lapses this long after it was minted, whether or not a renewal replaced it. */
26
+ export const ACK_TTL_MS = 15 * 60_000;
27
+ /** What a renderer is built for, besides its adapter: platform and group. */
28
+ function placeKey(place) {
29
+ return `${place.type}|${place.groupId ?? ""}`;
30
+ }
31
+ export class NeedsYouHub {
32
+ ctx;
33
+ items = [];
34
+ webSignature = "";
35
+ worldSignature = new Map();
36
+ worldSeen = new Map();
37
+ /** Each world's renderer, pinned to the adapter and place it was built for (#1398 review): a replaced adapter or
38
+ * moved place gets a new renderer, and the old one can no longer publish. */
39
+ live = new Map();
40
+ acks = new Map();
41
+ dmSeen = new Map();
42
+ dmLastAt = new Map();
43
+ /** Per world: the ids waiting to be DMed, and the one timer that will send them. */
44
+ dmPending = new Map();
45
+ dmTimer = new Map();
46
+ pending = null;
47
+ backstop = null;
48
+ stopped = false;
49
+ /** The first computation after start: what waits then is not news (a restart edits, it does not post or DM). */
50
+ seeded = false;
51
+ constructor(ctx) {
52
+ this.ctx = ctx;
53
+ }
54
+ start() {
55
+ this.recompute();
56
+ const tick = () => { this.backstop = this.ctx.setTimer(tick, BACKSTOP_MS); this.recompute(); };
57
+ this.backstop = this.ctx.setTimer(tick, BACKSTOP_MS);
58
+ }
59
+ /** Something that may change the list happened: recompute once, soon (coalesced). */
60
+ poke() {
61
+ if (this.stopped || this.pending !== null)
62
+ return;
63
+ this.pending = this.ctx.setTimer(() => { this.pending = null; this.recompute(); }, 0);
64
+ }
65
+ /** The current list for the web (global, §5.0). */
66
+ webItems() {
67
+ return this.items.map(({ promptAt: _promptAt, ...rest }) => rest);
68
+ }
69
+ recompute() {
70
+ if (this.stopped)
71
+ return;
72
+ const now = this.ctx.now();
73
+ let deliveries = [];
74
+ try {
75
+ deliveries = this.ctx.deliveries(new Date(now - ATTENTION_WINDOW_MS).toISOString());
76
+ }
77
+ catch (err) {
78
+ this.ctx.log("warn", "Needs you: could not read the delivery outbox", { err: String(err?.message ?? err) });
79
+ }
80
+ this.items = deriveNeedsYou({ prompts: this.ctx.prompts(), instances: this.ctx.instances(), deliveries, ownerOf: i => this.ctx.ownerOf(i) });
81
+ const webSig = renderSignature(this.items, now);
82
+ if (webSig !== this.webSignature) {
83
+ this.webSignature = webSig;
84
+ this.ctx.emitSse("needs", { items: this.webItems() });
85
+ }
86
+ const settings = this.ctx.settings();
87
+ const worlds = this.ctx.worlds();
88
+ const worldIds = new Set(worlds.map(w => w.id));
89
+ for (const [id, pinned] of this.live) {
90
+ const current = worlds.find(w => w.id === id);
91
+ if (!settings.liveMessage || !current) {
92
+ this.live.delete(id);
93
+ this.worldSignature.delete(id);
94
+ void pinned.renderer.disable();
95
+ }
96
+ else if (current.adapter !== pinned.adapter || placeKey(current.place) !== pinned.placeKey) {
97
+ // Another adapter (or place) under the same id: the old renderer stops without touching anything — its adapter
98
+ // may be gone — and a new one picks up from the persisted pointer.
99
+ this.live.delete(id);
100
+ this.worldSignature.delete(id);
101
+ pinned.renderer.abandon();
102
+ }
103
+ }
104
+ if (!settings.dm)
105
+ for (const id of [...this.dmPending.keys()])
106
+ this.cancelDms(id);
107
+ for (const id of [...this.dmPending.keys()])
108
+ if (!worldIds.has(id))
109
+ this.cancelDms(id);
110
+ const seeding = !this.seeded;
111
+ this.seeded = true;
112
+ for (const world of worlds) {
113
+ const mine = itemsForWorld(this.items, world.id);
114
+ if (seeding) {
115
+ this.worldSeen.set(world.id, new Set(mine.map(i => i.id)));
116
+ this.dmSeen.set(world.id, new Set(mine.map(i => i.id)));
117
+ }
118
+ const seen = this.worldSeen.get(world.id) ?? new Set();
119
+ const fresh = mine.filter(i => !seen.has(i.id));
120
+ this.worldSeen.set(world.id, new Set(mine.map(i => i.id)));
121
+ if (settings.liveMessage) {
122
+ let pinned = this.live.get(world.id);
123
+ if (!pinned) {
124
+ pinned = { renderer: this.makeLive(world), adapter: world.adapter, placeKey: placeKey(world.place) };
125
+ this.live.set(world.id, pinned);
126
+ }
127
+ const sig = renderSignature(mine, now);
128
+ if (sig !== this.worldSignature.get(world.id)) {
129
+ this.worldSignature.set(world.id, sig);
130
+ pinned.renderer.changed(fresh.length > 0);
131
+ }
132
+ }
133
+ if (settings.dm)
134
+ this.queueDms(world, mine, now);
135
+ }
136
+ }
137
+ // ── Live messages ──────────────────────────────────────────────────────────────────────────────────────────
138
+ pointerPath() { return join(this.ctx.dataDir, "needs-you-message.json"); }
139
+ readPointers() {
140
+ try {
141
+ const parsed = JSON.parse(readFileSync(this.pointerPath(), "utf8"));
142
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
143
+ return {};
144
+ const out = {};
145
+ for (const [world, p] of Object.entries(parsed)) {
146
+ const v = p;
147
+ if (v && typeof v.chatId === "string" && typeof v.messageId === "string" && (v.threadId === undefined || typeof v.threadId === "string")) {
148
+ out[world] = { chatId: v.chatId, messageId: v.messageId, ...(v.threadId !== undefined ? { threadId: v.threadId } : {}) };
149
+ }
150
+ }
151
+ return out;
152
+ }
153
+ catch {
154
+ return {};
155
+ }
156
+ }
157
+ writePointer(world, pointer) {
158
+ const all = this.readPointers();
159
+ if (pointer)
160
+ all[world] = pointer;
161
+ else
162
+ delete all[world];
163
+ try {
164
+ writeFileAtomic(this.pointerPath(), JSON.stringify(all, null, 2) + "\n");
165
+ }
166
+ catch (err) {
167
+ this.ctx.log("warn", "Needs you: could not save where the live message is", { world, err: String(err?.message ?? err) });
168
+ }
169
+ }
170
+ lineTitle(item) { return this.ctx.t(`needs.reason.${item.reason}`); }
171
+ makeLive(world) {
172
+ const ctx = this.ctx;
173
+ const owner = Symbol(world.id);
174
+ return new NeedsYouLiveMessage({
175
+ world: world.id,
176
+ now: () => ctx.mono(),
177
+ setTimer: (fn, ms) => ctx.setTimer(fn, ms),
178
+ clearTimer: h => ctx.clearTimer(h),
179
+ target: () => { const t = ctx.noticeTarget(world.id); return t ? canonicalTarget(t) : null; },
180
+ enabled: () => ctx.settings().liveMessage,
181
+ stopping: () => ctx.stopping() || this.stopped,
182
+ // The same world means the same adapter object and place it was built for, not just the same id.
183
+ worldExists: () => ctx.worlds().some(w => w.id === world.id && w.adapter === world.adapter && placeKey(w.place) === placeKey(world.place)),
184
+ content: () => {
185
+ const mine = itemsForWorld(this.items, world.id);
186
+ const lines = mine.map(item => ({
187
+ item, title: this.lineTitle(item),
188
+ link: item.promptAt ? messageLink(world.place, item.promptAt) : instanceLink(world.place, ctx.instanceTopic(item.instance)),
189
+ }));
190
+ const rendered = renderLiveMessage(lines, ctx.now(), (k, ...a) => ctx.t(k, ...a));
191
+ return { empty: mine.length === 0, ...rendered };
192
+ },
193
+ post: async (target, text, choices) => {
194
+ const sent = await world.adapter.notifyAlert(target.chatId, { type: "needs_you", instanceName: "", message: text, choices }, target.threadId ? { threadId: target.threadId } : undefined);
195
+ return { ...canonicalTarget(target), messageId: sent.messageId };
196
+ },
197
+ edit: async (pointer, text, choices) => {
198
+ if (!world.adapter.editAlert)
199
+ throw new Error("adapter cannot edit an alert");
200
+ await world.adapter.editAlert(pointer.chatId, pointer.messageId, { type: "needs_you", instanceName: "", message: text, choices }, pointer.threadId ? { threadId: pointer.threadId } : undefined);
201
+ },
202
+ remove: async (pointer) => { await world.adapter.deleteMessage?.(pointer.chatId, pointer.messageId, pointer.threadId); },
203
+ loadPointer: () => this.readPointers()[world.id] ?? null,
204
+ savePointer: pointer => this.writePointer(world.id, pointer),
205
+ mintAcks: (generation, place, items) => this.mintAcks(world.id, owner, generation, place, items),
206
+ revokeAcks: () => this.revokeAcks(owner),
207
+ log: (message, extra) => ctx.log("info", `Needs you: ${message}`, extra),
208
+ text: { stopped: ctx.t("needs.live_stopped"), off: ctx.t("needs.live_off") },
209
+ });
210
+ }
211
+ mintAcks(world, owner, generation, place, items) {
212
+ const minted = [];
213
+ const choices = items.filter(i => i.deliveryId).map(item => {
214
+ const nonce = randomBytes(16).toString("hex");
215
+ const entry = {
216
+ world, owner, generation, deadline: this.ctx.mono() + ACK_TTL_MS, chatId: place.chatId, ...(place.threadId !== undefined ? { threadId: place.threadId } : {}),
217
+ ...(place.messageId ? { messageId: place.messageId } : {}), deliveryId: item.deliveryId, instance: item.instance,
218
+ };
219
+ this.acks.set(nonce, entry);
220
+ minted.push(entry);
221
+ return { id: `${NEEDS_ACK_PREFIX}${nonce}:ack`, label: this.ctx.t("needs.ack_button", item.instance) };
222
+ });
223
+ return { choices, bind: pointer => { for (const e of minted)
224
+ e.messageId = pointer.messageId; } };
225
+ }
226
+ revokeAcks(owner) {
227
+ for (const [nonce, e] of this.acks)
228
+ if (e.owner === owner)
229
+ this.acks.delete(nonce);
230
+ }
231
+ // ── Acknowledge ────────────────────────────────────────────────────────────────────────────────────────────
232
+ /**
233
+ * A click on a live message's Acknowledge. true when it was ours (handled, whatever the answer), false otherwise.
234
+ * Stale capabilities (an older render, a replaced message, a restart) only answer the clicker: the live message is
235
+ * never edited from here — that would strip the current keyboard of the same message.
236
+ */
237
+ handleCallback(data, adapterId) {
238
+ if (!data.callbackData.startsWith(NEEDS_ACK_PREFIX))
239
+ return false;
240
+ const m = ACK_RE.exec(data.callbackData);
241
+ const entry = m ? this.acks.get(m[1]) : undefined;
242
+ if (entry && this.ctx.mono() >= entry.deadline)
243
+ this.acks.delete(m[1]);
244
+ // Unknown, revoked, lapsed — or not yet bound to the message its post returned: no authority yet.
245
+ if (!m || !entry || this.ctx.mono() >= entry.deadline || entry.messageId === undefined) {
246
+ data.ack?.(this.ctx.t("needs.ack_stale"));
247
+ return true;
248
+ }
249
+ const wrongPlace = entry.world !== adapterId || entry.chatId !== data.chatId
250
+ || (entry.threadId !== undefined && data.threadId !== entry.threadId)
251
+ || data.messageId !== entry.messageId;
252
+ if (wrongPlace) {
253
+ data.ack?.(this.ctx.t("buttons.wrong_place"));
254
+ return true;
255
+ }
256
+ if (!data.userId || !this.ctx.isFleetAdmin(data.userId, adapterId)) {
257
+ data.ack?.(this.ctx.t("buttons.admin_only"));
258
+ return true;
259
+ }
260
+ // §5.0: the item must still belong to this world.
261
+ if (this.ctx.ownerOf(entry.instance) !== adapterId) {
262
+ data.ack?.(this.ctx.t("needs.ack_not_this_world"));
263
+ return true;
264
+ }
265
+ const platform = this.ctx.worlds().find(w => w.id === adapterId)?.place.type ?? "chat";
266
+ data.ack?.(this.ctx.t(`needs.ack_${this.acknowledge(entry.deliveryId, `${platform}:${data.userId}`)}`));
267
+ return true;
268
+ }
269
+ /** The web's Acknowledge: any item (the web is global, §5.0). `principal` is "web:<session handle>" or "cli". */
270
+ webAcknowledge(itemId, principal) {
271
+ const m = /^delivery:([A-Za-z0-9._:-]{1,128})$/.exec(itemId);
272
+ if (!m)
273
+ return { status: 400, message: "Not an item that can be acknowledged" };
274
+ const listed = this.items.some(i => i.id === itemId);
275
+ if (!listed)
276
+ return { status: 409, message: this.ctx.t("needs.ack_already") };
277
+ const outcome = this.acknowledge(m[1], principal);
278
+ return { status: outcome === "failed" ? 500 : 200, message: this.ctx.t(`needs.ack_${outcome}`) };
279
+ }
280
+ /** done: this call acknowledged it; already: acknowledged, delivered or gone meanwhile; failed: not recorded. */
281
+ acknowledge(deliveryId, by) {
282
+ let done;
283
+ try {
284
+ done = this.ctx.acknowledge(deliveryId, by);
285
+ }
286
+ catch (err) {
287
+ this.ctx.log("warn", "Needs you: could not record an acknowledgement", { deliveryId, err: String(err?.message ?? err) });
288
+ return "failed";
289
+ }
290
+ this.poke();
291
+ if (done)
292
+ this.ctx.log("info", "Needs you: delivery acknowledged", { deliveryId, by });
293
+ return done ? "done" : "already";
294
+ }
295
+ // ── DMs (§5.5) ─────────────────────────────────────────────────────────────────────────────────────────────
296
+ queueDms(world, mine, now) {
297
+ const seen = this.dmSeen.get(world.id) ?? new Set();
298
+ const due = mine.filter(i => !seen.has(i.id) && (i.type !== "awaiting_input" || now - i.since >= AWAITING_PING_MIN_MS));
299
+ for (const i of due)
300
+ seen.add(i.id);
301
+ // Forget ids that are gone, so a recurrence (a new id anyway) is not confused with an old one.
302
+ const listed = new Set(mine.map(i => i.id));
303
+ for (const id of [...seen])
304
+ if (!listed.has(id))
305
+ seen.delete(id);
306
+ this.dmSeen.set(world.id, seen);
307
+ if (due.length === 0)
308
+ return;
309
+ const pending = this.dmPending.get(world.id) ?? new Set();
310
+ for (const i of due)
311
+ pending.add(i.id);
312
+ this.dmPending.set(world.id, pending);
313
+ this.scheduleDms(world.id);
314
+ }
315
+ /** One timer per world; it sends at once when the minute since the last DM has passed. */
316
+ scheduleDms(worldId) {
317
+ if (this.dmTimer.has(worldId))
318
+ return;
319
+ const last = this.dmLastAt.get(worldId) ?? -Infinity;
320
+ const wait = Math.max(0, last + DM_MIN_MS - this.ctx.mono());
321
+ this.dmTimer.set(worldId, this.ctx.setTimer(() => { this.dmTimer.delete(worldId); this.flushDms(worldId); }, wait));
322
+ }
323
+ cancelDms(worldId) {
324
+ const timer = this.dmTimer.get(worldId);
325
+ if (timer !== undefined)
326
+ this.ctx.clearTimer(timer);
327
+ this.dmTimer.delete(worldId);
328
+ this.dmPending.delete(worldId);
329
+ }
330
+ /**
331
+ * Send what is pending — re-resolved now (#1398 review): only items still listed AND still owned by this world, to
332
+ * this world's admins as they are now, through its current adapter; nothing at all once DMs are off, the world is
333
+ * gone, or the hub is stopped.
334
+ */
335
+ flushDms(worldId) {
336
+ const ids = this.dmPending.get(worldId) ?? new Set();
337
+ this.dmPending.delete(worldId);
338
+ if (this.stopped || ids.size === 0 || !this.ctx.settings().dm || this.ctx.stopping())
339
+ return;
340
+ const world = this.ctx.worlds().find(w => w.id === worldId);
341
+ if (!world || !world.adapter.sendDirect)
342
+ return;
343
+ // Owned by this world NOW — asked of the fleet per item, not taken from the last derivation (#1398 review r2).
344
+ const still = this.items.filter(i => ids.has(i.id) && this.ctx.ownerOf(i.instance) === worldId);
345
+ if (still.length === 0)
346
+ return;
347
+ this.dmLastAt.set(worldId, this.ctx.mono());
348
+ const text = [this.ctx.t("needs.dm_header", still.length), ...still.slice(0, 10).map(item => {
349
+ const link = item.promptAt ? messageLink(world.place, item.promptAt) : instanceLink(world.place, this.ctx.instanceTopic(item.instance));
350
+ return `• ${item.instance} — ${this.lineTitle(item)}${link ? ` · ${link}` : ""}`;
351
+ })].join("\n");
352
+ for (const admin of this.ctx.fleetAdmins(worldId)) {
353
+ // Telegram: only an admin who has started the bot can be messaged; the send fails otherwise, and that is fine.
354
+ world.adapter.sendDirect(admin, text).catch(err => this.ctx.log("debug", "Needs you: DM not delivered", { world: worldId, err: String(err?.message ?? err) }));
355
+ }
356
+ }
357
+ /** Shutdown: every live message says so, without buttons; no further renders or DMs. */
358
+ async stop() {
359
+ this.stopped = true;
360
+ if (this.pending !== null)
361
+ this.ctx.clearTimer(this.pending);
362
+ if (this.backstop !== null)
363
+ this.ctx.clearTimer(this.backstop);
364
+ for (const id of [...this.dmPending.keys(), ...this.dmTimer.keys()])
365
+ this.cancelDms(id);
366
+ await Promise.all([...this.live.values()].map(p => p.renderer.retire()));
367
+ this.acks.clear();
368
+ }
369
+ }
370
+ //# sourceMappingURL=needs-you-hub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"needs-you-hub.js","sourceRoot":"","sources":["../src/needs-you-hub.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * #1386 §5.1–5.4: one world's live "Needs you" message in its General — kept current, without flooding, and never
3
+ * left holding a capability it should not.
4
+ *
5
+ * - **Generations (§5.2a).** Every render is a generation. Its Acknowledge capabilities are minted for it, and the
6
+ * previous generation's are revoked *before the render's first await* — an old button is stale from that moment,
7
+ * whether or not the edit lands. Expiry never edits the message: the message is renewed at least every
8
+ * RENEW_MS.
9
+ * - **Single flight with fences (§5.3a).** One render at a time; a change meanwhile schedules exactly one more. After
10
+ * every await (post/edit/delete ACK) the render continues only if its generation is current, the feature is on,
11
+ * the world exists, the target is the one it started with, and the fleet is not stopping. Otherwise nothing is
12
+ * persisted, its capabilities are revoked, and a late post is deleted.
13
+ * - **Edit vs new post (§5.3).** Changes edit in place (debounced, at most one edit per EDIT_MIN_MS). A new item
14
+ * replaces the message with a new post — at the bottom, so people are notified — at most once per POST_MIN_MS;
15
+ * one inside that window is shown by an edit and posted when the window opens.
16
+ * - **The pointer (§5.4).** Reused only at the same canonical place; a moved target never receives this world's list
17
+ * at its former destination (the old message is deleted best effort, without new content).
18
+ *
19
+ * Every effect is injected; times come from a monotonic clock.
20
+ */
21
+ import type { NeedsYouItem } from "./needs-you.js";
22
+ export interface LiveTarget {
23
+ chatId: string;
24
+ threadId?: string;
25
+ }
26
+ export interface LivePointer extends LiveTarget {
27
+ messageId: string;
28
+ }
29
+ export interface LiveChoice {
30
+ id: string;
31
+ label: string;
32
+ }
33
+ export interface LiveContent {
34
+ /** Nothing waits on this world: no message is posted for it if none exists yet. */
35
+ empty: boolean;
36
+ text: string;
37
+ /** Delivery items that get an Acknowledge button on this render. */
38
+ ackable: NeedsYouItem[];
39
+ }
40
+ /** Capabilities minted for one render; `bind` fixes the message id once a post returns it. */
41
+ export interface LiveAcks {
42
+ choices: LiveChoice[];
43
+ bind(pointer: LivePointer): void;
44
+ }
45
+ export interface LiveDeps {
46
+ world: string;
47
+ now(): number;
48
+ setTimer(fn: () => void, ms: number): unknown;
49
+ clearTimer(handle: unknown): void;
50
+ /** The current canonical General target, or null when this world has none. */
51
+ target(): LiveTarget | null;
52
+ enabled(): boolean;
53
+ stopping(): boolean;
54
+ worldExists(): boolean;
55
+ /** This world's current content. */
56
+ content(): LiveContent;
57
+ post(target: LiveTarget, text: string, choices: LiveChoice[]): Promise<LivePointer>;
58
+ edit(pointer: LivePointer, text: string, choices: LiveChoice[]): Promise<void>;
59
+ remove(pointer: LivePointer): Promise<void>;
60
+ loadPointer(): LivePointer | null;
61
+ savePointer(pointer: LivePointer | null): void;
62
+ /** Mint Acknowledge capabilities for `generation`, bound to `place` (the message id may follow via bind). */
63
+ mintAcks(generation: number, place: LiveTarget & {
64
+ messageId?: string;
65
+ }, items: NeedsYouItem[]): LiveAcks;
66
+ /** Revoke every Acknowledge capability this world holds (all generations). */
67
+ revokeAcks(): void;
68
+ log(message: string, extra?: Record<string, unknown>): void;
69
+ text: {
70
+ stopped: string;
71
+ off: string;
72
+ };
73
+ }
74
+ export declare const DEBOUNCE_MS = 3000;
75
+ export declare const EDIT_MIN_MS = 10000;
76
+ export declare const POST_MIN_MS = 60000;
77
+ export declare const RENEW_MS: number;
78
+ /** A failed post backs off from POST_MIN_MS, doubling, up to this (#1398 review: never a tight retry loop). */
79
+ export declare const POST_BACKOFF_MAX_MS: number;
80
+ /** Telegram General is topic "1" on input and no thread on the wire: both are the same place. */
81
+ export declare function canonicalTarget(target: LiveTarget): LiveTarget;
82
+ export declare function samePlace(a: LiveTarget, b: LiveTarget): boolean;
83
+ export declare class NeedsYouLiveMessage {
84
+ private readonly deps;
85
+ private generation;
86
+ private pointer;
87
+ private inFlight;
88
+ private rerun;
89
+ private timer;
90
+ private dueAt;
91
+ private lastEditAt;
92
+ /** No post (of any kind: first, moved, new item, edit fallback) before this monotonic time. */
93
+ private nextPostAt;
94
+ private postFailures;
95
+ private postWanted;
96
+ private retired;
97
+ constructor(deps: LiveDeps);
98
+ /** The list changed. `newIds`: an item appeared that this world has not shown before (→ a new post, rate-limited). */
99
+ changed(newIds: boolean): void;
100
+ /** Current generation (tests and the ack handler's generation check). */
101
+ get currentGeneration(): number;
102
+ get currentPointer(): LivePointer | null;
103
+ private requestAt;
104
+ private scheduleRenewal;
105
+ /** One render. Public for tests; normal use goes through changed(). */
106
+ render(): Promise<void>;
107
+ private fenced;
108
+ private renderOnce;
109
+ private postNew;
110
+ /** Shutdown: revoke first, then say so on the message, without buttons. No further renders. */
111
+ retire(): Promise<void>;
112
+ /** Replaced by another renderer (a new adapter under this world's id): stop and revoke, touching nothing remote. */
113
+ abandon(): void;
114
+ /** live_message turned off (or the world removed): revoke, mark the message, forget it. */
115
+ disable(): Promise<void>;
116
+ }