@songsid/agend 2.2.0-alpha.1 → 2.2.0-alpha.3

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 (317) hide show
  1. package/README.md +6 -4
  2. package/README.zh-TW.md +6 -4
  3. package/dist/agent-cli.js +6 -1
  4. package/dist/agent-cli.js.map +1 -1
  5. package/dist/agent-endpoint.d.ts +4 -1
  6. package/dist/agent-endpoint.js +82 -14
  7. package/dist/agent-endpoint.js.map +1 -1
  8. package/dist/agent-token-header.d.ts +13 -0
  9. package/dist/agent-token-header.js +16 -0
  10. package/dist/agent-token-header.js.map +1 -0
  11. package/dist/atomic-write.d.ts +21 -0
  12. package/dist/atomic-write.js +65 -0
  13. package/dist/atomic-write.js.map +1 -0
  14. package/dist/auth-api.js +2 -0
  15. package/dist/auth-api.js.map +1 -1
  16. package/dist/backend/antigravity.js +4 -3
  17. package/dist/backend/antigravity.js.map +1 -1
  18. package/dist/backend/codex.d.ts +7 -0
  19. package/dist/backend/codex.js +7 -0
  20. package/dist/backend/codex.js.map +1 -1
  21. package/dist/backend/grok.js +1 -1
  22. package/dist/backend/grok.js.map +1 -1
  23. package/dist/backend/kiro.d.ts +7 -0
  24. package/dist/backend/kiro.js +82 -33
  25. package/dist/backend/kiro.js.map +1 -1
  26. package/dist/backend/muse.d.ts +7 -0
  27. package/dist/backend/muse.js +8 -1
  28. package/dist/backend/muse.js.map +1 -1
  29. package/dist/backend/types.d.ts +12 -0
  30. package/dist/backend/types.js.map +1 -1
  31. package/dist/binary-probe.d.ts +80 -0
  32. package/dist/binary-probe.js +182 -0
  33. package/dist/binary-probe.js.map +1 -0
  34. package/dist/cache-analysis.d.ts +92 -0
  35. package/dist/cache-analysis.js +147 -0
  36. package/dist/cache-analysis.js.map +1 -0
  37. package/dist/cache-ledger.d.ts +108 -0
  38. package/dist/cache-ledger.js +230 -0
  39. package/dist/cache-ledger.js.map +1 -0
  40. package/dist/cache-prices.d.ts +32 -0
  41. package/dist/cache-prices.js +73 -0
  42. package/dist/cache-prices.js.map +1 -0
  43. package/dist/cache-scan.d.ts +39 -0
  44. package/dist/cache-scan.js +115 -0
  45. package/dist/cache-scan.js.map +1 -0
  46. package/dist/cache-service.d.ts +131 -0
  47. package/dist/cache-service.js +452 -0
  48. package/dist/cache-service.js.map +1 -0
  49. package/dist/channel/adapters/discord.d.ts +5 -1
  50. package/dist/channel/adapters/discord.js +56 -11
  51. package/dist/channel/adapters/discord.js.map +1 -1
  52. package/dist/channel/adapters/telegram.d.ts +38 -1
  53. package/dist/channel/adapters/telegram.js +82 -0
  54. package/dist/channel/adapters/telegram.js.map +1 -1
  55. package/dist/channel/mcp-tools.js +1 -1
  56. package/dist/channel/mcp-tools.js.map +1 -1
  57. package/dist/channel/tool-router.d.ts +8 -1
  58. package/dist/channel/tool-router.js +4 -2
  59. package/dist/channel/tool-router.js.map +1 -1
  60. package/dist/channel/types.d.ts +21 -0
  61. package/dist/cli-entry.d.ts +19 -0
  62. package/dist/cli-entry.js +36 -0
  63. package/dist/cli-entry.js.map +1 -0
  64. package/dist/cli.js +376 -54
  65. package/dist/cli.js.map +1 -1
  66. package/dist/connection-secrets.d.ts +5 -0
  67. package/dist/connection-secrets.js.map +1 -1
  68. package/dist/cpu-profile.js +50 -0
  69. package/dist/cpu-profile.js.map +1 -1
  70. package/dist/daemon.d.ts +18 -0
  71. package/dist/daemon.js +256 -63
  72. package/dist/daemon.js.map +1 -1
  73. package/dist/delivery-outbox.d.ts +1 -0
  74. package/dist/delivery-outbox.js +12 -0
  75. package/dist/delivery-outbox.js.map +1 -1
  76. package/dist/discord-permissions.d.ts +33 -0
  77. package/dist/discord-permissions.js +42 -0
  78. package/dist/discord-permissions.js.map +1 -0
  79. package/dist/env-file.d.ts +11 -0
  80. package/dist/env-file.js +27 -0
  81. package/dist/env-file.js.map +1 -0
  82. package/dist/event-log.d.ts +4 -1
  83. package/dist/event-log.js +6 -3
  84. package/dist/event-log.js.map +1 -1
  85. package/dist/fleet-context.d.ts +5 -0
  86. package/dist/fleet-context.js.map +1 -1
  87. package/dist/fleet-control-audit.d.ts +5 -0
  88. package/dist/fleet-control-audit.js +7 -0
  89. package/dist/fleet-control-audit.js.map +1 -1
  90. package/dist/fleet-level-config.d.ts +8 -1
  91. package/dist/fleet-level-config.js +53 -0
  92. package/dist/fleet-level-config.js.map +1 -1
  93. package/dist/fleet-manager.d.ts +122 -7
  94. package/dist/fleet-manager.js +871 -152
  95. package/dist/fleet-manager.js.map +1 -1
  96. package/dist/fleet-stop-budget.d.ts +22 -0
  97. package/dist/fleet-stop-budget.js +95 -0
  98. package/dist/fleet-stop-budget.js.map +1 -0
  99. package/dist/full-restart.js +2 -3
  100. package/dist/full-restart.js.map +1 -1
  101. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +3 -1
  102. package/dist/install-lock.d.ts +49 -0
  103. package/dist/install-lock.js +200 -0
  104. package/dist/install-lock.js.map +1 -0
  105. package/dist/instance-config-impact.js +3 -2
  106. package/dist/instance-config-impact.js.map +1 -1
  107. package/dist/kiro-transcript-lane.d.ts +8 -4
  108. package/dist/kiro-transcript-lane.js +66 -44
  109. package/dist/kiro-transcript-lane.js.map +1 -1
  110. package/dist/locale.js +96 -0
  111. package/dist/locale.js.map +1 -1
  112. package/dist/next-steps.d.ts +5 -0
  113. package/dist/next-steps.js +26 -0
  114. package/dist/next-steps.js.map +1 -0
  115. package/dist/outbound-handlers.js +8 -0
  116. package/dist/outbound-handlers.js.map +1 -1
  117. package/dist/outbound-schemas.d.ts +4 -0
  118. package/dist/outbound-schemas.js +7 -2
  119. package/dist/outbound-schemas.js.map +1 -1
  120. package/dist/outbox-open-error.d.ts +7 -0
  121. package/dist/outbox-open-error.js +15 -0
  122. package/dist/outbox-open-error.js.map +1 -0
  123. package/dist/package-preimage.d.ts +26 -0
  124. package/dist/package-preimage.js +96 -0
  125. package/dist/package-preimage.js.map +1 -0
  126. package/dist/pane-context-cache.d.ts +25 -0
  127. package/dist/pane-context-cache.js +73 -0
  128. package/dist/pane-context-cache.js.map +1 -0
  129. package/dist/paths.d.ts +0 -7
  130. package/dist/paths.js +8 -2
  131. package/dist/paths.js.map +1 -1
  132. package/dist/provider-probe.d.ts +15 -0
  133. package/dist/provider-probe.js +20 -0
  134. package/dist/provider-probe.js.map +1 -1
  135. package/dist/public-link-progress.d.ts +73 -0
  136. package/dist/public-link-progress.js +190 -0
  137. package/dist/public-link-progress.js.map +1 -0
  138. package/dist/public-web-gateway.js +2 -2
  139. package/dist/public-web-gateway.js.map +1 -1
  140. package/dist/public-web-link.d.ts +6 -1
  141. package/dist/public-web-link.js +87 -15
  142. package/dist/public-web-link.js.map +1 -1
  143. package/dist/quickstart-api.d.ts +93 -20
  144. package/dist/quickstart-api.js +194 -62
  145. package/dist/quickstart-api.js.map +1 -1
  146. package/dist/quickstart.d.ts +15 -0
  147. package/dist/quickstart.js +110 -33
  148. package/dist/quickstart.js.map +1 -1
  149. package/dist/reply-buttons-controller.d.ts +98 -0
  150. package/dist/reply-buttons-controller.js +174 -0
  151. package/dist/reply-buttons-controller.js.map +1 -0
  152. package/dist/reply-buttons.d.ts +113 -0
  153. package/dist/reply-buttons.js +208 -0
  154. package/dist/reply-buttons.js.map +1 -0
  155. package/dist/reply-dedup.js +3 -1
  156. package/dist/reply-dedup.js.map +1 -1
  157. package/dist/restart-guard.d.ts +53 -0
  158. package/dist/restart-guard.js +114 -0
  159. package/dist/restart-guard.js.map +1 -0
  160. package/dist/scheduler/db.js +6 -2
  161. package/dist/scheduler/db.js.map +1 -1
  162. package/dist/service-activation.d.ts +62 -7
  163. package/dist/service-activation.js +237 -55
  164. package/dist/service-activation.js.map +1 -1
  165. package/dist/service-installer.d.ts +56 -1
  166. package/dist/service-installer.js +152 -12
  167. package/dist/service-installer.js.map +1 -1
  168. package/dist/service-plan.d.ts +65 -0
  169. package/dist/service-plan.js +108 -0
  170. package/dist/service-plan.js.map +1 -0
  171. package/dist/settings-api.js +92 -10
  172. package/dist/settings-api.js.map +1 -1
  173. package/dist/settings-authority.d.ts +11 -0
  174. package/dist/settings-authority.js +128 -0
  175. package/dist/settings-authority.js.map +1 -0
  176. package/dist/settings-change.d.ts +5 -0
  177. package/dist/settings-change.js +37 -8
  178. package/dist/settings-change.js.map +1 -1
  179. package/dist/settings-confirmation.d.ts +3 -0
  180. package/dist/settings-confirmation.js +7 -1
  181. package/dist/settings-confirmation.js.map +1 -1
  182. package/dist/settings-effect.js +19 -7
  183. package/dist/settings-effect.js.map +1 -1
  184. package/dist/settings-http-confirmation.js +1 -1
  185. package/dist/settings-http-confirmation.js.map +1 -1
  186. package/dist/settings-redaction.d.ts +18 -0
  187. package/dist/settings-redaction.js +58 -0
  188. package/dist/settings-redaction.js.map +1 -0
  189. package/dist/setup-form.d.ts +9 -1
  190. package/dist/setup-form.js +25 -1
  191. package/dist/setup-form.js.map +1 -1
  192. package/dist/setup-host.js +15 -6
  193. package/dist/setup-host.js.map +1 -1
  194. package/dist/setup-wizard.js +27 -19
  195. package/dist/setup-wizard.js.map +1 -1
  196. package/dist/sqlite-open-errors.d.ts +12 -0
  197. package/dist/sqlite-open-errors.js +13 -0
  198. package/dist/sqlite-open-errors.js.map +1 -0
  199. package/dist/systemd-runtime.d.ts +15 -0
  200. package/dist/systemd-runtime.js +41 -0
  201. package/dist/systemd-runtime.js.map +1 -0
  202. package/dist/tmux-control.d.ts +44 -0
  203. package/dist/tmux-control.js +170 -21
  204. package/dist/tmux-control.js.map +1 -1
  205. package/dist/token-env-name.d.ts +37 -0
  206. package/dist/token-env-name.js +93 -0
  207. package/dist/token-env-name.js.map +1 -0
  208. package/dist/tool-permissions.js +5 -3
  209. package/dist/tool-permissions.js.map +1 -1
  210. package/dist/topic-commands.d.ts +7 -16
  211. package/dist/topic-commands.js +56 -85
  212. package/dist/topic-commands.js.map +1 -1
  213. package/dist/transcript-monitor.js +3 -0
  214. package/dist/transcript-monitor.js.map +1 -1
  215. package/dist/transcript-sources.d.ts +68 -0
  216. package/dist/transcript-sources.js +336 -29
  217. package/dist/transcript-sources.js.map +1 -1
  218. package/dist/transcript-turns.d.ts +39 -0
  219. package/dist/transcript-turns.js +58 -0
  220. package/dist/transcript-turns.js.map +1 -0
  221. package/dist/tunnel/cloudflared-install.d.ts +18 -0
  222. package/dist/tunnel/cloudflared-install.js +15 -1
  223. package/dist/tunnel/cloudflared-install.js.map +1 -1
  224. package/dist/turn-reply-guard.d.ts +3 -0
  225. package/dist/turn-reply-guard.js.map +1 -1
  226. package/dist/ui/chat-commands.js +43 -0
  227. package/dist/ui/chat-render.js +34 -8
  228. package/dist/ui/chat-store.js +51 -2
  229. package/dist/ui/chat-strings.js +30 -2
  230. package/dist/ui/chat-thread.js +141 -47
  231. package/dist/ui/first-run.js +64 -0
  232. package/dist/ui/fleet-cache.js +168 -0
  233. package/dist/ui/html-attachment.js +26 -0
  234. package/dist/ui/panel-chat.js +117 -23
  235. package/dist/ui/panel-fleet.js +31 -17
  236. package/dist/ui/panel-settings.js +29 -15
  237. package/dist/ui/preview-panel.js +237 -0
  238. package/dist/ui/preview.js +7 -3
  239. package/dist/ui/settings-apply.js +3 -1
  240. package/dist/ui/settings-dialogs.js +95 -25
  241. package/dist/ui/settings-discord.js +130 -0
  242. package/dist/ui/settings-model.js +21 -0
  243. package/dist/ui/settings-strings.js +50 -8
  244. package/dist/ui/settings-token.js +54 -0
  245. package/dist/ui/settings-wizard.js +63 -29
  246. package/dist/ui/shared/app-route.js +1 -1
  247. package/dist/ui/shared/app-shell.js +25 -37
  248. package/dist/ui/shared/app-store.js +5 -3
  249. package/dist/ui/shared/app-stream.js +2 -1
  250. package/dist/ui/shared/app.css +181 -5
  251. package/dist/ui/shared/app.js +2 -1
  252. package/dist/ui/shared/instance-nav.js +310 -0
  253. package/dist/ui/shared/panel-view.js +12 -190
  254. package/dist/ui/shared/signin.js +13 -1
  255. package/dist/ui/shared/ui-icons.js +2 -0
  256. package/dist/ui/shared/view-roster-store.js +5 -0
  257. package/dist/ui/shared/view-strings.js +12 -0
  258. package/dist/ui/signin.html +2 -1
  259. package/dist/update-dispatch.d.ts +28 -0
  260. package/dist/update-dispatch.js +73 -0
  261. package/dist/update-dispatch.js.map +1 -0
  262. package/dist/update-install.d.ts +78 -8
  263. package/dist/update-install.js +158 -30
  264. package/dist/update-install.js.map +1 -1
  265. package/dist/update-launch.d.ts +22 -0
  266. package/dist/update-launch.js +106 -0
  267. package/dist/update-launch.js.map +1 -0
  268. package/dist/update-marker.js +3 -8
  269. package/dist/update-marker.js.map +1 -1
  270. package/dist/usage/format-rich.js +7 -1
  271. package/dist/usage/format-rich.js.map +1 -1
  272. package/dist/usage/i18n-keys.d.ts +1 -1
  273. package/dist/usage/i18n-keys.js +1 -1
  274. package/dist/usage/i18n-keys.js.map +1 -1
  275. package/dist/usage/providers.d.ts +4 -0
  276. package/dist/usage/providers.js +2 -1
  277. package/dist/usage/providers.js.map +1 -1
  278. package/dist/usage/usage-api.js +48 -2
  279. package/dist/usage/usage-api.js.map +1 -1
  280. package/dist/view-api.d.ts +40 -0
  281. package/dist/view-api.js +28 -10
  282. package/dist/view-api.js.map +1 -1
  283. package/dist/web-api.d.ts +22 -0
  284. package/dist/web-api.js +115 -16
  285. package/dist/web-api.js.map +1 -1
  286. package/dist/web-auth.d.ts +8 -0
  287. package/dist/web-auth.js +34 -8
  288. package/dist/web-auth.js.map +1 -1
  289. package/dist/web-chat-history.d.ts +21 -0
  290. package/dist/web-chat-history.js +44 -0
  291. package/dist/web-chat-history.js.map +1 -1
  292. package/dist/web-commands.d.ts +77 -0
  293. package/dist/web-commands.js +81 -0
  294. package/dist/web-commands.js.map +1 -0
  295. package/dist/web-host-guard.d.ts +18 -2
  296. package/dist/web-host-guard.js +30 -5
  297. package/dist/web-host-guard.js.map +1 -1
  298. package/dist/web-session.d.ts +7 -1
  299. package/dist/web-session.js +23 -2
  300. package/dist/web-session.js.map +1 -1
  301. package/dist/web-shell-routes.d.ts +1 -1
  302. package/dist/web-shell-routes.js +1 -1
  303. package/dist/web-shell-routes.js.map +1 -1
  304. package/launcher/agend +110 -0
  305. package/launcher/agend-agent +110 -0
  306. package/launcher/agend-agent.cjs +4 -0
  307. package/launcher/agend.cjs +4 -0
  308. package/launcher/install-admission.cjs +105 -0
  309. package/launcher/launch.cjs +64 -0
  310. package/launcher/postinstall.cjs +118 -0
  311. package/launcher/run-in-process.cjs +13 -0
  312. package/launcher/runtime-platform.cjs +86 -0
  313. package/launcher/runtime-select.cjs +217 -0
  314. package/package.json +12 -4
  315. package/scripts/preinstall-guard.cjs +40 -21
  316. package/templates/launchd.plist.ejs +2 -2
  317. package/templates/systemd.service.ejs +4 -4
