@omnicross/daemon 0.1.9 → 0.1.10

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.
package/dist/cli.js CHANGED
@@ -1,86 +1,633 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // src/commands/import-ccr.ts
4
- import { readFileSync as readFileSync3 } from "fs";
3
+ // src/commands/audit.ts
4
+ import { readdirSync as readdirSync3 } from "fs";
5
+ import { join as join5 } from "path";
5
6
  import { parseArgs } from "util";
6
7
 
7
- // src/ccr-import.ts
8
- function parseCcrConfig(raw) {
9
- if (!raw || typeof raw !== "object") {
10
- throw new Error("CCR config: top-level value must be an object");
8
+ // src/audit/auditBodyReader.ts
9
+ import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
10
+ import { join as join2 } from "path";
11
+ import { gunzipSync } from "zlib";
12
+
13
+ // src/audit/auditBodyStore.ts
14
+ var ANCHOR_EVERY = 64;
15
+ var ANCHOR_DELTA_RATIO = 0.75;
16
+ var DIVERGED_PREFIX_RATIO = 0.25;
17
+ var MAX_BASE_CHARS = 4e6;
18
+ var CACHE_BUDGET_CHARS = 16e6;
19
+ var CACHE_MAX_SESSIONS = 32;
20
+ var MAX_BASES_PER_SESSION = 4;
21
+ var isHighSurrogate = (code) => code >= 55296 && code <= 56319;
22
+ var isLowSurrogate = (code) => code >= 56320 && code <= 57343;
23
+ function computeBodyDelta(prev, next) {
24
+ const shortest = Math.min(prev.length, next.length);
25
+ let pre = 0;
26
+ while (pre < shortest && prev.charCodeAt(pre) === next.charCodeAt(pre)) pre += 1;
27
+ if (pre > 0 && isHighSurrogate(prev.charCodeAt(pre - 1))) pre -= 1;
28
+ const maxSuf = shortest - pre;
29
+ let suf = 0;
30
+ while (suf < maxSuf && prev.charCodeAt(prev.length - 1 - suf) === next.charCodeAt(next.length - 1 - suf)) {
31
+ suf += 1;
32
+ }
33
+ if (suf > 0 && isLowSurrogate(prev.charCodeAt(prev.length - suf))) suf -= 1;
34
+ return { pre, suf, ins: next.slice(pre, next.length - suf) };
35
+ }
36
+ function applyBodyDelta(prev, delta) {
37
+ const head = delta.pre > 0 ? prev.slice(0, delta.pre) : "";
38
+ const tail = delta.suf > 0 ? prev.slice(prev.length - delta.suf) : "";
39
+ return head + delta.ins + tail;
40
+ }
41
+ var SessionBaseCache = class {
42
+ constructor(maxSessions = CACHE_MAX_SESSIONS, budgetChars = CACHE_BUDGET_CHARS, maxBaseChars = MAX_BASE_CHARS, maxHeads = MAX_BASES_PER_SESSION) {
43
+ this.maxSessions = maxSessions;
44
+ this.budgetChars = budgetChars;
45
+ this.maxBaseChars = maxBaseChars;
46
+ this.maxHeads = maxHeads;
47
+ }
48
+ maxSessions;
49
+ budgetChars;
50
+ maxBaseChars;
51
+ maxHeads;
52
+ /** Session key to its retained heads, most-recent first. */
53
+ entries = /* @__PURE__ */ new Map();
54
+ chars = 0;
55
+ /** Retained sessions (tests + diagnostics). */
56
+ get size() {
57
+ return this.entries.size;
58
+ }
59
+ /** A session's retained heads, most-recent first. Refreshes LRU recency. */
60
+ get(sessionKey) {
61
+ const found = this.entries.get(sessionKey);
62
+ if (!found) return [];
63
+ this.entries.delete(sessionKey);
64
+ this.entries.set(sessionKey, found);
65
+ return found;
11
66
  }
12
- const obj = raw;
13
- const Providers = Array.isArray(obj["Providers"]) ? obj["Providers"] : [];
14
- const Router = obj["Router"] && typeof obj["Router"] === "object" ? obj["Router"] : {};
15
- return { Providers, Router };
67
+ /**
68
+ * Retain `base` as a head of `sessionKey`.
69
+ *
70
+ * `replacesId` is the head this turn CONTINUES (its body was preserved whole
71
+ * inside the new one), which is swapped out so a linear conversation keeps
72
+ * exactly one head. Omit it when the turn started a distinct stream %s that
73
+ * head is added alongside, which is what keeps a fork's branches apart.
74
+ *
75
+ * A body larger than `maxBaseChars` is not retained: the next turn anchors
76
+ * rather than letting one oversized session monopolize the budget.
77
+ */
78
+ remember(sessionKey, base, replacesId) {
79
+ const heads = this.entries.get(sessionKey) ?? [];
80
+ if (replacesId !== void 0) {
81
+ const at = heads.findIndex((head) => head.lastId === replacesId);
82
+ if (at >= 0) {
83
+ this.chars -= heads[at].text.length;
84
+ heads.splice(at, 1);
85
+ }
86
+ }
87
+ if (base.text.length <= this.maxBaseChars) {
88
+ heads.unshift(base);
89
+ this.chars += base.text.length;
90
+ }
91
+ while (heads.length > this.maxHeads) {
92
+ const dropped = heads.pop();
93
+ if (dropped) this.chars -= dropped.text.length;
94
+ }
95
+ this.entries.delete(sessionKey);
96
+ if (heads.length > 0) this.entries.set(sessionKey, heads);
97
+ this.evict();
98
+ }
99
+ /** Drop a session's heads (eviction, or a write failure invalidating them). */
100
+ forget(sessionKey) {
101
+ const heads = this.entries.get(sessionKey);
102
+ if (!heads) return;
103
+ for (const head of heads) this.chars -= head.text.length;
104
+ this.entries.delete(sessionKey);
105
+ }
106
+ /** Drop everything (writer disposal / test teardown). */
107
+ clear() {
108
+ this.entries.clear();
109
+ this.chars = 0;
110
+ }
111
+ /** Evict least-recently-used sessions until both bounds hold. */
112
+ evict() {
113
+ while (this.entries.size > this.maxSessions || this.chars > this.budgetChars && this.entries.size > 1) {
114
+ const oldest = this.entries.keys().next();
115
+ if (oldest.done) break;
116
+ this.forget(oldest.value);
117
+ }
118
+ }
119
+ };
120
+ function anchorReason(base, dayDir, delta, nextLength) {
121
+ if (!base || !delta) return "new";
122
+ if (base.dayDir !== dayDir) return "day";
123
+ if (base.chainLen >= ANCHOR_EVERY) return "chain";
124
+ if (delta.pre < base.text.length * DIVERGED_PREFIX_RATIO) return "diverged";
125
+ if (delta.ins.length > nextLength * ANCHOR_DELTA_RATIO) return "costly";
126
+ return null;
16
127
  }
17
- function inferApiFormat(provider) {
18
- const hay = `${provider.api_base_url ?? ""} ${provider.name ?? ""}`.toLowerCase();
19
- if (hay.includes("anthropic") || hay.includes("claude")) {
20
- return { format: "anthropic", ambiguous: false };
128
+ function pickBase(heads, next) {
129
+ let best = null;
130
+ for (const base of heads) {
131
+ const delta = computeBodyDelta(base.text, next);
132
+ if (best !== null && delta.ins.length >= best.delta.ins.length) continue;
133
+ best = { base, delta, continues: delta.pre + delta.suf >= base.text.length };
134
+ }
135
+ return best;
136
+ }
137
+ function encodeBodyEntry(record, sessionKey, dayDir, cache) {
138
+ const requestBody = record.requestBody;
139
+ const responseBody = record.responseBody;
140
+ if (requestBody === void 0 && responseBody === void 0) return null;
141
+ const entry = { id: record.id, ts: record.ts };
142
+ if (requestBody !== void 0) {
143
+ const heads = cache.get(sessionKey);
144
+ const sameDay = heads.filter((head) => head.dayDir === dayDir);
145
+ const chosen = pickBase(sameDay, requestBody);
146
+ const reason = heads.length > 0 && sameDay.length === 0 ? "day" : anchorReason(chosen?.base, dayDir, chosen?.delta ?? null, requestBody.length);
147
+ if (reason !== null) {
148
+ entry.req = { base: null, anchor: reason, pre: 0, suf: 0, ins: requestBody };
149
+ cache.remember(
150
+ sessionKey,
151
+ { dayDir, lastId: record.id, text: requestBody, chainLen: 0 },
152
+ chosen?.continues === true ? chosen.base.lastId : void 0
153
+ );
154
+ } else {
155
+ const picked = chosen;
156
+ entry.req = {
157
+ base: picked.base.lastId,
158
+ ...picked.continues ? { cont: true } : {},
159
+ pre: picked.delta.pre,
160
+ suf: picked.delta.suf,
161
+ ins: picked.delta.ins
162
+ };
163
+ cache.remember(
164
+ sessionKey,
165
+ { dayDir, lastId: record.id, text: requestBody, chainLen: picked.base.chainLen + 1 },
166
+ picked.continues ? picked.base.lastId : void 0
167
+ );
168
+ }
21
169
  }
22
- if (hay.includes("generativelanguage") || hay.includes("gemini") || hay.includes("google")) {
23
- return { format: "gemini", ambiguous: false };
170
+ if (responseBody !== void 0) entry.res = responseBody;
171
+ return JSON.stringify(entry);
172
+ }
173
+ function isAuditBodyEntry(value) {
174
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
175
+ const entry = value;
176
+ if (typeof entry["id"] !== "string" || typeof entry["ts"] !== "number") return false;
177
+ if (entry["res"] !== void 0 && typeof entry["res"] !== "string") return false;
178
+ const req = entry["req"];
179
+ if (req === void 0) return true;
180
+ if (!req || typeof req !== "object" || Array.isArray(req)) return false;
181
+ const delta = req;
182
+ if (delta["anchor"] !== void 0 && typeof delta["anchor"] !== "string") return false;
183
+ if (delta["cont"] !== void 0 && typeof delta["cont"] !== "boolean") return false;
184
+ return (delta["base"] === null || typeof delta["base"] === "string") && Number.isSafeInteger(delta["pre"]) && delta["pre"] >= 0 && Number.isSafeInteger(delta["suf"]) && delta["suf"] >= 0 && typeof delta["ins"] === "string";
185
+ }
186
+
187
+ // src/audit/auditDictionary.ts
188
+ import { existsSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs";
189
+ import { join } from "path";
190
+
191
+ // src/audit/auditFiles.ts
192
+ var AUDIT_FILE_RE = /^audit-(\d{4})-(\d{2})-(\d{2})\.jsonl$/;
193
+ var AUDIT_DAY_DIR_RE = /^audit-(\d{4})-(\d{2})-(\d{2})$/;
194
+ var AUDIT_META_FILE = "meta.jsonl";
195
+ var AUDIT_BODIES_DIR = "bodies";
196
+ var AUDIT_SESSION_KEY_RE = /^[0-9a-f]{8,64}$/;
197
+ var pad2 = (n) => String(n).padStart(2, "0");
198
+ var localDateStamp = (ts) => {
199
+ const d = new Date(ts);
200
+ return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
201
+ };
202
+ function auditDayDirName(ts) {
203
+ return `audit-${localDateStamp(ts)}`;
204
+ }
205
+ function isAuditDayDir(name) {
206
+ return AUDIT_DAY_DIR_RE.test(name);
207
+ }
208
+ function isSafeSessionKey(key) {
209
+ return typeof key === "string" && AUDIT_SESSION_KEY_RE.test(key);
210
+ }
211
+ function auditBodyFileName(sessionKey) {
212
+ return `${sessionKey}.jsonl`;
213
+ }
214
+ function auditFileDateMs(name) {
215
+ const m = AUDIT_FILE_RE.exec(name) ?? AUDIT_DAY_DIR_RE.exec(name);
216
+ if (!m) return null;
217
+ const year = Number(m[1]);
218
+ const month = Number(m[2]);
219
+ const day = Number(m[3]);
220
+ const d = new Date(year, month - 1, day);
221
+ if (d.getFullYear() !== year || d.getMonth() !== month - 1 || d.getDate() !== day) {
222
+ return null;
24
223
  }
25
- if (hay.includes("/responses")) {
26
- return { format: "openai-response", ambiguous: false };
224
+ return d.getTime();
225
+ }
226
+
227
+ // src/audit/auditDictionary.ts
228
+ var AUDIT_DICT_FILE = "_dict.jsonl";
229
+ var DICT_BASE_PREFIX = "dict:";
230
+ var DICT_CANDIDATES = 3;
231
+ var MIN_SAVING_RATIO = 0.2;
232
+ function parseEntries(raw) {
233
+ const entries = [];
234
+ for (const line of raw.split("\n")) {
235
+ const trimmed = line.trim();
236
+ if (!trimmed) continue;
237
+ try {
238
+ const parsed = JSON.parse(trimmed);
239
+ if (isAuditBodyEntry(parsed)) entries.push(parsed);
240
+ } catch {
241
+ }
27
242
  }
28
- if (hay.includes("openai") || hay.includes("/v1") || hay.includes("chat/completions")) {
29
- return { format: "openai", ambiguous: false };
243
+ return entries;
244
+ }
245
+ function plainShards(bodiesPath) {
246
+ try {
247
+ return readdirSync(bodiesPath).filter(
248
+ (file) => file.endsWith(".jsonl") && isSafeSessionKey(file.slice(0, -".jsonl".length))
249
+ );
250
+ } catch {
251
+ return [];
30
252
  }
31
- return { format: "openai", ambiguous: true };
32
253
  }
33
- function mapProviders(providers, notes) {
34
- const rows = [];
35
- for (const [i, p] of providers.entries()) {
36
- const id = p.name?.trim();
37
- if (!id) {
38
- notes.push(`Providers[${i}] has no name \u2014 skipped.`);
254
+ function chooseDictionary(anchors) {
255
+ if (anchors.length < 2) return null;
256
+ const total = anchors.reduce((sum, body) => sum + body.length, 0);
257
+ const candidates = [...anchors].sort((a, b) => b.length - a.length).slice(0, DICT_CANDIDATES);
258
+ let best = null;
259
+ for (const candidate of candidates) {
260
+ let cost = candidate.length;
261
+ for (const body of anchors) {
262
+ cost += body === candidate ? 0 : computeBodyDelta(candidate, body).ins.length;
263
+ }
264
+ if (best === null || cost < best.cost) best = { body: candidate, cost };
265
+ }
266
+ if (best === null) return null;
267
+ return total - best.cost >= total * MIN_SAVING_RATIO ? best.body : null;
268
+ }
269
+ var EMPTY = { shards: 0, anchors: 0, savedBytes: 0 };
270
+ function compactAuditDay(dayPath) {
271
+ const bodiesPath = join(dayPath, AUDIT_BODIES_DIR);
272
+ if (!existsSync(bodiesPath)) return EMPTY;
273
+ const dictPath = join(bodiesPath, AUDIT_DICT_FILE);
274
+ if (existsSync(dictPath) || existsSync(`${dictPath}.gz`)) return EMPTY;
275
+ const shardFiles = plainShards(bodiesPath);
276
+ if (shardFiles.length < 2) return EMPTY;
277
+ const loaded = /* @__PURE__ */ new Map();
278
+ const anchors = [];
279
+ for (const file of shardFiles) {
280
+ let entries;
281
+ try {
282
+ entries = parseEntries(readFileSync(join(bodiesPath, file), "utf8"));
283
+ } catch {
39
284
  continue;
40
285
  }
41
- const { format, ambiguous } = inferApiFormat(p);
42
- if (ambiguous) {
43
- notes.push(
44
- `Provider '${id}': could not infer apiFormat from base URL \u2014 defaulted to 'openai'. Edit the config if this provider speaks a different wire format.`
45
- );
286
+ loaded.set(file, entries);
287
+ for (const entry of entries) {
288
+ if (entry.req && entry.req.base === null) anchors.push(entry.req.ins);
46
289
  }
47
- rows.push({
48
- id,
49
- apiFormat: format,
50
- baseUrl: p.api_base_url ?? "",
51
- apiKey: p.api_key ?? "",
52
- models: Array.isArray(p.models) ? p.models : void 0
290
+ }
291
+ if (anchors.length < 2) return EMPTY;
292
+ const dictionary = chooseDictionary(anchors);
293
+ if (dictionary === null) return EMPTY;
294
+ const dictEntry = {
295
+ id: `${DICT_BASE_PREFIX}0`,
296
+ ts: 0,
297
+ req: { base: null, anchor: "dict", pre: 0, suf: 0, ins: dictionary }
298
+ };
299
+ writeFileSync(dictPath, JSON.stringify(dictEntry) + "\n", "utf8");
300
+ const result = { shards: 0, anchors: 0, savedBytes: 0 };
301
+ for (const [file, entries] of loaded) {
302
+ let changed = false;
303
+ let saved = 0;
304
+ const rewritten = entries.map((entry) => {
305
+ if (!entry.req || entry.req.base !== null || entry.req.ins === dictionary) return entry;
306
+ const delta = computeBodyDelta(dictionary, entry.req.ins);
307
+ if (delta.ins.length >= entry.req.ins.length) return entry;
308
+ changed = true;
309
+ saved += entry.req.ins.length - delta.ins.length;
310
+ return {
311
+ ...entry,
312
+ req: { base: dictEntry.id, pre: delta.pre, suf: delta.suf, ins: delta.ins }
313
+ };
53
314
  });
315
+ if (!changed) continue;
316
+ const target = join(bodiesPath, file);
317
+ const temp = `${target}.compacting`;
318
+ try {
319
+ writeFileSync(temp, rewritten.map((e) => JSON.stringify(e)).join("\n") + "\n", "utf8");
320
+ renameSync(temp, target);
321
+ } catch {
322
+ try {
323
+ if (existsSync(temp)) unlinkSync(temp);
324
+ } catch {
325
+ }
326
+ continue;
327
+ }
328
+ result.shards += 1;
329
+ result.anchors += rewritten.filter((e) => e.req?.base === dictEntry.id).length;
330
+ result.savedBytes += saved;
54
331
  }
55
- return rows;
332
+ if (result.shards === 0) {
333
+ try {
334
+ unlinkSync(dictPath);
335
+ } catch {
336
+ }
337
+ }
338
+ return result;
56
339
  }
57
- function noteRouterRoles(router, notes) {
58
- if (router.think) {
59
- notes.push(`Router.think \u2192 folded into 'default' (omnicross has no think slot).`);
340
+ function compactAllClosedAuditDays(auditDir, now = Date.now) {
341
+ const run = { days: 0, shards: 0, savedBytes: 0 };
342
+ if (!existsSync(auditDir)) return run;
343
+ const today = auditDayDirName(now());
344
+ let names;
345
+ try {
346
+ names = readdirSync(auditDir).filter(isAuditDayDir).sort();
347
+ } catch {
348
+ return run;
60
349
  }
61
- if (router.longContext) {
62
- notes.push(
63
- `Router.longContext \u2192 folded into 'default' (no longContext slot; longContextThreshold dropped).`
64
- );
350
+ for (const name of names) {
351
+ if (name === today) continue;
352
+ try {
353
+ const result = compactAuditDay(join(auditDir, name));
354
+ if (result.shards === 0) continue;
355
+ run.days += 1;
356
+ run.shards += result.shards;
357
+ run.savedBytes += result.savedBytes;
358
+ } catch {
359
+ }
65
360
  }
66
- if (router.image) {
67
- notes.push(`Router.image \u2192 mapped to 'vision' (CCR forceUseImageAgent dropped).`);
361
+ return run;
362
+ }
363
+
364
+ // src/audit/auditJsonl.ts
365
+ import { closeSync, openSync, readSync, statSync } from "fs";
366
+ var WINDOW_BYTES = 1 << 20;
367
+ var MAX_LINE_BYTES = 32 * 1024 * 1024;
368
+ var NEWLINE = 10;
369
+ function forEachLineFromTail(path2, onLine) {
370
+ let fd;
371
+ let end;
372
+ try {
373
+ end = statSync(path2).size;
374
+ if (end === 0) return;
375
+ fd = openSync(path2, "r");
376
+ } catch {
377
+ return;
68
378
  }
69
- if (router.webSearch) {
70
- notes.push(
71
- `Router.webSearch \u2192 DROPPED. omnicross injects web search via an interception port rather than routing to a natively-online model; the CCR webSearch model ('${router.webSearch}') was not carried over.`
72
- );
379
+ try {
380
+ let carry = Buffer.alloc(0);
381
+ while (end > 0) {
382
+ const start = Math.max(0, end - WINDOW_BYTES);
383
+ const window = Buffer.allocUnsafe(end - start);
384
+ let read;
385
+ try {
386
+ read = readSync(fd, window, 0, end - start, start);
387
+ } catch {
388
+ return;
389
+ }
390
+ const chunk = carry.length > 0 ? Buffer.concat([window.subarray(0, read), carry]) : window.subarray(0, read);
391
+ let lineEnd = chunk.length;
392
+ let nl = lineEnd > 0 ? chunk.lastIndexOf(NEWLINE, lineEnd - 1) : -1;
393
+ while (nl >= 0) {
394
+ if (nl + 1 < lineEnd) {
395
+ const line = chunk.subarray(nl + 1, lineEnd).toString("utf8").trim();
396
+ if (line && onLine(line)) return;
397
+ }
398
+ lineEnd = nl;
399
+ nl = lineEnd > 0 ? chunk.lastIndexOf(NEWLINE, lineEnd - 1) : -1;
400
+ }
401
+ if (start === 0) {
402
+ if (lineEnd > 0) {
403
+ const line = chunk.subarray(0, lineEnd).toString("utf8").trim();
404
+ if (line) onLine(line);
405
+ }
406
+ return;
407
+ }
408
+ if (lineEnd > MAX_LINE_BYTES) return;
409
+ carry = Buffer.from(chunk.subarray(0, lineEnd));
410
+ end = start;
411
+ }
412
+ } finally {
413
+ try {
414
+ closeSync(fd);
415
+ } catch {
416
+ }
73
417
  }
74
418
  }
75
- function mapCcrToOmnicross(ccr) {
76
- const notes = [];
77
- const providers = mapProviders(ccr.Providers ?? [], notes);
78
- noteRouterRoles(ccr.Router ?? {}, notes);
79
- return { config: { providers }, notes };
419
+
420
+ // src/audit/auditBodyReader.ts
421
+ function candidateDays(auditDir, ts) {
422
+ if (typeof ts === "number" && Number.isFinite(ts)) {
423
+ const named = auditDayDirName(ts);
424
+ if (existsSync2(join2(auditDir, named))) return [named];
425
+ }
426
+ try {
427
+ return readdirSync2(auditDir).filter(isAuditDayDir).sort().reverse();
428
+ } catch {
429
+ return [];
430
+ }
431
+ }
432
+ function readShard(auditDir, day, sessionKey) {
433
+ const base = join2(auditDir, day, AUDIT_BODIES_DIR, auditBodyFileName(sessionKey));
434
+ try {
435
+ if (existsSync2(base)) return readFileSync2(base, "utf8");
436
+ const gz = `${base}.gz`;
437
+ if (existsSync2(gz)) return gunzipSync(readFileSync2(gz)).toString("utf8");
438
+ } catch {
439
+ return null;
440
+ }
441
+ return null;
442
+ }
443
+ function parseShard(raw) {
444
+ const entries = /* @__PURE__ */ new Map();
445
+ for (const line of raw.split("\n")) {
446
+ const trimmed = line.trim();
447
+ if (!trimmed) continue;
448
+ let parsed;
449
+ try {
450
+ parsed = JSON.parse(trimmed);
451
+ } catch {
452
+ continue;
453
+ }
454
+ if (isAuditBodyEntry(parsed)) entries.set(parsed.id, parsed);
455
+ }
456
+ return entries;
457
+ }
458
+ function withDictionary(auditDir, day, entries) {
459
+ let needed = false;
460
+ for (const entry of entries.values()) {
461
+ if (entry.req?.base?.startsWith(DICT_BASE_PREFIX)) {
462
+ needed = true;
463
+ break;
464
+ }
465
+ }
466
+ if (!needed) return entries;
467
+ const base = join2(auditDir, day, AUDIT_BODIES_DIR, AUDIT_DICT_FILE);
468
+ let raw = null;
469
+ try {
470
+ if (existsSync2(base)) raw = readFileSync2(base, "utf8");
471
+ else if (existsSync2(`${base}.gz`)) raw = gunzipSync(readFileSync2(`${base}.gz`)).toString("utf8");
472
+ } catch {
473
+ return entries;
474
+ }
475
+ if (raw === null) return entries;
476
+ for (const [id, entry] of parseShard(raw)) entries.set(id, entry);
477
+ return entries;
478
+ }
479
+ function reconstructRequest(entries, entry) {
480
+ if (!entry.req) return void 0;
481
+ const chain = [];
482
+ const visited = /* @__PURE__ */ new Set();
483
+ let cursor = entry;
484
+ while (cursor?.req) {
485
+ if (visited.has(cursor.id)) return void 0;
486
+ visited.add(cursor.id);
487
+ chain.push(cursor);
488
+ if (cursor.req.base === null) break;
489
+ cursor = entries.get(cursor.req.base);
490
+ }
491
+ const anchor = chain[chain.length - 1];
492
+ if (!anchor?.req || anchor.req.base !== null) return void 0;
493
+ let text = anchor.req.ins;
494
+ for (let i = chain.length - 2; i >= 0; i -= 1) {
495
+ const delta = chain[i]?.req;
496
+ if (!delta) return void 0;
497
+ if (delta.pre > text.length || delta.suf > text.length - delta.pre) return void 0;
498
+ text = applyBodyDelta(text, delta);
499
+ }
500
+ return text;
501
+ }
502
+ function assignStreams(entries) {
503
+ const rootOf = /* @__PURE__ */ new Map();
504
+ for (const entry of entries.values()) {
505
+ const seen = /* @__PURE__ */ new Set();
506
+ let cursor = entry;
507
+ while (cursor?.req?.cont === true && cursor.req.base !== null && !seen.has(cursor.id)) {
508
+ seen.add(cursor.id);
509
+ const next = entries.get(cursor.req.base);
510
+ if (!next) break;
511
+ cursor = next;
512
+ }
513
+ rootOf.set(entry.id, cursor?.id ?? entry.id);
514
+ }
515
+ const firstTs = /* @__PURE__ */ new Map();
516
+ for (const entry of entries.values()) {
517
+ const root = rootOf.get(entry.id);
518
+ const known = firstTs.get(root);
519
+ if (known === void 0 || entry.ts < known) firstTs.set(root, entry.ts);
520
+ }
521
+ const order = [...firstTs.entries()].sort((a, b) => a[1] - b[1]).map(([root]) => root);
522
+ const index = new Map(order.map((root, i) => [root, i]));
523
+ const streams = /* @__PURE__ */ new Map();
524
+ for (const entry of entries.values()) {
525
+ streams.set(entry.id, index.get(rootOf.get(entry.id)) ?? 0);
526
+ }
527
+ return streams;
528
+ }
529
+ function readAuditBody(auditDir, query2) {
530
+ if (!isSafeSessionKey(query2.sessionKey) || !query2.id) return {};
531
+ if (!existsSync2(auditDir)) return {};
532
+ for (const day of candidateDays(auditDir, query2.ts)) {
533
+ const raw = readShard(auditDir, day, query2.sessionKey);
534
+ if (raw === null) continue;
535
+ const entries = withDictionary(auditDir, day, parseShard(raw));
536
+ const entry = entries.get(query2.id);
537
+ if (!entry) continue;
538
+ const result = {};
539
+ const requestBody = reconstructRequest(entries, entry);
540
+ if (requestBody !== void 0) result.requestBody = requestBody;
541
+ if (entry.res !== void 0) result.responseBody = entry.res;
542
+ return result;
543
+ }
544
+ return readLegacyInlineBody(auditDir, query2.id);
545
+ }
546
+ function readLegacyInlineBody(auditDir, id) {
547
+ let names;
548
+ try {
549
+ names = readdirSync2(auditDir).filter((name) => AUDIT_FILE_RE.test(name)).sort().reverse();
550
+ } catch {
551
+ return {};
552
+ }
553
+ const needle = JSON.stringify(id);
554
+ let found = {};
555
+ for (const name of names) {
556
+ forEachLineFromTail(join2(auditDir, name), (line) => {
557
+ if (!line.includes(needle)) return false;
558
+ let parsed;
559
+ try {
560
+ parsed = JSON.parse(line);
561
+ } catch {
562
+ return false;
563
+ }
564
+ const record = parsed;
565
+ if (record.id !== id) return false;
566
+ const result = {};
567
+ if (typeof record.requestBody === "string") result.requestBody = record.requestBody;
568
+ if (typeof record.responseBody === "string") result.responseBody = record.responseBody;
569
+ found = result;
570
+ return true;
571
+ });
572
+ if (found.requestBody !== void 0 || found.responseBody !== void 0) break;
573
+ }
574
+ return found;
575
+ }
576
+ function readAuditSessionTurns(auditDir, sessionKey, ts) {
577
+ if (!isSafeSessionKey(sessionKey) || !existsSync2(auditDir)) return [];
578
+ for (const day of candidateDays(auditDir, ts)) {
579
+ const raw = readShard(auditDir, day, sessionKey);
580
+ if (raw === null) continue;
581
+ const shardEntries = parseShard(raw);
582
+ const streams = assignStreams(shardEntries);
583
+ const entries = withDictionary(auditDir, day, shardEntries);
584
+ const turns = [];
585
+ for (const entry of entries.values()) {
586
+ if (entry.id.startsWith(DICT_BASE_PREFIX)) continue;
587
+ const turn = { id: entry.id, ts: entry.ts, stream: streams.get(entry.id) ?? 0 };
588
+ if (entry.req?.anchor === "diverged") turn.diverged = true;
589
+ const requestBody = reconstructRequest(entries, entry);
590
+ if (requestBody !== void 0) turn.requestBody = requestBody;
591
+ if (entry.res !== void 0) turn.responseBody = entry.res;
592
+ turns.push(turn);
593
+ }
594
+ turns.sort((a, b) => a.stream === b.stream ? a.ts - b.ts : a.stream - b.stream);
595
+ return turns;
596
+ }
597
+ return [];
598
+ }
599
+ function listAuditSessions(auditDir, ts) {
600
+ if (!existsSync2(auditDir)) return [];
601
+ const summaries = [];
602
+ for (const day of candidateDays(auditDir, ts)) {
603
+ const bodiesPath = join2(auditDir, day, AUDIT_BODIES_DIR);
604
+ let files;
605
+ try {
606
+ files = readdirSync2(bodiesPath);
607
+ } catch {
608
+ continue;
609
+ }
610
+ for (const file of files) {
611
+ const compressed = file.endsWith(".jsonl.gz");
612
+ const sessionKey = file.replace(/\.jsonl(\.gz)?$/, "");
613
+ if (!isSafeSessionKey(sessionKey) || !compressed && !file.endsWith(".jsonl")) continue;
614
+ let bytes = 0;
615
+ try {
616
+ bytes = statSync2(join2(bodiesPath, file)).size;
617
+ } catch {
618
+ continue;
619
+ }
620
+ const raw = readShard(auditDir, day, sessionKey);
621
+ const turns = raw === null ? 0 : parseShard(raw).size;
622
+ summaries.push({ sessionKey, day, turns, bytes, compressed });
623
+ }
624
+ }
625
+ summaries.sort((a, b) => a.day === b.day ? b.bytes - a.bytes : a.day < b.day ? 1 : -1);
626
+ return summaries;
80
627
  }
81
628
 
82
- // src/config.ts
83
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
629
+ // src/commands/paths.ts
630
+ import { dirname as dirname2, join as join4 } from "path";
84
631
 
85
632
  // src/secrets/envelope.ts
86
633
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
@@ -139,13 +686,13 @@ function decryptValue(envelope, key) {
139
686
 
140
687
  // src/secrets/masterKey.ts
141
688
  import { randomBytes as randomBytes2 } from "crypto";
142
- import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
689
+ import { chmodSync, existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
143
690
  import { homedir } from "os";
144
- import { dirname, join } from "path";
691
+ import { dirname, join as join3 } from "path";
145
692
  var MASTER_KEY_ENV = "OMNICROSS_MASTER_KEY";
146
693
  var KEY_BYTES2 = 32;
147
694
  function defaultMasterKeyPath() {
148
- return join(homedir(), ".omnicross", "master.key");
695
+ return join3(homedir(), ".omnicross", "master.key");
149
696
  }
150
697
  function decodeEnvKey(raw) {
151
698
  const trimmed = raw.trim();
@@ -161,7 +708,7 @@ function decodeEnvKey(raw) {
161
708
  return buf;
162
709
  }
163
710
  function readKeyFile(path2) {
164
- const raw = readFileSync(path2);
711
+ const raw = readFileSync3(path2);
165
712
  if (raw.length === KEY_BYTES2) return raw;
166
713
  const text = raw.toString("utf8").trim();
167
714
  if (/^[0-9a-fA-F]{64}$/.test(text)) return Buffer.from(text, "hex");
@@ -174,7 +721,7 @@ function readKeyFile(path2) {
174
721
  function generateKeyFile(path2) {
175
722
  const key = randomBytes2(KEY_BYTES2);
176
723
  mkdirSync(dirname(path2), { recursive: true });
177
- writeFileSync(path2, key, { mode: 384 });
724
+ writeFileSync2(path2, key, { mode: 384 });
178
725
  try {
179
726
  chmodSync(path2, 384);
180
727
  } catch {
@@ -187,7 +734,7 @@ function resolveMasterKey(options = {}) {
187
734
  return decodeEnvKey(envRaw);
188
735
  }
189
736
  const keyFilePath = options.keyFilePath ?? defaultMasterKeyPath();
190
- if (existsSync(keyFilePath)) {
737
+ if (existsSync3(keyFilePath)) {
191
738
  return readKeyFile(keyFilePath);
192
739
  }
193
740
  return generateKeyFile(keyFilePath);
@@ -403,39 +950,266 @@ function transformTokens(tokens, fn) {
403
950
  if (block && typeof block === "object" && !Array.isArray(block)) {
404
951
  bag[provider] = transformTokenBlock(block, fields, fn);
405
952
  }
406
- const accountsKey = `${provider}Accounts`;
407
- const accounts = bag[accountsKey];
408
- if (Array.isArray(accounts)) {
409
- bag[accountsKey] = accounts.map((entry) => {
410
- if (entry && typeof entry === "object" && "tokens" in entry && entry.tokens && typeof entry.tokens === "object") {
411
- const nextEntry = {
412
- ...entry,
413
- tokens: transformTokenBlock(
414
- entry.tokens,
415
- fields,
416
- fn
417
- )
418
- };
419
- const proxy = entry.proxy;
420
- if (proxy && typeof proxy === "object") {
421
- nextEntry.proxy = transformProxyConfig(proxy, fn);
422
- }
423
- return nextEntry;
424
- }
425
- return entry;
426
- });
953
+ const accountsKey = `${provider}Accounts`;
954
+ const accounts = bag[accountsKey];
955
+ if (Array.isArray(accounts)) {
956
+ bag[accountsKey] = accounts.map((entry) => {
957
+ if (entry && typeof entry === "object" && "tokens" in entry && entry.tokens && typeof entry.tokens === "object") {
958
+ const nextEntry = {
959
+ ...entry,
960
+ tokens: transformTokenBlock(
961
+ entry.tokens,
962
+ fields,
963
+ fn
964
+ )
965
+ };
966
+ const proxy = entry.proxy;
967
+ if (proxy && typeof proxy === "object") {
968
+ nextEntry.proxy = transformProxyConfig(proxy, fn);
969
+ }
970
+ return nextEntry;
971
+ }
972
+ return entry;
973
+ });
974
+ }
975
+ }
976
+ return next;
977
+ }
978
+ function encryptTokens(tokens, box) {
979
+ return transformTokens(tokens, (v) => box.encryptMaybe(v));
980
+ }
981
+ function decryptTokens(tokens, box) {
982
+ return transformTokens(tokens, (v) => box.decryptMaybe(v));
983
+ }
984
+
985
+ // src/commands/paths.ts
986
+ function defaultKeysPath(configPath) {
987
+ return join4(dirname2(configPath), "keys.json");
988
+ }
989
+ function defaultVouchersPath(configPath) {
990
+ return join4(dirname2(configPath), "vouchers.json");
991
+ }
992
+ function defaultTokensPath(configPath) {
993
+ return join4(dirname2(configPath), "tokens.json");
994
+ }
995
+ function defaultIntegrationsPath(configPath) {
996
+ return join4(dirname2(configPath), "integrations.json");
997
+ }
998
+ function defaultPricingPath(configPath) {
999
+ return join4(dirname2(configPath), "pricing.json");
1000
+ }
1001
+ function defaultPricingRefreshStatePath(configPath) {
1002
+ return join4(dirname2(configPath), "pricing-refresh.json");
1003
+ }
1004
+ function defaultAccountAllowancePath(configPath) {
1005
+ return join4(dirname2(configPath), "allowance-cache.json");
1006
+ }
1007
+ function defaultUsageEventsPath(configPath) {
1008
+ return join4(dirname2(configPath), "usage-events.jsonl");
1009
+ }
1010
+ function defaultAuditDir(configPath) {
1011
+ return join4(dirname2(configPath), "audit");
1012
+ }
1013
+ function defaultBillingDir(configPath) {
1014
+ return join4(dirname2(configPath), "billing");
1015
+ }
1016
+ function resolveSecretBox(masterKeyFilePath) {
1017
+ return new SecretBox(() => resolveMasterKey({ keyFilePath: masterKeyFilePath }));
1018
+ }
1019
+
1020
+ // src/commands/audit.ts
1021
+ function parseDate(value) {
1022
+ if (!value) return void 0;
1023
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value.trim());
1024
+ if (!m) throw new Error(`audit: --date must be YYYY-MM-DD (got ${value})`);
1025
+ const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
1026
+ return d.getTime();
1027
+ }
1028
+ function formatBytes(bytes) {
1029
+ if (bytes < 1024) return `${bytes} B`;
1030
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1031
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1032
+ }
1033
+ async function runAudit(argv) {
1034
+ const { values, positionals } = parseArgs({
1035
+ args: argv,
1036
+ options: {
1037
+ config: { type: "string", short: "c" },
1038
+ session: { type: "string", short: "s" },
1039
+ date: { type: "string", short: "d" },
1040
+ id: { type: "string" }
1041
+ },
1042
+ allowPositionals: true
1043
+ });
1044
+ const configPath = values.config;
1045
+ if (!configPath) throw new Error("audit: --config <path> is required");
1046
+ const auditDir = defaultAuditDir(configPath);
1047
+ const ts = parseDate(values.date);
1048
+ const action = positionals[0];
1049
+ if (action === "sessions") {
1050
+ const sessions2 = listAuditSessions(auditDir, ts);
1051
+ if (sessions2.length === 0) {
1052
+ console.info("No audit body shards found. Is `captureBodies` enabled?");
1053
+ return;
1054
+ }
1055
+ console.info(["DAY", "SESSION", "TURNS", "SIZE", "ARCHIVED"].join(" "));
1056
+ for (const s of sessions2) {
1057
+ console.info(
1058
+ [s.day, s.sessionKey, String(s.turns), formatBytes(s.bytes), s.compressed ? "gz" : "-"].join(" ")
1059
+ );
1060
+ }
1061
+ return;
1062
+ }
1063
+ if (action === "show") {
1064
+ const sessionKey = values.session;
1065
+ if (!sessionKey) throw new Error("audit show: --session <key> is required");
1066
+ if (values.id) {
1067
+ const body = readAuditBody(auditDir, { id: values.id, sessionKey, ...ts !== void 0 ? { ts } : {} });
1068
+ if (body.requestBody === void 0 && body.responseBody === void 0) {
1069
+ throw new Error(`audit show: no body found for record ${values.id}`);
1070
+ }
1071
+ if (body.requestBody !== void 0) console.info(`--- request ${values.id} ---
1072
+ ${body.requestBody}`);
1073
+ if (body.responseBody !== void 0) console.info(`--- response ${values.id} ---
1074
+ ${body.responseBody}`);
1075
+ return;
1076
+ }
1077
+ const turns = readAuditSessionTurns(auditDir, sessionKey, ts);
1078
+ if (turns.length === 0) throw new Error(`audit show: no shard found for session ${sessionKey}`);
1079
+ let stream = -1;
1080
+ for (const turn of turns) {
1081
+ const when = new Date(turn.ts).toISOString();
1082
+ if (turn.stream !== stream) {
1083
+ stream = turn.stream;
1084
+ console.info(`
1085
+ ########## stream ${stream} ##########`);
1086
+ }
1087
+ if (turn.diverged) {
1088
+ console.info("=== prefix diverged here (system prompt changed, or a restart reused this session) ===");
1089
+ }
1090
+ if (turn.requestBody !== void 0) {
1091
+ console.info(`--- request ${turn.id} @ ${when} ---
1092
+ ${turn.requestBody}`);
1093
+ }
1094
+ if (turn.responseBody !== void 0) {
1095
+ console.info(`--- response ${turn.id} @ ${when} ---
1096
+ ${turn.responseBody}`);
1097
+ }
1098
+ }
1099
+ return;
1100
+ }
1101
+ if (action === "compact") {
1102
+ const todayDir = auditDayDirName(Date.now());
1103
+ let names;
1104
+ try {
1105
+ names = readdirSync3(auditDir).filter(isAuditDayDir).sort();
1106
+ } catch {
1107
+ names = [];
1108
+ }
1109
+ const targets = ts !== void 0 ? names.filter((name) => name === auditDayDirName(ts)) : names.filter((name) => name !== todayDir);
1110
+ if (targets.length === 0) {
1111
+ console.info("Nothing to compact (today is skipped; a day is compacted once).");
1112
+ return;
1113
+ }
1114
+ let shards = 0;
1115
+ let saved = 0;
1116
+ for (const name of targets) {
1117
+ if (name === todayDir) {
1118
+ console.info(`Skipping ${name}: the current day is still being written.`);
1119
+ continue;
1120
+ }
1121
+ const result = compactAuditDay(join5(auditDir, name));
1122
+ shards += result.shards;
1123
+ saved += result.savedBytes;
1124
+ console.info(`${name}: ${result.shards} shard(s), ${result.anchors} anchor(s), ${formatBytes(result.savedBytes)} saved`);
1125
+ }
1126
+ console.info(`Done: ${shards} shard(s) rewritten, ${formatBytes(saved)} saved.`);
1127
+ return;
1128
+ }
1129
+ throw new Error("audit: expected `sessions`, `show`, or `compact` (see `omnicross help`)");
1130
+ }
1131
+
1132
+ // src/commands/import-ccr.ts
1133
+ import { readFileSync as readFileSync5 } from "fs";
1134
+ import { parseArgs as parseArgs2 } from "util";
1135
+
1136
+ // src/ccr-import.ts
1137
+ function parseCcrConfig(raw) {
1138
+ if (!raw || typeof raw !== "object") {
1139
+ throw new Error("CCR config: top-level value must be an object");
1140
+ }
1141
+ const obj = raw;
1142
+ const Providers = Array.isArray(obj["Providers"]) ? obj["Providers"] : [];
1143
+ const Router = obj["Router"] && typeof obj["Router"] === "object" ? obj["Router"] : {};
1144
+ return { Providers, Router };
1145
+ }
1146
+ function inferApiFormat(provider) {
1147
+ const hay = `${provider.api_base_url ?? ""} ${provider.name ?? ""}`.toLowerCase();
1148
+ if (hay.includes("anthropic") || hay.includes("claude")) {
1149
+ return { format: "anthropic", ambiguous: false };
1150
+ }
1151
+ if (hay.includes("generativelanguage") || hay.includes("gemini") || hay.includes("google")) {
1152
+ return { format: "gemini", ambiguous: false };
1153
+ }
1154
+ if (hay.includes("/responses")) {
1155
+ return { format: "openai-response", ambiguous: false };
1156
+ }
1157
+ if (hay.includes("openai") || hay.includes("/v1") || hay.includes("chat/completions")) {
1158
+ return { format: "openai", ambiguous: false };
1159
+ }
1160
+ return { format: "openai", ambiguous: true };
1161
+ }
1162
+ function mapProviders(providers, notes) {
1163
+ const rows = [];
1164
+ for (const [i, p] of providers.entries()) {
1165
+ const id = p.name?.trim();
1166
+ if (!id) {
1167
+ notes.push(`Providers[${i}] has no name \u2014 skipped.`);
1168
+ continue;
1169
+ }
1170
+ const { format, ambiguous } = inferApiFormat(p);
1171
+ if (ambiguous) {
1172
+ notes.push(
1173
+ `Provider '${id}': could not infer apiFormat from base URL \u2014 defaulted to 'openai'. Edit the config if this provider speaks a different wire format.`
1174
+ );
427
1175
  }
1176
+ rows.push({
1177
+ id,
1178
+ apiFormat: format,
1179
+ baseUrl: p.api_base_url ?? "",
1180
+ apiKey: p.api_key ?? "",
1181
+ models: Array.isArray(p.models) ? p.models : void 0
1182
+ });
428
1183
  }
429
- return next;
1184
+ return rows;
430
1185
  }
431
- function encryptTokens(tokens, box) {
432
- return transformTokens(tokens, (v) => box.encryptMaybe(v));
1186
+ function noteRouterRoles(router, notes) {
1187
+ if (router.think) {
1188
+ notes.push(`Router.think \u2192 folded into 'default' (omnicross has no think slot).`);
1189
+ }
1190
+ if (router.longContext) {
1191
+ notes.push(
1192
+ `Router.longContext \u2192 folded into 'default' (no longContext slot; longContextThreshold dropped).`
1193
+ );
1194
+ }
1195
+ if (router.image) {
1196
+ notes.push(`Router.image \u2192 mapped to 'vision' (CCR forceUseImageAgent dropped).`);
1197
+ }
1198
+ if (router.webSearch) {
1199
+ notes.push(
1200
+ `Router.webSearch \u2192 DROPPED. omnicross injects web search via an interception port rather than routing to a natively-online model; the CCR webSearch model ('${router.webSearch}') was not carried over.`
1201
+ );
1202
+ }
433
1203
  }
434
- function decryptTokens(tokens, box) {
435
- return transformTokens(tokens, (v) => box.decryptMaybe(v));
1204
+ function mapCcrToOmnicross(ccr) {
1205
+ const notes = [];
1206
+ const providers = mapProviders(ccr.Providers ?? [], notes);
1207
+ noteRouterRoles(ccr.Router ?? {}, notes);
1208
+ return { config: { providers }, notes };
436
1209
  }
437
1210
 
438
1211
  // src/config.ts
1212
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
439
1213
  var DEFAULT_ADMIN_PORT = 8766;
440
1214
  function validateAdmin(raw) {
441
1215
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
@@ -728,7 +1502,7 @@ function setSecretBox(box) {
728
1502
  function loadConfig(path2) {
729
1503
  let raw;
730
1504
  try {
731
- raw = readFileSync2(path2, "utf8");
1505
+ raw = readFileSync4(path2, "utf8");
732
1506
  } catch {
733
1507
  throw new Error(`config: cannot read file at '${path2}'`);
734
1508
  }
@@ -743,48 +1517,12 @@ function loadConfig(path2) {
743
1517
  }
744
1518
  function saveConfig(path2, cfg) {
745
1519
  const toWrite = secretBox ? encryptConfigSecrets(cfg, secretBox) : cfg;
746
- writeFileSync2(path2, JSON.stringify(toWrite, null, 2) + "\n", "utf8");
747
- }
748
-
749
- // src/commands/paths.ts
750
- import { dirname as dirname2, join as join2 } from "path";
751
- function defaultKeysPath(configPath) {
752
- return join2(dirname2(configPath), "keys.json");
753
- }
754
- function defaultVouchersPath(configPath) {
755
- return join2(dirname2(configPath), "vouchers.json");
756
- }
757
- function defaultTokensPath(configPath) {
758
- return join2(dirname2(configPath), "tokens.json");
759
- }
760
- function defaultIntegrationsPath(configPath) {
761
- return join2(dirname2(configPath), "integrations.json");
762
- }
763
- function defaultPricingPath(configPath) {
764
- return join2(dirname2(configPath), "pricing.json");
765
- }
766
- function defaultPricingRefreshStatePath(configPath) {
767
- return join2(dirname2(configPath), "pricing-refresh.json");
768
- }
769
- function defaultAccountAllowancePath(configPath) {
770
- return join2(dirname2(configPath), "allowance-cache.json");
771
- }
772
- function defaultUsageEventsPath(configPath) {
773
- return join2(dirname2(configPath), "usage-events.jsonl");
774
- }
775
- function defaultAuditDir(configPath) {
776
- return join2(dirname2(configPath), "audit");
777
- }
778
- function defaultBillingDir(configPath) {
779
- return join2(dirname2(configPath), "billing");
780
- }
781
- function resolveSecretBox(masterKeyFilePath) {
782
- return new SecretBox(() => resolveMasterKey({ keyFilePath: masterKeyFilePath }));
1520
+ writeFileSync3(path2, JSON.stringify(toWrite, null, 2) + "\n", "utf8");
783
1521
  }
784
1522
 
785
1523
  // src/commands/import-ccr.ts
786
1524
  async function runImportCcr(argv) {
787
- const { values, positionals } = parseArgs({
1525
+ const { values, positionals } = parseArgs2({
788
1526
  args: argv,
789
1527
  options: {
790
1528
  out: { type: "string", short: "o" },
@@ -799,7 +1537,7 @@ async function runImportCcr(argv) {
799
1537
  const outPath = values.out ?? "omnicross.config.json";
800
1538
  let raw;
801
1539
  try {
802
- raw = JSON.parse(readFileSync3(ccrPath, "utf8"));
1540
+ raw = JSON.parse(readFileSync5(ccrPath, "utf8"));
803
1541
  } catch {
804
1542
  throw new Error(`import-ccr: cannot read or parse '${ccrPath}'`);
805
1543
  }
@@ -821,24 +1559,24 @@ async function runImportCcr(argv) {
821
1559
 
822
1560
  // src/commands/integrations.ts
823
1561
  import { resolve as resolve2 } from "path";
824
- import { parseArgs as parseArgs2 } from "util";
1562
+ import { parseArgs as parseArgs3 } from "util";
825
1563
 
826
1564
  // src/integrations/IntegrationManager.ts
827
1565
  import { createHash } from "crypto";
828
- import { existsSync as existsSync3, readFileSync as readFileSync5, unlinkSync as unlinkSync2 } from "fs";
1566
+ import { existsSync as existsSync5, readFileSync as readFileSync7, unlinkSync as unlinkSync3 } from "fs";
829
1567
  import { homedir as homedir2 } from "os";
830
- import { dirname as dirname4, join as join3, resolve } from "path";
1568
+ import { dirname as dirname4, join as join6, resolve } from "path";
831
1569
  import { createIntegrationKey } from "@omnicross/core";
832
1570
 
833
1571
  // src/integrations/IntegrationStateStore.ts
834
1572
  import {
835
1573
  chmodSync as chmodSync2,
836
- existsSync as existsSync2,
1574
+ existsSync as existsSync4,
837
1575
  mkdirSync as mkdirSync2,
838
- readFileSync as readFileSync4,
839
- renameSync,
840
- unlinkSync,
841
- writeFileSync as writeFileSync3
1576
+ readFileSync as readFileSync6,
1577
+ renameSync as renameSync2,
1578
+ unlinkSync as unlinkSync2,
1579
+ writeFileSync as writeFileSync4
842
1580
  } from "fs";
843
1581
  import { dirname as dirname3 } from "path";
844
1582
  var EMPTY_STATE = { version: 1, clients: {} };
@@ -850,10 +1588,10 @@ var IntegrationStateStore = class {
850
1588
  path;
851
1589
  box;
852
1590
  load() {
853
- if (!existsSync2(this.path)) return { ...EMPTY_STATE, clients: {} };
1591
+ if (!existsSync4(this.path)) return { ...EMPTY_STATE, clients: {} };
854
1592
  let raw;
855
1593
  try {
856
- raw = JSON.parse(readFileSync4(this.path, "utf8"));
1594
+ raw = JSON.parse(readFileSync6(this.path, "utf8"));
857
1595
  } catch {
858
1596
  throw new Error(`integration state '${this.path}' is not valid JSON`);
859
1597
  }
@@ -923,17 +1661,17 @@ function isManagedFileRecord(value) {
923
1661
  function atomicWrite(path2, content) {
924
1662
  mkdirSync2(dirname3(path2), { recursive: true });
925
1663
  const temp = `${path2}.tmp-${process.pid}-${Date.now()}`;
926
- writeFileSync3(temp, content, { encoding: "utf8", mode: 384 });
1664
+ writeFileSync4(temp, content, { encoding: "utf8", mode: 384 });
927
1665
  try {
928
- renameSync(temp, path2);
1666
+ renameSync2(temp, path2);
929
1667
  } catch (error) {
930
1668
  try {
931
- unlinkSync(temp);
1669
+ unlinkSync2(temp);
932
1670
  } catch {
933
1671
  }
934
1672
  throw error;
935
1673
  } finally {
936
- if (existsSync2(path2)) {
1674
+ if (existsSync4(path2)) {
937
1675
  try {
938
1676
  chmodSync2(path2, 384);
939
1677
  } catch {
@@ -1427,10 +2165,10 @@ var IntegrationManager = class {
1427
2165
  };
1428
2166
  }
1429
2167
  defaultConfigPath(client) {
1430
- return client === "codex" ? join3(this.homeDir, ".codex", "config.toml") : join3(this.homeDir, ".claude", "settings.json");
2168
+ return client === "codex" ? join6(this.homeDir, ".codex", "config.toml") : join6(this.homeDir, ".claude", "settings.json");
1431
2169
  }
1432
2170
  codexAuthPathForConfig(configPath) {
1433
- return join3(dirname4(configPath), "auth.json");
2171
+ return join6(dirname4(configPath), "auth.json");
1434
2172
  }
1435
2173
  renderInstalled(client, base, secret) {
1436
2174
  if (client === "claude") {
@@ -1443,7 +2181,7 @@ var IntegrationManager = class {
1443
2181
  }
1444
2182
  };
1445
2183
  function readOptional(path2) {
1446
- return existsSync3(path2) ? readFileSync5(path2, "utf8") : null;
2184
+ return existsSync5(path2) ? readFileSync7(path2, "utf8") : null;
1447
2185
  }
1448
2186
  function sha256(value) {
1449
2187
  return createHash("sha256").update(value, "utf8").digest("hex");
@@ -1507,7 +2245,7 @@ function writeOptional(path2, content) {
1507
2245
  atomicWrite(path2, content);
1508
2246
  return;
1509
2247
  }
1510
- if (existsSync3(path2)) unlinkSync2(path2);
2248
+ if (existsSync5(path2)) unlinkSync3(path2);
1511
2249
  }
1512
2250
  function assertLoopbackGatewayUrl(value) {
1513
2251
  let url;
@@ -1524,7 +2262,7 @@ function assertLoopbackGatewayUrl(value) {
1524
2262
  }
1525
2263
 
1526
2264
  // src/ports/JsonOutboundKeyDb.ts
1527
- import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
2265
+ import { existsSync as existsSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
1528
2266
  var JsonOutboundKeyDb = class {
1529
2267
  /**
1530
2268
  * @param secretBox OPTIONAL reversible-secret codec. When present, a created
@@ -1657,16 +2395,16 @@ var JsonOutboundKeyDb = class {
1657
2395
  }
1658
2396
  /** Read the key rows, tolerating a missing/corrupt file (→ empty list). */
1659
2397
  readRows() {
1660
- if (!existsSync4(this.keysPath)) return [];
2398
+ if (!existsSync6(this.keysPath)) return [];
1661
2399
  try {
1662
- const parsed = JSON.parse(readFileSync6(this.keysPath, "utf8"));
2400
+ const parsed = JSON.parse(readFileSync8(this.keysPath, "utf8"));
1663
2401
  return Array.isArray(parsed) ? parsed : [];
1664
2402
  } catch {
1665
2403
  return [];
1666
2404
  }
1667
2405
  }
1668
2406
  writeRows(rows) {
1669
- writeFileSync4(this.keysPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
2407
+ writeFileSync5(this.keysPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
1670
2408
  }
1671
2409
  };
1672
2410
  function applyPolicyField(row, field, value) {
@@ -1677,7 +2415,7 @@ function applyPolicyField(row, field, value) {
1677
2415
 
1678
2416
  // src/commands/integrations.ts
1679
2417
  async function runIntegrations(argv) {
1680
- const { values, positionals } = parseArgs2({
2418
+ const { values, positionals } = parseArgs3({
1681
2419
  args: argv,
1682
2420
  options: {
1683
2421
  config: { type: "string", short: "c" },
@@ -1727,10 +2465,10 @@ function isClient(value) {
1727
2465
  }
1728
2466
 
1729
2467
  // src/commands/keys.ts
1730
- import { parseArgs as parseArgs3 } from "util";
2468
+ import { parseArgs as parseArgs4 } from "util";
1731
2469
  import { createNamedKey } from "@omnicross/core/outbound-api";
1732
2470
  async function runKeys(argv) {
1733
- const { values, positionals } = parseArgs3({
2471
+ const { values, positionals } = parseArgs4({
1734
2472
  args: argv,
1735
2473
  options: { config: { type: "string", short: "c" } },
1736
2474
  allowPositionals: true
@@ -1784,9 +2522,9 @@ async function keysRevoke(db, id) {
1784
2522
  // src/commands/launch.ts
1785
2523
  import { spawn as spawn2 } from "child_process";
1786
2524
  import { randomUUID as randomUUID6 } from "crypto";
1787
- import { existsSync as existsSync20 } from "fs";
1788
- import { delimiter as delimiter2, join as join12 } from "path";
1789
- import { parseArgs as parseArgs4 } from "util";
2525
+ import { existsSync as existsSync22 } from "fs";
2526
+ import { delimiter as delimiter2, join as join15 } from "path";
2527
+ import { parseArgs as parseArgs5 } from "util";
1790
2528
  import {
1791
2529
  buildChatCliLaunchConfig as buildChatCliLaunchConfig2,
1792
2530
  buildGeminiCliLaunchConfig as buildGeminiCliLaunchConfig2
@@ -1794,7 +2532,7 @@ import {
1794
2532
  import { ROUTE_LEASE_REQUEST_SCHEMA as ROUTE_LEASE_REQUEST_SCHEMA2 } from "@omnicross/core/provider-proxy";
1795
2533
 
1796
2534
  // src/bootstrap.ts
1797
- import { accessSync, constants as fsConstants, existsSync as existsSync19 } from "fs";
2535
+ import { accessSync, constants as fsConstants, existsSync as existsSync21 } from "fs";
1798
2536
  import { DEFAULT_AUDIT_CONFIG } from "@omnicross/contracts/audit-types";
1799
2537
  import { DEFAULT_BILLING_CONFIG } from "@omnicross/contracts/billing-types";
1800
2538
  import { getGeminiCodeAssistProjectResolver } from "@omnicross/core/auth/GeminiCodeAssistProjectResolver";
@@ -1828,7 +2566,12 @@ import {
1828
2566
  } from "@omnicross/core/provider-proxy";
1829
2567
  import { routeLeaseDescriptorPort } from "@omnicross/cli-launcher";
1830
2568
  import { KeySpendTracker } from "@omnicross/core/outbound-api";
1831
- import { PricingEngine, UsageRecorder } from "@omnicross/core/usage";
2569
+ import {
2570
+ __resetSharedUsageThroughputTrackerForTests,
2571
+ getSharedUsageThroughputTracker as getSharedUsageThroughputTracker2,
2572
+ PricingEngine,
2573
+ UsageRecorder
2574
+ } from "@omnicross/core/usage";
1832
2575
  import {
1833
2576
  setSubscriptionAccountService,
1834
2577
  setSubscriptionProviderRegistry,
@@ -2335,13 +3078,13 @@ var ClaudeAllowanceRefreshScheduler = class {
2335
3078
  // src/allowance/JsonAccountAllowancePersistence.ts
2336
3079
  import { randomUUID } from "crypto";
2337
3080
  import {
2338
- existsSync as existsSync5,
3081
+ existsSync as existsSync7,
2339
3082
  mkdirSync as mkdirSync3,
2340
- readFileSync as readFileSync7,
2341
- renameSync as renameSync2,
3083
+ readFileSync as readFileSync9,
3084
+ renameSync as renameSync3,
2342
3085
  rmSync,
2343
- statSync,
2344
- writeFileSync as writeFileSync5
3086
+ statSync as statSync3,
3087
+ writeFileSync as writeFileSync6
2345
3088
  } from "fs";
2346
3089
  import { dirname as dirname5 } from "path";
2347
3090
  import { normalizeAccountAllowanceSnapshot } from "@omnicross/core/pipeline/AccountAllowanceStore";
@@ -2355,10 +3098,10 @@ var JsonAccountAllowancePersistence = class {
2355
3098
  cachePath;
2356
3099
  /** Read only the `snapshots` payload; all row validation remains defensive. */
2357
3100
  load() {
2358
- if (!existsSync5(this.cachePath)) return [];
3101
+ if (!existsSync7(this.cachePath)) return [];
2359
3102
  try {
2360
- if (statSync(this.cachePath).size > MAX_ALLOWANCE_CACHE_BYTES) return [];
2361
- const raw = readFileSync7(this.cachePath, "utf8");
3103
+ if (statSync3(this.cachePath).size > MAX_ALLOWANCE_CACHE_BYTES) return [];
3104
+ const raw = readFileSync9(this.cachePath, "utf8");
2362
3105
  if (!raw.trim()) return [];
2363
3106
  const parsed = JSON.parse(raw);
2364
3107
  if (Array.isArray(parsed)) return parsed;
@@ -2389,8 +3132,8 @@ var JsonAccountAllowancePersistence = class {
2389
3132
  mkdirSync3(dirname5(this.cachePath), { recursive: true });
2390
3133
  const temporaryPath = `${this.cachePath}.${process.pid}.${randomUUID()}.tmp`;
2391
3134
  try {
2392
- writeFileSync5(temporaryPath, serialized, { encoding: "utf8", flag: "wx" });
2393
- renameSync2(temporaryPath, this.cachePath);
3135
+ writeFileSync6(temporaryPath, serialized, { encoding: "utf8", flag: "wx" });
3136
+ renameSync3(temporaryPath, this.cachePath);
2394
3137
  } finally {
2395
3138
  rmSync(temporaryPath, { force: true });
2396
3139
  }
@@ -2432,6 +3175,37 @@ function handleAuditQuery(req, res, reader) {
2432
3175
  res.writeHead(200, { "Content-Type": "application/json" });
2433
3176
  res.end(JSON.stringify({ records }));
2434
3177
  }
3178
+ function handleAuditBodyQuery(req, res, reader) {
3179
+ const url = new URL(req.url ?? "/", "http://localhost");
3180
+ const id = url.searchParams.get("id")?.trim();
3181
+ const sessionKey = url.searchParams.get("session")?.trim();
3182
+ if (!id || !sessionKey) {
3183
+ res.writeHead(400, { "Content-Type": "application/json" });
3184
+ res.end(JSON.stringify({ error: "id and session are required" }));
3185
+ return;
3186
+ }
3187
+ const query2 = { id, sessionKey };
3188
+ const ts = intParam(url.searchParams.get("ts"));
3189
+ if (ts !== void 0) query2.ts = ts;
3190
+ const body = reader ? reader(query2) : {};
3191
+ res.writeHead(200, { "Content-Type": "application/json" });
3192
+ res.end(JSON.stringify(body));
3193
+ }
3194
+ function handleAuditCompact(res, compact) {
3195
+ if (!compact) {
3196
+ res.writeHead(200, { "Content-Type": "application/json" });
3197
+ res.end(JSON.stringify({ days: 0, shards: 0, savedBytes: 0 }));
3198
+ return;
3199
+ }
3200
+ try {
3201
+ const result = compact();
3202
+ res.writeHead(200, { "Content-Type": "application/json" });
3203
+ res.end(JSON.stringify(result));
3204
+ } catch (error) {
3205
+ res.writeHead(500, { "Content-Type": "application/json" });
3206
+ res.end(JSON.stringify({ error: error instanceof Error ? error.message : "compaction failed" }));
3207
+ }
3208
+ }
2435
3209
  async function handleAuditStatsQuery(req, res, reader) {
2436
3210
  const url = new URL(req.url ?? "/", "http://localhost");
2437
3211
  const query2 = {};
@@ -3177,10 +3951,10 @@ async function exchangeGemini(code, codeVerifier, exchangeFetch) {
3177
3951
  // src/admin/cliLaunch.ts
3178
3952
  import { exec, spawn } from "child_process";
3179
3953
  import { randomUUID as randomUUID2 } from "crypto";
3180
- import { chmodSync as chmodSync3, existsSync as existsSync6, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
3954
+ import { chmodSync as chmodSync3, existsSync as existsSync8, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "fs";
3181
3955
  import { createServer } from "net";
3182
3956
  import { tmpdir } from "os";
3183
- import { delimiter, join as join4 } from "path";
3957
+ import { delimiter, join as join7 } from "path";
3184
3958
  import {
3185
3959
  buildChatCliLaunchConfig,
3186
3960
  buildClaudeCliLaunchConfig,
@@ -3237,8 +4011,8 @@ function isLaunchCliId(id) {
3237
4011
  function probeDefault(candidate) {
3238
4012
  const segments = (process.env["PATH"] ?? "").split(delimiter).filter(Boolean);
3239
4013
  for (const seg of segments) {
3240
- const full = join4(seg, candidate);
3241
- if (existsSync6(full)) return full;
4014
+ const full = join7(seg, candidate);
4015
+ if (existsSync8(full)) return full;
3242
4016
  }
3243
4017
  return null;
3244
4018
  }
@@ -3342,10 +4116,10 @@ function openTerminal({ cli, command, extraArgs, env, cwd, platform, onFailure }
3342
4116
  const runLine = [command, ...extraArgs].map(shq).join(" ");
3343
4117
  const script = `${cwd ? `cd ${shq(cwd)}; ` : ""}${runLine}`;
3344
4118
  if (platform === "darwin") {
3345
- const launchDir = mkdtempSync(join4(tmpdir(), "omnicross-terminal-"));
3346
- const commandFile = join4(launchDir, "launch.command");
3347
- const bootstrapFile = join4(launchDir, "bootstrap.cjs");
3348
- const socketPath = macIpc.socketPath ?? join4(launchDir, "descriptor.sock");
4119
+ const launchDir = mkdtempSync(join7(tmpdir(), "omnicross-terminal-"));
4120
+ const commandFile = join7(launchDir, "launch.command");
4121
+ const bootstrapFile = join7(launchDir, "bootstrap.cjs");
4122
+ const socketPath = macIpc.socketPath ?? join7(launchDir, "descriptor.sock");
3349
4123
  const openerEnv = { ...process.env };
3350
4124
  for (const key of Object.keys(env)) delete openerEnv[key];
3351
4125
  let claimed = false;
@@ -3415,8 +4189,8 @@ function openTerminal({ cli, command, extraArgs, env, cwd, platform, onFailure }
3415
4189
  }
3416
4190
  };
3417
4191
  try {
3418
- writeFileSync6(bootstrapFile, MAC_TERMINAL_BOOTSTRAP_SOURCE, { encoding: "utf8", mode: 448 });
3419
- writeFileSync6(commandFile, `#!/bin/bash
4192
+ writeFileSync7(bootstrapFile, MAC_TERMINAL_BOOTSTRAP_SOURCE, { encoding: "utf8", mode: 448 });
4193
+ writeFileSync7(commandFile, `#!/bin/bash
3420
4194
  rm -f -- "$0"
3421
4195
  exec ${shq(process.execPath)} ${shq(bootstrapFile)} ${shq(socketPath)} ${shq(launchDir)} ${shq(cwd ?? "")} ${runLine}
3422
4196
  `, {
@@ -4087,6 +4861,7 @@ function applyAuditConfig(config) {
4087
4861
  } else {
4088
4862
  setAuditCaptureConfig(null);
4089
4863
  setAuditSink(null);
4864
+ writer?.reset();
4090
4865
  if (sweeper) {
4091
4866
  if (config) sweeper.configure(config);
4092
4867
  sweeper.dispose();
@@ -4673,6 +5448,7 @@ async function handleImport(body, deps) {
4673
5448
  }
4674
5449
 
4675
5450
  // src/admin/usagePricing.ts
5451
+ import { getSharedUsageThroughputTracker } from "@omnicross/core/usage";
4676
5452
  var err4 = (status, message) => ({
4677
5453
  status,
4678
5454
  body: { error: { type: "admin_api_error", message } }
@@ -4698,6 +5474,9 @@ var BUCKET_SPAN_MS = {
4698
5474
  };
4699
5475
  var MAX_TIMESERIES_BUCKETS = 2e3;
4700
5476
  async function handleUsageGet(view, query2, deps) {
5477
+ if (view === "throughput") {
5478
+ return { status: 200, body: getSharedUsageThroughputTracker().snapshot() };
5479
+ }
4701
5480
  const range = parseRange(query2);
4702
5481
  if (!isRange(range)) return range;
4703
5482
  switch (view) {
@@ -6334,7 +7113,7 @@ function proxyToOutbound(res, outboundPort, path2, key, body) {
6334
7113
  }
6335
7114
 
6336
7115
  // src/admin/uiStatic.ts
6337
- import { existsSync as existsSync7, statSync as statSync2 } from "fs";
7116
+ import { existsSync as existsSync9, statSync as statSync4 } from "fs";
6338
7117
  import { readFile } from "fs/promises";
6339
7118
  import { createRequire } from "module";
6340
7119
  import path from "path";
@@ -6357,13 +7136,13 @@ var CONTENT_TYPES = {
6357
7136
  function resolveUiDist() {
6358
7137
  const fromEnv = process.env["OMNICROSS_UI_DIST"];
6359
7138
  if (fromEnv) {
6360
- return existsSync7(path.join(fromEnv, "index.html")) ? path.resolve(fromEnv) : null;
7139
+ return existsSync9(path.join(fromEnv, "index.html")) ? path.resolve(fromEnv) : null;
6361
7140
  }
6362
7141
  try {
6363
7142
  const req = createRequire(typeof __filename !== "undefined" ? __filename : import.meta.url);
6364
7143
  const pkgJson = req.resolve("@omnicross/ui/package.json");
6365
7144
  const dist = path.join(path.dirname(pkgJson), "dist");
6366
- return existsSync7(path.join(dist, "index.html")) ? dist : null;
7145
+ return existsSync9(path.join(dist, "index.html")) ? dist : null;
6367
7146
  } catch {
6368
7147
  return null;
6369
7148
  }
@@ -6412,7 +7191,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
6412
7191
  return true;
6413
7192
  }
6414
7193
  let target = filePath;
6415
- if (!existsSync7(target) || statSync2(target).isDirectory()) {
7194
+ if (!existsSync9(target) || statSync4(target).isDirectory()) {
6416
7195
  if (path.extname(rel) === "") {
6417
7196
  target = path.join(uiDist, "index.html");
6418
7197
  } else {
@@ -6429,7 +7208,7 @@ async function handleUiStatic(req, res, urlPath, uiDist) {
6429
7208
  }
6430
7209
 
6431
7210
  // src/admin/version.ts
6432
- var DAEMON_VERSION = true ? "0.1.9" : "0.0.0-dev";
7211
+ var DAEMON_VERSION = true ? "0.1.10" : "0.0.0-dev";
6433
7212
 
6434
7213
  // src/admin/AdminServer.ts
6435
7214
  var LOOPBACK_ADDR = "127.0.0.1";
@@ -6541,6 +7320,14 @@ var AdminServer = class {
6541
7320
  await handleAuditStatsQuery(req, res, this.deps.auditStatsReader);
6542
7321
  return;
6543
7322
  }
7323
+ if (path2 === "/admin/api/audit/body" && (req.method === "GET" || req.method === "HEAD")) {
7324
+ handleAuditBodyQuery(req, res, this.deps.auditBodyReader);
7325
+ return;
7326
+ }
7327
+ if (path2 === "/admin/api/audit/compact" && req.method === "POST") {
7328
+ handleAuditCompact(res, this.deps.auditCompactor);
7329
+ return;
7330
+ }
6544
7331
  if (path2 === "/admin/api/billing-status" && (req.method === "GET" || req.method === "HEAD")) {
6545
7332
  handleBillingStatus(res, this.deps.billingStatusReader);
6546
7333
  return;
@@ -7153,7 +7940,7 @@ function safeStringify(value) {
7153
7940
  }
7154
7941
 
7155
7942
  // src/ports/JsonApiServerSettingsStore.ts
7156
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
7943
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
7157
7944
  import { OUTBOUND_API_SERVER_CONFIG_KEY } from "@omnicross/core/outbound-api";
7158
7945
  var JsonApiServerSettingsStore = class {
7159
7946
  /**
@@ -7180,7 +7967,7 @@ var JsonApiServerSettingsStore = class {
7180
7967
  if (key !== OUTBOUND_API_SERVER_CONFIG_KEY) return;
7181
7968
  const file = this.readFile();
7182
7969
  file.server = this.encryptSecrets(value);
7183
- writeFileSync7(this.configPath, JSON.stringify(file, null, 2) + "\n", "utf8");
7970
+ writeFileSync8(this.configPath, JSON.stringify(file, null, 2) + "\n", "utf8");
7184
7971
  }
7185
7972
  /** Encrypt the proxy passwords + webhook + billing secrets before persisting (no-op without a box). */
7186
7973
  encryptSecrets(config) {
@@ -7203,7 +7990,7 @@ var JsonApiServerSettingsStore = class {
7203
7990
  /** Read the config.json, tolerating a missing/corrupt file (→ empty shape). */
7204
7991
  readFile() {
7205
7992
  try {
7206
- const raw = readFileSync8(this.configPath, "utf8");
7993
+ const raw = readFileSync10(this.configPath, "utf8");
7207
7994
  const parsed = JSON.parse(raw);
7208
7995
  if (parsed && typeof parsed === "object") return parsed;
7209
7996
  } catch {
@@ -7214,7 +8001,7 @@ var JsonApiServerSettingsStore = class {
7214
8001
 
7215
8002
  // src/ports/JsonlUsageEventStore.ts
7216
8003
  import { randomUUID as randomUUID4 } from "crypto";
7217
- import { appendFileSync, existsSync as existsSync8, readFileSync as readFileSync9 } from "fs";
8004
+ import { appendFileSync, existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
7218
8005
  var JsonlUsageEventStore = class {
7219
8006
  constructor(eventsPath, isPriced) {
7220
8007
  this.eventsPath = eventsPath;
@@ -7428,10 +8215,10 @@ var JsonlUsageEventStore = class {
7428
8215
  }
7429
8216
  /** Parse every line, skipping malformed/torn lines defensively. */
7430
8217
  readAllRows() {
7431
- if (!existsSync8(this.eventsPath)) return [];
8218
+ if (!existsSync10(this.eventsPath)) return [];
7432
8219
  let raw;
7433
8220
  try {
7434
- raw = readFileSync9(this.eventsPath, "utf8");
8221
+ raw = readFileSync11(this.eventsPath, "utf8");
7435
8222
  } catch {
7436
8223
  return [];
7437
8224
  }
@@ -7470,15 +8257,15 @@ function nextBoundary(ts, bucket) {
7470
8257
  return new Date(d.getFullYear(), d.getMonth() + 1, 1).getTime();
7471
8258
  }
7472
8259
  }
7473
- var pad2 = (n) => String(n).padStart(2, "0");
8260
+ var pad22 = (n) => String(n).padStart(2, "0");
7474
8261
  function bucketLabel(bucketStartTs, bucket) {
7475
8262
  const d = new Date(bucketStartTs);
7476
8263
  const y = d.getFullYear();
7477
- const mo = pad2(d.getMonth() + 1);
7478
- const day = pad2(d.getDate());
8264
+ const mo = pad22(d.getMonth() + 1);
8265
+ const day = pad22(d.getDate());
7479
8266
  switch (bucket) {
7480
8267
  case "hour":
7481
- return `${mo}-${day} ${pad2(d.getHours())}:00`;
8268
+ return `${mo}-${day} ${pad22(d.getHours())}:00`;
7482
8269
  case "day":
7483
8270
  return `${y}-${mo}-${day}`;
7484
8271
  case "month":
@@ -7534,7 +8321,7 @@ function median(values) {
7534
8321
  }
7535
8322
 
7536
8323
  // src/ports/JsonPricingStore.ts
7537
- import { existsSync as existsSync9, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
8324
+ import { existsSync as existsSync11, readFileSync as readFileSync12, renameSync as renameSync4, rmSync as rmSync3, writeFileSync as writeFileSync9 } from "fs";
7538
8325
  import { randomUUID as randomUUID5 } from "crypto";
7539
8326
  var JsonPricingStore = class {
7540
8327
  constructor(pricingPath) {
@@ -7549,9 +8336,9 @@ var JsonPricingStore = class {
7549
8336
  * otherwise unusable pricing table after a crash or manual file edit.
7550
8337
  */
7551
8338
  hasUsableSnapshot() {
7552
- if (!existsSync9(this.pricingPath)) return false;
8339
+ if (!existsSync11(this.pricingPath)) return false;
7553
8340
  try {
7554
- const parsed = JSON.parse(readFileSync10(this.pricingPath, "utf8"));
8341
+ const parsed = JSON.parse(readFileSync12(this.pricingPath, "utf8"));
7555
8342
  return Array.isArray(parsed) && parsed.some(isUsablePricingRow);
7556
8343
  } catch {
7557
8344
  return false;
@@ -7664,9 +8451,9 @@ var JsonPricingStore = class {
7664
8451
  }
7665
8452
  /** Read the pricing rows, tolerating a missing/corrupt file (→ empty list). */
7666
8453
  readRows() {
7667
- if (!existsSync9(this.pricingPath)) return [];
8454
+ if (!existsSync11(this.pricingPath)) return [];
7668
8455
  try {
7669
- const parsed = JSON.parse(readFileSync10(this.pricingPath, "utf8"));
8456
+ const parsed = JSON.parse(readFileSync12(this.pricingPath, "utf8"));
7670
8457
  return Array.isArray(parsed) ? parsed : [];
7671
8458
  } catch {
7672
8459
  return [];
@@ -7675,7 +8462,7 @@ var JsonPricingStore = class {
7675
8462
  writeRows(rows) {
7676
8463
  const temporaryPath = `${this.pricingPath}.${process.pid}.${randomUUID5()}.tmp`;
7677
8464
  try {
7678
- writeFileSync8(temporaryPath, JSON.stringify(rows, null, 2) + "\n", {
8465
+ writeFileSync9(temporaryPath, JSON.stringify(rows, null, 2) + "\n", {
7679
8466
  encoding: "utf8",
7680
8467
  flag: "wx"
7681
8468
  });
@@ -7686,7 +8473,7 @@ var JsonPricingStore = class {
7686
8473
  }
7687
8474
  /** Isolated for deterministic failure testing; never removes the target. */
7688
8475
  replaceFile(temporaryPath) {
7689
- renameSync3(temporaryPath, this.pricingPath);
8476
+ renameSync4(temporaryPath, this.pricingPath);
7690
8477
  }
7691
8478
  };
7692
8479
  function isUsablePricingRow(value) {
@@ -7696,7 +8483,7 @@ function isUsablePricingRow(value) {
7696
8483
  }
7697
8484
 
7698
8485
  // src/pricing/PricingRefreshScheduler.ts
7699
- import { existsSync as existsSync10, readFileSync as readFileSync11, renameSync as renameSync4, writeFileSync as writeFileSync9 } from "fs";
8486
+ import { existsSync as existsSync12, readFileSync as readFileSync13, renameSync as renameSync5, writeFileSync as writeFileSync10 } from "fs";
7700
8487
  var EMPTY_STATE2 = {
7701
8488
  lastAttemptAt: null,
7702
8489
  lastSuccessAt: null,
@@ -7734,9 +8521,9 @@ var PricingRefreshScheduler = class {
7734
8521
  this.timer = null;
7735
8522
  }
7736
8523
  getState() {
7737
- if (!existsSync10(this.statePath)) return { ...EMPTY_STATE2, sources: [] };
8524
+ if (!existsSync12(this.statePath)) return { ...EMPTY_STATE2, sources: [] };
7738
8525
  try {
7739
- const value = JSON.parse(readFileSync11(this.statePath, "utf8"));
8526
+ const value = JSON.parse(readFileSync13(this.statePath, "utf8"));
7740
8527
  return {
7741
8528
  lastAttemptAt: finiteOrNull(value.lastAttemptAt),
7742
8529
  lastSuccessAt: finiteOrNull(value.lastSuccessAt),
@@ -7789,9 +8576,9 @@ var PricingRefreshScheduler = class {
7789
8576
  }
7790
8577
  writeState(state) {
7791
8578
  const temporaryPath = `${this.statePath}.tmp`;
7792
- writeFileSync9(temporaryPath, `${JSON.stringify(state, null, 2)}
8579
+ writeFileSync10(temporaryPath, `${JSON.stringify(state, null, 2)}
7793
8580
  `, "utf8");
7794
- renameSync4(temporaryPath, this.statePath);
8581
+ renameSync5(temporaryPath, this.statePath);
7795
8582
  }
7796
8583
  };
7797
8584
  function finiteOrNull(value) {
@@ -7799,7 +8586,7 @@ function finiteOrNull(value) {
7799
8586
  }
7800
8587
 
7801
8588
  // src/ports/JsonVoucherDb.ts
7802
- import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
8589
+ import { existsSync as existsSync13, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
7803
8590
  var JsonVoucherDb = class {
7804
8591
  constructor(vouchersPath) {
7805
8592
  this.vouchersPath = vouchersPath;
@@ -7877,21 +8664,21 @@ var JsonVoucherDb = class {
7877
8664
  }
7878
8665
  /** Read the voucher rows, tolerating a missing/corrupt file (→ empty list). */
7879
8666
  readRows() {
7880
- if (!existsSync11(this.vouchersPath)) return [];
8667
+ if (!existsSync13(this.vouchersPath)) return [];
7881
8668
  try {
7882
- const parsed = JSON.parse(readFileSync12(this.vouchersPath, "utf8"));
8669
+ const parsed = JSON.parse(readFileSync14(this.vouchersPath, "utf8"));
7883
8670
  return Array.isArray(parsed) ? parsed : [];
7884
8671
  } catch {
7885
8672
  return [];
7886
8673
  }
7887
8674
  }
7888
8675
  writeRows(rows) {
7889
- writeFileSync10(this.vouchersPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
8676
+ writeFileSync11(this.vouchersPath, JSON.stringify(rows, null, 2) + "\n", "utf8");
7890
8677
  }
7891
8678
  };
7892
8679
 
7893
8680
  // src/ports/JsonSubscriptionCredentialStore.ts
7894
- import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
8681
+ import { existsSync as existsSync15, mkdirSync as mkdirSync4, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "fs";
7895
8682
  import { dirname as dirname6 } from "path";
7896
8683
  import { getSharedAccountHealth as getSharedAccountHealth2 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
7897
8684
  import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling3 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
@@ -7945,11 +8732,11 @@ function findDuplicateCredentialIds(accounts) {
7945
8732
  }
7946
8733
 
7947
8734
  // src/ports/external-cli-credentials.ts
7948
- import { existsSync as existsSync12, readFileSync as readFileSync13 } from "fs";
8735
+ import { existsSync as existsSync14, readFileSync as readFileSync15 } from "fs";
7949
8736
  import { homedir as homedir3 } from "os";
7950
- import { join as join5 } from "path";
8737
+ import { join as join8 } from "path";
7951
8738
  function externalStorePath(provider, home = homedir3()) {
7952
- return provider === "claude" ? join5(home, ".claude", ".credentials.json") : join5(home, ".codex", "auth.json");
8739
+ return provider === "claude" ? join8(home, ".claude", ".credentials.json") : join8(home, ".codex", "auth.json");
7953
8740
  }
7954
8741
  function decodeJwtExpiryMs(token) {
7955
8742
  try {
@@ -7998,10 +8785,10 @@ function parseCodexTokensEnvelope(raw) {
7998
8785
  }
7999
8786
  function readExternalCliCredentials(provider, home = homedir3()) {
8000
8787
  const path2 = externalStorePath(provider, home);
8001
- if (!existsSync12(path2)) return null;
8788
+ if (!existsSync14(path2)) return null;
8002
8789
  let raw;
8003
8790
  try {
8004
- const parsed = JSON.parse(readFileSync13(path2, "utf8"));
8791
+ const parsed = JSON.parse(readFileSync15(path2, "utf8"));
8005
8792
  raw = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
8006
8793
  } catch {
8007
8794
  return null;
@@ -8574,7 +9361,7 @@ var JsonSubscriptionCredentialStore = class {
8574
9361
  persist(config) {
8575
9362
  mkdirSync4(dirname6(this.tokensPath), { recursive: true });
8576
9363
  const encrypted = encryptTokens(config, this.box);
8577
- writeFileSync11(this.tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
9364
+ writeFileSync12(this.tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
8578
9365
  }
8579
9366
  /**
8580
9367
  * Read + parse `tokens.json`, tolerating a missing/corrupt file, then DECRYPT
@@ -8590,10 +9377,10 @@ var JsonSubscriptionCredentialStore = class {
8590
9377
  * `config.ts loadConfig`, which decrypts outside its parse try.
8591
9378
  */
8592
9379
  readConfig() {
8593
- if (!existsSync13(this.tokensPath)) return { updatedAt: "" };
9380
+ if (!existsSync15(this.tokensPath)) return { updatedAt: "" };
8594
9381
  let parsed;
8595
9382
  try {
8596
- const raw = JSON.parse(readFileSync14(this.tokensPath, "utf8"));
9383
+ const raw = JSON.parse(readFileSync16(this.tokensPath, "utf8"));
8597
9384
  parsed = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : null;
8598
9385
  } catch {
8599
9386
  parsed = null;
@@ -9113,39 +9900,21 @@ var AccountHealthSweeper = class {
9113
9900
  };
9114
9901
 
9115
9902
  // src/audit/AuditPruneSweeper.ts
9116
- import { existsSync as existsSync15, readdirSync as readdirSync2, unlinkSync as unlinkSync3 } from "fs";
9117
- import { join as join7 } from "path";
9118
-
9119
- // src/audit/auditFiles.ts
9120
- var AUDIT_FILE_RE = /^audit-(\d{4})-(\d{2})-(\d{2})\.jsonl$/;
9121
- var pad22 = (n) => String(n).padStart(2, "0");
9122
- function auditFileName(ts) {
9123
- const d = new Date(ts);
9124
- return `audit-${d.getFullYear()}-${pad22(d.getMonth() + 1)}-${pad22(d.getDate())}.jsonl`;
9125
- }
9126
- function auditFileDateMs(fileName) {
9127
- const m = AUDIT_FILE_RE.exec(fileName);
9128
- if (!m) return null;
9129
- const year = Number(m[1]);
9130
- const month = Number(m[2]);
9131
- const day = Number(m[3]);
9132
- const d = new Date(year, month - 1, day);
9133
- if (d.getFullYear() !== year || d.getMonth() !== month - 1 || d.getDate() !== day) {
9134
- return null;
9135
- }
9136
- return d.getTime();
9137
- }
9903
+ import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync17, readdirSync as readdirSync5, rmSync as rmSync4, unlinkSync as unlinkSync4 } from "fs";
9904
+ import { join as join10 } from "path";
9905
+ import { pipeline } from "stream/promises";
9906
+ import { createGzip } from "zlib";
9138
9907
 
9139
9908
  // src/audit/auditStats.ts
9140
9909
  import {
9141
9910
  createReadStream,
9142
- existsSync as existsSync14,
9143
- readFileSync as readFileSync15,
9144
- readdirSync,
9145
- statSync as statSync3,
9146
- writeFileSync as writeFileSync12
9911
+ existsSync as existsSync16,
9912
+ readFileSync as readFileSync17,
9913
+ readdirSync as readdirSync4,
9914
+ statSync as statSync5,
9915
+ writeFileSync as writeFileSync13
9147
9916
  } from "fs";
9148
- import { basename, dirname as dirname7, join as join6 } from "path";
9917
+ import { basename, dirname as dirname7, join as join9 } from "path";
9149
9918
  var SIDECAR_VERSION = 1;
9150
9919
  var META_PREFIX_BYTES = 64 * 1024;
9151
9920
  var READ_CHUNK_BYTES = 4 * 1024 * 1024;
@@ -9153,9 +9922,9 @@ function auditStatsFileName(auditFile) {
9153
9922
  return auditFile.replace(/\.jsonl$/, ".stats.json");
9154
9923
  }
9155
9924
  function readPersisted(path2) {
9156
- if (!existsSync14(path2)) return null;
9925
+ if (!existsSync16(path2)) return null;
9157
9926
  try {
9158
- const value = JSON.parse(readFileSync15(path2, "utf8"));
9927
+ const value = JSON.parse(readFileSync17(path2, "utf8"));
9159
9928
  if (value.version !== SIDECAR_VERSION || !Number.isSafeInteger(value.auditBytes) || (value.auditBytes ?? -1) < 0 || !Number.isSafeInteger(value.requestCount) || (value.requestCount ?? -1) < 0 || !Number.isSafeInteger(value.errorCount) || (value.errorCount ?? -1) < 0 || (value.errorCount ?? 0) > (value.requestCount ?? -1) || typeof value.complete !== "boolean" || value.minTs !== null && !Number.isFinite(value.minTs) || value.maxTs !== null && !Number.isFinite(value.maxTs)) {
9160
9929
  return null;
9161
9930
  }
@@ -9165,7 +9934,7 @@ function readPersisted(path2) {
9165
9934
  }
9166
9935
  }
9167
9936
  function updateAuditStatsAfterAppend(auditPath, auditBytesBefore, auditBytesAfter, record) {
9168
- const statsPath = join6(dirname7(auditPath), auditStatsFileName(basename(auditPath)));
9937
+ const statsPath = join9(dirname7(auditPath), auditStatsFileName(basename(auditPath)));
9169
9938
  const previous = auditBytesBefore === 0 ? {
9170
9939
  version: SIDECAR_VERSION,
9171
9940
  auditBytes: 0,
@@ -9185,13 +9954,13 @@ function updateAuditStatsAfterAppend(auditPath, auditBytesBefore, auditBytesAfte
9185
9954
  minTs: previous.minTs === null ? record.ts : Math.min(previous.minTs, record.ts),
9186
9955
  maxTs: previous.maxTs === null ? record.ts : Math.max(previous.maxTs, record.ts)
9187
9956
  };
9188
- writeFileSync12(statsPath, JSON.stringify(next), "utf8");
9957
+ writeFileSync13(statsPath, JSON.stringify(next), "utf8");
9189
9958
  }
9190
9959
  function queryCovers(stats, from, to) {
9191
9960
  return stats.requestCount === 0 || stats.minTs !== null && stats.maxTs !== null && from <= stats.minTs && to >= stats.maxTs;
9192
9961
  }
9193
- function fileOverlaps(file, from, to) {
9194
- const start = auditFileDateMs(file);
9962
+ function fileOverlaps(name, from, to) {
9963
+ const start = auditFileDateMs(name);
9195
9964
  if (start === null) return false;
9196
9965
  const date = new Date(start);
9197
9966
  const end = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1).getTime();
@@ -9296,21 +10065,27 @@ function mergePersistedStats(previous, appended) {
9296
10065
  };
9297
10066
  }
9298
10067
  async function readAuditStats(auditDir, query2 = {}) {
9299
- if (!existsSync14(auditDir)) return { requestCount: 0, errorCount: 0, complete: true };
10068
+ if (!existsSync16(auditDir)) return { requestCount: 0, errorCount: 0, complete: true };
9300
10069
  const from = typeof query2.from === "number" ? query2.from : -Infinity;
9301
10070
  const to = typeof query2.to === "number" ? query2.to : Infinity;
9302
- let files;
10071
+ let sources;
9303
10072
  try {
9304
- files = readdirSync(auditDir).filter((file) => AUDIT_FILE_RE.test(file) && fileOverlaps(file, from, to)).sort();
10073
+ sources = readdirSync4(auditDir).filter((name) => fileOverlaps(name, from, to)).sort().map(
10074
+ (name) => AUDIT_DAY_DIR_RE.test(name) ? {
10075
+ auditPath: join9(auditDir, name, AUDIT_META_FILE),
10076
+ statsPath: join9(auditDir, name, auditStatsFileName(AUDIT_META_FILE))
10077
+ } : {
10078
+ auditPath: join9(auditDir, name),
10079
+ statsPath: join9(auditDir, auditStatsFileName(name))
10080
+ }
10081
+ ).filter((source) => existsSync16(source.auditPath));
9305
10082
  } catch {
9306
10083
  return { requestCount: 0, errorCount: 0, complete: false };
9307
10084
  }
9308
10085
  const total = { requestCount: 0, errorCount: 0, complete: true };
9309
- for (const file of files) {
9310
- const auditPath = join6(auditDir, file);
10086
+ for (const { auditPath, statsPath } of sources) {
9311
10087
  try {
9312
- const auditBytes = statSync3(auditPath).size;
9313
- const statsPath = join6(auditDir, auditStatsFileName(file));
10088
+ const auditBytes = statSync5(auditPath).size;
9314
10089
  const persisted = readPersisted(statsPath);
9315
10090
  if (persisted && persisted.complete && persisted.auditBytes === auditBytes && queryCovers(persisted, from, to)) {
9316
10091
  total.requestCount += persisted.requestCount;
@@ -9329,7 +10104,7 @@ async function readAuditStats(auditDir, query2 = {}) {
9329
10104
  total.errorCount += scanned.filtered.errorCount + (resumable?.errorCount ?? 0);
9330
10105
  total.complete = total.complete && scanned.filtered.complete;
9331
10106
  const current = resumable ? mergePersistedStats(resumable, scanned.all) : scanned.all;
9332
- if (current.complete) writeFileSync12(statsPath, JSON.stringify(current), "utf8");
10107
+ if (current.complete) writeFileSync13(statsPath, JSON.stringify(current), "utf8");
9333
10108
  } catch {
9334
10109
  total.complete = false;
9335
10110
  }
@@ -9340,6 +10115,7 @@ async function readAuditStats(auditDir, query2 = {}) {
9340
10115
  // src/audit/AuditPruneSweeper.ts
9341
10116
  var DAY_MS = 24 * 60 * 6e4;
9342
10117
  var SWEEP_INTERVAL_MS2 = 60 * 6e4;
10118
+ var ARCHIVE_BATCH = 64;
9343
10119
  var AuditPruneSweeper = class {
9344
10120
  constructor(auditDir, logger, config, intervalMs = SWEEP_INTERVAL_MS2, now = Date.now) {
9345
10121
  this.auditDir = auditDir;
@@ -9355,6 +10131,7 @@ var AuditPruneSweeper = class {
9355
10131
  now;
9356
10132
  timer = null;
9357
10133
  sweeping = false;
10134
+ archiving = false;
9358
10135
  /** Whether pruning is active (audit enabled). */
9359
10136
  get enabled() {
9360
10137
  return this.config.enabled;
@@ -9364,13 +10141,13 @@ var AuditPruneSweeper = class {
9364
10141
  this.config = config;
9365
10142
  }
9366
10143
  /**
9367
- * Arm the prune interval AND run one prune immediately (boot cleanup). No-op
9368
- * when audit is disabled (zero regression). Idempotent.
10144
+ * Arm the interval AND run one pass immediately (boot cleanup). No-op when
10145
+ * audit is disabled (zero regression). Idempotent.
9369
10146
  */
9370
10147
  start() {
9371
10148
  if (this.timer || !this.config.enabled) return;
9372
- void this.sweep();
9373
- this.timer = setInterval(() => void this.sweep(), this.intervalMs);
10149
+ void this.runOnce();
10150
+ this.timer = setInterval(() => void this.runOnce(), this.intervalMs);
9374
10151
  this.timer.unref?.();
9375
10152
  }
9376
10153
  /** Clear the interval (daemon shutdown / test teardown). Idempotent. */
@@ -9380,31 +10157,43 @@ var AuditPruneSweeper = class {
9380
10157
  this.timer = null;
9381
10158
  }
9382
10159
  }
10160
+ /** Prune first, then archive — never spend CPU compressing a day about to go. */
10161
+ async runOnce() {
10162
+ await this.sweep();
10163
+ await this.archive();
10164
+ }
10165
+ /** The LOCAL-midnight epoch ms of the current day. */
10166
+ todayMidnight() {
10167
+ const today = new Date(this.now());
10168
+ return new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime();
10169
+ }
9383
10170
  /**
9384
- * One prune: unlink every audit date file strictly OLDER than the retention
9385
- * cutoff (`now - retentionDays` days, at local-midnight granularity). Exposed
9386
- * for tests; never throws. Returns the number of files removed.
10171
+ * One prune: remove every audit day strictly OLDER than the retention cutoff
10172
+ * (`now - retentionDays` days, at local-midnight granularity). Exposed for
10173
+ * tests; never throws. Returns the number of days removed.
9387
10174
  */
9388
10175
  async sweep() {
9389
10176
  if (!this.config.enabled || this.sweeping) return 0;
9390
10177
  this.sweeping = true;
9391
10178
  try {
9392
- if (!existsSync15(this.auditDir)) return 0;
9393
- const today = new Date(this.now());
9394
- const todayMidnight = new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime();
9395
- const cutoff = todayMidnight - (this.config.retentionDays - 1) * DAY_MS;
10179
+ if (!existsSync17(this.auditDir)) return 0;
10180
+ const cutoff = this.todayMidnight() - (this.config.retentionDays - 1) * DAY_MS;
9396
10181
  let removed = 0;
9397
- for (const file of readdirSync2(this.auditDir)) {
9398
- const dateMs = auditFileDateMs(file);
10182
+ for (const name of readdirSync5(this.auditDir)) {
10183
+ const dateMs = auditFileDateMs(name);
9399
10184
  if (dateMs === null || dateMs >= cutoff) continue;
9400
10185
  try {
9401
- unlinkSync3(join7(this.auditDir, file));
10186
+ if (isAuditDayDir(name)) {
10187
+ rmSync4(join10(this.auditDir, name), { recursive: true, force: true });
10188
+ } else {
10189
+ unlinkSync4(join10(this.auditDir, name));
10190
+ const statsPath = join10(this.auditDir, auditStatsFileName(name));
10191
+ if (existsSync17(statsPath)) unlinkSync4(statsPath);
10192
+ }
9402
10193
  removed += 1;
9403
- const statsPath = join7(this.auditDir, auditStatsFileName(file));
9404
- if (existsSync15(statsPath)) unlinkSync3(statsPath);
9405
10194
  } catch (error) {
9406
- this.logger.warn("[AuditPruneSweeper] failed to unlink expired audit file", {
9407
- file,
10195
+ this.logger.warn("[AuditPruneSweeper] failed to remove expired audit day", {
10196
+ name,
9408
10197
  error: error instanceof Error ? error.message : String(error)
9409
10198
  });
9410
10199
  }
@@ -9420,59 +10209,158 @@ var AuditPruneSweeper = class {
9420
10209
  this.sweeping = false;
9421
10210
  }
9422
10211
  }
10212
+ /**
10213
+ * Gzip the body shards of every CLOSED day (anything before today). Today is
10214
+ * deliberately left as plain text so it stays greppable while it is the day you
10215
+ * are debugging. Exposed for tests; never throws. Returns shards compressed.
10216
+ */
10217
+ async archive() {
10218
+ if (!this.config.enabled || this.archiving) return 0;
10219
+ this.archiving = true;
10220
+ try {
10221
+ if (!existsSync17(this.auditDir)) return 0;
10222
+ const today = this.todayMidnight();
10223
+ let compressed = 0;
10224
+ for (const name of readdirSync5(this.auditDir)) {
10225
+ if (compressed >= ARCHIVE_BATCH) break;
10226
+ const dateMs = auditFileDateMs(name);
10227
+ if (dateMs === null || dateMs >= today || !isAuditDayDir(name)) continue;
10228
+ const dayPath = join10(this.auditDir, name);
10229
+ try {
10230
+ const compaction = compactAuditDay(dayPath);
10231
+ if (compaction.shards > 0) {
10232
+ this.logger.debug("audit cross-session compaction complete", {
10233
+ day: name,
10234
+ shards: compaction.shards,
10235
+ anchors: compaction.anchors,
10236
+ savedBytes: compaction.savedBytes
10237
+ });
10238
+ }
10239
+ } catch (error) {
10240
+ this.logger.warn("[AuditPruneSweeper] cross-session compaction failed", {
10241
+ day: name,
10242
+ error: error instanceof Error ? error.message : String(error)
10243
+ });
10244
+ }
10245
+ compressed += await this.archiveDay(
10246
+ join10(dayPath, AUDIT_BODIES_DIR),
10247
+ ARCHIVE_BATCH - compressed
10248
+ );
10249
+ }
10250
+ if (compressed > 0) this.logger.debug("audit archive complete", { compressed });
10251
+ return compressed;
10252
+ } catch (error) {
10253
+ this.logger.warn("audit archive pass failed", {
10254
+ error: error instanceof Error ? error.message : String(error)
10255
+ });
10256
+ return 0;
10257
+ } finally {
10258
+ this.archiving = false;
10259
+ }
10260
+ }
10261
+ /** Gzip up to `budget` plain shards in one day's `bodies/` directory. */
10262
+ async archiveDay(bodiesPath, budget) {
10263
+ let shards;
10264
+ try {
10265
+ shards = readdirSync5(bodiesPath).filter((file) => file.endsWith(".jsonl"));
10266
+ } catch {
10267
+ return 0;
10268
+ }
10269
+ let compressed = 0;
10270
+ for (const shard of shards) {
10271
+ if (compressed >= budget) break;
10272
+ const source = join10(bodiesPath, shard);
10273
+ const target = `${source}.gz`;
10274
+ try {
10275
+ if (existsSync17(target)) {
10276
+ unlinkSync4(source);
10277
+ continue;
10278
+ }
10279
+ await pipeline(createReadStream2(source), createGzip(), createWriteStream2(target));
10280
+ unlinkSync4(source);
10281
+ compressed += 1;
10282
+ } catch (error) {
10283
+ try {
10284
+ if (existsSync17(target)) unlinkSync4(target);
10285
+ } catch {
10286
+ }
10287
+ this.logger.warn("[AuditPruneSweeper] failed to archive audit body shard", {
10288
+ shard,
10289
+ error: error instanceof Error ? error.message : String(error)
10290
+ });
10291
+ }
10292
+ }
10293
+ return compressed;
10294
+ }
9423
10295
  };
9424
10296
 
9425
10297
  // src/audit/auditReader.ts
9426
- import { existsSync as existsSync16, readdirSync as readdirSync3, readFileSync as readFileSync16 } from "fs";
9427
- import { join as join8 } from "path";
10298
+ import { existsSync as existsSync18, readdirSync as readdirSync6 } from "fs";
10299
+ import { join as join11 } from "path";
9428
10300
  var DEFAULT_LIMIT = 200;
9429
10301
  var MAX_LIMIT = 2e3;
9430
- function readAuditRecords(auditDir, query2 = {}) {
9431
- if (!existsSync16(auditDir)) return [];
9432
- let files;
10302
+ var OVERSCAN = 256;
10303
+ function daySources(auditDir) {
10304
+ let names;
9433
10305
  try {
9434
- files = readdirSync3(auditDir).filter((f) => AUDIT_FILE_RE.test(f));
10306
+ names = readdirSync6(auditDir);
9435
10307
  } catch {
9436
10308
  return [];
9437
10309
  }
10310
+ const sources = [];
10311
+ for (const name of names) {
10312
+ const dateMs = auditFileDateMs(name);
10313
+ if (dateMs === null) continue;
10314
+ if (AUDIT_DAY_DIR_RE.test(name)) {
10315
+ const path2 = join11(auditDir, name, AUDIT_META_FILE);
10316
+ if (existsSync18(path2)) sources.push({ path: path2, dateMs });
10317
+ } else if (AUDIT_FILE_RE.test(name)) {
10318
+ sources.push({ path: join11(auditDir, name), dateMs });
10319
+ }
10320
+ }
10321
+ return sources.sort((a, b) => b.dateMs - a.dateMs);
10322
+ }
10323
+ function isAuditRecord(value) {
10324
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
10325
+ const r = value;
10326
+ return typeof r["id"] === "string" && typeof r["ts"] === "number" && typeof r["method"] === "string" && typeof r["path"] === "string" && typeof r["status"] === "number";
10327
+ }
10328
+ function toMetaRecord(record) {
10329
+ if (record.requestBody === void 0 && record.responseBody === void 0) return record;
10330
+ const { requestBody: _req, responseBody: _res, ...meta } = record;
10331
+ return { ...meta, hasBody: true };
10332
+ }
10333
+ function readAuditRecords(auditDir, query2 = {}) {
10334
+ if (!existsSync18(auditDir)) return [];
9438
10335
  const from = typeof query2.from === "number" ? query2.from : -Infinity;
9439
10336
  const to = typeof query2.to === "number" ? query2.to : Infinity;
9440
10337
  const limit = Math.min(MAX_LIMIT, Math.max(1, Math.trunc(query2.limit ?? DEFAULT_LIMIT)));
9441
10338
  const matched = [];
9442
- for (const file of files.sort().reverse()) {
9443
- let raw;
9444
- try {
9445
- raw = readFileSync16(join8(auditDir, file), "utf8");
9446
- } catch {
9447
- continue;
9448
- }
9449
- for (const line of raw.split("\n")) {
9450
- const trimmed = line.trim();
9451
- if (!trimmed) continue;
9452
- let rec;
10339
+ for (const source of daySources(auditDir)) {
10340
+ const before = matched.length;
10341
+ forEachLineFromTail(source.path, (line) => {
10342
+ let parsed;
9453
10343
  try {
9454
- rec = JSON.parse(trimmed);
10344
+ parsed = JSON.parse(line);
9455
10345
  } catch {
9456
- continue;
10346
+ return false;
9457
10347
  }
9458
- if (!isAuditRecord(rec)) continue;
9459
- if (query2.keyId !== void 0 && rec.keyId !== query2.keyId) continue;
9460
- if (rec.ts < from || rec.ts > to) continue;
9461
- matched.push(rec);
9462
- }
10348
+ if (!isAuditRecord(parsed)) return false;
10349
+ if (query2.keyId !== void 0 && parsed.keyId !== query2.keyId) return false;
10350
+ if (query2.sessionKey !== void 0 && parsed.sessionKey !== query2.sessionKey) return false;
10351
+ if (parsed.ts < from || parsed.ts > to) return false;
10352
+ matched.push(toMetaRecord(parsed));
10353
+ return matched.length - before >= limit + OVERSCAN;
10354
+ });
10355
+ if (matched.length >= limit) break;
9463
10356
  }
9464
10357
  matched.sort((a, b) => b.ts - a.ts);
9465
10358
  return matched.slice(0, limit);
9466
10359
  }
9467
- function isAuditRecord(value) {
9468
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
9469
- const r = value;
9470
- return typeof r["id"] === "string" && typeof r["ts"] === "number" && typeof r["method"] === "string" && typeof r["path"] === "string" && typeof r["status"] === "number";
9471
- }
9472
10360
 
9473
10361
  // src/audit/AuditWriter.ts
9474
- import { appendFileSync as appendFileSync2, existsSync as existsSync17, mkdirSync as mkdirSync5, statSync as statSync4 } from "fs";
9475
- import { join as join9 } from "path";
10362
+ import { appendFileSync as appendFileSync2, existsSync as existsSync19, mkdirSync as mkdirSync5, statSync as statSync6 } from "fs";
10363
+ import { join as join12 } from "path";
9476
10364
  var AuditWriter = class {
9477
10365
  constructor(auditDir, logger, defer = (fn) => setTimeout(fn, 0)) {
9478
10366
  this.auditDir = auditDir;
@@ -9482,10 +10370,13 @@ var AuditWriter = class {
9482
10370
  auditDir;
9483
10371
  logger;
9484
10372
  defer;
9485
- dirEnsured = false;
10373
+ /** Day directories already created this process (avoids an mkdir per record). */
10374
+ ensuredDirs = /* @__PURE__ */ new Set();
10375
+ /** Per-session encoding bases. Memory-only; a miss simply writes a full snapshot. */
10376
+ bases = new SessionBaseCache();
9486
10377
  /**
9487
- * Enqueue one record for append. Returns IMMEDIATELY (fire-and-forget); the fs
9488
- * write happens on the deferred tick. A failure is logged, never thrown.
10378
+ * Enqueue one record. Returns IMMEDIATELY (fire-and-forget); every fs write and
10379
+ * the delta encoding happen on the deferred tick. A failure is logged, never thrown.
9489
10380
  */
9490
10381
  record(record) {
9491
10382
  this.defer(() => {
@@ -9498,25 +10389,41 @@ var AuditWriter = class {
9498
10389
  }
9499
10390
  });
9500
10391
  }
10392
+ /** Drop all retained encoding bases (config reload / shutdown / test teardown). */
10393
+ reset() {
10394
+ this.bases.clear();
10395
+ this.ensuredDirs.clear();
10396
+ }
9501
10397
  /**
9502
- * Append synchronously — the awaitable form tests use to assert the line landed.
9503
- * Ensures the `audit/` directory exists on first write (lazy, like the usage
9504
- * store's lazy file creation).
10398
+ * Append synchronously — the awaitable form tests use to assert a line landed.
10399
+ * Writes the metadata line first (canonical), then the body shard.
9505
10400
  */
9506
10401
  appendNow(record) {
9507
- if (!this.dirEnsured) {
9508
- mkdirSync5(this.auditDir, { recursive: true });
9509
- this.dirEnsured = true;
9510
- }
9511
- const file = join9(this.auditDir, auditFileName(record.ts));
9512
- const line = JSON.stringify(record) + "\n";
9513
- const auditBytesBefore = existsSync17(file) ? statSync4(file).size : 0;
10402
+ const dayDir = auditDayDirName(record.ts);
10403
+ const dayPath = this.ensureDir(join12(this.auditDir, dayDir));
10404
+ this.appendMeta(dayPath, record);
10405
+ this.appendBody(dayPath, dayDir, record);
10406
+ }
10407
+ /** Create a directory once per process and remember it. */
10408
+ ensureDir(path2) {
10409
+ if (!this.ensuredDirs.has(path2)) {
10410
+ mkdirSync5(path2, { recursive: true });
10411
+ this.ensuredDirs.add(path2);
10412
+ }
10413
+ return path2;
10414
+ }
10415
+ /** Write the body-free metadata line + refresh the exact-count sidecar. */
10416
+ appendMeta(dayPath, record) {
10417
+ const { requestBody: _req, responseBody: _res, ...meta } = record;
10418
+ const file = join12(dayPath, AUDIT_META_FILE);
10419
+ const line = JSON.stringify(meta) + "\n";
10420
+ const bytesBefore = existsSync19(file) ? statSync6(file).size : 0;
9514
10421
  appendFileSync2(file, line, "utf8");
9515
10422
  try {
9516
10423
  updateAuditStatsAfterAppend(
9517
10424
  file,
9518
- auditBytesBefore,
9519
- auditBytesBefore + Buffer.byteLength(line, "utf8"),
10425
+ bytesBefore,
10426
+ bytesBefore + Buffer.byteLength(line, "utf8"),
9520
10427
  record
9521
10428
  );
9522
10429
  } catch (error) {
@@ -9525,12 +10432,39 @@ var AuditWriter = class {
9525
10432
  });
9526
10433
  }
9527
10434
  }
10435
+ /**
10436
+ * Write the delta-encoded body shard for one record. A no-op when nothing was
10437
+ * captured or when the session key is missing/unsafe — in which case the body
10438
+ * is dropped rather than written to an unvalidated path.
10439
+ */
10440
+ appendBody(dayPath, dayDir, record) {
10441
+ if (record.requestBody === void 0 && record.responseBody === void 0) return;
10442
+ const sessionKey = record.sessionKey;
10443
+ if (!isSafeSessionKey(sessionKey)) {
10444
+ this.logger.warn("[AuditWriter] dropping audit body with no usable session key", {
10445
+ id: record.id
10446
+ });
10447
+ return;
10448
+ }
10449
+ try {
10450
+ const line = encodeBodyEntry(record, sessionKey, dayDir, this.bases);
10451
+ if (line === null) return;
10452
+ const bodiesPath = this.ensureDir(join12(dayPath, AUDIT_BODIES_DIR));
10453
+ appendFileSync2(join12(bodiesPath, auditBodyFileName(sessionKey)), line + "\n", "utf8");
10454
+ } catch (error) {
10455
+ this.bases.forget(sessionKey);
10456
+ this.logger.warn("[AuditWriter] failed to append audit body shard", {
10457
+ id: record.id,
10458
+ error: error instanceof Error ? error.message : String(error)
10459
+ });
10460
+ }
10461
+ }
9528
10462
  };
9529
10463
 
9530
10464
  // src/billing/BillingPublisher.ts
9531
10465
  import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync6 } from "fs";
9532
10466
  import { createHmac } from "crypto";
9533
- import { join as join10 } from "path";
10467
+ import { join as join13 } from "path";
9534
10468
  import { fetchUpstream as fetchUpstream5 } from "@omnicross/core/pipeline/upstreamFetch";
9535
10469
 
9536
10470
  // src/billing/billingFiles.ts
@@ -9601,7 +10535,7 @@ var BillingPublisher = class {
9601
10535
  */
9602
10536
  appendNow(event) {
9603
10537
  this.ensureDir();
9604
- const file = join10(this.billingDir, billingFileName(event.ts));
10538
+ const file = join13(this.billingDir, billingFileName(event.ts));
9605
10539
  appendFileSync3(file, JSON.stringify(event) + "\n", "utf8");
9606
10540
  }
9607
10541
  /**
@@ -9651,7 +10585,7 @@ var BillingPublisher = class {
9651
10585
  markDelivered(event) {
9652
10586
  try {
9653
10587
  this.ensureDir();
9654
- const file = join10(this.billingDir, deliveredFileName(event.ts));
10588
+ const file = join13(this.billingDir, deliveredFileName(event.ts));
9655
10589
  appendFileSync3(file, JSON.stringify({ id: event.id, deliveredAt: this.now() }) + "\n", "utf8");
9656
10590
  } catch (error) {
9657
10591
  this.logger.warn("[BillingPublisher] failed to append delivery marker", {
@@ -9667,14 +10601,14 @@ var BillingPublisher = class {
9667
10601
  };
9668
10602
 
9669
10603
  // src/billing/billingReader.ts
9670
- import { existsSync as existsSync18, readdirSync as readdirSync4, readFileSync as readFileSync17 } from "fs";
9671
- import { join as join11 } from "path";
10604
+ import { existsSync as existsSync20, readdirSync as readdirSync7, readFileSync as readFileSync18 } from "fs";
10605
+ import { join as join14 } from "path";
9672
10606
  function readBillingLedger(billingDir) {
9673
10607
  const view = { events: [], deliveredIds: /* @__PURE__ */ new Set() };
9674
- if (!existsSync18(billingDir)) return view;
10608
+ if (!existsSync20(billingDir)) return view;
9675
10609
  let files;
9676
10610
  try {
9677
- files = readdirSync4(billingDir);
10611
+ files = readdirSync7(billingDir);
9678
10612
  } catch {
9679
10613
  return view;
9680
10614
  }
@@ -9705,7 +10639,7 @@ function readBillingStatus(billingDir) {
9705
10639
  function parseLines(dir, file) {
9706
10640
  let raw;
9707
10641
  try {
9708
- raw = readFileSync17(join11(dir, file), "utf8");
10642
+ raw = readFileSync18(join14(dir, file), "utf8");
9709
10643
  } catch {
9710
10644
  return [];
9711
10645
  }
@@ -10209,8 +11143,10 @@ function buildDaemon(config, paths) {
10209
11143
  async (providerId, model) => await pricingEngine.getEntry(providerId, model) !== null
10210
11144
  );
10211
11145
  const keySpendTracker = new KeySpendTracker(usageEventStore);
11146
+ const usageThroughput = getSharedUsageThroughputTracker2();
10212
11147
  const usageRecorder = new UsageRecorder(usageEventStore, pricingEngine, logger, {
10213
- onRecord: (apiKeyId, costUsd, at) => keySpendTracker.add(apiKeyId, costUsd, at)
11148
+ onRecord: (apiKeyId, costUsd, at) => keySpendTracker.add(apiKeyId, costUsd, at),
11149
+ onEvent: (row, at) => usageThroughput.record(row, at)
10214
11150
  });
10215
11151
  const providerProxy = getProviderProxy({ llmConfig, apiKeyPool, usageRecorder });
10216
11152
  const routeLeaseManager = new RouteLeaseManager(
@@ -10359,6 +11295,11 @@ function buildDaemon(config, paths) {
10359
11295
  // NEVER unauth, NEVER on `/health`. Routed in `AdminServer` (not `adminApi.ts`).
10360
11296
  auditReader: (query2) => readAuditRecords(auditDir, query2),
10361
11297
  auditStatsReader: (query2) => readAuditStats(auditDir, query2),
11298
+ // audit-store-sharding: bodies live in per-session shards, so opening ONE
11299
+ // record's payload is a separate authed call that replays its delta chain.
11300
+ auditBodyReader: (query2) => readAuditBody(auditDir, query2),
11301
+ // audit-store-sharding D8: the manual counterpart to the daily pass.
11302
+ auditCompactor: () => compactAllClosedAuditDays(auditDir),
10362
11303
  // billing-event-stream: the AUTHED `GET /admin/api/billing-status` returns the
10363
11304
  // secret-free total/delivered/pending counts of the durable ledger.
10364
11305
  billingStatusReader: () => readBillingStatus(billingDir)
@@ -10417,7 +11358,7 @@ function buildDaemon(config, paths) {
10417
11358
  }
10418
11359
  function isTokensStoreReadable(tokensPath) {
10419
11360
  try {
10420
- if (!existsSync19(tokensPath)) return true;
11361
+ if (!existsSync21(tokensPath)) return true;
10421
11362
  accessSync(tokensPath, fsConstants.R_OK);
10422
11363
  return true;
10423
11364
  } catch {
@@ -10465,8 +11406,8 @@ function buildCliSpawnPlan(opts) {
10465
11406
  function resolveInPathDefault(candidate) {
10466
11407
  const segments = (process.env["PATH"] ?? "").split(delimiter2).filter(Boolean);
10467
11408
  for (const seg of segments) {
10468
- const full = join12(seg, candidate);
10469
- if (existsSync20(full)) return full;
11409
+ const full = join15(seg, candidate);
11410
+ if (existsSync22(full)) return full;
10470
11411
  }
10471
11412
  return null;
10472
11413
  }
@@ -10474,7 +11415,7 @@ async function runLaunch(argv, deps) {
10474
11415
  const sep = argv.indexOf("--");
10475
11416
  const own = sep === -1 ? argv : argv.slice(0, sep);
10476
11417
  const passthrough = sep === -1 ? [] : argv.slice(sep + 1);
10477
- const { values, positionals } = parseArgs4({
11418
+ const { values, positionals } = parseArgs5({
10478
11419
  args: own,
10479
11420
  options: {
10480
11421
  provider: { type: "string", short: "p" },
@@ -10644,12 +11585,12 @@ function spawnCliInherit(plan) {
10644
11585
  // src/commands/login.ts
10645
11586
  import { spawn as spawn3 } from "child_process";
10646
11587
  import { createInterface } from "readline";
10647
- import { parseArgs as parseArgs5 } from "util";
11588
+ import { parseArgs as parseArgs6 } from "util";
10648
11589
  import { fetchUpstream as fetchUpstream8, setUpstreamProxyResolver as setUpstreamProxyResolver2 } from "@omnicross/core/pipeline/upstreamFetch";
10649
11590
  import { claudeOAuth as claudeOAuth3, codexOAuth as codexOAuth3, geminiOAuth as geminiOAuth3 } from "@omnicross/subscriptions";
10650
11591
  var PROVIDERS2 = ["claude", "codex", "gemini"];
10651
11592
  async function runLogin(argv, deps) {
10652
- const { values, positionals } = parseArgs5({
11593
+ const { values, positionals } = parseArgs6({
10653
11594
  args: argv,
10654
11595
  options: {
10655
11596
  config: { type: "string", short: "c" },
@@ -10817,9 +11758,9 @@ function promptPaste(prompt) {
10817
11758
 
10818
11759
  // src/commands/providers.ts
10819
11760
  import { randomUUID as randomUUID7 } from "crypto";
10820
- import { parseArgs as parseArgs6 } from "util";
11761
+ import { parseArgs as parseArgs7 } from "util";
10821
11762
  async function runProviders(argv) {
10822
- const { values, positionals } = parseArgs6({
11763
+ const { values, positionals } = parseArgs7({
10823
11764
  args: argv,
10824
11765
  options: {
10825
11766
  config: { type: "string", short: "c" },
@@ -10966,10 +11907,10 @@ function providersRmKey(configPath, providerId, keyId) {
10966
11907
  }
10967
11908
 
10968
11909
  // src/commands/secrets.ts
10969
- import { existsSync as existsSync21, readFileSync as readFileSync18, writeFileSync as writeFileSync13 } from "fs";
10970
- import { parseArgs as parseArgs7 } from "util";
11910
+ import { existsSync as existsSync23, readFileSync as readFileSync19, writeFileSync as writeFileSync14 } from "fs";
11911
+ import { parseArgs as parseArgs8 } from "util";
10971
11912
  async function runSecrets(argv) {
10972
- const { values, positionals } = parseArgs7({
11913
+ const { values, positionals } = parseArgs8({
10973
11914
  args: argv,
10974
11915
  options: {
10975
11916
  config: { type: "string", short: "c" },
@@ -11039,12 +11980,12 @@ function secretsStatus(args) {
11039
11980
  reportField("admin.token", cfg.admin.token);
11040
11981
  }
11041
11982
  const tokensPath = defaultTokensPath(args.config);
11042
- if (existsSync21(tokensPath)) {
11983
+ if (existsSync23(tokensPath)) {
11043
11984
  console.info(`Secret status for ${tokensPath}:`);
11044
11985
  reportTokenFields(tokensPath);
11045
11986
  }
11046
11987
  const integrationsPath = defaultIntegrationsPath(args.config);
11047
- if (existsSync21(integrationsPath)) {
11988
+ if (existsSync23(integrationsPath)) {
11048
11989
  const state = readRawJson(integrationsPath);
11049
11990
  const key = state.gatewayKey;
11050
11991
  if (key && typeof key === "object" && !Array.isArray(key)) {
@@ -11098,8 +12039,8 @@ async function secretsRotate(args) {
11098
12039
  const integrationsPath = defaultIntegrationsPath(args.config);
11099
12040
  try {
11100
12041
  cfg = loadConfig(args.config);
11101
- if (existsSync21(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, oldBox);
11102
- if (existsSync21(integrationsPath)) {
12042
+ if (existsSync23(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, oldBox);
12043
+ if (existsSync23(integrationsPath)) {
11103
12044
  integrationsPlain = new IntegrationStateStore(integrationsPath, oldBox).load();
11104
12045
  }
11105
12046
  } finally {
@@ -11134,20 +12075,20 @@ function secretsDecrypt(args) {
11134
12075
  let tokensPlain = null;
11135
12076
  try {
11136
12077
  cfg = loadConfig(args.config);
11137
- if (existsSync21(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, box);
12078
+ if (existsSync23(tokensPath)) tokensPlain = decryptTokensFile(tokensPath, box);
11138
12079
  } finally {
11139
12080
  setSecretBox(null);
11140
12081
  }
11141
12082
  saveConfig(args.config, cfg);
11142
12083
  if (tokensPlain) {
11143
- writeFileSync13(tokensPath, JSON.stringify(tokensPlain, null, 2) + "\n", "utf8");
12084
+ writeFileSync14(tokensPath, JSON.stringify(tokensPlain, null, 2) + "\n", "utf8");
11144
12085
  }
11145
12086
  console.info(`Decrypted secrets to plaintext in ${args.config}` + tokensSuffix(args.config));
11146
12087
  }
11147
12088
  function readRawConfig(path2) {
11148
12089
  let parsed;
11149
12090
  try {
11150
- parsed = JSON.parse(readFileSync18(path2, "utf8"));
12091
+ parsed = JSON.parse(readFileSync19(path2, "utf8"));
11151
12092
  } catch {
11152
12093
  throw new Error(`secrets: cannot read or parse '${path2}'`);
11153
12094
  }
@@ -11155,7 +12096,7 @@ function readRawConfig(path2) {
11155
12096
  }
11156
12097
  function readRawJson(path2) {
11157
12098
  try {
11158
- const parsed = JSON.parse(readFileSync18(path2, "utf8"));
12099
+ const parsed = JSON.parse(readFileSync19(path2, "utf8"));
11159
12100
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
11160
12101
  return parsed;
11161
12102
  }
@@ -11165,13 +12106,13 @@ function readRawJson(path2) {
11165
12106
  }
11166
12107
  function encryptTokensFileInPlace(configPath, box) {
11167
12108
  const tokensPath = defaultTokensPath(configPath);
11168
- if (!existsSync21(tokensPath)) return;
12109
+ if (!existsSync23(tokensPath)) return;
11169
12110
  const plain = decryptTokensFile(tokensPath, box);
11170
12111
  writeTokensEncrypted(tokensPath, plain, box);
11171
12112
  }
11172
12113
  function rewriteIntegrationState(configPath, readBox, writeBox) {
11173
12114
  const path2 = defaultIntegrationsPath(configPath);
11174
- if (!existsSync21(path2)) return;
12115
+ if (!existsSync23(path2)) return;
11175
12116
  const state = new IntegrationStateStore(path2, readBox).load();
11176
12117
  new IntegrationStateStore(path2, writeBox).save(state);
11177
12118
  }
@@ -11184,7 +12125,7 @@ function writeTokensEncrypted(tokensPath, plain, box) {
11184
12125
  { updatedAt: "", ...plain },
11185
12126
  box
11186
12127
  );
11187
- writeFileSync13(tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
12128
+ writeFileSync14(tokensPath, JSON.stringify(encrypted, null, 2) + "\n", "utf8");
11188
12129
  }
11189
12130
  var TOKEN_FIELDS2 = {
11190
12131
  claude: ["accessToken", "refreshToken"],
@@ -11207,11 +12148,11 @@ function walkTokens(raw, fn) {
11207
12148
  return next;
11208
12149
  }
11209
12150
  function tokensSuffix(configPath) {
11210
- return existsSync21(defaultTokensPath(configPath)) ? " (+ tokens.json)" : "";
12151
+ return existsSync23(defaultTokensPath(configPath)) ? " (+ tokens.json)" : "";
11211
12152
  }
11212
12153
 
11213
12154
  // src/commands/start.ts
11214
- import { parseArgs as parseArgs8 } from "util";
12155
+ import { parseArgs as parseArgs9 } from "util";
11215
12156
  import { loadServerConfig as loadServerConfig3 } from "@omnicross/core/outbound-api";
11216
12157
  import { getSharedAccountHealth as getSharedAccountHealth5 } from "@omnicross/core/pipeline/SubscriptionAccountHealth";
11217
12158
  import { getSharedAccountAllowanceScheduling as getSharedAccountAllowanceScheduling6 } from "@omnicross/core/pipeline/AccountAllowanceScheduling";
@@ -11250,7 +12191,7 @@ async function seedIdentities(store, credentialStore) {
11250
12191
 
11251
12192
  // src/commands/start.ts
11252
12193
  async function runStart(argv) {
11253
- const { values } = parseArgs8({
12194
+ const { values } = parseArgs9({
11254
12195
  args: argv,
11255
12196
  options: {
11256
12197
  config: { type: "string", short: "c" },
@@ -11390,6 +12331,10 @@ Usage:
11390
12331
  omnicross secrets encrypt --config <p> Encrypt all at-rest secrets in place.
11391
12332
  omnicross secrets status --config <p> Report each secret field (no values shown).
11392
12333
  omnicross secrets rotate --config <p> --new-master-key-file <p> Re-seal under a new master key.
12334
+
12335
+ omnicross audit sessions --config <p> [--date YYYY-MM-DD] List captured body shards per session.
12336
+ omnicross audit show --config <p> --session <key> [--id <recordId>] Print reconstructed request/response bodies.
12337
+ omnicross audit compact --config <p> [--date YYYY-MM-DD] Run cross-session body compaction now.
11393
12338
  `;
11394
12339
  async function main() {
11395
12340
  const [, , subcommand, ...rest] = process.argv;
@@ -11421,6 +12366,9 @@ async function main() {
11421
12366
  case "secrets":
11422
12367
  await runSecrets(rest);
11423
12368
  return;
12369
+ case "audit":
12370
+ await runAudit(rest);
12371
+ return;
11424
12372
  case void 0:
11425
12373
  case "-h":
11426
12374
  case "--help":