crosscheck-mcp 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
9
12
  var __export = (target, all) => {
10
13
  for (var name in all)
11
14
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -28,39 +31,28 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
31
  ));
29
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
33
 
31
- // src/entrypoints/node-stdio.ts
32
- var node_stdio_exports = {};
33
- __export(node_stdio_exports, {
34
- RecordingEmitter: () => RecordingEmitter,
35
- SERVER_NAME: () => SERVER_NAME,
36
- SERVER_VERSION: () => SERVER_VERSION,
37
- connectAndServe: () => connectAndServe,
38
- createServer: () => createServer,
39
- getEventEmitter: () => getEventEmitter,
40
- setEventEmitter: () => setEventEmitter
41
- });
42
- module.exports = __toCommonJS(node_stdio_exports);
43
-
44
34
  // node_modules/tsup/assets/cjs_shims.js
45
- var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
46
- var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
47
-
48
- // src/entrypoints/node-stdio.ts
49
- var import_node_fs11 = require("fs");
50
- var import_node_path11 = __toESM(require("path"), 1);
51
- var import_node_url2 = require("url");
52
- var import_stdio2 = require("@modelcontextprotocol/sdk/server/stdio.js");
53
-
54
- // src/adapters/storage/better-sqlite3.ts
55
- var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
35
+ var getImportMetaUrl, importMetaUrl;
36
+ var init_cjs_shims = __esm({
37
+ "node_modules/tsup/assets/cjs_shims.js"() {
38
+ "use strict";
39
+ getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
40
+ importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
41
+ }
42
+ });
56
43
 
57
44
  // src/adapters/storage/migrations/0001_init.ts
