crosscheck-mcp 0.2.26 → 0.2.28

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.
@@ -15,20 +15,24 @@ var pricing_default = {
15
15
  notes: "Prices reflect public list pricing per provider. cached_per_1k applies to prompt tokens served from prompt-cache (Anthropic) or input-cache (OpenAI) when supported. Update when providers change rates. Missing models fall back to cost=0 with estimated=true. 2026-06-07: removed decommissioned gemini-2.0-flash / gemini-2.0-flash-lite (Google returns 404) and replaced the low-tier lite model with gemini-2.5-flash-lite. 2026-06-08: bumped the default Anthropic model to claude-opus-4-8. Kept gemini-2.5-pro as the Gemini default (gemini-3.1-pro-preview measured ~2.2x the cost at $2/$12 per M \u2014 output-token dominated by ~1.5k thinking tokens \u2014 so not worth it for a 1-of-4 panel voice). 2026-06-09: corrected rates verified against live provider pricing pages \u2014 gemini-2.5-pro output $5->$10/M; gemini-2.5-flash $0.15/$0.60 -> $0.30/$2.50; gpt-5 $5/$15 -> $1.25/$10 (cached $0.125); grok-4-latest input $5->$3/M (legacy grok-4 tier). Anthropic opus/sonnet/haiku rates confirmed unchanged. Older/unused models (gpt-4o, o1, o3, grok-3) not all re-verified. 2026-07-02: added claude-fable-5 as the optional reasoning-upgrade model (used only for the lead reasoning seat when the operator bumps a heavy task). 2026-07-04: set claude-fable-5 to its real pay-as-you-go API price effective 2026-07-07 \u2014 $10/M input ($0.01/1k), $50/M output ($0.05/1k), cached at 10% of input ($0.001/1k). Dropped the estimated flag. Note: Fable 5 is cheaper than opus-4-8 on both input and output. 2026-07-09: Google retired gemini-2.5-pro AND gemini-3-pro-preview (both now 404 'no longer available'). Moved the Gemini default to gemini-3.1-pro-preview ($2/M in, $12/M out, cache $0.20/M \u2014 the newest working pro; note it's a preview and may need another bump) and added gemini-3.5-flash ($1.50/M in, $9/M out, cache $0.15/M \u2014 GA) to the low/cheap tier. Removed the dead gemini-2.5-pro rate. IMPORTANT: gemini-3.x are heavy thinking models \u2014 thoughtsTokenCount (billed as output) is now folded into completion_tokens in the adapter, so cost reflects reasoning tokens. 2026-07-13: bumped the default OpenAI model to gpt-5.5 ($5/M in, $30/M out, cached $0.50/M \u2014 verified live). Note gpt-5.5 is markedly pricier than gpt-5 ($1.25/$10): ~4x input, 3x output. Kept gpt-5 in the table for cost lookups on pinned installs. 2026-07-16: added gpt-5.6 at the Sol (flagship) tier \u2014 $5/M in, $30/M out, cached $0.50/M (cache-write $6.25/M not modeled). gpt-5.6 is the second premium voice for the max-reasoning co-reasoner (runs alongside claude-fable-5 when an OpenAI key is set). Terra/Luna tiers not added (unused). 2026-07-17: added Moonshot AI (Kimi) provider with kimi-k3, base URL https://api.moonshot.ai/v1. Confirmed real rates \u2014 $3.00/M input (cache miss, $0.003/1k), $15.00/M output ($0.015/1k), $0.30/M cache-hit input ($0.0003/1k); 1M-token context. Kimi K3 is reasoning-class (temperature must be 1; uses max_completion_tokens). 2026-07-24: added claude-opus-5 ($5/M in, $25/M out, cached $0.50/M -- 10% of input, matching this table's existing cache-discount ratio) and made it the default anthropic model (was claude-opus-4-8). Fable 5 remains the reasoning-upgrade/super-mode target, unchanged. 2026-08-04: added Alibaba Cloud Qwen provider (OpenAI-compatible, DashScope international endpoint https://dashscope-intl.aliyuncs.com/compatible-mode/v1) with default model qwen3.8-max -- confirmed business pricing $2.00/M input ($0.002/1k), $6.00/M output ($0.006/1k), cache estimated at 10% of input ($0.0002/1k, not independently confirmed). Also added qwen3.7-max as a fallback tier at $1.25/M in ($0.00125/1k) / $3.75/M out ($0.00375/1k). Note: the model string initially configured (qwen-v3.8 / qwen-v3.7) does not exist on DashScope and 404s -- live-probed the real key against qwen3.8-max, qwen3.7-max, qwen3-max, qwen-max, and qwen-plus, all of which work; corrected the default and pricing keys to qwen3.8-max/qwen3.7-max and fixed QWEN_MODEL in both .env files to match. Qwen's Max tier is a standard instruct model, not reasoning-class -- normal temperature/max_tokens handling. 2026-09-06: added gpt-6-astra at published list rates ($10/$50 per Mtok, $1/Mtok cache read; the $12.50/Mtok cache-WRITE rate has no field in this schema and is not modelled). gemini-3.8-flash now carries Google's published paid-tier rates ($0.75/$3.75/$0.075 per Mtok). THESE DOUBLE ON 2027-01-01 ($1.50/$7.50/$0.15) and this schema has no effective-date support, so they must be updated by hand on that date or every Gemini cost will read half of actual. claude-fable-5-1 now carries published rates ($10/$50/$0.25 per Mtok). Note its cache-read rate is 4x cheaper than claude-fable-5's, so the two must not be assumed to track each other. No inferred rows remain. All three were previously absent, which silently recorded their cost as $0."
16
16
  },