@@ -0,0 +1,131 @@
1
+ import { type InstanceAnalysis } from "./cache-analysis.js";
2
+ /** An instance to analyse: a fleet.yaml instance, or a ClassicBot room (its workspace under the AgEnD home). */
3
+ export interface CacheInstance {
4
+ name: string;
5
+ backend: string;
6
+ workingDirectory: string;
7
+ ledgerPath: string;
8
+ }
9
+ export interface CacheServiceOptions {
10
+ instances(): CacheInstance[];
11
+ claudeProjectsDir(): string;
12
+ claudeKey(workingDirectory: string): string;
13
+ codexSessionsDir(): string;
14
+ /** Rollout files with their mtimes (the shared rollout index). */
15
+ listRollouts(root: string): Array<{
16
+ path: string;
17
+ mtimeMs: number;
18
+ }>;
19
+ /** Where the rollout → working-directory map is kept (one session_meta read per rollout, ever). */
20
+ metaPath: string;
21
+ now?: () => number;
22
+ passBytes?: number;
23
+ pauseMs?: number;
24
+ intervalMs?: number;
25
+ log?: (level: "info" | "warn" | "debug", msg: string, extra?: Record<string, unknown>) => void;
26
+ }
27
+ export type CacheWindow = "24h" | "7d" | "30d";
28
+ export declare const WINDOWS: Record<CacheWindow, number>;
29
+ export interface InstanceReport {
30
+ name: string;
31
+ backend: string;
32
+ /**
33
+ * "ok" with `analysis`; "no_data": nothing read yet (or no transcript); "credit_billed": kiro; "unsupported";
34
+ * "shared": its transcripts cannot be told apart from another instance's (the same working directory) — `with`.
35
+ */
36
+ status: "ok" | "no_data" | "credit_billed" | "unsupported" | "shared";
37
+ with?: string[];
38
+ analysis?: InstanceAnalysis;
39
+ }
40
+ export interface CacheReport {
41
+ window: CacheWindow;
42
+ from: number;
43
+ to: number;
44
+ pricesChecked: string;
45
+ priceSources: readonly string[];
46
+ /** `caughtUp`: a catch-up has finished since the fleet started (before that, what is shown may be partial). */
47
+ scanning: {
48
+ active: boolean;
49
+ caughtUp: boolean;
50
+ pendingBytes: number;
51
+ pendingFiles: number;
52
+ };
53
+ fleet: {
54
+ expiryCost: number;
55
+ saving: number;
56
+ recommended: number;
57
+ analysed: number;
58
+ priced: boolean;
59
+ };
60
+ instances: InstanceReport[];
61
+ }
62
+ export declare class CacheService {
63
+ private readonly o;
64
+ private readonly ledgers;
65
+ private readonly dirty;
66
+ /** Rollout path → the inode its session_meta was read from, and the cwd it names (null: not a session_meta). */
67
+ private meta;
68
+ private metaDirty;
69
+ private running;
70
+ private timer;
71
+ private stopped;
72
+ /** Set by stop() to fence new scan admission while the current pass drains. */
73
+ private closing;
74
+ private pending;
75
+ private caughtUp;
76
+ private readonly now;
77
+ constructor(o: CacheServiceOptions);
78
+ /** Catch up now (joins a catch-up already running). */
79
+ kick(): Promise<void>;
80
+ /** Keep up on a timer from now on (the first report starts it). */
81
+ start(): void;
82
+ /** Stop the timer, fence new scan admission, drain the current pass, then
83
+ * do one bounded save. Returns a promise callers MUST await for durability.
84
+ *
85
+ * Sequence:
86
+ * 1. Cancel timer and set closing=true so kick()/start() refuse new work.
87
+ * 2. Join this.running (if any) — the current catchUp() loop will exit at
88
+ * its next iteration boundary because closing=true, writing its own dirty
89
+ * data before returning.
90
+ * 3. Do one final save() of anything that is still dirty.
91
+ * 4. Set stopped=true.
92
+ *
93
+ * This bounds shutdown to one physical pass rather than scanning the entire
94
+ * backlog.
95
+ */
96
+ stop(): Promise<void>;
97
+ scanning(): CacheReport["scanning"];
98
+ private catchUp;
99
+ private ledgerFor;
100
+ /**
101
+ * The instances whose transcripts land where another's do — the same Claude project (working directory), the
102
+ * same Codex cwd — mapped to the others. They are not read: nothing in a transcript says which one wrote it.
103
+ */
104
+ private shared;
105
+ private passing;
106
+ /**
107
+ * One bounded pass over every instance's files. Returns the bytes still behind afterwards. Passes never overlap
108
+ * (two reading one file from the same cursor would count it twice): a pass asked for during another runs after it.
109
+ */
110
+ pass(): Promise<number>;
111
+ private passOnce;
112
+ /** A file that is not the one the cursor read (another inode, or shorter): keep the session's end, start at its end. */
113
+ private followFromEnd;
114
+ private read;
115
+ private claudeFiles;
116
+ /** Codex rollouts of the last KEEP_DAYS, by the instance whose working directory their session_meta names. */
117
+ private codexFilesByInstance;
118
+ /** Write what changed; whatever fails to write stays dirty and is written by a later pass. */
119
+ private save;
120
+ /** The analysis for a window, from the ledgers as they are now (a catch-up is started, not waited for). */
121
+ report(window: CacheWindow): Promise<CacheReport>;
122
+ }
123
+ /**
124
+ * A rollout's session_meta, read with one bounded read through the descriptor whose inode it records. Null while the
125
+ * first line is not complete yet (the next pass reads it again); `cwd: null` for a complete first line that is not
126
+ * a session_meta.
127
+ */
128
+ export declare function rolloutMeta(path: string): Promise<{
129
+ ino: number;
130
+ cwd: string | null;
131
+ } | null>;
@@ -0,0 +1,452 @@
1
+ /**
2
+ * #1468: keeps each instance's cache ledger (cache-ledger.ts) up to date from its transcripts, off the fleet loop's
3
+ * critical path, and answers the analysis (cache-analysis.ts) from the ledgers alone.
4
+ *
5
+ * - Which files: a Claude Code instance's `<claude config>/projects/<project key of its working directory>/*.jsonl`
6
+ * (the main conversation; subagents write elsewhere); a Codex instance's rollouts under the shared sessions
7
+ * directory whose `session_meta` names its working directory. Only files touched in the last KEEP_DAYS.
8
+ * - How: passes of at most `passBytes` (scan-jsonl awaits every chunk), with a pause between passes, until every
9
+ * file is caught up; then again every `intervalMs` and when the panel asks. Where each file stopped is persisted
10
+ * with the ledger (`<instance dir>/cache-ledger.json`), so a restart resumes instead of re-reading.
11
+ * - Never: a vendor API call, a child process, a synchronous read of a transcript.
12
+ * A file that shrank or was replaced (another inode) is followed from its current end: its earlier turns are
13
+ * already counted, and counting them twice would be worse than missing a rewrite. The inode is checked on the
14
+ * descriptor actually read, not only on the listing. Two instances whose transcripts land in the same place (the same
15
+ * working directory: one Claude project, one Codex cwd) cannot be told apart: neither is analysed, both say so.
16
+ */
17
+ import { mkdir, open, readdir, readFile, realpath, rename, stat, writeFile } from "node:fs/promises";
18
+ import { dirname, join, resolve } from "node:path";
19
+ import { scanJsonl } from "./cache-scan.js";
20
+ import { addTurn, claudeLine, codexLine, emptyLedger, KEEP_DAYS, pruneLedger, reviveLedger } from "./cache-ledger.js";
21
+ import { analyzeLedger } from "./cache-analysis.js";
22
+ import { PRICES_CHECKED, PRICE_SOURCES } from "./cache-prices.js";
23
+ export const WINDOWS = { "24h": 86_400_000, "7d": 7 * 86_400_000, "30d": 30 * 86_400_000 };
24
+ const DAY = 86_400_000;
25
+ const META_MAX_BYTES = 256 * 1024; // session_meta carries the instructions (~22 KB in real rollouts)
26
+ const kindOf = (backend) => (backend === "claude-code" ? "claude" : backend === "codex" ? "codex" : null);
27
+ const sleep = (ms) => new Promise((r) => { const h = setTimeout(r, ms); h.unref?.(); });
28
+ const dict = () => Object.create(null);
29
+ export class CacheService {
30
+ o;
31
+ ledgers = new Map();
32
+ dirty = new Set();
33
+ /** Rollout path → the inode its session_meta was read from, and the cwd it names (null: not a session_meta). */
34
+ meta = null;
35
+ metaDirty = false;
36
+ running = null;
37
+ timer = null;
38
+ stopped = false;
39
+ /** Set by stop() to fence new scan admission while the current pass drains. */
40
+ closing = false;
41
+ pending = { bytes: 0, files: 0 };
42
+ caughtUp = false;
43
+ now;
44
+ constructor(o) {
45
+ this.o = o;
46
+ this.now = o.now ?? Date.now;
47
+ }
48
+ /** Catch up now (joins a catch-up already running). */
49
+ kick() {
50
+ if (this.stopped || this.closing)
51
+ return Promise.resolve();
52
+ return this.running ??= this.catchUp().catch((err) => { this.o.log?.("warn", "cache analysis: a pass failed", { err: String(err) }); })
53
+ .finally(() => { this.running = null; });
54
+ }
55
+ /** Keep up on a timer from now on (the first report starts it). */
56
+ start() {
57
+ if (this.timer || this.stopped || this.closing)
58
+ return;
59
+ this.timer = setInterval(() => { void this.kick(); }, this.o.intervalMs ?? 10 * 60_000);
60
+ this.timer.unref?.();
61
+ }
62
+ /** Stop the timer, fence new scan admission, drain the current pass, then
63
+ * do one bounded save. Returns a promise callers MUST await for durability.
64
+ *
65
+ * Sequence:
66
+ * 1. Cancel timer and set closing=true so kick()/start() refuse new work.
67
+ * 2. Join this.running (if any) — the current catchUp() loop will exit at
68
+ * its next iteration boundary because closing=true, writing its own dirty
69
+ * data before returning.
70
+ * 3. Do one final save() of anything that is still dirty.
71
+ * 4. Set stopped=true.
72
+ *
73
+ * This bounds shutdown to one physical pass rather than scanning the entire
74
+ * backlog.
75
+ */
76
+ stop() {
77
+ if (this.timer)
78
+ clearInterval(this.timer);
79
+ this.timer = null;
80
+ // Set closing now so: (a) the current catchUp() loop exits after its next
81
+ // physical pass instead of rescanning the full backlog, and (b) no new
82
+ // kicks or timers can restart work once we start draining.
83
+ this.closing = true;
84
+ const inFlight = this.running ?? Promise.resolve();
85
+ return inFlight
86
+ .catch(() => { }) // a failed pass must not prevent the flush
87
+ .then(async () => {
88
+ // One bounded save for anything dirtied by the just-completed pass
89
+ // (or already dirty). Use save() directly, not kick(), to avoid
90
+ // re-entering the full scan loop.
91
+ if (this.dirty.size > 0 || this.metaDirty) {
92
+ const insts = this.o.instances();
93
+ await this.save(insts).catch(() => { });
94
+ }
95
+ })
96
+ .finally(() => { this.stopped = true; });
97
+ }
98
+ scanning() {
99
+ return { active: this.running !== null, caughtUp: this.caughtUp, pendingBytes: this.pending.bytes, pendingFiles: this.pending.files };
100
+ }
101
+ async catchUp() {
102
+ for (;;) {
103
+ const left = await this.pass();
104
+ if (left === 0)
105
+ this.caughtUp = true;
106
+ // Stop looping when: all caught up, explicitly stopped, or closing (stop()
107
+ // fenced new admission — let the current physical pass write its dirty data,
108
+ // then exit rather than scanning the full backlog during shutdown).
109
+ if (this.stopped || this.closing || left === 0)
110
+ return;
111
+ await sleep(this.o.pauseMs ?? 25);
112
+ }
113
+ }
114
+ async ledgerFor(inst) {
115
+ let l = this.ledgers.get(inst.name);
116
+ if (l)
117
+ return l;
118
+ try {
119
+ l = reviveLedger(JSON.parse(await readFile(inst.ledgerPath, "utf8")));
120
+ }
121
+ catch {
122
+ l = emptyLedger();
123
+ }
124
+ // Another pass may have loaded it meanwhile.
125
+ const again = this.ledgers.get(inst.name);
126
+ if (again)
127
+ return again;
128
+ this.ledgers.set(inst.name, l);
129
+ return l;
130
+ }
131
+ /**
132
+ * The instances whose transcripts land where another's do — the same Claude project (working directory), the
133
+ * same Codex cwd — mapped to the others. They are not read: nothing in a transcript says which one wrote it.
134
+ */
135
+ async shared(insts) {
136
+ const groups = new Map();
137
+ for (const i of insts) {
138
+ const kind = kindOf(i.backend);
139
+ if (!kind)
140
+ continue;
141
+ const keys = kind === "claude" ? [`claude|${this.o.claudeKey(i.workingDirectory)}`] : (await cwdKeys(i.workingDirectory)).map((k) => `codex|${k}`);
142
+ for (const k of keys)
143
+ groups.set(k, [...(groups.get(k) ?? []), i.name]);
144
+ }
145
+ const out = new Map();
146
+ for (const names of groups.values()) {
147
+ const unique = [...new Set(names)];
148
+ if (unique.length < 2)
149
+ continue;
150
+ for (const n of unique)
151
+ out.set(n, [...new Set([...(out.get(n) ?? []), ...unique.filter((m) => m !== n)])]);
152
+ }
153
+ return out;
154
+ }
155
+ passing = Promise.resolve();
156
+ /**
157
+ * One bounded pass over every instance's files. Returns the bytes still behind afterwards. Passes never overlap
158
+ * (two reading one file from the same cursor would count it twice): a pass asked for during another runs after it.
159
+ */
160
+ pass() {
161
+ const run = this.passing.then(() => this.passOnce());
162
+ this.passing = run.catch(() => { });
163
+ return run;
164
+ }
165
+ async passOnce() {
166
+ const cutoff = this.now() - KEEP_DAYS * DAY;
167
+ let budget = this.o.passBytes ?? 16 * 1024 * 1024;
168
+ let behindBytes = 0, behindFiles = 0;
169
+ const insts = this.o.instances();
170
+ const shared = await this.shared(insts);
171
+ const codex = await this.codexFilesByInstance(insts.filter((i) => !shared.has(i.name)), cutoff);
172
+ for (const inst of insts) {
173
+ if (this.stopped)
174
+ break;
175
+ const kind = kindOf(inst.backend);
176
+ if (!kind || shared.has(inst.name))
177
+ continue;
178
+ const ledger = await this.ledgerFor(inst);
179
+ const files = kind === "claude" ? await this.claudeFiles(inst, cutoff) : codex.get(inst.name) ?? [];
180
+ const listed = new Set(files.map((f) => f.path));
181
+ for (const path of Object.keys(ledger.files))
182
+ if (!listed.has(path)) {
183
+ delete ledger.files[path];
184
+ this.dirty.add(inst.name);
185
+ }
186
+ for (const f of files) {
187
+ let cur = ledger.files[f.path];
188
+ if (!cur) {
189
+ cur = ledger.files[f.path] = { kind, ino: f.ino, offset: 0 };
190
+ this.dirty.add(inst.name);
191
+ }
192
+ else if (cur.ino !== f.ino || f.size < cur.offset) {
193
+ cur = this.followFromEnd(ledger, f.path, cur, f.ino, f.size);
194
+ this.dirty.add(inst.name);
195
+ }
196
+ if (cur.offset >= f.size)
197
+ continue;
198
+ // Only an unfinished line was left, and the file has not grown since: nothing new to read.
199
+ if (cur.stalled === f.size)
200
+ continue;
201
+ if (budget <= 0) {
202
+ behindBytes += f.size - cur.offset;
203
+ behindFiles++;
204
+ continue;
205
+ }
206
+ const done = await this.read(ledger, cur, f.path, budget, cutoff);
207
+ this.dirty.add(inst.name);
208
+ budget -= done.read;
209
+ if (done.behind > 0) {
210
+ behindBytes += done.behind;
211
+ behindFiles++;
212
+ }
213
+ }
214
+ pruneLedger(ledger, cutoff);
215
+ }
216
+ this.pending = { bytes: behindBytes, files: behindFiles };
217
+ await this.save(insts);
218
+ return behindBytes;
219
+ }
220
+ /** A file that is not the one the cursor read (another inode, or shorter): keep the session's end, start at its end. */
221
+ followFromEnd(ledger, path, cur, ino, size) {
222
+ const next = { kind: cur.kind, ino, offset: size };
223
+ if (cur.last) {
224
+ next.last = cur.last;
225
+ next.first = cur.first;
226
+ }
227
+ if (cur.ttl !== undefined)
228
+ next.ttl = cur.ttl;
229
+ return ledger.files[path] = next;
230
+ }
231
+ async read(ledger, cur, path, budget, cutoff) {
232
+ try {
233
+ const res = await scanJsonl(path, cur.offset, { maxBytes: budget, ino: cur.ino }, (line) => {
234
+ const turn = cur.kind === "claude" ? claudeLine(line, cur) : codexLine(line, cur);
235
+ if (turn)
236
+ addTurn(ledger, cur, turn, cutoff);
237
+ });
238
+ if (res.replaced) {
239
+ this.followFromEnd(ledger, path, cur, res.ino, res.size);
240
+ return { read: 0, behind: 0 };
241
+ }
242
+ cur.offset = res.offset;
243
+ // Read to the end with an unfinished line left: the CLI is still writing it. Not behind, and not read again
244
+ // until the file grows.
245
+ if (res.done && res.offset < res.size)
246
+ cur.stalled = res.size;
247
+ else
248
+ delete cur.stalled;
249
+ return { read: Math.max(res.read, 1), behind: res.done ? 0 : res.size - res.offset };
250
+ }
251
+ catch (err) {
252
+ this.o.log?.("debug", "cache analysis: could not read a transcript", { path, err: String(err) });
253
+ return { read: 1, behind: 0 };
254
+ }
255
+ }
256
+ async claudeFiles(inst, cutoff) {
257
+ const dir = join(this.o.claudeProjectsDir(), this.o.claudeKey(inst.workingDirectory));
258
+ let names;
259
+ try {
260
+ names = await readdir(dir);
261
+ }
262
+ catch {
263
+ return [];
264
+ }
265
+ const out = [];
266
+ for (const n of names) {
267
+ if (!n.endsWith(".jsonl"))
268
+ continue;
269
+ const path = join(dir, n);
270
+ try {
271
+ const st = await stat(path);
272
+ if (st.isFile() && st.mtimeMs >= cutoff)
273
+ out.push({ path, ino: st.ino, size: st.size });
274
+ }
275
+ catch { /* gone */ }
276
+ }
277
+ return out;
278
+ }
279
+ /** Codex rollouts of the last KEEP_DAYS, by the instance whose working directory their session_meta names. */
280
+ async codexFilesByInstance(insts, cutoff) {
281
+ const out = new Map();
282
+ const codexInsts = insts.filter((i) => kindOf(i.backend) === "codex");
283
+ if (!codexInsts.length)
284
+ return out;
285
+ const byCwd = new Map();
286
+ for (const i of codexInsts)
287
+ for (const k of await cwdKeys(i.workingDirectory))
288
+ byCwd.set(k, i.name);
289
+ if (!this.meta) {
290
+ this.meta = dict();
291
+ try {
292
+ for (const [p, v] of Object.entries(JSON.parse(await readFile(this.o.metaPath, "utf8")))) {
293
+ const e = v;
294
+ if (e && typeof e.ino === "number" && (typeof e.cwd === "string" || e.cwd === null))
295
+ this.meta[p] = { ino: e.ino, cwd: e.cwd };
296
+ }
297
+ }
298
+ catch { /* none yet */ }
299
+ }
300
+ let rollouts = [];
301
+ try {
302
+ rollouts = this.o.listRollouts(this.o.codexSessionsDir()).filter((r) => r.mtimeMs >= cutoff);
303
+ }
304
+ catch { /* no sessions yet */ }
305
+ const live = new Set();
306
+ for (const r of rollouts) {
307
+ live.add(r.path);
308
+ let st;
309
+ try {
310
+ st = await stat(r.path);
311
+ }
312
+ catch {
313
+ continue;
314
+ }
315
+ let m = this.meta[r.path];
316
+ // Read once per physical file; a first line still being written is read again next pass.
317
+ if (!m || m.ino !== st.ino) {
318
+ const read = await rolloutMeta(r.path);
319
+ if (read) {
320
+ m = this.meta[r.path] = read;
321
+ this.metaDirty = true;
322
+ }
323
+ else {
324
+ delete this.meta[r.path];
325
+ continue;
326
+ }
327
+ }
328
+ const name = m.cwd ? byCwd.get(resolve(m.cwd)) : undefined;
329
+ // The meta belongs to the inode it was read from; a file replaced since is read again next pass.
330
+ if (!name || m.ino !== st.ino)
331
+ continue;
332
+ const list = out.get(name) ?? [];
333
+ list.push({ path: r.path, ino: st.ino, size: st.size });
334
+ out.set(name, list);
335
+ }
336
+ for (const p of Object.keys(this.meta))
337
+ if (!live.has(p)) {
338
+ delete this.meta[p];
339
+ this.metaDirty = true;
340
+ }
341
+ return out;
342
+ }
343
+ /** Write what changed; whatever fails to write stays dirty and is written by a later pass. */
344
+ async save(insts) {
345
+ const byName = new Map(insts.map((i) => [i.name, i]));
346
+ for (const name of [...this.dirty]) {
347
+ const inst = byName.get(name), l = this.ledgers.get(name);
348
+ if (!inst || !l) {
349
+ this.dirty.delete(name);
350
+ continue;
351
+ }
352
+ if (await writeAtomic(inst.ledgerPath, JSON.stringify(l)))
353
+ this.dirty.delete(name);
354
+ }
355
+ if (this.metaDirty && this.meta && await writeAtomic(this.o.metaPath, JSON.stringify(this.meta)))
356
+ this.metaDirty = false;
357
+ }
358
+ /** The analysis for a window, from the ledgers as they are now (a catch-up is started, not waited for). */
359
+ async report(window) {
360
+ this.start();
361
+ void this.kick();
362
+ const to = this.now(), from = to - WINDOWS[window];
363
+ const instances = [];
364
+ const fleet = { expiryCost: 0, saving: 0, recommended: 0, analysed: 0, priced: true };
365
+ const insts = this.o.instances();
366
+ const shared = await this.shared(insts);
367
+ for (const inst of insts) {
368
+ const kind = kindOf(inst.backend);
369
+ if (!kind) {
370
+ instances.push({ name: inst.name, backend: inst.backend, status: inst.backend.startsWith("kiro") ? "credit_billed" : "unsupported" });
371
+ continue;
372
+ }
373
+ const others = shared.get(inst.name);
374
+ if (others) {
375
+ instances.push({ name: inst.name, backend: inst.backend, status: "shared", with: others });
376
+ continue;
377
+ }
378
+ const ledger = await this.ledgerFor(inst);
379
+ const analysis = analyzeLedger(ledger, { backend: kind, from, to });
380
+ if (!analysis.requests && !analysis.sim.tailPings) {
381
+ instances.push({ name: inst.name, backend: inst.backend, status: "no_data" });
382
+ continue;
383
+ }
384
+ instances.push({ name: inst.name, backend: inst.backend, status: "ok", analysis });
385
+ fleet.analysed++;
386
+ if (!analysis.priced) {
387
+ fleet.priced = false;
388
+ continue;
389
+ }
390
+ fleet.expiryCost += analysis.sim.expiryCost;
391
+ if (analysis.recommendation.on) {
392
+ fleet.recommended++;
393
+ fleet.saving += analysis.sim.net;
394
+ }
395
+ }
396
+ return { window, from, to, pricesChecked: PRICES_CHECKED, priceSources: PRICE_SOURCES, scanning: this.scanning(), fleet, instances };
397
+ }
398
+ }
399
+ /** A working directory as configured and as the filesystem resolves it (a rollout records either). */
400
+ async function cwdKeys(dir) {
401
+ const keys = [resolve(dir)];
402
+ try {
403
+ const real = await realpath(dir);
404
+ if (real !== keys[0])
405
+ keys.push(real);
406
+ }
407
+ catch { /* missing: as configured */ }
408
+ return keys;
409
+ }
410
+ /**
411
+ * A rollout's session_meta, read with one bounded read through the descriptor whose inode it records. Null while the
412
+ * first line is not complete yet (the next pass reads it again); `cwd: null` for a complete first line that is not
413
+ * a session_meta.
414
+ */
415
+ export async function rolloutMeta(path) {
416
+ let fh;
417
+ try {
418
+ fh = await open(path, "r");
419
+ const ino = (await fh.stat()).ino;
420
+ const buf = Buffer.alloc(META_MAX_BYTES);
421
+ const { bytesRead } = await fh.read(buf, 0, META_MAX_BYTES, 0);
422
+ const nl = buf.subarray(0, bytesRead).indexOf(10);
423
+ if (nl === -1)
424
+ return bytesRead >= META_MAX_BYTES ? { ino, cwd: null } : null;
425
+ try {
426
+ const d = JSON.parse(buf.toString("utf8", 0, nl));
427
+ return { ino, cwd: d.type === "session_meta" && typeof d.payload?.cwd === "string" ? d.payload.cwd : null };
428
+ }
429
+ catch {
430
+ return { ino, cwd: null };
431
+ }
432
+ }
433
+ catch {
434
+ return null;
435
+ }
436
+ finally {
437
+ await fh?.close().catch(() => { });
438
+ }
439
+ }
440
+ async function writeAtomic(path, text) {
441
+ const tmp = `${path}.${process.pid}.tmp`;
442
+ try {
443
+ await mkdir(dirname(path), { recursive: true });
444
+ await writeFile(tmp, text);
445
+ await rename(tmp, path);
446
+ return true;
447
+ }
448
+ catch {
449
+ return false;
450
+ }
451
+ }
452
+ //# sourceMappingURL=cache-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-service.js","sourceRoot":"","sources":["../src/cache-service.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import { Client, ActionRowBuilder, ButtonBuilder } from "discord.js";
3
- import type { ChannelAdapter, ApprovalHandle, SendOpts, SentMessage, PermissionPrompt, Choice, AlertData, AdapterHealthSnapshot, TopicPresence, StickerInfo, StickerList, StickerPreview, StickerTarget } from "../types.js";
3
+ import type { ChannelAdapter, ApprovalHandle, SendOpts, ReplyButtonsOutcome, SentMessage, PermissionPrompt, Choice, AlertData, AdapterHealthSnapshot, TopicPresence, StickerInfo, StickerList, StickerPreview, StickerTarget } from "../types.js";
4
4
  import type { AccessManager } from "../access-manager.js";