58
- var m0001_init = {
59
- id: "0001_init",
60
- name: "initial schema (sessions, usage_log, claims, ...)",
61
- up: [
62
- // sessions — includes the totals columns that Python adds via ALTER.
63
- `CREATE TABLE IF NOT EXISTS sessions (
45
+ var m0001_init;
46
+ var init_init = __esm({
47
+ "src/adapters/storage/migrations/0001_init.ts"() {
48
+ "use strict";
49
+ init_cjs_shims();
50
+ m0001_init = {
51
+ id: "0001_init",
52
+ name: "initial schema (sessions, usage_log, claims, ...)",
53
+ up: [
54
+ // sessions — includes the totals columns that Python adds via ALTER.
55
+ `CREATE TABLE IF NOT EXISTS sessions (
64
56
  session_id TEXT PRIMARY KEY,
65
57
  started_at INTEGER NOT NULL,
66
58
  last_at INTEGER,
@@ -74,8 +66,8 @@ var m0001_init = {
74
66
  total_cost_usd REAL NOT NULL DEFAULT 0.0,
75
67
  total_cpu_ms INTEGER NOT NULL DEFAULT 0
76
68
  )`,
77
- // usage_log — per-call ledger.
78
- `CREATE TABLE IF NOT EXISTS usage_log (
69
+ // usage_log — per-call ledger.
70
+ `CREATE TABLE IF NOT EXISTS usage_log (
79
71
  id INTEGER PRIMARY KEY AUTOINCREMENT,
80
72
  session_id TEXT NOT NULL,
81
73
  ts INTEGER NOT NULL,
@@ -92,10 +84,10 @@ var m0001_init = {
92
84
  wall_ms INTEGER NOT NULL DEFAULT 0,
93
85
  cpu_ms INTEGER NOT NULL DEFAULT 0
94
86
  )`,
95
- `CREATE INDEX IF NOT EXISTS idx_usage_session ON usage_log(session_id)`,
96
- `CREATE INDEX IF NOT EXISTS idx_usage_provider ON usage_log(provider)`,
97
- // claims (FK to sessions, ON DELETE CASCADE).
98
- `CREATE TABLE IF NOT EXISTS claims (
87
+ `CREATE INDEX IF NOT EXISTS idx_usage_session ON usage_log(session_id)`,
88
+ `CREATE INDEX IF NOT EXISTS idx_usage_provider ON usage_log(provider)`,
89
+ // claims (FK to sessions, ON DELETE CASCADE).
90
+ `CREATE TABLE IF NOT EXISTS claims (
99
91
  id INTEGER PRIMARY KEY AUTOINCREMENT,
100
92
  session_id TEXT NOT NULL REFERENCES sessions(session_id) ON DELETE CASCADE,
101
93
  text TEXT NOT NULL,
@@ -105,10 +97,10 @@ var m0001_init = {
105
97
  kind TEXT,
106
98
  created_at INTEGER NOT NULL
107
99
  )`,
108
- `CREATE INDEX IF NOT EXISTS idx_claims_session ON claims(session_id)`,
109
- // claim_links (FK to claims). Kind enum widened in Python's
110
- // _migrate_claim_links_check; mirrored here as the CHECK clause.
111
- `CREATE TABLE IF NOT EXISTS claim_links (
100
+ `CREATE INDEX IF NOT EXISTS idx_claims_session ON claims(session_id)`,
101
+ // claim_links (FK to claims). Kind enum widened in Python's
102
+ // _migrate_claim_links_check; mirrored here as the CHECK clause.
103
+ `CREATE TABLE IF NOT EXISTS claim_links (
112
104
  id INTEGER PRIMARY KEY AUTOINCREMENT,
113
105
  src_id INTEGER NOT NULL REFERENCES claims(id) ON DELETE CASCADE,
114
106
  dst_id INTEGER NOT NULL REFERENCES claims(id) ON DELETE CASCADE,
@@ -116,18 +108,18 @@ var m0001_init = {
116
108
  created_at INTEGER NOT NULL,
117
109
  UNIQUE(src_id, dst_id, kind)
118
110
  )`,
119
- `CREATE INDEX IF NOT EXISTS idx_links_src ON claim_links(src_id)`,
120
- `CREATE INDEX IF NOT EXISTS idx_links_dst ON claim_links(dst_id)`,
121
- // provider_stats — ballots accumulator for the smart router.
122
- `CREATE TABLE IF NOT EXISTS provider_stats (
111
+ `CREATE INDEX IF NOT EXISTS idx_links_src ON claim_links(src_id)`,
112
+ `CREATE INDEX IF NOT EXISTS idx_links_dst ON claim_links(dst_id)`,
113
+ // provider_stats — ballots accumulator for the smart router.
114
+ `CREATE TABLE IF NOT EXISTS provider_stats (
123
115
  provider TEXT PRIMARY KEY,
124
116
  wins INTEGER NOT NULL DEFAULT 0,
125
117
  losses INTEGER NOT NULL DEFAULT 0,
126
118
  abstains INTEGER NOT NULL DEFAULT 0,
127
119
  last_at INTEGER
128
120
  )`,
129
- // delegations — cross-model handshake ledger.
130
- `CREATE TABLE IF NOT EXISTS delegations (
121
+ // delegations — cross-model handshake ledger.
122
+ `CREATE TABLE IF NOT EXISTS delegations (
131
123
  id INTEGER PRIMARY KEY AUTOINCREMENT,
132
124
  session_id TEXT,
133
125
  requester TEXT,
@@ -136,10 +128,10 @@ var m0001_init = {
136
128
  accepted INTEGER NOT NULL,
137
129
  created_at INTEGER NOT NULL
138
130
  )`,
139
- `CREATE INDEX IF NOT EXISTS idx_deleg_session ON delegations(session_id)`,
140
- `CREATE INDEX IF NOT EXISTS idx_deleg_req ON delegations(requester)`,
141
- // session_memory — facts / open_questions / decisions ledger.
142
- `CREATE TABLE IF NOT EXISTS session_memory (
131
+ `CREATE INDEX IF NOT EXISTS idx_deleg_session ON delegations(session_id)`,
132
+ `CREATE INDEX IF NOT EXISTS idx_deleg_req ON delegations(requester)`,
133
+ // session_memory — facts / open_questions / decisions ledger.
134
+ `CREATE TABLE IF NOT EXISTS session_memory (
143
135
  id INTEGER PRIMARY KEY AUTOINCREMENT,
144
136
  session_id TEXT NOT NULL,
145
137
  kind TEXT NOT NULL CHECK (kind IN ('fact','open_question','decision')),
@@ -151,27 +143,37 @@ var m0001_init = {
151
143
  stale_at INTEGER,
152
144
  stale_reason TEXT
153
145
  )`,
154
- `CREATE INDEX IF NOT EXISTS idx_session_memory_session ON session_memory(session_id)`,
155
- `CREATE INDEX IF NOT EXISTS idx_session_memory_kind ON session_memory(kind)`,
156
- // fetch_egress — per-session per-host byte ledger.
157
- `CREATE TABLE IF NOT EXISTS fetch_egress (
146
+ `CREATE INDEX IF NOT EXISTS idx_session_memory_session ON session_memory(session_id)`,
147
+ `CREATE INDEX IF NOT EXISTS idx_session_memory_kind ON session_memory(kind)`,
148
+ // fetch_egress — per-session per-host byte ledger.
149
+ `CREATE TABLE IF NOT EXISTS fetch_egress (
158
150
  session_id TEXT NOT NULL,
159
151
  host TEXT NOT NULL,
160
152
  total_bytes INTEGER NOT NULL DEFAULT 0,
161
153
  last_at INTEGER NOT NULL,
162
154
  PRIMARY KEY (session_id, host)
163
155
  )`,
164
- // transcripts_fts — FTS5 virtual table for the recall tool. Python uses
165
- // `tokenize='unicode61 remove_diacritics 2'`; mirrored exactly.
166
- `CREATE VIRTUAL TABLE IF NOT EXISTS transcripts_fts USING fts5(
156
+ // transcripts_fts — FTS5 virtual table for the recall tool. Python uses
157
+ // `tokenize='unicode61 remove_diacritics 2'`; mirrored exactly.
158
+ `CREATE VIRTUAL TABLE IF NOT EXISTS transcripts_fts USING fts5(
167
159
  session_id, tool, ts UNINDEXED, path UNINDEXED, content,
168
160
  tokenize='unicode61 remove_diacritics 2'
169
161
  )`
170
- ]
171
- };
162
+ ]
163
+ };
164
+ }
165
+ });
172
166
 
173
167
  // src/adapters/storage/migrations/index.ts
174
- var MIGRATIONS = [m0001_init];
168
+ var MIGRATIONS;
169
+ var init_migrations = __esm({
170
+ "src/adapters/storage/migrations/index.ts"() {
171
+ "use strict";
172
+ init_cjs_shims();
173
+ init_init();
174
+ MIGRATIONS = [m0001_init];
175
+ }
176
+ });
175
177
 
176
178
  // src/adapters/storage/schema.ts
177
179
  function canonicalSchema(reader) {
@@ -288,19 +290,18 @@ function listFks(reader, table) {
288
290
  })
289
291
  ).sort((a, b) => a.id - b.id || a.seq - b.seq);
290
292
  }
293
+ var init_schema = __esm({
294
+ "src/adapters/storage/schema.ts"() {
295
+ "use strict";
296
+ init_cjs_shims();
297
+ }
298
+ });
291
299
 
292
300
  // src/adapters/storage/better-sqlite3.ts
293
- var ALLOWED_LINK_KINDS = /* @__PURE__ */ new Set([
294
- "supports",
295
- "attacks",
296
- "derives_from",
297
- "merges_with"
298
- ]);
299
- var ALLOWED_MEMORY_KINDS = /* @__PURE__ */ new Set([
300
- "fact",
301
- "open_question",
302
- "decision"
303
- ]);
301
+ var better_sqlite3_exports = {};
302
+ __export(better_sqlite3_exports, {
303
+ openBetterSqliteStorage: () => openBetterSqliteStorage
304
+ });
304
305
  function openBetterSqliteStorage(opts) {
305
306
  const db = new import_better_sqlite3.default(opts.path);
306
307
  const wantWal = opts.wal ?? opts.path !== ":memory:";
@@ -310,101 +311,120 @@ function openBetterSqliteStorage(opts) {
310
311
  db.pragma("foreign_keys = ON");
311
312
  return new BetterSqliteStorage(db);
312
313
  }
313
- var BetterSqliteStorage = class {
314
- constructor(db) {
315
- this.db = db;
316
- }
317
- db;
318
- stmts = /* @__PURE__ */ new Map();
319
- // ------------------------------------------------------------------
320
- // Lifecycle / lifetime
321
- // ------------------------------------------------------------------
322
- async migrate() {
323
- this.db.exec(
324
- "CREATE TABLE IF NOT EXISTS schema_migrations (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)"
325
- );
326
- const existing = new Set(
327
- this.db.prepare("SELECT id FROM schema_migrations").all().map((r) => r.id)
328
- );
329
- const applied = [];
330
- const ordered = [...MIGRATIONS].sort((a, b) => a.id.localeCompare(b.id));
331
- for (const m of ordered) {
332
- if (existing.has(m.id)) continue;
333
- this.applyMigration(m);
334
- applied.push(m.id);
335
- }
336
- return { applied };
337
- }
338
- applyMigration(m) {
339
- const txn = this.db.transaction(() => {
340
- for (const stmt of m.up) this.db.exec(stmt);
341
- this.db.prepare(
342
- "INSERT INTO schema_migrations(id, applied_at) VALUES (?, ?)"
343
- ).run(m.id, Date.now());
344
- });
345
- txn();
346
- }
347
- async canonicalSchema() {
348
- const reader = {
349
- pragma: (name, arg) => arg === void 0 ? this.db.pragma(name) : this.db.pragma(`${name}('${arg.replace(/'/g, "''")}')`),
350
- list: (sql) => this.db.prepare(sql).all()
351
- };
352
- return canonicalSchema(reader);
353
- }
354
- unsafe() {
355
- return {
356
- exec: async (sql, params) => {
357
- const stmt = this.db.prepare(sql);
358
- const info = stmt.run(...params ?? []);
359
- return Number(info.changes);
360
- },
361
- query: async (sql, params) => this.db.prepare(sql).all(...params ?? [])
362
- };
363
- }
364
- async close() {
365
- this.db.close();
366
- }
367
- // ------------------------------------------------------------------
368
- // Transactions. better-sqlite3 supports nested transactions via
369
- // SAVEPOINTs automatically when the outer caller is already inside
370
- // db.transaction(). We expose a Txn that mirrors Storage's surface;
371
- // every method call inside the callback runs inside the open txn.
372
- // ------------------------------------------------------------------
373
- async txn(fn) {
374
- this.db.exec("BEGIN IMMEDIATE");
375
- try {
376
- const result = await fn(this);
377
- this.db.exec("COMMIT");
378
- return result;
379
- } catch (e) {
380
- try {
381
- this.db.exec("ROLLBACK");
382
- } catch {
314
+ var import_better_sqlite3, ALLOWED_LINK_KINDS, ALLOWED_MEMORY_KINDS, BetterSqliteStorage;
315
+ var init_better_sqlite3 = __esm({
316
+ "src/adapters/storage/better-sqlite3.ts"() {
317
+ "use strict";
318
+ init_cjs_shims();
319
+ import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
320
+ init_migrations();
321
+ init_schema();
322
+ ALLOWED_LINK_KINDS = /* @__PURE__ */ new Set([
323
+ "supports",
324
+ "attacks",
325
+ "derives_from",
326
+ "merges_with"
327
+ ]);
328
+ ALLOWED_MEMORY_KINDS = /* @__PURE__ */ new Set([
329
+ "fact",
330
+ "open_question",
331
+ "decision"
332
+ ]);
333
+ BetterSqliteStorage = class {
334
+ constructor(db) {
335
+ this.db = db;
383
336
  }
384
- throw e;
385
- }
386
- }
387
- // ==================================================================
388
- // sessions
389
- // ==================================================================
390
- async getSession(sessionId) {
391
- const row = this.cached(
392
- "session-get",
393
- "SELECT * FROM sessions WHERE session_id = ?"
394
- ).get(sessionId);
395
- return row ?? null;
396
- }
397
- async listSessions(opts) {
398
- const limit = opts?.limit ?? 100;
399
- return this.cached(
400
- "session-list",
401
- "SELECT * FROM sessions ORDER BY last_at DESC LIMIT ?"
402
- ).all(limit);
403
- }
404
- async upsertSession(row) {
405
- this.cached(
406
- "session-upsert",
407
- `INSERT INTO sessions
337
+ db;
338
+ stmts = /* @__PURE__ */ new Map();
339
+ // ------------------------------------------------------------------
340
+ // Lifecycle / lifetime
341
+ // ------------------------------------------------------------------
342
+ async migrate() {
343
+ this.db.exec(
344
+ "CREATE TABLE IF NOT EXISTS schema_migrations (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)"
345
+ );
346
+ const existing = new Set(
347
+ this.db.prepare("SELECT id FROM schema_migrations").all().map((r) => r.id)
348
+ );
349
+ const applied = [];
350
+ const ordered = [...MIGRATIONS].sort((a, b) => a.id.localeCompare(b.id));
351
+ for (const m of ordered) {
352
+ if (existing.has(m.id)) continue;
353
+ this.applyMigration(m);
354
+ applied.push(m.id);
355
+ }
356
+ return { applied };
357
+ }
358
+ applyMigration(m) {
359
+ const txn = this.db.transaction(() => {
360
+ for (const stmt of m.up) this.db.exec(stmt);
361
+ this.db.prepare(
362
+ "INSERT INTO schema_migrations(id, applied_at) VALUES (?, ?)"
363
+ ).run(m.id, Date.now());
364
+ });
365
+ txn();
366
+ }
367
+ async canonicalSchema() {
368
+ const reader = {
369
+ pragma: (name, arg) => arg === void 0 ? this.db.pragma(name) : this.db.pragma(`${name}('${arg.replace(/'/g, "''")}')`),
370
+ list: (sql) => this.db.prepare(sql).all()
371
+ };
372
+ return canonicalSchema(reader);
373
+ }
374
+ unsafe() {
375
+ return {
376
+ exec: async (sql, params) => {
377
+ const stmt = this.db.prepare(sql);
378
+ const info = stmt.run(...params ?? []);
379
+ return Number(info.changes);
380
+ },
381
+ query: async (sql, params) => this.db.prepare(sql).all(...params ?? [])
382
+ };
383
+ }
384
+ async close() {
385
+ this.db.close();
386
+ }
387
+ // ------------------------------------------------------------------
388
+ // Transactions. better-sqlite3 supports nested transactions via
389
+ // SAVEPOINTs automatically when the outer caller is already inside
390
+ // db.transaction(). We expose a Txn that mirrors Storage's surface;
391
+ // every method call inside the callback runs inside the open txn.
392
+ // ------------------------------------------------------------------
393
+ async txn(fn) {
394
+ this.db.exec("BEGIN IMMEDIATE");
395
+ try {
396
+ const result = await fn(this);
397
+ this.db.exec("COMMIT");
398
+ return result;
399
+ } catch (e) {
400
+ try {
401
+ this.db.exec("ROLLBACK");
402
+ } catch {
403
+ }
404
+ throw e;
405
+ }
406
+ }
407
+ // ==================================================================
408
+ // sessions
409
+ // ==================================================================
410
+ async getSession(sessionId) {
411
+ const row = this.cached(
412
+ "session-get",
413
+ "SELECT * FROM sessions WHERE session_id = ?"
414
+ ).get(sessionId);
415
+ return row ?? null;
416
+ }
417
+ async listSessions(opts) {
418
+ const limit = opts?.limit ?? 100;
419
+ return this.cached(
420
+ "session-list",
421
+ "SELECT * FROM sessions ORDER BY last_at DESC LIMIT ?"
422
+ ).all(limit);
423
+ }
424
+ async upsertSession(row) {
425
+ this.cached(
426
+ "session-upsert",
427
+ `INSERT INTO sessions
408
428
  (session_id, started_at, last_at, calls, wall_ms, cache_hits,
409
429
  total_prompt_tokens, total_completion_tokens, total_cached_tokens,
410
430
  total_tokens, total_cost_usd, total_cpu_ms)
@@ -420,31 +440,31 @@ var BetterSqliteStorage = class {
420
440
  total_tokens = excluded.total_tokens,
421
441
  total_cost_usd = excluded.total_cost_usd,
422
442
  total_cpu_ms = excluded.total_cpu_ms`
423
- ).run(
424
- row.session_id,
425
- row.started_at,
426
- row.last_at,
427
- row.calls,
428
- row.wall_ms,
429
- row.cache_hits,
430
- row.total_prompt_tokens,
431
- row.total_completion_tokens,
432
- row.total_cached_tokens,
433
- row.total_tokens,
434
- row.total_cost_usd,
435
- row.total_cpu_ms
436
- );
437
- }
438
- async accumulateSessionTotals(sessionId, delta) {
439
- this.cached(
440
- "session-touch",
441
- `INSERT OR IGNORE INTO sessions
443
+ ).run(
444
+ row.session_id,
445
+ row.started_at,
446
+ row.last_at,
447
+ row.calls,
448
+ row.wall_ms,
449
+ row.cache_hits,
450
+ row.total_prompt_tokens,
451
+ row.total_completion_tokens,
452
+ row.total_cached_tokens,
453
+ row.total_tokens,
454
+ row.total_cost_usd,
455
+ row.total_cpu_ms
456
+ );
457
+ }
458
+ async accumulateSessionTotals(sessionId, delta) {
459
+ this.cached(
460
+ "session-touch",
461
+ `INSERT OR IGNORE INTO sessions
442
462
  (session_id, started_at, last_at, calls, wall_ms, cache_hits)
443
463
  VALUES (?, ?, ?, 0, 0, 0)`
444
- ).run(sessionId, delta.last_at ?? 0, delta.last_at ?? null);
445
- this.cached(
446
- "session-acc",
447
- `UPDATE sessions SET
464
+ ).run(sessionId, delta.last_at ?? 0, delta.last_at ?? null);
465
+ this.cached(
466
+ "session-acc",
467
+ `UPDATE sessions SET
448
468
  calls = calls + ?,
449
469
  wall_ms = wall_ms + ?,
450
470
  cache_hits = cache_hits + ?,
@@ -456,75 +476,75 @@ var BetterSqliteStorage = class {
456
476
  total_cpu_ms = total_cpu_ms + ?,
457
477
  last_at = COALESCE(?, last_at)
458
478
  WHERE session_id = ?`
459
- ).run(
460
- delta.calls ?? 0,
461
- delta.wall_ms ?? 0,
462
- delta.cache_hits ?? 0,
463
- delta.total_prompt_tokens ?? 0,
464
- delta.total_completion_tokens ?? 0,
465
- delta.total_cached_tokens ?? 0,
466
- delta.total_tokens ?? 0,
467
- delta.total_cost_usd ?? 0,
468
- delta.total_cpu_ms ?? 0,
469
- delta.last_at ?? null,
470
- sessionId
471
- );
472
- }
473
- // ==================================================================
474
- // usage_log
475
- // ==================================================================
476
- async insertUsage(rows) {
477
- if (rows.length === 0) return;
478
- const stmt = this.cached(
479
- "usage-insert",
480
- `INSERT INTO usage_log
479
+ ).run(
480
+ delta.calls ?? 0,
481
+ delta.wall_ms ?? 0,
482
+ delta.cache_hits ?? 0,
483
+ delta.total_prompt_tokens ?? 0,
484
+ delta.total_completion_tokens ?? 0,
485
+ delta.total_cached_tokens ?? 0,
486
+ delta.total_tokens ?? 0,
487
+ delta.total_cost_usd ?? 0,
488
+ delta.total_cpu_ms ?? 0,
489
+ delta.last_at ?? null,
490
+ sessionId
491
+ );
492
+ }
493
+ // ==================================================================
494
+ // usage_log
495
+ // ==================================================================
496
+ async insertUsage(rows) {
497
+ if (rows.length === 0) return;
498
+ const stmt = this.cached(
499
+ "usage-insert",
500
+ `INSERT INTO usage_log
481
501
  (session_id, ts, tool, purpose, provider, model,
482
502
  prompt_tokens, completion_tokens, cached_tokens, total_tokens,
483
503
  cost_usd, estimated, wall_ms, cpu_ms)
484
504
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
485
- );
486
- const tx = this.db.transaction((items) => {
487
- for (const r of items) {
488
- stmt.run(
489
- r.session_id,
490
- r.ts,
491
- r.tool,
492
- r.purpose,
493
- r.provider,
494
- r.model,
495
- r.prompt_tokens ?? 0,
496
- r.completion_tokens ?? 0,
497
- r.cached_tokens ?? 0,
498
- r.total_tokens ?? 0,
499
- r.cost_usd ?? 0,
500
- r.estimated ?? 0,
501
- r.wall_ms ?? 0,
502
- r.cpu_ms ?? 0
503
505
  );
506
+ const tx = this.db.transaction((items) => {
507
+ for (const r of items) {
508
+ stmt.run(
509
+ r.session_id,
510
+ r.ts,
511
+ r.tool,
512
+ r.purpose,
513
+ r.provider,
514
+ r.model,
515
+ r.prompt_tokens ?? 0,
516
+ r.completion_tokens ?? 0,
517
+ r.cached_tokens ?? 0,
518
+ r.total_tokens ?? 0,
519
+ r.cost_usd ?? 0,
520
+ r.estimated ?? 0,
521
+ r.wall_ms ?? 0,
522
+ r.cpu_ms ?? 0
523
+ );
524
+ }
525
+ });
526
+ tx(rows);
504
527
  }
505
- });
506
- tx(rows);
507
- }
508
- async listUsageForSession(sessionId, opts) {
509
- const where = ["session_id = ?"];
510
- const params = [sessionId];
511
- if (opts?.only_purpose && opts.only_purpose.length > 0) {
512
- where.push(`purpose IN (${opts.only_purpose.map(() => "?").join(",")})`);
513
- params.push(...opts.only_purpose);
514
- }
515
- if (opts?.only_provider && opts.only_provider.length > 0) {
516
- where.push(`provider IN (${opts.only_provider.map(() => "?").join(",")})`);
517
- params.push(...opts.only_provider);
518
- }
519
- const limit = opts?.limit ?? 1e3;
520
- params.push(limit);
521
- const sql = `SELECT * FROM usage_log WHERE ${where.join(" AND ")} ORDER BY id ASC LIMIT ?`;
522
- return this.db.prepare(sql).all(...params);
523
- }
524
- async listUsageGroupedByPurpose(sessionId) {
525
- return this.cached(
526
- "usage-grp-purpose",
527
- `SELECT purpose,
528
+ async listUsageForSession(sessionId, opts) {
529
+ const where = ["session_id = ?"];
530
+ const params = [sessionId];
531
+ if (opts?.only_purpose && opts.only_purpose.length > 0) {
532
+ where.push(`purpose IN (${opts.only_purpose.map(() => "?").join(",")})`);
533
+ params.push(...opts.only_purpose);
534
+ }
535
+ if (opts?.only_provider && opts.only_provider.length > 0) {
536
+ where.push(`provider IN (${opts.only_provider.map(() => "?").join(",")})`);
537
+ params.push(...opts.only_provider);
538
+ }
539
+ const limit = opts?.limit ?? 1e3;
540
+ params.push(limit);
541
+ const sql = `SELECT * FROM usage_log WHERE ${where.join(" AND ")} ORDER BY id ASC LIMIT ?`;
542
+ return this.db.prepare(sql).all(...params);
543
+ }
544
+ async listUsageGroupedByPurpose(sessionId) {
545
+ return this.cached(
546
+ "usage-grp-purpose",
547
+ `SELECT purpose,
528
548
  COUNT(*) AS calls,
529
549
  COALESCE(SUM(prompt_tokens), 0) AS prompt_tokens,
530
550
  COALESCE(SUM(completion_tokens), 0) AS completion_tokens,
@@ -536,13 +556,13 @@ var BetterSqliteStorage = class {
536
556
  WHERE session_id = ?
537
557
  GROUP BY purpose
538
558
  ORDER BY purpose`
539
- ).all(sessionId);
540
- }
541
- async listUsageGroupedByProvider(purpose) {
542
- if (purpose !== void 0) {
543
- return this.cached(
544
- "usage-grp-provider-p",
545
- `SELECT provider,
559
+ ).all(sessionId);
560
+ }
561
+ async listUsageGroupedByProvider(purpose) {
562
+ if (purpose !== void 0) {
563
+ return this.cached(
564
+ "usage-grp-provider-p",
565
+ `SELECT provider,
546
566
  COUNT(*) AS calls,
547
567
  COALESCE(SUM(total_tokens), 0) AS total_tokens,
548
568
  COALESCE(SUM(cost_usd), 0) AS cost_usd,
@@ -551,11 +571,11 @@ var BetterSqliteStorage = class {
551
571
  WHERE purpose = ?
552
572
  GROUP BY provider
553
573
  ORDER BY provider`
554
- ).all(purpose);
555
- }
556
- return this.cached(
557
- "usage-grp-provider",
558
- `SELECT provider,
574
+ ).all(purpose);
575
+ }
576
+ return this.cached(
577
+ "usage-grp-provider",
578
+ `SELECT provider,
559
579
  COUNT(*) AS calls,
560
580
  COALESCE(SUM(total_tokens), 0) AS total_tokens,
561
581
  COALESCE(SUM(cost_usd), 0) AS cost_usd,
@@ -563,13 +583,13 @@ var BetterSqliteStorage = class {
563
583
  FROM usage_log
564
584
  GROUP BY provider
565
585
  ORDER BY provider`
566
- ).all();
567
- }
568
- async listRouterStatsByPurpose(purpose, sinceMs) {
569
- if (sinceMs !== void 0) {
570
- return this.cached(
571
- "router-stats-purpose-since",
572
- `SELECT LOWER(provider) AS provider,
586
+ ).all();
587
+ }
588
+ async listRouterStatsByPurpose(purpose, sinceMs) {
589
+ if (sinceMs !== void 0) {
590
+ return this.cached(
591
+ "router-stats-purpose-since",
592
+ `SELECT LOWER(provider) AS provider,
573
593
  COUNT(*) AS calls,
574
594
  COALESCE(SUM(total_tokens), 0) AS tokens_sum,
575
595
  COALESCE(AVG(total_tokens), 0) AS avg_total_tokens,
@@ -579,11 +599,11 @@ var BetterSqliteStorage = class {
579
599
  WHERE purpose = ? AND ts >= ? AND provider IS NOT NULL
580
600
  GROUP BY LOWER(provider)
581
601
  ORDER BY provider`
582
- ).all(purpose, sinceMs);
583
- }
584
- return this.cached(
585
- "router-stats-purpose",
586
- `SELECT LOWER(provider) AS provider,
602
+ ).all(purpose, sinceMs);
603
+ }
604
+ return this.cached(
605
+ "router-stats-purpose",
606
+ `SELECT LOWER(provider) AS provider,
587
607
  COUNT(*) AS calls,
588
608
  COALESCE(SUM(total_tokens), 0) AS tokens_sum,
589
609
  COALESCE(AVG(total_tokens), 0) AS avg_total_tokens,
@@ -593,321 +613,345 @@ var BetterSqliteStorage = class {
593
613
  WHERE purpose = ? AND provider IS NOT NULL
594
614
  GROUP BY LOWER(provider)
595
615
  ORDER BY provider`
596
- ).all(purpose);
597
- }
598
- // ==================================================================
599
- // claims
600
- // ==================================================================
601
- async insertClaim(claim) {
602
- const info = this.cached(
603
- "claim-insert",
604
- `INSERT INTO claims
616
+ ).all(purpose);
617
+ }
618
+ // ==================================================================
619
+ // claims
620
+ // ==================================================================
621
+ async insertClaim(claim) {
622
+ const info = this.cached(
623
+ "claim-insert",
624
+ `INSERT INTO claims
605
625
  (session_id, text, provider, confidence, citations_json, kind, created_at)
606
626
  VALUES (?, ?, ?, ?, ?, ?, ?)`
607
- ).run(
608
- claim.session_id,
609
- claim.text,
610
- claim.provider ?? null,
611
- claim.confidence ?? null,
612
- claim.citations ? JSON.stringify(claim.citations) : null,
613
- claim.kind ?? null,
614
- Date.now()
615
- );
616
- return Number(info.lastInsertRowid);
617
- }
618
- async insertClaimLink(srcId, dstId, kind) {
619
- if (!ALLOWED_LINK_KINDS.has(kind)) {
620
- throw new RangeError(`invalid claim_link kind: ${kind}`);
621
- }
622
- this.cached(
623
- "claim-link-insert",
624
- `INSERT OR IGNORE INTO claim_links (src_id, dst_id, kind, created_at)
627
+ ).run(
628
+ claim.session_id,
629
+ claim.text,
630
+ claim.provider ?? null,
631
+ claim.confidence ?? null,
632
+ claim.citations ? JSON.stringify(claim.citations) : null,
633
+ claim.kind ?? null,
634
+ Date.now()
635
+ );
636
+ return Number(info.lastInsertRowid);
637
+ }
638
+ async insertClaimLink(srcId, dstId, kind) {
639
+ if (!ALLOWED_LINK_KINDS.has(kind)) {
640
+ throw new RangeError(`invalid claim_link kind: ${kind}`);
641
+ }
642
+ this.cached(
643
+ "claim-link-insert",
644
+ `INSERT OR IGNORE INTO claim_links (src_id, dst_id, kind, created_at)
625
645
  VALUES (?, ?, ?, ?)`
626
- ).run(srcId, dstId, kind, Date.now());
627
- }
628
- async listClaimsForSession(sessionId) {
629
- return this.cached(
630
- "claim-list-session",
631
- "SELECT * FROM claims WHERE session_id = ? ORDER BY id"
632
- ).all(sessionId);
633
- }
634
- async getClaim(claimId) {
635
- const row = this.cached(
636
- "claim-get",
637
- "SELECT * FROM claims WHERE id = ?"
638
- ).get(claimId);
639
- return row ?? null;
640
- }
641
- async listClaimLinksForSession(sessionId) {
642
- return this.cached(
643
- "claim-link-list-session",
644
- `SELECT cl.*
646
+ ).run(srcId, dstId, kind, Date.now());
647
+ }
648
+ async listClaimsForSession(sessionId) {
649
+ return this.cached(
650
+ "claim-list-session",
651
+ "SELECT * FROM claims WHERE session_id = ? ORDER BY id"
652
+ ).all(sessionId);
653
+ }
654
+ async getClaim(claimId) {
655
+ const row = this.cached(
656
+ "claim-get",
657
+ "SELECT * FROM claims WHERE id = ?"
658
+ ).get(claimId);
659
+ return row ?? null;
660
+ }
661
+ async listClaimLinksForSession(sessionId) {
662
+ return this.cached(
663
+ "claim-link-list-session",
664
+ `SELECT cl.*
645
665
  FROM claim_links cl
646
666
  JOIN claims c ON c.id = cl.src_id OR c.id = cl.dst_id
647
667
  WHERE c.session_id = ?
648
668
  GROUP BY cl.id
649
669
  ORDER BY cl.id`
650
- ).all(sessionId);
651
- }
652
- async deleteClaimsForSession(sessionId) {
653
- const info = this.cached(
654
- "claim-delete-session",
655
- "DELETE FROM claims WHERE session_id = ?"
656
- ).run(sessionId);
657
- return Number(info.changes);
658
- }
659
- // ==================================================================
660
- // provider_stats
661
- // ==================================================================
662
- async listProviderStats(opts) {
663
- const limit = opts?.limit ?? 100;
664
- return this.cached(
665
- "provider-stats-list",
666
- "SELECT * FROM provider_stats ORDER BY (wins + losses + abstains) DESC, provider ASC LIMIT ?"
667
- ).all(limit);
668
- }
669
- async getProviderStats(provider) {
670
- const row = this.cached(
671
- "provider-stats-get",
672
- "SELECT * FROM provider_stats WHERE provider = ?"
673
- ).get(provider);
674
- return row ?? null;
675
- }
676
- async bumpProviderBallot(provider, ballot, at) {
677
- const column = ballot === "agree" ? "wins" : ballot === "disagree" ? "losses" : "abstains";
678
- this.db.prepare(
679
- `INSERT INTO provider_stats(provider, wins, losses, abstains, last_at)
670
+ ).all(sessionId);
671
+ }
672
+ async deleteClaimsForSession(sessionId) {
673
+ const info = this.cached(
674
+ "claim-delete-session",
675
+ "DELETE FROM claims WHERE session_id = ?"
676
+ ).run(sessionId);
677
+ return Number(info.changes);
678
+ }
679
+ // ==================================================================
680
+ // provider_stats
681
+ // ==================================================================
682
+ async listProviderStats(opts) {
683
+ const limit = opts?.limit ?? 100;
684
+ return this.cached(
685
+ "provider-stats-list",
686
+ "SELECT * FROM provider_stats ORDER BY (wins + losses + abstains) DESC, provider ASC LIMIT ?"
687
+ ).all(limit);
688
+ }
689
+ async getProviderStats(provider) {
690
+ const row = this.cached(
691
+ "provider-stats-get",
692
+ "SELECT * FROM provider_stats WHERE provider = ?"
693
+ ).get(provider);
694
+ return row ?? null;
695
+ }
696
+ async bumpProviderBallot(provider, ballot, at) {
697
+ const column = ballot === "agree" ? "wins" : ballot === "disagree" ? "losses" : "abstains";
698
+ this.db.prepare(
699
+ `INSERT INTO provider_stats(provider, wins, losses, abstains, last_at)
680
700
  VALUES (?, 0, 0, 0, ?)
681
701
  ON CONFLICT(provider) DO NOTHING`
682
- ).run(provider, at);
683
- this.db.prepare(
684
- `UPDATE provider_stats SET ${column} = ${column} + 1, last_at = ? WHERE provider = ?`
685
- ).run(at, provider);
686
- }
687
- // ==================================================================
688
- // delegations
689
- // ==================================================================
690
- async insertDelegation(row) {
691
- this.cached(
692
- "delegation-insert",
693
- `INSERT INTO delegations
702
+ ).run(provider, at);
703
+ this.db.prepare(
704
+ `UPDATE provider_stats SET ${column} = ${column} + 1, last_at = ? WHERE provider = ?`
705
+ ).run(at, provider);
706
+ }
707
+ // ==================================================================
708
+ // delegations
709
+ // ==================================================================
710
+ async insertDelegation(row) {
711
+ this.cached(
712
+ "delegation-insert",
713
+ `INSERT INTO delegations
694
714
  (session_id, requester, tool_call, via, accepted, created_at)
695
715
  VALUES (?, ?, ?, ?, ?, ?)`
696
- ).run(
697
- row.session_id,
698
- row.requester,
699
- row.tool_call,
700
- row.via,
701
- row.accepted,
702
- row.created_at
703
- );
704
- }
705
- async listDelegationsForSession(sessionId) {
706
- return this.cached(
707
- "delegation-list-session",
708
- "SELECT * FROM delegations WHERE session_id = ? ORDER BY id"
709
- ).all(sessionId);
710
- }
711
- async countDelegationsByRequester(requester) {
712
- const r = this.cached(
713
- "delegation-count-req",
714
- "SELECT COUNT(*) AS n FROM delegations WHERE requester = ?"
715
- ).get(requester);
716
- return Number(r.n);
717
- }
718
- async countDelegationsBySession(sessionId) {
719
- const r = this.cached(
720
- "delegation-count-session",
721
- "SELECT COUNT(*) AS n FROM delegations WHERE session_id = ?"
722
- ).get(sessionId);
723
- return Number(r.n);
724
- }
725
- async countAcceptedDelegationsBySession(sessionId) {
726
- const r = this.cached(
727
- "delegation-count-accepted-session",
728
- "SELECT COUNT(*) AS n FROM delegations WHERE session_id = ? AND accepted = 1"
729
- ).get(sessionId);
730
- return Number(r.n);
731
- }
732
- async countAcceptedDelegationsByRequester(requester) {
733
- const r = this.cached(
734
- "delegation-count-accepted-requester",
735
- "SELECT COUNT(*) AS n FROM delegations WHERE requester = ? AND accepted = 1"
736
- ).get(requester);
737
- return Number(r.n);
738
- }
739
- async listDelegationAggregatesByRequester() {
740
- const rows = this.cached(
741
- "delegation-agg-requester",
742
- "SELECT requester, accepted, COUNT(*) AS n FROM delegations WHERE requester IS NOT NULL GROUP BY requester, accepted"
743
- ).all();
744
- return rows.map((r) => ({
745
- requester: String(r.requester),
746
- accepted: r.accepted === 1 ? 1 : 0,
747
- count: Number(r.n)
748
- }));
749
- }
750
- // ==================================================================
751
- // global counts (scoreboard / observability)
752
- // ==================================================================
753
- async countScoreboardTotals() {
754
- const countOne = (table) => {
755
- try {
756
- const r = this.db.prepare(`SELECT COUNT(*) AS n FROM ${table}`).get();
757
- return r ? Number(r.n) : 0;
758
- } catch {
759
- return 0;
716
+ ).run(
717
+ row.session_id,
718
+ row.requester,
719
+ row.tool_call,
720
+ row.via,
721
+ row.accepted,
722
+ row.created_at
723
+ );
760
724
  }
761
- };
762
- return {
763
- sessions: countOne("sessions"),
764
- claims: countOne("claims"),
765
- claim_links: countOne("claim_links"),
766
- delegations: countOne("delegations")
767
- };
768
- }
769
- // ==================================================================
770
- // session_memory
771
- // ==================================================================
772
- async insertSessionMemory(row) {
773
- if (!ALLOWED_MEMORY_KINDS.has(row.kind)) {
774
- throw new RangeError(`invalid session_memory kind: ${row.kind}`);
775
- }
776
- const info = this.cached(
777
- "memory-insert",
778
- `INSERT INTO session_memory
725
+ async listDelegationsForSession(sessionId) {
726
+ return this.cached(
727
+ "delegation-list-session",
728
+ "SELECT * FROM delegations WHERE session_id = ? ORDER BY id"
729
+ ).all(sessionId);
730
+ }
731
+ async countDelegationsByRequester(requester) {
732
+ const r = this.cached(
733
+ "delegation-count-req",
734
+ "SELECT COUNT(*) AS n FROM delegations WHERE requester = ?"
735
+ ).get(requester);
736
+ return Number(r.n);
737
+ }
738
+ async countDelegationsBySession(sessionId) {
739
+ const r = this.cached(
740
+ "delegation-count-session",
741
+ "SELECT COUNT(*) AS n FROM delegations WHERE session_id = ?"
742
+ ).get(sessionId);
743
+ return Number(r.n);
744
+ }
745
+ async countAcceptedDelegationsBySession(sessionId) {
746
+ const r = this.cached(
747
+ "delegation-count-accepted-session",
748
+ "SELECT COUNT(*) AS n FROM delegations WHERE session_id = ? AND accepted = 1"
749
+ ).get(sessionId);
750
+ return Number(r.n);
751
+ }
752
+ async countAcceptedDelegationsByRequester(requester) {
753
+ const r = this.cached(
754
+ "delegation-count-accepted-requester",
755
+ "SELECT COUNT(*) AS n FROM delegations WHERE requester = ? AND accepted = 1"
756
+ ).get(requester);
757
+ return Number(r.n);
758
+ }
759
+ async listDelegationAggregatesByRequester() {
760
+ const rows = this.cached(
761
+ "delegation-agg-requester",
762
+ "SELECT requester, accepted, COUNT(*) AS n FROM delegations WHERE requester IS NOT NULL GROUP BY requester, accepted"
763
+ ).all();
764
+ return rows.map((r) => ({
765
+ requester: String(r.requester),
766
+ accepted: r.accepted === 1 ? 1 : 0,
767
+ count: Number(r.n)
768
+ }));
769
+ }
770
+ // ==================================================================
771
+ // global counts (scoreboard / observability)
772
+ // ==================================================================
773
+ async countScoreboardTotals() {
774
+ const countOne = (table) => {
775
+ try {
776
+ const r = this.db.prepare(`SELECT COUNT(*) AS n FROM ${table}`).get();
777
+ return r ? Number(r.n) : 0;
778
+ } catch {
779
+ return 0;
780
+ }
781
+ };
782
+ return {
783
+ sessions: countOne("sessions"),
784
+ claims: countOne("claims"),
785
+ claim_links: countOne("claim_links"),
786
+ delegations: countOne("delegations")
787
+ };
788
+ }
789
+ // ==================================================================
790
+ // session_memory
791
+ // ==================================================================
792
+ async insertSessionMemory(row) {
793
+ if (!ALLOWED_MEMORY_KINDS.has(row.kind)) {
794
+ throw new RangeError(`invalid session_memory kind: ${row.kind}`);
795
+ }
796
+ const info = this.cached(
797
+ "memory-insert",
798
+ `INSERT INTO session_memory
779
799
  (session_id, kind, content, source_tool, source_call_id, confidence, created_at)
780
800
  VALUES (?, ?, ?, ?, ?, ?, ?)`
781
- ).run(
782
- row.session_id,
783
- row.kind,
784
- row.content,
785
- row.source_tool ?? null,
786
- row.source_call_id ?? null,
787
- row.confidence ?? null,
788
- row.created_at
789
- );
790
- return Number(info.lastInsertRowid);
791
- }
792
- async listSessionMemory(sessionId, opts) {
793
- const where = ["session_id = ?"];
794
- const params = [sessionId];
795
- if (!opts?.include_stale) where.push("stale_at IS NULL");
796
- if (opts?.kinds && opts.kinds.length > 0) {
797
- where.push(`kind IN (${opts.kinds.map(() => "?").join(",")})`);
798
- params.push(...opts.kinds);
799
- }
800
- const limit = opts?.limit ?? 50;
801
- params.push(limit);
802
- const sql = `SELECT * FROM session_memory WHERE ${where.join(" AND ")} ORDER BY id DESC LIMIT ?`;
803
- return this.db.prepare(sql).all(...params);
804
- }
805
- async markSessionMemoryStale(sessionId, at, opts) {
806
- const where = ["session_id = ?", "stale_at IS NULL"];
807
- const params = [at, opts?.reason ?? "manual", sessionId];
808
- if (opts?.ids && opts.ids.length > 0) {
809
- where.push(`id IN (${opts.ids.map(() => "?").join(",")})`);
810
- params.push(...opts.ids);
811
- }
812
- if (opts?.kinds && opts.kinds.length > 0) {
813
- where.push(`kind IN (${opts.kinds.map(() => "?").join(",")})`);
814
- params.push(...opts.kinds);
815
- }
816
- const sql = `UPDATE session_memory SET stale_at = ?, stale_reason = ? WHERE ${where.join(" AND ")}`;
817
- const info = this.db.prepare(sql).run(...params);
818
- return Number(info.changes);
819
- }
820
- async clearSessionMemory(sessionId) {
821
- const info = this.cached(
822
- "memory-clear",
823
- "DELETE FROM session_memory WHERE session_id = ?"
824
- ).run(sessionId);
825
- return Number(info.changes);
826
- }
827
- // ==================================================================
828
- // fetch_egress
829
- // ==================================================================
830
- async recordFetchEgress(sessionId, host, bytes, at) {
831
- this.cached(
832
- "fetch-egress-upsert",
833
- `INSERT INTO fetch_egress (session_id, host, total_bytes, last_at)
801
+ ).run(
802
+ row.session_id,
803
+ row.kind,
804
+ row.content,
805
+ row.source_tool ?? null,
806
+ row.source_call_id ?? null,
807
+ row.confidence ?? null,
808
+ row.created_at
809
+ );
810
+ return Number(info.lastInsertRowid);
811
+ }
812
+ async listSessionMemory(sessionId, opts) {
813
+ const where = ["session_id = ?"];
814
+ const params = [sessionId];
815
+ if (!opts?.include_stale) where.push("stale_at IS NULL");
816
+ if (opts?.kinds && opts.kinds.length > 0) {
817
+ where.push(`kind IN (${opts.kinds.map(() => "?").join(",")})`);
818
+ params.push(...opts.kinds);
819
+ }
820
+ const limit = opts?.limit ?? 50;
821
+ params.push(limit);
822
+ const sql = `SELECT * FROM session_memory WHERE ${where.join(" AND ")} ORDER BY id DESC LIMIT ?`;
823
+ return this.db.prepare(sql).all(...params);
824
+ }
825
+ async markSessionMemoryStale(sessionId, at, opts) {
826
+ const where = ["session_id = ?", "stale_at IS NULL"];
827
+ const params = [at, opts?.reason ?? "manual", sessionId];
828
+ if (opts?.ids && opts.ids.length > 0) {
829
+ where.push(`id IN (${opts.ids.map(() => "?").join(",")})`);
830
+ params.push(...opts.ids);
831
+ }
832
+ if (opts?.kinds && opts.kinds.length > 0) {
833
+ where.push(`kind IN (${opts.kinds.map(() => "?").join(",")})`);
834
+ params.push(...opts.kinds);
835
+ }
836
+ const sql = `UPDATE session_memory SET stale_at = ?, stale_reason = ? WHERE ${where.join(" AND ")}`;
837
+ const info = this.db.prepare(sql).run(...params);
838
+ return Number(info.changes);
839
+ }
840
+ async clearSessionMemory(sessionId) {
841
+ const info = this.cached(
842
+ "memory-clear",
843
+ "DELETE FROM session_memory WHERE session_id = ?"
844
+ ).run(sessionId);
845
+ return Number(info.changes);
846
+ }
847
+ // ==================================================================
848
+ // fetch_egress
849
+ // ==================================================================
850
+ async recordFetchEgress(sessionId, host, bytes, at) {
851
+ this.cached(
852
+ "fetch-egress-upsert",
853
+ `INSERT INTO fetch_egress (session_id, host, total_bytes, last_at)
834
854
  VALUES (?, ?, ?, ?)
835
855
  ON CONFLICT(session_id, host) DO UPDATE SET
836
856
  total_bytes = total_bytes + excluded.total_bytes,
837
857
  last_at = excluded.last_at`
838
- ).run(sessionId, host, bytes, at);
839
- }
840
- async getFetchEgressTotals(sessionId) {
841
- const r = this.cached(
842
- "fetch-egress-totals",
843
- "SELECT COALESCE(SUM(total_bytes), 0) AS total_bytes, COUNT(DISTINCT host) AS unique_hosts FROM fetch_egress WHERE session_id = ?"
844
- ).get(sessionId);
845
- return {
846
- total_bytes: Number(r.total_bytes ?? 0),
847
- unique_hosts: Number(r.unique_hosts ?? 0)
848
- };
849
- }
850
- async hasFetchEgressHost(sessionId, host) {
851
- const r = this.cached(
852
- "fetch-egress-has-host",
853
- "SELECT 1 AS one FROM fetch_egress WHERE session_id = ? AND host = ? LIMIT 1"
854
- ).get(sessionId, host);
855
- return r !== void 0;
856
- }
857
- // ==================================================================
858
- // transcripts_fts — the encapsulated FTS5 surface.
859
- // ==================================================================
860
- async indexTranscript(row) {
861
- this.cached(
862
- "fts-insert",
863
- `INSERT INTO transcripts_fts (session_id, tool, ts, path, content)
858
+ ).run(sessionId, host, bytes, at);
859
+ }
860
+ async getFetchEgressTotals(sessionId) {
861
+ const r = this.cached(
862
+ "fetch-egress-totals",
863
+ "SELECT COALESCE(SUM(total_bytes), 0) AS total_bytes, COUNT(DISTINCT host) AS unique_hosts FROM fetch_egress WHERE session_id = ?"
864
+ ).get(sessionId);
865
+ return {
866
+ total_bytes: Number(r.total_bytes ?? 0),
867
+ unique_hosts: Number(r.unique_hosts ?? 0)
868
+ };
869
+ }
870
+ async hasFetchEgressHost(sessionId, host) {
871
+ const r = this.cached(
872
+ "fetch-egress-has-host",
873
+ "SELECT 1 AS one FROM fetch_egress WHERE session_id = ? AND host = ? LIMIT 1"
874
+ ).get(sessionId, host);
875
+ return r !== void 0;
876
+ }
877
+ // ==================================================================
878
+ // transcripts_fts — the encapsulated FTS5 surface.
879
+ // ==================================================================
880
+ async indexTranscript(row) {
881
+ this.cached(
882
+ "fts-insert",
883
+ `INSERT INTO transcripts_fts (session_id, tool, ts, path, content)
864
884
  VALUES (?, ?, ?, ?, ?)`
865
- ).run(row.session_id ?? "", row.tool, String(row.ts), row.path, row.content);
866
- }
867
- async recallSearch(query, k, opts) {
868
- const where = ["transcripts_fts MATCH ?"];
869
- const params = [query];
870
- if (opts?.session_id) {
871
- where.push("session_id = ?");
872
- params.push(opts.session_id);
873
- }
874
- if (opts?.tool) {
875
- where.push("tool = ?");
876
- params.push(opts.tool);
877
- }
878
- if (opts?.since_ms !== void 0) {
879
- where.push("CAST(ts AS INTEGER) >= ?");
880
- params.push(opts.since_ms);
881
- }
882
- params.push(k);
883
- const sql = `SELECT path, session_id, tool, ts, snippet(transcripts_fts, -1, '[[', ']]', '...', 16) AS snippet, bm25(transcripts_fts) AS rank FROM transcripts_fts WHERE ${where.join(" AND ")} ORDER BY rank LIMIT ?`;
884
- const rows = this.db.prepare(sql).all(...params);
885
- return rows.map((r) => ({
886
- path: r.path,
887
- session_id: r.session_id ?? null,
888
- tool: r.tool ?? null,
889
- ts: Number(r.ts),
890
- snippet: r.snippet,
891
- score: 1 / (1 + Math.max(0, r.rank ?? 0))
892
- }));
893
- }
894
- // ------------------------------------------------------------------
895
- // Prepared-statement cache. better-sqlite3 prepares statements lazily
896
- // and caches them internally, but the JS-side reference still costs
897
- // a hashmap lookup on every call. Keeping our own map by key lets
898
- // hot-path queries hit a single Map.get().
899
- // ------------------------------------------------------------------
900
- cached(key, sql) {
901
- let s = this.stmts.get(key);
902
- if (!s) {
903
- s = this.db.prepare(sql);
904
- this.stmts.set(key, s);
905
- }
906
- return s;
885
+ ).run(row.session_id ?? "", row.tool, String(row.ts), row.path, row.content);
886
+ }
887
+ async recallSearch(query, k, opts) {
888
+ const where = ["transcripts_fts MATCH ?"];
889
+ const params = [query];
890
+ if (opts?.session_id) {
891
+ where.push("session_id = ?");
892
+ params.push(opts.session_id);
893
+ }
894
+ if (opts?.tool) {
895
+ where.push("tool = ?");
896
+ params.push(opts.tool);
897
+ }
898
+ if (opts?.since_ms !== void 0) {
899
+ where.push("CAST(ts AS INTEGER) >= ?");
900
+ params.push(opts.since_ms);
901
+ }
902
+ params.push(k);
903
+ const sql = `SELECT path, session_id, tool, ts, snippet(transcripts_fts, -1, '[[', ']]', '...', 16) AS snippet, bm25(transcripts_fts) AS rank FROM transcripts_fts WHERE ${where.join(" AND ")} ORDER BY rank LIMIT ?`;
904
+ const rows = this.db.prepare(sql).all(...params);
905
+ return rows.map((r) => ({
906
+ path: r.path,
907
+ session_id: r.session_id ?? null,
908
+ tool: r.tool ?? null,
909
+ ts: Number(r.ts),
910
+ snippet: r.snippet,
911
+ score: 1 / (1 + Math.max(0, r.rank ?? 0))
912
+ }));
913
+ }
914
+ // ------------------------------------------------------------------
915
+ // Prepared-statement cache. better-sqlite3 prepares statements lazily
916
+ // and caches them internally, but the JS-side reference still costs
917
+ // a hashmap lookup on every call. Keeping our own map by key lets
918
+ // hot-path queries hit a single Map.get().
919
+ // ------------------------------------------------------------------
920
+ cached(key, sql) {
921
+ let s = this.stmts.get(key);
922
+ if (!s) {
923
+ s = this.db.prepare(sql);
924
+ this.stmts.set(key, s);
925
+ }
926
+ return s;
927
+ }
928
+ };
907
929
  }
908
- };
930
+ });
931
+
932
+ // src/entrypoints/node-stdio.ts
933
+ var node_stdio_exports = {};
934
+ __export(node_stdio_exports, {
935
+ RecordingEmitter: () => RecordingEmitter,
936
+ SERVER_NAME: () => SERVER_NAME,
937
+ SERVER_VERSION: () => SERVER_VERSION,
938
+ connectAndServe: () => connectAndServe,
939
+ createServer: () => createServer,
940
+ getEventEmitter: () => getEventEmitter,
941
+ setEventEmitter: () => setEventEmitter
942
+ });
943
+ module.exports = __toCommonJS(node_stdio_exports);
944
+ init_cjs_shims();
945
+ var import_node_fs11 = require("fs");
946
+ var import_node_path11 = __toESM(require("path"), 1);
947
+ var import_node_url2 = require("url");
948
+ var import_stdio2 = require("@modelcontextprotocol/sdk/server/stdio.js");
949
+
950
+ // src/bridge/index.ts
951
+ init_cjs_shims();
909
952
 
910
953
  // src/bridge/python-bridge.ts
954
+ init_cjs_shims();
911
955
  var import_node_path = __toESM(require("path"), 1);
912
956
  var import_node_url = require("url");
913
957
  var import_client = require("@modelcontextprotocol/sdk/client/index.js");
@@ -1007,6 +1051,7 @@ async function fetchToolNames(client, timeoutMs) {
1007
1051
  }
1008
1052
 
1009
1053
  // src/bridge/proxy-tools.ts
1054
+ init_cjs_shims();
1010
1055
  function buildPythonProxies(bridge) {
1011
1056
  const proxies = /* @__PURE__ */ new Map();
1012
1057
  for (const name of bridge.toolNames) {
@@ -1047,6 +1092,7 @@ function makeProxy(bridge, name) {
1047
1092
  }
1048
1093
 
1049
1094
  // src/core/events.ts
1095
+ init_cjs_shims();
1050
1096
  var import_node_fs = require("fs");
1051
1097
  var import_node_path2 = require("path");
1052
1098
  var StderrEmitter = class {
@@ -1147,6 +1193,7 @@ function envelopeBytes(v) {
1147
1193
  }
1148
1194
 
1149
1195
  // src/core/pricing.ts
1196
+ init_cjs_shims();
1150
1197
  var import_node_fs2 = require("fs");
1151
1198
  function loadPricing(path9) {
1152
1199
  let raw;
@@ -1200,7 +1247,14 @@ function roundTo(x, n) {
1200
1247
  return Number(x.toFixed(n));
1201
1248
  }
1202
1249
 
1250
+ // src/providers/registry.ts
1251
+ init_cjs_shims();
1252
+
1253
+ // src/providers/anthropic.ts
1254
+ init_cjs_shims();
1255
+
1203
1256
  // src/core/provider-caps.ts
1257
+ init_cjs_shims();
1204
1258
  var PROVIDER_CAPS = {
1205
1259
  anthropic: {
1206
1260
  family: "anthropic",
@@ -1243,6 +1297,7 @@ function supportsTemperature(provider, model) {
1243
1297
  }
1244
1298
 
1245
1299
  // src/providers/types.ts
1300
+ init_cjs_shims();
1246
1301
  var ProviderError = class extends Error {
1247
1302
  name = "ProviderError";
1248
1303
  kind;
@@ -1424,6 +1479,7 @@ async function sendAnthropic(args) {
1424
1479
  }
1425
1480
 
1426
1481
  // src/providers/gemini.ts
1482
+ init_cjs_shims();
1427
1483
  var GEMINI_API_URL_BASE = "https://generativelanguage.googleapis.com/v1beta/models";
1428
1484
  function jsonSchemaToGeminiSchema(schema) {
1429
1485
  const out = {};
@@ -1606,6 +1662,7 @@ async function sendGemini(args) {
1606
1662
  }
1607
1663
 
1608
1664
  // src/providers/openai-compatible.ts
1665
+ init_cjs_shims();
1609
1666
  var OPENAI_COMPAT_DEFAULT_URLS = {
1610
1667
  openai: "https://api.openai.com/v1/chat/completions",
1611
1668
  xai: "https://api.x.ai/v1/chat/completions",
@@ -1855,10 +1912,12 @@ function makeGeminiProvider(model, apiKey, opts) {
1855
1912
  }
1856
1913
 
1857
1914
  // src/server.ts
1915
+ init_cjs_shims();
1858
1916
  var import_server2 = require("@modelcontextprotocol/sdk/server/index.js");
1859
1917
  var import_types5 = require("@modelcontextprotocol/sdk/types.js");
1860
1918
 
1861
1919
  // src/instructions.ts
1920
+ init_cjs_shims();
1862
1921
  var ROUTABLE_TOOLS = [
1863
1922
  // Single-shot
1864
1923
  "pick",
@@ -1917,13 +1976,19 @@ This convention is opt-in: a user message without the \`xc\`/\`XC\` prefix shoul
1917
1976
  }
1918
1977
 
1919
1978
  // src/tools/index.ts
1979
+ init_cjs_shims();
1920
1980
  var import_zod = require("zod");
1921
1981
 
1922
1982
  // src/tools/audit.ts
1983
+ init_cjs_shims();
1923
1984
  var import_node_fs3 = require("fs");
1924
1985
  var import_node_path3 = require("path");
1925
1986
 
1987
+ // src/core/structured.ts
1988
+ init_cjs_shims();
1989
+
1926
1990
  // src/core/extract-json.ts
1991
+ init_cjs_shims();
1927
1992
  function extractJson(text) {
1928
1993
  if (typeof text !== "string") return null;
1929
1994
  const s = text.trim();
@@ -1978,6 +2043,7 @@ function extractJson(text) {
1978
2043
  }
1979
2044
 
1980
2045
  // src/core/json-schema.ts
2046
+ init_cjs_shims();
1981
2047
  function validateSchema(value, schema, path9 = "") {
1982
2048
  const errs = [];
1983
2049
  if ("anyOf" in schema) {
@@ -2141,6 +2207,7 @@ function pyReprType(t) {
2141
2207
  }
2142
2208
 
2143
2209
  // src/core/usage.ts
2210
+ init_cjs_shims();
2144
2211
  function emptyUsage(provider, model, purpose = "worker") {
2145
2212
  return {
2146
2213
  provider,
@@ -2274,6 +2341,7 @@ async function askOne(provider, messages, opts) {
2274
2341
  }
2275
2342
 
2276
2343
  // src/core/retarget.ts
2344
+ init_cjs_shims();
2277
2345
  function retargetProvider(p, newModel) {
2278
2346
  if (p.model === newModel) return p;
2279
2347
  return {
@@ -2298,7 +2366,11 @@ async function loadProviderWeights(storage, names) {
2298
2366
  return out;
2299
2367
  }
2300
2368
 
2369
+ // src/core/tiers.ts
2370
+ init_cjs_shims();
2371
+
2301
2372
  // src/core/pyrepr.ts
2373
+ init_cjs_shims();
2302
2374
  function pyStrRepr(s) {
2303
2375
  const hasSingle = s.indexOf("'") >= 0;
2304
2376
  const hasDouble = s.indexOf('"') >= 0;
@@ -3000,13 +3072,19 @@ function boolArg(v, defaultVal) {
3000
3072
  }
3001
3073
 
3002
3074
  // src/tools/bench.ts
3075
+ init_cjs_shims();
3003
3076
  var import_node_fs4 = require("fs");
3004
3077
  var import_node_path5 = __toESM(require("path"), 1);
3005
3078
 
3079
+ // src/tools/confer.ts
3080
+ init_cjs_shims();
3081
+
3006
3082
  // src/core/canary.ts
3083
+ init_cjs_shims();
3007
3084
  var import_node_crypto = require("crypto");
3008
3085
 
3009
3086
  // src/core/injection.ts
3087
+ init_cjs_shims();
3010
3088
  var INJECTION_PHRASES_RE = new RegExp(
3011
3089
  "\\b((?:ignore|disregard|forget)\\s+(?:all\\s+)?(?:previous\\s+|prior\\s+|the\\s+(?:above\\s+)?)?(?:instructions|directions|prompts|rules|context)|you are now\\b|act as (?:a |an )?(?:[A-Za-z]+)|pretend (?:to be|you are)|system prompt:?|new instructions:?)",
3012
3090
  "gi"
@@ -3071,6 +3149,7 @@ function countOccurrences(haystack, needle) {
3071
3149
  }
3072
3150
 
3073
3151
  // src/core/panel-judges.ts
3152
+ init_cjs_shims();
3074
3153
  function pickPanelJudge(providers, moderatorName, pricing) {
3075
3154
  if (pricing) {
3076
3155
  const tiers = tierLadder(pricing);
@@ -3252,6 +3331,7 @@ var STRUCTURED_SYNTHESIS_SCHEMA = {
3252
3331
  };
3253
3332
 
3254
3333
  // src/core/router.ts
3334
+ init_cjs_shims();
3255
3335
  var ROUTER_DEFAULT_WINDOW_SECONDS = 30 * 24 * 3600;
3256
3336
  var ROUTER_COLD_START_THRESHOLD = 5;
3257
3337
  function routerScore(stats, minCost, maxCost) {
@@ -3400,6 +3480,7 @@ async function pickAutoPanel(storage, purpose, n, providers, allowlist) {
3400
3480
  }
3401
3481
 
3402
3482
  // src/core/session-memory.ts
3483
+ init_cjs_shims();
3403
3484
  var SESSION_MEMORY_DEFAULT_LIMIT = 50;
3404
3485
  var SESSION_MEMORY_INJECT_BUDGET_CHARS = 4e3;
3405
3486
  async function renderSessionMemoryBlock(storage, sessionId) {
@@ -3447,6 +3528,7 @@ async function renderSessionMemoryBlock(storage, sessionId) {
3447
3528
  }
3448
3529
 
3449
3530
  // src/core/worker-tools.ts
3531
+ init_cjs_shims();
3450
3532
  var WORKER_TOOL_ALLOWLIST = /* @__PURE__ */ new Set(["fetch", "verify"]);
3451
3533
  var WORKER_TOOL_HOP_BUDGET = 2;
3452
3534
  var WORKER_TOOLS_MAX_RESULT_CHARS = 4e3;
@@ -4293,6 +4375,7 @@ ${existing.content}`
4293
4375
  }
4294
4376
 
4295
4377
  // src/tools/review.ts
4378
+ init_cjs_shims();
4296
4379
  async function runReview(args, opts) {
4297
4380
  const snippet = typeof args["snippet"] === "string" ? args["snippet"] : String(args["snippet"] ?? "");
4298
4381
  const intent = typeof args["intent"] === "string" ? args["intent"] : "";
@@ -4314,9 +4397,11 @@ ${snippet}
4314
4397
  }
4315
4398
 
4316
4399
  // src/tools/verify.ts
4400
+ init_cjs_shims();
4317
4401
  var import_node_perf_hooks = require("perf_hooks");
4318
4402
 
4319
4403
  // src/core/sandbox.ts
4404
+ init_cjs_shims();
4320
4405
  var import_node_child_process = require("child_process");
4321
4406
  var import_promises = require("fs/promises");
4322
4407
  var import_node_os = require("os");
@@ -4477,6 +4562,7 @@ function tryKill(child, signal, isUnix) {
4477
4562
  }
4478
4563
 
4479
4564
  // src/core/shlex.ts
4565
+ init_cjs_shims();
4480
4566
  function shlexSplit(s) {
4481
4567
  const out = [];
4482
4568
  let current = "";
@@ -5119,6 +5205,7 @@ function isObj4(v) {
5119
5205
  }
5120
5206
 
5121
5207
  // src/tools/config-pin.ts
5208
+ init_cjs_shims();
5122
5209
  var import_node_crypto2 = require("crypto");
5123
5210
  var import_node_fs5 = require("fs");
5124
5211
  var import_node_path6 = __toESM(require("path"), 1);
@@ -5351,14 +5438,17 @@ function pyRepr2(v) {
5351
5438
  }
5352
5439
 
5353
5440
  // src/tools/create.ts
5441
+ init_cjs_shims();
5354
5442
  var import_node_crypto4 = require("crypto");
5355
5443
  var import_node_fs7 = require("fs");
5356
5444
  var import_node_path8 = __toESM(require("path"), 1);
5357
5445
 
5358
5446
  // src/tools/orchestrate.ts
5447
+ init_cjs_shims();
5359
5448
  var import_node_perf_hooks2 = require("perf_hooks");
5360
5449
 
5361
5450
  // src/core/dead-models.ts
5451
+ init_cjs_shims();
5362
5452
  var DEAD_MODELS_TTL_MS = 5 * 60 * 1e3;
5363
5453
  var deadModels = /* @__PURE__ */ new Map();
5364
5454
  function makeKey(provider, model) {
@@ -5717,11 +5807,43 @@ Synthesize the node outputs into a single coherent deliverable. Preserve any [MI
5717
5807
  { role: "system", content: "You are the orchestrator. Combine node outputs into the final result." },
5718
5808
  { role: "user", content: recombinePrompt }
5719
5809
  ];
5720
- const synthAns = await askOne(moderator, recMsgs, {
5810
+ let synthProvider = moderator;
5811
+ let synthModel = null;
5812
+ if (cheapMode && opts.pricing) {
5813
+ const pick = selectForDifficulty({
5814
+ pricing: opts.pricing,
5815
+ tier: "med",
5816
+ availableProviders: cheapAvailable,
5817
+ providerWeights: cheapWeights,
5818
+ ...cheapAllowOnly ? { allowOnly: cheapAllowOnly } : {}
5819
+ });
5820
+ for (const c of pick.scored) {
5821
+ if (isModelDead(c.provider, c.model)) continue;
5822
+ const base = opts.providers[c.provider];
5823
+ if (base) {
5824
+ synthProvider = retargetProvider(base, c.model);
5825
+ synthModel = `${c.provider}/${c.model}`;
5826
+ break;
5827
+ }
5828
+ }
5829
+ }
5830
+ let synthAns = await askOne(synthProvider, recMsgs, {
5721
5831
  maxTokens,
5722
5832
  temperature: 0.4,
5723
5833
  purpose: "synth"
5724
5834
  });
5835
+ if (synthAns.error !== void 0 && synthProvider !== moderator) {
5836
+ if (isDeadModelError(synthAns) && synthModel) {
5837
+ const [prov, mdl] = synthModel.split("/");
5838
+ if (prov && mdl) recordDeadModel(prov, mdl, synthAns.error ?? "");
5839
+ }
5840
+ synthAns = await askOne(moderator, recMsgs, {
5841
+ maxTokens,
5842
+ temperature: 0.4,
5843
+ purpose: "synth"
5844
+ });
5845
+ synthModel = null;
5846
+ }
5725
5847
  const finalText = synthAns.error !== void 0 ? "" : synthAns.response ?? "";
5726
5848
  const synthErr = synthAns.error;
5727
5849
  const publicNodes = Object.keys(nodesById).map(
@@ -5745,6 +5867,7 @@ Synthesize the node outputs into a single coherent deliverable. Preserve any [MI
5745
5867
  fail_fast: failFast,
5746
5868
  cheap_mode: cheapMode
5747
5869
  };
5870
+ if (synthModel) result["synth_model"] = synthModel;
5748
5871
  if (synthErr) result["synth_error"] = synthErr;
5749
5872
  if (plannerErrors.length > 0) result["planner_errors"] = plannerErrors;
5750
5873
  if (unknownNames.length > 0) result["skipped_unknown_providers"] = unknownNames;
@@ -6086,6 +6209,7 @@ function pyRound6(x) {
6086
6209
  }
6087
6210
 
6088
6211
  // src/tools/fetch.ts
6212
+ init_cjs_shims();
6089
6213
  var import_node_crypto3 = require("crypto");
6090
6214
  var import_node_fs6 = require("fs");
6091
6215
  var import_node_path7 = __toESM(require("path"), 1);
@@ -6317,6 +6441,7 @@ function errorPayload(code, message, hint, kind = "client") {
6317
6441
  }
6318
6442
 
6319
6443
  // src/core/call-context.ts
6444
+ init_cjs_shims();
6320
6445
  function buildCallContext(args) {
6321
6446
  const ctx = {
6322
6447
  cheap_mode: args.cheapMode,
@@ -6738,6 +6863,7 @@ function errorEnvelope6(toolName, code, message, hint) {
6738
6863
  }
6739
6864
 
6740
6865
  // src/tools/coordinate.ts
6866
+ init_cjs_shims();
6741
6867
  var DEFERRED_OPTS3 = [
6742
6868
  // empty — every coordinate opt runs natively when its deps
6743
6869
  // (storage / innerCallers) are wired. Without them the
@@ -7137,6 +7263,7 @@ function errorEnvelope7(code, message, hint) {
7137
7263
  }
7138
7264
 
7139
7265
  // src/tools/critique.ts
7266
+ init_cjs_shims();
7140
7267
  var CRITIQUE_MAX_WEAKNESSES = 5;
7141
7268
  var SEVERITY_ALIASES2 = {
7142
7269
  medium: "med",
@@ -7357,6 +7484,7 @@ function isObj6(v) {
7357
7484
  }
7358
7485
 
7359
7486
  // src/tools/debate.ts
7487
+ init_cjs_shims();
7360
7488
  var DEFERRED_OPTS4 = [
7361
7489
  // empty — every debate opt runs natively when its deps
7362
7490
  // (storage / innerCallers) are wired.
@@ -7713,6 +7841,7 @@ function errorEnvelope9(code, message, hint) {
7713
7841
  }
7714
7842
 
7715
7843
  // src/tools/delegate.ts
7844
+ init_cjs_shims();
7716
7845
  var DELEGABLE_TOOLS = /* @__PURE__ */ new Set(["confer", "review"]);
7717
7846
  var DEFAULT_DELEGATION_LIMITS = {
7718
7847
  max_per_session: 50,
@@ -7878,6 +8007,7 @@ function pyListRepr2(xs) {
7878
8007
  }
7879
8008
 
7880
8009
  // src/tools/explain.ts
8010
+ init_cjs_shims();
7881
8011
  var import_node_fs8 = require("fs");
7882
8012
  var import_node_path9 = __toESM(require("path"), 1);
7883
8013
  async function runExplain(args, opts) {
@@ -8202,6 +8332,7 @@ function errorEnvelope11(code, message, hint, kind = "client", extra = {}) {
8202
8332
  }
8203
8333
 
8204
8334
  // src/tools/list-providers.ts
8335
+ init_cjs_shims();
8205
8336
  var KNOWN_PROVIDERS6 = [
8206
8337
  "anthropic",
8207
8338
  "openai",
@@ -8233,6 +8364,7 @@ function runListProviders(_args, opts) {
8233
8364
  }
8234
8365
 
8235
8366
  // src/tools/pick.ts
8367
+ init_cjs_shims();
8236
8368
  var PICK_SCORES_SCHEMA = {
8237
8369
  type: "object",
8238
8370
  additionalProperties: false,
@@ -8549,6 +8681,7 @@ function toArray(v) {
8549
8681
  }
8550
8682
 
8551
8683
  // src/tools/plan.ts
8684
+ init_cjs_shims();
8552
8685
  var PLAN_MODE_PRESETS = {
8553
8686
  fast: { max_rounds: 2, early_stop: true, early_stop_threshold: 0.7 },
8554
8687
  thorough: { max_rounds: 5, early_stop: false, early_stop_threshold: 0.7 }
@@ -8588,6 +8721,7 @@ Return: (1) the plan as numbered steps, (2) risks, (3) alternatives considered.`
8588
8721
  }
8589
8722
 
8590
8723
  // src/tools/recall.ts
8724
+ init_cjs_shims();
8591
8725
  async function runRecall(args, opts) {
8592
8726
  const queryRaw = args["query"];
8593
8727
  const query = typeof queryRaw === "string" ? queryRaw.trim() : "";
@@ -8685,6 +8819,7 @@ function errorEnvelope12(code, message, hint) {
8685
8819
  }
8686
8820
 
8687
8821
  // src/tools/recommend-panel.ts
8822
+ init_cjs_shims();
8688
8823
  async function runRecommendPanel(args, opts) {
8689
8824
  const purpose = typeof args["purpose"] === "string" ? args["purpose"] : "";
8690
8825
  if (!purpose) {
@@ -8801,6 +8936,7 @@ function toStringArray3(v) {
8801
8936
  }
8802
8937
 
8803
8938
  // src/tools/scoreboard.ts
8939
+ init_cjs_shims();
8804
8940
  var import_node_fs9 = require("fs");
8805
8941
  async function runScoreboard(args, opts) {
8806
8942
  if (!opts.storage) {
@@ -8936,6 +9072,7 @@ function errorEnvelope14(code, message, hint) {
8936
9072
  }
8937
9073
 
8938
9074
  // src/tools/session-memory.ts
9075
+ init_cjs_shims();
8939
9076
  var VALID_KINDS = /* @__PURE__ */ new Set([
8940
9077
  "fact",
8941
9078
  "open_question",
@@ -9112,6 +9249,7 @@ function pyRepr6(v) {
9112
9249
  }
9113
9250
 
9114
9251
  // src/tools/solve.ts
9252
+ init_cjs_shims();
9115
9253
  var import_node_perf_hooks3 = require("perf_hooks");
9116
9254
  async function runSolve(args, opts) {
9117
9255
  const problem = typeof args["problem"] === "string" ? args["problem"] : String(args["problem"] ?? "");
@@ -9481,6 +9619,7 @@ function pyRepr7(v) {
9481
9619
  }
9482
9620
 
9483
9621
  // src/tools/update-crosscheck.ts
9622
+ init_cjs_shims();
9484
9623
  var import_node_child_process2 = require("child_process");
9485
9624
  var import_node_fs10 = require("fs");
9486
9625
  var import_node_path10 = __toESM(require("path"), 1);
@@ -9699,6 +9838,7 @@ function withTimeout2(promise, ms) {
9699
9838
  }
9700
9839
 
9701
9840
  // src/tools/triangulate.ts
9841
+ init_cjs_shims();
9702
9842
  async function runTriangulate(args, opts) {
9703
9843
  const question = typeof args["question"] === "string" ? args["question"] : String(args["question"] ?? "");
9704
9844
  const context = typeof args["context"] === "string" ? args["context"] : "";
@@ -10568,7 +10708,7 @@ function pingTool() {
10568
10708
 
10569
10709
  // src/server.ts
10570
10710
  var SERVER_NAME = "crosscheck-agent";
10571
- var SERVER_VERSION = "0.1.0";
10711
+ var SERVER_VERSION = true ? "0.1.3" : "0.0.0-dev";
10572
10712
  function createServer(opts = {}) {
10573
10713
  const server = new import_server2.Server(
10574
10714
  { name: SERVER_NAME, version: SERVER_VERSION },
@@ -10723,7 +10863,8 @@ async function main() {
10723
10863
  if (dbPath) {
10724
10864
  try {
10725
10865
  (0, import_node_fs11.mkdirSync)(import_node_path11.default.dirname(dbPath), { recursive: true });
10726
- storage = openBetterSqliteStorage({ path: dbPath });
10866
+ const { openBetterSqliteStorage: openBetterSqliteStorage2 } = await Promise.resolve().then(() => (init_better_sqlite3(), better_sqlite3_exports));
10867
+ storage = openBetterSqliteStorage2({ path: dbPath });
10727
10868
  await storage.migrate();
10728
10869
  process.stderr.write(
10729
10870
  `crosscheck-agent: storage wired at ${dbPath}