crosscheck-mcp 0.2.28 → 0.2.30

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.
@@ -1293,6 +1293,11 @@ function reasoningSharesOutputBudget(provider) {
1293
1293
 
1294
1294
  // src/providers/types.ts
1295
1295
  init_cjs_shims();
1296
+ var IMAGE_MEDIA_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
1297
+ function imagesOf(m) {
1298
+ if (m.role !== "user" || !Array.isArray(m.images)) return [];
1299
+ return m.images.filter((i) => Boolean(i) && typeof i.data === "string" && i.data.length > 0 && IMAGE_MEDIA_TYPES.includes(i.mediaType));
1300
+ }
1296
1301
  var ProviderError = class extends Error {
1297
1302
  name = "ProviderError";
1298
1303
  kind;
@@ -1617,6 +1622,52 @@ function rejectsDisabledThinking(model) {
1617
1622
  const m = model.toLowerCase();
1618
1623
  return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
1619
1624
  }
1625
+ var NO_FORCED_TOOL_PREFIXES = [
1626
+ "claude-fable-5-1",
1627
+ "claude-mythos-5-1",
1628
+ "claude-opus-5-5",
1629
+ "claude-sonnet-5-5"
1630
+ ];
1631
+ function rejectsForcedToolUse(model) {
1632
+ const m = model.toLowerCase();
1633
+ return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
1634
+ }
1635
+ var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
1636
+ "minimum",
1637
+ "maximum",
1638
+ "exclusiveMinimum",
1639
+ "exclusiveMaximum",
1640
+ "multipleOf",
1641
+ "minLength",
1642
+ "maxLength",
1643
+ "pattern",
1644
+ "minItems",
1645
+ "maxItems",
1646
+ "uniqueItems",
1647
+ "minProperties",
1648
+ "maxProperties",
1649
+ "$schema"
1650
+ ]);
1651
+ function toStructuredOutputSchema(schema) {
1652
+ const walk = (node) => {
1653
+ if (Array.isArray(node)) return node.map(walk);
1654
+ if (!node || typeof node !== "object") return node;
1655
+ const out = {};
1656
+ for (const [k, v] of Object.entries(node)) {
1657
+ if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
1658
+ if (k === "properties" && v && typeof v === "object") {
1659
+ out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
1660
+ } else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
1661
+ out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
1662
+ } else {
1663
+ out[k] = v;
1664
+ }
1665
+ }
1666
+ if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
1667
+ return out;
1668
+ };
1669
+ return walk(schema);
1670
+ }
1620
1671
  var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
1621
1672
  function applyPromptCaching(body, env = process.env) {
1622
1673
  const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
@@ -1646,7 +1697,12 @@ function buildAnthropicRequest(opts) {
1646
1697
  }
1647
1698
  continue;
1648
1699
  }
1649
- convo.push({ role: m.role, content: typeof m.content === "string" ? m.content : "" });
1700
+ const text = typeof m.content === "string" ? m.content : "";
1701
+ const images = imagesOf(m);
1702
+ convo.push(images.length ? { role: m.role, content: [
1703
+ ...images.map((i) => ({ type: "image", source: { type: "base64", media_type: i.mediaType, data: i.data } })),
1704
+ { type: "text", text }
1705
+ ] } : { role: m.role, content: text });
1650
1706
  }
1651
1707
  const body = {
1652
1708
  model: opts.model,
@@ -1668,7 +1724,12 @@ function buildAnthropicRequest(opts) {
1668
1724
  body.thinking = { type: "disabled" };
1669
1725
  }
1670
1726
  }
