crosscheck-mcp 0.2.2 → 0.2.4

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.
@@ -464,6 +464,7 @@ interface FetchConfig {
464
464
 
465
465
  declare const SERVER_NAME = "crosscheck-agent";
466
466
  declare const SERVER_VERSION: string;
467
+
467
468
  interface CreateServerOptions {
468
469
  /** Optional Python bridge. When supplied, the bridge's tools are
469
470
  * merged into the registry as proxy entries — they forward `tools/call`
@@ -464,6 +464,7 @@ interface FetchConfig {
464
464
 
465
465
  declare const SERVER_NAME = "crosscheck-agent";
466
466
  declare const SERVER_VERSION: string;
467
+
467
468
  interface CreateServerOptions {
468
469
  /** Optional Python bridge. When supplied, the bridge's tools are
469
470
  * merged into the registry as proxy entries — they forward `tools/call`
@@ -1459,7 +1459,10 @@ function buildAnthropicRequest(opts) {
1459
1459
  const headers = {
1460
1460
  "content-type": "application/json",
1461
1461
  "x-api-key": opts.apiKey,
1462
- "anthropic-version": ANTHROPIC_VERSION_HEADER
1462
+ "anthropic-version": ANTHROPIC_VERSION_HEADER,
1463
+ // Required for browser-origin calls (the Chrome extension); harmless from
1464
+ // Node. Without it the Anthropic API rejects requests made from a browser.
1465
+ "anthropic-dangerous-direct-browser-access": "true"
1463
1466
  };
1464
1467
  return { url: ANTHROPIC_API_URL, headers, body };
1465
1468
  }
@@ -1921,7 +1924,7 @@ async function sendOpenAICompatible(args) {
1921
1924
  // src/providers/registry.ts
1922
1925
  var DEFAULT_MODELS = {
1923
1926
  anthropic: "claude-opus-4-8",
1924
- openai: "gpt-5",
1927
+ openai: "gpt-5.5",
1925
1928
  xai: "grok-4-latest",
1926
1929
  mistral: "mistral-large-latest",
1927
1930
  groq: "llama-3.3-70b-versatile",
@@ -2135,6 +2138,11 @@ Spend visibility:
2135
2138
  init_esm_shims();
2136
2139
  import { z } from "zod";
2137
2140
 
2141
+ // src/server-meta.ts
2142
+ init_esm_shims();
2143
+ var SERVER_NAME = "crosscheck-agent";
2144
+ var SERVER_VERSION = true ? "0.2.4" : "0.0.0-dev";
2145
+
2138
2146
  // src/tools/audit.ts
2139
2147
  init_esm_shims();
2140
2148
  import { readdirSync, readFileSync as readFileSync3, statSync } from "fs";
@@ -3633,6 +3641,51 @@ async function loadProviderWeights(storage, names) {
3633
3641
  return out;
3634
3642
  }
3635
3643
 
3644
+ // src/core/co-reason.ts
3645
+ init_esm_shims();
3646
+ var CO_REASON_MODEL = "gpt-5.6";
3647
+ var CO_REASON_PROVIDER = "openai";
3648
+ var CO_REASON_LABEL = "GPT-5.6";
3649
+ function pickCoReasoner(providers, upgradeRequested) {
3650
+ if (!upgradeRequested) return null;
3651
+ const base = providers[CO_REASON_PROVIDER];
3652
+ return base ? retargetProvider(base, CO_REASON_MODEL) : null;
3653
+ }
3654
+ async function coReasonThenInject(opts) {
3655
+ const { provider, messages, maxTokens } = opts;
3656
+ if (!provider) return { messages, answer: null };
3657
+ const answer = await askOne(provider, messages, {
3658
+ maxTokens,
3659
+ temperature: 0.3,
3660
+ purpose: opts.purpose ?? "co-reason"
3661
+ });
3662
+ const text = typeof answer.response === "string" ? answer.response.trim() : "";
3663
+ if (answer.error !== void 0 || !text) {
3664
+ return { messages, answer };
3665
+ }
3666
+ return { messages: injectSecondOpinion(messages, text), answer };
3667
+ }
3668
+ function secondOpinionBlock(analysis) {
3669
+ return `
3670
+
3671
+ --- SECOND-OPINION ANALYSIS (${CO_REASON_LABEL}) ---
3672
+ Another top-tier model analyzed the same task. Weigh it critically \u2014 it may be wrong or incomplete \u2014 then produce your own final answer.
3673
+
3674
+ ${analysis}`;
3675
+ }
3676
+ function injectSecondOpinion(messages, analysis) {
3677
+ const block = secondOpinionBlock(analysis);
3678
+ const out = messages.map((m) => ({ ...m }));
3679
+ for (let i = out.length - 1; i >= 0; i--) {
3680
+ if (out[i].role === "user") {
3681
+ out[i] = { ...out[i], content: String(out[i].content) + block };
3682
+ return out;
3683
+ }
3684
+ }
3685
+ out.push({ role: "user", content: block.trimStart() });
3686
+ return out;
3687
+ }
3688
+
3636
3689
  // src/core/tiers.ts
3637
3690
  init_esm_shims();
3638
3691
 
@@ -3827,7 +3880,7 @@ function buildSuggestedUpgrade(toolName, assessment) {
3827
3880
  model: UPGRADE_MODEL,
3828
3881
  label: UPGRADE_LABEL,
3829
3882
  reason: assessment.reason,
3830
- 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.`
3883
+ 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.`
3831
3884
  };
3832
3885
  }
3833
3886
 
@@ -3976,7 +4029,7 @@ ${outputResolved}
3976
4029
 
3977
4030
  RUBRIC ITEMS:
3978
4031
  ${rubricText}`;
3979
- const msgs = [
4032
+ let msgs = [
3980
4033
  { role: "system", content: sysMsg },
3981
4034
  { role: "user", content: userMsg }
3982
4035
  ];
@@ -4100,6 +4153,15 @@ ${rubricText}`;
4100
4153
  const upgradeRequested = isUpgradeRequested(args);
4101
4154
  const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
4102
4155
  const auditorForCall = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : auditor;
4156
+ const coReason = await coReasonThenInject({
4157
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
4158
+ messages: msgs,
4159
+ maxTokens: 2048,
4160
+ purpose: "audit-coreason"
4161
+ });
4162
+ msgs = coReason.messages;
4163
+ if (coReason.answer) auditAnswers.push(coReason.answer);
4164
+ const coReasoned = coReason.answer !== null;
4103
4165
  const r = await requestStructured(auditorForCall, msgs, AUDIT_RUBRIC_SCHEMA, {
4104
4166
  maxTokens: 2048,
4105
4167
  maxRetries: 1,
@@ -4155,7 +4217,8 @@ ${rubricText}`;
4155
4217
  applied: true,
4156
4218
  model: UPGRADE_MODEL,
4157
4219
  label: UPGRADE_LABEL,
4158
- seat: "auditor"
4220
+ seat: "auditor",
4221
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
4159
4222
  };
4160
4223
  } else if (upgradeRequested) {
4161
4224
  result["reasoning_upgrade"] = {
@@ -5681,7 +5744,7 @@ ${ctxBody}` });
5681
5744
  args["worker_tool_cost_cap_mode"],
5682
5745
  opts.workerToolsCfg
5683
5746
  );
5684
- const workerCall = (p) => {
5747
+ const dispatchOne = (p) => {
5685
5748
  if (acceptedWorkerTools.length > 0 && opts.innerCallers) {
5686
5749
  const opts2 = {
5687
5750
  provider: p,
@@ -5703,6 +5766,15 @@ ${ctxBody}` });
5703
5766
  purpose: "confer"
5704
5767
  });
5705
5768
  };
5769
+ const onAnswer = opts.onAnswer;
5770
+ const workerCall = onAnswer ? async (p) => {
5771
+ const answer = await dispatchOne(p);
5772
+ try {
5773
+ onAnswer(answer, p.name);
5774
+ } catch {
5775
+ }
5776
+ return answer;
5777
+ } : dispatchOne;
5706
5778
  if (earlyStop && selected.length >= 3) {
5707
5779
  const phase1 = await Promise.all(selected.slice(0, 2).map(workerCall));
5708
5780
  const phase1Clean = phase1.filter(
@@ -7831,7 +7903,7 @@ Synthesize the node outputs into a single coherent deliverable. Preserve any [MI
7831
7903
  });
7832
7904
  const personaMeta = persona.meta;
7833
7905
  const recombineSys = "You are the orchestrator. Combine node outputs into the final result.";
7834
- const recMsgs = [
7906
+ let recMsgs = [
7835
7907
  { role: "system", content: persona.block ? `${persona.block}
7836
7908
 
7837
7909
  ${recombineSys}` : recombineSys },
@@ -7870,6 +7942,15 @@ ${recombineSys}` : recombineSys },
7870
7942
  provider: synthProvider.name
7871
7943
  } }
7872
7944
  );
7945
+ const coReason = await coReasonThenInject({
7946
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
7947
+ messages: recMsgs,
7948
+ maxTokens,
7949
+ purpose: "orchestrate-coreason"
7950
+ });
7951
+ recMsgs = coReason.messages;
7952
+ if (coReason.answer) orchAnswers.push(coReason.answer);
7953
+ const coReasoned = coReason.answer !== null;
7873
7954
  let synthAns = await askOne(synthProvider, recMsgs, {
7874
7955
  maxTokens,
7875
7956
  temperature: 0.4,
@@ -7920,7 +8001,8 @@ ${recombineSys}` : recombineSys },
7920
8001
  applied: true,
7921
8002
  model: UPGRADE_MODEL,
7922
8003
  label: UPGRADE_LABEL,
7923
- seat: "recombine/synthesis"
8004
+ seat: "recombine/synthesis",
8005
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
7924
8006
  };
7925
8007
  } else if (upgradeRequested) {
7926
8008
  result["reasoning_upgrade"] = {
@@ -9241,7 +9323,7 @@ ${proposalRender}`
9241
9323
  critiqueAnswers[i]?.response ?? ""
9242
9324
  )
9243
9325
  ).join("\n\n") : "(no critiques)";
9244
- const synthMessages = [
9326
+ let synthMessages = [
9245
9327
  { role: "system", content: synthSystem },
9246
9328
  {
9247
9329
  role: "user",
@@ -9254,6 +9336,14 @@ CRITIQUES:
9254
9336
  ${critiqueBlock}`
9255
9337
  }
9256
9338
  ];
9339
+ const coReason = await coReasonThenInject({
9340
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
9341
+ messages: synthMessages,
9342
+ maxTokens,
9343
+ purpose: "coordinate-coreason"
9344
+ });
9345
+ synthMessages = coReason.messages;
9346
+ const coReasonAns = coReason.answer;
9257
9347
  const synthResult = await requestStructured(
9258
9348
  synthForCall,
9259
9349
  synthMessages,
@@ -9309,7 +9399,8 @@ ${critiqueBlock}`
9309
9399
  applied: true,
9310
9400
  model: UPGRADE_MODEL,
9311
9401
  label: UPGRADE_LABEL,
9312
- seat: "synthesizer"
9402
+ seat: "synthesizer",
9403
+ ...coReasonAns ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
9313
9404
  };
9314
9405
  } else if (upgradeRequested) {
9315
9406
  result["reasoning_upgrade"] = {
@@ -9325,6 +9416,7 @@ ${critiqueBlock}`
9325
9416
  const allCallEnvelopes = [
9326
9417
  scannedProposal,
9327
9418
  ...scannedCritiques,
9419
+ ...coReasonAns ? [coReasonAns] : [],
9328
9420
  synthAns
9329
9421
  ];
9330
9422
  const wallMs = Math.trunc(performance8.now() - callStartedWall);
@@ -9889,7 +9981,14 @@ ${prior}` });
9889
9981
  }
9890
9982
  for (const p of selected) {
9891
9983
  const entry = await callPanelist(p, roundMessages);
9892
- transcript.push({ ...entry, round: rnd });
9984
+ const withRound = { ...entry, round: rnd };
9985
+ transcript.push(withRound);
9986
+ if (opts.onTurn) {
9987
+ try {
9988
+ opts.onTurn(withRound, rnd, p.name);
9989
+ } catch {
9990
+ }
9991
+ }
9893
9992
  }
9894
9993
  if (earlyStopOpt && rnd < maxRounds) {
9895
9994
  const thisRound = transcript.filter(
@@ -9924,6 +10023,7 @@ ${prior}` });
9924
10023
  let synthesisStructured = null;
9925
10024
  let synthesisErrors = [];
9926
10025
  let personaMeta = null;
10026
+ let coReasoned = false;
9927
10027
  if (moderator) {
9928
10028
  const synthProvider = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : moderator;
9929
10029
  const condensed = transcript.map(
@@ -9939,7 +10039,7 @@ ${e.response ?? "(error)"}`
9939
10039
  });
9940
10040
  personaMeta = persona.meta;
9941
10041
  const synthSys = "You are the moderator. Synthesise the debate into a single grounded recommendation.";
9942
- const synthMessages = [
10042
+ let synthMessages = [
9943
10043
  {
9944
10044
  role: "system",
9945
10045
  content: persona.block ? `${persona.block}
@@ -9954,6 +10054,15 @@ TRANSCRIPT:
9954
10054
  ${condensed}`
9955
10055
  }
9956
10056
  ];
10057
+ const coReason = await coReasonThenInject({
10058
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
10059
+ messages: synthMessages,
10060
+ maxTokens,
10061
+ purpose: "debate-coreason"
10062
+ });
10063
+ synthMessages = coReason.messages;
10064
+ if (coReason.answer) extraAnswers.push(coReason.answer);
10065
+ coReasoned = coReason.answer !== null;
9957
10066
  if (structuredOpt) {
9958
10067
  const r = await requestStructured(
9959
10068
  synthProvider,
@@ -9971,6 +10080,12 @@ ${condensed}`
9971
10080
  purpose: "synth"
9972
10081
  });
9973
10082
  }
10083
+ if (synthesis && opts.onSynthesis) {
10084
+ try {
10085
+ opts.onSynthesis(synthesis);
10086
+ } catch {
10087
+ }
10088
+ }
9974
10089
  }
9975
10090
  let claimsBlock = null;
9976
10091
  if (Boolean(args["extract_claims"])) {
@@ -10002,7 +10117,8 @@ ${condensed}`
10002
10117
  applied: true,
10003
10118
  model: UPGRADE_MODEL,
10004
10119
  label: UPGRADE_LABEL,
10005
- seat: "moderator synthesis"
10120
+ seat: "moderator synthesis",
10121
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
10006
10122
  };
10007
10123
  } else if (upgradeRequested) {
10008
10124
  result["reasoning_upgrade"] = {
@@ -11803,7 +11919,7 @@ async function runSolve(args, opts) {
11803
11919
  return { error: "no active providers have API keys in .env" };
11804
11920
  }
11805
11921
  const systemMsg = "You are solving a problem step-by-step. Produce ONLY the literal solution (code, command, or text) with no commentary, no markdown fences, no preamble. Your output is fed directly to a verifier.";
11806
- const userBlock = context ? `CONTEXT:
11922
+ let userBlock = context ? `CONTEXT:
11807
11923
  ${context}
11808
11924
 
11809
11925
  PROBLEM:
@@ -11830,6 +11946,20 @@ ${problem}` : problem;
11830
11946
  const upgradeRequested = isUpgradeRequested(args);
11831
11947
  const fableProvider = upgradeRequested && opts.providers["anthropic"] ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : null;
11832
11948
  const upgraded = fableProvider !== null;
11949
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
11950
+ let coReasoned = false;
11951
+ if (coProvider) {
11952
+ const coAns = await askOne(
11953
+ coProvider,
11954
+ [{ role: "system", content: systemMsg }, { role: "user", content: userBlock }],
11955
+ { maxTokens, temperature: 0.3, purpose: "solve-coreason" }
11956
+ );
11957
+ solveAnswers.push(coAns);
11958
+ coReasoned = true;
11959
+ if (coAns.error === void 0 && typeof coAns.response === "string" && coAns.response.trim()) {
11960
+ userBlock += secondOpinionBlock(coAns.response.trim());
11961
+ }
11962
+ }
11833
11963
  for (let i = 1; i <= maxAttempts; i++) {
11834
11964
  const provider = fableProvider ?? selected[(i - 1) % selected.length];
11835
11965
  const msgs = [
@@ -11933,7 +12063,8 @@ Re-emit the FULL solution. No commentary.`
11933
12063
  applied: true,
11934
12064
  model: UPGRADE_MODEL,
11935
12065
  label: UPGRADE_LABEL,
11936
- seat: "solver"
12066
+ seat: "solver",
12067
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
11937
12068
  };
11938
12069
  } else if (upgradeRequested) {
11939
12070
  result["reasoning_upgrade"] = {
@@ -12224,7 +12355,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
12224
12355
  var DEFAULT_PACKAGE = "crosscheck-cli";
12225
12356
  var FETCH_TIMEOUT_MS = 3e3;
12226
12357
  function engineVersion() {
12227
- return true ? "0.2.2" : "0.0.0-dev";
12358
+ return true ? "0.2.4" : "0.0.0-dev";
12228
12359
  }
12229
12360
  function defaultUpdateCachePath() {
12230
12361
  const base = process.env["CROSSCHECK_DATA_DIR"] || path10.join(os.homedir() || os.tmpdir(), ".crosscheck");
@@ -14075,8 +14206,6 @@ async function flush() {
14075
14206
  }
14076
14207
 
14077
14208
  // src/server.ts
14078
- var SERVER_NAME = "crosscheck-agent";
14079
- var SERVER_VERSION = true ? "0.2.2" : "0.0.0-dev";
14080
14209
  function extractRunSummaryText(out) {
14081
14210
  if (out === null || typeof out !== "object" || Array.isArray(out)) return void 0;
14082
14211
  const rec = out;