crosscheck-mcp 0.2.28 → 0.2.29

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.
@@ -1617,6 +1617,52 @@ function rejectsDisabledThinking(model) {
1617
1617
  const m = model.toLowerCase();
1618
1618
  return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
1619
1619
  }
1620
+ var NO_FORCED_TOOL_PREFIXES = [
1621
+ "claude-fable-5-1",
1622
+ "claude-mythos-5-1",
1623
+ "claude-opus-5-5",
1624
+ "claude-sonnet-5-5"
1625
+ ];
1626
+ function rejectsForcedToolUse(model) {
1627
+ const m = model.toLowerCase();
1628
+ return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
1629
+ }
1630
+ var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
1631
+ "minimum",
1632
+ "maximum",
1633
+ "exclusiveMinimum",
1634
+ "exclusiveMaximum",
1635
+ "multipleOf",
1636
+ "minLength",
1637
+ "maxLength",
1638
+ "pattern",
1639
+ "minItems",
1640
+ "maxItems",
1641
+ "uniqueItems",
1642
+ "minProperties",
1643
+ "maxProperties",
1644
+ "$schema"
1645
+ ]);
1646
+ function toStructuredOutputSchema(schema) {
1647
+ const walk = (node) => {
1648
+ if (Array.isArray(node)) return node.map(walk);
1649
+ if (!node || typeof node !== "object") return node;
1650
+ const out = {};
1651
+ for (const [k, v] of Object.entries(node)) {
1652
+ if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
1653
+ if (k === "properties" && v && typeof v === "object") {
1654
+ out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
1655
+ } else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
1656
+ out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
1657
+ } else {
1658
+ out[k] = v;
1659
+ }
1660
+ }
1661
+ if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
1662
+ return out;
1663
+ };
1664
+ return walk(schema);
1665
+ }
1620
1666
  var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
1621
1667
  function applyPromptCaching(body, env = process.env) {
1622
1668
  const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
@@ -1668,7 +1714,12 @@ function buildAnthropicRequest(opts) {
1668
1714
  body.thinking = { type: "disabled" };
1669
1715
  }
1670
1716
  }