1671
- if (opts.jsonSchema) {
1727
+ if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
1728
+ body.output_config = {
1729
+ ...body.output_config ?? {},
1730
+ format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
1731
+ };
1732
+ } else if (opts.jsonSchema) {
1672
1733
  body.tools = [{
1673
1734
  name: ANTHROPIC_STRUCTURED_TOOL_NAME,
1674
1735
  description: "Emit a single JSON object matching the requested schema.",
@@ -1882,7 +1943,10 @@ function buildGeminiRequest(opts) {
1882
1943
  const role = m.role === "user" ? "user" : "model";
1883
1944
  contents.push({
1884
1945
  role,
1885
- parts: [{ text: typeof m.content === "string" ? m.content : "" }]
1946
+ parts: [
1947
+ ...imagesOf(m).map((i) => ({ inline_data: { mime_type: i.mediaType, data: i.data } })),
1948
+ { text: typeof m.content === "string" ? m.content : "" }
1949
+ ]
1886
1950
  });
1887
1951
  }
1888
1952
  const body = {
@@ -2051,10 +2115,11 @@ function supportsNativeJsonSchema(provider, model) {
2051
2115
  return true;
2052
2116
  }
2053
2117
  function buildOpenAICompatibleRequest(opts) {
2054
- const msgs = opts.messages.map((m) => ({
2055
- role: m.role,
2056
- content: typeof m.content === "string" ? m.content : ""
2057
- }));
2118
+ const msgs = opts.messages.map((m) => {
2119
+ const text = typeof m.content === "string" ? m.content : "";
2120
+ const images = imagesOf(m);
2121
+ return images.length ? { role: m.role, content: [{ type: "text", text }, ...images.map((i) => ({ type: "image_url", image_url: { url: `data:${i.mediaType};base64,${i.data}` } }))] } : { role: m.role, content: text };
2122
+ });
2058
2123
  const body = {
2059
2124
  model: opts.model,
2060
2125
  messages: msgs
@@ -2071,7 +2136,15 @@ function buildOpenAICompatibleRequest(opts) {
2071
2136
  json_schema: {
2072
2137
  name: "structured_output",
2073
2138
  schema: opts.jsonSchema,
2074
- strict: true
2139
+ // NOT strict. Strict mode requires `additionalProperties: false` on
2140
+ // every object and every property listed in `required` — the
2141
+ // engine's schemas don't meet that, so every structured OpenAI call
2142
+ // (planner, judges, synthesis) was a 400, unnoticed until the canary
2143
+ // grew a structured check (2026-10-11). Non-strict still shapes the
2144
+ // reply to the schema, and structured.ts validates it against the
2145
+ // full schema regardless, so strictness added a failure mode and no
2146
+ // safety.
2147
+ strict: false
2075
2148
  }
2076
2149
  };
2077
2150
  }
@@ -2368,7 +2441,7 @@ function makeGeminiProvider(model, apiKey, opts, fallbackModels = []) {
2368
2441
  // src/server.ts
2369
2442
  init_cjs_shims();
2370
2443
  var import_server = require("@modelcontextprotocol/sdk/server/index.js");
2371
- var import_types9 = require("@modelcontextprotocol/sdk/types.js");
2444
+ var import_types12 = require("@modelcontextprotocol/sdk/types.js");
2372
2445
 
2373
2446
  // src/instructions.ts
2374
2447
  init_cjs_shims();
@@ -2456,7 +2529,7 @@ var import_zod = require("zod");
2456
2529
  // src/server-meta.ts
2457
2530
  init_cjs_shims();
2458
2531
  var SERVER_NAME = "crosscheck-agent";
2459
- var SERVER_VERSION = true ? "0.2.28" : "0.0.0-dev";
2532
+ var SERVER_VERSION = true ? "0.2.30" : "0.0.0-dev";
2460
2533
 
2461
2534
  // src/tools/audit.ts
2462
2535
  init_cjs_shims();
@@ -5465,6 +5538,7 @@ async function pickAutoPanel(storage, purpose, n, providers, allowlist) {
5465
5538
 
5466
5539
  // src/core/super-mode.ts
5467
5540
  init_cjs_shims();
5541
+ var import_node_async_hooks = require("async_hooks");
5468
5542
  var SUPER_MODELS = {
5469
5543
  // Fable 5.1 verified present on the account; 5 as the fallback for accounts
5470
5544
  // that haven't been granted 5.1 yet.
@@ -5507,7 +5581,9 @@ function parseChain(v) {
5507
5581
  }
5508
5582
  return out;
5509
5583
  }
5510
- function superChainFor(provider, env = process.env) {
5584
+ var superEnvStore = new import_node_async_hooks.AsyncLocalStorage();
5585
+ var currentEnv = () => superEnvStore.getStore() ?? process.env;
5586
+ function superChainFor(provider, env = currentEnv()) {
5511
5587
  const varName = SUPER_ENV_VARS[provider];
5512
5588
  const user = varName ? parseChain(env[varName]) : [];
5513
5589
  if (user.length > 0) {
@@ -5516,14 +5592,14 @@ function superChainFor(provider, env = process.env) {
5516
5592
  }
5517
5593
  return SUPER_MODELS[provider] ?? [];
5518
5594
  }
5519
- function superPrimary(provider, env = process.env) {
5595
+ function superPrimary(provider, env = currentEnv()) {
5520
5596
  return superChainFor(provider, env)[0];
5521
5597
  }
5522
5598
  var SUPER_PROVIDER_NAMES = Object.keys(SUPER_MODELS);
5523
5599
  function isSuperRequested(args) {
5524
5600
  return args["super"] === true;
5525
5601
  }
5526
- function retargetForSuper(p, env = process.env) {
5602
+ function retargetForSuper(p, env = currentEnv()) {
5527
5603
  const chain = superChainFor(p.name, env);
5528
5604
  if (chain.length === 0) return p;
5529
5605
  const [primary, ...fallbacks] = chain;
@@ -7604,9 +7680,9 @@ var import_node_perf_hooks6 = require("perf_hooks");
7604
7680
 
7605
7681
  // src/core/progress.ts
7606
7682
  init_cjs_shims();
7607
- var import_node_async_hooks = require("async_hooks");
7683
+ var import_node_async_hooks2 = require("async_hooks");
7608
7684
  var import_node_perf_hooks5 = require("perf_hooks");
7609
- var progressStorage = new import_node_async_hooks.AsyncLocalStorage();
7685
+ var progressStorage = new import_node_async_hooks2.AsyncLocalStorage();
7610
7686
  async function withProgress(token, sendNotification, fn) {
7611
7687
  if (token === void 0 || token === null) {
7612
7688
  return fn();
@@ -9143,6 +9219,16 @@ function buildCallContext(args) {
9143
9219
  var CREATE_DOC_MAX_BYTES = 32 * 1024;
9144
9220
  var CREATE_AUDIT_THRESHOLD = 0.7;
9145
9221
  async function runCreate(args, opts) {
9222
+ const subEnvelopes = [];
9223
+ const tracked = (fn) => async (...a) => {
9224
+ const out = await fn(...a);
9225
+ subEnvelopes.push(out);
9226
+ return out;
9227
+ };
9228
+ const confer = tracked(runConfer);
9229
+ const orchestrate = tracked(runOrchestrate);
9230
+ const review = tracked(runReview);
9231
+ const audit = tracked(runAudit);
9146
9232
  const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
9147
9233
  if (!instruction) {
9148
9234
  return errorEnvelope6(
@@ -9179,7 +9265,7 @@ ${constraints}
9179
9265
 
9180
9266
  ` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
9181
9267
  ${documentsPayload}`;
9182
- const scope = await runConfer({
9268
+ const scope = await confer({
9183
9269
  question: "We are about to orchestrate a full plan->build->review->audit lifecycle for this instruction. List 3-6 concrete sub-tasks (each with a one-line description and a difficulty: low|med|high), any critical assumptions, and any missing-information risks. Be concise and decisive \u2014 your output will be used to build the orchestration DAG.\n\nINSTRUCTION:\n" + instruction,
9184
9270
  context: contextBlock,
9185
9271
  ...providers !== void 0 ? { providers } : {},
@@ -9206,7 +9292,7 @@ ${scopeAnswer || "(none)"}
9206
9292
  };
9207
9293
  if (providers !== void 0) orchestrateArgs["providers"] = providers;
9208
9294
  if (planOnly) orchestrateArgs["plan_only"] = true;
9209
- let orchestration = await runOrchestrate(orchestrateArgs, {
9295
+ let orchestration = await orchestrate(orchestrateArgs, {
9210
9296
  providers: opts.providers,
9211
9297
  allowlist: opts.allowlist ?? null,
9212
9298
  moderator,
@@ -9235,7 +9321,7 @@ ${scopeAnswer || "(none)"}
9235
9321
  }
9236
9322
  let reviewEnvelope = null;
9237
9323
  if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
9238
- reviewEnvelope = await runReview({
9324
+ reviewEnvelope = await review({
9239
9325
  snippet: orchestration["final"],
9240
9326
  intent: `final deliverable for: ${instruction}`,
9241
9327
  ...providers !== void 0 ? { providers } : {},
@@ -9255,7 +9341,7 @@ ${scopeAnswer || "(none)"}
9255
9341
  const panelExhausted = producingPanel.length > 0 && producingPanel.every(
9256
9342
  (p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
9257
9343
  ) && producingPanel.length >= Object.keys(opts.providers).length;
9258
- auditEnvelope = await runAudit({
9344
+ auditEnvelope = await audit({
9259
9345
  output_to_audit: orchestration["final"],
9260
9346
  producing_panelists: producingPanel,
9261
9347
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -9284,7 +9370,7 @@ ${retryConstraints}
9284
9370
  DOCUMENTS:
9285
9371
  ${documentsPayload}`
9286
9372
  };
9287
- const retryOrchestration = await runOrchestrate(
9373
+ const retryOrchestration = await orchestrate(
9288
9374
  retryOrchestrateArgs,
9289
9375
  {
9290
9376
  providers: opts.providers,
@@ -9298,7 +9384,7 @@ ${documentsPayload}`
9298
9384
  if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
9299
9385
  const retryPanel = computeProducingPanel(retryOrchestration);
9300
9386
  const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
9301
- auditEnvelope = await runAudit({
9387
+ auditEnvelope = await audit({
9302
9388
  output_to_audit: retryOrchestration["final"],
9303
9389
  producing_panelists: retryPanel,
9304
9390
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -9373,9 +9459,28 @@ ${documentsPayload}`
9373
9459
  ["auditor", "items", "overall_score", "passed", "rubric"]
9374
9460
  ),
9375
9461
  artifacts,
9376
- warnings
9462
+ warnings,
9463
+ ...combinedUsage(subEnvelopes)
9377
9464
  };
9378
9465
  }
9466
+ function combinedUsage(envelopes) {
9467
+ const usages = [];
9468
+ const byCallTiming = [];
9469
+ let wall = 0, cpu = 0;
9470
+ for (const env of envelopes) {
9471
+ const e = env ?? {};
9472
+ const calls = e["usage"]?.["by_call"] ?? [];
9473
+ const t = e["timing"] ?? {};
9474
+ const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
9475
+ if (!Array.isArray(calls) || calls.length === 0) continue;
9476
+ usages.push(...calls);
9477
+ if (timing.length === calls.length) byCallTiming.push(...timing);
9478
+ else for (const c of calls) byCallTiming.push({ provider: c.provider, model: c.model, purpose: c.purpose ?? null, wall_ms: 0, cpu_ms: 0, cache_hit: false });
9479
+ wall += Number(t["wall_ms"] ?? 0) || 0;
9480
+ cpu += Number(t["cpu_ms"] ?? 0) || 0;
9481
+ }
9482
+ return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
9483
+ }
9379
9484
  async function ingestDocuments(documents, sessionId, opts) {
9380
9485
  if (documents.length === 0) return [];
9381
9486
  const out = [];
@@ -12872,7 +12977,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
12872
12977
  var DEFAULT_PACKAGE = "crosscheck-cli";
12873
12978
  var FETCH_TIMEOUT_MS = 3e3;
12874
12979
  function engineVersion() {
12875
- return true ? "0.2.28" : "0.0.0-dev";
12980
+ return true ? "0.2.30" : "0.0.0-dev";
12876
12981
  }
12877
12982
  function defaultUpdateCachePath() {
12878
12983
  const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path13.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
@@ -15083,14 +15188,14 @@ function createServer(opts = {}) {
15083
15188
  });
15084
15189
  };
15085
15190
  const tools = buildToolRegistry(opts);
15086
- server.setRequestHandler(import_types9.ListToolsRequestSchema, async () => ({
15191
+ server.setRequestHandler(import_types12.ListToolsRequestSchema, async () => ({
15087
15192
  tools: Array.from(tools.values()).map((t) => ({
15088
15193
  name: t.name,
15089
15194
  description: t.description,
15090
15195
  inputSchema: t.inputSchema
15091
15196
  }))
15092
15197
  }));
15093
- server.setRequestHandler(import_types9.CallToolRequestSchema, async (req) => {
15198
+ server.setRequestHandler(import_types12.CallToolRequestSchema, async (req) => {
15094
15199
  const name = req.params.name;
15095
15200
  const tool = tools.get(name);
15096
15201
  if (!tool) {