crosscheck-mcp 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node-stdio.cjs +361 -16
- package/dist/node-stdio.cjs.map +1 -1
- package/dist/node-stdio.d.cts +14 -0
- package/dist/node-stdio.d.ts +14 -0
- package/dist/node-stdio.js +361 -16
- package/dist/node-stdio.js.map +1 -1
- package/dist/pricing.json +3 -1
- package/package.json +4 -8
package/dist/node-stdio.cjs
CHANGED
|
@@ -558,6 +558,22 @@ var init_better_sqlite3 = __esm({
|
|
|
558
558
|
ORDER BY purpose`
|
|
559
559
|
).all(sessionId);
|
|
560
560
|
}
|
|
561
|
+
async listUsageGroupedByModel(sessionId) {
|
|
562
|
+
return this.cached(
|
|
563
|
+
"usage-grp-model",
|
|
564
|
+
`SELECT provider,
|
|
565
|
+
model,
|
|
566
|
+
COUNT(*) AS calls,
|
|
567
|
+
COALESCE(SUM(prompt_tokens), 0) AS prompt_tokens,
|
|
568
|
+
COALESCE(SUM(completion_tokens), 0) AS completion_tokens,
|
|
569
|
+
COALESCE(SUM(total_tokens), 0) AS total_tokens,
|
|
570
|
+
COALESCE(SUM(cost_usd), 0) AS cost_usd
|
|
571
|
+
FROM usage_log
|
|
572
|
+
WHERE session_id = ?
|
|
573
|
+
GROUP BY provider, model
|
|
574
|
+
ORDER BY cost_usd DESC, provider, model`
|
|
575
|
+
).all(sessionId);
|
|
576
|
+
}
|
|
561
577
|
async listUsageGroupedByProvider(purpose) {
|
|
562
578
|
if (purpose !== void 0) {
|
|
563
579
|
return this.cached(
|
|
@@ -1076,7 +1092,8 @@ function modelPricing(pricing, provider, model) {
|
|
|
1076
1092
|
return {
|
|
1077
1093
|
prompt_per_1k: numberOrZero(e["prompt_per_1k"]),
|
|
1078
1094
|
completion_per_1k: numberOrZero(e["completion_per_1k"]),
|
|
1079
|
-
cached_per_1k: numberOrZero(e["cached_per_1k"])
|
|
1095
|
+
cached_per_1k: numberOrZero(e["cached_per_1k"]),
|
|
1096
|
+
...e["estimated"] === true ? { estimated: true } : {}
|
|
1080
1097
|
};
|
|
1081
1098
|
}
|
|
1082
1099
|
function numberOrZero(v) {
|
|
@@ -1096,7 +1113,7 @@ function calculateCost(pricing, provider, model, promptTokens, completionTokens,
|
|
|
1096
1113
|
const prompt = Math.max(0, Math.trunc(promptTokens) - cached);
|
|
1097
1114
|
const completion = Math.max(0, Math.trunc(completionTokens));
|
|
1098
1115
|
const raw = prompt / 1e3 * rates.prompt_per_1k + completion / 1e3 * rates.completion_per_1k + cached / 1e3 * rates.cached_per_1k;
|
|
1099
|
-
return { cost_usd: roundTo(raw, 8), estimated:
|
|
1116
|
+
return { cost_usd: roundTo(raw, 8), estimated: rates.estimated === true };
|
|
1100
1117
|
}
|
|
1101
1118
|
function roundTo(x, n) {
|
|
1102
1119
|
if (!Number.isFinite(x)) return 0;
|
|
@@ -1116,7 +1133,7 @@ var PROVIDER_CAPS = {
|
|
|
1116
1133
|
family: "anthropic",
|
|
1117
1134
|
system_role: "separate",
|
|
1118
1135
|
supports_temperature: "model",
|
|
1119
|
-
reasoning_prefixes: ["claude-opus-4-7", "claude-opus-4-8"]
|
|
1136
|
+
reasoning_prefixes: ["claude-opus-4-7", "claude-opus-4-8", "claude-fable-5"]
|
|
1120
1137
|
},
|
|
1121
1138
|
openai: {
|
|
1122
1139
|
family: "openai_chat",
|
|
@@ -2065,7 +2082,17 @@ Examples:
|
|
|
2065
2082
|
- \`xc what's the right caching strategy here?\` \u2192 \`mcp__crosscheck__${DEFAULT_TOOL}({ question: "what's the right caching strategy here?" })\` (no tool name match \u2192 default to ${DEFAULT_TOOL})
|
|
2066
2083
|
- \`XC how risky is this refactor?\` \u2192 same default-to-${DEFAULT_TOOL} behavior
|
|
2067
2084
|
|
|
2068
|
-
This convention is opt-in: a user message without the \`xc\`/\`XC\` prefix should NOT be auto-routed here. Pick tools normally based on the conversation
|
|
2085
|
+
This convention is opt-in: a user message without the \`xc\`/\`XC\` prefix should NOT be auto-routed here. Pick tools normally based on the conversation.
|
|
2086
|
+
|
|
2087
|
+
Reasoning upgrade (Fable 5):
|
|
2088
|
+
- The reasoning tools (plan, solve, debate, orchestrate, audit, triangulate) can bump their lead reasoning seat to Fable 5 \u2014 Anthropic's newest thinking model \u2014 instead of the default Opus 4.8. Only that one seat is upgraded; other panel seats stay on their normal models, so premium tokens are not wasted.
|
|
2089
|
+
- When a tool result includes a "suggested_upgrade" block, the engine judged the task reasoning-heavy. Surface it: ask the user something like "This looks reasoning-heavy \u2014 bump the lead seat to Fable 5 (higher quality, higher cost)?" If they say yes, re-run the SAME tool with reasoning:"max" added. Do NOT upgrade silently.
|
|
2090
|
+
- If the user explicitly asks for the best/deepest reasoning up front, pass reasoning:"max" directly. A result with reasoning_upgrade.applied = true confirms Fable 5 was used.
|
|
2091
|
+
|
|
2092
|
+
Spend visibility:
|
|
2093
|
+
- Every reasoning-tool result carries a "run_summary" whose pre-rendered "text" block already includes a "spend by model (this call)" breakdown. Show that block \u2014 do not bury the cost.
|
|
2094
|
+
- "run_summary" also carries "session_by_model" + "session_cost_usd" (per-model spend for the whole session). At the END of a multi-turn task, present the session spend per model plus the aggregate total, so the user knows what the task cost without scrolling back.
|
|
2095
|
+
- Fable 5's price is a provisional placeholder; rows from it are flagged "(est)"/estimated \u2014 say so when reporting those dollar figures.`;
|
|
2069
2096
|
}
|
|
2070
2097
|
|
|
2071
2098
|
// src/tools/index.ts
|
|
@@ -2321,6 +2348,7 @@ function roundCost(x) {
|
|
|
2321
2348
|
function aggregateUsage(usages) {
|
|
2322
2349
|
const byCall = usages.map((u) => ({ ...u }));
|
|
2323
2350
|
const byProvider = /* @__PURE__ */ new Map();
|
|
2351
|
+
const byModel = /* @__PURE__ */ new Map();
|
|
2324
2352
|
let totalPrompt = 0;
|
|
2325
2353
|
let totalCompletion = 0;
|
|
2326
2354
|
let totalCached = 0;
|
|
@@ -2348,6 +2376,29 @@ function aggregateUsage(usages) {
|
|
|
2348
2376
|
bp.cost_usd = roundCost(bp.cost_usd + u.cost_usd);
|
|
2349
2377
|
bp.calls += 1;
|
|
2350
2378
|
bp.estimated = bp.estimated || u.estimated;
|
|
2379
|
+
const modelKey = `${u.provider}/${u.model}`;
|
|
2380
|
+
let bm = byModel.get(modelKey);
|
|
2381
|
+
if (!bm) {
|
|
2382
|
+
bm = {
|
|
2383
|
+
provider: u.provider,
|
|
2384
|
+
model: u.model,
|
|
2385
|
+
prompt_tokens: 0,
|
|
2386
|
+
completion_tokens: 0,
|
|
2387
|
+
cached_tokens: 0,
|
|
2388
|
+
total_tokens: 0,
|
|
2389
|
+
cost_usd: 0,
|
|
2390
|
+
calls: 0,
|
|
2391
|
+
estimated: false
|
|
2392
|
+
};
|
|
2393
|
+
byModel.set(modelKey, bm);
|
|
2394
|
+
}
|
|
2395
|
+
bm.prompt_tokens += u.prompt_tokens;
|
|
2396
|
+
bm.completion_tokens += u.completion_tokens;
|
|
2397
|
+
bm.cached_tokens += u.cached_tokens;
|
|
2398
|
+
bm.total_tokens += u.total_tokens;
|
|
2399
|
+
bm.cost_usd = roundCost(bm.cost_usd + u.cost_usd);
|
|
2400
|
+
bm.calls += 1;
|
|
2401
|
+
bm.estimated = bm.estimated || u.estimated;
|
|
2351
2402
|
totalPrompt += u.prompt_tokens;
|
|
2352
2403
|
totalCompletion += u.completion_tokens;
|
|
2353
2404
|
totalCached += u.cached_tokens;
|
|
@@ -2357,6 +2408,7 @@ function aggregateUsage(usages) {
|
|
|
2357
2408
|
return {
|
|
2358
2409
|
by_call: byCall,
|
|
2359
2410
|
by_provider: Array.from(byProvider.values()),
|
|
2411
|
+
by_model: Array.from(byModel.values()),
|
|
2360
2412
|
totals: {
|
|
2361
2413
|
prompt_tokens: totalPrompt,
|
|
2362
2414
|
completion_tokens: totalCompletion,
|
|
@@ -2439,7 +2491,46 @@ function renderRunSummary(opts) {
|
|
|
2439
2491
|
`${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)`
|
|
2440
2492
|
);
|
|
2441
2493
|
}
|
|
2442
|
-
const
|
|
2494
|
+
const callByModel = rollupSpendByModel(
|
|
2495
|
+
opts.answers.map((a) => ({
|
|
2496
|
+
provider: a.usage?.provider ?? "",
|
|
2497
|
+
model: a.usage?.model ?? "",
|
|
2498
|
+
calls: 1,
|
|
2499
|
+
total_tokens: a.usage?.total_tokens ?? 0,
|
|
2500
|
+
cost_usd: a.usage?.cost_usd ?? 0,
|
|
2501
|
+
estimated: a.usage?.estimated ?? false
|
|
2502
|
+
})).filter((r) => r.provider !== "")
|
|
2503
|
+
);
|
|
2504
|
+
let sessionByModel;
|
|
2505
|
+
let sessionCost;
|
|
2506
|
+
if (opts.sessionModelRows && opts.sessionModelRows.length > 0) {
|
|
2507
|
+
sessionByModel = rollupSpendByModel(
|
|
2508
|
+
opts.sessionModelRows.map((r) => ({
|
|
2509
|
+
provider: r.provider,
|
|
2510
|
+
model: r.model,
|
|
2511
|
+
calls: r.calls,
|
|
2512
|
+
total_tokens: r.total_tokens,
|
|
2513
|
+
cost_usd: r.cost_usd,
|
|
2514
|
+
// Derive estimated from the pricing doc (SQL rows don't carry it).
|
|
2515
|
+
estimated: opts.pricing ? modelPricing(opts.pricing, r.provider, r.model)?.estimated === true : false
|
|
2516
|
+
}))
|
|
2517
|
+
);
|
|
2518
|
+
sessionCost = round8(sessionByModel.reduce((s, r) => s + r.cost_usd, 0));
|
|
2519
|
+
}
|
|
2520
|
+
const lines = [header, ...bodyLines];
|
|
2521
|
+
if (callByModel.length > 0) {
|
|
2522
|
+
lines.push("spend by model (this call):");
|
|
2523
|
+
lines.push(...renderSpendByModelLines(callByModel));
|
|
2524
|
+
}
|
|
2525
|
+
if (sessionByModel && sessionByModel.length > 0 && sessionCost !== void 0) {
|
|
2526
|
+
lines.push(
|
|
2527
|
+
`session so far \u2014 spend by model (${withCommas(
|
|
2528
|
+
sessionByModel.reduce((s, r) => s + r.total_tokens, 0)
|
|
2529
|
+
)} tokens, $${sessionCost.toFixed(4)}${sessionByModel.some((r) => r.estimated) ? " \xB7 includes estimated rates" : ""}):`
|
|
2530
|
+
);
|
|
2531
|
+
lines.push(...renderSpendByModelLines(sessionByModel));
|
|
2532
|
+
}
|
|
2533
|
+
const text = lines.join("\n");
|
|
2443
2534
|
return {
|
|
2444
2535
|
session_id: opts.sessionId,
|
|
2445
2536
|
tool: opts.toolName,
|
|
@@ -2449,9 +2540,47 @@ function renderRunSummary(opts) {
|
|
|
2449
2540
|
ended_at: endedAt,
|
|
2450
2541
|
rows,
|
|
2451
2542
|
totals,
|
|
2543
|
+
call_by_model: callByModel,
|
|
2544
|
+
...sessionByModel ? { session_by_model: sessionByModel } : {},
|
|
2545
|
+
...sessionCost !== void 0 ? { session_cost_usd: sessionCost } : {},
|
|
2452
2546
|
text
|
|
2453
2547
|
};
|
|
2454
2548
|
}
|
|
2549
|
+
function rollupSpendByModel(frags) {
|
|
2550
|
+
const m = /* @__PURE__ */ new Map();
|
|
2551
|
+
for (const f of frags) {
|
|
2552
|
+
const key = `${f.provider}/${f.model}`;
|
|
2553
|
+
let row = m.get(key);
|
|
2554
|
+
if (!row) {
|
|
2555
|
+
row = {
|
|
2556
|
+
provider: f.provider,
|
|
2557
|
+
model: f.model,
|
|
2558
|
+
calls: 0,
|
|
2559
|
+
total_tokens: 0,
|
|
2560
|
+
cost_usd: 0,
|
|
2561
|
+
estimated: false
|
|
2562
|
+
};
|
|
2563
|
+
m.set(key, row);
|
|
2564
|
+
}
|
|
2565
|
+
row.calls += f.calls;
|
|
2566
|
+
row.total_tokens += f.total_tokens;
|
|
2567
|
+
row.cost_usd = round8(row.cost_usd + f.cost_usd);
|
|
2568
|
+
row.estimated = row.estimated || f.estimated;
|
|
2569
|
+
}
|
|
2570
|
+
return Array.from(m.values()).sort(
|
|
2571
|
+
(a, b) => b.cost_usd - a.cost_usd || a.provider.localeCompare(b.provider)
|
|
2572
|
+
);
|
|
2573
|
+
}
|
|
2574
|
+
function renderSpendByModelLines(rows) {
|
|
2575
|
+
const nameW = Math.max(...rows.map((r) => `${r.provider}/${r.model}`.length), 0);
|
|
2576
|
+
return rows.map((r) => {
|
|
2577
|
+
const name = `${r.provider}/${r.model}`.padEnd(nameW);
|
|
2578
|
+
const calls = `${r.calls} call${r.calls === 1 ? "" : "s"}`.padStart(8);
|
|
2579
|
+
const toks = `${withCommas(r.total_tokens)} tok`.padStart(13);
|
|
2580
|
+
const cost = `$${r.cost_usd.toFixed(4)}`.padStart(10);
|
|
2581
|
+
return ` ${name} ${calls} ${toks} ${cost}${r.estimated ? " (est)" : ""}`;
|
|
2582
|
+
});
|
|
2583
|
+
}
|
|
2455
2584
|
async function attachUsageBlock(result, answers, opts) {
|
|
2456
2585
|
const allCalls = [...answers, ...opts?.extras ?? []];
|
|
2457
2586
|
const usages = [];
|
|
@@ -2487,7 +2616,12 @@ async function attachUsageBlock(result, answers, opts) {
|
|
|
2487
2616
|
result["timing"] = timing;
|
|
2488
2617
|
if (opts?.toolName && !result["_suppress_run_summary"]) {
|
|
2489
2618
|
let sessionScope;
|
|
2619
|
+
let sessionModelRows;
|
|
2490
2620
|
if (opts.storage && opts.sessionId) {
|
|
2621
|
+
try {
|
|
2622
|
+
sessionModelRows = await opts.storage.listUsageGroupedByModel(opts.sessionId);
|
|
2623
|
+
} catch {
|
|
2624
|
+
}
|
|
2491
2625
|
try {
|
|
2492
2626
|
const rows = await opts.storage.listUsageGroupedByPurpose(opts.sessionId);
|
|
2493
2627
|
if (rows.length > 0) {
|
|
@@ -2517,6 +2651,8 @@ async function attachUsageBlock(result, answers, opts) {
|
|
|
2517
2651
|
toolName: opts.toolName,
|
|
2518
2652
|
answers: allCalls,
|
|
2519
2653
|
...sessionScope ? { sessionScope } : {},
|
|
2654
|
+
...sessionModelRows && sessionModelRows.length > 0 ? { sessionModelRows } : {},
|
|
2655
|
+
...opts.pricing ? { pricing: opts.pricing } : {},
|
|
2520
2656
|
...opts.endedAtS !== void 0 ? { endedAtS: opts.endedAtS } : {}
|
|
2521
2657
|
});
|
|
2522
2658
|
}
|
|
@@ -3582,6 +3718,83 @@ function selectForDifficulty(args) {
|
|
|
3582
3718
|
};
|
|
3583
3719
|
}
|
|
3584
3720
|
|
|
3721
|
+
// src/core/reasoning-upgrade.ts
|
|
3722
|
+
init_cjs_shims();
|
|
3723
|
+
var UPGRADE_MODEL = "claude-fable-5";
|
|
3724
|
+
var UPGRADE_LABEL = "Fable 5";
|
|
3725
|
+
function isUpgradeRequested(args) {
|
|
3726
|
+
if (args["upgrade"] === true) return true;
|
|
3727
|
+
const reasoning = args["reasoning"];
|
|
3728
|
+
if (typeof reasoning === "string" && reasoning.trim().toLowerCase() === "max") {
|
|
3729
|
+
return true;
|
|
3730
|
+
}
|
|
3731
|
+
const model = args["model"];
|
|
3732
|
+
if (typeof model === "string") {
|
|
3733
|
+
const m = model.trim().toLowerCase();
|
|
3734
|
+
if (m === "fable5" || m === "fable-5" || m === "fable" || m === UPGRADE_MODEL) {
|
|
3735
|
+
return true;
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
return false;
|
|
3739
|
+
}
|
|
3740
|
+
var HEAVY_TERMS = [
|
|
3741
|
+
/\bprov(e|ing|en)\b|\bproof\b|\btheorem\b|\bderiv(e|ation)\b/i,
|
|
3742
|
+
/\barchitect(ure|ing)?\b|\bdesign\s+(a|the|an)\b|\bhigh[-\s]?level\s+design\b/i,
|
|
3743
|
+
/\btrade[-\s]?offs?\b|\bpros?\s+and\s+cons?\b|\bweigh\b/i,
|
|
3744
|
+
/\boptimi[sz]e\b|\bcomplexity\b|\bO\(|\balgorithm(ic)?\b/i,
|
|
3745
|
+
/\brace\s+condition\b|\bconcurren(t|cy)\b|\bdeadlock\b|\bdistributed\b|\bconsensus\b/i,
|
|
3746
|
+
/\broot[-\s]?cause\b|\bdebug(ging)?\b|\bwhy\s+(does|is|would|might)\b/i,
|
|
3747
|
+
/\bsecurity\b|\bthreat\s+model\b|\bexploit\b|\bvulnerabilit(y|ies)\b/i,
|
|
3748
|
+
/\bmigrat(e|ion)\b|\brefactor\b|\bre[-\s]?architect\b/i,
|
|
3749
|
+
/\binvariant\b|\bcorrectness\b|\bedge\s+cases?\b|\bformal(ly)?\b/i,
|
|
3750
|
+
/\bstrateg(y|ic|ies)\b|\bplan\s+(the|a|an|out)\b|\broadmap\b/i,
|
|
3751
|
+
/\breason\s+(through|about)\b|\bstep[-\s]?by[-\s]?step\b|\bthink\s+deeply\b/i,
|
|
3752
|
+
/\bnp[-\s]?(hard|complete)\b|\bgraph\b|\bstate\s+machine\b|\bconstraint\b/i
|
|
3753
|
+
];
|
|
3754
|
+
var DIFFICULTY_TERMS = /\b(hard|tricky|subtle|complex|complicated|non[-\s]?trivial|thorny|gnarly|difficult|deep)\b/i;
|
|
3755
|
+
function assessReasoning(text) {
|
|
3756
|
+
const s = typeof text === "string" ? text : "";
|
|
3757
|
+
const signals = [];
|
|
3758
|
+
let score = 0;
|
|
3759
|
+
let termHits = 0;
|
|
3760
|
+
for (const re of HEAVY_TERMS) {
|
|
3761
|
+
if (re.test(s)) termHits += 1;
|
|
3762
|
+
}
|
|
3763
|
+
if (termHits > 0) {
|
|
3764
|
+
const add = Math.min(termHits, 4);
|
|
3765
|
+
score += add;
|
|
3766
|
+
signals.push(`${termHits} reasoning cue${termHits === 1 ? "" : "s"}`);
|
|
3767
|
+
}
|
|
3768
|
+
if (DIFFICULTY_TERMS.test(s)) {
|
|
3769
|
+
score += 1;
|
|
3770
|
+
signals.push("explicit difficulty marker");
|
|
3771
|
+
}
|
|
3772
|
+
const words = s.split(/\s+/).filter(Boolean).length;
|
|
3773
|
+
if (words >= 120) {
|
|
3774
|
+
score += 2;
|
|
3775
|
+
signals.push("long, detailed prompt");
|
|
3776
|
+
} else if (words >= 50) {
|
|
3777
|
+
score += 1;
|
|
3778
|
+
signals.push("substantial prompt");
|
|
3779
|
+
}
|
|
3780
|
+
const constraints = (s.match(/\b(must|should|need to|ensure|require[ds]?|constraint)\b/gi) ?? []).length + (s.match(/(^|\n)\s*(?:[-*]|\d+[.)])\s+/g) ?? []).length;
|
|
3781
|
+
if (constraints >= 3) {
|
|
3782
|
+
score += 1;
|
|
3783
|
+
signals.push(`${constraints} constraints/steps`);
|
|
3784
|
+
}
|
|
3785
|
+
const heavy = score >= 3;
|
|
3786
|
+
const reason = heavy ? `Task looks reasoning-heavy (${signals.join(", ") || "score " + score}).` : `Task looks routine (score ${score}).`;
|
|
3787
|
+
return { heavy, score, reason, signals };
|
|
3788
|
+
}
|
|
3789
|
+
function buildSuggestedUpgrade(toolName, assessment) {
|
|
3790
|
+
return {
|
|
3791
|
+
model: UPGRADE_MODEL,
|
|
3792
|
+
label: UPGRADE_LABEL,
|
|
3793
|
+
reason: assessment.reason,
|
|
3794
|
+
how: `re-run \`${toolName}\` with reasoning:"max" (or upgrade:true) to route the lead reasoning seat to ${UPGRADE_LABEL}. Other panel seats stay on their normal models, so only the high-level reasoning uses the premium model.`
|
|
3795
|
+
};
|
|
3796
|
+
}
|
|
3797
|
+
|
|
3585
3798
|
// src/tools/audit.ts
|
|
3586
3799
|
var AUDIT_OBVIOUS_FAILURE_HIGH = 0.3;
|
|
3587
3800
|
var AUDIT_OBVIOUS_FAILURE_MED = 0.2;
|
|
@@ -3848,7 +4061,10 @@ ${rubricText}`;
|
|
|
3848
4061
|
"Set ANTHROPIC_API_KEY or another provider in .env, or set `allow_self_audit=true` to permit the producing panel to self-grade."
|
|
3849
4062
|
);
|
|
3850
4063
|
}
|
|
3851
|
-
const
|
|
4064
|
+
const upgradeRequested = isUpgradeRequested(args);
|
|
4065
|
+
const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
|
|
4066
|
+
const auditorForCall = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : auditor;
|
|
4067
|
+
const r = await requestStructured(auditorForCall, msgs, AUDIT_RUBRIC_SCHEMA, {
|
|
3852
4068
|
maxTokens: 2048,
|
|
3853
4069
|
maxRetries: 1,
|
|
3854
4070
|
purpose: "audit"
|
|
@@ -3890,7 +4106,7 @@ ${rubricText}`;
|
|
|
3890
4106
|
tool: "audit",
|
|
3891
4107
|
mode: "single",
|
|
3892
4108
|
strict_mode: strictMode,
|
|
3893
|
-
auditor: { provider:
|
|
4109
|
+
auditor: { provider: auditorForCall.name, model: auditorForCall.model },
|
|
3894
4110
|
rubric: rubricItems,
|
|
3895
4111
|
items: itemsWithMeta,
|
|
3896
4112
|
overall_score: overall,
|
|
@@ -3898,6 +4114,26 @@ ${rubricText}`;
|
|
|
3898
4114
|
};
|
|
3899
4115
|
if (persona.meta.used !== null) result["persona"] = persona.meta;
|
|
3900
4116
|
if (errs.length > 0) result["validation_errors"] = errs;
|
|
4117
|
+
if (upgraded) {
|
|
4118
|
+
result["reasoning_upgrade"] = {
|
|
4119
|
+
applied: true,
|
|
4120
|
+
model: UPGRADE_MODEL,
|
|
4121
|
+
label: UPGRADE_LABEL,
|
|
4122
|
+
seat: "auditor"
|
|
4123
|
+
};
|
|
4124
|
+
} else if (upgradeRequested) {
|
|
4125
|
+
result["reasoning_upgrade"] = {
|
|
4126
|
+
applied: false,
|
|
4127
|
+
reason: `no Anthropic key available \u2014 the ${UPGRADE_LABEL} upgrade needs it.`
|
|
4128
|
+
};
|
|
4129
|
+
} else {
|
|
4130
|
+
const assessment = assessReasoning(
|
|
4131
|
+
typeof outputToAudit === "string" ? outputToAudit : String(outputToAudit ?? "")
|
|
4132
|
+
);
|
|
4133
|
+
if (assessment.heavy && opts.providers["anthropic"]) {
|
|
4134
|
+
result["suggested_upgrade"] = buildSuggestedUpgrade("audit", assessment);
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
3901
4137
|
if (!allPass && opts.storage && typeof sessionId === "string" && sessionId) {
|
|
3902
4138
|
const marked = await markStaleOnAuditFailure(
|
|
3903
4139
|
opts.storage,
|
|
@@ -7550,7 +7786,12 @@ ${recombineSys}` : recombineSys },
|
|
|
7550
7786
|
];
|
|
7551
7787
|
let synthProvider = moderator;
|
|
7552
7788
|
let synthModel = null;
|
|
7553
|
-
|
|
7789
|
+
const upgradeRequested = isUpgradeRequested(args);
|
|
7790
|
+
const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
|
|
7791
|
+
if (upgraded) {
|
|
7792
|
+
synthProvider = retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL);
|
|
7793
|
+
synthModel = `anthropic/${UPGRADE_MODEL}`;
|
|
7794
|
+
} else if (cheapMode && opts.pricing) {
|
|
7554
7795
|
const pick = selectForDifficulty({
|
|
7555
7796
|
pricing: opts.pricing,
|
|
7556
7797
|
tier: "med",
|
|
@@ -7621,6 +7862,24 @@ ${recombineSys}` : recombineSys },
|
|
|
7621
7862
|
if (personaMeta.used !== null) result["persona"] = personaMeta;
|
|
7622
7863
|
if (synthModel) result["synth_model"] = synthModel;
|
|
7623
7864
|
if (synthErr) result["synth_error"] = synthErr;
|
|
7865
|
+
if (upgraded) {
|
|
7866
|
+
result["reasoning_upgrade"] = {
|
|
7867
|
+
applied: true,
|
|
7868
|
+
model: UPGRADE_MODEL,
|
|
7869
|
+
label: UPGRADE_LABEL,
|
|
7870
|
+
seat: "recombine/synthesis"
|
|
7871
|
+
};
|
|
7872
|
+
} else if (upgradeRequested) {
|
|
7873
|
+
result["reasoning_upgrade"] = {
|
|
7874
|
+
applied: false,
|
|
7875
|
+
reason: `no Anthropic key available \u2014 the ${UPGRADE_LABEL} upgrade needs it.`
|
|
7876
|
+
};
|
|
7877
|
+
} else if (goal) {
|
|
7878
|
+
const assessment = assessReasoning(goal);
|
|
7879
|
+
if (assessment.heavy && opts.providers["anthropic"]) {
|
|
7880
|
+
result["suggested_upgrade"] = buildSuggestedUpgrade("orchestrate", assessment);
|
|
7881
|
+
}
|
|
7882
|
+
}
|
|
7624
7883
|
if (plannerErrors.length > 0) result["planner_errors"] = plannerErrors;
|
|
7625
7884
|
if (unknownNames.length > 0) result["skipped_unknown_providers"] = unknownNames;
|
|
7626
7885
|
if (blocked.length > 0) result["blocked_by_allowlist"] = blocked;
|
|
@@ -8792,6 +9051,9 @@ async function runCoordinate(args, opts) {
|
|
|
8792
9051
|
const synthName = typeof args["synthesizer"] === "string" && args["synthesizer"] ? args["synthesizer"] : typeof args["moderator"] === "string" && args["moderator"] ? args["moderator"] : opts.moderator ?? "anthropic";
|
|
8793
9052
|
const proposer = opts.providers[proposerName.toLowerCase()] ?? selected[0];
|
|
8794
9053
|
const synth = opts.providers[synthName.toLowerCase()] ?? proposer;
|
|
9054
|
+
const upgradeRequested = isUpgradeRequested(args);
|
|
9055
|
+
const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
|
|
9056
|
+
const synthForCall = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : synth;
|
|
8795
9057
|
let critics = [];
|
|
8796
9058
|
if (Array.isArray(args["critics"])) {
|
|
8797
9059
|
for (const n of args["critics"]) {
|
|
@@ -8940,7 +9202,7 @@ ${critiqueBlock}`
|
|
|
8940
9202
|
}
|
|
8941
9203
|
];
|
|
8942
9204
|
const synthResult = await requestStructured(
|
|
8943
|
-
|
|
9205
|
+
synthForCall,
|
|
8944
9206
|
synthMessages,
|
|
8945
9207
|
STRUCTURED_SYNTHESIS_SCHEMA,
|
|
8946
9208
|
{ maxTokens, maxRetries: 1, purpose: "synth" }
|
|
@@ -8989,6 +9251,24 @@ ${critiqueBlock}`
|
|
|
8989
9251
|
}
|
|
8990
9252
|
if (unknownNames.length > 0) result["skipped_unknown_providers"] = unknownNames;
|
|
8991
9253
|
if (blocked.length > 0) result["blocked_by_allowlist"] = blocked;
|
|
9254
|
+
if (upgraded) {
|
|
9255
|
+
result["reasoning_upgrade"] = {
|
|
9256
|
+
applied: true,
|
|
9257
|
+
model: UPGRADE_MODEL,
|
|
9258
|
+
label: UPGRADE_LABEL,
|
|
9259
|
+
seat: "synthesizer"
|
|
9260
|
+
};
|
|
9261
|
+
} else if (upgradeRequested) {
|
|
9262
|
+
result["reasoning_upgrade"] = {
|
|
9263
|
+
applied: false,
|
|
9264
|
+
reason: `no Anthropic key available \u2014 the ${UPGRADE_LABEL} upgrade needs it.`
|
|
9265
|
+
};
|
|
9266
|
+
} else {
|
|
9267
|
+
const assessment = assessReasoning(topic);
|
|
9268
|
+
if (assessment.heavy && opts.providers["anthropic"]) {
|
|
9269
|
+
result["suggested_upgrade"] = buildSuggestedUpgrade("coordinate", assessment);
|
|
9270
|
+
}
|
|
9271
|
+
}
|
|
8992
9272
|
const allCallEnvelopes = [
|
|
8993
9273
|
scannedProposal,
|
|
8994
9274
|
...scannedCritiques,
|
|
@@ -9529,6 +9809,8 @@ async function runDebate(args, opts) {
|
|
|
9529
9809
|
let agreementBlock = null;
|
|
9530
9810
|
const moderatorName = typeof args["moderator"] === "string" && args["moderator"] ? args["moderator"] : opts.moderator ?? "anthropic";
|
|
9531
9811
|
const moderator = opts.providers[moderatorName.toLowerCase()] ?? selected[0];
|
|
9812
|
+
const upgradeRequested = isUpgradeRequested(args);
|
|
9813
|
+
const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
|
|
9532
9814
|
for (let rnd = 1; rnd <= maxRounds; rnd++) {
|
|
9533
9815
|
const roundMessages = [
|
|
9534
9816
|
{
|
|
@@ -9590,6 +9872,7 @@ ${prior}` });
|
|
|
9590
9872
|
let synthesisErrors = [];
|
|
9591
9873
|
let personaMeta = null;
|
|
9592
9874
|
if (moderator) {
|
|
9875
|
+
const synthProvider = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : moderator;
|
|
9593
9876
|
const condensed = transcript.map(
|
|
9594
9877
|
(e) => `[${e.provider} \u2014 round ${e.round}]
|
|
9595
9878
|
${e.response ?? "(error)"}`
|
|
@@ -9620,7 +9903,7 @@ ${condensed}`
|
|
|
9620
9903
|
];
|
|
9621
9904
|
if (structuredOpt) {
|
|
9622
9905
|
const r = await requestStructured(
|
|
9623
|
-
|
|
9906
|
+
synthProvider,
|
|
9624
9907
|
synthMessages,
|
|
9625
9908
|
STRUCTURED_SYNTHESIS_SCHEMA,
|
|
9626
9909
|
{ maxTokens, maxRetries: 1, purpose: "synth" }
|
|
@@ -9629,7 +9912,7 @@ ${condensed}`
|
|
|
9629
9912
|
synthesisStructured = r.obj;
|
|
9630
9913
|
synthesisErrors = r.errors;
|
|
9631
9914
|
} else {
|
|
9632
|
-
synthesis = await askOne(
|
|
9915
|
+
synthesis = await askOne(synthProvider, synthMessages, {
|
|
9633
9916
|
maxTokens,
|
|
9634
9917
|
temperature: 0.4,
|
|
9635
9918
|
purpose: "synth"
|
|
@@ -9661,6 +9944,24 @@ ${condensed}`
|
|
|
9661
9944
|
synthesis
|
|
9662
9945
|
};
|
|
9663
9946
|
if (personaMeta && personaMeta.used !== null) result["persona"] = personaMeta;
|
|
9947
|
+
if (upgraded) {
|
|
9948
|
+
result["reasoning_upgrade"] = {
|
|
9949
|
+
applied: true,
|
|
9950
|
+
model: UPGRADE_MODEL,
|
|
9951
|
+
label: UPGRADE_LABEL,
|
|
9952
|
+
seat: "moderator synthesis"
|
|
9953
|
+
};
|
|
9954
|
+
} else if (upgradeRequested) {
|
|
9955
|
+
result["reasoning_upgrade"] = {
|
|
9956
|
+
applied: false,
|
|
9957
|
+
reason: `no Anthropic key available \u2014 the ${UPGRADE_LABEL} upgrade needs it.`
|
|
9958
|
+
};
|
|
9959
|
+
} else {
|
|
9960
|
+
const assessment = assessReasoning(topic);
|
|
9961
|
+
if (assessment.heavy && opts.providers["anthropic"]) {
|
|
9962
|
+
result["suggested_upgrade"] = buildSuggestedUpgrade("debate", assessment);
|
|
9963
|
+
}
|
|
9964
|
+
}
|
|
9664
9965
|
if (synthesisStructured !== null) {
|
|
9665
9966
|
result["synthesis_structured"] = synthesisStructured;
|
|
9666
9967
|
}
|
|
@@ -10732,7 +11033,15 @@ Return: (1) the plan as numbered steps, (2) risks, (3) alternatives considered.`
|
|
|
10732
11033
|
if (args["providers"] !== void 0) debateArgs["providers"] = args["providers"];
|
|
10733
11034
|
if (args["moderator"] !== void 0) debateArgs["moderator"] = args["moderator"];
|
|
10734
11035
|
if (args["session_id"] !== void 0) debateArgs["session_id"] = args["session_id"];
|
|
10735
|
-
|
|
11036
|
+
if (args["reasoning"] !== void 0) debateArgs["reasoning"] = args["reasoning"];
|
|
11037
|
+
if (args["upgrade"] !== void 0) debateArgs["upgrade"] = args["upgrade"];
|
|
11038
|
+
if (args["model"] !== void 0) debateArgs["model"] = args["model"];
|
|
11039
|
+
const result = await runDebate(debateArgs, opts);
|
|
11040
|
+
if (result["suggested_upgrade"] && typeof result["suggested_upgrade"] === "object") {
|
|
11041
|
+
const su = result["suggested_upgrade"];
|
|
11042
|
+
su["how"] = `re-run \`plan\` with reasoning:"max" (or upgrade:true) to route the plan-synthesis seat to Fable 5. The debaters stay on their normal models.`;
|
|
11043
|
+
}
|
|
11044
|
+
return result;
|
|
10736
11045
|
}
|
|
10737
11046
|
|
|
10738
11047
|
// src/tools/recall.ts
|
|
@@ -11465,8 +11774,11 @@ ${problem}` : problem;
|
|
|
11465
11774
|
let winningProvider = null;
|
|
11466
11775
|
let lastVerification = null;
|
|
11467
11776
|
const maxTokens = opts.maxTokens ?? 4096;
|
|
11777
|
+
const upgradeRequested = isUpgradeRequested(args);
|
|
11778
|
+
const fableProvider = upgradeRequested && opts.providers["anthropic"] ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : null;
|
|
11779
|
+
const upgraded = fableProvider !== null;
|
|
11468
11780
|
for (let i = 1; i <= maxAttempts; i++) {
|
|
11469
|
-
const provider = selected[(i - 1) % selected.length];
|
|
11781
|
+
const provider = fableProvider ?? selected[(i - 1) % selected.length];
|
|
11470
11782
|
const msgs = [
|
|
11471
11783
|
{ role: "system", content: systemMsg },
|
|
11472
11784
|
{ role: "user", content: userBlock }
|
|
@@ -11563,6 +11875,24 @@ Re-emit the FULL solution. No commentary.`
|
|
|
11563
11875
|
}
|
|
11564
11876
|
if (unknownNames.length > 0) result["skipped_unknown_providers"] = unknownNames;
|
|
11565
11877
|
if (blocked.length > 0) result["blocked_by_allowlist"] = blocked;
|
|
11878
|
+
if (upgraded) {
|
|
11879
|
+
result["reasoning_upgrade"] = {
|
|
11880
|
+
applied: true,
|
|
11881
|
+
model: UPGRADE_MODEL,
|
|
11882
|
+
label: UPGRADE_LABEL,
|
|
11883
|
+
seat: "solver"
|
|
11884
|
+
};
|
|
11885
|
+
} else if (upgradeRequested) {
|
|
11886
|
+
result["reasoning_upgrade"] = {
|
|
11887
|
+
applied: false,
|
|
11888
|
+
reason: `no Anthropic key available \u2014 the ${UPGRADE_LABEL} upgrade needs it.`
|
|
11889
|
+
};
|
|
11890
|
+
} else {
|
|
11891
|
+
const assessment = assessReasoning(problem);
|
|
11892
|
+
if (assessment.heavy && opts.providers["anthropic"]) {
|
|
11893
|
+
result["suggested_upgrade"] = buildSuggestedUpgrade("solve", assessment);
|
|
11894
|
+
}
|
|
11895
|
+
}
|
|
11566
11896
|
const sessionId = typeof args["session_id"] === "string" ? args["session_id"] : null;
|
|
11567
11897
|
const allCallEnvelopes = solveAnswers;
|
|
11568
11898
|
const wallMs = Math.trunc(import_node_perf_hooks11.performance.now() - callStartedWall);
|
|
@@ -11841,7 +12171,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
|
|
|
11841
12171
|
var DEFAULT_PACKAGE = "crosscheck-cli";
|
|
11842
12172
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
11843
12173
|
function engineVersion() {
|
|
11844
|
-
return true ? "0.1.
|
|
12174
|
+
return true ? "0.1.15" : "0.0.0-dev";
|
|
11845
12175
|
}
|
|
11846
12176
|
function defaultUpdateCachePath() {
|
|
11847
12177
|
const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path13.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
|
|
@@ -12195,6 +12525,9 @@ async function runTriangulate(args, opts) {
|
|
|
12195
12525
|
};
|
|
12196
12526
|
if (args["providers"] !== void 0) coordArgs["providers"] = args["providers"];
|
|
12197
12527
|
if (args["session_id"] !== void 0) coordArgs["session_id"] = args["session_id"];
|
|
12528
|
+
if (args["reasoning"] !== void 0) coordArgs["reasoning"] = args["reasoning"];
|
|
12529
|
+
if (args["upgrade"] !== void 0) coordArgs["upgrade"] = args["upgrade"];
|
|
12530
|
+
if (args["model"] !== void 0) coordArgs["model"] = args["model"];
|
|
12198
12531
|
const coord = await runCoordinate(coordArgs, opts);
|
|
12199
12532
|
if (typeof coord["error"] === "string") return coord;
|
|
12200
12533
|
const synth = coord["synthesis_structured"] ?? {};
|
|
@@ -12243,10 +12576,16 @@ async function runTriangulate(args, opts) {
|
|
|
12243
12576
|
"session",
|
|
12244
12577
|
"transcript_path",
|
|
12245
12578
|
"blocked_by_allowlist",
|
|
12246
|
-
"skipped_unknown_providers"
|
|
12579
|
+
"skipped_unknown_providers",
|
|
12580
|
+
"reasoning_upgrade",
|
|
12581
|
+
"suggested_upgrade"
|
|
12247
12582
|
]) {
|
|
12248
12583
|
if (k in coord) result[k] = coord[k];
|
|
12249
12584
|
}
|
|
12585
|
+
if (result["suggested_upgrade"] && typeof result["suggested_upgrade"] === "object") {
|
|
12586
|
+
const su = result["suggested_upgrade"];
|
|
12587
|
+
su["how"] = `re-run \`triangulate\` with reasoning:"max" (or upgrade:true) to route the synthesizer seat to Fable 5. The proposer + critics stay on their normal models.`;
|
|
12588
|
+
}
|
|
12250
12589
|
return result;
|
|
12251
12590
|
}
|
|
12252
12591
|
|
|
@@ -12467,6 +12806,7 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
|
|
|
12467
12806
|
additionalProperties: true,
|
|
12468
12807
|
properties: {
|
|
12469
12808
|
goal: { type: "string" },
|
|
12809
|
+
reasoning: { type: "string", enum: ["default", "max"], description: '"max" bumps the recombine/synthesis seat to Fable 5 (premium thinking model); worker nodes stay on their normal (incl. cheap-mode) models. Omit for the default.' },
|
|
12470
12810
|
dag: { type: "object", additionalProperties: true },
|
|
12471
12811
|
context: { type: "string" },
|
|
12472
12812
|
providers: { type: "array", items: { type: "string" } },
|
|
@@ -12501,6 +12841,7 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
|
|
|
12501
12841
|
additionalProperties: true,
|
|
12502
12842
|
properties: {
|
|
12503
12843
|
problem: { type: "string" },
|
|
12844
|
+
reasoning: { type: "string", enum: ["default", "max"], description: '"max" bumps the lead reasoning seat to Fable 5 (premium thinking model) for this call; other seats stay on their normal models. Omit for the Opus 4.8 default.' },
|
|
12504
12845
|
verifier: { type: "object", additionalProperties: true },
|
|
12505
12846
|
context: { type: "string" },
|
|
12506
12847
|
max_attempts: { type: "integer", minimum: 1 },
|
|
@@ -12835,6 +13176,7 @@ function planTool(providers, allowlist, bridge) {
|
|
|
12835
13176
|
additionalProperties: true,
|
|
12836
13177
|
properties: {
|
|
12837
13178
|
goal: { type: "string" },
|
|
13179
|
+
reasoning: { type: "string", enum: ["default", "max"], description: '"max" bumps the plan-synthesis seat to Fable 5 (premium thinking model); the debaters stay on their normal models. Omit for the Opus 4.8 default.' },
|
|
12838
13180
|
constraints: { type: "string" },
|
|
12839
13181
|
context: { type: "string" },
|
|
12840
13182
|
providers: { type: "array", items: { type: "string" } },
|
|
@@ -12864,6 +13206,7 @@ function triangulateTool(providers, allowlist, bridge) {
|
|
|
12864
13206
|
additionalProperties: true,
|
|
12865
13207
|
properties: {
|
|
12866
13208
|
question: { type: "string" },
|
|
13209
|
+
reasoning: { type: "string", enum: ["default", "max"], description: '"max" bumps the synthesizer seat to Fable 5 (premium thinking model); the proposer + critics stay on their normal models. Omit for the default.' },
|
|
12867
13210
|
context: { type: "string" },
|
|
12868
13211
|
providers: { type: "array", items: { type: "string" } },
|
|
12869
13212
|
session_id: { type: "string" },
|
|
@@ -12927,6 +13270,7 @@ function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing
|
|
|
12927
13270
|
providers: { type: "array", items: { type: "string" } },
|
|
12928
13271
|
moderator: { type: "string" },
|
|
12929
13272
|
session_id: { type: "string" },
|
|
13273
|
+
reasoning: { type: "string", enum: ["default", "max"], description: '"max" bumps the moderator-synthesis seat to Fable 5 (premium thinking model); the debaters stay on their normal models. Omit for the Opus 4.8 default.' },
|
|
12930
13274
|
structured: { type: "boolean" },
|
|
12931
13275
|
extract_claims: { type: "boolean" },
|
|
12932
13276
|
early_stop: { type: "boolean" },
|
|
@@ -13011,6 +13355,7 @@ function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storag
|
|
|
13011
13355
|
additionalProperties: true,
|
|
13012
13356
|
properties: {
|
|
13013
13357
|
output_to_audit: { type: "string" },
|
|
13358
|
+
reasoning: { type: "string", enum: ["default", "max"], description: '"max" bumps the auditor seat to Fable 5 (premium thinking model) in single-auditor mode. Omit for the default.' },
|
|
13014
13359
|
session_id: { type: "string" },
|
|
13015
13360
|
auditor: { type: "string" },
|
|
13016
13361
|
producing_panelists: { type: "array", items: { type: "string" } },
|
|
@@ -13373,7 +13718,7 @@ async function flush() {
|
|
|
13373
13718
|
|
|
13374
13719
|
// src/server.ts
|
|
13375
13720
|
var SERVER_NAME = "crosscheck-agent";
|
|
13376
|
-
var SERVER_VERSION = true ? "0.1.
|
|
13721
|
+
var SERVER_VERSION = true ? "0.1.15" : "0.0.0-dev";
|
|
13377
13722
|
function extractRunSummaryText(out) {
|
|
13378
13723
|
if (out === null || typeof out !== "object" || Array.isArray(out)) return void 0;
|
|
13379
13724
|
const rs = out["run_summary"];
|