1671
- if (opts.jsonSchema) {
1717
+ if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
1718
+ body.output_config = {
1719
+ ...body.output_config ?? {},
1720
+ format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
1721
+ };
1722
+ } else if (opts.jsonSchema) {
1672
1723
  body.tools = [{
1673
1724
  name: ANTHROPIC_STRUCTURED_TOOL_NAME,
1674
1725
  description: "Emit a single JSON object matching the requested schema.",
@@ -2071,7 +2122,15 @@ function buildOpenAICompatibleRequest(opts) {
2071
2122
  json_schema: {
2072
2123
  name: "structured_output",
2073
2124
  schema: opts.jsonSchema,
2074
- strict: true
2125
+ // NOT strict. Strict mode requires `additionalProperties: false` on
2126
+ // every object and every property listed in `required` — the
2127
+ // engine's schemas don't meet that, so every structured OpenAI call
2128
+ // (planner, judges, synthesis) was a 400, unnoticed until the canary
2129
+ // grew a structured check (2026-10-11). Non-strict still shapes the
2130
+ // reply to the schema, and structured.ts validates it against the
2131
+ // full schema regardless, so strictness added a failure mode and no
2132
+ // safety.
2133
+ strict: false
2075
2134
  }
2076
2135
  };
2077
2136
  }
@@ -2456,7 +2515,7 @@ var import_zod = require("zod");
2456
2515
  // src/server-meta.ts
2457
2516
  init_cjs_shims();
2458
2517
  var SERVER_NAME = "crosscheck-agent";
2459
- var SERVER_VERSION = true ? "0.2.28" : "0.0.0-dev";
2518
+ var SERVER_VERSION = true ? "0.2.29" : "0.0.0-dev";
2460
2519
 
2461
2520
  // src/tools/audit.ts
2462
2521
  init_cjs_shims();
@@ -9143,6 +9202,16 @@ function buildCallContext(args) {
9143
9202
  var CREATE_DOC_MAX_BYTES = 32 * 1024;
9144
9203
  var CREATE_AUDIT_THRESHOLD = 0.7;
9145
9204
  async function runCreate(args, opts) {
9205
+ const subEnvelopes = [];
9206
+ const tracked = (fn) => async (...a) => {
9207
+ const out = await fn(...a);
9208
+ subEnvelopes.push(out);
9209
+ return out;
9210
+ };
9211
+ const confer = tracked(runConfer);
9212
+ const orchestrate = tracked(runOrchestrate);
9213
+ const review = tracked(runReview);
9214
+ const audit = tracked(runAudit);
9146
9215
  const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
9147
9216
  if (!instruction) {
9148
9217
  return errorEnvelope6(
@@ -9179,7 +9248,7 @@ ${constraints}
9179
9248
 
9180
9249
  ` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
9181
9250
  ${documentsPayload}`;
9182
- const scope = await runConfer({
9251
+ const scope = await confer({
9183
9252
  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
9253
  context: contextBlock,
9185
9254
  ...providers !== void 0 ? { providers } : {},
@@ -9206,7 +9275,7 @@ ${scopeAnswer || "(none)"}
9206
9275
  };
9207
9276
  if (providers !== void 0) orchestrateArgs["providers"] = providers;
9208
9277
  if (planOnly) orchestrateArgs["plan_only"] = true;
9209
- let orchestration = await runOrchestrate(orchestrateArgs, {
9278
+ let orchestration = await orchestrate(orchestrateArgs, {
9210
9279
  providers: opts.providers,
9211
9280
  allowlist: opts.allowlist ?? null,
9212
9281
  moderator,
@@ -9235,7 +9304,7 @@ ${scopeAnswer || "(none)"}
9235
9304
  }
9236
9305
  let reviewEnvelope = null;
9237
9306
  if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
9238
- reviewEnvelope = await runReview({
9307
+ reviewEnvelope = await review({
9239
9308
  snippet: orchestration["final"],
9240
9309
  intent: `final deliverable for: ${instruction}`,
9241
9310
  ...providers !== void 0 ? { providers } : {},
@@ -9255,7 +9324,7 @@ ${scopeAnswer || "(none)"}
9255
9324
  const panelExhausted = producingPanel.length > 0 && producingPanel.every(
9256
9325
  (p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
9257
9326
  ) && producingPanel.length >= Object.keys(opts.providers).length;
9258
- auditEnvelope = await runAudit({
9327
+ auditEnvelope = await audit({
9259
9328
  output_to_audit: orchestration["final"],
9260
9329
  producing_panelists: producingPanel,
9261
9330
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -9284,7 +9353,7 @@ ${retryConstraints}
9284
9353
  DOCUMENTS:
9285
9354
  ${documentsPayload}`
9286
9355
  };
9287
- const retryOrchestration = await runOrchestrate(
9356
+ const retryOrchestration = await orchestrate(
9288
9357
  retryOrchestrateArgs,
9289
9358
  {
9290
9359
  providers: opts.providers,
@@ -9298,7 +9367,7 @@ ${documentsPayload}`
9298
9367
  if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
9299
9368
  const retryPanel = computeProducingPanel(retryOrchestration);
9300
9369
  const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
9301
- auditEnvelope = await runAudit({
9370
+ auditEnvelope = await audit({
9302
9371
  output_to_audit: retryOrchestration["final"],
9303
9372
  producing_panelists: retryPanel,
9304
9373
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -9373,9 +9442,28 @@ ${documentsPayload}`
9373
9442
  ["auditor", "items", "overall_score", "passed", "rubric"]
9374
9443
  ),
9375
9444
  artifacts,
9376
- warnings
9445
+ warnings,
9446
+ ...combinedUsage(subEnvelopes)
9377
9447
  };
9378
9448
  }
9449
+ function combinedUsage(envelopes) {
9450
+ const usages = [];
9451
+ const byCallTiming = [];
9452
+ let wall = 0, cpu = 0;
9453
+ for (const env of envelopes) {
9454
+ const e = env ?? {};
9455
+ const calls = e["usage"]?.["by_call"] ?? [];
9456
+ const t = e["timing"] ?? {};
9457
+ const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
9458
+ if (!Array.isArray(calls) || calls.length === 0) continue;
9459
+ usages.push(...calls);
9460
+ if (timing.length === calls.length) byCallTiming.push(...timing);
9461
+ 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 });
9462
+ wall += Number(t["wall_ms"] ?? 0) || 0;
9463
+ cpu += Number(t["cpu_ms"] ?? 0) || 0;
9464
+ }
9465
+ return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
9466
+ }
9379
9467
  async function ingestDocuments(documents, sessionId, opts) {
9380
9468
  if (documents.length === 0) return [];
9381
9469
  const out = [];
@@ -12872,7 +12960,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
12872
12960
  var DEFAULT_PACKAGE = "crosscheck-cli";
12873
12961
  var FETCH_TIMEOUT_MS = 3e3;
12874
12962
  function engineVersion() {
12875
- return true ? "0.2.28" : "0.0.0-dev";
12963
+ return true ? "0.2.29" : "0.0.0-dev";
12876
12964
  }
12877
12965
  function defaultUpdateCachePath() {
12878
12966
  const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path13.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");