botmux 2.67.1 → 2.68.0

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 (55) hide show
  1. package/dist/adapters/cli/pi.d.ts.map +1 -1
  2. package/dist/adapters/cli/pi.js +0 -1
  3. package/dist/adapters/cli/pi.js.map +1 -1
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +79 -17
  6. package/dist/cli.js.map +1 -1
  7. package/dist/core/auto-start.d.ts +23 -0
  8. package/dist/core/auto-start.d.ts.map +1 -1
  9. package/dist/core/auto-start.js +30 -0
  10. package/dist/core/auto-start.js.map +1 -1
  11. package/dist/core/command-handler.d.ts +9 -9
  12. package/dist/core/command-handler.d.ts.map +1 -1
  13. package/dist/core/command-handler.js +23 -16
  14. package/dist/core/command-handler.js.map +1 -1
  15. package/dist/core/cost-calculator.d.ts +27 -0
  16. package/dist/core/cost-calculator.d.ts.map +1 -1
  17. package/dist/core/cost-calculator.js +483 -27
  18. package/dist/core/cost-calculator.js.map +1 -1
  19. package/dist/core/dashboard-rows.d.ts +3 -0
  20. package/dist/core/dashboard-rows.d.ts.map +1 -1
  21. package/dist/core/dashboard-rows.js +11 -0
  22. package/dist/core/dashboard-rows.js.map +1 -1
  23. package/dist/core/worker-pool.d.ts.map +1 -1
  24. package/dist/core/worker-pool.js +22 -1
  25. package/dist/core/worker-pool.js.map +1 -1
  26. package/dist/daemon.d.ts.map +1 -1
  27. package/dist/daemon.js +15 -6
  28. package/dist/daemon.js.map +1 -1
  29. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  30. package/dist/dashboard/web/i18n.js +4 -0
  31. package/dist/dashboard/web/i18n.js.map +1 -1
  32. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  33. package/dist/dashboard/web/sessions.js +16 -1
  34. package/dist/dashboard/web/sessions.js.map +1 -1
  35. package/dist/dashboard-web/app.js +120 -116
  36. package/dist/dashboard-web/style.css +4 -0
  37. package/dist/dashboard.js +41 -13
  38. package/dist/dashboard.js.map +1 -1
  39. package/dist/i18n/en.js +2 -2
  40. package/dist/i18n/en.js.map +1 -1
  41. package/dist/i18n/zh.js +2 -2
  42. package/dist/i18n/zh.js.map +1 -1
  43. package/dist/services/aiden-checkpoints.d.ts +5 -0
  44. package/dist/services/aiden-checkpoints.d.ts.map +1 -0
  45. package/dist/services/aiden-checkpoints.js +91 -0
  46. package/dist/services/aiden-checkpoints.js.map +1 -0
  47. package/dist/services/codex-transcript.d.ts +7 -0
  48. package/dist/services/codex-transcript.d.ts.map +1 -1
  49. package/dist/services/codex-transcript.js +60 -1
  50. package/dist/services/codex-transcript.js.map +1 -1
  51. package/dist/services/usage-ledger.d.ts +81 -0
  52. package/dist/services/usage-ledger.d.ts.map +1 -0
  53. package/dist/services/usage-ledger.js +353 -0
  54. package/dist/services/usage-ledger.js.map +1 -0
  55. package/package.json +1 -1
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Usage ledger — durable per-turn token usage records.
3
+ *
4
+ * On every turn boundary (working→idle edge, session close) the daemon takes
5
+ * a cumulative token snapshot of the session's transcript (via the cached
6
+ * reader in cost-calculator) and appends the positive delta as one
7
+ * self-describing JSON line to a daily ledger file.
8
+ *
9
+ * The ledger is the stable contract for external usage trackers (kaboo-cli
10
+ * reads it the same way it reads HappyClaw's usage_records table):
11
+ * ~/.botmux/usage/usage-YYYY-MM-DD.jsonl (UTC date, append-only)
12
+ * ~/.botmux/usage/state.json (per-session baselines)
13
+ *
14
+ * Records intentionally carry redundant context (larkAppId, chatId, title,
15
+ * callerOpenId, cumulative totals) so a single excerpted line self-validates
16
+ * without joining back to sessions.json.
17
+ */
18
+ import { appendFileSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
19
+ import { homedir } from 'node:os';
20
+ import { join } from 'node:path';
21
+ import { createHash } from 'node:crypto';
22
+ import { logger } from '../utils/logger.js';
23
+ import { getSessionTokenUsage } from '../core/cost-calculator.js';
24
+ /** Last authoritative baseline per session, kept in memory: the hot path
25
+ * never rescans the ledger, and a lost/stale state file inside one process
26
+ * lifetime cannot regress the baseline. */
27
+ const sessionBaselineMemory = new Map();
28
+ export function __resetUsageLedgerMemoryForTest() {
29
+ sessionBaselineMemory.clear();
30
+ }
31
+ function baselineMemoryKey(larkAppId, sessionId) {
32
+ return `${larkAppId ?? ''}\u0000${sessionId}`;
33
+ }
34
+ function finiteNum(v) {
35
+ return typeof v === 'number' && Number.isFinite(v) ? v : 0;
36
+ }
37
+ /** Reconstruct the newest baseline for a session from the ledger files
38
+ * themselves (newest file first; last matching line in a file is newest).
39
+ * This is the crash-recovery source of truth: a record that reached the
40
+ * ledger but whose state advance was lost is still binding. */
41
+ function baselineFromLedger(dir, sessionId) {
42
+ let files;
43
+ try {
44
+ files = readdirSync(dir)
45
+ .filter((f) => /^usage-\d{4}-\d{2}-\d{2}\.jsonl$/.test(f))
46
+ .sort()
47
+ .reverse();
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ for (const name of files) {
53
+ let content;
54
+ try {
55
+ content = readFileSync(join(dir, name), 'utf8');
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ let latest = null;
61
+ for (const line of content.split('\n')) {
62
+ if (!line.includes(sessionId))
63
+ continue;
64
+ try {
65
+ const rec = JSON.parse(line);
66
+ if (rec?.sessionId === sessionId)
67
+ latest = rec;
68
+ }
69
+ catch { /* skip malformed lines */ }
70
+ }
71
+ if (latest) {
72
+ return {
73
+ inputTokens: finiteNum(latest.totalInputTokens),
74
+ outputTokens: finiteNum(latest.totalOutputTokens),
75
+ cacheReadTokens: finiteNum(latest.totalCacheReadTokens),
76
+ cacheCreateTokens: finiteNum(latest.totalCacheCreateTokens),
77
+ recordedAt: typeof latest.ts === 'string' ? latest.ts : new Date(0).toISOString(),
78
+ epoch: finiteNum(latest.epoch),
79
+ };
80
+ }
81
+ }
82
+ return null;
83
+ }
84
+ /** Of two baseline candidates, pick the newer: higher epoch wins; within an
85
+ * epoch totals are monotonic, so the larger sum wins. */
86
+ function newerBaseline(a, b) {
87
+ if (!a)
88
+ return b ?? undefined;
89
+ if (!b)
90
+ return a;
91
+ const ea = a.epoch ?? 0;
92
+ const eb = b.epoch ?? 0;
93
+ if (ea !== eb)
94
+ return ea > eb ? a : b;
95
+ const sum = (x) => x.inputTokens + x.outputTokens + x.cacheReadTokens + x.cacheCreateTokens;
96
+ return sum(a) >= sum(b) ? a : b;
97
+ }
98
+ /** Effective baseline = newest of (state file, in-memory latest, ledger scan).
99
+ * The ledger scan runs at most once per session per process lifetime. */
100
+ function resolveBaseline(dir, larkAppId, sessionId, stateBaseline) {
101
+ const key = baselineMemoryKey(larkAppId, sessionId);
102
+ let remembered = sessionBaselineMemory.get(key);
103
+ if (remembered === undefined) {
104
+ remembered = baselineFromLedger(dir, sessionId);
105
+ sessionBaselineMemory.set(key, remembered);
106
+ }
107
+ return newerBaseline(stateBaseline, remembered);
108
+ }
109
+ /** Baselines for sessions idle longer than this are pruned from state.json. */
110
+ const BASELINE_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
111
+ export function defaultLedgerDir() {
112
+ return process.env.BOTMUX_USAGE_DIR || join(homedir(), '.botmux', 'usage');
113
+ }
114
+ // Baselines are partitioned per bot (larkAppId): botmux can run one daemon
115
+ // per bot, and a shared read-modify-write state file would let one daemon's
116
+ // rename clobber another's freshly advanced baselines.
117
+ function statePath(dir, larkAppId) {
118
+ const id = (larkAppId ?? '').replace(/[^A-Za-z0-9_-]/g, '') || 'default';
119
+ return join(dir, `state-${id}.json`);
120
+ }
121
+ function loadState(dir, larkAppId) {
122
+ try {
123
+ const parsed = JSON.parse(readFileSync(statePath(dir, larkAppId), 'utf8'));
124
+ if (parsed && typeof parsed === 'object' && parsed.sessions && typeof parsed.sessions === 'object') {
125
+ return { v: 1, sessions: parsed.sessions };
126
+ }
127
+ }
128
+ catch { /* first run or corrupt state — start fresh */ }
129
+ return { v: 1, sessions: {} };
130
+ }
131
+ function saveState(dir, larkAppId, state, now) {
132
+ for (const [sessionId, baseline] of Object.entries(state.sessions)) {
133
+ const recordedAt = Date.parse(baseline.recordedAt);
134
+ if (Number.isFinite(recordedAt) && now.getTime() - recordedAt > BASELINE_RETENTION_MS) {
135
+ delete state.sessions[sessionId];
136
+ }
137
+ }
138
+ // temp+rename keeps a crash from truncating state; the pid suffix keeps
139
+ // concurrent daemons from stomping each other's tmp file.
140
+ const target = statePath(dir, larkAppId);
141
+ const tmp = `${target}.${process.pid}.tmp`;
142
+ writeFileSync(tmp, JSON.stringify(state));
143
+ renameSync(tmp, target);
144
+ }
145
+ /** Deterministic id for one baseline→snapshot transition: a crash-replay of
146
+ * the same transition regenerates the SAME id, so the consumer's DedupKey
147
+ * collapses the duplicated ledger line instead of double counting it. */
148
+ function deterministicRecordId(sessionId, epoch, prev, cur) {
149
+ const h = createHash('sha256');
150
+ h.update([
151
+ sessionId,
152
+ epoch,
153
+ prev?.inputTokens ?? 0,
154
+ prev?.outputTokens ?? 0,
155
+ prev?.cacheReadTokens ?? 0,
156
+ prev?.cacheCreateTokens ?? 0,
157
+ cur.inputTokens,
158
+ cur.outputTokens,
159
+ cur.cacheReadTokens,
160
+ cur.cacheCreateTokens,
161
+ ].join('|'));
162
+ return h.digest('hex').slice(0, 32);
163
+ }
164
+ function ledgerFilePath(dir, now) {
165
+ const date = now.toISOString().slice(0, 10);
166
+ return join(dir, `usage-${date}.jsonl`);
167
+ }
168
+ /**
169
+ * Diff the cumulative usage snapshot against the session's stored baseline
170
+ * and append a record when the delta is positive. Returns the record, or
171
+ * null when there is nothing to write (no growth, or a shrink — transcript
172
+ * rotation / clear — which just resets the baseline).
173
+ */
174
+ export function recordSessionUsage(args) {
175
+ try {
176
+ const now = args.now ?? new Date();
177
+ const dir = args.ledgerDir ?? defaultLedgerDir();
178
+ mkdirSync(dir, { recursive: true });
179
+ const state = loadState(dir, args.larkAppId);
180
+ const prev = resolveBaseline(dir, args.larkAppId, args.sessionId, state.sessions[args.sessionId]);
181
+ const cur = args.usage;
182
+ const prevEpoch = prev?.epoch ?? 0;
183
+ const deltaInput = cur.inputTokens - (prev?.inputTokens ?? 0);
184
+ const deltaOutput = cur.outputTokens - (prev?.outputTokens ?? 0);
185
+ const deltaCacheRead = cur.cacheReadTokens - (prev?.cacheReadTokens ?? 0);
186
+ const deltaCacheCreate = cur.cacheCreateTokens - (prev?.cacheCreateTokens ?? 0);
187
+ const baseline = {
188
+ inputTokens: cur.inputTokens,
189
+ outputTokens: cur.outputTokens,
190
+ cacheReadTokens: cur.cacheReadTokens,
191
+ cacheCreateTokens: cur.cacheCreateTokens,
192
+ recordedAt: now.toISOString(),
193
+ epoch: prevEpoch,
194
+ };
195
+ if (deltaInput < 0 || deltaOutput < 0 || deltaCacheRead < 0 || deltaCacheCreate < 0) {
196
+ // Cumulative shrank (/clear, rotation): re-anchor, never write negatives.
197
+ // The epoch bump keeps a later identical totals transition from reusing
198
+ // a pre-reset recordId.
199
+ baseline.epoch = prevEpoch + 1;
200
+ sessionBaselineMemory.set(baselineMemoryKey(args.larkAppId, args.sessionId), baseline);
201
+ state.sessions[args.sessionId] = baseline;
202
+ saveState(dir, args.larkAppId, state, now);
203
+ return null;
204
+ }
205
+ if (deltaInput === 0 && deltaOutput === 0 && deltaCacheRead === 0 && deltaCacheCreate === 0) {
206
+ return null;
207
+ }
208
+ const record = {
209
+ v: 1,
210
+ recordId: deterministicRecordId(args.sessionId, prevEpoch, prev, cur),
211
+ ts: now.toISOString(),
212
+ epoch: prevEpoch,
213
+ ...(args.larkAppId ? { larkAppId: args.larkAppId } : {}),
214
+ sessionId: args.sessionId,
215
+ ...(args.cliId ? { cliId: args.cliId } : {}),
216
+ ...(args.cliSessionId ? { cliSessionId: args.cliSessionId } : {}),
217
+ ...(args.chatId ? { chatId: args.chatId } : {}),
218
+ ...(args.title ? { title: args.title } : {}),
219
+ ...(args.workingDir ? { workingDir: args.workingDir } : {}),
220
+ ...(args.callerOpenId ? { callerOpenId: args.callerOpenId } : {}),
221
+ model: cur.model,
222
+ inputTokens: deltaInput,
223
+ outputTokens: deltaOutput,
224
+ cacheReadTokens: deltaCacheRead,
225
+ cacheCreateTokens: deltaCacheCreate,
226
+ totalInputTokens: cur.inputTokens,
227
+ totalOutputTokens: cur.outputTokens,
228
+ totalCacheReadTokens: cur.cacheReadTokens,
229
+ totalCacheCreateTokens: cur.cacheCreateTokens,
230
+ };
231
+ // Append first, then advance the baseline: a crash in between replays the
232
+ // same transition with the SAME recordId, which the consumer dedupes.
233
+ appendFileSync(ledgerFilePath(dir, now), JSON.stringify(record) + '\n');
234
+ // Memory advances immediately after the append: even if saveState throws
235
+ // without killing the process, this process will not re-bill the interval.
236
+ sessionBaselineMemory.set(baselineMemoryKey(args.larkAppId, args.sessionId), baseline);
237
+ state.sessions[args.sessionId] = baseline;
238
+ saveState(dir, args.larkAppId, state, now);
239
+ return record;
240
+ }
241
+ catch (err) {
242
+ // The ledger must never take the daemon down with it.
243
+ logger.error(`usage-ledger: failed to record session usage: ${err?.message ?? err}`);
244
+ return null;
245
+ }
246
+ }
247
+ /**
248
+ * Re-anchor a session's baseline to the current cumulative snapshot WITHOUT
249
+ * writing a record. Called at worker spawn: anything already in the
250
+ * transcript at that point (resumed history, direct-tmux use while the
251
+ * daemon was down) stays out of the ledger — only growth that happens while
252
+ * botmux drives the session is recorded.
253
+ */
254
+ export function anchorSessionUsage(args) {
255
+ try {
256
+ const now = args.now ?? new Date();
257
+ const dir = args.ledgerDir ?? defaultLedgerDir();
258
+ mkdirSync(dir, { recursive: true });
259
+ const state = loadState(dir, args.larkAppId);
260
+ const prev = resolveBaseline(dir, args.larkAppId, args.sessionId, state.sessions[args.sessionId]);
261
+ const baseline = {
262
+ inputTokens: args.usage.inputTokens,
263
+ outputTokens: args.usage.outputTokens,
264
+ cacheReadTokens: args.usage.cacheReadTokens,
265
+ cacheCreateTokens: args.usage.cacheCreateTokens,
266
+ recordedAt: now.toISOString(),
267
+ // Anchors start a new epoch: transitions after a re-anchor must never
268
+ // collide with recordIds from before it.
269
+ epoch: (prev?.epoch ?? 0) + 1,
270
+ };
271
+ sessionBaselineMemory.set(baselineMemoryKey(args.larkAppId, args.sessionId), baseline);
272
+ state.sessions[args.sessionId] = baseline;
273
+ saveState(dir, args.larkAppId, state, now);
274
+ }
275
+ catch (err) {
276
+ logger.error(`usage-ledger: failed to anchor session baseline: ${err?.message ?? err}`);
277
+ }
278
+ }
279
+ function ledgerArgsForDaemonSession(ds) {
280
+ const s = ds.session;
281
+ const workingDir = ds.workingDir ?? s.workingDir;
282
+ // fresh: ledger snapshots are turn-boundary exact — bypass the dashboard
283
+ // read throttle (incremental folding keeps this cheap).
284
+ const usage = getSessionTokenUsage({
285
+ cliId: s.cliId ?? 'unknown',
286
+ sessionId: s.sessionId,
287
+ cliSessionId: s.cliSessionId,
288
+ cwd: workingDir,
289
+ fresh: true,
290
+ });
291
+ return {
292
+ sessionId: s.sessionId,
293
+ usage,
294
+ larkAppId: ds.larkAppId ?? s.larkAppId,
295
+ cliId: s.cliId,
296
+ cliSessionId: s.cliSessionId,
297
+ chatId: s.chatId,
298
+ title: s.title,
299
+ workingDir,
300
+ callerOpenId: s.lastCallerOpenId ?? s.creatorOpenId ?? s.ownerOpenId,
301
+ };
302
+ }
303
+ /** Turn boundary (idle/limited edge, session close): append the delta. */
304
+ export function recordUsageForDaemonSession(ds, opts) {
305
+ try {
306
+ const args = ledgerArgsForDaemonSession(ds);
307
+ if (!args.usage)
308
+ return null;
309
+ return recordSessionUsage({ ...args, usage: args.usage, ...opts });
310
+ }
311
+ catch (err) {
312
+ logger.error(`usage-ledger: failed to record daemon session usage: ${err?.message ?? err}`);
313
+ return null;
314
+ }
315
+ }
316
+ /**
317
+ * Daemon-restart restore: a turn that was in flight when the daemon died may
318
+ * have finished inside tmux while we were away — that work was submitted by
319
+ * botmux and belongs in the ledger. If the session already has a baseline,
320
+ * record the catch-up delta; only sessions the ledger has never seen are
321
+ * anchored (their transcript history predates botmux bookkeeping).
322
+ */
323
+ export function reconcileUsageForDaemonSession(ds, opts) {
324
+ try {
325
+ const args = ledgerArgsForDaemonSession(ds);
326
+ if (!args.usage)
327
+ return null;
328
+ const dir = opts?.ledgerDir ?? defaultLedgerDir();
329
+ const state = loadState(dir, args.larkAppId);
330
+ if (resolveBaseline(dir, args.larkAppId, args.sessionId, state.sessions[args.sessionId])) {
331
+ return recordSessionUsage({ ...args, usage: args.usage, ...opts });
332
+ }
333
+ anchorSessionUsage({ ...args, usage: args.usage, ...opts });
334
+ return null;
335
+ }
336
+ catch (err) {
337
+ logger.error(`usage-ledger: failed to reconcile daemon session usage: ${err?.message ?? err}`);
338
+ return null;
339
+ }
340
+ }
341
+ /** Worker spawn: re-anchor so pre-existing transcript history is not billed. */
342
+ export function anchorUsageForDaemonSession(ds, opts) {
343
+ try {
344
+ const args = ledgerArgsForDaemonSession(ds);
345
+ if (!args.usage)
346
+ return;
347
+ anchorSessionUsage({ ...args, usage: args.usage, ...opts });
348
+ }
349
+ catch (err) {
350
+ logger.error(`usage-ledger: failed to anchor daemon session usage: ${err?.message ?? err}`);
351
+ }
352
+ }
353
+ //# sourceMappingURL=usage-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-ledger.js","sourceRoot":"","sources":["../../src/services/usage-ledger.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botmux",
3
- "version": "2.67.1",
3
+ "version": "2.68.0",
4
4
  "description": "Bridge between IM platforms and AI coding CLIs — one topic, one CLI session with live streaming",
5
5
  "type": "module",
6
6
  "main": "dist/index-daemon.js",