crosscheck-mcp 0.2.27 → 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.
- package/README.md +4 -20
- package/dist/browser-ext.cjs +386 -360
- package/dist/browser-ext.cjs.map +1 -1
- package/dist/browser-ext.js +371 -345
- package/dist/browser-ext.js.map +1 -1
- package/dist/embed.cjs +635 -381
- package/dist/embed.cjs.map +1 -1
- package/dist/embed.d.cts +151 -2
- package/dist/embed.d.ts +151 -2
- package/dist/embed.js +612 -362
- package/dist/embed.js.map +1 -1
- package/dist/node-stdio.cjs +453 -473
- package/dist/node-stdio.cjs.map +1 -1
- package/dist/node-stdio.d.cts +12 -122
- package/dist/node-stdio.d.ts +12 -122
- package/dist/node-stdio.js +424 -444
- package/dist/node-stdio.js.map +1 -1
- package/dist/pricing.json +47 -9
- package/dist/self-check.cjs.map +1 -1
- package/dist/self-check.js.map +1 -1
- package/dist/types-BcprisDl.d.cts +76 -0
- package/dist/types-BcprisDl.d.ts +76 -0
- package/package.json +7 -2
package/dist/node-stdio.js
CHANGED
|
@@ -934,8 +934,8 @@ var init_better_sqlite3 = __esm({
|
|
|
934
934
|
|
|
935
935
|
// src/entrypoints/node-stdio.ts
|
|
936
936
|
init_esm_shims();
|
|
937
|
-
import { existsSync as existsSync14, mkdirSync as
|
|
938
|
-
import
|
|
937
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync11 } from "fs";
|
|
938
|
+
import path16 from "path";
|
|
939
939
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
940
940
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
941
941
|
|
|
@@ -952,10 +952,10 @@ var StderrEmitter = class {
|
|
|
952
952
|
}
|
|
953
953
|
};
|
|
954
954
|
var FileEmitter = class {
|
|
955
|
-
constructor(
|
|
956
|
-
this.path =
|
|
955
|
+
constructor(path17) {
|
|
956
|
+
this.path = path17;
|
|
957
957
|
try {
|
|
958
|
-
mkdirSync(dirname(
|
|
958
|
+
mkdirSync(dirname(path17), { recursive: true });
|
|
959
959
|
} catch {
|
|
960
960
|
}
|
|
961
961
|
}
|
|
@@ -988,13 +988,13 @@ var NullEmitter = class {
|
|
|
988
988
|
function buildDefaultEmitter(env) {
|
|
989
989
|
const mode = (env["CROSSCHECK_EVENTS"] ?? "stderr").toLowerCase();
|
|
990
990
|
if (mode === "off") return new NullEmitter();
|
|
991
|
-
const
|
|
991
|
+
const path17 = env["CROSSCHECK_EVENTS_PATH"];
|
|
992
992
|
if (mode === "file") {
|
|
993
|
-
return
|
|
993
|
+
return path17 ? new FileEmitter(path17) : new NullEmitter();
|
|
994
994
|
}
|
|
995
995
|
if (mode === "both") {
|
|
996
996
|
const ems = [new StderrEmitter()];
|
|
997
|
-
if (
|
|
997
|
+
if (path17) ems.push(new FileEmitter(path17));
|
|
998
998
|
return new TeeEmitter(ems);
|
|
999
999
|
}
|
|
1000
1000
|
return new StderrEmitter();
|
|
@@ -1043,10 +1043,10 @@ function envelopeBytes(v) {
|
|
|
1043
1043
|
// src/core/pricing.ts
|
|
1044
1044
|
init_esm_shims();
|
|
1045
1045
|
import { readFileSync } from "fs";
|
|
1046
|
-
function loadPricing(
|
|
1046
|
+
function loadPricing(path17) {
|
|
1047
1047
|
let raw;
|
|
1048
1048
|
try {
|
|
1049
|
-
raw = readFileSync(
|
|
1049
|
+
raw = readFileSync(path17, "utf8");
|
|
1050
1050
|
} catch {
|
|
1051
1051
|
return {};
|
|
1052
1052
|
}
|
|
@@ -1063,20 +1063,30 @@ function modelPricing(pricing, provider, model) {
|
|
|
1063
1063
|
const block = pricing[provider];
|
|
1064
1064
|
if (!block || typeof block !== "object" || Array.isArray(block)) return null;
|
|
1065
1065
|
const table = block;
|
|
1066
|
+
if (model.startsWith("_")) return null;
|
|
1066
1067
|
let entry = table[model];
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1068
|
+
let match = "exact";
|
|
1069
|
+
if (!isRates(entry)) {
|
|
1070
|
+
const best = Object.keys(table).filter((k) => !k.startsWith("_")).filter((k) => model.startsWith(k) && DATE_STAMP.test(model.slice(k.length))).sort((a, b) => b.length - a.length)[0];
|
|
1071
|
+
if (best !== void 0) {
|
|
1072
|
+
entry = table[best];
|
|
1073
|
+
match = "stamp";
|
|
1074
|
+
}
|
|
1070
1075
|
}
|
|
1071
|
-
if (!
|
|
1076
|
+
if (!isRates(entry)) return null;
|
|
1072
1077
|
const e = entry;
|
|
1073
1078
|
return {
|
|
1074
1079
|
prompt_per_1k: numberOrZero(e["prompt_per_1k"]),
|
|
1075
1080
|
completion_per_1k: numberOrZero(e["completion_per_1k"]),
|
|
1076
1081
|
cached_per_1k: numberOrZero(e["cached_per_1k"]),
|
|
1077
|
-
...e["estimated"] === true ? { estimated: true } : {}
|
|
1082
|
+
...e["estimated"] === true ? { estimated: true } : {},
|
|
1083
|
+
match
|
|
1078
1084
|
};
|
|
1079
1085
|
}
|
|
1086
|
+
var DATE_STAMP = /^-\d{8}$/;
|
|
1087
|
+
function isRates(v) {
|
|
1088
|
+
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
1089
|
+
}
|
|
1080
1090
|
function numberOrZero(v) {
|
|
1081
1091
|
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
1082
1092
|
if (typeof v === "string") {
|
|
@@ -1216,8 +1226,20 @@ var PROVIDER_CAPS = {
|
|
|
1216
1226
|
gemini: {
|
|
1217
1227
|
family: "gemini",
|
|
1218
1228
|
system_role: "separate",
|
|
1219
|
-
|
|
1220
|
-
|
|
1229
|
+
// No sampling, on any Gemini model. Ignored since 3.6 Flash and rejected
|
|
1230
|
+
// by upcoming models (Google, 2026-10). "model" means "omit for reasoning
|
|
1231
|
+
// models", and every Gemini model is reasoning-class (below) — so this
|
|
1232
|
+
// resolves to never, through the same rule the other providers use. The
|
|
1233
|
+
// adapter also never sends it; this keeps the record honest for anything
|
|
1234
|
+
// else that reads it.
|
|
1235
|
+
supports_temperature: "model",
|
|
1236
|
+
// EVERY Gemini model is reasoning-class. The old list named three
|
|
1237
|
+
// families and missed gemini-3.8-flash — the DEFAULT — so the default
|
|
1238
|
+
// model got the small non-reasoning budgets (768 tokens for an audit)
|
|
1239
|
+
// while spending up to ~480 tokens of each call thinking. Google's docs
|
|
1240
|
+
// say thinking cannot be switched off on current models, so a list of
|
|
1241
|
+
// which ones think is a list that can only ever be incomplete.
|
|
1242
|
+
reasoning_prefixes: ["gemini-"]
|
|
1221
1243
|
},
|
|
1222
1244
|
// Qwen's "Max" tier (qwen-v3.8, qwen-v3.7) is a standard instruct/chat
|
|
1223
1245
|
// model, not a visible-reasoning model like QwQ — normal temperature and
|
|
@@ -1342,6 +1364,74 @@ function httpFailureToProviderError(provider, status, bodyText, retryAfterS, mod
|
|
|
1342
1364
|
);
|
|
1343
1365
|
}
|
|
1344
1366
|
|
|
1367
|
+
// src/providers/network-errors.ts
|
|
1368
|
+
init_esm_shims();
|
|
1369
|
+
function codeOf(e) {
|
|
1370
|
+
if (!e || typeof e !== "object") return null;
|
|
1371
|
+
const c = e.code;
|
|
1372
|
+
return typeof c === "string" && c.length > 0 ? c : null;
|
|
1373
|
+
}
|
|
1374
|
+
function rootCause(e, depth = 0) {
|
|
1375
|
+
if (depth > 5 || !e || typeof e !== "object") return e;
|
|
1376
|
+
const o = e;
|
|
1377
|
+
if (Array.isArray(o.errors) && o.errors.length > 0) {
|
|
1378
|
+
const coded = o.errors.find((x) => codeOf(x) !== null);
|
|
1379
|
+
return rootCause(coded ?? o.errors[0], depth + 1);
|
|
1380
|
+
}
|
|
1381
|
+
if (o.cause !== void 0 && o.cause !== null) return rootCause(o.cause, depth + 1);
|
|
1382
|
+
return e;
|
|
1383
|
+
}
|
|
1384
|
+
var BY_CODE = {
|
|
1385
|
+
ENOTFOUND: { cause: "dns", detail: "the provider's hostname did not resolve \u2014 DNS, or a typo'd base URL", transient: false, kind: "network" },
|
|
1386
|
+
EAI_AGAIN: { cause: "dns", detail: "DNS lookup failed temporarily \u2014 resolver or network is flapping", transient: true, kind: "network" },
|
|
1387
|
+
ECONNREFUSED: { cause: "refused", detail: "the connection was refused \u2014 nothing is listening, or a proxy blocked it", transient: false, kind: "network" },
|
|
1388
|
+
ECONNRESET: { cause: "reset", detail: "the peer closed the connection mid-request \u2014 flaky path, or an upstream error behind a proxy", transient: true, kind: "network" },
|
|
1389
|
+
EPIPE: { cause: "reset", detail: "the connection closed while we were still writing", transient: true, kind: "network" },
|
|
1390
|
+
ETIMEDOUT: { cause: "connect_timeout", detail: "the connection timed out before it was established", transient: true, kind: "timeout" },
|
|
1391
|
+
EHOSTUNREACH: { cause: "unreachable", detail: "no route to the provider \u2014 VPN, or offline", transient: true, kind: "network" },
|
|
1392
|
+
ENETUNREACH: { cause: "unreachable", detail: "the network is unreachable \u2014 offline, or a routing change", transient: true, kind: "network" },
|
|
1393
|
+
ENETDOWN: { cause: "unreachable", detail: "the local network is down", transient: true, kind: "network" },
|
|
1394
|
+
EPROTO: { cause: "tls", detail: "the TLS handshake failed \u2014 an intercepting proxy, or a protocol mismatch", transient: false, kind: "network" },
|
|
1395
|
+
ERR_TLS_CERT_ALTNAME_INVALID: { cause: "tls", detail: "the certificate did not match the hostname \u2014 traffic is being intercepted", transient: false, kind: "network" },
|
|
1396
|
+
CERT_HAS_EXPIRED: { cause: "tls", detail: "the server certificate has expired, or this machine's clock is wrong", transient: false, kind: "network" },
|
|
1397
|
+
UNABLE_TO_VERIFY_LEAF_SIGNATURE: { cause: "tls", detail: "the certificate chain could not be verified \u2014 a corporate proxy's root is probably not trusted here", transient: false, kind: "network" },
|
|
1398
|
+
UND_ERR_CONNECT_TIMEOUT: { cause: "connect_timeout", detail: "could not open a connection within the timeout \u2014 firewall, or the host is down", transient: true, kind: "timeout" },
|
|
1399
|
+
UND_ERR_HEADERS_TIMEOUT: { cause: "read_timeout", detail: "connected, but the provider sent no response headers in time \u2014 it is overloaded or thinking too long", transient: true, kind: "timeout" },
|
|
1400
|
+
UND_ERR_BODY_TIMEOUT: { cause: "read_timeout", detail: "the response body stalled mid-stream", transient: true, kind: "timeout" },
|
|
1401
|
+
UND_ERR_SOCKET: { cause: "reset", detail: "the socket closed unexpectedly", transient: true, kind: "network" },
|
|
1402
|
+
UND_ERR_ABORTED: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" },
|
|
1403
|
+
ABORT_ERR: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" }
|
|
1404
|
+
};
|
|
1405
|
+
function diagnoseNetworkError(e) {
|
|
1406
|
+
const root = rootCause(e);
|
|
1407
|
+
const code = codeOf(root) ?? codeOf(e);
|
|
1408
|
+
if (code && BY_CODE[code]) return { ...BY_CODE[code], code };
|
|
1409
|
+
const name = root && typeof root === "object" ? root.name : void 0;
|
|
1410
|
+
if (name === "AbortError" || name === "TimeoutError") {
|
|
1411
|
+
return {
|
|
1412
|
+
cause: name === "TimeoutError" ? "read_timeout" : "aborted",
|
|
1413
|
+
code: code ?? String(name),
|
|
1414
|
+
detail: name === "TimeoutError" ? "the request exceeded its timeout" : "the request was cancelled",
|
|
1415
|
+
transient: name === "TimeoutError",
|
|
1416
|
+
kind: name === "TimeoutError" ? "timeout" : "network"
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
return {
|
|
1420
|
+
cause: "unknown",
|
|
1421
|
+
code,
|
|
1422
|
+
detail: code ? `the connection failed with ${code}` : "the connection failed and the underlying error carried no code",
|
|
1423
|
+
transient: true,
|
|
1424
|
+
kind: "network"
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
function looksLikeNetworkFailure(d) {
|
|
1428
|
+
return d.code !== null || d.cause !== "unknown";
|
|
1429
|
+
}
|
|
1430
|
+
function networkErrorMessage(provider, d) {
|
|
1431
|
+
const code = d.code ? ` [${d.code}]` : "";
|
|
1432
|
+
return `${provider}: ${d.detail}${code}`;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1345
1435
|
// src/providers/retry.ts
|
|
1346
1436
|
init_esm_shims();
|
|
1347
1437
|
var override = null;
|
|
@@ -1503,6 +1593,52 @@ function rejectsDisabledThinking(model) {
|
|
|
1503
1593
|
const m = model.toLowerCase();
|
|
1504
1594
|
return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
|
|
1505
1595
|
}
|
|
1596
|
+
var NO_FORCED_TOOL_PREFIXES = [
|
|
1597
|
+
"claude-fable-5-1",
|
|
1598
|
+
"claude-mythos-5-1",
|
|
1599
|
+
"claude-opus-5-5",
|
|
1600
|
+
"claude-sonnet-5-5"
|
|
1601
|
+
];
|
|
1602
|
+
function rejectsForcedToolUse(model) {
|
|
1603
|
+
const m = model.toLowerCase();
|
|
1604
|
+
return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
|
|
1605
|
+
}
|
|
1606
|
+
var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
|
|
1607
|
+
"minimum",
|
|
1608
|
+
"maximum",
|
|
1609
|
+
"exclusiveMinimum",
|
|
1610
|
+
"exclusiveMaximum",
|
|
1611
|
+
"multipleOf",
|
|
1612
|
+
"minLength",
|
|
1613
|
+
"maxLength",
|
|
1614
|
+
"pattern",
|
|
1615
|
+
"minItems",
|
|
1616
|
+
"maxItems",
|
|
1617
|
+
"uniqueItems",
|
|
1618
|
+
"minProperties",
|
|
1619
|
+
"maxProperties",
|
|
1620
|
+
"$schema"
|
|
1621
|
+
]);
|
|
1622
|
+
function toStructuredOutputSchema(schema) {
|
|
1623
|
+
const walk = (node) => {
|
|
1624
|
+
if (Array.isArray(node)) return node.map(walk);
|
|
1625
|
+
if (!node || typeof node !== "object") return node;
|
|
1626
|
+
const out = {};
|
|
1627
|
+
for (const [k, v] of Object.entries(node)) {
|
|
1628
|
+
if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
|
|
1629
|
+
if (k === "properties" && v && typeof v === "object") {
|
|
1630
|
+
out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
|
|
1631
|
+
} else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
|
|
1632
|
+
out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
|
|
1633
|
+
} else {
|
|
1634
|
+
out[k] = v;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
|
|
1638
|
+
return out;
|
|
1639
|
+
};
|
|
1640
|
+
return walk(schema);
|
|
1641
|
+
}
|
|
1506
1642
|
var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
|
|
1507
1643
|
function applyPromptCaching(body, env = process.env) {
|
|
1508
1644
|
const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
|
|
@@ -1554,7 +1690,12 @@ function buildAnthropicRequest(opts) {
|
|
|
1554
1690
|
body.thinking = { type: "disabled" };
|
|
1555
1691
|
}
|
|
1556
1692
|
}
|
|
1557
|
-
if (opts.jsonSchema) {
|
|
1693
|
+
if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
|
|
1694
|
+
body.output_config = {
|
|
1695
|
+
...body.output_config ?? {},
|
|
1696
|
+
format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
|
|
1697
|
+
};
|
|
1698
|
+
} else if (opts.jsonSchema) {
|
|
1558
1699
|
body.tools = [{
|
|
1559
1700
|
name: ANTHROPIC_STRUCTURED_TOOL_NAME,
|
|
1560
1701
|
description: "Emit a single JSON object matching the requested schema.",
|
|
@@ -1673,7 +1814,11 @@ async function sendAnthropic(args) {
|
|
|
1673
1814
|
try {
|
|
1674
1815
|
respLike = await doFetch(url, init);
|
|
1675
1816
|
} catch (e) {
|
|
1676
|
-
|
|
1817
|
+
const d = diagnoseNetworkError(e);
|
|
1818
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
1819
|
+
throw new ProviderError(d.kind, networkErrorMessage("anthropic", d), {
|
|
1820
|
+
transient: d.transient
|
|
1821
|
+
});
|
|
1677
1822
|
}
|
|
1678
1823
|
const status = respLike.status;
|
|
1679
1824
|
if (status >= 200 && status < 300) {
|
|
@@ -1747,6 +1892,11 @@ function jsonSchemaToGeminiSchema(schema) {
|
|
|
1747
1892
|
}
|
|
1748
1893
|
return out;
|
|
1749
1894
|
}
|
|
1895
|
+
var GEMINI_THINKING_HEADROOM_TOKENS = 16384;
|
|
1896
|
+
function thinkingHeadroom() {
|
|
1897
|
+
const raw = Number(process.env["CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS"]);
|
|
1898
|
+
return Number.isFinite(raw) && raw >= 0 ? Math.trunc(raw) : GEMINI_THINKING_HEADROOM_TOKENS;
|
|
1899
|
+
}
|
|
1750
1900
|
function buildGeminiRequest(opts) {
|
|
1751
1901
|
const contents = [];
|
|
1752
1902
|
let systemText = null;
|
|
@@ -1765,8 +1915,9 @@ function buildGeminiRequest(opts) {
|
|
|
1765
1915
|
const body = {
|
|
1766
1916
|
contents,
|
|
1767
1917
|
generationConfig: {
|
|
1768
|
-
|
|
1769
|
-
|
|
1918
|
+
// Answer budget + thinking headroom. No temperature / topP / topK /
|
|
1919
|
+
// thinkingBudget, on any model — see the header note.
|
|
1920
|
+
maxOutputTokens: opts.maxTokens + thinkingHeadroom()
|
|
1770
1921
|
}
|
|
1771
1922
|
};
|
|
1772
1923
|
if (systemText !== null && systemText !== "") {
|
|
@@ -1776,8 +1927,8 @@ function buildGeminiRequest(opts) {
|
|
|
1776
1927
|
body.generationConfig.responseMimeType = "application/json";
|
|
1777
1928
|
body.generationConfig.responseSchema = jsonSchemaToGeminiSchema(opts.jsonSchema);
|
|
1778
1929
|
}
|
|
1779
|
-
const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent
|
|
1780
|
-
return { url, headers: {}, body };
|
|
1930
|
+
const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent`;
|
|
1931
|
+
return { url, headers: { "x-goog-api-key": opts.apiKey }, body };
|
|
1781
1932
|
}
|
|
1782
1933
|
function parseGeminiResponse(opts) {
|
|
1783
1934
|
const r = opts.resp ?? {};
|
|
@@ -1807,16 +1958,19 @@ function parseGeminiResponse(opts) {
|
|
|
1807
1958
|
}
|
|
1808
1959
|
try {
|
|
1809
1960
|
const first = cands[0];
|
|
1810
|
-
const
|
|
1811
|
-
const
|
|
1961
|
+
const finishReason = typeof first["finishReason"] === "string" ? first["finishReason"] : void 0;
|
|
1962
|
+
const content = first["content"] ?? {};
|
|
1963
|
+
const parts = Array.isArray(content["parts"]) ? content["parts"] : [];
|
|
1812
1964
|
let text = "";
|
|
1813
1965
|
for (const p of parts) {
|
|
1814
1966
|
if (p && typeof p === "object") {
|
|
1815
|
-
const
|
|
1967
|
+
const part = p;
|
|
1968
|
+
if (part["thought"] === true) continue;
|
|
1969
|
+
const t = part["text"];
|
|
1816
1970
|
if (typeof t === "string") text += t;
|
|
1817
1971
|
}
|
|
1818
1972
|
}
|
|
1819
|
-
return { text, usage };
|
|
1973
|
+
return { text, usage, ...finishReason ? { finishReason } : {} };
|
|
1820
1974
|
} catch (e) {
|
|
1821
1975
|
throw new ProviderError(
|
|
1822
1976
|
"parse",
|
|
@@ -1845,7 +1999,8 @@ async function sendGemini(args) {
|
|
|
1845
1999
|
apiKey: args.apiKey,
|
|
1846
2000
|
messages: args.messages,
|
|
1847
2001
|
maxTokens: args.maxTokens,
|
|
1848
|
-
|
|
2002
|
+
// args.temperature is deliberately NOT forwarded: Gemini ignores it and
|
|
2003
|
+
// upcoming models reject it. See the header note.
|
|
1849
2004
|
...args.jsonSchema ? { jsonSchema: args.jsonSchema } : {}
|
|
1850
2005
|
});
|
|
1851
2006
|
const doFetch = args.fetchImpl ?? globalThis.fetch;
|
|
@@ -1860,7 +2015,11 @@ async function sendGemini(args) {
|
|
|
1860
2015
|
try {
|
|
1861
2016
|
respLike = await doFetch(url, init);
|
|
1862
2017
|
} catch (e) {
|
|
1863
|
-
|
|
2018
|
+
const d = diagnoseNetworkError(e);
|
|
2019
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
2020
|
+
throw new ProviderError(d.kind, networkErrorMessage("gemini", d), {
|
|
2021
|
+
transient: d.transient
|
|
2022
|
+
});
|
|
1864
2023
|
}
|
|
1865
2024
|
const status = respLike.status;
|
|
1866
2025
|
if (status >= 200 && status < 300) {
|
|
@@ -1870,11 +2029,18 @@ async function sendGemini(args) {
|
|
|
1870
2029
|
} catch (e) {
|
|
1871
2030
|
throw new ProviderError("parse", `gemini: response body not JSON: ${e.message}`);
|
|
1872
2031
|
}
|
|
1873
|
-
const { text, usage } = parseGeminiResponse({
|
|
2032
|
+
const { text, usage, finishReason } = parseGeminiResponse({
|
|
1874
2033
|
resp: parsed,
|
|
1875
2034
|
model: args.model,
|
|
1876
2035
|
purpose: args.purpose ?? "worker"
|
|
1877
2036
|
});
|
|
2037
|
+
if (text.trim() === "" && finishReason === "MAX_TOKENS") {
|
|
2038
|
+
throw new ProviderError(
|
|
2039
|
+
"parse",
|
|
2040
|
+
`gemini: the answer was cut off before any visible text \u2014 thinking used the whole output budget (${usage.completion_tokens} tokens). Raise CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS or the purpose's budget.`,
|
|
2041
|
+
{ transient: false }
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
1878
2044
|
return { text, attempts: 1, usage: applyPricing2(usage, args.pricing) };
|
|
1879
2045
|
}
|
|
1880
2046
|
const bodyText = await respLike.text().catch(() => "");
|
|
@@ -1932,7 +2098,15 @@ function buildOpenAICompatibleRequest(opts) {
|
|
|
1932
2098
|
json_schema: {
|
|
1933
2099
|
name: "structured_output",
|
|
1934
2100
|
schema: opts.jsonSchema,
|
|
1935
|
-
strict:
|
|
2101
|
+
// NOT strict. Strict mode requires `additionalProperties: false` on
|
|
2102
|
+
// every object and every property listed in `required` — the
|
|
2103
|
+
// engine's schemas don't meet that, so every structured OpenAI call
|
|
2104
|
+
// (planner, judges, synthesis) was a 400, unnoticed until the canary
|
|
2105
|
+
// grew a structured check (2026-10-11). Non-strict still shapes the
|
|
2106
|
+
// reply to the schema, and structured.ts validates it against the
|
|
2107
|
+
// full schema regardless, so strictness added a failure mode and no
|
|
2108
|
+
// safety.
|
|
2109
|
+
strict: false
|
|
1936
2110
|
}
|
|
1937
2111
|
};
|
|
1938
2112
|
}
|
|
@@ -2042,7 +2216,11 @@ async function sendOpenAICompatible(args) {
|
|
|
2042
2216
|
try {
|
|
2043
2217
|
respLike = await doFetch(url, init);
|
|
2044
2218
|
} catch (e) {
|
|
2045
|
-
|
|
2219
|
+
const d = diagnoseNetworkError(e);
|
|
2220
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
2221
|
+
throw new ProviderError(d.kind, networkErrorMessage(args.provider, d), {
|
|
2222
|
+
transient: d.transient
|
|
2223
|
+
});
|
|
2046
2224
|
}
|
|
2047
2225
|
const status = respLike.status;
|
|
2048
2226
|
if (status >= 200 && status < 300) {
|
|
@@ -2230,50 +2408,6 @@ import {
|
|
|
2230
2408
|
ListToolsRequestSchema
|
|
2231
2409
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
2232
2410
|
|
|
2233
|
-
// src/bridge/index.ts
|
|
2234
|
-
init_esm_shims();
|
|
2235
|
-
|
|
2236
|
-
// src/bridge/proxy-tools.ts
|
|
2237
|
-
init_esm_shims();
|
|
2238
|
-
function buildPythonProxies(bridge) {
|
|
2239
|
-
const proxies = /* @__PURE__ */ new Map();
|
|
2240
|
-
for (const name of bridge.toolNames) {
|
|
2241
|
-
proxies.set(name, makeProxy(bridge, name));
|
|
2242
|
-
}
|
|
2243
|
-
return proxies;
|
|
2244
|
-
}
|
|
2245
|
-
function makeProxy(bridge, name) {
|
|
2246
|
-
return {
|
|
2247
|
-
name,
|
|
2248
|
-
description: `(forwarded to Python crosscheck-agent) ${name}`,
|
|
2249
|
-
// We don't carry the per-tool input schema across the bridge in
|
|
2250
|
-
// route-all mode — the TS server is a transparent forwarder, so
|
|
2251
|
-
// arg validation happens on the Python side. inputSchema is left
|
|
2252
|
-
// permissive; the Python validator throws structured errors that
|
|
2253
|
-
// tunnel back through `callTool()`.
|
|
2254
|
-
inputSchema: {
|
|
2255
|
-
type: "object",
|
|
2256
|
-
additionalProperties: true,
|
|
2257
|
-
description: `Forwarded to Python \u2014 see Python tool '${name}' for full schema.`
|
|
2258
|
-
},
|
|
2259
|
-
handler: async (args) => {
|
|
2260
|
-
const r = await bridge.callTool(name, args);
|
|
2261
|
-
if (!r.content.length) {
|
|
2262
|
-
return {};
|
|
2263
|
-
}
|
|
2264
|
-
const first = r.content[0];
|
|
2265
|
-
if (first.type === "text" && first.text) {
|
|
2266
|
-
try {
|
|
2267
|
-
return JSON.parse(first.text);
|
|
2268
|
-
} catch {
|
|
2269
|
-
return { text: first.text };
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
return { content: r.content };
|
|
2273
|
-
}
|
|
2274
|
-
};
|
|
2275
|
-
}
|
|
2276
|
-
|
|
2277
2411
|
// src/instructions.ts
|
|
2278
2412
|
init_esm_shims();
|
|
2279
2413
|
var ROUTABLE_TOOLS = [
|
|
@@ -2360,7 +2494,7 @@ import { z } from "zod";
|
|
|
2360
2494
|
// src/server-meta.ts
|
|
2361
2495
|
init_esm_shims();
|
|
2362
2496
|
var SERVER_NAME = "crosscheck-agent";
|
|
2363
|
-
var SERVER_VERSION = true ? "0.2.
|
|
2497
|
+
var SERVER_VERSION = true ? "0.2.29" : "0.0.0-dev";
|
|
2364
2498
|
|
|
2365
2499
|
// src/tools/audit.ts
|
|
2366
2500
|
init_esm_shims();
|
|
@@ -2427,27 +2561,27 @@ function extractJson(text) {
|
|
|
2427
2561
|
|
|
2428
2562
|
// src/core/json-schema.ts
|
|
2429
2563
|
init_esm_shims();
|
|
2430
|
-
function validateSchema(value, schema,
|
|
2564
|
+
function validateSchema(value, schema, path17 = "") {
|
|
2431
2565
|
const errs = [];
|
|
2432
2566
|
if ("anyOf" in schema) {
|
|
2433
2567
|
const subs = schema["anyOf"].map(
|
|
2434
|
-
(s) => validateSchema(value, s,
|
|
2568
|
+
(s) => validateSchema(value, s, path17)
|
|
2435
2569
|
);
|
|
2436
2570
|
if (!subs.some((e) => e.length === 0)) {
|
|
2437
|
-
errs.push(`${
|
|
2571
|
+
errs.push(`${path17 || "<root>"}: did not match anyOf`);
|
|
2438
2572
|
}
|
|
2439
2573
|
return errs;
|
|
2440
2574
|
}
|
|
2441
2575
|
if ("oneOf" in schema) {
|
|
2442
|
-
const passed = schema["oneOf"].filter((s) => validateSchema(value, s,
|
|
2576
|
+
const passed = schema["oneOf"].filter((s) => validateSchema(value, s, path17).length === 0).length;
|
|
2443
2577
|
if (passed !== 1) {
|
|
2444
|
-
errs.push(`${
|
|
2578
|
+
errs.push(`${path17 || "<root>"}: matched ${passed} of oneOf, expected 1`);
|
|
2445
2579
|
}
|
|
2446
2580
|
return errs;
|
|
2447
2581
|
}
|
|
2448
2582
|
if ("const" in schema && !deepEqual(value, schema["const"])) {
|
|
2449
2583
|
errs.push(
|
|
2450
|
-
`${
|
|
2584
|
+
`${path17 || "<root>"}: expected const ${pyRepr(schema["const"])}, got ${pyRepr(value)}`
|
|
2451
2585
|
);
|
|
2452
2586
|
return errs;
|
|
2453
2587
|
}
|
|
@@ -2457,7 +2591,7 @@ function validateSchema(value, schema, path16 = "") {
|
|
|
2457
2591
|
const ok = types.some((tt) => matchesType(value, String(tt)));
|
|
2458
2592
|
if (!ok) {
|
|
2459
2593
|
errs.push(
|
|
2460
|
-
`${
|
|
2594
|
+
`${path17 || "<root>"}: expected type ${pyReprType(t)}, got ${pyTypeName(value)}`
|
|
2461
2595
|
);
|
|
2462
2596
|
return errs;
|
|
2463
2597
|
}
|
|
@@ -2466,29 +2600,29 @@ function validateSchema(value, schema, path16 = "") {
|
|
|
2466
2600
|
if ("enum" in schema) {
|
|
2467
2601
|
const en = schema["enum"];
|
|
2468
2602
|
if (!en.some((x) => deepEqual(x, value))) {
|
|
2469
|
-
errs.push(`${
|
|
2603
|
+
errs.push(`${path17 || "<root>"}: value ${pyRepr(value)} not in enum`);
|
|
2470
2604
|
}
|
|
2471
2605
|
}
|
|
2472
2606
|
if ("minLength" in schema && value.length < schema["minLength"]) {
|
|
2473
|
-
errs.push(`${
|
|
2607
|
+
errs.push(`${path17 || "<root>"}: shorter than minLength ${schema["minLength"]}`);
|
|
2474
2608
|
}
|
|
2475
2609
|
}
|
|
2476
2610
|
if (typeof value === "number" && !Number.isNaN(value)) {
|
|
2477
2611
|
if ("minimum" in schema && value < schema["minimum"]) {
|
|
2478
|
-
errs.push(`${
|
|
2612
|
+
errs.push(`${path17 || "<root>"}: ${value} < minimum ${schema["minimum"]}`);
|
|
2479
2613
|
}
|
|
2480
2614
|
if ("maximum" in schema && value > schema["maximum"]) {
|
|
2481
|
-
errs.push(`${
|
|
2615
|
+
errs.push(`${path17 || "<root>"}: ${value} > maximum ${schema["maximum"]}`);
|
|
2482
2616
|
}
|
|
2483
2617
|
}
|
|
2484
2618
|
if (Array.isArray(value)) {
|
|
2485
2619
|
if ("minItems" in schema && value.length < schema["minItems"]) {
|
|
2486
|
-
errs.push(`${
|
|
2620
|
+
errs.push(`${path17 || "<root>"}: fewer items than minItems ${schema["minItems"]}`);
|
|
2487
2621
|
}
|
|
2488
2622
|
const itemSchema = schema["items"];
|
|
2489
2623
|
if (isObj(itemSchema)) {
|
|
2490
2624
|
for (let i = 0; i < value.length; i++) {
|
|
2491
|
-
errs.push(...validateSchema(value[i], itemSchema, `${
|
|
2625
|
+
errs.push(...validateSchema(value[i], itemSchema, `${path17}[${i}]`));
|
|
2492
2626
|
}
|
|
2493
2627
|
}
|
|
2494
2628
|
}
|
|
@@ -2497,19 +2631,19 @@ function validateSchema(value, schema, path16 = "") {
|
|
|
2497
2631
|
const required = schema["required"] ?? [];
|
|
2498
2632
|
for (const r of required) {
|
|
2499
2633
|
if (!(r in value)) {
|
|
2500
|
-
errs.push(`${
|
|
2634
|
+
errs.push(`${path17 || "<root>"}: missing required key ${pyRepr(r)}`);
|
|
2501
2635
|
}
|
|
2502
2636
|
}
|
|
2503
2637
|
if (schema["additionalProperties"] === false) {
|
|
2504
2638
|
for (const k of Object.keys(value)) {
|
|
2505
2639
|
if (!(k in props)) {
|
|
2506
|
-
errs.push(`${
|
|
2640
|
+
errs.push(`${path17 || "<root>"}: unknown key ${pyRepr(k)}`);
|
|
2507
2641
|
}
|
|
2508
2642
|
}
|
|
2509
2643
|
}
|
|
2510
2644
|
for (const [k, v] of Object.entries(value)) {
|
|
2511
2645
|
const ps = props[k];
|
|
2512
|
-
if (ps) errs.push(...validateSchema(v, ps,
|
|
2646
|
+
if (ps) errs.push(...validateSchema(v, ps, path17 ? `${path17}.${k}` : k));
|
|
2513
2647
|
}
|
|
2514
2648
|
}
|
|
2515
2649
|
return errs;
|
|
@@ -2591,6 +2725,34 @@ function pyReprType(t) {
|
|
|
2591
2725
|
|
|
2592
2726
|
// src/core/usage.ts
|
|
2593
2727
|
init_esm_shims();
|
|
2728
|
+
|
|
2729
|
+
// src/core/session.ts
|
|
2730
|
+
init_esm_shims();
|
|
2731
|
+
import { randomUUID } from "crypto";
|
|
2732
|
+
var processSessionId = null;
|
|
2733
|
+
var startedAt = null;
|
|
2734
|
+
function engineSessionId() {
|
|
2735
|
+
if (processSessionId === null) {
|
|
2736
|
+
processSessionId = randomUUID();
|
|
2737
|
+
startedAt = Date.now();
|
|
2738
|
+
}
|
|
2739
|
+
return processSessionId;
|
|
2740
|
+
}
|
|
2741
|
+
function resolveSessionId(callerSupplied) {
|
|
2742
|
+
const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
|
|
2743
|
+
return trimmed.length > 0 ? trimmed : engineSessionId();
|
|
2744
|
+
}
|
|
2745
|
+
function localSessionRecordingEnabled(env = globalThis.process?.env ?? {}) {
|
|
2746
|
+
const v = (env["CROSSCHECK_RECORD_SESSIONS"] ?? "").trim().toLowerCase();
|
|
2747
|
+
return !["0", "false", "off", "no"].includes(v);
|
|
2748
|
+
}
|
|
2749
|
+
function recordingSessionId(callerSupplied) {
|
|
2750
|
+
if (localSessionRecordingEnabled()) return resolveSessionId(callerSupplied);
|
|
2751
|
+
const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
|
|
2752
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
// src/core/usage.ts
|
|
2594
2756
|
function emptyUsage(provider, model, purpose = "worker") {
|
|
2595
2757
|
return {
|
|
2596
2758
|
provider,
|
|
@@ -2695,11 +2857,11 @@ function withCommas(n) {
|
|
|
2695
2857
|
function renderRunSummary(opts) {
|
|
2696
2858
|
const endedAt = opts.endedAtS ?? Math.trunc(Date.now() / 1e3);
|
|
2697
2859
|
let scope = "call";
|
|
2698
|
-
let
|
|
2860
|
+
let startedAt2 = null;
|
|
2699
2861
|
let rows = [];
|
|
2700
2862
|
if (opts.sessionScope && opts.sessionScope.rows.length > 0) {
|
|
2701
2863
|
scope = "session";
|
|
2702
|
-
|
|
2864
|
+
startedAt2 = opts.sessionScope.startedAt;
|
|
2703
2865
|
rows = opts.sessionScope.rows.map((r) => ({ ...r }));
|
|
2704
2866
|
} else {
|
|
2705
2867
|
const byPurpose = /* @__PURE__ */ new Map();
|
|
@@ -2730,6 +2892,7 @@ function renderRunSummary(opts) {
|
|
|
2730
2892
|
row.cpu_ms += a.cpu_ms ?? 0;
|
|
2731
2893
|
if (a.cache_hit) row.cache_hits += 1;
|
|
2732
2894
|
if (a.error) row.errors += 1;
|
|
2895
|
+
if (a.usage?.estimated) row.estimated = true;
|
|
2733
2896
|
}
|
|
2734
2897
|
rows = Array.from(byPurpose.values());
|
|
2735
2898
|
}
|
|
@@ -2742,16 +2905,18 @@ function renderRunSummary(opts) {
|
|
|
2742
2905
|
wall_ms: rows.reduce((s, r) => s + r.wall_ms, 0),
|
|
2743
2906
|
cpu_ms: rows.reduce((s, r) => s + r.cpu_ms, 0),
|
|
2744
2907
|
cache_hits: rows.reduce((s, r) => s + r.cache_hits, 0),
|
|
2745
|
-
errors: rows.reduce((s, r) => s + r.errors, 0)
|
|
2908
|
+
errors: rows.reduce((s, r) => s + r.errors, 0),
|
|
2909
|
+
...rows.some((r) => r.estimated) ? { estimated: true } : {}
|
|
2746
2910
|
};
|
|
2747
2911
|
const titleLeft = scope === "session" ? `session: ${opts.sessionId ?? ""}` : `call: ${opts.toolName}`;
|
|
2748
|
-
const
|
|
2912
|
+
const costText = totals.estimated ? `$${totals.cost_usd.toFixed(4)}+ (some calls unpriced)` : `$${totals.cost_usd.toFixed(4)}`;
|
|
2913
|
+
const header = `${titleLeft} (${totals.calls} calls, ${withCommas(totals.total_tokens)} tokens, ${costText}, ${(totals.wall_ms / 1e3).toFixed(1)}s wall, ${(totals.cpu_ms / 1e3).toFixed(3)}s cpu)`;
|
|
2749
2914
|
const bodyLines = [];
|
|
2750
2915
|
for (let i = 0; i < rows.length; i++) {
|
|
2751
2916
|
const r = rows[i];
|
|
2752
2917
|
const glyph = i === rows.length - 1 ? "`-" : "|-";
|
|
2753
2918
|
bodyLines.push(
|
|
2754
|
-
`${glyph} purpose: ${r.purpose} (calls=${r.calls} tokens=${withCommas(r.total_tokens)} cost=$${r.cost_usd.toFixed(4)} wall=${(r.wall_ms / 1e3).toFixed(1)}s cpu=${(r.cpu_ms / 1e3).toFixed(3)}s)`
|
|
2919
|
+
`${glyph} purpose: ${r.purpose} (calls=${r.calls} tokens=${withCommas(r.total_tokens)} cost=$${r.cost_usd.toFixed(4)}${r.estimated ? "+" : ""} wall=${(r.wall_ms / 1e3).toFixed(1)}s cpu=${(r.cpu_ms / 1e3).toFixed(3)}s)`
|
|
2755
2920
|
);
|
|
2756
2921
|
}
|
|
2757
2922
|
const callByModel = rollupSpendByModel(
|
|
@@ -2799,7 +2964,7 @@ function renderRunSummary(opts) {
|
|
|
2799
2964
|
tool: opts.toolName,
|
|
2800
2965
|
scope,
|
|
2801
2966
|
currency: "USD",
|
|
2802
|
-
started_at:
|
|
2967
|
+
started_at: startedAt2,
|
|
2803
2968
|
ended_at: endedAt,
|
|
2804
2969
|
rows,
|
|
2805
2970
|
totals,
|
|
@@ -2924,14 +3089,15 @@ async function attachUsageBlock(result, answers, opts) {
|
|
|
2924
3089
|
delete result["_suppress_run_summary"];
|
|
2925
3090
|
}
|
|
2926
3091
|
async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
|
|
2927
|
-
|
|
3092
|
+
const sid = recordingSessionId(sessionId);
|
|
3093
|
+
if (!sid || answers.length === 0) return;
|
|
2928
3094
|
const now = nowS ?? Math.trunc(Date.now() / 1e3);
|
|
2929
3095
|
const rows = [];
|
|
2930
3096
|
for (const a of answers) {
|
|
2931
3097
|
const u = a.usage;
|
|
2932
3098
|
if (!u || typeof u.provider !== "string" || u.provider === "") continue;
|
|
2933
3099
|
rows.push({
|
|
2934
|
-
session_id:
|
|
3100
|
+
session_id: sid,
|
|
2935
3101
|
ts: now,
|
|
2936
3102
|
tool: toolName,
|
|
2937
3103
|
purpose: u.purpose ?? "worker",
|
|
@@ -2954,13 +3120,14 @@ async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
|
|
|
2954
3120
|
}
|
|
2955
3121
|
}
|
|
2956
3122
|
async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, nowS) {
|
|
2957
|
-
|
|
3123
|
+
const sid = recordingSessionId(sessionId);
|
|
3124
|
+
if (!sid) return;
|
|
2958
3125
|
const now = nowS ?? Math.trunc(Date.now() / 1e3);
|
|
2959
3126
|
try {
|
|
2960
|
-
let existing = await storage.getSession(
|
|
3127
|
+
let existing = await storage.getSession(sid);
|
|
2961
3128
|
if (!existing) {
|
|
2962
3129
|
await storage.upsertSession({
|
|
2963
|
-
session_id:
|
|
3130
|
+
session_id: sid,
|
|
2964
3131
|
started_at: now,
|
|
2965
3132
|
last_at: now,
|
|
2966
3133
|
calls: 0,
|
|
@@ -2973,7 +3140,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
|
|
|
2973
3140
|
total_cost_usd: 0,
|
|
2974
3141
|
total_cpu_ms: 0
|
|
2975
3142
|
});
|
|
2976
|
-
existing = await storage.getSession(
|
|
3143
|
+
existing = await storage.getSession(sid);
|
|
2977
3144
|
}
|
|
2978
3145
|
if (!existing) return;
|
|
2979
3146
|
let promptDelta = 0;
|
|
@@ -2993,7 +3160,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
|
|
|
2993
3160
|
}
|
|
2994
3161
|
if (a.cache_hit) cacheHitDelta += 1;
|
|
2995
3162
|
}
|
|
2996
|
-
await storage.accumulateSessionTotals(
|
|
3163
|
+
await storage.accumulateSessionTotals(sid, {
|
|
2997
3164
|
calls: answers.length,
|
|
2998
3165
|
wall_ms: wallMs,
|
|
2999
3166
|
cache_hits: cacheHitDelta,
|
|
@@ -5962,10 +6129,6 @@ If you need supporting evidence, you may emit ONE \`<tool_call>...</tool_call>\`
|
|
|
5962
6129
|
}
|
|
5963
6130
|
|
|
5964
6131
|
// src/tools/confer.ts
|
|
5965
|
-
var DEFERRED_OPTS = [
|
|
5966
|
-
// empty — every confer opt runs natively except worker_tools, which
|
|
5967
|
-
// is gated below (non-empty list → defer).
|
|
5968
|
-
];
|
|
5969
6132
|
async function runConfer(args, opts) {
|
|
5970
6133
|
const callStartedWall = performance3.now();
|
|
5971
6134
|
const callStartedCpu = process.cpuUsage();
|
|
@@ -5981,16 +6144,11 @@ async function runConfer(args, opts) {
|
|
|
5981
6144
|
rejectedWorkerTools.push(t);
|
|
5982
6145
|
}
|
|
5983
6146
|
}
|
|
5984
|
-
|
|
5985
|
-
const needsBridge = DEFERRED_OPTS.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
5986
|
-
if (needsBridge) {
|
|
5987
|
-
if (opts.bridge && opts.bridge.toolNames.has("confer")) {
|
|
5988
|
-
return await deferConfer(args, opts.bridge);
|
|
5989
|
-
}
|
|
6147
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
5990
6148
|
return errorEnvelope2(
|
|
5991
6149
|
"CONFER_OPT_NOT_NATIVE",
|
|
5992
6150
|
"worker_tools requested but innerCallers are not wired",
|
|
5993
|
-
"Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host
|
|
6151
|
+
"Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host."
|
|
5994
6152
|
);
|
|
5995
6153
|
}
|
|
5996
6154
|
const question = typeof args["question"] === "string" ? args["question"] : String(args["question"] ?? "");
|
|
@@ -6341,21 +6499,6 @@ function unknownProviderError(unknownNames, available) {
|
|
|
6341
6499
|
available_now: Object.keys(available).sort()
|
|
6342
6500
|
};
|
|
6343
6501
|
}
|
|
6344
|
-
async function deferConfer(args, bridge) {
|
|
6345
|
-
const r = await bridge.callTool("confer", args);
|
|
6346
|
-
const text = r.content[0]?.text;
|
|
6347
|
-
if (typeof text === "string") {
|
|
6348
|
-
try {
|
|
6349
|
-
return JSON.parse(text);
|
|
6350
|
-
} catch {
|
|
6351
|
-
}
|
|
6352
|
-
}
|
|
6353
|
-
return errorEnvelope2(
|
|
6354
|
-
"CONFER_BRIDGE_BAD_ENVELOPE",
|
|
6355
|
-
"bridge returned an unparseable envelope for confer",
|
|
6356
|
-
"Check that the Python child is healthy."
|
|
6357
|
-
);
|
|
6358
|
-
}
|
|
6359
6502
|
function errorEnvelope2(code, message, hint) {
|
|
6360
6503
|
return {
|
|
6361
6504
|
tool: "confer",
|
|
@@ -6731,7 +6874,7 @@ function errorEnvelope3(code, message, hint) {
|
|
|
6731
6874
|
transient: false
|
|
6732
6875
|
};
|
|
6733
6876
|
}
|
|
6734
|
-
async function runVerify(args,
|
|
6877
|
+
async function runVerify(args, fetchConfig) {
|
|
6735
6878
|
const checks = args["checks"];
|
|
6736
6879
|
if (!Array.isArray(checks) || checks.length === 0) {
|
|
6737
6880
|
return {
|
|
@@ -6743,7 +6886,6 @@ async function runVerify(args, bridge, fetchConfig) {
|
|
|
6743
6886
|
)
|
|
6744
6887
|
};
|
|
6745
6888
|
}
|
|
6746
|
-
void bridge;
|
|
6747
6889
|
const allowShell = Boolean(args["allow_shell"] ?? false);
|
|
6748
6890
|
const wallStart = performance4.now();
|
|
6749
6891
|
const cpuStart = process.cpuUsage();
|
|
@@ -7045,7 +7187,6 @@ async function runBench(args, opts) {
|
|
|
7045
7187
|
const innerOpts = {
|
|
7046
7188
|
providers: opts.providers,
|
|
7047
7189
|
allowlist: opts.allowlist ?? null,
|
|
7048
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7049
7190
|
...opts.moderator ? { moderator: opts.moderator } : {}
|
|
7050
7191
|
};
|
|
7051
7192
|
let inner;
|
|
@@ -7696,11 +7837,11 @@ function getNodeCache(cfg2, repoRoot, key, nowMs) {
|
|
|
7696
7837
|
return null;
|
|
7697
7838
|
}
|
|
7698
7839
|
}
|
|
7699
|
-
function atomicWriteJson(
|
|
7700
|
-
mkdirSync4(dirname2(
|
|
7701
|
-
const tmp = `${
|
|
7840
|
+
function atomicWriteJson(path17, payload) {
|
|
7841
|
+
mkdirSync4(dirname2(path17), { recursive: true });
|
|
7842
|
+
const tmp = `${path17}.${process.pid}.${Date.now()}.tmp`;
|
|
7702
7843
|
writeFileSync3(tmp, JSON.stringify(payload), "utf8");
|
|
7703
|
-
renameSync(tmp,
|
|
7844
|
+
renameSync(tmp, path17);
|
|
7704
7845
|
}
|
|
7705
7846
|
function putNodeCache(cfg2, repoRoot, key, value) {
|
|
7706
7847
|
if (!cfg2 || cfg2.enabled === false) return;
|
|
@@ -7758,7 +7899,6 @@ var EST_TOKENS = {
|
|
|
7758
7899
|
med: [1500, 800],
|
|
7759
7900
|
high: [2500, 1500]
|
|
7760
7901
|
};
|
|
7761
|
-
var DEFERRED_OPTS2 = [];
|
|
7762
7902
|
var REACTIVE_SIGNAL_RE = /<signals>\s*(\{[\s\S]*?\})\s*<\/signals>/g;
|
|
7763
7903
|
function parseReactiveSignals(output) {
|
|
7764
7904
|
if (typeof output !== "string" || !output.includes("<signals>")) return [];
|
|
@@ -7798,17 +7938,6 @@ async function runOrchestrate(args, opts) {
|
|
|
7798
7938
|
);
|
|
7799
7939
|
if (breakerEnv) return breakerEnv;
|
|
7800
7940
|
}
|
|
7801
|
-
const needsBridge = DEFERRED_OPTS2.some((k) => Boolean(args[k]));
|
|
7802
|
-
if (needsBridge) {
|
|
7803
|
-
if (opts.bridge && opts.bridge.toolNames.has("orchestrate")) {
|
|
7804
|
-
return await deferOrchestrate(args, opts.bridge);
|
|
7805
|
-
}
|
|
7806
|
-
return errorEnvelope5(
|
|
7807
|
-
"ORCHESTRATE_OPT_NOT_NATIVE",
|
|
7808
|
-
"this orchestrate opt-in requires the Python bridge in v1",
|
|
7809
|
-
"v1 native covers the plain DAG flow + cheap_mode. reactive (mid-flight DAG updates) still defers. Set CROSSCHECK_BRIDGE_PYTHON=1 to enable."
|
|
7810
|
-
);
|
|
7811
|
-
}
|
|
7812
7941
|
const goal = typeof args["goal"] === "string" ? args["goal"] : null;
|
|
7813
7942
|
const dagIn = isObj5(args["dag"]) ? args["dag"] : null;
|
|
7814
7943
|
if (goal === null === (dagIn === null)) {
|
|
@@ -8750,21 +8879,6 @@ function resolveProviders3(names, available, allowlist) {
|
|
|
8750
8879
|
}
|
|
8751
8880
|
return out;
|
|
8752
8881
|
}
|
|
8753
|
-
async function deferOrchestrate(args, bridge) {
|
|
8754
|
-
const r = await bridge.callTool("orchestrate", args);
|
|
8755
|
-
const text = r.content[0]?.text;
|
|
8756
|
-
if (typeof text === "string") {
|
|
8757
|
-
try {
|
|
8758
|
-
return JSON.parse(text);
|
|
8759
|
-
} catch {
|
|
8760
|
-
}
|
|
8761
|
-
}
|
|
8762
|
-
return errorEnvelope5(
|
|
8763
|
-
"ORCHESTRATE_BRIDGE_BAD_ENVELOPE",
|
|
8764
|
-
"bridge returned an unparseable envelope for orchestrate",
|
|
8765
|
-
"Check that the Python child is healthy."
|
|
8766
|
-
);
|
|
8767
|
-
}
|
|
8768
8882
|
function errorEnvelope5(code, message, hint, kind = "client") {
|
|
8769
8883
|
return {
|
|
8770
8884
|
tool: "orchestrate",
|
|
@@ -9084,6 +9198,16 @@ function buildCallContext(args) {
|
|
|
9084
9198
|
var CREATE_DOC_MAX_BYTES = 32 * 1024;
|
|
9085
9199
|
var CREATE_AUDIT_THRESHOLD = 0.7;
|
|
9086
9200
|
async function runCreate(args, opts) {
|
|
9201
|
+
const subEnvelopes = [];
|
|
9202
|
+
const tracked = (fn) => async (...a) => {
|
|
9203
|
+
const out = await fn(...a);
|
|
9204
|
+
subEnvelopes.push(out);
|
|
9205
|
+
return out;
|
|
9206
|
+
};
|
|
9207
|
+
const confer = tracked(runConfer);
|
|
9208
|
+
const orchestrate = tracked(runOrchestrate);
|
|
9209
|
+
const review = tracked(runReview);
|
|
9210
|
+
const audit = tracked(runAudit);
|
|
9087
9211
|
const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
|
|
9088
9212
|
if (!instruction) {
|
|
9089
9213
|
return errorEnvelope6(
|
|
@@ -9120,7 +9244,7 @@ ${constraints}
|
|
|
9120
9244
|
|
|
9121
9245
|
` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
|
|
9122
9246
|
${documentsPayload}`;
|
|
9123
|
-
const scope = await
|
|
9247
|
+
const scope = await confer({
|
|
9124
9248
|
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,
|
|
9125
9249
|
context: contextBlock,
|
|
9126
9250
|
...providers !== void 0 ? { providers } : {},
|
|
@@ -9129,7 +9253,6 @@ ${documentsPayload}`;
|
|
|
9129
9253
|
}, {
|
|
9130
9254
|
providers: opts.providers,
|
|
9131
9255
|
allowlist: opts.allowlist ?? null,
|
|
9132
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9133
9256
|
ctx
|
|
9134
9257
|
});
|
|
9135
9258
|
const scopeAnswer = Array.isArray(scope["answers"]) ? scope["answers"].filter((a) => typeof a["response"] === "string" && a["response"]).map((a) => `[${a["provider"]}]
|
|
@@ -9148,11 +9271,10 @@ ${scopeAnswer || "(none)"}
|
|
|
9148
9271
|
};
|
|
9149
9272
|
if (providers !== void 0) orchestrateArgs["providers"] = providers;
|
|
9150
9273
|
if (planOnly) orchestrateArgs["plan_only"] = true;
|
|
9151
|
-
let orchestration = await
|
|
9274
|
+
let orchestration = await orchestrate(orchestrateArgs, {
|
|
9152
9275
|
providers: opts.providers,
|
|
9153
9276
|
allowlist: opts.allowlist ?? null,
|
|
9154
9277
|
moderator,
|
|
9155
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9156
9278
|
ctx
|
|
9157
9279
|
});
|
|
9158
9280
|
let attempts = 1;
|
|
@@ -9178,7 +9300,7 @@ ${scopeAnswer || "(none)"}
|
|
|
9178
9300
|
}
|
|
9179
9301
|
let reviewEnvelope = null;
|
|
9180
9302
|
if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
|
|
9181
|
-
reviewEnvelope = await
|
|
9303
|
+
reviewEnvelope = await review({
|
|
9182
9304
|
snippet: orchestration["final"],
|
|
9183
9305
|
intent: `final deliverable for: ${instruction}`,
|
|
9184
9306
|
...providers !== void 0 ? { providers } : {},
|
|
@@ -9187,7 +9309,6 @@ ${scopeAnswer || "(none)"}
|
|
|
9187
9309
|
}, {
|
|
9188
9310
|
providers: opts.providers,
|
|
9189
9311
|
allowlist: opts.allowlist ?? null,
|
|
9190
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9191
9312
|
ctx
|
|
9192
9313
|
});
|
|
9193
9314
|
}
|
|
@@ -9199,7 +9320,7 @@ ${scopeAnswer || "(none)"}
|
|
|
9199
9320
|
const panelExhausted = producingPanel.length > 0 && producingPanel.every(
|
|
9200
9321
|
(p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
|
|
9201
9322
|
) && producingPanel.length >= Object.keys(opts.providers).length;
|
|
9202
|
-
auditEnvelope = await
|
|
9323
|
+
auditEnvelope = await audit({
|
|
9203
9324
|
output_to_audit: orchestration["final"],
|
|
9204
9325
|
producing_panelists: producingPanel,
|
|
9205
9326
|
...auditRubric !== void 0 ? { rubric: auditRubric } : {},
|
|
@@ -9210,7 +9331,6 @@ ${scopeAnswer || "(none)"}
|
|
|
9210
9331
|
}, {
|
|
9211
9332
|
providers: opts.providers,
|
|
9212
9333
|
allowlist: opts.allowlist ?? null,
|
|
9213
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9214
9334
|
ctx
|
|
9215
9335
|
});
|
|
9216
9336
|
let overallF = toNumberOrNull(auditEnvelope["overall_score"]);
|
|
@@ -9229,13 +9349,12 @@ ${retryConstraints}
|
|
|
9229
9349
|
DOCUMENTS:
|
|
9230
9350
|
${documentsPayload}`
|
|
9231
9351
|
};
|
|
9232
|
-
const retryOrchestration = await
|
|
9352
|
+
const retryOrchestration = await orchestrate(
|
|
9233
9353
|
retryOrchestrateArgs,
|
|
9234
9354
|
{
|
|
9235
9355
|
providers: opts.providers,
|
|
9236
9356
|
allowlist: opts.allowlist ?? null,
|
|
9237
9357
|
moderator,
|
|
9238
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9239
9358
|
ctx
|
|
9240
9359
|
}
|
|
9241
9360
|
);
|
|
@@ -9244,7 +9363,7 @@ ${documentsPayload}`
|
|
|
9244
9363
|
if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
|
|
9245
9364
|
const retryPanel = computeProducingPanel(retryOrchestration);
|
|
9246
9365
|
const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
|
|
9247
|
-
auditEnvelope = await
|
|
9366
|
+
auditEnvelope = await audit({
|
|
9248
9367
|
output_to_audit: retryOrchestration["final"],
|
|
9249
9368
|
producing_panelists: retryPanel,
|
|
9250
9369
|
...auditRubric !== void 0 ? { rubric: auditRubric } : {},
|
|
@@ -9255,7 +9374,6 @@ ${documentsPayload}`
|
|
|
9255
9374
|
}, {
|
|
9256
9375
|
providers: opts.providers,
|
|
9257
9376
|
allowlist: opts.allowlist ?? null,
|
|
9258
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9259
9377
|
ctx
|
|
9260
9378
|
});
|
|
9261
9379
|
overallF = toNumberOrNull(auditEnvelope["overall_score"]);
|
|
@@ -9320,9 +9438,28 @@ ${documentsPayload}`
|
|
|
9320
9438
|
["auditor", "items", "overall_score", "passed", "rubric"]
|
|
9321
9439
|
),
|
|
9322
9440
|
artifacts,
|
|
9323
|
-
warnings
|
|
9441
|
+
warnings,
|
|
9442
|
+
...combinedUsage(subEnvelopes)
|
|
9324
9443
|
};
|
|
9325
9444
|
}
|
|
9445
|
+
function combinedUsage(envelopes) {
|
|
9446
|
+
const usages = [];
|
|
9447
|
+
const byCallTiming = [];
|
|
9448
|
+
let wall = 0, cpu = 0;
|
|
9449
|
+
for (const env of envelopes) {
|
|
9450
|
+
const e = env ?? {};
|
|
9451
|
+
const calls = e["usage"]?.["by_call"] ?? [];
|
|
9452
|
+
const t = e["timing"] ?? {};
|
|
9453
|
+
const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
|
|
9454
|
+
if (!Array.isArray(calls) || calls.length === 0) continue;
|
|
9455
|
+
usages.push(...calls);
|
|
9456
|
+
if (timing.length === calls.length) byCallTiming.push(...timing);
|
|
9457
|
+
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 });
|
|
9458
|
+
wall += Number(t["wall_ms"] ?? 0) || 0;
|
|
9459
|
+
cpu += Number(t["cpu_ms"] ?? 0) || 0;
|
|
9460
|
+
}
|
|
9461
|
+
return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
|
|
9462
|
+
}
|
|
9326
9463
|
async function ingestDocuments(documents, sessionId, opts) {
|
|
9327
9464
|
if (documents.length === 0) return [];
|
|
9328
9465
|
const out = [];
|
|
@@ -9494,11 +9631,6 @@ function errorEnvelope6(toolName, code, message, hint) {
|
|
|
9494
9631
|
// src/tools/coordinate.ts
|
|
9495
9632
|
init_esm_shims();
|
|
9496
9633
|
import { performance as performance8 } from "perf_hooks";
|
|
9497
|
-
var DEFERRED_OPTS3 = [
|
|
9498
|
-
// empty — every coordinate opt runs natively when its deps
|
|
9499
|
-
// (storage / innerCallers) are wired. Without them the
|
|
9500
|
-
// worker_tools gate still triggers a bridge defer.
|
|
9501
|
-
];
|
|
9502
9634
|
var COORDINATE_DEFAULT_TEMP = 0.4;
|
|
9503
9635
|
var ROLE_TURN_SCHEMA = {
|
|
9504
9636
|
type: "object",
|
|
@@ -9553,23 +9685,18 @@ async function runCoordinate(args, opts) {
|
|
|
9553
9685
|
rejectedWorkerTools.push(t);
|
|
9554
9686
|
}
|
|
9555
9687
|
}
|
|
9556
|
-
|
|
9557
|
-
const needsBridge = DEFERRED_OPTS3.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
9558
|
-
if (needsBridge) {
|
|
9688
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
9559
9689
|
if (superRequested) {
|
|
9560
9690
|
return errorEnvelope7(
|
|
9561
9691
|
"COORDINATE_SUPER_NOT_NATIVE",
|
|
9562
|
-
"super mode requested
|
|
9563
|
-
"worker_tools
|
|
9692
|
+
"super mode requested with worker_tools, but innerCallers are not wired",
|
|
9693
|
+
"worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
|
|
9564
9694
|
);
|
|
9565
9695
|
}
|
|
9566
|
-
if (opts.bridge && opts.bridge.toolNames.has("coordinate")) {
|
|
9567
|
-
return await deferCoordinate(args, opts.bridge);
|
|
9568
|
-
}
|
|
9569
9696
|
return errorEnvelope7(
|
|
9570
9697
|
"COORDINATE_OPT_NOT_NATIVE",
|
|
9571
9698
|
"worker_tools requested but innerCallers are not wired",
|
|
9572
|
-
"Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host
|
|
9699
|
+
"Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host."
|
|
9573
9700
|
);
|
|
9574
9701
|
}
|
|
9575
9702
|
const untrusted = Boolean(args["untrusted_input"]);
|
|
@@ -9969,21 +10096,6 @@ function unknownProviderError3(unknownNames, available) {
|
|
|
9969
10096
|
available_now: Object.keys(available).sort()
|
|
9970
10097
|
};
|
|
9971
10098
|
}
|
|
9972
|
-
async function deferCoordinate(args, bridge) {
|
|
9973
|
-
const r = await bridge.callTool("coordinate", args);
|
|
9974
|
-
const text = r.content[0]?.text;
|
|
9975
|
-
if (typeof text === "string") {
|
|
9976
|
-
try {
|
|
9977
|
-
return JSON.parse(text);
|
|
9978
|
-
} catch {
|
|
9979
|
-
}
|
|
9980
|
-
}
|
|
9981
|
-
return errorEnvelope7(
|
|
9982
|
-
"COORDINATE_BRIDGE_BAD_ENVELOPE",
|
|
9983
|
-
"bridge returned an unparseable envelope for coordinate",
|
|
9984
|
-
"Check that the Python child is healthy."
|
|
9985
|
-
);
|
|
9986
|
-
}
|
|
9987
10099
|
function errorEnvelope7(code, message, hint) {
|
|
9988
10100
|
return {
|
|
9989
10101
|
tool: "coordinate",
|
|
@@ -10316,10 +10428,6 @@ function buildModeratorTranscript(transcript) {
|
|
|
10316
10428
|
|
|
10317
10429
|
// src/tools/debate.ts
|
|
10318
10430
|
import { performance as performance10 } from "perf_hooks";
|
|
10319
|
-
var DEFERRED_OPTS4 = [
|
|
10320
|
-
// empty — every debate opt runs natively when its deps
|
|
10321
|
-
// (storage / innerCallers) are wired.
|
|
10322
|
-
];
|
|
10323
10431
|
async function runDebate(args, opts) {
|
|
10324
10432
|
const callStartedWall = performance10.now();
|
|
10325
10433
|
const callStartedCpu = process.cpuUsage();
|
|
@@ -10337,23 +10445,18 @@ async function runDebate(args, opts) {
|
|
|
10337
10445
|
rejectedWorkerTools.push(t);
|
|
10338
10446
|
}
|
|
10339
10447
|
}
|
|
10340
|
-
|
|
10341
|
-
const needsBridge = DEFERRED_OPTS4.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
10342
|
-
if (needsBridge) {
|
|
10448
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
10343
10449
|
if (superRequested) {
|
|
10344
10450
|
return errorEnvelope9(
|
|
10345
10451
|
"DEBATE_SUPER_NOT_NATIVE",
|
|
10346
|
-
"super mode requested
|
|
10347
|
-
"worker_tools
|
|
10452
|
+
"super mode requested with worker_tools, but innerCallers are not wired",
|
|
10453
|
+
"worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
|
|
10348
10454
|
);
|
|
10349
10455
|
}
|
|
10350
|
-
if (opts.bridge && opts.bridge.toolNames.has("debate")) {
|
|
10351
|
-
return await deferDebate(args, opts.bridge);
|
|
10352
|
-
}
|
|
10353
10456
|
return errorEnvelope9(
|
|
10354
10457
|
"DEBATE_OPT_NOT_NATIVE",
|
|
10355
10458
|
"worker_tools requested but innerCallers are not wired",
|
|
10356
|
-
"Native debate covers N-round + plain/structured moderator synthesis + inject_session_memory + auto_panel + extract_claims + early_stop. worker_tools needs innerCallers wired by the host
|
|
10459
|
+
"Native debate covers N-round + plain/structured moderator synthesis + inject_session_memory + auto_panel + extract_claims + early_stop. worker_tools needs innerCallers wired by the host."
|
|
10357
10460
|
);
|
|
10358
10461
|
}
|
|
10359
10462
|
const topic = typeof args["topic"] === "string" ? args["topic"] : String(args["topic"] ?? "");
|
|
@@ -10790,21 +10893,6 @@ function unknownProviderError5(unknownNames, available) {
|
|
|
10790
10893
|
available_now: Object.keys(available).sort()
|
|
10791
10894
|
};
|
|
10792
10895
|
}
|
|
10793
|
-
async function deferDebate(args, bridge) {
|
|
10794
|
-
const r = await bridge.callTool("debate", args);
|
|
10795
|
-
const text = r.content[0]?.text;
|
|
10796
|
-
if (typeof text === "string") {
|
|
10797
|
-
try {
|
|
10798
|
-
return JSON.parse(text);
|
|
10799
|
-
} catch {
|
|
10800
|
-
}
|
|
10801
|
-
}
|
|
10802
|
-
return errorEnvelope9(
|
|
10803
|
-
"DEBATE_BRIDGE_BAD_ENVELOPE",
|
|
10804
|
-
"bridge returned an unparseable envelope for debate",
|
|
10805
|
-
"Check that the Python child is healthy."
|
|
10806
|
-
);
|
|
10807
|
-
}
|
|
10808
10896
|
function errorEnvelope9(code, message, hint) {
|
|
10809
10897
|
return {
|
|
10810
10898
|
tool: "debate",
|
|
@@ -10825,9 +10913,6 @@ var DEFAULT_DELEGATION_LIMITS = {
|
|
|
10825
10913
|
};
|
|
10826
10914
|
async function runDelegate(args, opts) {
|
|
10827
10915
|
if (!opts.storage) {
|
|
10828
|
-
if (opts.bridge && opts.bridge.toolNames.has("delegate")) {
|
|
10829
|
-
return await deferDelegate(args, opts.bridge);
|
|
10830
|
-
}
|
|
10831
10916
|
return errorEnvelope10(
|
|
10832
10917
|
"DELEGATE_STORAGE_UNAVAILABLE",
|
|
10833
10918
|
"delegate needs the local database (for quota tracking), which isn't available",
|
|
@@ -10899,7 +10984,6 @@ async function runDelegate(args, opts) {
|
|
|
10899
10984
|
const innerOpts = {
|
|
10900
10985
|
providers: opts.providers,
|
|
10901
10986
|
allowlist: opts.allowlist ?? null,
|
|
10902
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
10903
10987
|
...opts.moderator ? { moderator: opts.moderator } : {}
|
|
10904
10988
|
};
|
|
10905
10989
|
let result;
|
|
@@ -10938,21 +11022,6 @@ async function record(storage, sessionId, requester, toolCall, via, accepted, no
|
|
|
10938
11022
|
created_at: nowEpochSeconds
|
|
10939
11023
|
});
|
|
10940
11024
|
}
|
|
10941
|
-
async function deferDelegate(args, bridge) {
|
|
10942
|
-
const r = await bridge.callTool("delegate", args);
|
|
10943
|
-
const text = r.content[0]?.text;
|
|
10944
|
-
if (typeof text === "string") {
|
|
10945
|
-
try {
|
|
10946
|
-
return JSON.parse(text);
|
|
10947
|
-
} catch {
|
|
10948
|
-
}
|
|
10949
|
-
}
|
|
10950
|
-
return errorEnvelope10(
|
|
10951
|
-
"DELEGATE_BRIDGE_BAD_ENVELOPE",
|
|
10952
|
-
"bridge returned an unparseable envelope for delegate",
|
|
10953
|
-
"Check that the Python child is healthy."
|
|
10954
|
-
);
|
|
10955
|
-
}
|
|
10956
11025
|
function errorEnvelope10(code, message, hint) {
|
|
10957
11026
|
return {
|
|
10958
11027
|
tool: "delegate",
|
|
@@ -10996,9 +11065,6 @@ async function runExplain(args, opts) {
|
|
|
10996
11065
|
);
|
|
10997
11066
|
}
|
|
10998
11067
|
if (!opts.storage) {
|
|
10999
|
-
if (opts.bridge && opts.bridge.toolNames.has("explain")) {
|
|
11000
|
-
return await deferExplain(args, opts.bridge);
|
|
11001
|
-
}
|
|
11002
11068
|
return errorEnvelope11(
|
|
11003
11069
|
"EXPLAIN_STORAGE_UNAVAILABLE",
|
|
11004
11070
|
"explain needs the local transcript/stats database, which isn't available",
|
|
@@ -11280,21 +11346,6 @@ function pyRepr5(v) {
|
|
|
11280
11346
|
}
|
|
11281
11347
|
return String(v);
|
|
11282
11348
|
}
|
|
11283
|
-
async function deferExplain(args, bridge) {
|
|
11284
|
-
const r = await bridge.callTool("explain", args);
|
|
11285
|
-
const text = r.content[0]?.text;
|
|
11286
|
-
if (typeof text === "string") {
|
|
11287
|
-
try {
|
|
11288
|
-
return JSON.parse(text);
|
|
11289
|
-
} catch {
|
|
11290
|
-
}
|
|
11291
|
-
}
|
|
11292
|
-
return errorEnvelope11(
|
|
11293
|
-
"EXPLAIN_BRIDGE_BAD_ENVELOPE",
|
|
11294
|
-
"bridge returned an unparseable envelope for explain",
|
|
11295
|
-
"Check that the Python child is healthy."
|
|
11296
|
-
);
|
|
11297
|
-
}
|
|
11298
11349
|
function errorEnvelope11(code, message, hint, kind = "client", extra = {}) {
|
|
11299
11350
|
return {
|
|
11300
11351
|
tool: "explain",
|
|
@@ -11852,9 +11903,6 @@ async function runRecall(args, opts) {
|
|
|
11852
11903
|
if (k < 1) k = 1;
|
|
11853
11904
|
if (k > 50) k = 50;
|
|
11854
11905
|
if (!opts.storage) {
|
|
11855
|
-
if (opts.bridge && opts.bridge.toolNames.has("recall")) {
|
|
11856
|
-
return await deferRecall(args, opts.bridge);
|
|
11857
|
-
}
|
|
11858
11906
|
return errorEnvelope12(
|
|
11859
11907
|
"RECALL_STORAGE_UNAVAILABLE",
|
|
11860
11908
|
"recall needs the local database, which isn't available",
|
|
@@ -11907,21 +11955,6 @@ async function runRecall(args, opts) {
|
|
|
11907
11955
|
applied_filters: applied
|
|
11908
11956
|
};
|
|
11909
11957
|
}
|
|
11910
|
-
async function deferRecall(args, bridge) {
|
|
11911
|
-
const r = await bridge.callTool("recall", args);
|
|
11912
|
-
const text = r.content[0]?.text;
|
|
11913
|
-
if (typeof text === "string") {
|
|
11914
|
-
try {
|
|
11915
|
-
return JSON.parse(text);
|
|
11916
|
-
} catch {
|
|
11917
|
-
}
|
|
11918
|
-
}
|
|
11919
|
-
return errorEnvelope12(
|
|
11920
|
-
"RECALL_BRIDGE_BAD_ENVELOPE",
|
|
11921
|
-
"bridge returned an unparseable envelope for recall",
|
|
11922
|
-
"Check that the Python child is healthy."
|
|
11923
|
-
);
|
|
11924
|
-
}
|
|
11925
11958
|
function errorEnvelope12(code, message, hint) {
|
|
11926
11959
|
return {
|
|
11927
11960
|
tool: "recall",
|
|
@@ -11945,9 +11978,6 @@ async function runRecommendPanel(args, opts) {
|
|
|
11945
11978
|
);
|
|
11946
11979
|
}
|
|
11947
11980
|
if (!opts.storage) {
|
|
11948
|
-
if (opts.bridge && opts.bridge.toolNames.has("recommend_panel")) {
|
|
11949
|
-
return await deferRecommendPanel(args, opts.bridge);
|
|
11950
|
-
}
|
|
11951
11981
|
return errorEnvelope13(
|
|
11952
11982
|
"RECOMMEND_PANEL_STORAGE_UNAVAILABLE",
|
|
11953
11983
|
"recommend_panel needs the local stats database, which isn't available",
|
|
@@ -12010,21 +12040,6 @@ async function runRecommendPanel(args, opts) {
|
|
|
12010
12040
|
meta: result.meta
|
|
12011
12041
|
};
|
|
12012
12042
|
}
|
|
12013
|
-
async function deferRecommendPanel(args, bridge) {
|
|
12014
|
-
const r = await bridge.callTool("recommend_panel", args);
|
|
12015
|
-
const text = r.content[0]?.text;
|
|
12016
|
-
if (typeof text === "string") {
|
|
12017
|
-
try {
|
|
12018
|
-
return JSON.parse(text);
|
|
12019
|
-
} catch {
|
|
12020
|
-
}
|
|
12021
|
-
}
|
|
12022
|
-
return errorEnvelope13(
|
|
12023
|
-
"RECOMMEND_PANEL_BRIDGE_BAD_ENVELOPE",
|
|
12024
|
-
"bridge returned an unparseable envelope for recommend_panel",
|
|
12025
|
-
"Check that the Python child is healthy."
|
|
12026
|
-
);
|
|
12027
|
-
}
|
|
12028
12043
|
function errorEnvelope13(code, message, hint) {
|
|
12029
12044
|
return {
|
|
12030
12045
|
tool: "recommend_panel",
|
|
@@ -12055,9 +12070,6 @@ init_esm_shims();
|
|
|
12055
12070
|
import { readFileSync as readFileSync10, existsSync as existsSync8 } from "fs";
|
|
12056
12071
|
async function runScoreboard(args, opts) {
|
|
12057
12072
|
if (!opts.storage) {
|
|
12058
|
-
if (opts.bridge && opts.bridge.toolNames.has("scoreboard")) {
|
|
12059
|
-
return await deferScoreboard(args, opts.bridge);
|
|
12060
|
-
}
|
|
12061
12073
|
return errorEnvelope14(
|
|
12062
12074
|
"SCOREBOARD_STORAGE_UNAVAILABLE",
|
|
12063
12075
|
"scoreboard needs the local stats database, which isn't available",
|
|
@@ -12180,21 +12192,6 @@ function clampInt3(raw, min, max, fallback) {
|
|
|
12180
12192
|
if (!Number.isFinite(n)) return fallback;
|
|
12181
12193
|
return Math.min(max, Math.max(min, Math.trunc(n)));
|
|
12182
12194
|
}
|
|
12183
|
-
async function deferScoreboard(args, bridge) {
|
|
12184
|
-
const r = await bridge.callTool("scoreboard", args);
|
|
12185
|
-
const text = r.content[0]?.text;
|
|
12186
|
-
if (typeof text === "string") {
|
|
12187
|
-
try {
|
|
12188
|
-
return JSON.parse(text);
|
|
12189
|
-
} catch {
|
|
12190
|
-
}
|
|
12191
|
-
}
|
|
12192
|
-
return errorEnvelope14(
|
|
12193
|
-
"SCOREBOARD_BRIDGE_BAD_ENVELOPE",
|
|
12194
|
-
"bridge returned an unparseable envelope for scoreboard",
|
|
12195
|
-
"Check that the Python child is healthy."
|
|
12196
|
-
);
|
|
12197
|
-
}
|
|
12198
12195
|
function errorEnvelope14(code, message, hint) {
|
|
12199
12196
|
return {
|
|
12200
12197
|
tool: "scoreboard",
|
|
@@ -12232,9 +12229,6 @@ async function runSessionMemory(args, opts) {
|
|
|
12232
12229
|
);
|
|
12233
12230
|
}
|
|
12234
12231
|
if (!opts.storage) {
|
|
12235
|
-
if (opts.bridge && opts.bridge.toolNames.has("session_memory")) {
|
|
12236
|
-
return await deferSessionMemory(args, opts.bridge);
|
|
12237
|
-
}
|
|
12238
12232
|
return errorEnvelope15(
|
|
12239
12233
|
"SESSION_MEMORY_STORAGE_UNAVAILABLE",
|
|
12240
12234
|
"session_memory needs the local database, which isn't available",
|
|
@@ -12339,21 +12333,6 @@ function clampInt4(raw, min, max, fallback) {
|
|
|
12339
12333
|
if (!Number.isFinite(n)) return fallback;
|
|
12340
12334
|
return Math.min(max, Math.max(min, Math.trunc(n)));
|
|
12341
12335
|
}
|
|
12342
|
-
async function deferSessionMemory(args, bridge) {
|
|
12343
|
-
const r = await bridge.callTool("session_memory", args);
|
|
12344
|
-
const text = r.content[0]?.text;
|
|
12345
|
-
if (typeof text === "string") {
|
|
12346
|
-
try {
|
|
12347
|
-
return JSON.parse(text);
|
|
12348
|
-
} catch {
|
|
12349
|
-
}
|
|
12350
|
-
}
|
|
12351
|
-
return errorEnvelope15(
|
|
12352
|
-
"SESSION_MEMORY_BRIDGE_BAD_ENVELOPE",
|
|
12353
|
-
"bridge returned an unparseable envelope for session_memory",
|
|
12354
|
-
"Check that the Python child is healthy."
|
|
12355
|
-
);
|
|
12356
|
-
}
|
|
12357
12336
|
function errorEnvelope15(code, message, hint) {
|
|
12358
12337
|
return {
|
|
12359
12338
|
tool: "session_memory",
|
|
@@ -12977,7 +12956,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
|
|
|
12977
12956
|
var DEFAULT_PACKAGE = "crosscheck-cli";
|
|
12978
12957
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
12979
12958
|
function engineVersion() {
|
|
12980
|
-
return true ? "0.2.
|
|
12959
|
+
return true ? "0.2.29" : "0.0.0-dev";
|
|
12981
12960
|
}
|
|
12982
12961
|
function defaultUpdateCachePath() {
|
|
12983
12962
|
const base = process.env["CROSSCHECK_DATA_DIR"] || path10.join(os.homedir() || os.tmpdir(), ".crosscheck");
|
|
@@ -13751,12 +13730,11 @@ function helpTool() {
|
|
|
13751
13730
|
}
|
|
13752
13731
|
});
|
|
13753
13732
|
}
|
|
13754
|
-
function registerCoreTools(
|
|
13755
|
-
const o = opts && typeof opts === "object" && "toolNames" in opts ? { bridge: opts } : opts;
|
|
13733
|
+
function registerCoreTools(o = {}) {
|
|
13756
13734
|
const tools = /* @__PURE__ */ new Map();
|
|
13757
13735
|
const list = [
|
|
13758
13736
|
pingTool(),
|
|
13759
|
-
verifyTool(o.
|
|
13737
|
+
verifyTool(o.fetchConfig),
|
|
13760
13738
|
pickTool(
|
|
13761
13739
|
o.providers ?? {},
|
|
13762
13740
|
o.providerAllowlist ?? null,
|
|
@@ -13768,7 +13746,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13768
13746
|
auditTool(
|
|
13769
13747
|
o.providers ?? {},
|
|
13770
13748
|
o.providerAllowlist ?? null,
|
|
13771
|
-
o.bridge,
|
|
13772
13749
|
o.transcriptsDir,
|
|
13773
13750
|
o.pricing,
|
|
13774
13751
|
o.storage,
|
|
@@ -13778,7 +13755,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13778
13755
|
conferTool(
|
|
13779
13756
|
o.providers ?? {},
|
|
13780
13757
|
o.providerAllowlist ?? null,
|
|
13781
|
-
o.bridge,
|
|
13782
13758
|
o.moderatorDefault ?? "anthropic",
|
|
13783
13759
|
o.pricing,
|
|
13784
13760
|
o.storage,
|
|
@@ -13791,7 +13767,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13791
13767
|
debateTool(
|
|
13792
13768
|
o.providers ?? {},
|
|
13793
13769
|
o.providerAllowlist ?? null,
|
|
13794
|
-
o.bridge,
|
|
13795
13770
|
buildInnerCallers(o),
|
|
13796
13771
|
o.storage,
|
|
13797
13772
|
o.pricing,
|
|
@@ -13803,7 +13778,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13803
13778
|
coordinateTool(
|
|
13804
13779
|
o.providers ?? {},
|
|
13805
13780
|
o.providerAllowlist ?? null,
|
|
13806
|
-
o.bridge,
|
|
13807
13781
|
buildInnerCallers(o),
|
|
13808
13782
|
o.storage,
|
|
13809
13783
|
o.circuitBreakers,
|
|
@@ -13814,7 +13788,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13814
13788
|
triangulateTool(
|
|
13815
13789
|
o.providers ?? {},
|
|
13816
13790
|
o.providerAllowlist ?? null,
|
|
13817
|
-
o.bridge,
|
|
13818
13791
|
o.storage,
|
|
13819
13792
|
o.circuitBreakers,
|
|
13820
13793
|
o.transcriptsDir,
|
|
@@ -13823,7 +13796,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13823
13796
|
planTool(
|
|
13824
13797
|
o.providers ?? {},
|
|
13825
13798
|
o.providerAllowlist ?? null,
|
|
13826
|
-
o.bridge,
|
|
13827
13799
|
o.storage,
|
|
13828
13800
|
o.circuitBreakers,
|
|
13829
13801
|
o.transcriptsDir,
|
|
@@ -13832,7 +13804,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13832
13804
|
critiqueTool(
|
|
13833
13805
|
o.providers ?? {},
|
|
13834
13806
|
o.providerAllowlist ?? null,
|
|
13835
|
-
o.bridge,
|
|
13836
13807
|
o.storage,
|
|
13837
13808
|
o.circuitBreakers,
|
|
13838
13809
|
o.transcriptsDir,
|
|
@@ -13841,7 +13812,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13841
13812
|
reviewTool(
|
|
13842
13813
|
o.providers ?? {},
|
|
13843
13814
|
o.providerAllowlist ?? null,
|
|
13844
|
-
o.bridge,
|
|
13845
13815
|
o.storage,
|
|
13846
13816
|
o.circuitBreakers,
|
|
13847
13817
|
o.transcriptsDir,
|
|
@@ -13849,25 +13819,23 @@ function registerCoreTools(opts = {}) {
|
|
|
13849
13819
|
),
|
|
13850
13820
|
listProvidersTool(o.providers ?? {}, o.activeProviders ?? null, o.moderatorDefault ?? "anthropic"),
|
|
13851
13821
|
modelsTool(o.providers ?? {}, o.activeProviders ?? null),
|
|
13852
|
-
recallTool(o.storage
|
|
13853
|
-
sessionMemoryTool(o.storage
|
|
13854
|
-
scoreboardTool(o.storage, o.
|
|
13855
|
-
explainTool(o.storage, o.
|
|
13822
|
+
recallTool(o.storage),
|
|
13823
|
+
sessionMemoryTool(o.storage),
|
|
13824
|
+
scoreboardTool(o.storage, o.eventsPath),
|
|
13825
|
+
explainTool(o.storage, o.transcriptsDir),
|
|
13856
13826
|
delegateTool(
|
|
13857
13827
|
o.providers ?? {},
|
|
13858
13828
|
o.providerAllowlist ?? null,
|
|
13859
13829
|
o.storage,
|
|
13860
|
-
o.bridge,
|
|
13861
13830
|
o.moderatorDefault ?? "anthropic"
|
|
13862
13831
|
),
|
|
13863
13832
|
fetchTool(o.storage, o.fetchConfig, o.repoRoot),
|
|
13864
|
-
recommendPanelTool(o.providers ?? {}, o.storage
|
|
13833
|
+
recommendPanelTool(o.providers ?? {}, o.storage),
|
|
13865
13834
|
updateCrosscheckTool(o.repoRoot ?? null),
|
|
13866
13835
|
benchTool(
|
|
13867
13836
|
o.providers ?? {},
|
|
13868
13837
|
o.providerAllowlist ?? null,
|
|
13869
13838
|
o.storage,
|
|
13870
|
-
o.bridge,
|
|
13871
13839
|
o.moderatorDefault ?? "anthropic",
|
|
13872
13840
|
o.benchGoldensDir,
|
|
13873
13841
|
o.circuitBreakers,
|
|
@@ -13878,7 +13846,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13878
13846
|
solveTool(
|
|
13879
13847
|
o.providers ?? {},
|
|
13880
13848
|
o.providerAllowlist ?? null,
|
|
13881
|
-
o.bridge,
|
|
13882
13849
|
o.storage,
|
|
13883
13850
|
o.circuitBreakers,
|
|
13884
13851
|
o.transcriptsDir,
|
|
@@ -13887,7 +13854,6 @@ function registerCoreTools(opts = {}) {
|
|
|
13887
13854
|
orchestrateTool(
|
|
13888
13855
|
o.providers ?? {},
|
|
13889
13856
|
o.providerAllowlist ?? null,
|
|
13890
|
-
o.bridge,
|
|
13891
13857
|
o.moderatorDefault ?? "anthropic",
|
|
13892
13858
|
o.storage,
|
|
13893
13859
|
o.pricing,
|
|
@@ -13934,7 +13900,6 @@ function createTool(o, toolName, cheapDefault) {
|
|
|
13934
13900
|
providers: o.providers ?? {},
|
|
13935
13901
|
allowlist: o.providerAllowlist ?? null,
|
|
13936
13902
|
...o.storage ? { storage: o.storage } : {},
|
|
13937
|
-
...o.bridge ? { bridge: o.bridge } : {},
|
|
13938
13903
|
...o.moderatorDefault ? { moderator: o.moderatorDefault } : {},
|
|
13939
13904
|
...o.fetchConfig ? { fetchConfig: o.fetchConfig } : {},
|
|
13940
13905
|
...o.repoRoot ? { repoRoot: o.repoRoot } : {},
|
|
@@ -13943,7 +13908,7 @@ function createTool(o, toolName, cheapDefault) {
|
|
|
13943
13908
|
})
|
|
13944
13909
|
};
|
|
13945
13910
|
}
|
|
13946
|
-
function orchestrateTool(providers, allowlist,
|
|
13911
|
+
function orchestrateTool(providers, allowlist, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
|
|
13947
13912
|
return {
|
|
13948
13913
|
name: "orchestrate",
|
|
13949
13914
|
description: "Plan and execute a DAG of LLM subtasks. Either supply a `goal` (planner will draft the DAG) OR a hand-authored `dag`. Workers run topologically; recombine produces a single `final`. Covers the sequential flow, cheap_mode (per-node tier picking), and reactive (mid-flight DAG updates) \u2014 all native.",
|
|
@@ -13968,7 +13933,6 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
|
|
|
13968
13933
|
providers,
|
|
13969
13934
|
allowlist,
|
|
13970
13935
|
moderator,
|
|
13971
|
-
...bridge ? { bridge } : {},
|
|
13972
13936
|
...storage ? { storage } : {},
|
|
13973
13937
|
...pricing ? { pricing } : {},
|
|
13974
13938
|
...breakers ? { breakers } : {},
|
|
@@ -13978,7 +13942,7 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
|
|
|
13978
13942
|
})
|
|
13979
13943
|
};
|
|
13980
13944
|
}
|
|
13981
|
-
function solveTool(providers, allowlist,
|
|
13945
|
+
function solveTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
13982
13946
|
return {
|
|
13983
13947
|
name: "solve",
|
|
13984
13948
|
description: "Iterative LLM solver. Generates a proposal, verifies it against the supplied verifier, and retries with feedback up to max_attempts. Verifier kinds: regex_response and shell (run in a native sandbox with wall-clock + optional memory/CPU limits). With target_path, returns a unified-diff patch.",
|
|
@@ -14000,7 +13964,6 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
|
|
|
14000
13964
|
handler: (args) => runSolve(args, {
|
|
14001
13965
|
providers,
|
|
14002
13966
|
allowlist,
|
|
14003
|
-
...bridge ? { bridge } : {},
|
|
14004
13967
|
...storage ? { storage } : {},
|
|
14005
13968
|
...breakers ? { breakers } : {},
|
|
14006
13969
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -14039,7 +14002,7 @@ function configPinTool(repoRoot, config2, rejectDriftEnv) {
|
|
|
14039
14002
|
}
|
|
14040
14003
|
};
|
|
14041
14004
|
}
|
|
14042
|
-
function benchTool(providers, allowlist, storage,
|
|
14005
|
+
function benchTool(providers, allowlist, storage, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
|
|
14043
14006
|
return {
|
|
14044
14007
|
name: "bench",
|
|
14045
14008
|
description: "Run benchmark goldens against each provider's confer/review output. Each golden: {name, tool_call: confer|review, args, verifiers[]}. Returns per-provider pass/fail/error + a ranking sorted by score. Records ballots into provider_stats when storage is wired (used by triangulate's win-rate weights).",
|
|
@@ -14058,7 +14021,6 @@ function benchTool(providers, allowlist, storage, bridge, moderator, defaultGold
|
|
|
14058
14021
|
allowlist,
|
|
14059
14022
|
moderator,
|
|
14060
14023
|
...storage ? { storage } : {},
|
|
14061
|
-
...bridge ? { bridge } : {},
|
|
14062
14024
|
...defaultGoldensDir ? { defaultGoldensDir } : {},
|
|
14063
14025
|
...breakers ? { breakers } : {},
|
|
14064
14026
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -14085,7 +14047,7 @@ function updateCrosscheckTool(repoRoot) {
|
|
|
14085
14047
|
}
|
|
14086
14048
|
};
|
|
14087
14049
|
}
|
|
14088
|
-
function recommendPanelTool(providers, storage
|
|
14050
|
+
function recommendPanelTool(providers, storage) {
|
|
14089
14051
|
return {
|
|
14090
14052
|
name: "recommend_panel",
|
|
14091
14053
|
description: "Recommend a minimal effective panel for a given purpose, based on historical usage_log + provider_stats. Cold-start falls back to the configured panel ordered by win-rate.",
|
|
@@ -14103,8 +14065,7 @@ function recommendPanelTool(providers, storage, bridge) {
|
|
|
14103
14065
|
},
|
|
14104
14066
|
handler: (args) => runRecommendPanel(args, {
|
|
14105
14067
|
providers,
|
|
14106
|
-
...storage ? { storage } : {}
|
|
14107
|
-
...bridge ? { bridge } : {}
|
|
14068
|
+
...storage ? { storage } : {}
|
|
14108
14069
|
})
|
|
14109
14070
|
};
|
|
14110
14071
|
}
|
|
@@ -14129,7 +14090,7 @@ function fetchTool(storage, fetchConfig, repoRoot) {
|
|
|
14129
14090
|
})
|
|
14130
14091
|
};
|
|
14131
14092
|
}
|
|
14132
|
-
function delegateTool(providers, allowlist, storage,
|
|
14093
|
+
function delegateTool(providers, allowlist, storage, moderator) {
|
|
14133
14094
|
return {
|
|
14134
14095
|
name: "delegate",
|
|
14135
14096
|
description: "Run a delegable tool (confer | review) restricted to a single named provider, with explicit quota check. Records every attempt (accepted or refused) to the delegations table; quota in the response reflects counts AFTER the current call.",
|
|
@@ -14149,12 +14110,11 @@ function delegateTool(providers, allowlist, storage, bridge, moderator) {
|
|
|
14149
14110
|
providers,
|
|
14150
14111
|
allowlist,
|
|
14151
14112
|
moderator,
|
|
14152
|
-
...storage ? { storage } : {}
|
|
14153
|
-
...bridge ? { bridge } : {}
|
|
14113
|
+
...storage ? { storage } : {}
|
|
14154
14114
|
})
|
|
14155
14115
|
};
|
|
14156
14116
|
}
|
|
14157
|
-
function explainTool(storage,
|
|
14117
|
+
function explainTool(storage, transcriptsDir) {
|
|
14158
14118
|
return {
|
|
14159
14119
|
name: "explain",
|
|
14160
14120
|
description: "Replay a session as a navigable tree with cost/latency annotations. Reads usage_log + optionally walks the transcripts directory for per-tool summaries.",
|
|
@@ -14172,12 +14132,11 @@ function explainTool(storage, bridge, transcriptsDir) {
|
|
|
14172
14132
|
},
|
|
14173
14133
|
handler: (args) => runExplain(args, {
|
|
14174
14134
|
...storage ? { storage } : {},
|
|
14175
|
-
...bridge ? { bridge } : {},
|
|
14176
14135
|
...transcriptsDir ? { transcriptsDir } : {}
|
|
14177
14136
|
})
|
|
14178
14137
|
};
|
|
14179
14138
|
}
|
|
14180
|
-
function scoreboardTool(storage,
|
|
14139
|
+
function scoreboardTool(storage, eventsPath) {
|
|
14181
14140
|
return {
|
|
14182
14141
|
name: "scoreboard",
|
|
14183
14142
|
description: "Aggregate provider ballot stats + delegation counts + table totals. Supports top_k (rank limit) and recent_limit (tail of events.jsonl when configured). Reads the engine's local stats database (auto-created at <data dir>/db.sqlite).",
|
|
@@ -14191,12 +14150,11 @@ function scoreboardTool(storage, bridge, eventsPath) {
|
|
|
14191
14150
|
},
|
|
14192
14151
|
handler: (args) => runScoreboard(args, {
|
|
14193
14152
|
...storage ? { storage } : {},
|
|
14194
|
-
...bridge ? { bridge } : {},
|
|
14195
14153
|
...eventsPath ? { eventsPath } : {}
|
|
14196
14154
|
})
|
|
14197
14155
|
};
|
|
14198
14156
|
}
|
|
14199
|
-
function sessionMemoryTool(storage
|
|
14157
|
+
function sessionMemoryTool(storage) {
|
|
14200
14158
|
return {
|
|
14201
14159
|
name: "session_memory",
|
|
14202
14160
|
description: "CRUD over the per-session working memory ledger. Actions: list, add, mark_stale, clear. Uses the engine's local database (auto-created at <data dir>/db.sqlite).",
|
|
@@ -14219,15 +14177,14 @@ function sessionMemoryTool(storage, bridge) {
|
|
|
14219
14177
|
required: ["action", "session_id"]
|
|
14220
14178
|
},
|
|
14221
14179
|
handler: (args) => runSessionMemory(args, {
|
|
14222
|
-
...storage ? { storage } : {}
|
|
14223
|
-
...bridge ? { bridge } : {}
|
|
14180
|
+
...storage ? { storage } : {}
|
|
14224
14181
|
})
|
|
14225
14182
|
};
|
|
14226
14183
|
}
|
|
14227
|
-
function recallTool(storage
|
|
14184
|
+
function recallTool(storage) {
|
|
14228
14185
|
return {
|
|
14229
14186
|
name: "recall",
|
|
14230
|
-
description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter
|
|
14187
|
+
description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter.",
|
|
14231
14188
|
inputSchema: {
|
|
14232
14189
|
type: "object",
|
|
14233
14190
|
additionalProperties: true,
|
|
@@ -14241,8 +14198,7 @@ function recallTool(storage, bridge) {
|
|
|
14241
14198
|
required: ["query"]
|
|
14242
14199
|
},
|
|
14243
14200
|
handler: (args) => runRecall(args, {
|
|
14244
|
-
...storage ? { storage } : {}
|
|
14245
|
-
...bridge ? { bridge } : {}
|
|
14201
|
+
...storage ? { storage } : {}
|
|
14246
14202
|
})
|
|
14247
14203
|
};
|
|
14248
14204
|
}
|
|
@@ -14278,7 +14234,7 @@ function modelsTool(providers, activeProviders) {
|
|
|
14278
14234
|
handler: async (args) => runModels(args, { providers, activeProviders })
|
|
14279
14235
|
};
|
|
14280
14236
|
}
|
|
14281
|
-
function reviewTool(providers, allowlist,
|
|
14237
|
+
function reviewTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
14282
14238
|
return {
|
|
14283
14239
|
name: "review",
|
|
14284
14240
|
description: "Have an LLM panel peer-review a code or proposal snippet. Returns the confer envelope (one answer per provider).",
|
|
@@ -14297,7 +14253,6 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
|
|
|
14297
14253
|
handler: (args) => runReview(args, {
|
|
14298
14254
|
providers,
|
|
14299
14255
|
allowlist,
|
|
14300
|
-
...bridge ? { bridge } : {},
|
|
14301
14256
|
...storage ? { storage } : {},
|
|
14302
14257
|
...breakers ? { breakers } : {},
|
|
14303
14258
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -14305,7 +14260,7 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
|
|
|
14305
14260
|
})
|
|
14306
14261
|
};
|
|
14307
14262
|
}
|
|
14308
|
-
function critiqueTool(providers, allowlist,
|
|
14263
|
+
function critiqueTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
14309
14264
|
return {
|
|
14310
14265
|
name: "critique",
|
|
14311
14266
|
description: "Have each LLM panelist list the top weaknesses of a proposed answer or approach (severity-rated). Returns per-provider weakness lists + a merged list ordered by severity.",
|
|
@@ -14325,7 +14280,6 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
|
|
|
14325
14280
|
handler: (args) => runCritique(args, {
|
|
14326
14281
|
providers,
|
|
14327
14282
|
allowlist,
|
|
14328
|
-
...bridge ? { bridge } : {},
|
|
14329
14283
|
...storage ? { storage } : {},
|
|
14330
14284
|
...breakers ? { breakers } : {},
|
|
14331
14285
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -14333,7 +14287,7 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
|
|
|
14333
14287
|
})
|
|
14334
14288
|
};
|
|
14335
14289
|
}
|
|
14336
|
-
function planTool(providers, allowlist,
|
|
14290
|
+
function planTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
14337
14291
|
return {
|
|
14338
14292
|
name: "plan",
|
|
14339
14293
|
description: 'Have an LLM panel debate a step-by-step plan for the stated goal under the given constraints. Returns the debate envelope with a moderator-synthesised plan. Defaults to `mode: "fast"` (2 rounds + early_stop) \u2014 set `mode: "thorough"` for 5 rounds without early_stop. Explicit `max_rounds` / `early_stop` / `early_stop_threshold` always override the mode preset. Use `structured: true` for schema-validated synthesis.',
|
|
@@ -14360,7 +14314,6 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
|
|
|
14360
14314
|
handler: (args) => runPlan(args, {
|
|
14361
14315
|
providers,
|
|
14362
14316
|
allowlist,
|
|
14363
|
-
...bridge ? { bridge } : {},
|
|
14364
14317
|
...storage ? { storage } : {},
|
|
14365
14318
|
...breakers ? { breakers } : {},
|
|
14366
14319
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -14368,7 +14321,7 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
|
|
|
14368
14321
|
})
|
|
14369
14322
|
};
|
|
14370
14323
|
}
|
|
14371
|
-
function triangulateTool(providers, allowlist,
|
|
14324
|
+
function triangulateTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
14372
14325
|
return {
|
|
14373
14326
|
name: "triangulate",
|
|
14374
14327
|
description: "Run a coordinate flow and reshape the output as a consensus + minority report with per-provider weights. v1 uses 1.0 weights (matches a fresh provider_stats DB); future versions thread real win-rate weights when the DB layer ports.",
|
|
@@ -14389,7 +14342,6 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
|
|
|
14389
14342
|
handler: (args) => runTriangulate(args, {
|
|
14390
14343
|
providers,
|
|
14391
14344
|
allowlist,
|
|
14392
|
-
...bridge ? { bridge } : {},
|
|
14393
14345
|
...storage ? { storage } : {},
|
|
14394
14346
|
...breakers ? { breakers } : {},
|
|
14395
14347
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -14397,7 +14349,7 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
|
|
|
14397
14349
|
})
|
|
14398
14350
|
};
|
|
14399
14351
|
}
|
|
14400
|
-
function coordinateTool(providers, allowlist,
|
|
14352
|
+
function coordinateTool(providers, allowlist, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
14401
14353
|
return {
|
|
14402
14354
|
name: "coordinate",
|
|
14403
14355
|
description: "Run a three-role coordination flow (proposer \u2192 critics \u2192 synthesizer) with structured output at every step. Native opts: untrusted_input (canary + neutralize), worker_tools (bounded ReAct on proposer + critic roles; synth never sees inner tools), inject_session_memory (storage-backed working-memory block prepended to the topic).",
|
|
@@ -14422,7 +14374,6 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
|
|
|
14422
14374
|
handler: (args) => runCoordinate(args, {
|
|
14423
14375
|
providers,
|
|
14424
14376
|
allowlist,
|
|
14425
|
-
...bridge ? { bridge } : {},
|
|
14426
14377
|
innerCallers,
|
|
14427
14378
|
...storage ? { storage } : {},
|
|
14428
14379
|
...breakers ? { breakers } : {},
|
|
@@ -14432,7 +14383,7 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
|
|
|
14432
14383
|
})
|
|
14433
14384
|
};
|
|
14434
14385
|
}
|
|
14435
|
-
function debateTool(providers, allowlist,
|
|
14386
|
+
function debateTool(providers, allowlist, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
14436
14387
|
return {
|
|
14437
14388
|
name: "debate",
|
|
14438
14389
|
description: "Run a multi-round debate between LLM providers and synthesise the result via a moderator. Native opts: inject_session_memory, auto_panel, worker_tools, structured synthesis (schema-validated), extract_claims (final-round distillation), early_stop (post-round agreement check).",
|
|
@@ -14462,7 +14413,6 @@ function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing
|
|
|
14462
14413
|
handler: (args) => runDebate(args, {
|
|
14463
14414
|
providers,
|
|
14464
14415
|
allowlist,
|
|
14465
|
-
...bridge ? { bridge } : {},
|
|
14466
14416
|
innerCallers,
|
|
14467
14417
|
...storage ? { storage } : {},
|
|
14468
14418
|
...pricing ? { pricing } : {},
|
|
@@ -14482,10 +14432,10 @@ function buildInnerCallers(o) {
|
|
|
14482
14432
|
...o.repoRoot ? { repoRoot: o.repoRoot } : {}
|
|
14483
14433
|
});
|
|
14484
14434
|
}
|
|
14485
|
-
out.verify = (args) => runVerify(args, o.
|
|
14435
|
+
out.verify = (args) => runVerify(args, o.fetchConfig);
|
|
14486
14436
|
return out;
|
|
14487
14437
|
}
|
|
14488
|
-
function conferTool(providers, allowlist,
|
|
14438
|
+
function conferTool(providers, allowlist, moderator, pricing, storage, innerCallers, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
14489
14439
|
return {
|
|
14490
14440
|
name: "confer",
|
|
14491
14441
|
description: "Ask a panel of LLM providers the same question; return one answer per provider. Native opts: untrusted_input (canary + neutralization), early_stop (cheap-tier agreement check after first 2 panelists when N>=3), extract_claims (cheap-tier extractor with per-provider support maps), inject_session_memory (storage-backed working-memory block prepended to the first user message), auto_panel (router-driven top-N panel pick), worker_tools (bounded ReAct loop per panelist when innerCallers are wired by the host).",
|
|
@@ -14512,7 +14462,6 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
|
|
|
14512
14462
|
handler: (args) => runConfer(args, {
|
|
14513
14463
|
providers,
|
|
14514
14464
|
allowlist,
|
|
14515
|
-
...bridge ? { bridge } : {},
|
|
14516
14465
|
moderator,
|
|
14517
14466
|
...pricing ? { pricing } : {},
|
|
14518
14467
|
...storage ? { storage } : {},
|
|
@@ -14524,7 +14473,7 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
|
|
|
14524
14473
|
})
|
|
14525
14474
|
};
|
|
14526
14475
|
}
|
|
14527
|
-
function auditTool(providers, allowlist,
|
|
14476
|
+
function auditTool(providers, allowlist, transcriptsDir, pricing, storage, breakers, repoRoot) {
|
|
14528
14477
|
return {
|
|
14529
14478
|
name: "audit",
|
|
14530
14479
|
description: "Score a piece of output against an audit rubric. Single-judge by default; coalesce-mode (multi-judge consensus) and panel-exhausted self-audit run natively. cheap_mode picks the cheapest 'med'-tier model as auditor when a pricing.json is wired. session_id-only inputs load the latest transcript automatically when a transcripts directory is wired.",
|
|
@@ -14550,7 +14499,6 @@ function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storag
|
|
|
14550
14499
|
handler: (args) => runAudit(args, {
|
|
14551
14500
|
providers,
|
|
14552
14501
|
allowlist,
|
|
14553
|
-
...bridge ? { bridge } : {},
|
|
14554
14502
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
14555
14503
|
...pricing ? { pricing } : {},
|
|
14556
14504
|
...storage ? { storage } : {},
|
|
@@ -14614,7 +14562,7 @@ function pickTool(providers, allowlist, storage, breakers, transcriptsDir, repoR
|
|
|
14614
14562
|
})
|
|
14615
14563
|
};
|
|
14616
14564
|
}
|
|
14617
|
-
function verifyTool(
|
|
14565
|
+
function verifyTool(fetchConfig) {
|
|
14618
14566
|
return {
|
|
14619
14567
|
name: "verify",
|
|
14620
14568
|
description: "Run a list of deterministic property checks against caller-supplied data. No LLM calls; everything is local. Returns per-check {passed, reason} plus all_passed / summary / timing fields. Supports the text kinds (contains, not_contains, regex_match, contains_any, contains_all, min_length), shell (sandboxed subprocess with timeout + Unix pgid isolation), and url_head (HEAD request gated by fetch.url_allowlist). All kinds run natively.",
|
|
@@ -14632,7 +14580,7 @@ function verifyTool(bridge, fetchConfig) {
|
|
|
14632
14580
|
},
|
|
14633
14581
|
required: ["checks"]
|
|
14634
14582
|
},
|
|
14635
|
-
handler: (args) => runVerify(args,
|
|
14583
|
+
handler: (args) => runVerify(args, fetchConfig)
|
|
14636
14584
|
};
|
|
14637
14585
|
}
|
|
14638
14586
|
function pingTool() {
|
|
@@ -14964,10 +14912,12 @@ function canonicalEventBody(e) {
|
|
|
14964
14912
|
e.status,
|
|
14965
14913
|
e.errorClass ?? ""
|
|
14966
14914
|
].join("|");
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
14970
|
-
|
|
14915
|
+
const hasV2 = e.runId !== void 0 || e.purpose !== void 0 || e.fingerprint !== void 0;
|
|
14916
|
+
const hasV3 = e.sessionId !== void 0;
|
|
14917
|
+
if (!hasV2 && !hasV3) return base;
|
|
14918
|
+
const parts = [base, e.runId ?? "", e.purpose ?? "", e.fingerprint ?? ""];
|
|
14919
|
+
if (hasV3) parts.push(e.sessionId ?? "");
|
|
14920
|
+
return parts.join("|");
|
|
14971
14921
|
}
|
|
14972
14922
|
function normalizePurpose(v) {
|
|
14973
14923
|
if (typeof v !== "string") return void 0;
|
|
@@ -15085,7 +15035,7 @@ function scheduleFlush() {
|
|
|
15085
15035
|
}, FLUSH_INTERVAL_MS);
|
|
15086
15036
|
if (typeof flushTimer.unref === "function") flushTimer.unref();
|
|
15087
15037
|
}
|
|
15088
|
-
function enqueue(cfg2, input, runId, fingerprint) {
|
|
15038
|
+
function enqueue(cfg2, input, runId, fingerprint, sessionId) {
|
|
15089
15039
|
const base = {
|
|
15090
15040
|
eventId: crypto4.randomUUID(),
|
|
15091
15041
|
seatId: cfg2.seatId,
|
|
@@ -15104,6 +15054,7 @@ function enqueue(cfg2, input, runId, fingerprint) {
|
|
|
15104
15054
|
// omitting keeps the JSON honest about what we actually know.
|
|
15105
15055
|
...input.errorClass === void 0 ? {} : { errorClass: input.errorClass },
|
|
15106
15056
|
runId,
|
|
15057
|
+
sessionId,
|
|
15107
15058
|
// Omit entirely (not "") when unknown, so the canonical body stays
|
|
15108
15059
|
// consistent with what the server reconstructs from the JSON.
|
|
15109
15060
|
...input.purpose === void 0 ? {} : { purpose: input.purpose },
|
|
@@ -15118,15 +15069,23 @@ function enqueue(cfg2, input, runId, fingerprint) {
|
|
|
15118
15069
|
if (queue.length >= FLUSH_BATCH_AT) void flush();
|
|
15119
15070
|
else scheduleFlush();
|
|
15120
15071
|
}
|
|
15072
|
+
function sessionIdFromEnvelope(out) {
|
|
15073
|
+
if (!out || typeof out !== "object") return null;
|
|
15074
|
+
const rs = out["run_summary"];
|
|
15075
|
+
if (!rs || typeof rs !== "object") return null;
|
|
15076
|
+
const v = rs["session_id"];
|
|
15077
|
+
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
15078
|
+
}
|
|
15121
15079
|
function recordUsage(out, toolName) {
|
|
15122
15080
|
try {
|
|
15123
15081
|
const cfg2 = getConfig2();
|
|
15124
15082
|
if (!cfg2) return;
|
|
15125
15083
|
if (toolName === "update_crosscheck") return;
|
|
15126
15084
|
const runId = crypto4.randomUUID();
|
|
15085
|
+
const sessionId = resolveSessionId(sessionIdFromEnvelope(out));
|
|
15127
15086
|
const fingerprint = currentFingerprint();
|
|
15128
15087
|
for (const ev of usageEventsFromEnvelope(out, toolName)) {
|
|
15129
|
-
enqueue(cfg2, ev, runId, fingerprint);
|
|
15088
|
+
enqueue(cfg2, ev, runId, fingerprint, sessionId);
|
|
15130
15089
|
}
|
|
15131
15090
|
} catch {
|
|
15132
15091
|
}
|
|
@@ -15233,7 +15192,7 @@ function createServer(opts = {}) {
|
|
|
15233
15192
|
throw new Error(`unknown tool: ${name}`);
|
|
15234
15193
|
}
|
|
15235
15194
|
const args = req.params.arguments ?? {};
|
|
15236
|
-
const
|
|
15195
|
+
const startedAt2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
15237
15196
|
const startedHr = process.hrtime.bigint();
|
|
15238
15197
|
const id = nextEventId();
|
|
15239
15198
|
syncSegment(opts.repoRoot);
|
|
@@ -15247,7 +15206,7 @@ function createServer(opts = {}) {
|
|
|
15247
15206
|
event: "tool_invoke",
|
|
15248
15207
|
id,
|
|
15249
15208
|
tool: name,
|
|
15250
|
-
started_at:
|
|
15209
|
+
started_at: startedAt2,
|
|
15251
15210
|
duration_ms: 0,
|
|
15252
15211
|
status: "ok",
|
|
15253
15212
|
args_keys: topLevelKeys(args),
|
|
@@ -15281,7 +15240,7 @@ function createServer(opts = {}) {
|
|
|
15281
15240
|
event: "tool_invoke",
|
|
15282
15241
|
id,
|
|
15283
15242
|
tool: name,
|
|
15284
|
-
started_at:
|
|
15243
|
+
started_at: startedAt2,
|
|
15285
15244
|
duration_ms: durationMs,
|
|
15286
15245
|
status: "ok",
|
|
15287
15246
|
args_keys: topLevelKeys(args),
|
|
@@ -15303,7 +15262,7 @@ function createServer(opts = {}) {
|
|
|
15303
15262
|
event: "tool_invoke",
|
|
15304
15263
|
id,
|
|
15305
15264
|
tool: name,
|
|
15306
|
-
started_at:
|
|
15265
|
+
started_at: startedAt2,
|
|
15307
15266
|
duration_ms: durationMs,
|
|
15308
15267
|
status: "error",
|
|
15309
15268
|
args_keys: topLevelKeys(args),
|
|
@@ -15334,7 +15293,6 @@ async function connectAndServe(transport, opts = {}) {
|
|
|
15334
15293
|
}
|
|
15335
15294
|
function buildToolRegistry(opts) {
|
|
15336
15295
|
const registerOpts = {};
|
|
15337
|
-
if (opts.bridge) registerOpts.bridge = opts.bridge;
|
|
15338
15296
|
if (opts.providers) registerOpts.providers = opts.providers;
|
|
15339
15297
|
if (opts.providerAllowlist !== void 0)
|
|
15340
15298
|
registerOpts.providerAllowlist = opts.providerAllowlist;
|
|
@@ -15351,13 +15309,7 @@ function buildToolRegistry(opts) {
|
|
|
15351
15309
|
if (opts.moderatorDefault) registerOpts.moderatorDefault = opts.moderatorDefault;
|
|
15352
15310
|
if (opts.benchGoldensDir) registerOpts.benchGoldensDir = opts.benchGoldensDir;
|
|
15353
15311
|
if (opts.eventsPath) registerOpts.eventsPath = opts.eventsPath;
|
|
15354
|
-
|
|
15355
|
-
if (!opts.bridge) return tools;
|
|
15356
|
-
const proxies = buildPythonProxies(opts.bridge);
|
|
15357
|
-
for (const [name, proxy] of proxies) {
|
|
15358
|
-
if (!tools.has(name)) tools.set(name, proxy);
|
|
15359
|
-
}
|
|
15360
|
-
return tools;
|
|
15312
|
+
return registerCoreTools(registerOpts);
|
|
15361
15313
|
}
|
|
15362
15314
|
|
|
15363
15315
|
// src/core/config-file.ts
|
|
@@ -15532,14 +15484,39 @@ function loadConfigFile(opts) {
|
|
|
15532
15484
|
return mapConfig(obj, file);
|
|
15533
15485
|
}
|
|
15534
15486
|
|
|
15487
|
+
// src/core/process-registry.ts
|
|
15488
|
+
init_esm_shims();
|
|
15489
|
+
import { mkdirSync as mkdirSync10, readdirSync as readdirSync5, readFileSync as readFileSync16, rmSync, writeFileSync as writeFileSync9 } from "fs";
|
|
15490
|
+
import os2 from "os";
|
|
15491
|
+
import path15 from "path";
|
|
15492
|
+
function registryDir(env = process.env) {
|
|
15493
|
+
const base = env["CROSSCHECK_DATA_DIR"] || path15.join(env["HOME"] ?? env["USERPROFILE"] ?? os2.homedir(), ".crosscheck");
|
|
15494
|
+
return path15.join(base, "procs");
|
|
15495
|
+
}
|
|
15496
|
+
function registerProcess(rec, env = process.env) {
|
|
15497
|
+
try {
|
|
15498
|
+
const dir = registryDir(env);
|
|
15499
|
+
mkdirSync10(dir, { recursive: true, mode: 448 });
|
|
15500
|
+
writeFileSync9(path15.join(dir, `${rec.pid}.json`), JSON.stringify(rec), { mode: 384 });
|
|
15501
|
+
} catch {
|
|
15502
|
+
}
|
|
15503
|
+
}
|
|
15504
|
+
function unregisterProcess(pid = process.pid, env = process.env) {
|
|
15505
|
+
try {
|
|
15506
|
+
rmSync(path15.join(registryDir(env), `${pid}.json`), { force: true });
|
|
15507
|
+
} catch {
|
|
15508
|
+
}
|
|
15509
|
+
}
|
|
15510
|
+
|
|
15535
15511
|
// src/entrypoints/node-stdio.ts
|
|
15512
|
+
var HERE = typeof __dirname !== "undefined" ? __dirname : path16.dirname(fileURLToPath3(import.meta.url));
|
|
15536
15513
|
var SHUTDOWN_TIMEOUT_MS = 2e3;
|
|
15537
15514
|
async function main() {
|
|
15538
15515
|
enforceLicenseOrExit();
|
|
15539
|
-
const cfgDataDir = process.env["CROSSCHECK_DATA_DIR"] ||
|
|
15516
|
+
const cfgDataDir = process.env["CROSSCHECK_DATA_DIR"] || path16.join(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".crosscheck");
|
|
15540
15517
|
const configFile = loadConfigFile({
|
|
15541
15518
|
startDir: process.cwd(),
|
|
15542
|
-
repoRoot: findGitRoot(
|
|
15519
|
+
repoRoot: findGitRoot(HERE),
|
|
15543
15520
|
dataDir: cfgDataDir
|
|
15544
15521
|
});
|
|
15545
15522
|
if (configFile) {
|
|
@@ -15553,15 +15530,17 @@ async function main() {
|
|
|
15553
15530
|
`);
|
|
15554
15531
|
}
|
|
15555
15532
|
setEventEmitter(buildDefaultEmitter(process.env));
|
|
15556
|
-
if (process.env["CROSSCHECK_BRIDGE_PYTHON"] === "1") {
|
|
15557
|
-
process.stderr.write(
|
|
15558
|
-
"crosscheck-agent: CROSSCHECK_BRIDGE_PYTHON is deprecated and ignored \u2014 the engine is native-only.\n"
|
|
15559
|
-
);
|
|
15560
|
-
}
|
|
15561
15533
|
installShutdownHandlers();
|
|
15534
|
+
registerProcess({
|
|
15535
|
+
pid: process.pid,
|
|
15536
|
+
version: SERVER_VERSION,
|
|
15537
|
+
startedAt: Date.now(),
|
|
15538
|
+
ppid: process.ppid,
|
|
15539
|
+
sessionId: engineSessionId()
|
|
15540
|
+
});
|
|
15562
15541
|
const bundledPricing = (() => {
|
|
15563
15542
|
try {
|
|
15564
|
-
return
|
|
15543
|
+
return path16.join(path16.dirname(fileURLToPath3(import.meta.url)), "pricing.json");
|
|
15565
15544
|
} catch {
|
|
15566
15545
|
return void 0;
|
|
15567
15546
|
}
|
|
@@ -15588,10 +15567,10 @@ async function main() {
|
|
|
15588
15567
|
}
|
|
15589
15568
|
let storage;
|
|
15590
15569
|
if (process.env["CROSSCHECK_DB_DISABLED"] !== "1") {
|
|
15591
|
-
const dbPath = process.env["CROSSCHECK_DB_PATH"] ?? resolveRepoFile(".crosscheck/db.sqlite") ??
|
|
15570
|
+
const dbPath = process.env["CROSSCHECK_DB_PATH"] ?? resolveRepoFile(".crosscheck/db.sqlite") ?? path16.join(cfgDataDir, "db.sqlite");
|
|
15592
15571
|
if (dbPath) {
|
|
15593
15572
|
try {
|
|
15594
|
-
|
|
15573
|
+
mkdirSync11(path16.dirname(dbPath), { recursive: true });
|
|
15595
15574
|
const { openBetterSqliteStorage: openBetterSqliteStorage2 } = await Promise.resolve().then(() => (init_better_sqlite3(), better_sqlite3_exports));
|
|
15596
15575
|
storage = openBetterSqliteStorage2({ path: dbPath });
|
|
15597
15576
|
await storage.migrate();
|
|
@@ -15609,7 +15588,7 @@ async function main() {
|
|
|
15609
15588
|
}
|
|
15610
15589
|
}
|
|
15611
15590
|
const transcriptsDir = configFile?.logTranscripts === false ? void 0 : process.env["CROSSCHECK_TRANSCRIPTS_DIR"] ?? configFile?.transcriptsDir ?? resolveRepoFile(".crosscheck/transcripts");
|
|
15612
|
-
const repoRoot = process.env["CROSSCHECK_REPO_ROOT"] ?? findGitRoot(
|
|
15591
|
+
const repoRoot = process.env["CROSSCHECK_REPO_ROOT"] ?? findGitRoot(HERE);
|
|
15613
15592
|
const transport = new StdioServerTransport();
|
|
15614
15593
|
const serverOpts = { providers };
|
|
15615
15594
|
if (storage) serverOpts.storage = storage;
|
|
@@ -15639,6 +15618,7 @@ function installShutdownHandlers() {
|
|
|
15639
15618
|
new Promise((resolve2) => setTimeout(resolve2, SHUTDOWN_TIMEOUT_MS))
|
|
15640
15619
|
]).catch(() => {
|
|
15641
15620
|
});
|
|
15621
|
+
unregisterProcess();
|
|
15642
15622
|
process.stderr.write(`crosscheck-agent: shutdown (${reason})
|
|
15643
15623
|
`);
|
|
15644
15624
|
process.exit(0);
|
|
@@ -15657,11 +15637,11 @@ function installShutdownHandlers() {
|
|
|
15657
15637
|
});
|
|
15658
15638
|
}
|
|
15659
15639
|
function resolveRepoFile(rel) {
|
|
15660
|
-
let dir =
|
|
15640
|
+
let dir = HERE;
|
|
15661
15641
|
for (let i = 0; i < 8; i++) {
|
|
15662
|
-
const candidate =
|
|
15642
|
+
const candidate = path16.join(dir, rel);
|
|
15663
15643
|
if (existsSync14(candidate)) return candidate;
|
|
15664
|
-
const parent =
|
|
15644
|
+
const parent = path16.dirname(dir);
|
|
15665
15645
|
if (parent === dir) break;
|
|
15666
15646
|
dir = parent;
|
|
15667
15647
|
}
|
|
@@ -15670,8 +15650,8 @@ function resolveRepoFile(rel) {
|
|
|
15670
15650
|
function findGitRoot(startDir) {
|
|
15671
15651
|
let dir = startDir;
|
|
15672
15652
|
for (let i = 0; i < 12; i++) {
|
|
15673
|
-
if (existsSync14(
|
|
15674
|
-
const parent =
|
|
15653
|
+
if (existsSync14(path16.join(dir, ".git"))) return dir;
|
|
15654
|
+
const parent = path16.dirname(dir);
|
|
15675
15655
|
if (parent === dir) break;
|
|
15676
15656
|
dir = parent;
|
|
15677
15657
|
}
|
|
@@ -15681,7 +15661,7 @@ var isMainEntry = (() => {
|
|
|
15681
15661
|
try {
|
|
15682
15662
|
const argv1 = process.argv[1];
|
|
15683
15663
|
if (!argv1) return false;
|
|
15684
|
-
return /(?:\/|\\)node-stdio\.(?:js|cjs|mjs)$/.test(argv1);
|
|
15664
|
+
return /(?:\/|\\)node-stdio\.(?:js|cjs|mjs|ts)$/.test(argv1);
|
|
15685
15665
|
} catch {
|
|
15686
15666
|
return false;
|
|
15687
15667
|
}
|