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.
@@ -1,5 +1,6 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
3
+ import { P as Provider } from './types-HA3W47O4.cjs';
3
4
 
4
5
  interface PricingDoc {
5
6
  /** `<provider>` -> `<model>` -> ModelRates. */
@@ -322,81 +323,6 @@ interface Storage extends StorageRead, StorageWrite {
322
323
  close(): Promise<void>;
323
324
  }
324
325
 
325
- /** One provider call's token + cost record. Mirrors `Usage.to_dict()`
326
- * output exactly. */
327
- interface Usage {
328
- provider: string;
329
- model: string;
330
- prompt_tokens: number;
331
- completion_tokens: number;
332
- cached_tokens: number;
333
- total_tokens: number;
334
- cost_usd: number;
335
- estimated: boolean;
336
- purpose: string;
337
- }
338
-
339
- /** Inbound message shape — chat-completions style. */
340
- interface ChatMessage {
341
- role: "system" | "user" | "assistant" | string;
342
- content: string;
343
- [k: string]: unknown;
344
- }
345
- /** A successful `send()` result. */
346
- interface SendResult {
347
- /** Concatenated text from the provider response. */
348
- text: string;
349
- /** Number of HTTP attempts that produced this result (>= 1). */
350
- attempts: number;
351
- /** Parsed + cost-augmented usage record. */
352
- usage: Usage;
353
- }
354
- /** Args passed into every `Provider.send()` call. Mirrors the Python
355
- * `send(messages, max_tokens, temperature, purpose='worker')` signature
356
- * plus an optional `signal` for cancellation. */
357
- interface SendArgs {
358
- messages: readonly ChatMessage[];
359
- maxTokens: number;
360
- temperature: number;
361
- purpose?: string;
362
- /** Optional AbortSignal so callers can cancel long-running calls. */
363
- signal?: AbortSignal;
364
- /** Optional one-call model override. Used by the cheap-mode tier
365
- * picker (see core/retarget.ts) to route a node to a cheaper model
366
- * without mutating the provider's default. */
367
- modelOverride?: string;
368
- /** F4b: optional JSON Schema that the response MUST conform to.
369
- * When set, provider adapters that support native structured output
370
- * (currently: openai-compatible adapter with provider=openai) wire
371
- * it into the request as `response_format: {type: "json_schema"}`
372
- * or the provider's equivalent. Adapters that don't support native
373
- * structured mode silently ignore this field — the schema-in-prompt
374
- * + F4c tolerant parser path still works as the universal fallback.
375
- * Mirror of OpenAI's json_schema spec; downstream adapters normalise
376
- * to their own provider's native shape. */
377
- jsonSchema?: Record<string, unknown>;
378
- }
379
- /** Provider adapter. */
380
- interface Provider {
381
- /** Lowercased identifier (e.g. "anthropic", "openai"). */
382
- readonly name: string;
383
- /** Default model for this provider (env-resolved at factory time). */
384
- readonly model: string;
385
- /** Ordered fallback models — "greenlight" candidates to try, in order,
386
- * when `model` comes back with a model-access failure (the account/
387
- * project doesn't have it enabled) rather than any other kind of
388
- * error. Env-resolved at factory time from `<PROVIDER>_MODEL_
389
- * FALLBACKS`, or set from a user's/org's configured chain. Empty for
390
- * most providers — a bad key or rate limit isn't fixed by switching
391
- * models, so this is only ever consulted for that one failure mode
392
- * (see core/model-fallback.ts). */
393
- readonly fallbackModels?: readonly string[];
394
- /** Make a request and return the parsed result. Throws `ProviderError`
395
- * on classified failures (auth, rate_limit, timeout, server, parse,
396
- * network, client). */
397
- send(args: SendArgs): Promise<SendResult>;
398
- }
399
-
400
326
  interface FetchConfig {
401
327
  enabled?: boolean;
402
328
  url_allowlist?: readonly string[];
@@ -1,5 +1,6 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
3
+ import { P as Provider } from './types-HA3W47O4.js';
3
4
 
4
5
  interface PricingDoc {
5
6
  /** `<provider>` -> `<model>` -> ModelRates. */
@@ -322,81 +323,6 @@ interface Storage extends StorageRead, StorageWrite {
322
323
  close(): Promise<void>;
323
324
  }
324
325
 
325
- /** One provider call's token + cost record. Mirrors `Usage.to_dict()`
326
- * output exactly. */
327
- interface Usage {
328
- provider: string;
329
- model: string;
330
- prompt_tokens: number;
331
- completion_tokens: number;
332
- cached_tokens: number;
333
- total_tokens: number;
334
- cost_usd: number;
335
- estimated: boolean;
336
- purpose: string;
337
- }
338
-
339
- /** Inbound message shape — chat-completions style. */
340
- interface ChatMessage {
341
- role: "system" | "user" | "assistant" | string;
342
- content: string;
343
- [k: string]: unknown;
344
- }
345
- /** A successful `send()` result. */
346
- interface SendResult {
347
- /** Concatenated text from the provider response. */
348
- text: string;
349
- /** Number of HTTP attempts that produced this result (>= 1). */
350
- attempts: number;
351
- /** Parsed + cost-augmented usage record. */
352
- usage: Usage;
353
- }
354
- /** Args passed into every `Provider.send()` call. Mirrors the Python
355
- * `send(messages, max_tokens, temperature, purpose='worker')` signature
356
- * plus an optional `signal` for cancellation. */
357
- interface SendArgs {
358
- messages: readonly ChatMessage[];
359
- maxTokens: number;
360
- temperature: number;
361
- purpose?: string;
362
- /** Optional AbortSignal so callers can cancel long-running calls. */
363
- signal?: AbortSignal;
364
- /** Optional one-call model override. Used by the cheap-mode tier
365
- * picker (see core/retarget.ts) to route a node to a cheaper model
366
- * without mutating the provider's default. */
367
- modelOverride?: string;
368
- /** F4b: optional JSON Schema that the response MUST conform to.
369
- * When set, provider adapters that support native structured output
370
- * (currently: openai-compatible adapter with provider=openai) wire
371
- * it into the request as `response_format: {type: "json_schema"}`
372
- * or the provider's equivalent. Adapters that don't support native
373
- * structured mode silently ignore this field — the schema-in-prompt
374
- * + F4c tolerant parser path still works as the universal fallback.
375
- * Mirror of OpenAI's json_schema spec; downstream adapters normalise
376
- * to their own provider's native shape. */
377
- jsonSchema?: Record<string, unknown>;
378
- }
379
- /** Provider adapter. */
380
- interface Provider {
381
- /** Lowercased identifier (e.g. "anthropic", "openai"). */
382
- readonly name: string;
383
- /** Default model for this provider (env-resolved at factory time). */
384
- readonly model: string;
385
- /** Ordered fallback models — "greenlight" candidates to try, in order,
386
- * when `model` comes back with a model-access failure (the account/
387
- * project doesn't have it enabled) rather than any other kind of
388
- * error. Env-resolved at factory time from `<PROVIDER>_MODEL_
389
- * FALLBACKS`, or set from a user's/org's configured chain. Empty for
390
- * most providers — a bad key or rate limit isn't fixed by switching
391
- * models, so this is only ever consulted for that one failure mode
392
- * (see core/model-fallback.ts). */
393
- readonly fallbackModels?: readonly string[];
394
- /** Make a request and return the parsed result. Throws `ProviderError`
395
- * on classified failures (auth, rate_limit, timeout, server, parse,
396
- * network, client). */
397
- send(args: SendArgs): Promise<SendResult>;
398
- }
399
-
400
326
  interface FetchConfig {
401
327
  enabled?: boolean;
402
328
  url_allowlist?: readonly string[];
@@ -1269,6 +1269,11 @@ function reasoningSharesOutputBudget(provider) {
1269
1269
 
1270
1270
  // src/providers/types.ts
1271
1271
  init_esm_shims();
1272
+ var IMAGE_MEDIA_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
1273
+ function imagesOf(m) {
1274
+ if (m.role !== "user" || !Array.isArray(m.images)) return [];
1275
+ return m.images.filter((i) => Boolean(i) && typeof i.data === "string" && i.data.length > 0 && IMAGE_MEDIA_TYPES.includes(i.mediaType));
1276
+ }
1272
1277
  var ProviderError = class extends Error {
1273
1278
  name = "ProviderError";
1274
1279
  kind;
@@ -1593,6 +1598,52 @@ function rejectsDisabledThinking(model) {
1593
1598
  const m = model.toLowerCase();
1594
1599
  return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
1595
1600
  }
1601
+ var NO_FORCED_TOOL_PREFIXES = [
1602
+ "claude-fable-5-1",
1603
+ "claude-mythos-5-1",
1604
+ "claude-opus-5-5",
1605
+ "claude-sonnet-5-5"
1606
+ ];
1607
+ function rejectsForcedToolUse(model) {
1608
+ const m = model.toLowerCase();
1609
+ return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
1610
+ }
1611
+ var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
1612
+ "minimum",
1613
+ "maximum",
1614
+ "exclusiveMinimum",
1615
+ "exclusiveMaximum",
1616
+ "multipleOf",
1617
+ "minLength",
1618
+ "maxLength",
1619
+ "pattern",
1620
+ "minItems",
1621
+ "maxItems",
1622
+ "uniqueItems",
1623
+ "minProperties",
1624
+ "maxProperties",
1625
+ "$schema"
1626
+ ]);
1627
+ function toStructuredOutputSchema(schema) {
1628
+ const walk = (node) => {
1629
+ if (Array.isArray(node)) return node.map(walk);
1630
+ if (!node || typeof node !== "object") return node;
1631
+ const out = {};
1632
+ for (const [k, v] of Object.entries(node)) {
1633
+ if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
1634
+ if (k === "properties" && v && typeof v === "object") {
1635
+ out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
1636
+ } else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
1637
+ out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
1638
+ } else {
1639
+ out[k] = v;
1640
+ }
1641
+ }
1642
+ if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
1643
+ return out;
1644
+ };
1645
+ return walk(schema);
1646
+ }
1596
1647
  var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
1597
1648
  function applyPromptCaching(body, env = process.env) {
1598
1649
  const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
@@ -1622,7 +1673,12 @@ function buildAnthropicRequest(opts) {
1622
1673
  }
1623
1674
  continue;
1624
1675
  }
1625
- convo.push({ role: m.role, content: typeof m.content === "string" ? m.content : "" });
1676
+ const text = typeof m.content === "string" ? m.content : "";
1677
+ const images = imagesOf(m);
1678
+ convo.push(images.length ? { role: m.role, content: [
1679
+ ...images.map((i) => ({ type: "image", source: { type: "base64", media_type: i.mediaType, data: i.data } })),
1680
+ { type: "text", text }
1681
+ ] } : { role: m.role, content: text });
1626
1682
  }
1627
1683
  const body = {
1628
1684
  model: opts.model,
@@ -1644,7 +1700,12 @@ function buildAnthropicRequest(opts) {
1644
1700
  body.thinking = { type: "disabled" };
1645
1701
  }
1646
1702
  }
1647
- if (opts.jsonSchema) {
1703
+ if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
1704
+ body.output_config = {
1705
+ ...body.output_config ?? {},
1706
+ format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
1707
+ };
1708
+ } else if (opts.jsonSchema) {
1648
1709
  body.tools = [{
1649
1710
  name: ANTHROPIC_STRUCTURED_TOOL_NAME,
1650
1711
  description: "Emit a single JSON object matching the requested schema.",
@@ -1858,7 +1919,10 @@ function buildGeminiRequest(opts) {
1858
1919
  const role = m.role === "user" ? "user" : "model";
1859
1920
  contents.push({
1860
1921
  role,
1861
- parts: [{ text: typeof m.content === "string" ? m.content : "" }]
1922
+ parts: [
1923
+ ...imagesOf(m).map((i) => ({ inline_data: { mime_type: i.mediaType, data: i.data } })),
1924
+ { text: typeof m.content === "string" ? m.content : "" }
1925
+ ]
1862
1926
  });
1863
1927
  }
1864
1928
  const body = {
@@ -2027,10 +2091,11 @@ function supportsNativeJsonSchema(provider, model) {
2027
2091
  return true;
2028
2092
  }
2029
2093
  function buildOpenAICompatibleRequest(opts) {
2030
- const msgs = opts.messages.map((m) => ({
2031
- role: m.role,
2032
- content: typeof m.content === "string" ? m.content : ""
2033
- }));
2094
+ const msgs = opts.messages.map((m) => {
2095
+ const text = typeof m.content === "string" ? m.content : "";
2096
+ const images = imagesOf(m);
2097
+ 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 };
2098
+ });
2034
2099
  const body = {
2035
2100
  model: opts.model,
2036
2101
  messages: msgs
@@ -2047,7 +2112,15 @@ function buildOpenAICompatibleRequest(opts) {
2047
2112
  json_schema: {
2048
2113
  name: "structured_output",
2049
2114
  schema: opts.jsonSchema,
2050
- strict: true
2115
+ // NOT strict. Strict mode requires `additionalProperties: false` on
2116
+ // every object and every property listed in `required` — the
2117
+ // engine's schemas don't meet that, so every structured OpenAI call
2118
+ // (planner, judges, synthesis) was a 400, unnoticed until the canary
2119
+ // grew a structured check (2026-10-11). Non-strict still shapes the
2120
+ // reply to the schema, and structured.ts validates it against the
2121
+ // full schema regardless, so strictness added a failure mode and no
2122
+ // safety.
2123
+ strict: false
2051
2124
  }
2052
2125
  };
2053
2126
  }
@@ -2435,7 +2508,7 @@ import { z } from "zod";
2435
2508
  // src/server-meta.ts
2436
2509
  init_esm_shims();
2437
2510
  var SERVER_NAME = "crosscheck-agent";
2438
- var SERVER_VERSION = true ? "0.2.28" : "0.0.0-dev";
2511
+ var SERVER_VERSION = true ? "0.2.30" : "0.0.0-dev";
2439
2512
 
2440
2513
  // src/tools/audit.ts
2441
2514
  init_esm_shims();
@@ -5444,6 +5517,7 @@ async function pickAutoPanel(storage, purpose, n, providers, allowlist) {
5444
5517
 
5445
5518
  // src/core/super-mode.ts
5446
5519
  init_esm_shims();
5520
+ import { AsyncLocalStorage } from "async_hooks";
5447
5521
  var SUPER_MODELS = {
5448
5522
  // Fable 5.1 verified present on the account; 5 as the fallback for accounts
5449
5523
  // that haven't been granted 5.1 yet.
@@ -5486,7 +5560,9 @@ function parseChain(v) {
5486
5560
  }
5487
5561
  return out;
5488
5562
  }
5489
- function superChainFor(provider, env = process.env) {
5563
+ var superEnvStore = new AsyncLocalStorage();
5564
+ var currentEnv = () => superEnvStore.getStore() ?? process.env;
5565
+ function superChainFor(provider, env = currentEnv()) {
5490
5566
  const varName = SUPER_ENV_VARS[provider];
5491
5567
  const user = varName ? parseChain(env[varName]) : [];
5492
5568
  if (user.length > 0) {
@@ -5495,14 +5571,14 @@ function superChainFor(provider, env = process.env) {
5495
5571
  }
5496
5572
  return SUPER_MODELS[provider] ?? [];
5497
5573
  }
5498
- function superPrimary(provider, env = process.env) {
5574
+ function superPrimary(provider, env = currentEnv()) {
5499
5575
  return superChainFor(provider, env)[0];
5500
5576
  }
5501
5577
  var SUPER_PROVIDER_NAMES = Object.keys(SUPER_MODELS);
5502
5578
  function isSuperRequested(args) {
5503
5579
  return args["super"] === true;
5504
5580
  }
5505
- function retargetForSuper(p, env = process.env) {
5581
+ function retargetForSuper(p, env = currentEnv()) {
5506
5582
  const chain = superChainFor(p.name, env);
5507
5583
  if (chain.length === 0) return p;
5508
5584
  const [primary, ...fallbacks] = chain;
@@ -7590,9 +7666,9 @@ import { performance as performance7 } from "perf_hooks";
7590
7666
 
7591
7667
  // src/core/progress.ts
7592
7668
  init_esm_shims();
7593
- import { AsyncLocalStorage } from "async_hooks";
7669
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
7594
7670
  import { performance as performance6 } from "perf_hooks";
7595
- var progressStorage = new AsyncLocalStorage();
7671
+ var progressStorage = new AsyncLocalStorage2();
7596
7672
  async function withProgress(token, sendNotification, fn) {
7597
7673
  if (token === void 0 || token === null) {
7598
7674
  return fn();
@@ -9139,6 +9215,16 @@ function buildCallContext(args) {
9139
9215
  var CREATE_DOC_MAX_BYTES = 32 * 1024;
9140
9216
  var CREATE_AUDIT_THRESHOLD = 0.7;
9141
9217
  async function runCreate(args, opts) {
9218
+ const subEnvelopes = [];
9219
+ const tracked = (fn) => async (...a) => {
9220
+ const out = await fn(...a);
9221
+ subEnvelopes.push(out);
9222
+ return out;
9223
+ };
9224
+ const confer = tracked(runConfer);
9225
+ const orchestrate = tracked(runOrchestrate);
9226
+ const review = tracked(runReview);
9227
+ const audit = tracked(runAudit);
9142
9228
  const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
9143
9229
  if (!instruction) {
9144
9230
  return errorEnvelope6(
@@ -9175,7 +9261,7 @@ ${constraints}
9175
9261
 
9176
9262
  ` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
9177
9263
  ${documentsPayload}`;
9178
- const scope = await runConfer({
9264
+ const scope = await confer({
9179
9265
  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,
9180
9266
  context: contextBlock,
9181
9267
  ...providers !== void 0 ? { providers } : {},
@@ -9202,7 +9288,7 @@ ${scopeAnswer || "(none)"}
9202
9288
  };
9203
9289
  if (providers !== void 0) orchestrateArgs["providers"] = providers;
9204
9290
  if (planOnly) orchestrateArgs["plan_only"] = true;
9205
- let orchestration = await runOrchestrate(orchestrateArgs, {
9291
+ let orchestration = await orchestrate(orchestrateArgs, {
9206
9292
  providers: opts.providers,
9207
9293
  allowlist: opts.allowlist ?? null,
9208
9294
  moderator,
@@ -9231,7 +9317,7 @@ ${scopeAnswer || "(none)"}
9231
9317
  }
9232
9318
  let reviewEnvelope = null;
9233
9319
  if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
9234
- reviewEnvelope = await runReview({
9320
+ reviewEnvelope = await review({
9235
9321
  snippet: orchestration["final"],
9236
9322
  intent: `final deliverable for: ${instruction}`,
9237
9323
  ...providers !== void 0 ? { providers } : {},
@@ -9251,7 +9337,7 @@ ${scopeAnswer || "(none)"}
9251
9337
  const panelExhausted = producingPanel.length > 0 && producingPanel.every(
9252
9338
  (p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
9253
9339
  ) && producingPanel.length >= Object.keys(opts.providers).length;
9254
- auditEnvelope = await runAudit({
9340
+ auditEnvelope = await audit({
9255
9341
  output_to_audit: orchestration["final"],
9256
9342
  producing_panelists: producingPanel,
9257
9343
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -9280,7 +9366,7 @@ ${retryConstraints}
9280
9366
  DOCUMENTS:
9281
9367
  ${documentsPayload}`
9282
9368
  };
9283
- const retryOrchestration = await runOrchestrate(
9369
+ const retryOrchestration = await orchestrate(
9284
9370
  retryOrchestrateArgs,
9285
9371
  {
9286
9372
  providers: opts.providers,
@@ -9294,7 +9380,7 @@ ${documentsPayload}`
9294
9380
  if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
9295
9381
  const retryPanel = computeProducingPanel(retryOrchestration);
9296
9382
  const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
9297
- auditEnvelope = await runAudit({
9383
+ auditEnvelope = await audit({
9298
9384
  output_to_audit: retryOrchestration["final"],
9299
9385
  producing_panelists: retryPanel,
9300
9386
  ...auditRubric !== void 0 ? { rubric: auditRubric } : {},
@@ -9369,9 +9455,28 @@ ${documentsPayload}`
9369
9455
  ["auditor", "items", "overall_score", "passed", "rubric"]
9370
9456
  ),
9371
9457
  artifacts,
9372
- warnings
9458
+ warnings,
9459
+ ...combinedUsage(subEnvelopes)
9373
9460
  };
9374
9461
  }
9462
+ function combinedUsage(envelopes) {
9463
+ const usages = [];
9464
+ const byCallTiming = [];
9465
+ let wall = 0, cpu = 0;
9466
+ for (const env of envelopes) {
9467
+ const e = env ?? {};
9468
+ const calls = e["usage"]?.["by_call"] ?? [];
9469
+ const t = e["timing"] ?? {};
9470
+ const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
9471
+ if (!Array.isArray(calls) || calls.length === 0) continue;
9472
+ usages.push(...calls);
9473
+ if (timing.length === calls.length) byCallTiming.push(...timing);
9474
+ 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 });
9475
+ wall += Number(t["wall_ms"] ?? 0) || 0;
9476
+ cpu += Number(t["cpu_ms"] ?? 0) || 0;
9477
+ }
9478
+ return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
9479
+ }
9375
9480
  async function ingestDocuments(documents, sessionId, opts) {
9376
9481
  if (documents.length === 0) return [];
9377
9482
  const out = [];
@@ -12868,7 +12973,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
12868
12973
  var DEFAULT_PACKAGE = "crosscheck-cli";
12869
12974
  var FETCH_TIMEOUT_MS = 3e3;
12870
12975
  function engineVersion() {
12871
- return true ? "0.2.28" : "0.0.0-dev";
12976
+ return true ? "0.2.30" : "0.0.0-dev";
12872
12977
  }
12873
12978
  function defaultUpdateCachePath() {
12874
12979
  const base = process.env["CROSSCHECK_DATA_DIR"] || path10.join(os.homedir() || os.tmpdir(), ".crosscheck");