crosscheck-mcp 0.2.3 → 0.2.5

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.
@@ -1198,6 +1198,14 @@ var PROVIDER_CAPS = {
1198
1198
  mistral: { family: "openai_chat", system_role: "inline", supports_temperature: true },
1199
1199
  groq: { family: "openai_chat", system_role: "inline", supports_temperature: true },
1200
1200
  deepseek: { family: "openai_chat", system_role: "inline", supports_temperature: true },
1201
+ kimi: {
1202
+ family: "openai_chat",
1203
+ system_role: "inline",
1204
+ // Kimi K3 is reasoning-class: it rejects temperature != 1 and wants
1205
+ // max_completion_tokens (like OpenAI's gpt-5 / o-series).
1206
+ supports_temperature: "model",
1207
+ reasoning_prefixes: ["kimi-k3"]
1208
+ },
1201
1209
  gemini: {
1202
1210
  family: "gemini",
1203
1211
  system_role: "separate",
@@ -1483,7 +1491,10 @@ function buildAnthropicRequest(opts) {
1483
1491
  const headers = {
1484
1492
  "content-type": "application/json",
1485
1493
  "x-api-key": opts.apiKey,
1486
- "anthropic-version": ANTHROPIC_VERSION_HEADER
1494
+ "anthropic-version": ANTHROPIC_VERSION_HEADER,
1495
+ // Required for browser-origin calls (the Chrome extension); harmless from
1496
+ // Node. Without it the Anthropic API rejects requests made from a browser.
1497
+ "anthropic-dangerous-direct-browser-access": "true"
1487
1498
  };
1488
1499
  return { url: ANTHROPIC_API_URL, headers, body };
1489
1500
  }
@@ -1782,7 +1793,9 @@ var OPENAI_COMPAT_DEFAULT_URLS = {
1782
1793
  xai: "https://api.x.ai/v1/chat/completions",
1783
1794
  mistral: "https://api.mistral.ai/v1/chat/completions",
1784
1795
  groq: "https://api.groq.com/openai/v1/chat/completions",
1785
- deepseek: "https://api.deepseek.com/v1/chat/completions"
1796
+ deepseek: "https://api.deepseek.com/v1/chat/completions",
1797
+ // Moonshot AI (Kimi). OpenAI-compatible chat completions endpoint.
1798
+ kimi: "https://api.moonshot.ai/v1/chat/completions"
1786
1799
  };
1787
1800
  var OPENAI_COMPAT_NATIVE_STRUCTURED = /* @__PURE__ */ new Set([
1788
1801
  "openai"
@@ -1950,7 +1963,8 @@ var DEFAULT_MODELS = {
1950
1963
  mistral: "mistral-large-latest",
1951
1964
  groq: "llama-3.3-70b-versatile",
1952
1965
  deepseek: "deepseek-chat",
1953
- gemini: "gemini-3.1-pro-preview"
1966
+ gemini: "gemini-3.1-pro-preview",
1967
+ kimi: "kimi-k3"
1954
1968
  };
1955
1969
  function buildProviders(opts) {
1956
1970
  const out = {};
@@ -1964,7 +1978,8 @@ function buildProviders(opts) {
1964
1978
  { name: "xai", keyEnv: "XAI_API_KEY", modelEnv: "XAI_MODEL", defaultModel: DEFAULT_MODELS["xai"] },
1965
1979
  { name: "mistral", keyEnv: "MISTRAL_API_KEY", modelEnv: "MISTRAL_MODEL", defaultModel: DEFAULT_MODELS["mistral"] },
1966
1980
  { name: "groq", keyEnv: "GROQ_API_KEY", modelEnv: "GROQ_MODEL", defaultModel: DEFAULT_MODELS["groq"] },
1967
- { name: "deepseek", keyEnv: "DEEPSEEK_API_KEY", modelEnv: "DEEPSEEK_MODEL", defaultModel: DEFAULT_MODELS["deepseek"] }
1981
+ { name: "deepseek", keyEnv: "DEEPSEEK_API_KEY", modelEnv: "DEEPSEEK_MODEL", defaultModel: DEFAULT_MODELS["deepseek"] },
1982
+ { name: "kimi", keyEnv: "KIMI_API_KEY", modelEnv: "KIMI_MODEL", defaultModel: DEFAULT_MODELS["kimi"] }
1968
1983
  ];
1969
1984
  for (const s of openAiCompatSpec) {
1970
1985
  const apiKey = opts.env[s.keyEnv];
@@ -2033,7 +2048,7 @@ function makeGeminiProvider(model, apiKey, opts) {
2033
2048
 
2034
2049
  // src/server.ts
2035
2050
  init_cjs_shims();
2036
- var import_server2 = require("@modelcontextprotocol/sdk/server/index.js");
2051
+ var import_server = require("@modelcontextprotocol/sdk/server/index.js");
2037
2052
  var import_types8 = require("@modelcontextprotocol/sdk/types.js");
2038
2053
 
2039
2054
  // src/bridge/index.ts
@@ -2156,6 +2171,11 @@ Spend visibility:
2156
2171
  init_cjs_shims();
2157
2172
  var import_zod = require("zod");
2158
2173
 
2174
+ // src/server-meta.ts
2175
+ init_cjs_shims();
2176
+ var SERVER_NAME = "crosscheck-agent";
2177
+ var SERVER_VERSION = true ? "0.2.5" : "0.0.0-dev";
2178
+
2159
2179
  // src/tools/audit.ts
2160
2180
  init_cjs_shims();
2161
2181
  var import_node_fs5 = require("fs");
@@ -3654,6 +3674,51 @@ async function loadProviderWeights(storage, names) {
3654
3674
  return out;
3655
3675
  }
3656
3676
 
3677
+ // src/core/co-reason.ts
3678
+ init_cjs_shims();
3679
+ var CO_REASON_MODEL = "gpt-5.6";
3680
+ var CO_REASON_PROVIDER = "openai";
3681
+ var CO_REASON_LABEL = "GPT-5.6";
3682
+ function pickCoReasoner(providers, upgradeRequested) {
3683
+ if (!upgradeRequested) return null;
3684
+ const base = providers[CO_REASON_PROVIDER];
3685
+ return base ? retargetProvider(base, CO_REASON_MODEL) : null;
3686
+ }
3687
+ async function coReasonThenInject(opts) {
3688
+ const { provider, messages, maxTokens } = opts;
3689
+ if (!provider) return { messages, answer: null };
3690
+ const answer = await askOne(provider, messages, {
3691
+ maxTokens,
3692
+ temperature: 0.3,
3693
+ purpose: opts.purpose ?? "co-reason"
3694
+ });
3695
+ const text = typeof answer.response === "string" ? answer.response.trim() : "";
3696
+ if (answer.error !== void 0 || !text) {
3697
+ return { messages, answer };
3698
+ }
3699
+ return { messages: injectSecondOpinion(messages, text), answer };
3700
+ }
3701
+ function secondOpinionBlock(analysis) {
3702
+ return `
3703
+
3704
+ --- SECOND-OPINION ANALYSIS (${CO_REASON_LABEL}) ---
3705
+ 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.
3706
+
3707
+ ${analysis}`;
3708
+ }
3709
+ function injectSecondOpinion(messages, analysis) {
3710
+ const block = secondOpinionBlock(analysis);
3711
+ const out = messages.map((m) => ({ ...m }));
3712
+ for (let i = out.length - 1; i >= 0; i--) {
3713
+ if (out[i].role === "user") {
3714
+ out[i] = { ...out[i], content: String(out[i].content) + block };
3715
+ return out;
3716
+ }
3717
+ }
3718
+ out.push({ role: "user", content: block.trimStart() });
3719
+ return out;
3720
+ }
3721
+
3657
3722
  // src/core/tiers.ts
3658
3723
  init_cjs_shims();
3659
3724
 
@@ -3848,7 +3913,7 @@ function buildSuggestedUpgrade(toolName, assessment) {
3848
3913
  model: UPGRADE_MODEL,
3849
3914
  label: UPGRADE_LABEL,
3850
3915
  reason: assessment.reason,
3851
- 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.`
3916
+ 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.`
3852
3917
  };
3853
3918
  }
3854
3919
 
@@ -3997,7 +4062,7 @@ ${outputResolved}
3997
4062
 
3998
4063
  RUBRIC ITEMS:
3999
4064
  ${rubricText}`;
4000
- const msgs = [
4065
+ let msgs = [
4001
4066
  { role: "system", content: sysMsg },
4002
4067
  { role: "user", content: userMsg }
4003
4068
  ];
@@ -4121,6 +4186,15 @@ ${rubricText}`;
4121
4186
  const upgradeRequested = isUpgradeRequested(args);
4122
4187
  const upgraded = upgradeRequested && opts.providers["anthropic"] !== void 0;
4123
4188
  const auditorForCall = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : auditor;
4189
+ const coReason = await coReasonThenInject({
4190
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
4191
+ messages: msgs,
4192
+ maxTokens: 2048,
4193
+ purpose: "audit-coreason"
4194
+ });
4195
+ msgs = coReason.messages;
4196
+ if (coReason.answer) auditAnswers.push(coReason.answer);
4197
+ const coReasoned = coReason.answer !== null;
4124
4198
  const r = await requestStructured(auditorForCall, msgs, AUDIT_RUBRIC_SCHEMA, {
4125
4199
  maxTokens: 2048,
4126
4200
  maxRetries: 1,
@@ -4176,7 +4250,8 @@ ${rubricText}`;
4176
4250
  applied: true,
4177
4251
  model: UPGRADE_MODEL,
4178
4252
  label: UPGRADE_LABEL,
4179
- seat: "auditor"
4253
+ seat: "auditor",
4254
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
4180
4255
  };
4181
4256
  } else if (upgradeRequested) {
4182
4257
  result["reasoning_upgrade"] = {
@@ -5702,7 +5777,7 @@ ${ctxBody}` });
5702
5777
  args["worker_tool_cost_cap_mode"],
5703
5778
  opts.workerToolsCfg
5704
5779
  );
5705
- const workerCall = (p) => {
5780
+ const dispatchOne = (p) => {
5706
5781
  if (acceptedWorkerTools.length > 0 && opts.innerCallers) {
5707
5782
  const opts2 = {
5708
5783
  provider: p,
@@ -5724,6 +5799,15 @@ ${ctxBody}` });
5724
5799
  purpose: "confer"
5725
5800
  });
5726
5801
  };
5802
+ const onAnswer = opts.onAnswer;
5803
+ const workerCall = onAnswer ? async (p) => {
5804
+ const answer = await dispatchOne(p);
5805
+ try {
5806
+ onAnswer(answer, p.name);
5807
+ } catch {
5808
+ }
5809
+ return answer;
5810
+ } : dispatchOne;
5727
5811
  if (earlyStop && selected.length >= 3) {
5728
5812
  const phase1 = await Promise.all(selected.slice(0, 2).map(workerCall));
5729
5813
  const phase1Clean = phase1.filter(
@@ -7835,7 +7919,7 @@ Synthesize the node outputs into a single coherent deliverable. Preserve any [MI
7835
7919
  });
7836
7920
  const personaMeta = persona.meta;
7837
7921
  const recombineSys = "You are the orchestrator. Combine node outputs into the final result.";
7838
- const recMsgs = [
7922
+ let recMsgs = [
7839
7923
  { role: "system", content: persona.block ? `${persona.block}
7840
7924
 
7841
7925
  ${recombineSys}` : recombineSys },
@@ -7874,6 +7958,15 @@ ${recombineSys}` : recombineSys },
7874
7958
  provider: synthProvider.name
7875
7959
  } }
7876
7960
  );
7961
+ const coReason = await coReasonThenInject({
7962
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
7963
+ messages: recMsgs,
7964
+ maxTokens,
7965
+ purpose: "orchestrate-coreason"
7966
+ });
7967
+ recMsgs = coReason.messages;
7968
+ if (coReason.answer) orchAnswers.push(coReason.answer);
7969
+ const coReasoned = coReason.answer !== null;
7877
7970
  let synthAns = await askOne(synthProvider, recMsgs, {
7878
7971
  maxTokens,
7879
7972
  temperature: 0.4,
@@ -7924,7 +8017,8 @@ ${recombineSys}` : recombineSys },
7924
8017
  applied: true,
7925
8018
  model: UPGRADE_MODEL,
7926
8019
  label: UPGRADE_LABEL,
7927
- seat: "recombine/synthesis"
8020
+ seat: "recombine/synthesis",
8021
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
7928
8022
  };
7929
8023
  } else if (upgradeRequested) {
7930
8024
  result["reasoning_upgrade"] = {
@@ -9245,7 +9339,7 @@ ${proposalRender}`
9245
9339
  critiqueAnswers[i]?.response ?? ""
9246
9340
  )
9247
9341
  ).join("\n\n") : "(no critiques)";
9248
- const synthMessages = [
9342
+ let synthMessages = [
9249
9343
  { role: "system", content: synthSystem },
9250
9344
  {
9251
9345
  role: "user",
@@ -9258,6 +9352,14 @@ CRITIQUES:
9258
9352
  ${critiqueBlock}`
9259
9353
  }
9260
9354
  ];
9355
+ const coReason = await coReasonThenInject({
9356
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
9357
+ messages: synthMessages,
9358
+ maxTokens,
9359
+ purpose: "coordinate-coreason"
9360
+ });
9361
+ synthMessages = coReason.messages;
9362
+ const coReasonAns = coReason.answer;
9261
9363
  const synthResult = await requestStructured(
9262
9364
  synthForCall,
9263
9365
  synthMessages,
@@ -9313,7 +9415,8 @@ ${critiqueBlock}`
9313
9415
  applied: true,
9314
9416
  model: UPGRADE_MODEL,
9315
9417
  label: UPGRADE_LABEL,
9316
- seat: "synthesizer"
9418
+ seat: "synthesizer",
9419
+ ...coReasonAns ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
9317
9420
  };
9318
9421
  } else if (upgradeRequested) {
9319
9422
  result["reasoning_upgrade"] = {
@@ -9329,6 +9432,7 @@ ${critiqueBlock}`
9329
9432
  const allCallEnvelopes = [
9330
9433
  scannedProposal,
9331
9434
  ...scannedCritiques,
9435
+ ...coReasonAns ? [coReasonAns] : [],
9332
9436
  synthAns
9333
9437
  ];
9334
9438
  const wallMs = Math.trunc(import_node_perf_hooks7.performance.now() - callStartedWall);
@@ -9893,7 +9997,14 @@ ${prior}` });
9893
9997
  }
9894
9998
  for (const p of selected) {
9895
9999
  const entry = await callPanelist(p, roundMessages);
9896
- transcript.push({ ...entry, round: rnd });
10000
+ const withRound = { ...entry, round: rnd };
10001
+ transcript.push(withRound);
10002
+ if (opts.onTurn) {
10003
+ try {
10004
+ opts.onTurn(withRound, rnd, p.name);
10005
+ } catch {
10006
+ }
10007
+ }
9897
10008
  }
9898
10009
  if (earlyStopOpt && rnd < maxRounds) {
9899
10010
  const thisRound = transcript.filter(
@@ -9928,6 +10039,7 @@ ${prior}` });
9928
10039
  let synthesisStructured = null;
9929
10040
  let synthesisErrors = [];
9930
10041
  let personaMeta = null;
10042
+ let coReasoned = false;
9931
10043
  if (moderator) {
9932
10044
  const synthProvider = upgraded ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : moderator;
9933
10045
  const condensed = transcript.map(
@@ -9943,7 +10055,7 @@ ${e.response ?? "(error)"}`
9943
10055
  });
9944
10056
  personaMeta = persona.meta;
9945
10057
  const synthSys = "You are the moderator. Synthesise the debate into a single grounded recommendation.";
9946
- const synthMessages = [
10058
+ let synthMessages = [
9947
10059
  {
9948
10060
  role: "system",
9949
10061
  content: persona.block ? `${persona.block}
@@ -9958,6 +10070,15 @@ TRANSCRIPT:
9958
10070
  ${condensed}`
9959
10071
  }
9960
10072
  ];
10073
+ const coReason = await coReasonThenInject({
10074
+ provider: pickCoReasoner(opts.providers, upgradeRequested),
10075
+ messages: synthMessages,
10076
+ maxTokens,
10077
+ purpose: "debate-coreason"
10078
+ });
10079
+ synthMessages = coReason.messages;
10080
+ if (coReason.answer) extraAnswers.push(coReason.answer);
10081
+ coReasoned = coReason.answer !== null;
9961
10082
  if (structuredOpt) {
9962
10083
  const r = await requestStructured(
9963
10084
  synthProvider,
@@ -9975,6 +10096,12 @@ ${condensed}`
9975
10096
  purpose: "synth"
9976
10097
  });
9977
10098
  }
10099
+ if (synthesis && opts.onSynthesis) {
10100
+ try {
10101
+ opts.onSynthesis(synthesis);
10102
+ } catch {
10103
+ }
10104
+ }
9978
10105
  }
9979
10106
  let claimsBlock = null;
9980
10107
  if (Boolean(args["extract_claims"])) {
@@ -10006,7 +10133,8 @@ ${condensed}`
10006
10133
  applied: true,
10007
10134
  model: UPGRADE_MODEL,
10008
10135
  label: UPGRADE_LABEL,
10009
- seat: "moderator synthesis"
10136
+ seat: "moderator synthesis",
10137
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
10010
10138
  };
10011
10139
  } else if (upgradeRequested) {
10012
10140
  result["reasoning_upgrade"] = {
@@ -11807,7 +11935,7 @@ async function runSolve(args, opts) {
11807
11935
  return { error: "no active providers have API keys in .env" };
11808
11936
  }
11809
11937
  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.";
11810
- const userBlock = context ? `CONTEXT:
11938
+ let userBlock = context ? `CONTEXT:
11811
11939
  ${context}
11812
11940
 
11813
11941
  PROBLEM:
@@ -11834,6 +11962,20 @@ ${problem}` : problem;
11834
11962
  const upgradeRequested = isUpgradeRequested(args);
11835
11963
  const fableProvider = upgradeRequested && opts.providers["anthropic"] ? retargetProvider(opts.providers["anthropic"], UPGRADE_MODEL) : null;
11836
11964
  const upgraded = fableProvider !== null;
11965
+ const coProvider = pickCoReasoner(opts.providers, upgradeRequested);
11966
+ let coReasoned = false;
11967
+ if (coProvider) {
11968
+ const coAns = await askOne(
11969
+ coProvider,
11970
+ [{ role: "system", content: systemMsg }, { role: "user", content: userBlock }],
11971
+ { maxTokens, temperature: 0.3, purpose: "solve-coreason" }
11972
+ );
11973
+ solveAnswers.push(coAns);
11974
+ coReasoned = true;
11975
+ if (coAns.error === void 0 && typeof coAns.response === "string" && coAns.response.trim()) {
11976
+ userBlock += secondOpinionBlock(coAns.response.trim());
11977
+ }
11978
+ }
11837
11979
  for (let i = 1; i <= maxAttempts; i++) {
11838
11980
  const provider = fableProvider ?? selected[(i - 1) % selected.length];
11839
11981
  const msgs = [
@@ -11937,7 +12079,8 @@ Re-emit the FULL solution. No commentary.`
11937
12079
  applied: true,
11938
12080
  model: UPGRADE_MODEL,
11939
12081
  label: UPGRADE_LABEL,
11940
- seat: "solver"
12082
+ seat: "solver",
12083
+ ...coReasoned ? { co_reasoner: { model: CO_REASON_MODEL, label: CO_REASON_LABEL } } : {}
11941
12084
  };
11942
12085
  } else if (upgradeRequested) {
11943
12086
  result["reasoning_upgrade"] = {
@@ -12228,7 +12371,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
12228
12371
  var DEFAULT_PACKAGE = "crosscheck-cli";
12229
12372
  var FETCH_TIMEOUT_MS = 3e3;
12230
12373
  function engineVersion() {
12231
- return true ? "0.2.3" : "0.0.0-dev";
12374
+ return true ? "0.2.5" : "0.0.0-dev";
12232
12375
  }
12233
12376
  function defaultUpdateCachePath() {
12234
12377
  const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path13.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
@@ -14079,8 +14222,6 @@ async function flush() {
14079
14222
  }
14080
14223
 
14081
14224
  // src/server.ts
14082
- var SERVER_NAME = "crosscheck-agent";
14083
- var SERVER_VERSION = true ? "0.2.3" : "0.0.0-dev";
14084
14225
  function extractRunSummaryText(out) {
14085
14226
  if (out === null || typeof out !== "object" || Array.isArray(out)) return void 0;
14086
14227
  const rec = out;
@@ -14094,7 +14235,7 @@ function extractRunSummaryText(out) {
14094
14235
  return void 0;
14095
14236
  }
14096
14237
  function createServer(opts = {}) {
14097
- const server = new import_server2.Server(
14238
+ const server = new import_server.Server(
14098
14239
  { name: SERVER_NAME, version: SERVER_VERSION },
14099
14240
  {
14100
14241
  capabilities: { tools: {} },