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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +2 -0
  2. package/README.zh-TW.md +2 -0
  3. package/dist/agent-cli.js +6 -1
  4. package/dist/agent-cli.js.map +1 -1
  5. package/dist/agent-endpoint.js +68 -12
  6. package/dist/agent-endpoint.js.map +1 -1
  7. package/dist/agent-token-header.d.ts +13 -0
  8. package/dist/agent-token-header.js +16 -0
  9. package/dist/agent-token-header.js.map +1 -0
  10. package/dist/backend/antigravity.js +4 -3
  11. package/dist/backend/antigravity.js.map +1 -1
  12. package/dist/backend/grok.js +1 -1
  13. package/dist/backend/grok.js.map +1 -1
  14. package/dist/backend/kiro.d.ts +7 -0
  15. package/dist/backend/kiro.js +82 -33
  16. package/dist/backend/kiro.js.map +1 -1
  17. package/dist/backend/muse.js +1 -1
  18. package/dist/backend/muse.js.map +1 -1
  19. package/dist/backend/types.d.ts +6 -0
  20. package/dist/backend/types.js.map +1 -1
  21. package/dist/cache-analysis.d.ts +92 -0
  22. package/dist/cache-analysis.js +147 -0
  23. package/dist/cache-analysis.js.map +1 -0
  24. package/dist/cache-ledger.d.ts +108 -0
  25. package/dist/cache-ledger.js +230 -0
  26. package/dist/cache-ledger.js.map +1 -0
  27. package/dist/cache-prices.d.ts +32 -0
  28. package/dist/cache-prices.js +73 -0
  29. package/dist/cache-prices.js.map +1 -0
  30. package/dist/cache-scan.d.ts +39 -0
  31. package/dist/cache-scan.js +115 -0
  32. package/dist/cache-scan.js.map +1 -0
  33. package/dist/cache-service.d.ts +115 -0
  34. package/dist/cache-service.js +417 -0
  35. package/dist/cache-service.js.map +1 -0
  36. package/dist/cli-entry.d.ts +19 -0
  37. package/dist/cli-entry.js +36 -0
  38. package/dist/cli-entry.js.map +1 -0
  39. package/dist/cli.js +251 -24
  40. package/dist/cli.js.map +1 -1
  41. package/dist/daemon.d.ts +6 -0
  42. package/dist/daemon.js +90 -37
  43. package/dist/daemon.js.map +1 -1
  44. package/dist/event-log.d.ts +4 -1
  45. package/dist/event-log.js +6 -3
  46. package/dist/event-log.js.map +1 -1
  47. package/dist/fleet-control-audit.d.ts +5 -0
  48. package/dist/fleet-control-audit.js +7 -0
  49. package/dist/fleet-control-audit.js.map +1 -1
  50. package/dist/fleet-level-config.js +22 -0
  51. package/dist/fleet-level-config.js.map +1 -1
  52. package/dist/fleet-manager.d.ts +46 -0
  53. package/dist/fleet-manager.js +287 -40
  54. package/dist/fleet-manager.js.map +1 -1
  55. package/dist/full-restart.js +2 -3
  56. package/dist/full-restart.js.map +1 -1
  57. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +3 -1
  58. package/dist/install-lock.d.ts +49 -0
  59. package/dist/install-lock.js +200 -0
  60. package/dist/install-lock.js.map +1 -0
  61. package/dist/instance-config-impact.js +3 -2
  62. package/dist/instance-config-impact.js.map +1 -1
  63. package/dist/locale.js +14 -0
  64. package/dist/locale.js.map +1 -1
  65. package/dist/outbound-schemas.js +1 -1
  66. package/dist/outbound-schemas.js.map +1 -1
  67. package/dist/package-preimage.d.ts +26 -0
  68. package/dist/package-preimage.js +96 -0
  69. package/dist/package-preimage.js.map +1 -0
  70. package/dist/public-web-gateway.js +2 -2
  71. package/dist/public-web-gateway.js.map +1 -1
  72. package/dist/quickstart.js +10 -4
  73. package/dist/quickstart.js.map +1 -1
  74. package/dist/restart-guard.d.ts +52 -0
  75. package/dist/restart-guard.js +109 -0
  76. package/dist/restart-guard.js.map +1 -0
  77. package/dist/scheduler/db.js +6 -2
  78. package/dist/scheduler/db.js.map +1 -1
  79. package/dist/service-activation.d.ts +47 -5
  80. package/dist/service-activation.js +156 -51
  81. package/dist/service-activation.js.map +1 -1
  82. package/dist/service-installer.d.ts +56 -1
  83. package/dist/service-installer.js +134 -12
  84. package/dist/service-installer.js.map +1 -1
  85. package/dist/service-plan.d.ts +65 -0
  86. package/dist/service-plan.js +108 -0
  87. package/dist/service-plan.js.map +1 -0
  88. package/dist/settings-api.js +46 -5
  89. package/dist/settings-api.js.map +1 -1
  90. package/dist/settings-change.js +34 -6
  91. package/dist/settings-change.js.map +1 -1
  92. package/dist/setup-host.js +2 -3
  93. package/dist/setup-host.js.map +1 -1
  94. package/dist/setup-wizard.js +2 -1
  95. package/dist/setup-wizard.js.map +1 -1
  96. package/dist/sqlite-open-errors.d.ts +12 -0
  97. package/dist/sqlite-open-errors.js +13 -0
  98. package/dist/sqlite-open-errors.js.map +1 -0
  99. package/dist/tmux-control.d.ts +22 -0
  100. package/dist/tmux-control.js +89 -5
  101. package/dist/tmux-control.js.map +1 -1
  102. package/dist/topic-commands.js +14 -5
  103. package/dist/topic-commands.js.map +1 -1
  104. package/dist/ui/chat-commands.js +43 -0
  105. package/dist/ui/chat-render.js +2 -2
  106. package/dist/ui/chat-store.js +30 -1
  107. package/dist/ui/chat-strings.js +22 -2
  108. package/dist/ui/chat-thread.js +47 -10
  109. package/dist/ui/fleet-cache.js +168 -0
  110. package/dist/ui/panel-chat.js +104 -18
  111. package/dist/ui/panel-fleet.js +26 -12
  112. package/dist/ui/panel-settings.js +12 -8
  113. package/dist/ui/preview-panel.js +202 -0
  114. package/dist/ui/preview.js +7 -3
  115. package/dist/ui/settings-strings.js +4 -2
  116. package/dist/ui/shared/app-route.js +1 -1
  117. package/dist/ui/shared/app-shell.js +6 -4
  118. package/dist/ui/shared/app.css +147 -3
  119. package/dist/ui/shared/signin.js +13 -1
  120. package/dist/ui/shared/ui-icons.js +2 -0
  121. package/dist/ui/signin.html +2 -1
  122. package/dist/update-dispatch.d.ts +28 -0
  123. package/dist/update-dispatch.js +73 -0
  124. package/dist/update-dispatch.js.map +1 -0
  125. package/dist/update-install.d.ts +65 -7
  126. package/dist/update-install.js +126 -26
  127. package/dist/update-install.js.map +1 -1
  128. package/dist/web-api.d.ts +14 -0
  129. package/dist/web-api.js +65 -0
  130. package/dist/web-api.js.map +1 -1
  131. package/dist/web-commands.d.ts +77 -0
  132. package/dist/web-commands.js +81 -0
  133. package/dist/web-commands.js.map +1 -0
  134. package/dist/web-shell-routes.d.ts +1 -1
  135. package/dist/web-shell-routes.js +1 -1
  136. package/dist/web-shell-routes.js.map +1 -1
  137. package/launcher/agend +110 -0
  138. package/launcher/agend-agent +110 -0
  139. package/launcher/agend-agent.cjs +4 -0
  140. package/launcher/agend.cjs +4 -0
  141. package/launcher/install-admission.cjs +105 -0
  142. package/launcher/launch.cjs +64 -0
  143. package/launcher/postinstall.cjs +114 -0
  144. package/launcher/run-in-process.cjs +13 -0
  145. package/launcher/runtime-platform.cjs +86 -0
  146. package/launcher/runtime-select.cjs +217 -0
  147. package/package.json +12 -4
  148. package/scripts/preinstall-guard.cjs +40 -21
  149. package/templates/launchd.plist.ejs +2 -2
  150. package/templates/systemd.service.ejs +1 -1