5
5
  /** Curated ClassicBot backends for Discord's native slash-option dropdown. */
6
6
  export declare const DISCORD_START_BACKEND_CHOICES: readonly [{
@@ -183,6 +183,10 @@ export declare class DiscordAdapter extends EventEmitter implements ChannelAdapt
183
183
  /** Private delivery: a DM to the user (fails if the user disallows DMs from this server). */
184
184
  sendDirect(userId: string, text: string, opts?: SendOpts): Promise<SentMessage>;
185
185
  sendText(chatId: string, text: string, opts?: SendOpts): Promise<SentMessage>;
186
+ /** #1266: this adapter puts a reply's buttons (message components) on its last message. */
187
+ get supportsReplyButtons(): boolean;
188
+ /** #1266: the same buttons, all disabled; the chosen one is marked and names who chose it. */
189
+ settleReplyButtons(chatId: string, messageId: string, threadId: string | undefined, labels: readonly string[], outcome: ReplyButtonsOutcome): Promise<void>;
186
190
  sendFile(chatId: string, filePath: string, opts?: SendOpts): Promise<SentMessage>;
187
191
  editMessage(chatId: string, messageId: string, text: string, threadId?: string): Promise<void>;
188
192
  /** Edit text and clear components (Discord keeps components on a plain edit,