@songsid/agend 2.1.12 → 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,228 @@
1
+ export const DEBOUNCE_MS = 3_000;
2
+ export const EDIT_MIN_MS = 10_000;
3
+ export const POST_MIN_MS = 60_000;
4
+ export const RENEW_MS = 10 * 60_000;
5
+ /** A failed post backs off from POST_MIN_MS, doubling, up to this (#1398 review: never a tight retry loop). */
6
+ export const POST_BACKOFF_MAX_MS = 15 * 60_000;
7
+ /** Telegram General is topic "1" on input and no thread on the wire: both are the same place. */
8
+ export function canonicalTarget(target) {
9
+ const thread = target.threadId === undefined || target.threadId === "" || target.threadId === "1" ? undefined : String(target.threadId);
10
+ return thread === undefined ? { chatId: String(target.chatId) } : { chatId: String(target.chatId), threadId: thread };
11
+ }
12
+ export function samePlace(a, b) {
13
+ const x = canonicalTarget(a), y = canonicalTarget(b);
14
+ return x.chatId === y.chatId && x.threadId === y.threadId;
15
+ }
16
+ export class NeedsYouLiveMessage {
17
+ deps;
18
+ generation = 0;
19
+ pointer;
20
+ inFlight = false;
21
+ rerun = false;
22
+ timer = null;
23
+ dueAt = Infinity;
24
+ lastEditAt = -Infinity;
25
+ /** No post (of any kind: first, moved, new item, edit fallback) before this monotonic time. */
26
+ nextPostAt = -Infinity;
27
+ postFailures = 0;
28
+ postWanted = false;
29
+ retired = false;
30
+ constructor(deps) {
31
+ this.deps = deps;
32
+ this.pointer = deps.loadPointer();
33
+ // A restart has no capabilities: render at once so the message gets fresh ones (pre-restart buttons are stale).
34
+ this.requestAt(deps.now());
35
+ }
36
+ /** The list changed. `newIds`: an item appeared that this world has not shown before (→ a new post, rate-limited). */
37
+ changed(newIds) {
38
+ if (this.retired)
39
+ return;
40
+ if (newIds)
41
+ this.postWanted = true;
42
+ const now = this.deps.now();
43
+ let at = now + DEBOUNCE_MS;
44
+ if (this.postWanted)
45
+ at = Math.max(at, Math.min(this.nextPostAt, this.lastEditAt + EDIT_MIN_MS));
46
+ else
47
+ at = Math.max(at, this.lastEditAt + EDIT_MIN_MS);
48
+ this.requestAt(at);
49
+ }
50
+ /** Current generation (tests and the ack handler's generation check). */
51
+ get currentGeneration() { return this.generation; }
52
+ get currentPointer() { return this.pointer; }
53
+ requestAt(at) {
54
+ if (this.retired || at >= this.dueAt)
55
+ return;
56
+ if (this.timer !== null)
57
+ this.deps.clearTimer(this.timer);
58
+ this.dueAt = at;
59
+ this.timer = this.deps.setTimer(() => { this.timer = null; this.dueAt = Infinity; void this.render(); }, Math.max(0, at - this.deps.now()));
60
+ }
61
+ scheduleRenewal() {
62
+ this.requestAt(this.deps.now() + RENEW_MS);
63
+ }
64
+ /** One render. Public for tests; normal use goes through changed(). */
65
+ async render() {
66
+ if (this.retired)
67
+ return;
68
+ if (this.inFlight) {
69
+ this.rerun = true;
70
+ return;
71
+ }
72
+ this.inFlight = true;
73
+ try {
74
+ await this.renderOnce();
75
+ }
76
+ finally {
77
+ this.inFlight = false;
78
+ if (this.rerun && !this.retired) {
79
+ this.rerun = false;
80
+ this.requestAt(this.deps.now());
81
+ }
82
+ else if (!this.retired) {
83
+ // A new item shown by an edit inside the post window is posted when the window opens.
84
+ if (this.postWanted)
85
+ this.requestAt(Math.max(this.deps.now(), this.nextPostAt));
86
+ if (this.timer === null)
87
+ this.scheduleRenewal();
88
+ }
89
+ }
90
+ }
91
+ fenced(generation, target) {
92
+ const now = this.deps.target();
93
+ return generation === this.generation && !this.retired && this.deps.enabled() && !this.deps.stopping()
94
+ && this.deps.worldExists() && now !== null && samePlace(now, target);
95
+ }
96
+ async renderOnce() {
97
+ const target = this.deps.target();
98
+ if (!this.deps.enabled() || this.deps.stopping() || !this.deps.worldExists() || target === null)
99
+ return;
100
+ const generation = ++this.generation;
101
+ // Revoke before await: every earlier generation's buttons are stale from here on, whatever happens below.
102
+ this.deps.revokeAcks();
103
+ const content = this.deps.content();
104
+ const now = this.deps.now();
105
+ // Nothing to say and nothing said yet: a fleet that never needed anyone posts nothing.
106
+ if (this.pointer === null && content.empty) {
107
+ this.postWanted = false;
108
+ return;
109
+ }
110
+ const moved = this.pointer !== null && !samePlace(this.pointer, target);
111
+ const mayPost = now >= this.nextPostAt;
112
+ if (this.pointer === null || moved) {
113
+ // Only a post will do. Not yet allowed (a failed one is backing off): try again when it is.
114
+ if (!mayPost) {
115
+ this.postWanted = true;
116
+ return;
117
+ }
118
+ await this.postNew(generation, target, content, moved);
119
+ return;
120
+ }
121
+ if (this.postWanted && mayPost) {
122
+ await this.postNew(generation, target, content, false);
123
+ return;
124
+ }
125
+ const pointer = this.pointer;
126
+ const acks = this.deps.mintAcks(generation, pointer, content.ackable);
127
+ try {
128
+ await this.deps.edit(pointer, content.text, acks.choices);
129
+ }
130
+ catch (err) {
131
+ if (!this.fenced(generation, target)) {
132
+ this.deps.revokeAcks();
133
+ return;
134
+ }
135
+ this.deps.revokeAcks();
136
+ if (this.deps.now() < this.nextPostAt) {
137
+ // The fallback post is rate-limited like any other: try again when it may.
138
+ this.deps.log("live message edit failed; will post when allowed", { world: this.deps.world, err: String(err?.message ?? err) });
139
+ this.postWanted = true;
140
+ return;
141
+ }
142
+ this.deps.log("live message edit failed; posting a new one", { world: this.deps.world, err: String(err?.message ?? err) });
143
+ const next = ++this.generation;
144
+ await this.postNew(next, target, this.deps.content(), false);
145
+ return;
146
+ }
147
+ if (!this.fenced(generation, target)) {
148
+ this.deps.revokeAcks();
149
+ return;
150
+ }
151
+ this.lastEditAt = this.deps.now();
152
+ }
153
+ async postNew(generation, target, content, moved) {
154
+ const old = this.pointer;
155
+ const acks = this.deps.mintAcks(generation, canonicalTarget(target), content.ackable);
156
+ let sent;
157
+ try {
158
+ sent = await this.deps.post(target, content.text, acks.choices);
159
+ }
160
+ catch (err) {
161
+ this.deps.revokeAcks();
162
+ this.postFailures++;
163
+ const backoff = Math.min(POST_MIN_MS * 2 ** (this.postFailures - 1), POST_BACKOFF_MAX_MS);
164
+ this.nextPostAt = this.deps.now() + backoff;
165
+ this.postWanted = true; // retried — no sooner than nextPostAt
166
+ this.deps.log("live message post failed", { world: this.deps.world, err: String(err?.message ?? err), retryInMs: backoff });
167
+ return;
168
+ }
169
+ if (!this.fenced(generation, target)) {
170
+ // A late ACK: disabled, rebound, superseded or stopping meanwhile. Publish nothing current.
171
+ this.deps.revokeAcks();
172
+ void this.deps.remove(sent).catch(() => { });
173
+ return;
174
+ }
175
+ acks.bind(sent);
176
+ this.pointer = sent;
177
+ this.deps.savePointer(sent);
178
+ const at = this.deps.now();
179
+ this.nextPostAt = at + POST_MIN_MS;
180
+ this.postFailures = 0;
181
+ this.lastEditAt = at;
182
+ this.postWanted = false;
183
+ // The previous message goes — without new content, so a moved target's former destination never gets this list.
184
+ if (old !== null && !(old.messageId === sent.messageId && samePlace(old, sent))) {
185
+ void this.deps.remove(old).catch(err => this.deps.log(moved ? "could not remove the live message at its former target" : "could not remove the previous live message", { world: this.deps.world, err: String(err?.message ?? err) }));
186
+ }
187
+ }
188
+ /** Shutdown: revoke first, then say so on the message, without buttons. No further renders. */
189
+ async retire() {
190
+ if (this.retired)
191
+ return;
192
+ this.retired = true;
193
+ if (this.timer !== null) {
194
+ this.deps.clearTimer(this.timer);
195
+ this.timer = null;
196
+ }
197
+ this.deps.revokeAcks();
198
+ this.generation++;
199
+ if (this.pointer)
200
+ await this.deps.edit(this.pointer, this.deps.text.stopped, []).catch(() => { });
201
+ }
202
+ /** Replaced by another renderer (a new adapter under this world's id): stop and revoke, touching nothing remote. */
203
+ abandon() {
204
+ if (this.timer !== null) {
205
+ this.deps.clearTimer(this.timer);
206
+ this.timer = null;
207
+ }
208
+ this.retired = true;
209
+ this.deps.revokeAcks();
210
+ this.generation++;
211
+ }
212
+ /** live_message turned off (or the world removed): revoke, mark the message, forget it. */
213
+ async disable() {
214
+ if (this.timer !== null) {
215
+ this.deps.clearTimer(this.timer);
216
+ this.timer = null;
217
+ }
218
+ this.retired = true;
219
+ this.deps.revokeAcks();
220
+ this.generation++;
221
+ const pointer = this.pointer;
222
+ this.pointer = null;
223
+ this.deps.savePointer(null);
224
+ if (pointer)
225
+ await this.deps.edit(pointer, this.deps.text.off, []).catch(() => { });
226
+ }
227
+ }
228
+ //# sourceMappingURL=needs-you-live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"needs-you-live.js","sourceRoot":"","sources":["../src/needs-you-live.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * #1386 "Needs you": one list of everything currently waiting on the person, derived — on demand, never stored —
3
+ * from state the fleet already holds. Design: docs/design/1386-needs-you-inbox.md (§3 sources, §4 derivation).
4
+ *
5
+ * This module is pure: the fleet collects the inputs, this decides the items, which world owns each, what the
6
+ * rendered list is (its signature), and the live chat message's text and links. Nothing here touches a socket,
7
+ * a file or a clock of its own.
8
+ */
9
+ export type NeedsYouType = "prompt" | "awaiting_input" | "instance" | "delivery";
10
+ export interface NeedsYouItem {
11
+ /** Stable per occurrence: a new episode, crash or delivery is a new id (§3). */
12
+ id: string;
13
+ type: NeedsYouType;
14
+ /** The instance to open; a delivery's is its target. */
15
+ instance: string;
16
+ /** The world (adapter id) that owns the instance, or undefined: listed only in /ui (§5.0). */
17
+ owner?: string;
18
+ /** Which kind of wait, for the title (localized by the renderer, not here). */
19
+ reason: NeedsYouReason;
20
+ /** One line, may be "": a prompt's text, an interaction summary, "source → target · kind". */
21
+ detail: string;
22
+ /** Epoch ms when it started waiting. */
23
+ since: number;
24
+ /** prompt: the nonce the web answers through POST /ui/prompt, its buttons, and where the buttons are. */
25
+ nonce?: string;
26
+ actions?: Array<{
27
+ id: string;
28
+ label: string;
29
+ }>;
30
+ promptAt?: {
31
+ adapterId: string;
32
+ chatId: string;
33
+ threadId?: string;
34
+ messageId?: string;
35
+ };
36
+ /** delivery: the outbox row; Acknowledge offered. */
37
+ deliveryId?: string;
38
+ }
39
+ export type NeedsYouReason = "hang" | "exited" | "assist" | "permission" | "dangerous_command" | "login" | "dialog" | "terminal_input" | "auth_paused" | "crashed" | "delivery_uncertain" | "delivery_failed";
40
+ /** A fleet prompt offered on the dashboard (hang / exit-restart / interactive-assist), as the fleet holds it. */
41
+ export interface PromptInput {
42
+ nonce: string;
43
+ prefix: string;
44
+ instance: string;
45
+ text: string;
46
+ actions: Array<{
47
+ id: string;
48
+ label: string;
49
+ }>;
50
+ createdAt: number;
51
+ adapterId: string;
52
+ chatId: string;
53
+ threadId?: string;
54
+ messageId?: string;
55
+ /** interactive-assist only: the interaction wait it was raised for (§3.2). */
56
+ assistFor?: {
57
+ owner: string | null;
58
+ episode: number | null;
59
+ };
60
+ }
61
+ export interface InstanceInput {
62
+ name: string;
63
+ /** presentation state: "awaiting_input" when the CLI waits at its terminal and that is not stale/suspected. */
64
+ state?: string;
65
+ interaction?: {
66
+ kind?: string | null;
67
+ owner?: string | null;
68
+ episode?: number | null;
69
+ since?: number | null;
70
+ } | null;
71
+ interactionSummary?: string | null;
72
+ /** The pause marker's reason, for a paused instance; and when it was paused. */
73
+ pauseReason?: string | null;
74
+ pausedAt?: number | null;
75
+ /** "crashed" with the time the fleet first saw it so (§3.3). */
76
+ crashedAt?: number | null;
77
+ }
78
+ export interface DeliveryInput {
79
+ deliveryId: string;
80
+ state: "uncertain" | "failed";
81
+ source: string;
82
+ target: string;
83
+ kind: string;
84
+ finishedAt: number;
85
+ }
86
+ export interface NeedsYouInputs {
87
+ prompts: PromptInput[];
88
+ instances: InstanceInput[];
89
+ deliveries: DeliveryInput[];
90
+ /** The live world that owns an instance, or undefined (no channel, or its world is gone). */
91
+ ownerOf: (instance: string) => string | undefined;
92
+ }
93
+ /** §3: every item, from the inputs only. Ordered by instance (the one with the oldest item first), then oldest first. */
94
+ export declare function deriveNeedsYou(inputs: NeedsYouInputs): NeedsYouItem[];
95
+ /** §5.0: the items a world's chat surfaces show — only those whose instance it owns. */
96
+ export declare function itemsForWorld(items: readonly NeedsYouItem[], world: string): NeedsYouItem[];
97
+ /** The age bucket shown next to an item: changes of it re-render, nothing finer does. */
98
+ export declare function ageLabel(sinceMs: number, nowMs: number): string;
99
+ /**
100
+ * §4.2: what a surface shows, as a string — ids in order, each item's displayed text and age bucket, and its action
101
+ * coordinates (the prompt message it links to, its owning world). Two lists with the same signature render the same.
102
+ * New-item notification is keyed on ids, separately; a re-render never notifies.
103
+ */
104
+ export declare function renderSignature(items: readonly NeedsYouItem[], nowMs: number): string;
105
+ export interface WorldPlace {
106
+ type: "discord" | "telegram" | string;
107
+ /** Discord: the guild id. Telegram: the supergroup id (-100…). */
108
+ groupId?: string;
109
+ }
110
+ /** A link to a message (a prompt's own buttons), or undefined when none can be built for this platform/place. */
111
+ export declare function messageLink(place: WorldPlace, at: {
112
+ chatId: string;
113
+ threadId?: string;
114
+ messageId?: string;
115
+ }): string | undefined;
116
+ /** A way to the instance's own thread: Discord's channel mention (clickable in place), Telegram's topic link. */
117
+ export declare function instanceLink(place: WorldPlace, topicId: string | undefined): string | undefined;
118
+ export interface LiveLine {
119
+ item: NeedsYouItem;
120
+ title: string;
121
+ link?: string;
122
+ }
123
+ export declare const LIVE_MAX_LINES = 10;
124
+ export declare const LIVE_MAX_ACKS = 5;
125
+ /**
126
+ * The live message for one world: header, at most LIVE_MAX_LINES lines (then "… and N more"), and which delivery
127
+ * items get an Acknowledge button (the newest LIVE_MAX_ACKS of those shown). `t` localizes.
128
+ */
129
+ export declare function renderLiveMessage(lines: readonly LiveLine[], nowMs: number, t: (key: string, ...args: Array<string | number>) => string): {
130
+ text: string;
131
+ ackable: NeedsYouItem[];
132
+ };
@@ -0,0 +1,164 @@
1
+ /**
2
+ * #1386 "Needs you": one list of everything currently waiting on the person, derived — on demand, never stored —
3
+ * from state the fleet already holds. Design: docs/design/1386-needs-you-inbox.md (§3 sources, §4 derivation).
4
+ *
5
+ * This module is pure: the fleet collects the inputs, this decides the items, which world owns each, what the
6
+ * rendered list is (its signature), and the live chat message's text and links. Nothing here touches a socket,
7
+ * a file or a clock of its own.
8
+ */
9
+ const PROMPT_REASON = {
10
+ "hang:": "hang",
11
+ "exit-restart:": "exited",
12
+ "interactive-assist:": "assist",
13
+ };
14
+ const INTERACTION_REASON = {
15
+ permission: "permission",
16
+ dangerous_command: "dangerous_command",
17
+ login: "login",
18
+ dialog: "dialog",
19
+ suspected_terminal_input: "terminal_input",
20
+ };
21
+ const oneLine = (text, max = 160) => {
22
+ const flat = text.replace(/\s+/g, " ").trim();
23
+ return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;
24
+ };
25
+ /** §3: every item, from the inputs only. Ordered by instance (the one with the oldest item first), then oldest first. */
26
+ export function deriveNeedsYou(inputs) {
27
+ const items = [];
28
+ // §3.1 prompts.
29
+ for (const p of inputs.prompts) {
30
+ const reason = PROMPT_REASON[p.prefix];
31
+ if (!reason)
32
+ continue;
33
+ items.push({
34
+ id: `prompt:${p.nonce}`, type: "prompt", instance: p.instance, reason,
35
+ detail: oneLine(p.text), since: p.createdAt, nonce: p.nonce, actions: p.actions,
36
+ promptAt: { adapterId: p.adapterId, chatId: p.chatId, ...(p.threadId !== undefined ? { threadId: p.threadId } : {}), ...(p.messageId ? { messageId: p.messageId } : {}) },
37
+ });
38
+ }
39
+ for (const inst of inputs.instances) {
40
+ // §3.2 awaiting_input — folded into an interactive-assist prompt only when it was raised for this same wait.
41
+ if (inst.state === "awaiting_input" && inst.interaction) {
42
+ const episode = inst.interaction.episode ?? null;
43
+ const owner = inst.interaction.owner ?? null;
44
+ const folded = inputs.prompts.some(p => p.prefix === "interactive-assist:" && p.instance === inst.name
45
+ && p.assistFor !== undefined && p.assistFor.episode === episode && p.assistFor.owner === owner);
46
+ if (!folded) {
47
+ items.push({
48
+ id: `awaiting:${inst.name}:${owner ?? "-"}:${episode ?? "-"}`, type: "awaiting_input", instance: inst.name,
49
+ reason: INTERACTION_REASON[inst.interaction.kind ?? ""] ?? "dialog",
50
+ detail: oneLine(inst.interactionSummary ?? ""), since: inst.interaction.since ?? 0,
51
+ });
52
+ }
53
+ }
54
+ // §3.3 instance: paused for sign-in, or crashed.
55
+ if (inst.pauseReason === "auth") {
56
+ items.push({ id: `auth:${inst.name}:${inst.pausedAt ?? 0}`, type: "instance", instance: inst.name, reason: "auth_paused", detail: "", since: inst.pausedAt ?? 0 });
57
+ }
58
+ if (inst.crashedAt != null) {
59
+ items.push({ id: `crashed:${inst.name}:${inst.crashedAt}`, type: "instance", instance: inst.name, reason: "crashed", detail: "", since: inst.crashedAt });
60
+ }
61
+ }
62
+ // §3.4 deliveries (already filtered by the outbox: unacknowledged, last 24 h, newest 50).
63
+ for (const d of inputs.deliveries) {
64
+ items.push({
65
+ id: `delivery:${d.deliveryId}`, type: "delivery", instance: d.target,
66
+ reason: d.state === "uncertain" ? "delivery_uncertain" : "delivery_failed",
67
+ detail: oneLine(`${d.source} → ${d.target} · ${d.kind}`), since: d.finishedAt, deliveryId: d.deliveryId,
68
+ });
69
+ }
70
+ for (const item of items) {
71
+ const owner = inputs.ownerOf(item.instance);
72
+ if (owner !== undefined)
73
+ item.owner = owner;
74
+ }
75
+ // Group by instance; instances ordered by their oldest item, items oldest first.
76
+ const oldest = new Map();
77
+ for (const item of items)
78
+ oldest.set(item.instance, Math.min(oldest.get(item.instance) ?? Infinity, item.since));
79
+ return items.sort((a, b) => (oldest.get(a.instance) - oldest.get(b.instance)) || a.instance.localeCompare(b.instance) || (a.since - b.since) || a.id.localeCompare(b.id));
80
+ }
81
+ /** §5.0: the items a world's chat surfaces show — only those whose instance it owns. */
82
+ export function itemsForWorld(items, world) {
83
+ return items.filter(item => item.owner === world);
84
+ }
85
+ /** The age bucket shown next to an item: changes of it re-render, nothing finer does. */
86
+ export function ageLabel(sinceMs, nowMs) {
87
+ const minutes = Math.max(0, Math.floor((nowMs - sinceMs) / 60_000));
88
+ if (minutes < 1)
89
+ return "<1m";
90
+ if (minutes < 60)
91
+ return `${minutes}m`;
92
+ const hours = Math.floor(minutes / 60);
93
+ return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;
94
+ }
95
+ /**
96
+ * §4.2: what a surface shows, as a string — ids in order, each item's displayed text and age bucket, and its action
97
+ * coordinates (the prompt message it links to, its owning world). Two lists with the same signature render the same.
98
+ * New-item notification is keyed on ids, separately; a re-render never notifies.
99
+ */
100
+ export function renderSignature(items, nowMs) {
101
+ return JSON.stringify(items.map(i => [
102
+ i.id, i.reason, i.detail, ageLabel(i.since, nowMs), i.owner ?? null,
103
+ i.promptAt ? [i.promptAt.adapterId, i.promptAt.chatId, i.promptAt.threadId ?? null, i.promptAt.messageId ?? null] : null,
104
+ ]));
105
+ }
106
+ const SNOWFLAKE = /^\d{5,25}$/;
107
+ /** A link to a message (a prompt's own buttons), or undefined when none can be built for this platform/place. */
108
+ export function messageLink(place, at) {
109
+ if (!at.messageId)
110
+ return undefined;
111
+ if (place.type === "discord") {
112
+ const channel = at.threadId ?? at.chatId;
113
+ if (!place.groupId || !SNOWFLAKE.test(place.groupId) || !SNOWFLAKE.test(channel) || !SNOWFLAKE.test(at.messageId))
114
+ return undefined;
115
+ return `https://discord.com/channels/${place.groupId}/${channel}/${at.messageId}`;
116
+ }
117
+ if (place.type === "telegram") {
118
+ const internal = telegramInternalId(at.chatId);
119
+ if (!internal || !/^\d+$/.test(at.messageId))
120
+ return undefined;
121
+ const topic = at.threadId && at.threadId !== "1" && /^\d+$/.test(at.threadId) ? `${at.threadId}/` : "";
122
+ return `https://t.me/c/${internal}/${topic}${at.messageId}`;
123
+ }
124
+ return undefined;
125
+ }
126
+ /** A way to the instance's own thread: Discord's channel mention (clickable in place), Telegram's topic link. */
127
+ export function instanceLink(place, topicId) {
128
+ if (!topicId)
129
+ return undefined;
130
+ if (place.type === "discord")
131
+ return SNOWFLAKE.test(topicId) ? `<#${topicId}>` : undefined;
132
+ if (place.type === "telegram") {
133
+ const internal = telegramInternalId(place.groupId ?? "");
134
+ return internal && /^\d+$/.test(topicId) && topicId !== "1" ? `https://t.me/c/${internal}/${topicId}` : undefined;
135
+ }
136
+ return undefined;
137
+ }
138
+ /** t.me/c/ links take a supergroup's id without its -100 prefix; anything else has no such link. */
139
+ function telegramInternalId(chatId) {
140
+ const m = /^-100(\d+)$/.exec(chatId);
141
+ return m ? m[1] : undefined;
142
+ }
143
+ export const LIVE_MAX_LINES = 10;
144
+ export const LIVE_MAX_ACKS = 5;
145
+ /**
146
+ * The live message for one world: header, at most LIVE_MAX_LINES lines (then "… and N more"), and which delivery
147
+ * items get an Acknowledge button (the newest LIVE_MAX_ACKS of those shown). `t` localizes.
148
+ */
149
+ export function renderLiveMessage(lines, nowMs, t) {
150
+ if (lines.length === 0)
151
+ return { text: t("needs.live_empty"), ackable: [] };
152
+ const shown = lines.slice(0, LIVE_MAX_LINES);
153
+ const body = shown.map(l => {
154
+ const age = ageLabel(l.item.since, nowMs);
155
+ const head = `• ${l.item.instance} — ${l.title} (${age})`;
156
+ return l.link ? `${head} · ${l.link}` : head;
157
+ });
158
+ if (lines.length > shown.length)
159
+ body.push(t("needs.live_more", lines.length - shown.length));
160
+ const ackable = shown.filter(l => l.item.type === "delivery").map(l => l.item)
161
+ .sort((a, b) => b.since - a.since).slice(0, LIVE_MAX_ACKS);
162
+ return { text: [t("needs.live_header", lines.length), ...body].join("\n"), ackable };
163
+ }
164
+ //# sourceMappingURL=needs-you.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"needs-you.js","sourceRoot":"","sources":["../src/needs-you.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Runtime version guard: better-sqlite3 v13 requires Node-API 10.
3
+ *
4
+ * Node-API 10 is available from:
5
+ * Node 22.14.0 (LTS) — released 2025-02-06
6
+ * Node 23.6.0 — released 2025-01-13
7
+ * Node 24+ — all releases
8
+ *
9
+ * This function is exported so tests can verify the exact boundary without
10
+ * duplicating the logic. The CLI bootstrap calls checkNodeVersion() at the
11
+ * very top so that even the OLD updater's `agend --version` verification
12
+ * will fail on an incompatible runtime, aborting the install.
13
+ *
14
+ * References:
15
+ * https://github.com/WiseLibs/better-sqlite3/blob/v13.0.3/binding.gyp
16
+ * https://nodejs.org/api/n-api.html#node-api-version-matrix
17
+ */
18
+ /** Returns true when the running Node supports N-API 10. */
19
+ export declare function isNodeCompatible(nodeVersion?: string): boolean;
20
+ /**
21
+ * Call at binary bootstrap. Prints a clear error and calls process.exit(1)
22
+ * when the running Node cannot load better-sqlite3's N-API 10 prebuilt.
23
+ *
24
+ * Placing this guard at bootstrap means:
25
+ * - `agend --version` exits 1 on incompatible Node
26
+ * - The OLD updater's verification step (`agend --version` → failUpdate on
27
+ * non-zero) aborts the install rather than letting a restart crash the fleet
28
+ * - Any DB command (`schedule list`, daemon start, …) is also blocked
29
+ */
30
+ export declare function checkNodeVersion(): void;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Runtime version guard: better-sqlite3 v13 requires Node-API 10.
3
+ *
4
+ * Node-API 10 is available from:
5
+ * Node 22.14.0 (LTS) — released 2025-02-06
6
+ * Node 23.6.0 — released 2025-01-13
7
+ * Node 24+ — all releases
8
+ *
9
+ * This function is exported so tests can verify the exact boundary without
10
+ * duplicating the logic. The CLI bootstrap calls checkNodeVersion() at the
11
+ * very top so that even the OLD updater's `agend --version` verification
12
+ * will fail on an incompatible runtime, aborting the install.
13
+ *
14
+ * References:
15
+ * https://github.com/WiseLibs/better-sqlite3/blob/v13.0.3/binding.gyp
16
+ * https://nodejs.org/api/n-api.html#node-api-version-matrix
17
+ */
18
+ /** Returns true when the running Node supports N-API 10. */
19
+ export function isNodeCompatible(nodeVersion = process.versions.node) {
20
+ const [majStr, minStr] = nodeVersion.split(".");
21
+ const maj = parseInt(majStr, 10);
22
+ const min = parseInt(minStr, 10);
23
+ if (maj >= 24)
24
+ return true;
25
+ if (maj === 23 && min >= 6)
26
+ return true;
27
+ if (maj === 22 && min >= 14)
28
+ return true;
29
+ return false;
30
+ }
31
+ /**
32
+ * Call at binary bootstrap. Prints a clear error and calls process.exit(1)
33
+ * when the running Node cannot load better-sqlite3's N-API 10 prebuilt.
34
+ *
35
+ * Placing this guard at bootstrap means:
36
+ * - `agend --version` exits 1 on incompatible Node
37
+ * - The OLD updater's verification step (`agend --version` → failUpdate on
38
+ * non-zero) aborts the install rather than letting a restart crash the fleet
39
+ * - Any DB command (`schedule list`, daemon start, …) is also blocked
40
+ */
41
+ export function checkNodeVersion() {
42
+ if (!isNodeCompatible()) {
43
+ process.stderr.write(`agend requires Node.js ^22.14.0 || ^23.6.0 || >=24.\n` +
44
+ `better-sqlite3 v13 uses Node-API 10, available from Node 22.14.0 / 23.6.0 / 24+.\n` +
45
+ `Running: Node ${process.version}.\n` +
46
+ `Upgrade Node first (e.g. nvm install 22), then restart.\n`);
47
+ process.exit(1);
48
+ }
49
+ }
50
+ //# sourceMappingURL=node-version-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-version-guard.js","sourceRoot":"","sources":["../src/node-version-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,4DAA4D;AAC5D,MAAM,UAAU,gBAAgB,CAAC,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI;IAClE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,GAAG,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,GAAG,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;QACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uDAAuD;YACvD,oFAAoF;YACpF,iBAAiB,OAAO,CAAC,OAAO,KAAK;YACrC,2DAA2D,CAC5D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Shared filesystem boundary for independent, same-user operator sockets. */
2
+ export declare function operatorUid(label: string): number;
3
+ export declare function assertOperatorRoot(dataDir: string, label: string): Promise<void>;
4
+ export declare function assertOperatorClientPath(dataDir: string, socketPath: string, label: string): Promise<void>;