@@ -0,0 +1,32 @@
1
+ /**
2
+ * #1468: list prices for the prompt-cache analysis — the one table, with the day it was checked against the vendors'
3
+ * own pricing pages. USD per million tokens, standard tier, global routing (no batch, fast, data-residency or
4
+ * regional uplift: AgEnD's CLIs run on subscriptions, so these are list-price equivalents, not a bill).
5
+ *
6
+ * Claude (platform.claude.com/docs/en/about-claude/pricing): a 5-minute cache write is 1.25x base input, a 1-hour
7
+ * write 2x; a cache hit is 0.1x, except 0.05x on Opus/Sonnet 5.5 and 0.025x on Fable/Mythos 5.1. Haiku 5.5 is priced
8
+ * by prompt length (over 100,000 tokens: the higher row), counting cache reads and writes.
9
+ * OpenAI (developers.openai.com/api/docs/pricing, …/guides/prompt-caching): on GPT-5.6 and later a cache write is
10
+ * 1.25x uncached input and the cache lives 30 minutes after its last write or reuse; prompts over 272K input tokens
11
+ * pay the long-context row.
12
+ */
13
+ export declare const PRICES_CHECKED = "2026-10-09";
14
+ export declare const PRICE_SOURCES: readonly ["https://platform.claude.com/docs/en/about-claude/pricing", "https://developers.openai.com/api/docs/pricing", "https://developers.openai.com/api/docs/guides/prompt-caching"];
15
+ /** USD per million tokens. `write` is the one cache-write rate an OpenAI model has; Claude has `write5m`/`write1h`. */
16
+ export interface Rates {
17
+ input: number;
18
+ read: number;
19
+ write5m: number;
20
+ write1h: number;
21
+ write: number;
22
+ output: number;
23
+ }
24
+ /**
25
+ * The table's key for a model id as a transcript records it: "claude-opus-4-5-20251101" → "claude-opus-4-5",
26
+ * "claude-opus-5-5[1m]" → "claude-opus-5-5". Exact keys only — "claude-opus-5" never prices "claude-opus-5-5".
27
+ */
28
+ export declare function priceKey(model: string | null | undefined): string | null;
29
+ /** The rates for one request of `model` with a prompt of `promptTokens`; null when the model is not in the table. */
30
+ export declare function ratesFor(model: string | null | undefined, promptTokens?: number): Rates | null;
31
+ /** Whether a prompt of this size pays the model's long-context (or over-100K) row. */
32
+ export declare function isLongPrompt(model: string | null | undefined, promptTokens: number): boolean;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * #1468: list prices for the prompt-cache analysis — the one table, with the day it was checked against the vendors'
3
+ * own pricing pages. USD per million tokens, standard tier, global routing (no batch, fast, data-residency or
4
+ * regional uplift: AgEnD's CLIs run on subscriptions, so these are list-price equivalents, not a bill).
5
+ *
6
+ * Claude (platform.claude.com/docs/en/about-claude/pricing): a 5-minute cache write is 1.25x base input, a 1-hour
7
+ * write 2x; a cache hit is 0.1x, except 0.05x on Opus/Sonnet 5.5 and 0.025x on Fable/Mythos 5.1. Haiku 5.5 is priced
8
+ * by prompt length (over 100,000 tokens: the higher row), counting cache reads and writes.
9
+ * OpenAI (developers.openai.com/api/docs/pricing, …/guides/prompt-caching): on GPT-5.6 and later a cache write is
10
+ * 1.25x uncached input and the cache lives 30 minutes after its last write or reuse; prompts over 272K input tokens
11
+ * pay the long-context row.
12
+ */
13
+ export const PRICES_CHECKED = "2026-10-09";
14
+ export const PRICE_SOURCES = [
15
+ "https://platform.claude.com/docs/en/about-claude/pricing",
16
+ "https://developers.openai.com/api/docs/pricing",
17
+ "https://developers.openai.com/api/docs/guides/prompt-caching",
18
+ ];
19
+ const claude = (input, read, output) => ({ input, read, write5m: input * 1.25, write1h: input * 2, write: input * 1.25, output });
20
+ const openai = (input, read, write, output) => ({ input, read, write5m: write, write1h: write, write, output });
21
+ const TABLE = {
22
+ "claude-fable-5-1": { rates: [claude(10, 0.25, 50)] },
23
+ "claude-mythos-5-1": { rates: [claude(10, 0.25, 50)] },
24
+ "claude-fable-5": { rates: [claude(10, 1, 50)] },
25
+ "claude-mythos-5": { rates: [claude(10, 1, 50)] },
26
+ "claude-opus-5-5": { rates: [claude(4, 0.20, 20)] },
27
+ "claude-opus-5": { rates: [claude(5, 0.50, 25)] },
28
+ "claude-opus-4-8": { rates: [claude(5, 0.50, 25)] },
29
+ "claude-opus-4-7": { rates: [claude(5, 0.50, 25)] },
30
+ "claude-opus-4-6": { rates: [claude(5, 0.50, 25)] },
31
+ "claude-opus-4-5": { rates: [claude(5, 0.50, 25)] },
32
+ "claude-opus-4-1": { rates: [claude(15, 1.50, 75)] },
33
+ "claude-opus-4": { rates: [claude(15, 1.50, 75)] },
34
+ "claude-sonnet-5-5": { rates: [claude(2, 0.10, 10)] },
35
+ "claude-sonnet-5": { rates: [claude(2, 0.20, 10)] },
36
+ "claude-sonnet-4-6": { rates: [claude(3, 0.30, 15)] },
37
+ "claude-sonnet-4-5": { rates: [claude(3, 0.30, 15)] },
38
+ "claude-sonnet-4": { rates: [claude(3, 0.30, 15)] },
39
+ "claude-haiku-5-5": { rates: [claude(0.10, 0.01, 0.50), claude(0.50, 0.05, 2.50)], longOver: 100_000 },
40
+ "claude-haiku-4-5": { rates: [claude(1, 0.10, 5)] },
41
+ "gpt-6.1-sol": { rates: [openai(2, 0.10, 2.50, 10), openai(4, 0.20, 5, 15)], longOver: 272_000 },
42
+ "gpt-6-sol": { rates: [openai(2, 0.20, 2.50, 10), openai(4, 0.40, 5, 15)], longOver: 272_000 },
43
+ "gpt-6-astra": { rates: [openai(10, 1, 12.50, 50), openai(20, 2, 25, 75)], longOver: 272_000 },
44
+ "gpt-6-luna": { rates: [openai(0.10, 0.01, 0.125, 0.50), openai(0.20, 0.02, 0.25, 0.75)], longOver: 272_000 },
45
+ "gpt-5.6-sol": { rates: [openai(4, 0.40, 5, 20), openai(8, 0.80, 10, 30)], longOver: 272_000 },
46
+ "gpt-5.6-terra": { rates: [openai(2, 0.20, 2.50, 12), openai(4, 0.40, 5, 18)], longOver: 272_000 },
47
+ "gpt-5.6-luna": { rates: [openai(0.20, 0.02, 0.25, 1.20), openai(0.40, 0.04, 0.50, 1.80)], longOver: 272_000 },
48
+ };
49
+ /**
50
+ * The table's key for a model id as a transcript records it: "claude-opus-4-5-20251101" → "claude-opus-4-5",
51
+ * "claude-opus-5-5[1m]" → "claude-opus-5-5". Exact keys only — "claude-opus-5" never prices "claude-opus-5-5".
52
+ */
53
+ export function priceKey(model) {
54
+ if (typeof model !== "string")
55
+ return null;
56
+ const id = model.trim().toLowerCase().replace(/\[[^\]]*\]$/, "").replace(/-\d{8}$/, "");
57
+ return Object.prototype.hasOwnProperty.call(TABLE, id) ? id : null;
58
+ }
59
+ /** The rates for one request of `model` with a prompt of `promptTokens`; null when the model is not in the table. */
60
+ export function ratesFor(model, promptTokens = 0) {
61
+ const key = priceKey(model);
62
+ if (!key)
63
+ return null;
64
+ const row = TABLE[key];
65
+ return row.longOver !== undefined && promptTokens > row.longOver && row.rates[1] ? row.rates[1] : row.rates[0];
66
+ }
67
+ /** Whether a prompt of this size pays the model's long-context (or over-100K) row. */
68
+ export function isLongPrompt(model, promptTokens) {
69
+ const key = priceKey(model);
70
+ const row = key ? TABLE[key] : undefined;
71
+ return !!row && row.longOver !== undefined && promptTokens > row.longOver;
72
+ }
73
+ //# sourceMappingURL=cache-prices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-prices.js","sourceRoot":"","sources":["../src/cache-prices.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export interface ScanOptions {
2
+ maxBytes: number;
3
+ /** The inode the caller's cursor belongs to: if the descriptor opened is another file, nothing is read. */
4
+ ino?: number;
5
+ chunkBytes?: number;
6
+ wholeUpTo?: number;
7
+ headBytes?: number;
8
+ tailBytes?: number;
9
+ }
10
+ /** A whole line (`whole`), or a long one's two ends (`head`/`tail`). `length` is the line's size in bytes. */
11
+ export type ScanLine = {
12
+ whole: Buffer;
13
+ length: number;
14
+ } | {
15
+ head: Buffer;
16
+ tail: Buffer;
17
+ length: number;
18
+ };
19
+ export interface ScanResult {
20
+ /** Where the next pass starts: just after the last complete line read. */
21
+ offset: number;
22
+ /** The file's size when this pass started (of the descriptor actually opened). */
23
+ size: number;
24
+ /** Nothing complete is left before `size`. */
25
+ done: boolean;
26
+ /** Bytes committed (whole lines). */
27
+ bytes: number;
28
+ /** Bytes physically read — what a pass's budget is charged, unfinished line included. */
29
+ read: number;
30
+ /** The inode of the descriptor opened. */
31
+ ino: number;
32
+ /** `opts.ino` was given and the path now names another file: nothing was read. */
33
+ replaced?: true;
34
+ }
35
+ export declare const SCAN_CHUNK_BYTES: number;
36
+ export declare const SCAN_WHOLE_UP_TO: number;
37
+ export declare function scanJsonl(path: string, from: number, opts: ScanOptions, onLine: (line: ScanLine) => void): Promise<ScanResult>;
38
+ /** The JSON object that starts at `start` (an opening brace) in `text`, or null if it does not close there. */
39
+ export declare function objectAt(text: string, start: number): string | null;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * #1468: read a JSONL file from a byte offset, line by line, without ever holding a large line or blocking the
3
+ * fleet loop. Transcripts reach hundreds of MB, and a single line (a tool result) can be tens of MB:
4
+ * - every chunk read is awaited, so the event loop runs between chunks;
5
+ * - a line up to `wholeUpTo` bytes is handed over whole; a longer one only as its first `headBytes` and last
6
+ * `tailBytes` (a Claude assistant line has its model/id at the start and its usage/timestamp at the end);
7
+ * - a pass stops at the first line end once `maxBytes` have been read (physically: an unfinished line costs what it
8
+ * took to read) and returns the offset to resume from — always a line start. An unfinished last line (a file
9
+ * being appended to) is left for the next pass;
10
+ * - given the cursor's inode, a descriptor that turns out to be another file is not read at all.
11
+ */
12
+ import { open } from "node:fs/promises";
13
+ export const SCAN_CHUNK_BYTES = 256 * 1024;
14
+ export const SCAN_WHOLE_UP_TO = 1024 * 1024;
15
+ const HEAD_BYTES = 8 * 1024;
16
+ const TAIL_BYTES = 64 * 1024;
17
+ export async function scanJsonl(path, from, opts, onLine) {
18
+ const chunkBytes = opts.chunkBytes ?? SCAN_CHUNK_BYTES;
19
+ const wholeUpTo = opts.wholeUpTo ?? SCAN_WHOLE_UP_TO;
20
+ const headBytes = opts.headBytes ?? HEAD_BYTES;
21
+ const tailBytes = opts.tailBytes ?? TAIL_BYTES;
22
+ const fh = await open(path, "r");
23
+ try {
24
+ const st = await fh.stat();
25
+ const size = st.size, ino = st.ino;
26
+ // The file as opened, not as listed: a rename between the two must not feed another file's lines to this cursor.
27
+ if (opts.ino !== undefined && ino !== opts.ino)
28
+ return { offset: from, size, done: true, bytes: 0, read: 0, ino, replaced: true };
29
+ let pos = from, committed = from;
30
+ let parts = [], partLen = 0;
31
+ let big = false, head = Buffer.alloc(0), tail = Buffer.alloc(0), total = 0;
32
+ const append = (seg) => {
33
+ if (!big) {
34
+ if (partLen + seg.length <= wholeUpTo) {
35
+ parts.push(seg);
36
+ partLen += seg.length;
37
+ return;
38
+ }
39
+ const all = Buffer.concat([...parts, seg]);
40
+ head = Buffer.from(all.subarray(0, headBytes));
41
+ tail = Buffer.from(all.subarray(Math.max(0, all.length - tailBytes)));
42
+ total = all.length;
43
+ big = true;
44
+ parts = [];
45
+ partLen = 0;
46
+ return;
47
+ }
48
+ total += seg.length;
49
+ const joined = seg.length >= tailBytes ? seg : Buffer.concat([tail, seg]);
50
+ tail = Buffer.from(joined.subarray(Math.max(0, joined.length - tailBytes)));
51
+ };
52
+ const emit = () => {
53
+ if (big)
54
+ onLine({ head, tail, length: total });
55
+ else if (partLen > 0)
56
+ onLine({ whole: parts.length === 1 ? parts[0] : Buffer.concat(parts, partLen), length: partLen });
57
+ parts = [];
58
+ partLen = 0;
59
+ big = false;
60
+ head = Buffer.alloc(0);
61
+ tail = Buffer.alloc(0);
62
+ total = 0;
63
+ };
64
+ while (pos < size) {
65
+ const want = Math.min(chunkBytes, size - pos);
66
+ const chunk = Buffer.allocUnsafe(want);
67
+ const { bytesRead } = await fh.read(chunk, 0, want, pos);
68
+ if (bytesRead <= 0)
69
+ break;
70
+ let i = 0;
71
+ while (i < bytesRead) {
72
+ const nl = chunk.indexOf(10, i);
73
+ if (nl === -1 || nl >= bytesRead) {
74
+ append(chunk.subarray(i, bytesRead));
75
+ i = bytesRead;
76
+ break;
77
+ }
78
+ append(chunk.subarray(i, nl));
79
+ emit();
80
+ committed = pos + nl + 1;
81
+ i = nl + 1;
82
+ if (pos + bytesRead - from >= opts.maxBytes)
83
+ return { offset: committed, size, done: committed >= size, bytes: committed - from, read: pos + bytesRead - from, ino };
84
+ }
85
+ pos += bytesRead;
86
+ }
87
+ return { offset: committed, size, done: true, bytes: committed - from, read: pos - from, ino };
88
+ }
89
+ finally {
90
+ await fh.close();
91
+ }
92
+ }
93
+ /** The JSON object that starts at `start` (an opening brace) in `text`, or null if it does not close there. */
94
+ export function objectAt(text, start) {
95
+ if (text[start] !== "{")
96
+ return null;
97
+ let depth = 0, inString = false;
98
+ for (let i = start; i < text.length; i++) {
99
+ const c = text[i];
100
+ if (inString) {
101
+ if (c === "\\")
102
+ i++;
103
+ else if (c === "\"")
104
+ inString = false;
105
+ }
106
+ else if (c === "\"")
107
+ inString = true;
108
+ else if (c === "{")
109
+ depth++;
110
+ else if (c === "}" && --depth === 0)
111
+ return text.slice(start, i + 1);
112
+ }
113
+ return null;
114
+ }
115
+ //# sourceMappingURL=cache-scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-scan.js","sourceRoot":"","sources":["../src/cache-scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
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
+ private pending;
73
+ private caughtUp;
74
+ private readonly now;
75
+ constructor(o: CacheServiceOptions);
76
+ /** Catch up now (joins a catch-up already running). */
77
+ kick(): Promise<void>;
78
+ /** Keep up on a timer from now on (the first report starts it). */
79
+ start(): void;
80
+ stop(): void;
81
+ scanning(): CacheReport["scanning"];
82
+ private catchUp;
83
+ private ledgerFor;
84
+ /**
85
+ * The instances whose transcripts land where another's do — the same Claude project (working directory), the
86
+ * same Codex cwd — mapped to the others. They are not read: nothing in a transcript says which one wrote it.
87
+ */
88
+ private shared;
89
+ private passing;
90
+ /**
91
+ * One bounded pass over every instance's files. Returns the bytes still behind afterwards. Passes never overlap
92
+ * (two reading one file from the same cursor would count it twice): a pass asked for during another runs after it.
93
+ */
94
+ pass(): Promise<number>;
95
+ private passOnce;
96
+ /** A file that is not the one the cursor read (another inode, or shorter): keep the session's end, start at its end. */
97
+ private followFromEnd;
98
+ private read;
99
+ private claudeFiles;
100
+ /** Codex rollouts of the last KEEP_DAYS, by the instance whose working directory their session_meta names. */
101
+ private codexFilesByInstance;
102
+ /** Write what changed; whatever fails to write stays dirty and is written by a later pass. */
103
+ private save;
104
+ /** The analysis for a window, from the ledgers as they are now (a catch-up is started, not waited for). */
105
+ report(window: CacheWindow): Promise<CacheReport>;
106
+ }
107
+ /**
108
+ * A rollout's session_meta, read with one bounded read through the descriptor whose inode it records. Null while the
109
+ * first line is not complete yet (the next pass reads it again); `cwd: null` for a complete first line that is not
110
+ * a session_meta.
111
+ */
112
+ export declare function rolloutMeta(path: string): Promise<{
113
+ ino: number;
114
+ cwd: string | null;
115
+ } | null>;