17
17
  anthropic: {
18
+ _source: {
19
+ url: "https://platform.claude.com/docs/en/about-claude/pricing",
20
+ verified_at: "2026-09-27"
21
+ },
18
22
  "claude-opus-4-5": {
19
- prompt_per_1k: 0.015,
20
- completion_per_1k: 0.075,
21
- cached_per_1k: 15e-4
23
+ prompt_per_1k: 5e-3,
24
+ completion_per_1k: 0.025,
25
+ cached_per_1k: 5e-4
22
26
  },
23
27
  "claude-opus-4-7": {
24
- prompt_per_1k: 0.015,
25
- completion_per_1k: 0.075,
26
- cached_per_1k: 15e-4
28
+ prompt_per_1k: 5e-3,
29
+ completion_per_1k: 0.025,
30
+ cached_per_1k: 5e-4
27
31
  },
28
32
  "claude-opus-4-8": {
29
- prompt_per_1k: 0.015,
30
- completion_per_1k: 0.075,
31
- cached_per_1k: 15e-4
33
+ prompt_per_1k: 5e-3,
34
+ completion_per_1k: 0.025,
35
+ cached_per_1k: 5e-4
32
36
  },
33
37
  "claude-opus-5-5": {
34
38
  prompt_per_1k: 4e-3,
@@ -77,10 +81,44 @@ var pricing_default = {
77
81
  }
78
82
  },
79
83
  openai: {
84
+ _source: {
85
+ url: "https://developers.openai.com/api/docs/pricing",
86
+ verified_at: "2026-09-27"
87
+ },
88
+ "gpt-6-astra": {
89
+ prompt_per_1k: 0.01,
90
+ completion_per_1k: 0.05,
91
+ cached_per_1k: 1e-3
92
+ },
93
+ "gpt-6-sol": {
94
+ prompt_per_1k: 2e-3,
95
+ completion_per_1k: 0.01,
96
+ cached_per_1k: 2e-4
97
+ },
98
+ "gpt-6-luna": {
99
+ prompt_per_1k: 1e-4,
100
+ completion_per_1k: 5e-4,
101
+ cached_per_1k: 1e-5
102
+ },
103
+ "gpt-5.6-sol": {
104
+ prompt_per_1k: 4e-3,
105
+ completion_per_1k: 0.02,
106
+ cached_per_1k: 4e-4
107
+ },
108
+ "gpt-5.6-terra": {
109
+ prompt_per_1k: 2e-3,
110
+ completion_per_1k: 0.012,
111
+ cached_per_1k: 2e-4
112
+ },
113
+ "gpt-5.6-luna": {
114
+ prompt_per_1k: 2e-4,
115
+ completion_per_1k: 12e-4,
116
+ cached_per_1k: 2e-5
117
+ },
80
118
  "gpt-5.6": {
81
- prompt_per_1k: 5e-3,
82
- completion_per_1k: 0.03,
83
- cached_per_1k: 5e-4
119
+ prompt_per_1k: 4e-3,
120
+ completion_per_1k: 0.02,
121
+ cached_per_1k: 4e-4
84
122
  },
85
123
  "gpt-5.5": {
86
124
  prompt_per_1k: 5e-3,
@@ -93,9 +131,14 @@ var pricing_default = {
93
131
  cached_per_1k: 125e-6
94
132
  },
95
133
  "gpt-5-mini": {
96
- prompt_per_1k: 5e-4,
97
- completion_per_1k: 15e-4,
98
- cached_per_1k: 25e-5
134
+ prompt_per_1k: 25e-5,
135
+ completion_per_1k: 2e-3,
136
+ cached_per_1k: 25e-6
137
+ },
138
+ "gpt-5-nano": {
139
+ prompt_per_1k: 5e-5,
140
+ completion_per_1k: 4e-4,
141
+ cached_per_1k: 5e-6
99
142
  },
100
143
  "gpt-4o": {
101
144
  prompt_per_1k: 25e-4,
@@ -118,19 +161,44 @@ var pricing_default = {
118
161
  cached_per_1k: 15e-4
119
162
  },
120
163
  o3: {
121
- prompt_per_1k: 0.01,
122
- completion_per_1k: 0.04,
123
- cached_per_1k: 5e-3
164
+ prompt_per_1k: 2e-3,
165
+ completion_per_1k: 8e-3,
166
+ cached_per_1k: 5e-4
124
167
  },
125
168
  "o3-mini": {
126
169
  prompt_per_1k: 11e-4,
127
170
  completion_per_1k: 44e-4,
128
171
  cached_per_1k: 55e-5
129
172
  },
130
- "gpt-6-astra": {
131
- prompt_per_1k: 0.01,
132
- completion_per_1k: 0.05,
133
- cached_per_1k: 1e-3
173
+ "gpt-5-pro": {
174
+ prompt_per_1k: 0.015,
175
+ completion_per_1k: 0.12,
176
+ cached_per_1k: 0
177
+ },
178
+ "gpt-5.2-pro": {
179
+ prompt_per_1k: 0.021,
180
+ completion_per_1k: 0.168,
181
+ cached_per_1k: 0
182
+ },
183
+ "gpt-5.4-pro": {
184
+ prompt_per_1k: 0.03,
185
+ completion_per_1k: 0.18,
186
+ cached_per_1k: 0
187
+ },
188
+ "gpt-5.5-pro": {
189
+ prompt_per_1k: 0.03,
190
+ completion_per_1k: 0.18,
191
+ cached_per_1k: 0
192
+ },
193
+ "o1-pro": {
194
+ prompt_per_1k: 0.15,
195
+ completion_per_1k: 0.6,
196
+ cached_per_1k: 0
197
+ },
198
+ "o3-pro": {
199
+ prompt_per_1k: 0.02,
200
+ completion_per_1k: 0.08,
201
+ cached_per_1k: 0
134
202
  }
135
203
  },
136
204
  xai: {
@@ -365,20 +433,30 @@ function modelPricing(pricing, provider, model) {
365
433
  const block = pricing[provider];
366
434
  if (!block || typeof block !== "object" || Array.isArray(block)) return null;
367
435
  const table = block;
436
+ if (model.startsWith("_")) return null;
368
437
  let entry = table[model];
369
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
370
- const best = Object.keys(table).filter((k) => model.startsWith(k)).sort((a, b) => b.length - a.length)[0];
371
- entry = best !== void 0 ? table[best] : void 0;
438
+ let match = "exact";
439
+ if (!isRates(entry)) {
440
+ const best = Object.keys(table).filter((k) => !k.startsWith("_")).filter((k) => model.startsWith(k) && DATE_STAMP.test(model.slice(k.length))).sort((a, b) => b.length - a.length)[0];
441
+ if (best !== void 0) {
442
+ entry = table[best];
443
+ match = "stamp";
444
+ }
372
445
  }
373
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) return null;
446
+ if (!isRates(entry)) return null;
374
447
  const e = entry;
375
448
  return {
376
449
  prompt_per_1k: numberOrZero(e["prompt_per_1k"]),
377
450
  completion_per_1k: numberOrZero(e["completion_per_1k"]),
378
451
  cached_per_1k: numberOrZero(e["cached_per_1k"]),
379
- ...e["estimated"] === true ? { estimated: true } : {}
452
+ ...e["estimated"] === true ? { estimated: true } : {},
453
+ match
380
454
  };
381
455
  }
456
+ var DATE_STAMP = /^-\d{8}$/;
457
+ function isRates(v) {
458
+ return Boolean(v) && typeof v === "object" && !Array.isArray(v);
459
+ }
382
460
  function numberOrZero(v) {
383
461
  if (typeof v === "number" && Number.isFinite(v)) return v;
384
462
  if (typeof v === "string") {
@@ -458,8 +536,20 @@ var PROVIDER_CAPS = {
458
536
  gemini: {
459
537
  family: "gemini",
460
538
  system_role: "separate",
461
- supports_temperature: true,
462
- reasoning_prefixes: ["gemini-3.1-pro", "gemini-3.5-flash", "gemini-2.5-pro"]
539
+ // No sampling, on any Gemini model. Ignored since 3.6 Flash and rejected
540
+ // by upcoming models (Google, 2026-10). "model" means "omit for reasoning
541
+ // models", and every Gemini model is reasoning-class (below) — so this
542
+ // resolves to never, through the same rule the other providers use. The
543
+ // adapter also never sends it; this keeps the record honest for anything
544
+ // else that reads it.
545
+ supports_temperature: "model",
546
+ // EVERY Gemini model is reasoning-class. The old list named three
547
+ // families and missed gemini-3.8-flash — the DEFAULT — so the default
548
+ // model got the small non-reasoning budgets (768 tokens for an audit)
549
+ // while spending up to ~480 tokens of each call thinking. Google's docs
550
+ // say thinking cannot be switched off on current models, so a list of
551
+ // which ones think is a list that can only ever be incomplete.
552
+ reasoning_prefixes: ["gemini-"]
463
553
  },
464
554
  // Qwen's "Max" tier (qwen-v3.8, qwen-v3.7) is a standard instruct/chat
465
555
  // model, not a visible-reasoning model like QwQ — normal temperature and
@@ -582,6 +672,73 @@ function httpFailureToProviderError(provider, status, bodyText, retryAfterS, mod
582
672
  );
583
673
  }
584
674
 
675
+ // src/providers/network-errors.ts
676
+ function codeOf(e) {
677
+ if (!e || typeof e !== "object") return null;
678
+ const c = e.code;
679
+ return typeof c === "string" && c.length > 0 ? c : null;
680
+ }
681
+ function rootCause(e, depth = 0) {
682
+ if (depth > 5 || !e || typeof e !== "object") return e;
683
+ const o = e;
684
+ if (Array.isArray(o.errors) && o.errors.length > 0) {
685
+ const coded = o.errors.find((x) => codeOf(x) !== null);
686
+ return rootCause(coded ?? o.errors[0], depth + 1);
687
+ }
688
+ if (o.cause !== void 0 && o.cause !== null) return rootCause(o.cause, depth + 1);
689
+ return e;
690
+ }
691
+ var BY_CODE = {
692
+ ENOTFOUND: { cause: "dns", detail: "the provider's hostname did not resolve \u2014 DNS, or a typo'd base URL", transient: false, kind: "network" },
693
+ EAI_AGAIN: { cause: "dns", detail: "DNS lookup failed temporarily \u2014 resolver or network is flapping", transient: true, kind: "network" },
694
+ ECONNREFUSED: { cause: "refused", detail: "the connection was refused \u2014 nothing is listening, or a proxy blocked it", transient: false, kind: "network" },
695
+ ECONNRESET: { cause: "reset", detail: "the peer closed the connection mid-request \u2014 flaky path, or an upstream error behind a proxy", transient: true, kind: "network" },
696
+ EPIPE: { cause: "reset", detail: "the connection closed while we were still writing", transient: true, kind: "network" },
697
+ ETIMEDOUT: { cause: "connect_timeout", detail: "the connection timed out before it was established", transient: true, kind: "timeout" },
698
+ EHOSTUNREACH: { cause: "unreachable", detail: "no route to the provider \u2014 VPN, or offline", transient: true, kind: "network" },
699
+ ENETUNREACH: { cause: "unreachable", detail: "the network is unreachable \u2014 offline, or a routing change", transient: true, kind: "network" },
700
+ ENETDOWN: { cause: "unreachable", detail: "the local network is down", transient: true, kind: "network" },
701
+ EPROTO: { cause: "tls", detail: "the TLS handshake failed \u2014 an intercepting proxy, or a protocol mismatch", transient: false, kind: "network" },
702
+ ERR_TLS_CERT_ALTNAME_INVALID: { cause: "tls", detail: "the certificate did not match the hostname \u2014 traffic is being intercepted", transient: false, kind: "network" },
703
+ CERT_HAS_EXPIRED: { cause: "tls", detail: "the server certificate has expired, or this machine's clock is wrong", transient: false, kind: "network" },
704
+ UNABLE_TO_VERIFY_LEAF_SIGNATURE: { cause: "tls", detail: "the certificate chain could not be verified \u2014 a corporate proxy's root is probably not trusted here", transient: false, kind: "network" },
705
+ UND_ERR_CONNECT_TIMEOUT: { cause: "connect_timeout", detail: "could not open a connection within the timeout \u2014 firewall, or the host is down", transient: true, kind: "timeout" },
706
+ UND_ERR_HEADERS_TIMEOUT: { cause: "read_timeout", detail: "connected, but the provider sent no response headers in time \u2014 it is overloaded or thinking too long", transient: true, kind: "timeout" },
707
+ UND_ERR_BODY_TIMEOUT: { cause: "read_timeout", detail: "the response body stalled mid-stream", transient: true, kind: "timeout" },
708
+ UND_ERR_SOCKET: { cause: "reset", detail: "the socket closed unexpectedly", transient: true, kind: "network" },
709
+ UND_ERR_ABORTED: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" },
710
+ ABORT_ERR: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" }
711
+ };
712
+ function diagnoseNetworkError(e) {
713
+ const root = rootCause(e);
714
+ const code = codeOf(root) ?? codeOf(e);
715
+ if (code && BY_CODE[code]) return { ...BY_CODE[code], code };
716
+ const name = root && typeof root === "object" ? root.name : void 0;
717
+ if (name === "AbortError" || name === "TimeoutError") {
718
+ return {
719
+ cause: name === "TimeoutError" ? "read_timeout" : "aborted",
720
+ code: code ?? String(name),
721
+ detail: name === "TimeoutError" ? "the request exceeded its timeout" : "the request was cancelled",
722
+ transient: name === "TimeoutError",
723
+ kind: name === "TimeoutError" ? "timeout" : "network"
724
+ };
725
+ }
726
+ return {
727
+ cause: "unknown",
728
+ code,
729
+ detail: code ? `the connection failed with ${code}` : "the connection failed and the underlying error carried no code",
730
+ transient: true,
731
+ kind: "network"
732
+ };
733
+ }
734
+ function looksLikeNetworkFailure(d) {
735
+ return d.code !== null || d.cause !== "unknown";
736
+ }
737
+ function networkErrorMessage(provider, d) {
738
+ const code = d.code ? ` [${d.code}]` : "";
739
+ return `${provider}: ${d.detail}${code}`;
740
+ }
741
+
585
742
  // src/providers/retry.ts
586
743
  var override = null;
587
744
  function resolveRetryConfig() {
@@ -904,7 +1061,11 @@ async function sendAnthropic(args) {
904
1061
  try {
905
1062
  respLike = await doFetch(url, init);
906
1063
  } catch (e) {
907
- throw new ProviderError("network", `anthropic: fetch failed: ${e.message}`);
1064
+ const d = diagnoseNetworkError(e);
1065
+ if (!looksLikeNetworkFailure(d)) throw e;
1066
+ throw new ProviderError(d.kind, networkErrorMessage("anthropic", d), {
1067
+ transient: d.transient
1068
+ });
908
1069
  }
909
1070
  const status = respLike.status;
910
1071
  if (status >= 200 && status < 300) {
@@ -977,6 +1138,11 @@ function jsonSchemaToGeminiSchema(schema) {
977
1138
  }
978
1139
  return out;
979
1140
  }
1141
+ var GEMINI_THINKING_HEADROOM_TOKENS = 16384;
1142
+ function thinkingHeadroom() {
1143
+ const raw = Number(process.env["CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS"]);
1144
+ return Number.isFinite(raw) && raw >= 0 ? Math.trunc(raw) : GEMINI_THINKING_HEADROOM_TOKENS;
1145
+ }
980
1146
  function buildGeminiRequest(opts) {
981
1147
  const contents = [];
982
1148
  let systemText = null;
@@ -995,8 +1161,9 @@ function buildGeminiRequest(opts) {
995
1161
  const body = {
996
1162
  contents,
997
1163
  generationConfig: {
998
- maxOutputTokens: opts.maxTokens,
999
- temperature: opts.temperature
1164
+ // Answer budget + thinking headroom. No temperature / topP / topK /
1165
+ // thinkingBudget, on any model — see the header note.
1166
+ maxOutputTokens: opts.maxTokens + thinkingHeadroom()
1000
1167
  }
1001
1168
  };
1002
1169
  if (systemText !== null && systemText !== "") {
@@ -1006,8 +1173,8 @@ function buildGeminiRequest(opts) {
1006
1173
  body.generationConfig.responseMimeType = "application/json";
1007
1174
  body.generationConfig.responseSchema = jsonSchemaToGeminiSchema(opts.jsonSchema);
1008
1175
  }
1009
- const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent?key=${encodeURIComponent(opts.apiKey)}`;
1010
- return { url, headers: {}, body };
1176
+ const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent`;
1177
+ return { url, headers: { "x-goog-api-key": opts.apiKey }, body };
1011
1178
  }
1012
1179
  function parseGeminiResponse(opts) {
1013
1180
  const r = opts.resp ?? {};
@@ -1037,16 +1204,19 @@ function parseGeminiResponse(opts) {
1037
1204
  }
1038
1205
  try {
1039
1206
  const first = cands[0];
1040
- const content = first["content"];
1041
- const parts = content["parts"];
1207
+ const finishReason = typeof first["finishReason"] === "string" ? first["finishReason"] : void 0;
1208
+ const content = first["content"] ?? {};
1209
+ const parts = Array.isArray(content["parts"]) ? content["parts"] : [];
1042
1210
  let text = "";
1043
1211
  for (const p of parts) {
1044
1212
  if (p && typeof p === "object") {
1045
- const t = p["text"];
1213
+ const part = p;
1214
+ if (part["thought"] === true) continue;
1215
+ const t = part["text"];
1046
1216
  if (typeof t === "string") text += t;
1047
1217
  }
1048
1218
  }
1049
- return { text, usage };
1219
+ return { text, usage, ...finishReason ? { finishReason } : {} };
1050
1220
  } catch (e) {
1051
1221
  throw new ProviderError(
1052
1222
  "parse",
@@ -1075,7 +1245,8 @@ async function sendGemini(args) {
1075
1245
  apiKey: args.apiKey,
1076
1246
  messages: args.messages,
1077
1247
  maxTokens: args.maxTokens,
1078
- temperature: args.temperature,
1248
+ // args.temperature is deliberately NOT forwarded: Gemini ignores it and
1249
+ // upcoming models reject it. See the header note.
1079
1250
  ...args.jsonSchema ? { jsonSchema: args.jsonSchema } : {}
1080
1251
  });
1081
1252
  const doFetch = args.fetchImpl ?? globalThis.fetch;
@@ -1090,7 +1261,11 @@ async function sendGemini(args) {
1090
1261
  try {
1091
1262
  respLike = await doFetch(url, init);
1092
1263
  } catch (e) {
1093
- throw new ProviderError("network", `gemini: fetch failed: ${e.message}`);
1264
+ const d = diagnoseNetworkError(e);
1265
+ if (!looksLikeNetworkFailure(d)) throw e;
1266
+ throw new ProviderError(d.kind, networkErrorMessage("gemini", d), {
1267
+ transient: d.transient
1268
+ });
1094
1269
  }
1095
1270
  const status = respLike.status;
1096
1271
  if (status >= 200 && status < 300) {
@@ -1100,11 +1275,18 @@ async function sendGemini(args) {
1100
1275
  } catch (e) {
1101
1276
  throw new ProviderError("parse", `gemini: response body not JSON: ${e.message}`);
1102
1277
  }
1103
- const { text, usage } = parseGeminiResponse({
1278
+ const { text, usage, finishReason } = parseGeminiResponse({
1104
1279
  resp: parsed,
1105
1280
  model: args.model,
1106
1281
  purpose: args.purpose ?? "worker"
1107
1282
  });
1283
+ if (text.trim() === "" && finishReason === "MAX_TOKENS") {
1284
+ throw new ProviderError(
1285
+ "parse",
1286
+ `gemini: the answer was cut off before any visible text \u2014 thinking used the whole output budget (${usage.completion_tokens} tokens). Raise CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS or the purpose's budget.`,
1287
+ { transient: false }
1288
+ );
1289
+ }
1108
1290
  return { text, attempts: 1, usage: applyPricing2(usage, args.pricing) };
1109
1291
  }
1110
1292
  const bodyText = await respLike.text().catch(() => "");
@@ -1271,7 +1453,11 @@ async function sendOpenAICompatible(args) {
1271
1453
  try {
1272
1454
  respLike = await doFetch(url, init);
1273
1455
  } catch (e) {
1274
- throw new ProviderError("network", `${args.provider}: fetch failed: ${e.message}`);
1456
+ const d = diagnoseNetworkError(e);
1457
+ if (!looksLikeNetworkFailure(d)) throw e;
1458
+ throw new ProviderError(d.kind, networkErrorMessage(args.provider, d), {
1459
+ transient: d.transient
1460
+ });
1275
1461
  }
1276
1462
  const status = respLike.status;
1277
1463
  if (status >= 200 && status < 300) {
@@ -1299,7 +1485,7 @@ async function sendOpenAICompatible(args) {
1299
1485
  // src/providers/registry.ts
1300
1486
  var DEFAULT_MODELS = {
1301
1487
  anthropic: "claude-opus-5-5",
1302
- openai: "gpt-5.6-sol",
1488
+ openai: "gpt-6-sol",
1303
1489
  xai: "grok-4-latest",
1304
1490
  mistral: "mistral-large-latest",
1305
1491
  groq: "llama-3.3-70b-versatile",
@@ -1445,7 +1631,7 @@ import { z } from "zod";
1445
1631
 
1446
1632
  // src/server-meta.ts
1447
1633
  var SERVER_NAME = "crosscheck-agent";
1448
- var SERVER_VERSION = true ? "0.2.26" : "0.0.0-dev";
1634
+ var SERVER_VERSION = true ? "0.2.28" : "0.0.0-dev";
1449
1635
 
1450
1636
  // src/tools/audit.ts
1451
1637
  import { readdirSync, readFileSync as readFileSync3, statSync } from "fs";
@@ -1668,6 +1854,31 @@ function pyReprType(t) {
1668
1854
  return String(t);
1669
1855
  }
1670
1856
 
1857
+ // src/core/session.ts
1858
+ import { randomUUID } from "crypto";
1859
+ var processSessionId = null;
1860
+ var startedAt = null;
1861
+ function engineSessionId() {
1862
+ if (processSessionId === null) {
1863
+ processSessionId = randomUUID();
1864
+ startedAt = Date.now();
1865
+ }
1866
+ return processSessionId;
1867
+ }
1868
+ function resolveSessionId(callerSupplied) {
1869
+ const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
1870
+ return trimmed.length > 0 ? trimmed : engineSessionId();
1871
+ }
1872
+ function localSessionRecordingEnabled(env = globalThis.process?.env ?? {}) {
1873
+ const v = (env["CROSSCHECK_RECORD_SESSIONS"] ?? "").trim().toLowerCase();
1874
+ return !["0", "false", "off", "no"].includes(v);
1875
+ }
1876
+ function recordingSessionId(callerSupplied) {
1877
+ if (localSessionRecordingEnabled()) return resolveSessionId(callerSupplied);
1878
+ const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
1879
+ return trimmed.length > 0 ? trimmed : null;
1880
+ }
1881
+
1671
1882
  // src/core/usage.ts
1672
1883
  function emptyUsage(provider, model, purpose = "worker") {
1673
1884
  return {
@@ -1773,11 +1984,11 @@ function withCommas(n) {
1773
1984
  function renderRunSummary(opts) {
1774
1985
  const endedAt = opts.endedAtS ?? Math.trunc(Date.now() / 1e3);
1775
1986
  let scope = "call";
1776
- let startedAt = null;
1987
+ let startedAt2 = null;
1777
1988
  let rows = [];
1778
1989
  if (opts.sessionScope && opts.sessionScope.rows.length > 0) {
1779
1990
  scope = "session";
1780
- startedAt = opts.sessionScope.startedAt;
1991
+ startedAt2 = opts.sessionScope.startedAt;
1781
1992
  rows = opts.sessionScope.rows.map((r) => ({ ...r }));
1782
1993
  } else {
1783
1994
  const byPurpose = /* @__PURE__ */ new Map();
@@ -1808,6 +2019,7 @@ function renderRunSummary(opts) {
1808
2019
  row.cpu_ms += a.cpu_ms ?? 0;
1809
2020
  if (a.cache_hit) row.cache_hits += 1;
1810
2021
  if (a.error) row.errors += 1;
2022
+ if (a.usage?.estimated) row.estimated = true;
1811
2023
  }
1812
2024
  rows = Array.from(byPurpose.values());
1813
2025
  }
@@ -1820,16 +2032,18 @@ function renderRunSummary(opts) {
1820
2032
  wall_ms: rows.reduce((s, r) => s + r.wall_ms, 0),
1821
2033
  cpu_ms: rows.reduce((s, r) => s + r.cpu_ms, 0),
1822
2034
  cache_hits: rows.reduce((s, r) => s + r.cache_hits, 0),
1823
- errors: rows.reduce((s, r) => s + r.errors, 0)
2035
+ errors: rows.reduce((s, r) => s + r.errors, 0),
2036
+ ...rows.some((r) => r.estimated) ? { estimated: true } : {}
1824
2037
  };
1825
2038
  const titleLeft = scope === "session" ? `session: ${opts.sessionId ?? ""}` : `call: ${opts.toolName}`;
1826
- const header = `${titleLeft} (${totals.calls} calls, ${withCommas(totals.total_tokens)} tokens, $${totals.cost_usd.toFixed(4)}, ${(totals.wall_ms / 1e3).toFixed(1)}s wall, ${(totals.cpu_ms / 1e3).toFixed(3)}s cpu)`;
2039
+ const costText = totals.estimated ? `$${totals.cost_usd.toFixed(4)}+ (some calls unpriced)` : `$${totals.cost_usd.toFixed(4)}`;
2040
+ const header = `${titleLeft} (${totals.calls} calls, ${withCommas(totals.total_tokens)} tokens, ${costText}, ${(totals.wall_ms / 1e3).toFixed(1)}s wall, ${(totals.cpu_ms / 1e3).toFixed(3)}s cpu)`;
1827
2041
  const bodyLines = [];
1828
2042
  for (let i = 0; i < rows.length; i++) {
1829
2043
  const r = rows[i];
1830
2044
  const glyph = i === rows.length - 1 ? "`-" : "|-";
1831
2045
  bodyLines.push(
1832
- `${glyph} purpose: ${r.purpose} (calls=${r.calls} tokens=${withCommas(r.total_tokens)} cost=$${r.cost_usd.toFixed(4)} wall=${(r.wall_ms / 1e3).toFixed(1)}s cpu=${(r.cpu_ms / 1e3).toFixed(3)}s)`
2046
+ `${glyph} purpose: ${r.purpose} (calls=${r.calls} tokens=${withCommas(r.total_tokens)} cost=$${r.cost_usd.toFixed(4)}${r.estimated ? "+" : ""} wall=${(r.wall_ms / 1e3).toFixed(1)}s cpu=${(r.cpu_ms / 1e3).toFixed(3)}s)`
1833
2047
  );
1834
2048
  }
1835
2049
  const callByModel = rollupSpendByModel(
@@ -1877,7 +2091,7 @@ function renderRunSummary(opts) {
1877
2091
  tool: opts.toolName,
1878
2092
  scope,
1879
2093
  currency: "USD",
1880
- started_at: startedAt,
2094
+ started_at: startedAt2,
1881
2095
  ended_at: endedAt,
1882
2096
  rows,
1883
2097
  totals,
@@ -2002,14 +2216,15 @@ async function attachUsageBlock(result, answers, opts) {
2002
2216
  delete result["_suppress_run_summary"];
2003
2217
  }
2004
2218
  async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
2005
- if (!sessionId || answers.length === 0) return;
2219
+ const sid = recordingSessionId(sessionId);
2220
+ if (!sid || answers.length === 0) return;
2006
2221
  const now = nowS ?? Math.trunc(Date.now() / 1e3);
2007
2222
  const rows = [];
2008
2223
  for (const a of answers) {
2009
2224
  const u = a.usage;
2010
2225
  if (!u || typeof u.provider !== "string" || u.provider === "") continue;
2011
2226
  rows.push({
2012
- session_id: sessionId,
2227
+ session_id: sid,
2013
2228
  ts: now,
2014
2229
  tool: toolName,
2015
2230
  purpose: u.purpose ?? "worker",
@@ -2032,13 +2247,14 @@ async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
2032
2247
  }
2033
2248
  }
2034
2249
  async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, nowS) {
2035
- if (!sessionId) return;
2250
+ const sid = recordingSessionId(sessionId);
2251
+ if (!sid) return;
2036
2252
  const now = nowS ?? Math.trunc(Date.now() / 1e3);
2037
2253
  try {
2038
- let existing = await storage.getSession(sessionId);
2254
+ let existing = await storage.getSession(sid);
2039
2255
  if (!existing) {
2040
2256
  await storage.upsertSession({
2041
- session_id: sessionId,
2257
+ session_id: sid,
2042
2258
  started_at: now,
2043
2259
  last_at: now,
2044
2260
  calls: 0,
@@ -2051,7 +2267,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
2051
2267
  total_cost_usd: 0,
2052
2268
  total_cpu_ms: 0
2053
2269
  });
2054
- existing = await storage.getSession(sessionId);
2270
+ existing = await storage.getSession(sid);
2055
2271
  }
2056
2272
  if (!existing) return;
2057
2273
  let promptDelta = 0;
@@ -2071,7 +2287,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
2071
2287
  }
2072
2288
  if (a.cache_hit) cacheHitDelta += 1;
2073
2289
  }
2074
- await storage.accumulateSessionTotals(sessionId, {
2290
+ await storage.accumulateSessionTotals(sid, {
2075
2291
  calls: answers.length,
2076
2292
  wall_ms: wallMs,
2077
2293
  cache_hits: cacheHitDelta,
@@ -3019,13 +3235,25 @@ function numberOrNull(v) {
3019
3235
  import { performance as performance2 } from "perf_hooks";
3020
3236
 
3021
3237
  // src/core/co-reason.ts
3022
- var CO_REASON_MODEL = "gpt-5.6-sol";
3238
+ var CO_REASON_MODEL = "gpt-6-sol";
3239
+ var CO_REASON_ALTERNATE = "gpt-6-astra";
3240
+ var LABELS = {
3241
+ "gpt-6-sol": "GPT-6 Sol",
3242
+ "gpt-6-astra": "GPT-6 Astra",
3243
+ "gpt-5.6-sol": "GPT-5.6 Sol"
3244
+ };
3245
+ function coReasonLabel(model) {
3246
+ return LABELS[model] ?? model;
3247
+ }
3248
+ var CO_REASON_LABEL = coReasonLabel(CO_REASON_MODEL);
3023
3249
  var CO_REASON_PROVIDER = "openai";
3024
- var CO_REASON_LABEL = "GPT-5.6";
3025
- function pickCoReasoner(providers, upgradeRequested) {
3250
+ function pickCoReasoner(providers, upgradeRequested, openAiSeatModel) {
3026
3251
  if (!upgradeRequested) return null;
3027
3252
  const base = providers[CO_REASON_PROVIDER];
3028
- return base ? retargetProvider(base, CO_REASON_MODEL) : null;
3253
+ if (!base) return null;
3254
+ const seat = openAiSeatModel ?? base.model;
3255
+ const model = seat === CO_REASON_MODEL ? CO_REASON_ALTERNATE : CO_REASON_MODEL;
3256
+ return retargetProvider(base, model);
3029
3257
  }
3030
3258
  async function coReasonThenInject(opts) {
3031
3259
  const { provider, messages, maxTokens } = opts;
@@ -3251,7 +3479,7 @@ function buildSuggestedUpgrade(toolName, assessment) {
3251
3479
  model: UPGRADE_MODEL,
3252
3480
  label: UPGRADE_LABEL,
3253
3481
  reason: assessment.reason,
3254
- how: `re-run \`${toolName}\` with reasoning:"max" (or upgrade:true) to route the lead reasoning seat to ${UPGRADE_LABEL}, and \u2014 when an OpenAI key is configured \u2014 add a GPT-5.6 second-opinion pass that ${UPGRADE_LABEL} weighs before finalizing. Other panel seats stay on their normal models.`
3482
+ how: `re-run \`${toolName}\` with reasoning:"max" (or upgrade:true) to route the lead reasoning seat to ${UPGRADE_LABEL}, and \u2014 when an OpenAI key is configured \u2014 add an OpenAI second-opinion pass that ${UPGRADE_LABEL} weighs before finalizing (the result names which model ran). Other panel seats stay on their normal models.`
3255
3483
  };
3256
3484
  }
3257
3485
 
@@ -3554,8 +3782,9 @@ ${rubricText}`;
3554
3782
  const upgradeRequested = isUpgradeRequested(args);
3555
3783
  const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
3556
3784
  const auditorForCall = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : auditor;
3785
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
3557
3786
  const coReason = await coReasonThenInject({
3558
- provider: pickCoReasoner(opts.providers, upgradeRequested),
3787
+ provider: coProvider,
3559
3788
  messages: msgs,
3560
3789
  maxTokens: 2048,
3561
3790
  purpose: "audit-coreason"
@@ -3639,7 +3868,7 @@ ${rubricText}`;
3639
3868
  model: UPGRADE_MODEL,
3640
3869
  label: UPGRADE_LABEL,
3641
3870
  seat: "auditor",
3642
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
3871
+ ...coReasoned ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
3643
3872
  };
3644
3873
  } else if (upgradeRequested) {
3645
3874
  result["reasoning_upgrade"] = {
@@ -4370,8 +4599,12 @@ var SUPER_MODELS = {
4370
4599
  // Fable 5.1 verified present on the account; 5 as the fallback for accounts
4371
4600
  // that haven't been granted 5.1 yet.
4372
4601
  anthropic: ["claude-fable-5-1", UPGRADE_MODEL],
4373
- // Astra when it exists; gpt-5.6 until then. See the note above.
4374
- openai: ["gpt-6-astra", CO_REASON_MODEL],
4602
+ // Astra is live (verified against the account's model list 2026-09-23).
4603
+ // The fallback is named explicitly rather than reusing CO_REASON_MODEL:
4604
+ // that constant means "OpenAI's top reasoning model" for the max-reasoning
4605
+ // co-reasoner, which is a different question from "what should super fall
4606
+ // back to". Sharing the symbol silently coupled two unrelated decisions.
4607
+ openai: ["gpt-6-astra", "gpt-6-sol"],
4375
4608
  // Explicitly left as-is per product decision. Note grok-4-latest is not in
4376
4609
  // xAI's published model list, but it resolves in practice — real panel calls
4377
4610
  // on it succeeded as recently as 2026-08-30 — so it is an unlisted alias
@@ -4986,10 +5219,6 @@ If you need supporting evidence, you may emit ONE \`<tool_call>...</tool_call>\`
4986
5219
  }
4987
5220
 
4988
5221
  // src/tools/confer.ts
4989
- var DEFERRED_OPTS = [
4990
- // empty — every confer opt runs natively except worker_tools, which
4991
- // is gated below (non-empty list → defer).
4992
- ];
4993
5222
  async function runConfer(args, opts) {
4994
5223
  const callStartedWall = performance3.now();
4995
5224
  const callStartedCpu = process.cpuUsage();
@@ -5005,16 +5234,11 @@ async function runConfer(args, opts) {
5005
5234
  rejectedWorkerTools.push(t);
5006
5235
  }
5007
5236
  }
5008
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
5009
- const needsBridge = DEFERRED_OPTS.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
5010
- if (needsBridge) {
5011
- if (opts.bridge && opts.bridge.toolNames.has("confer")) {
5012
- return await deferConfer(args, opts.bridge);
5013
- }
5237
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
5014
5238
  return errorEnvelope2(
5015
5239
  "CONFER_OPT_NOT_NATIVE",
5016
5240
  "worker_tools requested but innerCallers are not wired",
5017
- "Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host (or CROSSCHECK_BRIDGE_PYTHON=1 as a backstop)."
5241
+ "Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host."
5018
5242
  );
5019
5243
  }
5020
5244
  const question = typeof args["question"] === "string" ? args["question"] : String(args["question"] ?? "");
@@ -5365,21 +5589,6 @@ function unknownProviderError(unknownNames, available) {
5365
5589
  available_now: Object.keys(available).sort()
5366
5590
  };
5367
5591
  }
5368
- async function deferConfer(args, bridge) {
5369
- const r = await bridge.callTool("confer", args);
5370
- const text = r.content[0]?.text;
5371
- if (typeof text === "string") {
5372
- try {
5373
- return JSON.parse(text);
5374
- } catch {
5375
- }
5376
- }
5377
- return errorEnvelope2(
5378
- "CONFER_BRIDGE_BAD_ENVELOPE",
5379
- "bridge returned an unparseable envelope for confer",
5380
- "Check that the Python child is healthy."
5381
- );
5382
- }
5383
5592
  function errorEnvelope2(code, message, hint) {
5384
5593
  return {
5385
5594
  tool: "confer",
@@ -5751,7 +5960,7 @@ function errorEnvelope3(code, message, hint) {
5751
5960
  transient: false
5752
5961
  };
5753
5962
  }
5754
- async function runVerify(args, bridge, fetchConfig) {
5963
+ async function runVerify(args, fetchConfig) {
5755
5964
  const checks = args["checks"];
5756
5965
  if (!Array.isArray(checks) || checks.length === 0) {
5757
5966
  return {
@@ -5763,7 +5972,6 @@ async function runVerify(args, bridge, fetchConfig) {
5763
5972
  )
5764
5973
  };
5765
5974
  }
5766
- void bridge;
5767
5975
  const allowShell = Boolean(args["allow_shell"] ?? false);
5768
5976
  const wallStart = performance4.now();
5769
5977
  const cpuStart = process.cpuUsage();
@@ -6065,7 +6273,6 @@ async function runBench(args, opts) {
6065
6273
  const innerOpts = {
6066
6274
  providers: opts.providers,
6067
6275
  allowlist: opts.allowlist ?? null,
6068
- ...opts.bridge ? { bridge: opts.bridge } : {},
6069
6276
  ...opts.moderator ? { moderator: opts.moderator } : {}
6070
6277
  };
6071
6278
  let inner;
@@ -6759,7 +6966,6 @@ var EST_TOKENS = {
6759
6966
  med: [1500, 800],
6760
6967
  high: [2500, 1500]
6761
6968
  };
6762
- var DEFERRED_OPTS2 = [];
6763
6969
  var REACTIVE_SIGNAL_RE = /<signals>\s*(\{[\s\S]*?\})\s*<\/signals>/g;
6764
6970
  function parseReactiveSignals(output) {
6765
6971
  if (typeof output !== "string" || !output.includes("<signals>")) return [];
@@ -6799,17 +7005,6 @@ async function runOrchestrate(args, opts) {
6799
7005
  );
6800
7006
  if (breakerEnv) return breakerEnv;
6801
7007
  }
6802
- const needsBridge = DEFERRED_OPTS2.some((k) => Boolean(args[k]));
6803
- if (needsBridge) {
6804
- if (opts.bridge && opts.bridge.toolNames.has("orchestrate")) {
6805
- return await deferOrchestrate(args, opts.bridge);
6806
- }
6807
- return errorEnvelope5(
6808
- "ORCHESTRATE_OPT_NOT_NATIVE",
6809
- "this orchestrate opt-in requires the Python bridge in v1",
6810
- "v1 native covers the plain DAG flow + cheap_mode. reactive (mid-flight DAG updates) still defers. Set CROSSCHECK_BRIDGE_PYTHON=1 to enable."
6811
- );
6812
- }
6813
7008
  const goal = typeof args["goal"] === "string" ? args["goal"] : null;
6814
7009
  const dagIn = isObj5(args["dag"]) ? args["dag"] : null;
6815
7010
  if (goal === null === (dagIn === null)) {
@@ -7352,8 +7547,9 @@ ${recombineSys}` : recombineSys },
7352
7547
  provider: synthProvider.name
7353
7548
  } }
7354
7549
  );
7550
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
7355
7551
  const coReason = await coReasonThenInject({
7356
- provider: pickCoReasoner(opts.providers, upgradeRequested),
7552
+ provider: coProvider,
7357
7553
  messages: recMsgs,
7358
7554
  maxTokens,
7359
7555
  purpose: "orchestrate-coreason"
@@ -7412,7 +7608,7 @@ ${recombineSys}` : recombineSys },
7412
7608
  model: UPGRADE_MODEL,
7413
7609
  label: UPGRADE_LABEL,
7414
7610
  seat: "recombine/synthesis",
7415
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
7611
+ ...coReasoned ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
7416
7612
  };
7417
7613
  } else if (upgradeRequested) {
7418
7614
  result["reasoning_upgrade"] = {
@@ -7750,21 +7946,6 @@ function resolveProviders3(names, available, allowlist) {
7750
7946
  }
7751
7947
  return out;
7752
7948
  }
7753
- async function deferOrchestrate(args, bridge) {
7754
- const r = await bridge.callTool("orchestrate", args);
7755
- const text = r.content[0]?.text;
7756
- if (typeof text === "string") {
7757
- try {
7758
- return JSON.parse(text);
7759
- } catch {
7760
- }
7761
- }
7762
- return errorEnvelope5(
7763
- "ORCHESTRATE_BRIDGE_BAD_ENVELOPE",
7764
- "bridge returned an unparseable envelope for orchestrate",
7765
- "Check that the Python child is healthy."
7766
- );
7767
- }
7768
7949
  function errorEnvelope5(code, message, hint, kind = "client") {
7769
7950
  return {
7770
7951
  tool: "orchestrate",
@@ -8127,7 +8308,6 @@ ${documentsPayload}`;
8127
8308
  }, {
8128
8309
  providers: opts.providers,
8129
8310
  allowlist: opts.allowlist ?? null,
8130
- ...opts.bridge ? { bridge: opts.bridge } : {},
8131
8311
  ctx
8132
8312
  });
8133
8313
  const scopeAnswer = Array.isArray(scope["answers"]) ? scope["answers"].filter((a) => typeof a["response"] === "string" && a["response"]).map((a) => `[${a["provider"]}]
@@ -8150,7 +8330,6 @@ ${scopeAnswer || "(none)"}
8150
8330
  providers: opts.providers,
8151
8331
  allowlist: opts.allowlist ?? null,
8152
8332
  moderator,
8153
- ...opts.bridge ? { bridge: opts.bridge } : {},
8154
8333
  ctx
8155
8334
  });
8156
8335
  let attempts = 1;
@@ -8185,7 +8364,6 @@ ${scopeAnswer || "(none)"}
8185
8364
  }, {
8186
8365
  providers: opts.providers,
8187
8366
  allowlist: opts.allowlist ?? null,
8188
- ...opts.bridge ? { bridge: opts.bridge } : {},
8189
8367
  ctx
8190
8368
  });
8191
8369
  }
@@ -8208,7 +8386,6 @@ ${scopeAnswer || "(none)"}
8208
8386
  }, {
8209
8387
  providers: opts.providers,
8210
8388
  allowlist: opts.allowlist ?? null,
8211
- ...opts.bridge ? { bridge: opts.bridge } : {},
8212
8389
  ctx
8213
8390
  });
8214
8391
  let overallF = toNumberOrNull(auditEnvelope["overall_score"]);
@@ -8233,7 +8410,6 @@ ${documentsPayload}`
8233
8410
  providers: opts.providers,
8234
8411
  allowlist: opts.allowlist ?? null,
8235
8412
  moderator,
8236
- ...opts.bridge ? { bridge: opts.bridge } : {},
8237
8413
  ctx
8238
8414
  }
8239
8415
  );
@@ -8253,7 +8429,6 @@ ${documentsPayload}`
8253
8429
  }, {
8254
8430
  providers: opts.providers,
8255
8431
  allowlist: opts.allowlist ?? null,
8256
- ...opts.bridge ? { bridge: opts.bridge } : {},
8257
8432
  ctx
8258
8433
  });
8259
8434
  overallF = toNumberOrNull(auditEnvelope["overall_score"]);
@@ -8491,11 +8666,6 @@ function errorEnvelope6(toolName, code, message, hint) {
8491
8666
 
8492
8667
  // src/tools/coordinate.ts
8493
8668
  import { performance as performance8 } from "perf_hooks";
8494
- var DEFERRED_OPTS3 = [
8495
- // empty — every coordinate opt runs natively when its deps
8496
- // (storage / innerCallers) are wired. Without them the
8497
- // worker_tools gate still triggers a bridge defer.
8498
- ];
8499
8669
  var COORDINATE_DEFAULT_TEMP = 0.4;
8500
8670
  var ROLE_TURN_SCHEMA = {
8501
8671
  type: "object",
@@ -8550,23 +8720,18 @@ async function runCoordinate(args, opts) {
8550
8720
  rejectedWorkerTools.push(t);
8551
8721
  }
8552
8722
  }
8553
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
8554
- const needsBridge = DEFERRED_OPTS3.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
8555
- if (needsBridge) {
8723
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
8556
8724
  if (superRequested) {
8557
8725
  return errorEnvelope7(
8558
8726
  "COORDINATE_SUPER_NOT_NATIVE",
8559
- "super mode requested but worker_tools needs the Python bridge",
8560
- "worker_tools without innerCallers wired defers to the Python bridge, which doesn't support super mode. Drop worker_tools, or wire innerCallers, to use super."
8727
+ "super mode requested with worker_tools, but innerCallers are not wired",
8728
+ "worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
8561
8729
  );
8562
8730
  }
8563
- if (opts.bridge && opts.bridge.toolNames.has("coordinate")) {
8564
- return await deferCoordinate(args, opts.bridge);
8565
- }
8566
8731
  return errorEnvelope7(
8567
8732
  "COORDINATE_OPT_NOT_NATIVE",
8568
8733
  "worker_tools requested but innerCallers are not wired",
8569
- "Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host (or CROSSCHECK_BRIDGE_PYTHON=1 as a backstop)."
8734
+ "Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host."
8570
8735
  );
8571
8736
  }
8572
8737
  const untrusted = Boolean(args["untrusted_input"]);
@@ -8758,8 +8923,9 @@ CRITIQUES:
8758
8923
  ${critiqueBlock}`
8759
8924
  }
8760
8925
  ];
8926
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
8761
8927
  const coReason = await coReasonThenInject({
8762
- provider: pickCoReasoner(opts.providers, upgradeRequested),
8928
+ provider: coProvider,
8763
8929
  messages: synthMessages,
8764
8930
  maxTokens,
8765
8931
  purpose: "coordinate-coreason"
@@ -8823,7 +8989,7 @@ ${critiqueBlock}`
8823
8989
  model: superRequested ? superPrimary("anthropic") ?? UPGRADE_MODEL : UPGRADE_MODEL,
8824
8990
  label: UPGRADE_LABEL,
8825
8991
  seat: "synthesizer",
8826
- ...coReasonAns ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
8992
+ ...coReasonAns ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
8827
8993
  };
8828
8994
  } else if (upgradeRequested) {
8829
8995
  result["reasoning_upgrade"] = {
@@ -8965,21 +9131,6 @@ function unknownProviderError3(unknownNames, available) {
8965
9131
  available_now: Object.keys(available).sort()
8966
9132
  };
8967
9133
  }
8968
- async function deferCoordinate(args, bridge) {
8969
- const r = await bridge.callTool("coordinate", args);
8970
- const text = r.content[0]?.text;
8971
- if (typeof text === "string") {
8972
- try {
8973
- return JSON.parse(text);
8974
- } catch {
8975
- }
8976
- }
8977
- return errorEnvelope7(
8978
- "COORDINATE_BRIDGE_BAD_ENVELOPE",
8979
- "bridge returned an unparseable envelope for coordinate",
8980
- "Check that the Python child is healthy."
8981
- );
8982
- }
8983
9134
  function errorEnvelope7(code, message, hint) {
8984
9135
  return {
8985
9136
  tool: "coordinate",
@@ -9307,10 +9458,6 @@ function buildModeratorTranscript(transcript) {
9307
9458
 
9308
9459
  // src/tools/debate.ts
9309
9460
  import { performance as performance10 } from "perf_hooks";
9310
- var DEFERRED_OPTS4 = [
9311
- // empty — every debate opt runs natively when its deps
9312
- // (storage / innerCallers) are wired.
9313
- ];
9314
9461
  async function runDebate(args, opts) {
9315
9462
  const callStartedWall = performance10.now();
9316
9463
  const callStartedCpu = process.cpuUsage();
@@ -9328,23 +9475,18 @@ async function runDebate(args, opts) {
9328
9475
  rejectedWorkerTools.push(t);
9329
9476
  }
9330
9477
  }
9331
- const workerToolsNeedsBridge = acceptedWorkerTools.length > 0 && !opts.innerCallers;
9332
- const needsBridge = DEFERRED_OPTS4.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
9333
- if (needsBridge) {
9478
+ if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
9334
9479
  if (superRequested) {
9335
9480
  return errorEnvelope9(
9336
9481
  "DEBATE_SUPER_NOT_NATIVE",
9337
- "super mode requested but worker_tools needs the Python bridge",
9338
- "worker_tools without innerCallers wired defers to the Python bridge, which doesn't support super mode. Drop worker_tools, or wire innerCallers, to use super."
9482
+ "super mode requested with worker_tools, but innerCallers are not wired",
9483
+ "worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
9339
9484
  );
9340
9485
  }
9341
- if (opts.bridge && opts.bridge.toolNames.has("debate")) {
9342
- return await deferDebate(args, opts.bridge);
9343
- }
9344
9486
  return errorEnvelope9(
9345
9487
  "DEBATE_OPT_NOT_NATIVE",
9346
9488
  "worker_tools requested but innerCallers are not wired",
9347
- "Native debate covers N-round + plain/structured moderator synthesis + inject_session_memory + auto_panel + extract_claims + early_stop. worker_tools needs innerCallers wired by the host (or CROSSCHECK_BRIDGE_PYTHON=1 as a backstop)."
9489
+ "Native debate covers N-round + plain/structured moderator synthesis + inject_session_memory + auto_panel + extract_claims + early_stop. worker_tools needs innerCallers wired by the host."
9348
9490
  );
9349
9491
  }
9350
9492
  const topic = typeof args["topic"] === "string" ? args["topic"] : String(args["topic"] ?? "");
@@ -9545,6 +9687,7 @@ ${prior.body}` });
9545
9687
  let synthesisErrors = [];
9546
9688
  let personaMeta = null;
9547
9689
  let coReasoned = false;
9690
+ let coReasonerModel = null;
9548
9691
  if (moderator) {
9549
9692
  const synthProvider = superRequested && opts.providers["anthropic"] ? retargetForSuper(opts.providers["anthropic"]) : upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : moderator;
9550
9693
  const condensed = buildModeratorTranscript(transcript);
@@ -9572,13 +9715,16 @@ TRANSCRIPT:
9572
9715
  ${condensed}`
9573
9716
  }
9574
9717
  ];
9718
+ const openAiSeat = selected.find((p) => p.name === "openai")?.model;
9719
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested, openAiSeat);
9575
9720
  const coReason = await coReasonThenInject({
9576
- provider: pickCoReasoner(opts.providers, upgradeRequested),
9721
+ provider: coProvider,
9577
9722
  messages: synthMessages,
9578
9723
  maxTokens,
9579
9724
  purpose: "debate-coreason"
9580
9725
  });
9581
9726
  synthMessages = coReason.messages;
9727
+ coReasonerModel = coProvider?.model ?? null;
9582
9728
  if (coReason.answer) extraAnswers.push(coReason.answer);
9583
9729
  coReasoned = coReason.answer !== null;
9584
9730
  if (structuredOpt) {
@@ -9637,7 +9783,7 @@ ${condensed}`
9637
9783
  model: superRequested ? superPrimary("anthropic") ?? UPGRADE_MODEL : UPGRADE_MODEL,
9638
9784
  label: UPGRADE_LABEL,
9639
9785
  seat: "moderator synthesis",
9640
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
9786
+ ...coReasoned && coReasonerModel ? { co_reasoner: { model: coReasonerModel, label: coReasonLabel(coReasonerModel) } } : {}
9641
9787
  };
9642
9788
  } else if (upgradeRequested) {
9643
9789
  result["reasoning_upgrade"] = {
@@ -9777,21 +9923,6 @@ function unknownProviderError5(unknownNames, available) {
9777
9923
  available_now: Object.keys(available).sort()
9778
9924
  };
9779
9925
  }
9780
- async function deferDebate(args, bridge) {
9781
- const r = await bridge.callTool("debate", args);
9782
- const text = r.content[0]?.text;
9783
- if (typeof text === "string") {
9784
- try {
9785
- return JSON.parse(text);
9786
- } catch {
9787
- }
9788
- }
9789
- return errorEnvelope9(
9790
- "DEBATE_BRIDGE_BAD_ENVELOPE",
9791
- "bridge returned an unparseable envelope for debate",
9792
- "Check that the Python child is healthy."
9793
- );
9794
- }
9795
9926
  function errorEnvelope9(code, message, hint) {
9796
9927
  return {
9797
9928
  tool: "debate",
@@ -9811,9 +9942,6 @@ var DEFAULT_DELEGATION_LIMITS = {
9811
9942
  };
9812
9943
  async function runDelegate(args, opts) {
9813
9944
  if (!opts.storage) {
9814
- if (opts.bridge && opts.bridge.toolNames.has("delegate")) {
9815
- return await deferDelegate(args, opts.bridge);
9816
- }
9817
9945
  return errorEnvelope10(
9818
9946
  "DELEGATE_STORAGE_UNAVAILABLE",
9819
9947
  "delegate needs the local database (for quota tracking), which isn't available",
@@ -9885,7 +10013,6 @@ async function runDelegate(args, opts) {
9885
10013
  const innerOpts = {
9886
10014
  providers: opts.providers,
9887
10015
  allowlist: opts.allowlist ?? null,
9888
- ...opts.bridge ? { bridge: opts.bridge } : {},
9889
10016
  ...opts.moderator ? { moderator: opts.moderator } : {}
9890
10017
  };
9891
10018
  let result;
@@ -9924,21 +10051,6 @@ async function record(storage, sessionId, requester, toolCall, via, accepted, no
9924
10051
  created_at: nowEpochSeconds
9925
10052
  });
9926
10053
  }
9927
- async function deferDelegate(args, bridge) {
9928
- const r = await bridge.callTool("delegate", args);
9929
- const text = r.content[0]?.text;
9930
- if (typeof text === "string") {
9931
- try {
9932
- return JSON.parse(text);
9933
- } catch {
9934
- }
9935
- }
9936
- return errorEnvelope10(
9937
- "DELEGATE_BRIDGE_BAD_ENVELOPE",
9938
- "bridge returned an unparseable envelope for delegate",
9939
- "Check that the Python child is healthy."
9940
- );
9941
- }
9942
10054
  function errorEnvelope10(code, message, hint) {
9943
10055
  return {
9944
10056
  tool: "delegate",
@@ -9981,9 +10093,6 @@ async function runExplain(args, opts) {
9981
10093
  );
9982
10094
  }
9983
10095
  if (!opts.storage) {
9984
- if (opts.bridge && opts.bridge.toolNames.has("explain")) {
9985
- return await deferExplain(args, opts.bridge);
9986
- }
9987
10096
  return errorEnvelope11(
9988
10097
  "EXPLAIN_STORAGE_UNAVAILABLE",
9989
10098
  "explain needs the local transcript/stats database, which isn't available",
@@ -10265,21 +10374,6 @@ function pyRepr5(v) {
10265
10374
  }
10266
10375
  return String(v);
10267
10376
  }
10268
- async function deferExplain(args, bridge) {
10269
- const r = await bridge.callTool("explain", args);
10270
- const text = r.content[0]?.text;
10271
- if (typeof text === "string") {
10272
- try {
10273
- return JSON.parse(text);
10274
- } catch {
10275
- }
10276
- }
10277
- return errorEnvelope11(
10278
- "EXPLAIN_BRIDGE_BAD_ENVELOPE",
10279
- "bridge returned an unparseable envelope for explain",
10280
- "Check that the Python child is healthy."
10281
- );
10282
- }
10283
10377
  function errorEnvelope11(code, message, hint, kind = "client", extra = {}) {
10284
10378
  return {
10285
10379
  tool: "explain",
@@ -10832,9 +10926,6 @@ async function runRecall(args, opts) {
10832
10926
  if (k < 1) k = 1;
10833
10927
  if (k > 50) k = 50;
10834
10928
  if (!opts.storage) {
10835
- if (opts.bridge && opts.bridge.toolNames.has("recall")) {
10836
- return await deferRecall(args, opts.bridge);
10837
- }
10838
10929
  return errorEnvelope12(
10839
10930
  "RECALL_STORAGE_UNAVAILABLE",
10840
10931
  "recall needs the local database, which isn't available",
@@ -10887,21 +10978,6 @@ async function runRecall(args, opts) {
10887
10978
  applied_filters: applied
10888
10979
  };
10889
10980
  }
10890
- async function deferRecall(args, bridge) {
10891
- const r = await bridge.callTool("recall", args);
10892
- const text = r.content[0]?.text;
10893
- if (typeof text === "string") {
10894
- try {
10895
- return JSON.parse(text);
10896
- } catch {
10897
- }
10898
- }
10899
- return errorEnvelope12(
10900
- "RECALL_BRIDGE_BAD_ENVELOPE",
10901
- "bridge returned an unparseable envelope for recall",
10902
- "Check that the Python child is healthy."
10903
- );
10904
- }
10905
10981
  function errorEnvelope12(code, message, hint) {
10906
10982
  return {
10907
10983
  tool: "recall",
@@ -10924,9 +11000,6 @@ async function runRecommendPanel(args, opts) {
10924
11000
  );
10925
11001
  }
10926
11002
  if (!opts.storage) {
10927
- if (opts.bridge && opts.bridge.toolNames.has("recommend_panel")) {
10928
- return await deferRecommendPanel(args, opts.bridge);
10929
- }
10930
11003
  return errorEnvelope13(
10931
11004
  "RECOMMEND_PANEL_STORAGE_UNAVAILABLE",
10932
11005
  "recommend_panel needs the local stats database, which isn't available",
@@ -10989,21 +11062,6 @@ async function runRecommendPanel(args, opts) {
10989
11062
  meta: result.meta
10990
11063
  };
10991
11064
  }
10992
- async function deferRecommendPanel(args, bridge) {
10993
- const r = await bridge.callTool("recommend_panel", args);
10994
- const text = r.content[0]?.text;
10995
- if (typeof text === "string") {
10996
- try {
10997
- return JSON.parse(text);
10998
- } catch {
10999
- }
11000
- }
11001
- return errorEnvelope13(
11002
- "RECOMMEND_PANEL_BRIDGE_BAD_ENVELOPE",
11003
- "bridge returned an unparseable envelope for recommend_panel",
11004
- "Check that the Python child is healthy."
11005
- );
11006
- }
11007
11065
  function errorEnvelope13(code, message, hint) {
11008
11066
  return {
11009
11067
  tool: "recommend_panel",
@@ -11033,9 +11091,6 @@ function toStringArray3(v) {
11033
11091
  import { readFileSync as readFileSync10, existsSync as existsSync8 } from "fs";
11034
11092
  async function runScoreboard(args, opts) {
11035
11093
  if (!opts.storage) {
11036
- if (opts.bridge && opts.bridge.toolNames.has("scoreboard")) {
11037
- return await deferScoreboard(args, opts.bridge);
11038
- }
11039
11094
  return errorEnvelope14(
11040
11095
  "SCOREBOARD_STORAGE_UNAVAILABLE",
11041
11096
  "scoreboard needs the local stats database, which isn't available",
@@ -11158,21 +11213,6 @@ function clampInt3(raw, min, max, fallback) {
11158
11213
  if (!Number.isFinite(n)) return fallback;
11159
11214
  return Math.min(max, Math.max(min, Math.trunc(n)));
11160
11215
  }
11161
- async function deferScoreboard(args, bridge) {
11162
- const r = await bridge.callTool("scoreboard", args);
11163
- const text = r.content[0]?.text;
11164
- if (typeof text === "string") {
11165
- try {
11166
- return JSON.parse(text);
11167
- } catch {
11168
- }
11169
- }
11170
- return errorEnvelope14(
11171
- "SCOREBOARD_BRIDGE_BAD_ENVELOPE",
11172
- "bridge returned an unparseable envelope for scoreboard",
11173
- "Check that the Python child is healthy."
11174
- );
11175
- }
11176
11216
  function errorEnvelope14(code, message, hint) {
11177
11217
  return {
11178
11218
  tool: "scoreboard",
@@ -11209,9 +11249,6 @@ async function runSessionMemory(args, opts) {
11209
11249
  );
11210
11250
  }
11211
11251
  if (!opts.storage) {
11212
- if (opts.bridge && opts.bridge.toolNames.has("session_memory")) {
11213
- return await deferSessionMemory(args, opts.bridge);
11214
- }
11215
11252
  return errorEnvelope15(
11216
11253
  "SESSION_MEMORY_STORAGE_UNAVAILABLE",
11217
11254
  "session_memory needs the local database, which isn't available",
@@ -11316,21 +11353,6 @@ function clampInt4(raw, min, max, fallback) {
11316
11353
  if (!Number.isFinite(n)) return fallback;
11317
11354
  return Math.min(max, Math.max(min, Math.trunc(n)));
11318
11355
  }
11319
- async function deferSessionMemory(args, bridge) {
11320
- const r = await bridge.callTool("session_memory", args);
11321
- const text = r.content[0]?.text;
11322
- if (typeof text === "string") {
11323
- try {
11324
- return JSON.parse(text);
11325
- } catch {
11326
- }
11327
- }
11328
- return errorEnvelope15(
11329
- "SESSION_MEMORY_BRIDGE_BAD_ENVELOPE",
11330
- "bridge returned an unparseable envelope for session_memory",
11331
- "Check that the Python child is healthy."
11332
- );
11333
- }
11334
11356
  function errorEnvelope15(code, message, hint) {
11335
11357
  return {
11336
11358
  tool: "session_memory",
@@ -11661,7 +11683,7 @@ Re-emit the FULL solution. No commentary.`
11661
11683
  model: UPGRADE_MODEL,
11662
11684
  label: UPGRADE_LABEL,
11663
11685
  seat: "solver",
11664
- ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
11686
+ ...coReasoned ? { co_reasoner: { model: coProvider.model, label: coReasonLabel(coProvider.model) } } : {}
11665
11687
  };
11666
11688
  } else if (upgradeRequested) {
11667
11689
  result["reasoning_upgrade"] = {
@@ -11950,7 +11972,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
11950
11972
  var DEFAULT_PACKAGE = "crosscheck-cli";
11951
11973
  var FETCH_TIMEOUT_MS = 3e3;
11952
11974
  function engineVersion() {
11953
- return true ? "0.2.26" : "0.0.0-dev";
11975
+ return true ? "0.2.28" : "0.0.0-dev";
11954
11976
  }
11955
11977
  function defaultUpdateCachePath() {
11956
11978
  const base = process.env["CROSSCHECK_DATA_DIR"] || path9.join(os.homedir() || os.tmpdir(), ".crosscheck");
@@ -12722,12 +12744,11 @@ function helpTool() {
12722
12744
  }
12723
12745
  });
12724
12746
  }
12725
- function registerCoreTools(opts = {}) {
12726
- const o = opts && typeof opts === "object" && "toolNames" in opts ? { bridge: opts } : opts;
12747
+ function registerCoreTools(o = {}) {
12727
12748
  const tools = /* @__PURE__ */ new Map();
12728
12749
  const list = [
12729
12750
  pingTool(),
12730
- verifyTool(o.bridge, o.fetchConfig),
12751
+ verifyTool(o.fetchConfig),
12731
12752
  pickTool(
12732
12753
  o.providers ?? {},
12733
12754
  o.providerAllowlist ?? null,
@@ -12739,7 +12760,6 @@ function registerCoreTools(opts = {}) {
12739
12760
  auditTool(
12740
12761
  o.providers ?? {},
12741
12762
  o.providerAllowlist ?? null,
12742
- o.bridge,
12743
12763
  o.transcriptsDir,
12744
12764
  o.pricing,
12745
12765
  o.storage,
@@ -12749,7 +12769,6 @@ function registerCoreTools(opts = {}) {
12749
12769
  conferTool(
12750
12770
  o.providers ?? {},
12751
12771
  o.providerAllowlist ?? null,
12752
- o.bridge,
12753
12772
  o.moderatorDefault ?? "anthropic",
12754
12773
  o.pricing,
12755
12774
  o.storage,
@@ -12762,7 +12781,6 @@ function registerCoreTools(opts = {}) {
12762
12781
  debateTool(
12763
12782
  o.providers ?? {},
12764
12783
  o.providerAllowlist ?? null,
12765
- o.bridge,
12766
12784
  buildInnerCallers(o),
12767
12785
  o.storage,
12768
12786
  o.pricing,
@@ -12774,7 +12792,6 @@ function registerCoreTools(opts = {}) {
12774
12792
  coordinateTool(
12775
12793
  o.providers ?? {},
12776
12794
  o.providerAllowlist ?? null,
12777
- o.bridge,
12778
12795
  buildInnerCallers(o),
12779
12796
  o.storage,
12780
12797
  o.circuitBreakers,
@@ -12785,7 +12802,6 @@ function registerCoreTools(opts = {}) {
12785
12802
  triangulateTool(
12786
12803
  o.providers ?? {},
12787
12804
  o.providerAllowlist ?? null,
12788
- o.bridge,
12789
12805
  o.storage,
12790
12806
  o.circuitBreakers,
12791
12807
  o.transcriptsDir,
@@ -12794,7 +12810,6 @@ function registerCoreTools(opts = {}) {
12794
12810
  planTool(
12795
12811
  o.providers ?? {},
12796
12812
  o.providerAllowlist ?? null,
12797
- o.bridge,
12798
12813
  o.storage,
12799
12814
  o.circuitBreakers,
12800
12815
  o.transcriptsDir,
@@ -12803,7 +12818,6 @@ function registerCoreTools(opts = {}) {
12803
12818
  critiqueTool(
12804
12819
  o.providers ?? {},
12805
12820
  o.providerAllowlist ?? null,
12806
- o.bridge,
12807
12821
  o.storage,
12808
12822
  o.circuitBreakers,
12809
12823
  o.transcriptsDir,
@@ -12812,7 +12826,6 @@ function registerCoreTools(opts = {}) {
12812
12826
  reviewTool(
12813
12827
  o.providers ?? {},
12814
12828
  o.providerAllowlist ?? null,
12815
- o.bridge,
12816
12829
  o.storage,
12817
12830
  o.circuitBreakers,
12818
12831
  o.transcriptsDir,
@@ -12820,25 +12833,23 @@ function registerCoreTools(opts = {}) {
12820
12833
  ),
12821
12834
  listProvidersTool(o.providers ?? {}, o.activeProviders ?? null, o.moderatorDefault ?? "anthropic"),
12822
12835
  modelsTool(o.providers ?? {}, o.activeProviders ?? null),
12823
- recallTool(o.storage, o.bridge),
12824
- sessionMemoryTool(o.storage, o.bridge),
12825
- scoreboardTool(o.storage, o.bridge, o.eventsPath),
12826
- explainTool(o.storage, o.bridge, o.transcriptsDir),
12836
+ recallTool(o.storage),
12837
+ sessionMemoryTool(o.storage),
12838
+ scoreboardTool(o.storage, o.eventsPath),
12839
+ explainTool(o.storage, o.transcriptsDir),
12827
12840
  delegateTool(
12828
12841
  o.providers ?? {},
12829
12842
  o.providerAllowlist ?? null,
12830
12843
  o.storage,
12831
- o.bridge,
12832
12844
  o.moderatorDefault ?? "anthropic"
12833
12845
  ),
12834
12846
  fetchTool(o.storage, o.fetchConfig, o.repoRoot),
12835
- recommendPanelTool(o.providers ?? {}, o.storage, o.bridge),
12847
+ recommendPanelTool(o.providers ?? {}, o.storage),
12836
12848
  updateCrosscheckTool(o.repoRoot ?? null),
12837
12849
  benchTool(
12838
12850
  o.providers ?? {},
12839
12851
  o.providerAllowlist ?? null,
12840
12852
  o.storage,
12841
- o.bridge,
12842
12853
  o.moderatorDefault ?? "anthropic",
12843
12854
  o.benchGoldensDir,
12844
12855
  o.circuitBreakers,
@@ -12849,7 +12860,6 @@ function registerCoreTools(opts = {}) {
12849
12860
  solveTool(
12850
12861
  o.providers ?? {},
12851
12862
  o.providerAllowlist ?? null,
12852
- o.bridge,
12853
12863
  o.storage,
12854
12864
  o.circuitBreakers,
12855
12865
  o.transcriptsDir,
@@ -12858,7 +12868,6 @@ function registerCoreTools(opts = {}) {
12858
12868
  orchestrateTool(
12859
12869
  o.providers ?? {},
12860
12870
  o.providerAllowlist ?? null,
12861
- o.bridge,
12862
12871
  o.moderatorDefault ?? "anthropic",
12863
12872
  o.storage,
12864
12873
  o.pricing,
@@ -12905,7 +12914,6 @@ function createTool(o, toolName, cheapDefault) {
12905
12914
  providers: o.providers ?? {},
12906
12915
  allowlist: o.providerAllowlist ?? null,
12907
12916
  ...o.storage ? { storage: o.storage } : {},
12908
- ...o.bridge ? { bridge: o.bridge } : {},
12909
12917
  ...o.moderatorDefault ? { moderator: o.moderatorDefault } : {},
12910
12918
  ...o.fetchConfig ? { fetchConfig: o.fetchConfig } : {},
12911
12919
  ...o.repoRoot ? { repoRoot: o.repoRoot } : {},
@@ -12914,7 +12922,7 @@ function createTool(o, toolName, cheapDefault) {
12914
12922
  })
12915
12923
  };
12916
12924
  }
12917
- function orchestrateTool(providers, allowlist, bridge, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
12925
+ function orchestrateTool(providers, allowlist, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
12918
12926
  return {
12919
12927
  name: "orchestrate",
12920
12928
  description: "Plan and execute a DAG of LLM subtasks. Either supply a `goal` (planner will draft the DAG) OR a hand-authored `dag`. Workers run topologically; recombine produces a single `final`. Covers the sequential flow, cheap_mode (per-node tier picking), and reactive (mid-flight DAG updates) \u2014 all native.",
@@ -12939,7 +12947,6 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
12939
12947
  providers,
12940
12948
  allowlist,
12941
12949
  moderator,
12942
- ...bridge ? { bridge } : {},
12943
12950
  ...storage ? { storage } : {},
12944
12951
  ...pricing ? { pricing } : {},
12945
12952
  ...breakers ? { breakers } : {},
@@ -12949,7 +12956,7 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
12949
12956
  })
12950
12957
  };
12951
12958
  }
12952
- function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
12959
+ function solveTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
12953
12960
  return {
12954
12961
  name: "solve",
12955
12962
  description: "Iterative LLM solver. Generates a proposal, verifies it against the supplied verifier, and retries with feedback up to max_attempts. Verifier kinds: regex_response and shell (run in a native sandbox with wall-clock + optional memory/CPU limits). With target_path, returns a unified-diff patch.",
@@ -12971,7 +12978,6 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
12971
12978
  handler: (args) => runSolve(args, {
12972
12979
  providers,
12973
12980
  allowlist,
12974
- ...bridge ? { bridge } : {},
12975
12981
  ...storage ? { storage } : {},
12976
12982
  ...breakers ? { breakers } : {},
12977
12983
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13010,7 +13016,7 @@ function configPinTool(repoRoot, config, rejectDriftEnv) {
13010
13016
  }
13011
13017
  };
13012
13018
  }
13013
- function benchTool(providers, allowlist, storage, bridge, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
13019
+ function benchTool(providers, allowlist, storage, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
13014
13020
  return {
13015
13021
  name: "bench",
13016
13022
  description: "Run benchmark goldens against each provider's confer/review output. Each golden: {name, tool_call: confer|review, args, verifiers[]}. Returns per-provider pass/fail/error + a ranking sorted by score. Records ballots into provider_stats when storage is wired (used by triangulate's win-rate weights).",
@@ -13029,7 +13035,6 @@ function benchTool(providers, allowlist, storage, bridge, moderator, defaultGold
13029
13035
  allowlist,
13030
13036
  moderator,
13031
13037
  ...storage ? { storage } : {},
13032
- ...bridge ? { bridge } : {},
13033
13038
  ...defaultGoldensDir ? { defaultGoldensDir } : {},
13034
13039
  ...breakers ? { breakers } : {},
13035
13040
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13056,7 +13061,7 @@ function updateCrosscheckTool(repoRoot) {
13056
13061
  }
13057
13062
  };
13058
13063
  }
13059
- function recommendPanelTool(providers, storage, bridge) {
13064
+ function recommendPanelTool(providers, storage) {
13060
13065
  return {
13061
13066
  name: "recommend_panel",
13062
13067
  description: "Recommend a minimal effective panel for a given purpose, based on historical usage_log + provider_stats. Cold-start falls back to the configured panel ordered by win-rate.",
@@ -13074,8 +13079,7 @@ function recommendPanelTool(providers, storage, bridge) {
13074
13079
  },
13075
13080
  handler: (args) => runRecommendPanel(args, {
13076
13081
  providers,
13077
- ...storage ? { storage } : {},
13078
- ...bridge ? { bridge } : {}
13082
+ ...storage ? { storage } : {}
13079
13083
  })
13080
13084
  };
13081
13085
  }
@@ -13100,7 +13104,7 @@ function fetchTool(storage, fetchConfig, repoRoot) {
13100
13104
  })
13101
13105
  };
13102
13106
  }
13103
- function delegateTool(providers, allowlist, storage, bridge, moderator) {
13107
+ function delegateTool(providers, allowlist, storage, moderator) {
13104
13108
  return {
13105
13109
  name: "delegate",
13106
13110
  description: "Run a delegable tool (confer | review) restricted to a single named provider, with explicit quota check. Records every attempt (accepted or refused) to the delegations table; quota in the response reflects counts AFTER the current call.",
@@ -13120,12 +13124,11 @@ function delegateTool(providers, allowlist, storage, bridge, moderator) {
13120
13124
  providers,
13121
13125
  allowlist,
13122
13126
  moderator,
13123
- ...storage ? { storage } : {},
13124
- ...bridge ? { bridge } : {}
13127
+ ...storage ? { storage } : {}
13125
13128
  })
13126
13129
  };
13127
13130
  }
13128
- function explainTool(storage, bridge, transcriptsDir) {
13131
+ function explainTool(storage, transcriptsDir) {
13129
13132
  return {
13130
13133
  name: "explain",
13131
13134
  description: "Replay a session as a navigable tree with cost/latency annotations. Reads usage_log + optionally walks the transcripts directory for per-tool summaries.",
@@ -13143,12 +13146,11 @@ function explainTool(storage, bridge, transcriptsDir) {
13143
13146
  },
13144
13147
  handler: (args) => runExplain(args, {
13145
13148
  ...storage ? { storage } : {},
13146
- ...bridge ? { bridge } : {},
13147
13149
  ...transcriptsDir ? { transcriptsDir } : {}
13148
13150
  })
13149
13151
  };
13150
13152
  }
13151
- function scoreboardTool(storage, bridge, eventsPath) {
13153
+ function scoreboardTool(storage, eventsPath) {
13152
13154
  return {
13153
13155
  name: "scoreboard",
13154
13156
  description: "Aggregate provider ballot stats + delegation counts + table totals. Supports top_k (rank limit) and recent_limit (tail of events.jsonl when configured). Reads the engine's local stats database (auto-created at <data dir>/db.sqlite).",
@@ -13162,12 +13164,11 @@ function scoreboardTool(storage, bridge, eventsPath) {
13162
13164
  },
13163
13165
  handler: (args) => runScoreboard(args, {
13164
13166
  ...storage ? { storage } : {},
13165
- ...bridge ? { bridge } : {},
13166
13167
  ...eventsPath ? { eventsPath } : {}
13167
13168
  })
13168
13169
  };
13169
13170
  }
13170
- function sessionMemoryTool(storage, bridge) {
13171
+ function sessionMemoryTool(storage) {
13171
13172
  return {
13172
13173
  name: "session_memory",
13173
13174
  description: "CRUD over the per-session working memory ledger. Actions: list, add, mark_stale, clear. Uses the engine's local database (auto-created at <data dir>/db.sqlite).",
@@ -13190,15 +13191,14 @@ function sessionMemoryTool(storage, bridge) {
13190
13191
  required: ["action", "session_id"]
13191
13192
  },
13192
13193
  handler: (args) => runSessionMemory(args, {
13193
- ...storage ? { storage } : {},
13194
- ...bridge ? { bridge } : {}
13194
+ ...storage ? { storage } : {}
13195
13195
  })
13196
13196
  };
13197
13197
  }
13198
- function recallTool(storage, bridge) {
13198
+ function recallTool(storage) {
13199
13199
  return {
13200
13200
  name: "recall",
13201
- description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter; falls back to the Python bridge when not available.",
13201
+ description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter.",
13202
13202
  inputSchema: {
13203
13203
  type: "object",
13204
13204
  additionalProperties: true,
@@ -13212,8 +13212,7 @@ function recallTool(storage, bridge) {
13212
13212
  required: ["query"]
13213
13213
  },
13214
13214
  handler: (args) => runRecall(args, {
13215
- ...storage ? { storage } : {},
13216
- ...bridge ? { bridge } : {}
13215
+ ...storage ? { storage } : {}
13217
13216
  })
13218
13217
  };
13219
13218
  }
@@ -13249,7 +13248,7 @@ function modelsTool(providers, activeProviders) {
13249
13248
  handler: async (args) => runModels(args, { providers, activeProviders })
13250
13249
  };
13251
13250
  }
13252
- function reviewTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
13251
+ function reviewTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
13253
13252
  return {
13254
13253
  name: "review",
13255
13254
  description: "Have an LLM panel peer-review a code or proposal snippet. Returns the confer envelope (one answer per provider).",
@@ -13268,7 +13267,6 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
13268
13267
  handler: (args) => runReview(args, {
13269
13268
  providers,
13270
13269
  allowlist,
13271
- ...bridge ? { bridge } : {},
13272
13270
  ...storage ? { storage } : {},
13273
13271
  ...breakers ? { breakers } : {},
13274
13272
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13276,7 +13274,7 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
13276
13274
  })
13277
13275
  };
13278
13276
  }
13279
- function critiqueTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
13277
+ function critiqueTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
13280
13278
  return {
13281
13279
  name: "critique",
13282
13280
  description: "Have each LLM panelist list the top weaknesses of a proposed answer or approach (severity-rated). Returns per-provider weakness lists + a merged list ordered by severity.",
@@ -13296,7 +13294,6 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
13296
13294
  handler: (args) => runCritique(args, {
13297
13295
  providers,
13298
13296
  allowlist,
13299
- ...bridge ? { bridge } : {},
13300
13297
  ...storage ? { storage } : {},
13301
13298
  ...breakers ? { breakers } : {},
13302
13299
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13304,7 +13301,7 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
13304
13301
  })
13305
13302
  };
13306
13303
  }
13307
- function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
13304
+ function planTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
13308
13305
  return {
13309
13306
  name: "plan",
13310
13307
  description: 'Have an LLM panel debate a step-by-step plan for the stated goal under the given constraints. Returns the debate envelope with a moderator-synthesised plan. Defaults to `mode: "fast"` (2 rounds + early_stop) \u2014 set `mode: "thorough"` for 5 rounds without early_stop. Explicit `max_rounds` / `early_stop` / `early_stop_threshold` always override the mode preset. Use `structured: true` for schema-validated synthesis.',
@@ -13331,7 +13328,6 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
13331
13328
  handler: (args) => runPlan(args, {
13332
13329
  providers,
13333
13330
  allowlist,
13334
- ...bridge ? { bridge } : {},
13335
13331
  ...storage ? { storage } : {},
13336
13332
  ...breakers ? { breakers } : {},
13337
13333
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13339,7 +13335,7 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
13339
13335
  })
13340
13336
  };
13341
13337
  }
13342
- function triangulateTool(providers, allowlist, bridge, storage, breakers, transcriptsDir, repoRoot) {
13338
+ function triangulateTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
13343
13339
  return {
13344
13340
  name: "triangulate",
13345
13341
  description: "Run a coordinate flow and reshape the output as a consensus + minority report with per-provider weights. v1 uses 1.0 weights (matches a fresh provider_stats DB); future versions thread real win-rate weights when the DB layer ports.",
@@ -13360,7 +13356,6 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
13360
13356
  handler: (args) => runTriangulate(args, {
13361
13357
  providers,
13362
13358
  allowlist,
13363
- ...bridge ? { bridge } : {},
13364
13359
  ...storage ? { storage } : {},
13365
13360
  ...breakers ? { breakers } : {},
13366
13361
  ...transcriptsDir ? { transcriptsDir } : {},
@@ -13368,7 +13363,7 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
13368
13363
  })
13369
13364
  };
13370
13365
  }
13371
- function coordinateTool(providers, allowlist, bridge, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13366
+ function coordinateTool(providers, allowlist, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13372
13367
  return {
13373
13368
  name: "coordinate",
13374
13369
  description: "Run a three-role coordination flow (proposer \u2192 critics \u2192 synthesizer) with structured output at every step. Native opts: untrusted_input (canary + neutralize), worker_tools (bounded ReAct on proposer + critic roles; synth never sees inner tools), inject_session_memory (storage-backed working-memory block prepended to the topic).",
@@ -13393,7 +13388,6 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
13393
13388
  handler: (args) => runCoordinate(args, {
13394
13389
  providers,
13395
13390
  allowlist,
13396
- ...bridge ? { bridge } : {},
13397
13391
  innerCallers,
13398
13392
  ...storage ? { storage } : {},
13399
13393
  ...breakers ? { breakers } : {},
@@ -13403,7 +13397,7 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
13403
13397
  })
13404
13398
  };
13405
13399
  }
13406
- function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13400
+ function debateTool(providers, allowlist, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13407
13401
  return {
13408
13402
  name: "debate",
13409
13403
  description: "Run a multi-round debate between LLM providers and synthesise the result via a moderator. Native opts: inject_session_memory, auto_panel, worker_tools, structured synthesis (schema-validated), extract_claims (final-round distillation), early_stop (post-round agreement check).",
@@ -13433,7 +13427,6 @@ function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing
13433
13427
  handler: (args) => runDebate(args, {
13434
13428
  providers,
13435
13429
  allowlist,
13436
- ...bridge ? { bridge } : {},
13437
13430
  innerCallers,
13438
13431
  ...storage ? { storage } : {},
13439
13432
  ...pricing ? { pricing } : {},
@@ -13453,10 +13446,10 @@ function buildInnerCallers(o) {
13453
13446
  ...o.repoRoot ? { repoRoot: o.repoRoot } : {}
13454
13447
  });
13455
13448
  }
13456
- out.verify = (args) => runVerify(args, o.bridge, o.fetchConfig);
13449
+ out.verify = (args) => runVerify(args, o.fetchConfig);
13457
13450
  return out;
13458
13451
  }
13459
- function conferTool(providers, allowlist, bridge, moderator, pricing, storage, innerCallers, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13452
+ function conferTool(providers, allowlist, moderator, pricing, storage, innerCallers, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
13460
13453
  return {
13461
13454
  name: "confer",
13462
13455
  description: "Ask a panel of LLM providers the same question; return one answer per provider. Native opts: untrusted_input (canary + neutralization), early_stop (cheap-tier agreement check after first 2 panelists when N>=3), extract_claims (cheap-tier extractor with per-provider support maps), inject_session_memory (storage-backed working-memory block prepended to the first user message), auto_panel (router-driven top-N panel pick), worker_tools (bounded ReAct loop per panelist when innerCallers are wired by the host).",
@@ -13483,7 +13476,6 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
13483
13476
  handler: (args) => runConfer(args, {
13484
13477
  providers,
13485
13478
  allowlist,
13486
- ...bridge ? { bridge } : {},
13487
13479
  moderator,
13488
13480
  ...pricing ? { pricing } : {},
13489
13481
  ...storage ? { storage } : {},
@@ -13495,7 +13487,7 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
13495
13487
  })
13496
13488
  };
13497
13489
  }
13498
- function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storage, breakers, repoRoot) {
13490
+ function auditTool(providers, allowlist, transcriptsDir, pricing, storage, breakers, repoRoot) {
13499
13491
  return {
13500
13492
  name: "audit",
13501
13493
  description: "Score a piece of output against an audit rubric. Single-judge by default; coalesce-mode (multi-judge consensus) and panel-exhausted self-audit run natively. cheap_mode picks the cheapest 'med'-tier model as auditor when a pricing.json is wired. session_id-only inputs load the latest transcript automatically when a transcripts directory is wired.",
@@ -13521,7 +13513,6 @@ function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storag
13521
13513
  handler: (args) => runAudit(args, {
13522
13514
  providers,
13523
13515
  allowlist,
13524
- ...bridge ? { bridge } : {},
13525
13516
  ...transcriptsDir ? { transcriptsDir } : {},
13526
13517
  ...pricing ? { pricing } : {},
13527
13518
  ...storage ? { storage } : {},
@@ -13585,7 +13576,7 @@ function pickTool(providers, allowlist, storage, breakers, transcriptsDir, repoR
13585
13576
  })
13586
13577
  };
13587
13578
  }
13588
- function verifyTool(bridge, fetchConfig) {
13579
+ function verifyTool(fetchConfig) {
13589
13580
  return {
13590
13581
  name: "verify",
13591
13582
  description: "Run a list of deterministic property checks against caller-supplied data. No LLM calls; everything is local. Returns per-check {passed, reason} plus all_passed / summary / timing fields. Supports the text kinds (contains, not_contains, regex_match, contains_any, contains_all, min_length), shell (sandboxed subprocess with timeout + Unix pgid isolation), and url_head (HEAD request gated by fetch.url_allowlist). All kinds run natively.",
@@ -13603,7 +13594,7 @@ function verifyTool(bridge, fetchConfig) {
13603
13594
  },
13604
13595
  required: ["checks"]
13605
13596
  },
13606
- handler: (args) => runVerify(args, bridge, fetchConfig)
13597
+ handler: (args) => runVerify(args, fetchConfig)
13607
13598
  };
13608
13599
  }
13609
13600
  function pingTool() {
@@ -13653,7 +13644,7 @@ function createCrosscheck(opts) {
13653
13644
  // Direct runConfer call with a streaming hook — bypasses the tool
13654
13645
  // registry (whose handler signature can't carry a callback). Uses the
13655
13646
  // same opts the registry wires for confer in a browser build: providers
13656
- // + pricing + default moderator; storage/bridge/innerCallers aren't
13647
+ // + pricing + default moderator; storage/innerCallers aren't
13657
13648
  // available here, matching the non-streaming path.
13658
13649
  conferStream: (args, onAnswer) => runConfer(args, { providers, pricing: pricingDoc, moderator: "anthropic", onAnswer }),
13659
13650
  debateStream: (args, { onTurn, onSynthesis } = {}) => runDebate(args, {