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/embed.cjs
CHANGED
|
@@ -31,13 +31,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/entrypoints/embed.ts
|
|
32
32
|
var embed_exports = {};
|
|
33
33
|
__export(embed_exports, {
|
|
34
|
+
ACTIVITY_TEXT_CAP: () => ACTIVITY_TEXT_CAP,
|
|
34
35
|
DEFAULT_EXCLUDED_PROVIDERS: () => DEFAULT_EXCLUDED_PROVIDERS,
|
|
35
36
|
DEFAULT_FALLBACKS: () => DEFAULT_FALLBACKS,
|
|
36
37
|
DEFAULT_MODELS: () => DEFAULT_MODELS,
|
|
37
38
|
__KEY_ENV: () => KEY_ENV,
|
|
38
39
|
__MODEL_ENV: () => MODEL_ENV,
|
|
39
40
|
__test_internals: () => __test_internals,
|
|
40
|
-
createEmbeddedEngine: () => createEmbeddedEngine
|
|
41
|
+
createEmbeddedEngine: () => createEmbeddedEngine,
|
|
42
|
+
isAlive: () => isAlive,
|
|
43
|
+
listProcesses: () => listProcesses,
|
|
44
|
+
processRegistryPath: () => processRegistryPath
|
|
41
45
|
});
|
|
42
46
|
module.exports = __toCommonJS(embed_exports);
|
|
43
47
|
|
|
@@ -46,16 +50,17 @@ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${_
|
|
|
46
50
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
47
51
|
|
|
48
52
|
// src/entrypoints/embed.ts
|
|
49
|
-
var
|
|
50
|
-
var
|
|
53
|
+
var import_node_async_hooks2 = require("async_hooks");
|
|
54
|
+
var import_node_fs16 = require("fs");
|
|
55
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
51
56
|
var import_node_url2 = require("url");
|
|
52
57
|
|
|
53
58
|
// src/core/pricing.ts
|
|
54
59
|
var import_node_fs = require("fs");
|
|
55
|
-
function loadPricing(
|
|
60
|
+
function loadPricing(path13) {
|
|
56
61
|
let raw;
|
|
57
62
|
try {
|
|
58
|
-
raw = (0, import_node_fs.readFileSync)(
|
|
63
|
+
raw = (0, import_node_fs.readFileSync)(path13, "utf8");
|
|
59
64
|
} catch {
|
|
60
65
|
return {};
|
|
61
66
|
}
|
|
@@ -72,20 +77,30 @@ function modelPricing(pricing, provider, model) {
|
|
|
72
77
|
const block = pricing[provider];
|
|
73
78
|
if (!block || typeof block !== "object" || Array.isArray(block)) return null;
|
|
74
79
|
const table = block;
|
|
80
|
+
if (model.startsWith("_")) return null;
|
|
75
81
|
let entry = table[model];
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
let match = "exact";
|
|
83
|
+
if (!isRates(entry)) {
|
|
84
|
+
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];
|
|
85
|
+
if (best !== void 0) {
|
|
86
|
+
entry = table[best];
|
|
87
|
+
match = "stamp";
|
|
88
|
+
}
|
|
79
89
|
}
|
|
80
|
-
if (!
|
|
90
|
+
if (!isRates(entry)) return null;
|
|
81
91
|
const e = entry;
|
|
82
92
|
return {
|
|
83
93
|
prompt_per_1k: numberOrZero(e["prompt_per_1k"]),
|
|
84
94
|
completion_per_1k: numberOrZero(e["completion_per_1k"]),
|
|
85
95
|
cached_per_1k: numberOrZero(e["cached_per_1k"]),
|
|
86
|
-
...e["estimated"] === true ? { estimated: true } : {}
|
|
96
|
+
...e["estimated"] === true ? { estimated: true } : {},
|
|
97
|
+
match
|
|
87
98
|
};
|
|
88
99
|
}
|
|
100
|
+
var DATE_STAMP = /^-\d{8}$/;
|
|
101
|
+
function isRates(v) {
|
|
102
|
+
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
103
|
+
}
|
|
89
104
|
function numberOrZero(v) {
|
|
90
105
|
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
91
106
|
if (typeof v === "string") {
|
|
@@ -165,8 +180,20 @@ var PROVIDER_CAPS = {
|
|
|
165
180
|
gemini: {
|
|
166
181
|
family: "gemini",
|
|
167
182
|
system_role: "separate",
|
|
168
|
-
|
|
169
|
-
|
|
183
|
+
// No sampling, on any Gemini model. Ignored since 3.6 Flash and rejected
|
|
184
|
+
// by upcoming models (Google, 2026-10). "model" means "omit for reasoning
|
|
185
|
+
// models", and every Gemini model is reasoning-class (below) — so this
|
|
186
|
+
// resolves to never, through the same rule the other providers use. The
|
|
187
|
+
// adapter also never sends it; this keeps the record honest for anything
|
|
188
|
+
// else that reads it.
|
|
189
|
+
supports_temperature: "model",
|
|
190
|
+
// EVERY Gemini model is reasoning-class. The old list named three
|
|
191
|
+
// families and missed gemini-3.8-flash — the DEFAULT — so the default
|
|
192
|
+
// model got the small non-reasoning budgets (768 tokens for an audit)
|
|
193
|
+
// while spending up to ~480 tokens of each call thinking. Google's docs
|
|
194
|
+
// say thinking cannot be switched off on current models, so a list of
|
|
195
|
+
// which ones think is a list that can only ever be incomplete.
|
|
196
|
+
reasoning_prefixes: ["gemini-"]
|
|
170
197
|
},
|
|
171
198
|
// Qwen's "Max" tier (qwen-v3.8, qwen-v3.7) is a standard instruct/chat
|
|
172
199
|
// model, not a visible-reasoning model like QwQ — normal temperature and
|
|
@@ -289,6 +316,73 @@ function httpFailureToProviderError(provider, status, bodyText, retryAfterS, mod
|
|
|
289
316
|
);
|
|
290
317
|
}
|
|
291
318
|
|
|
319
|
+
// src/providers/network-errors.ts
|
|
320
|
+
function codeOf(e) {
|
|
321
|
+
if (!e || typeof e !== "object") return null;
|
|
322
|
+
const c = e.code;
|
|
323
|
+
return typeof c === "string" && c.length > 0 ? c : null;
|
|
324
|
+
}
|
|
325
|
+
function rootCause(e, depth = 0) {
|
|
326
|
+
if (depth > 5 || !e || typeof e !== "object") return e;
|
|
327
|
+
const o = e;
|
|
328
|
+
if (Array.isArray(o.errors) && o.errors.length > 0) {
|
|
329
|
+
const coded = o.errors.find((x) => codeOf(x) !== null);
|
|
330
|
+
return rootCause(coded ?? o.errors[0], depth + 1);
|
|
331
|
+
}
|
|
332
|
+
if (o.cause !== void 0 && o.cause !== null) return rootCause(o.cause, depth + 1);
|
|
333
|
+
return e;
|
|
334
|
+
}
|
|
335
|
+
var BY_CODE = {
|
|
336
|
+
ENOTFOUND: { cause: "dns", detail: "the provider's hostname did not resolve \u2014 DNS, or a typo'd base URL", transient: false, kind: "network" },
|
|
337
|
+
EAI_AGAIN: { cause: "dns", detail: "DNS lookup failed temporarily \u2014 resolver or network is flapping", transient: true, kind: "network" },
|
|
338
|
+
ECONNREFUSED: { cause: "refused", detail: "the connection was refused \u2014 nothing is listening, or a proxy blocked it", transient: false, kind: "network" },
|
|
339
|
+
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" },
|
|
340
|
+
EPIPE: { cause: "reset", detail: "the connection closed while we were still writing", transient: true, kind: "network" },
|
|
341
|
+
ETIMEDOUT: { cause: "connect_timeout", detail: "the connection timed out before it was established", transient: true, kind: "timeout" },
|
|
342
|
+
EHOSTUNREACH: { cause: "unreachable", detail: "no route to the provider \u2014 VPN, or offline", transient: true, kind: "network" },
|
|
343
|
+
ENETUNREACH: { cause: "unreachable", detail: "the network is unreachable \u2014 offline, or a routing change", transient: true, kind: "network" },
|
|
344
|
+
ENETDOWN: { cause: "unreachable", detail: "the local network is down", transient: true, kind: "network" },
|
|
345
|
+
EPROTO: { cause: "tls", detail: "the TLS handshake failed \u2014 an intercepting proxy, or a protocol mismatch", transient: false, kind: "network" },
|
|
346
|
+
ERR_TLS_CERT_ALTNAME_INVALID: { cause: "tls", detail: "the certificate did not match the hostname \u2014 traffic is being intercepted", transient: false, kind: "network" },
|
|
347
|
+
CERT_HAS_EXPIRED: { cause: "tls", detail: "the server certificate has expired, or this machine's clock is wrong", transient: false, kind: "network" },
|
|
348
|
+
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" },
|
|
349
|
+
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" },
|
|
350
|
+
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" },
|
|
351
|
+
UND_ERR_BODY_TIMEOUT: { cause: "read_timeout", detail: "the response body stalled mid-stream", transient: true, kind: "timeout" },
|
|
352
|
+
UND_ERR_SOCKET: { cause: "reset", detail: "the socket closed unexpectedly", transient: true, kind: "network" },
|
|
353
|
+
UND_ERR_ABORTED: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" },
|
|
354
|
+
ABORT_ERR: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" }
|
|
355
|
+
};
|
|
356
|
+
function diagnoseNetworkError(e) {
|
|
357
|
+
const root = rootCause(e);
|
|
358
|
+
const code = codeOf(root) ?? codeOf(e);
|
|
359
|
+
if (code && BY_CODE[code]) return { ...BY_CODE[code], code };
|
|
360
|
+
const name = root && typeof root === "object" ? root.name : void 0;
|
|
361
|
+
if (name === "AbortError" || name === "TimeoutError") {
|
|
362
|
+
return {
|
|
363
|
+
cause: name === "TimeoutError" ? "read_timeout" : "aborted",
|
|
364
|
+
code: code ?? String(name),
|
|
365
|
+
detail: name === "TimeoutError" ? "the request exceeded its timeout" : "the request was cancelled",
|
|
366
|
+
transient: name === "TimeoutError",
|
|
367
|
+
kind: name === "TimeoutError" ? "timeout" : "network"
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
cause: "unknown",
|
|
372
|
+
code,
|
|
373
|
+
detail: code ? `the connection failed with ${code}` : "the connection failed and the underlying error carried no code",
|
|
374
|
+
transient: true,
|
|
375
|
+
kind: "network"
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function looksLikeNetworkFailure(d) {
|
|
379
|
+
return d.code !== null || d.cause !== "unknown";
|
|
380
|
+
}
|
|
381
|
+
function networkErrorMessage(provider, d) {
|
|
382
|
+
const code = d.code ? ` [${d.code}]` : "";
|
|
383
|
+
return `${provider}: ${d.detail}${code}`;
|
|
384
|
+
}
|
|
385
|
+
|
|
292
386
|
// src/providers/retry.ts
|
|
293
387
|
var override = null;
|
|
294
388
|
function resolveRetryConfig() {
|
|
@@ -441,6 +535,52 @@ function rejectsDisabledThinking(model) {
|
|
|
441
535
|
const m = model.toLowerCase();
|
|
442
536
|
return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
|
|
443
537
|
}
|
|
538
|
+
var NO_FORCED_TOOL_PREFIXES = [
|
|
539
|
+
"claude-fable-5-1",
|
|
540
|
+
"claude-mythos-5-1",
|
|
541
|
+
"claude-opus-5-5",
|
|
542
|
+
"claude-sonnet-5-5"
|
|
543
|
+
];
|
|
544
|
+
function rejectsForcedToolUse(model) {
|
|
545
|
+
const m = model.toLowerCase();
|
|
546
|
+
return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
|
|
547
|
+
}
|
|
548
|
+
var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
|
|
549
|
+
"minimum",
|
|
550
|
+
"maximum",
|
|
551
|
+
"exclusiveMinimum",
|
|
552
|
+
"exclusiveMaximum",
|
|
553
|
+
"multipleOf",
|
|
554
|
+
"minLength",
|
|
555
|
+
"maxLength",
|
|
556
|
+
"pattern",
|
|
557
|
+
"minItems",
|
|
558
|
+
"maxItems",
|
|
559
|
+
"uniqueItems",
|
|
560
|
+
"minProperties",
|
|
561
|
+
"maxProperties",
|
|
562
|
+
"$schema"
|
|
563
|
+
]);
|
|
564
|
+
function toStructuredOutputSchema(schema) {
|
|
565
|
+
const walk = (node) => {
|
|
566
|
+
if (Array.isArray(node)) return node.map(walk);
|
|
567
|
+
if (!node || typeof node !== "object") return node;
|
|
568
|
+
const out = {};
|
|
569
|
+
for (const [k, v] of Object.entries(node)) {
|
|
570
|
+
if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
|
|
571
|
+
if (k === "properties" && v && typeof v === "object") {
|
|
572
|
+
out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
|
|
573
|
+
} else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
|
|
574
|
+
out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
|
|
575
|
+
} else {
|
|
576
|
+
out[k] = v;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
|
|
580
|
+
return out;
|
|
581
|
+
};
|
|
582
|
+
return walk(schema);
|
|
583
|
+
}
|
|
444
584
|
var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
|
|
445
585
|
function applyPromptCaching(body, env = process.env) {
|
|
446
586
|
const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
|
|
@@ -492,7 +632,12 @@ function buildAnthropicRequest(opts) {
|
|
|
492
632
|
body.thinking = { type: "disabled" };
|
|
493
633
|
}
|
|
494
634
|
}
|
|
495
|
-
if (opts.jsonSchema) {
|
|
635
|
+
if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
|
|
636
|
+
body.output_config = {
|
|
637
|
+
...body.output_config ?? {},
|
|
638
|
+
format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
|
|
639
|
+
};
|
|
640
|
+
} else if (opts.jsonSchema) {
|
|
496
641
|
body.tools = [{
|
|
497
642
|
name: ANTHROPIC_STRUCTURED_TOOL_NAME,
|
|
498
643
|
description: "Emit a single JSON object matching the requested schema.",
|
|
@@ -611,7 +756,11 @@ async function sendAnthropic(args) {
|
|
|
611
756
|
try {
|
|
612
757
|
respLike = await doFetch(url, init);
|
|
613
758
|
} catch (e) {
|
|
614
|
-
|
|
759
|
+
const d = diagnoseNetworkError(e);
|
|
760
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
761
|
+
throw new ProviderError(d.kind, networkErrorMessage("anthropic", d), {
|
|
762
|
+
transient: d.transient
|
|
763
|
+
});
|
|
615
764
|
}
|
|
616
765
|
const status = respLike.status;
|
|
617
766
|
if (status >= 200 && status < 300) {
|
|
@@ -684,6 +833,11 @@ function jsonSchemaToGeminiSchema(schema) {
|
|
|
684
833
|
}
|
|
685
834
|
return out;
|
|
686
835
|
}
|
|
836
|
+
var GEMINI_THINKING_HEADROOM_TOKENS = 16384;
|
|
837
|
+
function thinkingHeadroom() {
|
|
838
|
+
const raw = Number(process.env["CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS"]);
|
|
839
|
+
return Number.isFinite(raw) && raw >= 0 ? Math.trunc(raw) : GEMINI_THINKING_HEADROOM_TOKENS;
|
|
840
|
+
}
|
|
687
841
|
function buildGeminiRequest(opts) {
|
|
688
842
|
const contents = [];
|
|
689
843
|
let systemText = null;
|
|
@@ -702,8 +856,9 @@ function buildGeminiRequest(opts) {
|
|
|
702
856
|
const body = {
|
|
703
857
|
contents,
|
|
704
858
|
generationConfig: {
|
|
705
|
-
|
|
706
|
-
|
|
859
|
+
// Answer budget + thinking headroom. No temperature / topP / topK /
|
|
860
|
+
// thinkingBudget, on any model — see the header note.
|
|
861
|
+
maxOutputTokens: opts.maxTokens + thinkingHeadroom()
|
|
707
862
|
}
|
|
708
863
|
};
|
|
709
864
|
if (systemText !== null && systemText !== "") {
|
|
@@ -713,8 +868,8 @@ function buildGeminiRequest(opts) {
|
|
|
713
868
|
body.generationConfig.responseMimeType = "application/json";
|
|
714
869
|
body.generationConfig.responseSchema = jsonSchemaToGeminiSchema(opts.jsonSchema);
|
|
715
870
|
}
|
|
716
|
-
const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent
|
|
717
|
-
return { url, headers: {}, body };
|
|
871
|
+
const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent`;
|
|
872
|
+
return { url, headers: { "x-goog-api-key": opts.apiKey }, body };
|
|
718
873
|
}
|
|
719
874
|
function parseGeminiResponse(opts) {
|
|
720
875
|
const r = opts.resp ?? {};
|
|
@@ -744,16 +899,19 @@ function parseGeminiResponse(opts) {
|
|
|
744
899
|
}
|
|
745
900
|
try {
|
|
746
901
|
const first = cands[0];
|
|
747
|
-
const
|
|
748
|
-
const
|
|
902
|
+
const finishReason = typeof first["finishReason"] === "string" ? first["finishReason"] : void 0;
|
|
903
|
+
const content = first["content"] ?? {};
|
|
904
|
+
const parts = Array.isArray(content["parts"]) ? content["parts"] : [];
|
|
749
905
|
let text = "";
|
|
750
906
|
for (const p of parts) {
|
|
751
907
|
if (p && typeof p === "object") {
|
|
752
|
-
const
|
|
908
|
+
const part = p;
|
|
909
|
+
if (part["thought"] === true) continue;
|
|
910
|
+
const t = part["text"];
|
|
753
911
|
if (typeof t === "string") text += t;
|
|
754
912
|
}
|
|
755
913
|
}
|
|
756
|
-
return { text, usage };
|
|
914
|
+
return { text, usage, ...finishReason ? { finishReason } : {} };
|
|
757
915
|
} catch (e) {
|
|
758
916
|
throw new ProviderError(
|
|
759
917
|
"parse",
|
|
@@ -782,7 +940,8 @@ async function sendGemini(args) {
|
|
|
782
940
|
apiKey: args.apiKey,
|
|
783
941
|
messages: args.messages,
|
|
784
942
|
maxTokens: args.maxTokens,
|
|
785
|
-
|
|
943
|
+
// args.temperature is deliberately NOT forwarded: Gemini ignores it and
|
|
944
|
+
// upcoming models reject it. See the header note.
|
|
786
945
|
...args.jsonSchema ? { jsonSchema: args.jsonSchema } : {}
|
|
787
946
|
});
|
|
788
947
|
const doFetch = args.fetchImpl ?? globalThis.fetch;
|
|
@@ -797,7 +956,11 @@ async function sendGemini(args) {
|
|
|
797
956
|
try {
|
|
798
957
|
respLike = await doFetch(url, init);
|
|
799
958
|
} catch (e) {
|
|
800
|
-
|
|
959
|
+
const d = diagnoseNetworkError(e);
|
|
960
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
961
|
+
throw new ProviderError(d.kind, networkErrorMessage("gemini", d), {
|
|
962
|
+
transient: d.transient
|
|
963
|
+
});
|
|
801
964
|
}
|
|
802
965
|
const status = respLike.status;
|
|
803
966
|
if (status >= 200 && status < 300) {
|
|
@@ -807,11 +970,18 @@ async function sendGemini(args) {
|
|
|
807
970
|
} catch (e) {
|
|
808
971
|
throw new ProviderError("parse", `gemini: response body not JSON: ${e.message}`);
|
|
809
972
|
}
|
|
810
|
-
const { text, usage } = parseGeminiResponse({
|
|
973
|
+
const { text, usage, finishReason } = parseGeminiResponse({
|
|
811
974
|
resp: parsed,
|
|
812
975
|
model: args.model,
|
|
813
976
|
purpose: args.purpose ?? "worker"
|
|
814
977
|
});
|
|
978
|
+
if (text.trim() === "" && finishReason === "MAX_TOKENS") {
|
|
979
|
+
throw new ProviderError(
|
|
980
|
+
"parse",
|
|
981
|
+
`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.`,
|
|
982
|
+
{ transient: false }
|
|
983
|
+
);
|
|
984
|
+
}
|
|
815
985
|
return { text, attempts: 1, usage: applyPricing2(usage, args.pricing) };
|
|
816
986
|
}
|
|
817
987
|
const bodyText = await respLike.text().catch(() => "");
|
|
@@ -868,7 +1038,15 @@ function buildOpenAICompatibleRequest(opts) {
|
|
|
868
1038
|
json_schema: {
|
|
869
1039
|
name: "structured_output",
|
|
870
1040
|
schema: opts.jsonSchema,
|
|
871
|
-
strict:
|
|
1041
|
+
// NOT strict. Strict mode requires `additionalProperties: false` on
|
|
1042
|
+
// every object and every property listed in `required` — the
|
|
1043
|
+
// engine's schemas don't meet that, so every structured OpenAI call
|
|
1044
|
+
// (planner, judges, synthesis) was a 400, unnoticed until the canary
|
|
1045
|
+
// grew a structured check (2026-10-11). Non-strict still shapes the
|
|
1046
|
+
// reply to the schema, and structured.ts validates it against the
|
|
1047
|
+
// full schema regardless, so strictness added a failure mode and no
|
|
1048
|
+
// safety.
|
|
1049
|
+
strict: false
|
|
872
1050
|
}
|
|
873
1051
|
};
|
|
874
1052
|
}
|
|
@@ -978,7 +1156,11 @@ async function sendOpenAICompatible(args) {
|
|
|
978
1156
|
try {
|
|
979
1157
|
respLike = await doFetch(url, init);
|
|
980
1158
|
} catch (e) {
|
|
981
|
-
|
|
1159
|
+
const d = diagnoseNetworkError(e);
|
|
1160
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
1161
|
+
throw new ProviderError(d.kind, networkErrorMessage(args.provider, d), {
|
|
1162
|
+
transient: d.transient
|
|
1163
|
+
});
|
|
982
1164
|
}
|
|
983
1165
|
const status = respLike.status;
|
|
984
1166
|
if (status >= 200 && status < 300) {
|
|
@@ -1152,7 +1334,7 @@ var import_zod = require("zod");
|
|
|
1152
1334
|
|
|
1153
1335
|
// src/server-meta.ts
|
|
1154
1336
|
var SERVER_NAME = "crosscheck-agent";
|
|
1155
|
-
var SERVER_VERSION = true ? "0.2.
|
|
1337
|
+
var SERVER_VERSION = true ? "0.2.29" : "0.0.0-dev";
|
|
1156
1338
|
|
|
1157
1339
|
// src/tools/audit.ts
|
|
1158
1340
|
var import_node_fs4 = require("fs");
|
|
@@ -1213,27 +1395,27 @@ function extractJson(text) {
|
|
|
1213
1395
|
}
|
|
1214
1396
|
|
|
1215
1397
|
// src/core/json-schema.ts
|
|
1216
|
-
function validateSchema(value, schema,
|
|
1398
|
+
function validateSchema(value, schema, path13 = "") {
|
|
1217
1399
|
const errs = [];
|
|
1218
1400
|
if ("anyOf" in schema) {
|
|
1219
1401
|
const subs = schema["anyOf"].map(
|
|
1220
|
-
(s) => validateSchema(value, s,
|
|
1402
|
+
(s) => validateSchema(value, s, path13)
|
|
1221
1403
|
);
|
|
1222
1404
|
if (!subs.some((e) => e.length === 0)) {
|
|
1223
|
-
errs.push(`${
|
|
1405
|
+
errs.push(`${path13 || "<root>"}: did not match anyOf`);
|
|
1224
1406
|
}
|
|
1225
1407
|
return errs;
|
|
1226
1408
|
}
|
|
1227
1409
|
if ("oneOf" in schema) {
|
|
1228
|
-
const passed = schema["oneOf"].filter((s) => validateSchema(value, s,
|
|
1410
|
+
const passed = schema["oneOf"].filter((s) => validateSchema(value, s, path13).length === 0).length;
|
|
1229
1411
|
if (passed !== 1) {
|
|
1230
|
-
errs.push(`${
|
|
1412
|
+
errs.push(`${path13 || "<root>"}: matched ${passed} of oneOf, expected 1`);
|
|
1231
1413
|
}
|
|
1232
1414
|
return errs;
|
|
1233
1415
|
}
|
|
1234
1416
|
if ("const" in schema && !deepEqual(value, schema["const"])) {
|
|
1235
1417
|
errs.push(
|
|
1236
|
-
`${
|
|
1418
|
+
`${path13 || "<root>"}: expected const ${pyRepr(schema["const"])}, got ${pyRepr(value)}`
|
|
1237
1419
|
);
|
|
1238
1420
|
return errs;
|
|
1239
1421
|
}
|
|
@@ -1243,7 +1425,7 @@ function validateSchema(value, schema, path12 = "") {
|
|
|
1243
1425
|
const ok = types.some((tt) => matchesType(value, String(tt)));
|
|
1244
1426
|
if (!ok) {
|
|
1245
1427
|
errs.push(
|
|
1246
|
-
`${
|
|
1428
|
+
`${path13 || "<root>"}: expected type ${pyReprType(t)}, got ${pyTypeName(value)}`
|
|
1247
1429
|
);
|
|
1248
1430
|
return errs;
|
|
1249
1431
|
}
|
|
@@ -1252,29 +1434,29 @@ function validateSchema(value, schema, path12 = "") {
|
|
|
1252
1434
|
if ("enum" in schema) {
|
|
1253
1435
|
const en = schema["enum"];
|
|
1254
1436
|
if (!en.some((x) => deepEqual(x, value))) {
|
|
1255
|
-
errs.push(`${
|
|
1437
|
+
errs.push(`${path13 || "<root>"}: value ${pyRepr(value)} not in enum`);
|
|
1256
1438
|
}
|
|
1257
1439
|
}
|
|
1258
1440
|
if ("minLength" in schema && value.length < schema["minLength"]) {
|
|
1259
|
-
errs.push(`${
|
|
1441
|
+
errs.push(`${path13 || "<root>"}: shorter than minLength ${schema["minLength"]}`);
|
|
1260
1442
|
}
|
|
1261
1443
|
}
|
|
1262
1444
|
if (typeof value === "number" && !Number.isNaN(value)) {
|
|
1263
1445
|
if ("minimum" in schema && value < schema["minimum"]) {
|
|
1264
|
-
errs.push(`${
|
|
1446
|
+
errs.push(`${path13 || "<root>"}: ${value} < minimum ${schema["minimum"]}`);
|
|
1265
1447
|
}
|
|
1266
1448
|
if ("maximum" in schema && value > schema["maximum"]) {
|
|
1267
|
-
errs.push(`${
|
|
1449
|
+
errs.push(`${path13 || "<root>"}: ${value} > maximum ${schema["maximum"]}`);
|
|
1268
1450
|
}
|
|
1269
1451
|
}
|
|
1270
1452
|
if (Array.isArray(value)) {
|
|
1271
1453
|
if ("minItems" in schema && value.length < schema["minItems"]) {
|
|
1272
|
-
errs.push(`${
|
|
1454
|
+
errs.push(`${path13 || "<root>"}: fewer items than minItems ${schema["minItems"]}`);
|
|
1273
1455
|
}
|
|
1274
1456
|
const itemSchema = schema["items"];
|
|
1275
1457
|
if (isObj(itemSchema)) {
|
|
1276
1458
|
for (let i = 0; i < value.length; i++) {
|
|
1277
|
-
errs.push(...validateSchema(value[i], itemSchema, `${
|
|
1459
|
+
errs.push(...validateSchema(value[i], itemSchema, `${path13}[${i}]`));
|
|
1278
1460
|
}
|
|
1279
1461
|
}
|
|
1280
1462
|
}
|
|
@@ -1283,19 +1465,19 @@ function validateSchema(value, schema, path12 = "") {
|
|
|
1283
1465
|
const required = schema["required"] ?? [];
|
|
1284
1466
|
for (const r of required) {
|
|
1285
1467
|
if (!(r in value)) {
|
|
1286
|
-
errs.push(`${
|
|
1468
|
+
errs.push(`${path13 || "<root>"}: missing required key ${pyRepr(r)}`);
|
|
1287
1469
|
}
|
|
1288
1470
|
}
|
|
1289
1471
|
if (schema["additionalProperties"] === false) {
|
|
1290
1472
|
for (const k of Object.keys(value)) {
|
|
1291
1473
|
if (!(k in props)) {
|
|
1292
|
-
errs.push(`${
|
|
1474
|
+
errs.push(`${path13 || "<root>"}: unknown key ${pyRepr(k)}`);
|
|
1293
1475
|
}
|
|
1294
1476
|
}
|
|
1295
1477
|
}
|
|
1296
1478
|
for (const [k, v] of Object.entries(value)) {
|
|
1297
1479
|
const ps = props[k];
|
|
1298
|
-
if (ps) errs.push(...validateSchema(v, ps,
|
|
1480
|
+
if (ps) errs.push(...validateSchema(v, ps, path13 ? `${path13}.${k}` : k));
|
|
1299
1481
|
}
|
|
1300
1482
|
}
|
|
1301
1483
|
return errs;
|
|
@@ -1375,6 +1557,31 @@ function pyReprType(t) {
|
|
|
1375
1557
|
return String(t);
|
|
1376
1558
|
}
|
|
1377
1559
|
|
|
1560
|
+
// src/core/session.ts
|
|
1561
|
+
var import_node_crypto = require("crypto");
|
|
1562
|
+
var processSessionId = null;
|
|
1563
|
+
var startedAt = null;
|
|
1564
|
+
function engineSessionId() {
|
|
1565
|
+
if (processSessionId === null) {
|
|
1566
|
+
processSessionId = (0, import_node_crypto.randomUUID)();
|
|
1567
|
+
startedAt = Date.now();
|
|
1568
|
+
}
|
|
1569
|
+
return processSessionId;
|
|
1570
|
+
}
|
|
1571
|
+
function resolveSessionId(callerSupplied) {
|
|
1572
|
+
const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
|
|
1573
|
+
return trimmed.length > 0 ? trimmed : engineSessionId();
|
|
1574
|
+
}
|
|
1575
|
+
function localSessionRecordingEnabled(env = globalThis.process?.env ?? {}) {
|
|
1576
|
+
const v = (env["CROSSCHECK_RECORD_SESSIONS"] ?? "").trim().toLowerCase();
|
|
1577
|
+
return !["0", "false", "off", "no"].includes(v);
|
|
1578
|
+
}
|
|
1579
|
+
function recordingSessionId(callerSupplied) {
|
|
1580
|
+
if (localSessionRecordingEnabled()) return resolveSessionId(callerSupplied);
|
|
1581
|
+
const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
|
|
1582
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1378
1585
|
// src/core/usage.ts
|
|
1379
1586
|
function emptyUsage(provider, model, purpose = "worker") {
|
|
1380
1587
|
return {
|
|
@@ -1480,11 +1687,11 @@ function withCommas(n) {
|
|
|
1480
1687
|
function renderRunSummary(opts) {
|
|
1481
1688
|
const endedAt = opts.endedAtS ?? Math.trunc(Date.now() / 1e3);
|
|
1482
1689
|
let scope = "call";
|
|
1483
|
-
let
|
|
1690
|
+
let startedAt2 = null;
|
|
1484
1691
|
let rows = [];
|
|
1485
1692
|
if (opts.sessionScope && opts.sessionScope.rows.length > 0) {
|
|
1486
1693
|
scope = "session";
|
|
1487
|
-
|
|
1694
|
+
startedAt2 = opts.sessionScope.startedAt;
|
|
1488
1695
|
rows = opts.sessionScope.rows.map((r) => ({ ...r }));
|
|
1489
1696
|
} else {
|
|
1490
1697
|
const byPurpose = /* @__PURE__ */ new Map();
|
|
@@ -1515,6 +1722,7 @@ function renderRunSummary(opts) {
|
|
|
1515
1722
|
row.cpu_ms += a.cpu_ms ?? 0;
|
|
1516
1723
|
if (a.cache_hit) row.cache_hits += 1;
|
|
1517
1724
|
if (a.error) row.errors += 1;
|
|
1725
|
+
if (a.usage?.estimated) row.estimated = true;
|
|
1518
1726
|
}
|
|
1519
1727
|
rows = Array.from(byPurpose.values());
|
|
1520
1728
|
}
|
|
@@ -1527,16 +1735,18 @@ function renderRunSummary(opts) {
|
|
|
1527
1735
|
wall_ms: rows.reduce((s, r) => s + r.wall_ms, 0),
|
|
1528
1736
|
cpu_ms: rows.reduce((s, r) => s + r.cpu_ms, 0),
|
|
1529
1737
|
cache_hits: rows.reduce((s, r) => s + r.cache_hits, 0),
|
|
1530
|
-
errors: rows.reduce((s, r) => s + r.errors, 0)
|
|
1738
|
+
errors: rows.reduce((s, r) => s + r.errors, 0),
|
|
1739
|
+
...rows.some((r) => r.estimated) ? { estimated: true } : {}
|
|
1531
1740
|
};
|
|
1532
1741
|
const titleLeft = scope === "session" ? `session: ${opts.sessionId ?? ""}` : `call: ${opts.toolName}`;
|
|
1533
|
-
const
|
|
1742
|
+
const costText = totals.estimated ? `$${totals.cost_usd.toFixed(4)}+ (some calls unpriced)` : `$${totals.cost_usd.toFixed(4)}`;
|
|
1743
|
+
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)`;
|
|
1534
1744
|
const bodyLines = [];
|
|
1535
1745
|
for (let i = 0; i < rows.length; i++) {
|
|
1536
1746
|
const r = rows[i];
|
|
1537
1747
|
const glyph = i === rows.length - 1 ? "`-" : "|-";
|
|
1538
1748
|
bodyLines.push(
|
|
1539
|
-
`${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)`
|
|
1749
|
+
`${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)`
|
|
1540
1750
|
);
|
|
1541
1751
|
}
|
|
1542
1752
|
const callByModel = rollupSpendByModel(
|
|
@@ -1584,7 +1794,7 @@ function renderRunSummary(opts) {
|
|
|
1584
1794
|
tool: opts.toolName,
|
|
1585
1795
|
scope,
|
|
1586
1796
|
currency: "USD",
|
|
1587
|
-
started_at:
|
|
1797
|
+
started_at: startedAt2,
|
|
1588
1798
|
ended_at: endedAt,
|
|
1589
1799
|
rows,
|
|
1590
1800
|
totals,
|
|
@@ -1709,14 +1919,15 @@ async function attachUsageBlock(result, answers, opts) {
|
|
|
1709
1919
|
delete result["_suppress_run_summary"];
|
|
1710
1920
|
}
|
|
1711
1921
|
async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
|
|
1712
|
-
|
|
1922
|
+
const sid = recordingSessionId(sessionId);
|
|
1923
|
+
if (!sid || answers.length === 0) return;
|
|
1713
1924
|
const now = nowS ?? Math.trunc(Date.now() / 1e3);
|
|
1714
1925
|
const rows = [];
|
|
1715
1926
|
for (const a of answers) {
|
|
1716
1927
|
const u = a.usage;
|
|
1717
1928
|
if (!u || typeof u.provider !== "string" || u.provider === "") continue;
|
|
1718
1929
|
rows.push({
|
|
1719
|
-
session_id:
|
|
1930
|
+
session_id: sid,
|
|
1720
1931
|
ts: now,
|
|
1721
1932
|
tool: toolName,
|
|
1722
1933
|
purpose: u.purpose ?? "worker",
|
|
@@ -1739,13 +1950,14 @@ async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
|
|
|
1739
1950
|
}
|
|
1740
1951
|
}
|
|
1741
1952
|
async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, nowS) {
|
|
1742
|
-
|
|
1953
|
+
const sid = recordingSessionId(sessionId);
|
|
1954
|
+
if (!sid) return;
|
|
1743
1955
|
const now = nowS ?? Math.trunc(Date.now() / 1e3);
|
|
1744
1956
|
try {
|
|
1745
|
-
let existing = await storage.getSession(
|
|
1957
|
+
let existing = await storage.getSession(sid);
|
|
1746
1958
|
if (!existing) {
|
|
1747
1959
|
await storage.upsertSession({
|
|
1748
|
-
session_id:
|
|
1960
|
+
session_id: sid,
|
|
1749
1961
|
started_at: now,
|
|
1750
1962
|
last_at: now,
|
|
1751
1963
|
calls: 0,
|
|
@@ -1758,7 +1970,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
|
|
|
1758
1970
|
total_cost_usd: 0,
|
|
1759
1971
|
total_cpu_ms: 0
|
|
1760
1972
|
});
|
|
1761
|
-
existing = await storage.getSession(
|
|
1973
|
+
existing = await storage.getSession(sid);
|
|
1762
1974
|
}
|
|
1763
1975
|
if (!existing) return;
|
|
1764
1976
|
let promptDelta = 0;
|
|
@@ -1778,7 +1990,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
|
|
|
1778
1990
|
}
|
|
1779
1991
|
if (a.cache_hit) cacheHitDelta += 1;
|
|
1780
1992
|
}
|
|
1781
|
-
await storage.accumulateSessionTotals(
|
|
1993
|
+
await storage.accumulateSessionTotals(sid, {
|
|
1782
1994
|
calls: answers.length,
|
|
1783
1995
|
wall_ms: wallMs,
|
|
1784
1996
|
cache_hits: cacheHitDelta,
|
|
@@ -2160,7 +2372,7 @@ function buildPersonaInjection(opts) {
|
|
|
2160
2372
|
}
|
|
2161
2373
|
|
|
2162
2374
|
// src/core/canary.ts
|
|
2163
|
-
var
|
|
2375
|
+
var import_node_crypto2 = require("crypto");
|
|
2164
2376
|
|
|
2165
2377
|
// src/core/injection.ts
|
|
2166
2378
|
var INJECTION_PHRASES_RE = new RegExp(
|
|
@@ -2178,8 +2390,8 @@ var UNTRUSTED_SYSTEM_NOTE = "Some inputs in this conversation are wrapped in <un
|
|
|
2178
2390
|
function mintCanary() {
|
|
2179
2391
|
const t = process.hrtime.bigint().toString();
|
|
2180
2392
|
const pid = String(process.pid);
|
|
2181
|
-
const r = (0,
|
|
2182
|
-
const hex = (0,
|
|
2393
|
+
const r = (0, import_node_crypto2.randomBytes)(16).toString("hex");
|
|
2394
|
+
const hex = (0, import_node_crypto2.createHash)("sha256").update(`${t}-${pid}-${r}`).digest("hex").slice(0, 16).toUpperCase();
|
|
2183
2395
|
return `CC_CANARY_${hex}`;
|
|
2184
2396
|
}
|
|
2185
2397
|
function wrapUntrusted(content, canary) {
|
|
@@ -2366,7 +2578,7 @@ var import_node_fs3 = require("fs");
|
|
|
2366
2578
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
2367
2579
|
|
|
2368
2580
|
// src/core/redact.ts
|
|
2369
|
-
var
|
|
2581
|
+
var import_node_crypto3 = require("crypto");
|
|
2370
2582
|
function builtinRedactionRules() {
|
|
2371
2583
|
return [
|
|
2372
2584
|
{ pattern: /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, label: "EMAIL", prefix_group: false },
|
|
@@ -2393,7 +2605,7 @@ function hmacSuffix(cfg, label, value) {
|
|
|
2393
2605
|
const sid = cfg.session_id ?? "";
|
|
2394
2606
|
const sidBytes = Buffer.from(sid, "utf8");
|
|
2395
2607
|
const key = Buffer.concat([Buffer.from(secret), sidBytes]);
|
|
2396
|
-
const digest = (0,
|
|
2608
|
+
const digest = (0, import_node_crypto3.createHmac)("sha256", key).update(`${label}:${value}`, "utf8").digest("hex");
|
|
2397
2609
|
return digest.slice(0, 8);
|
|
2398
2610
|
}
|
|
2399
2611
|
function redactText(s, cfg) {
|
|
@@ -4710,10 +4922,6 @@ If you need supporting evidence, you may emit ONE \`<tool_call>...</tool_call>\`
|
|
|
4710
4922
|
}
|
|
4711
4923
|
|
|
4712
4924
|
// src/tools/confer.ts
|
|
4713
|
-
var DEFERRED_OPTS = [
|
|
4714
|
-
// empty — every confer opt runs natively except worker_tools, which
|
|
4715
|
-
// is gated below (non-empty list → defer).
|
|
4716
|
-
];
|
|
4717
4925
|
async function runConfer(args, opts) {
|
|
4718
4926
|
const callStartedWall = import_node_perf_hooks2.performance.now();
|
|
4719
4927
|
const callStartedCpu = process.cpuUsage();
|
|
@@ -4729,16 +4937,11 @@ async function runConfer(args, opts) {
|
|
|
4729
4937
|
rejectedWorkerTools.push(t);
|
|
4730
4938
|
}
|
|
4731
4939
|
}
|
|
4732
|
-
|
|
4733
|
-
const needsBridge = DEFERRED_OPTS.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
4734
|
-
if (needsBridge) {
|
|
4735
|
-
if (opts.bridge && opts.bridge.toolNames.has("confer")) {
|
|
4736
|
-
return await deferConfer(args, opts.bridge);
|
|
4737
|
-
}
|
|
4940
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
4738
4941
|
return errorEnvelope2(
|
|
4739
4942
|
"CONFER_OPT_NOT_NATIVE",
|
|
4740
4943
|
"worker_tools requested but innerCallers are not wired",
|
|
4741
|
-
"Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host
|
|
4944
|
+
"Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host."
|
|
4742
4945
|
);
|
|
4743
4946
|
}
|
|
4744
4947
|
const question = typeof args["question"] === "string" ? args["question"] : String(args["question"] ?? "");
|
|
@@ -5089,21 +5292,6 @@ function unknownProviderError(unknownNames, available) {
|
|
|
5089
5292
|
available_now: Object.keys(available).sort()
|
|
5090
5293
|
};
|
|
5091
5294
|
}
|
|
5092
|
-
async function deferConfer(args, bridge) {
|
|
5093
|
-
const r = await bridge.callTool("confer", args);
|
|
5094
|
-
const text = r.content[0]?.text;
|
|
5095
|
-
if (typeof text === "string") {
|
|
5096
|
-
try {
|
|
5097
|
-
return JSON.parse(text);
|
|
5098
|
-
} catch {
|
|
5099
|
-
}
|
|
5100
|
-
}
|
|
5101
|
-
return errorEnvelope2(
|
|
5102
|
-
"CONFER_BRIDGE_BAD_ENVELOPE",
|
|
5103
|
-
"bridge returned an unparseable envelope for confer",
|
|
5104
|
-
"Check that the Python child is healthy."
|
|
5105
|
-
);
|
|
5106
|
-
}
|
|
5107
5295
|
function errorEnvelope2(code, message, hint) {
|
|
5108
5296
|
return {
|
|
5109
5297
|
tool: "confer",
|
|
@@ -5475,7 +5663,7 @@ function errorEnvelope3(code, message, hint) {
|
|
|
5475
5663
|
transient: false
|
|
5476
5664
|
};
|
|
5477
5665
|
}
|
|
5478
|
-
async function runVerify(args,
|
|
5666
|
+
async function runVerify(args, fetchConfig) {
|
|
5479
5667
|
const checks = args["checks"];
|
|
5480
5668
|
if (!Array.isArray(checks) || checks.length === 0) {
|
|
5481
5669
|
return {
|
|
@@ -5487,7 +5675,6 @@ async function runVerify(args, bridge, fetchConfig) {
|
|
|
5487
5675
|
)
|
|
5488
5676
|
};
|
|
5489
5677
|
}
|
|
5490
|
-
void bridge;
|
|
5491
5678
|
const allowShell = Boolean(args["allow_shell"] ?? false);
|
|
5492
5679
|
const wallStart = import_node_perf_hooks3.performance.now();
|
|
5493
5680
|
const cpuStart = process.cpuUsage();
|
|
@@ -5789,7 +5976,6 @@ async function runBench(args, opts) {
|
|
|
5789
5976
|
const innerOpts = {
|
|
5790
5977
|
providers: opts.providers,
|
|
5791
5978
|
allowlist: opts.allowlist ?? null,
|
|
5792
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
5793
5979
|
...opts.moderator ? { moderator: opts.moderator } : {}
|
|
5794
5980
|
};
|
|
5795
5981
|
let inner;
|
|
@@ -6001,7 +6187,7 @@ function isObj4(v) {
|
|
|
6001
6187
|
}
|
|
6002
6188
|
|
|
6003
6189
|
// src/tools/config-pin.ts
|
|
6004
|
-
var
|
|
6190
|
+
var import_node_crypto4 = require("crypto");
|
|
6005
6191
|
var import_node_fs6 = require("fs");
|
|
6006
6192
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
6007
6193
|
var DEFAULT_PIN_PATH = ".crosscheck/config_pins.json";
|
|
@@ -6156,7 +6342,7 @@ function hashFile(abs) {
|
|
|
6156
6342
|
return "";
|
|
6157
6343
|
}
|
|
6158
6344
|
const normalized = stripCrBeforeLf(raw);
|
|
6159
|
-
return "sha256:" + (0,
|
|
6345
|
+
return "sha256:" + (0, import_node_crypto4.createHash)("sha256").update(normalized).digest("hex");
|
|
6160
6346
|
}
|
|
6161
6347
|
function stripCrBeforeLf(buf) {
|
|
6162
6348
|
const out = [];
|
|
@@ -6233,7 +6419,7 @@ function pyRepr2(v) {
|
|
|
6233
6419
|
}
|
|
6234
6420
|
|
|
6235
6421
|
// src/tools/create.ts
|
|
6236
|
-
var
|
|
6422
|
+
var import_node_crypto7 = require("crypto");
|
|
6237
6423
|
var import_node_fs9 = require("fs");
|
|
6238
6424
|
var import_node_path9 = __toESM(require("path"), 1);
|
|
6239
6425
|
|
|
@@ -6244,6 +6430,19 @@ var import_node_perf_hooks6 = require("perf_hooks");
|
|
|
6244
6430
|
var import_node_async_hooks = require("async_hooks");
|
|
6245
6431
|
var import_node_perf_hooks5 = require("perf_hooks");
|
|
6246
6432
|
var progressStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
6433
|
+
async function withProgress(token, sendNotification, fn) {
|
|
6434
|
+
if (token === void 0 || token === null) {
|
|
6435
|
+
return fn();
|
|
6436
|
+
}
|
|
6437
|
+
const ctx = {
|
|
6438
|
+
token,
|
|
6439
|
+
wallStart: import_node_perf_hooks5.performance.now(),
|
|
6440
|
+
cpuStart: process.cpuUsage(),
|
|
6441
|
+
step: { value: 0 },
|
|
6442
|
+
sendNotification
|
|
6443
|
+
};
|
|
6444
|
+
return progressStorage.run(ctx, fn);
|
|
6445
|
+
}
|
|
6247
6446
|
async function emitProgress(message, opts) {
|
|
6248
6447
|
const ctx = progressStorage.getStore();
|
|
6249
6448
|
const wallStart = ctx ? ctx.wallStart : import_node_perf_hooks5.performance.now();
|
|
@@ -6319,7 +6518,7 @@ function isDeadModelError(err) {
|
|
|
6319
6518
|
}
|
|
6320
6519
|
|
|
6321
6520
|
// src/core/node-cache.ts
|
|
6322
|
-
var
|
|
6521
|
+
var import_node_crypto5 = require("crypto");
|
|
6323
6522
|
var import_node_fs7 = require("fs");
|
|
6324
6523
|
var import_node_path7 = require("path");
|
|
6325
6524
|
var NODE_CACHE_KEY_VERSION = "v2";
|
|
@@ -6346,7 +6545,7 @@ function canonicalizeNodeText(s) {
|
|
|
6346
6545
|
return out;
|
|
6347
6546
|
}
|
|
6348
6547
|
function sha256Hex(s) {
|
|
6349
|
-
return (0,
|
|
6548
|
+
return (0, import_node_crypto5.createHash)("sha256").update(s, "utf8").digest("hex");
|
|
6350
6549
|
}
|
|
6351
6550
|
function nodeCacheKey(node, upstreamOutputs, provider, model) {
|
|
6352
6551
|
const canonUpstream = {};
|
|
@@ -6404,11 +6603,11 @@ function getNodeCache(cfg, repoRoot, key, nowMs) {
|
|
|
6404
6603
|
return null;
|
|
6405
6604
|
}
|
|
6406
6605
|
}
|
|
6407
|
-
function atomicWriteJson(
|
|
6408
|
-
(0, import_node_fs7.mkdirSync)((0, import_node_path7.dirname)(
|
|
6409
|
-
const tmp = `${
|
|
6606
|
+
function atomicWriteJson(path13, payload) {
|
|
6607
|
+
(0, import_node_fs7.mkdirSync)((0, import_node_path7.dirname)(path13), { recursive: true });
|
|
6608
|
+
const tmp = `${path13}.${process.pid}.${Date.now()}.tmp`;
|
|
6410
6609
|
(0, import_node_fs7.writeFileSync)(tmp, JSON.stringify(payload), "utf8");
|
|
6411
|
-
(0, import_node_fs7.renameSync)(tmp,
|
|
6610
|
+
(0, import_node_fs7.renameSync)(tmp, path13);
|
|
6412
6611
|
}
|
|
6413
6612
|
function putNodeCache(cfg, repoRoot, key, value) {
|
|
6414
6613
|
if (!cfg || cfg.enabled === false) return;
|
|
@@ -6466,7 +6665,6 @@ var EST_TOKENS = {
|
|
|
6466
6665
|
med: [1500, 800],
|
|
6467
6666
|
high: [2500, 1500]
|
|
6468
6667
|
};
|
|
6469
|
-
var DEFERRED_OPTS2 = [];
|
|
6470
6668
|
var REACTIVE_SIGNAL_RE = /<signals>\s*(\{[\s\S]*?\})\s*<\/signals>/g;
|
|
6471
6669
|
function parseReactiveSignals(output) {
|
|
6472
6670
|
if (typeof output !== "string" || !output.includes("<signals>")) return [];
|
|
@@ -6506,17 +6704,6 @@ async function runOrchestrate(args, opts) {
|
|
|
6506
6704
|
);
|
|
6507
6705
|
if (breakerEnv) return breakerEnv;
|
|
6508
6706
|
}
|
|
6509
|
-
const needsBridge = DEFERRED_OPTS2.some((k) => Boolean(args[k]));
|
|
6510
|
-
if (needsBridge) {
|
|
6511
|
-
if (opts.bridge && opts.bridge.toolNames.has("orchestrate")) {
|
|
6512
|
-
return await deferOrchestrate(args, opts.bridge);
|
|
6513
|
-
}
|
|
6514
|
-
return errorEnvelope5(
|
|
6515
|
-
"ORCHESTRATE_OPT_NOT_NATIVE",
|
|
6516
|
-
"this orchestrate opt-in requires the Python bridge in v1",
|
|
6517
|
-
"v1 native covers the plain DAG flow + cheap_mode. reactive (mid-flight DAG updates) still defers. Set CROSSCHECK_BRIDGE_PYTHON=1 to enable."
|
|
6518
|
-
);
|
|
6519
|
-
}
|
|
6520
6707
|
const goal = typeof args["goal"] === "string" ? args["goal"] : null;
|
|
6521
6708
|
const dagIn = isObj5(args["dag"]) ? args["dag"] : null;
|
|
6522
6709
|
if (goal === null === (dagIn === null)) {
|
|
@@ -7458,21 +7645,6 @@ function resolveProviders3(names, available, allowlist) {
|
|
|
7458
7645
|
}
|
|
7459
7646
|
return out;
|
|
7460
7647
|
}
|
|
7461
|
-
async function deferOrchestrate(args, bridge) {
|
|
7462
|
-
const r = await bridge.callTool("orchestrate", args);
|
|
7463
|
-
const text = r.content[0]?.text;
|
|
7464
|
-
if (typeof text === "string") {
|
|
7465
|
-
try {
|
|
7466
|
-
return JSON.parse(text);
|
|
7467
|
-
} catch {
|
|
7468
|
-
}
|
|
7469
|
-
}
|
|
7470
|
-
return errorEnvelope5(
|
|
7471
|
-
"ORCHESTRATE_BRIDGE_BAD_ENVELOPE",
|
|
7472
|
-
"bridge returned an unparseable envelope for orchestrate",
|
|
7473
|
-
"Check that the Python child is healthy."
|
|
7474
|
-
);
|
|
7475
|
-
}
|
|
7476
7648
|
function errorEnvelope5(code, message, hint, kind = "client") {
|
|
7477
7649
|
return {
|
|
7478
7650
|
tool: "orchestrate",
|
|
@@ -7520,7 +7692,7 @@ function pyRound6(x) {
|
|
|
7520
7692
|
}
|
|
7521
7693
|
|
|
7522
7694
|
// src/tools/fetch.ts
|
|
7523
|
-
var
|
|
7695
|
+
var import_node_crypto6 = require("crypto");
|
|
7524
7696
|
var import_node_fs8 = require("fs");
|
|
7525
7697
|
var import_node_path8 = __toESM(require("path"), 1);
|
|
7526
7698
|
var DEFAULT_CONFIG = {
|
|
@@ -7734,10 +7906,10 @@ function extractHost(url) {
|
|
|
7734
7906
|
}
|
|
7735
7907
|
}
|
|
7736
7908
|
function sha256Hex2(s) {
|
|
7737
|
-
return (0,
|
|
7909
|
+
return (0, import_node_crypto6.createHash)("sha256").update(s, "utf8").digest("hex");
|
|
7738
7910
|
}
|
|
7739
7911
|
function sha256HexBytes(bytes) {
|
|
7740
|
-
return (0,
|
|
7912
|
+
return (0, import_node_crypto6.createHash)("sha256").update(bytes).digest("hex");
|
|
7741
7913
|
}
|
|
7742
7914
|
function resolveEvidenceDir(configured, repoRoot) {
|
|
7743
7915
|
if (import_node_path8.default.isAbsolute(configured)) return configured;
|
|
@@ -7790,6 +7962,16 @@ function buildCallContext(args) {
|
|
|
7790
7962
|
var CREATE_DOC_MAX_BYTES = 32 * 1024;
|
|
7791
7963
|
var CREATE_AUDIT_THRESHOLD = 0.7;
|
|
7792
7964
|
async function runCreate(args, opts) {
|
|
7965
|
+
const subEnvelopes = [];
|
|
7966
|
+
const tracked = (fn) => async (...a) => {
|
|
7967
|
+
const out = await fn(...a);
|
|
7968
|
+
subEnvelopes.push(out);
|
|
7969
|
+
return out;
|
|
7970
|
+
};
|
|
7971
|
+
const confer = tracked(runConfer);
|
|
7972
|
+
const orchestrate = tracked(runOrchestrate);
|
|
7973
|
+
const review = tracked(runReview);
|
|
7974
|
+
const audit = tracked(runAudit);
|
|
7793
7975
|
const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
|
|
7794
7976
|
if (!instruction) {
|
|
7795
7977
|
return errorEnvelope6(
|
|
@@ -7826,7 +8008,7 @@ ${constraints}
|
|
|
7826
8008
|
|
|
7827
8009
|
` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
|
|
7828
8010
|
${documentsPayload}`;
|
|
7829
|
-
const scope = await
|
|
8011
|
+
const scope = await confer({
|
|
7830
8012
|
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,
|
|
7831
8013
|
context: contextBlock,
|
|
7832
8014
|
...providers !== void 0 ? { providers } : {},
|
|
@@ -7835,7 +8017,6 @@ ${documentsPayload}`;
|
|
|
7835
8017
|
}, {
|
|
7836
8018
|
providers: opts.providers,
|
|
7837
8019
|
allowlist: opts.allowlist ?? null,
|
|
7838
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7839
8020
|
ctx
|
|
7840
8021
|
});
|
|
7841
8022
|
const scopeAnswer = Array.isArray(scope["answers"]) ? scope["answers"].filter((a) => typeof a["response"] === "string" && a["response"]).map((a) => `[${a["provider"]}]
|
|
@@ -7854,11 +8035,10 @@ ${scopeAnswer || "(none)"}
|
|
|
7854
8035
|
};
|
|
7855
8036
|
if (providers !== void 0) orchestrateArgs["providers"] = providers;
|
|
7856
8037
|
if (planOnly) orchestrateArgs["plan_only"] = true;
|
|
7857
|
-
let orchestration = await
|
|
8038
|
+
let orchestration = await orchestrate(orchestrateArgs, {
|
|
7858
8039
|
providers: opts.providers,
|
|
7859
8040
|
allowlist: opts.allowlist ?? null,
|
|
7860
8041
|
moderator,
|
|
7861
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7862
8042
|
ctx
|
|
7863
8043
|
});
|
|
7864
8044
|
let attempts = 1;
|
|
@@ -7884,7 +8064,7 @@ ${scopeAnswer || "(none)"}
|
|
|
7884
8064
|
}
|
|
7885
8065
|
let reviewEnvelope = null;
|
|
7886
8066
|
if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
|
|
7887
|
-
reviewEnvelope = await
|
|
8067
|
+
reviewEnvelope = await review({
|
|
7888
8068
|
snippet: orchestration["final"],
|
|
7889
8069
|
intent: `final deliverable for: ${instruction}`,
|
|
7890
8070
|
...providers !== void 0 ? { providers } : {},
|
|
@@ -7893,7 +8073,6 @@ ${scopeAnswer || "(none)"}
|
|
|
7893
8073
|
}, {
|
|
7894
8074
|
providers: opts.providers,
|
|
7895
8075
|
allowlist: opts.allowlist ?? null,
|
|
7896
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7897
8076
|
ctx
|
|
7898
8077
|
});
|
|
7899
8078
|
}
|
|
@@ -7905,7 +8084,7 @@ ${scopeAnswer || "(none)"}
|
|
|
7905
8084
|
const panelExhausted = producingPanel.length > 0 && producingPanel.every(
|
|
7906
8085
|
(p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
|
|
7907
8086
|
) && producingPanel.length >= Object.keys(opts.providers).length;
|
|
7908
|
-
auditEnvelope = await
|
|
8087
|
+
auditEnvelope = await audit({
|
|
7909
8088
|
output_to_audit: orchestration["final"],
|
|
7910
8089
|
producing_panelists: producingPanel,
|
|
7911
8090
|
...auditRubric !== void 0 ? { rubric: auditRubric } : {},
|
|
@@ -7916,7 +8095,6 @@ ${scopeAnswer || "(none)"}
|
|
|
7916
8095
|
}, {
|
|
7917
8096
|
providers: opts.providers,
|
|
7918
8097
|
allowlist: opts.allowlist ?? null,
|
|
7919
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7920
8098
|
ctx
|
|
7921
8099
|
});
|
|
7922
8100
|
let overallF = toNumberOrNull(auditEnvelope["overall_score"]);
|
|
@@ -7935,13 +8113,12 @@ ${retryConstraints}
|
|
|
7935
8113
|
DOCUMENTS:
|
|
7936
8114
|
${documentsPayload}`
|
|
7937
8115
|
};
|
|
7938
|
-
const retryOrchestration = await
|
|
8116
|
+
const retryOrchestration = await orchestrate(
|
|
7939
8117
|
retryOrchestrateArgs,
|
|
7940
8118
|
{
|
|
7941
8119
|
providers: opts.providers,
|
|
7942
8120
|
allowlist: opts.allowlist ?? null,
|
|
7943
8121
|
moderator,
|
|
7944
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7945
8122
|
ctx
|
|
7946
8123
|
}
|
|
7947
8124
|
);
|
|
@@ -7950,7 +8127,7 @@ ${documentsPayload}`
|
|
|
7950
8127
|
if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
|
|
7951
8128
|
const retryPanel = computeProducingPanel(retryOrchestration);
|
|
7952
8129
|
const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
|
|
7953
|
-
auditEnvelope = await
|
|
8130
|
+
auditEnvelope = await audit({
|
|
7954
8131
|
output_to_audit: retryOrchestration["final"],
|
|
7955
8132
|
producing_panelists: retryPanel,
|
|
7956
8133
|
...auditRubric !== void 0 ? { rubric: auditRubric } : {},
|
|
@@ -7961,7 +8138,6 @@ ${documentsPayload}`
|
|
|
7961
8138
|
}, {
|
|
7962
8139
|
providers: opts.providers,
|
|
7963
8140
|
allowlist: opts.allowlist ?? null,
|
|
7964
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7965
8141
|
ctx
|
|
7966
8142
|
});
|
|
7967
8143
|
overallF = toNumberOrNull(auditEnvelope["overall_score"]);
|
|
@@ -8026,9 +8202,28 @@ ${documentsPayload}`
|
|
|
8026
8202
|
["auditor", "items", "overall_score", "passed", "rubric"]
|
|
8027
8203
|
),
|
|
8028
8204
|
artifacts,
|
|
8029
|
-
warnings
|
|
8205
|
+
warnings,
|
|
8206
|
+
...combinedUsage(subEnvelopes)
|
|
8030
8207
|
};
|
|
8031
8208
|
}
|
|
8209
|
+
function combinedUsage(envelopes) {
|
|
8210
|
+
const usages = [];
|
|
8211
|
+
const byCallTiming = [];
|
|
8212
|
+
let wall = 0, cpu = 0;
|
|
8213
|
+
for (const env of envelopes) {
|
|
8214
|
+
const e = env ?? {};
|
|
8215
|
+
const calls = e["usage"]?.["by_call"] ?? [];
|
|
8216
|
+
const t = e["timing"] ?? {};
|
|
8217
|
+
const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
|
|
8218
|
+
if (!Array.isArray(calls) || calls.length === 0) continue;
|
|
8219
|
+
usages.push(...calls);
|
|
8220
|
+
if (timing.length === calls.length) byCallTiming.push(...timing);
|
|
8221
|
+
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 });
|
|
8222
|
+
wall += Number(t["wall_ms"] ?? 0) || 0;
|
|
8223
|
+
cpu += Number(t["cpu_ms"] ?? 0) || 0;
|
|
8224
|
+
}
|
|
8225
|
+
return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
|
|
8226
|
+
}
|
|
8032
8227
|
async function ingestDocuments(documents, sessionId, opts) {
|
|
8033
8228
|
if (documents.length === 0) return [];
|
|
8034
8229
|
const out = [];
|
|
@@ -8098,7 +8293,7 @@ async function ingestDocuments(documents, sessionId, opts) {
|
|
|
8098
8293
|
source: ref,
|
|
8099
8294
|
type: "file",
|
|
8100
8295
|
status: "ok",
|
|
8101
|
-
hash: (0,
|
|
8296
|
+
hash: (0, import_node_crypto7.createHash)("sha256").update(text, "utf8").digest("hex"),
|
|
8102
8297
|
content: ""
|
|
8103
8298
|
}, text));
|
|
8104
8299
|
}
|
|
@@ -8135,7 +8330,7 @@ ${d.content}
|
|
|
8135
8330
|
function makeSessionId(opts, supplied) {
|
|
8136
8331
|
if (typeof supplied === "string" && supplied) return supplied;
|
|
8137
8332
|
const stamp = opts.nowEpochSeconds ? opts.nowEpochSeconds() : Math.floor(Date.now() / 1e3);
|
|
8138
|
-
const rnd = opts.randomBytes ? opts.randomBytes() : (0,
|
|
8333
|
+
const rnd = opts.randomBytes ? opts.randomBytes() : (0, import_node_crypto7.createHash)("sha256").update(`${stamp}-${process.pid}-${Math.random()}`).digest("hex");
|
|
8139
8334
|
const suffix = rnd.slice(0, 8);
|
|
8140
8335
|
return `${opts.toolName}-${stamp}-${suffix}`;
|
|
8141
8336
|
}
|
|
@@ -8199,11 +8394,6 @@ function errorEnvelope6(toolName, code, message, hint) {
|
|
|
8199
8394
|
|
|
8200
8395
|
// src/tools/coordinate.ts
|
|
8201
8396
|
var import_node_perf_hooks7 = require("perf_hooks");
|
|
8202
|
-
var DEFERRED_OPTS3 = [
|
|
8203
|
-
// empty — every coordinate opt runs natively when its deps
|
|
8204
|
-
// (storage / innerCallers) are wired. Without them the
|
|
8205
|
-
// worker_tools gate still triggers a bridge defer.
|
|
8206
|
-
];
|
|
8207
8397
|
var COORDINATE_DEFAULT_TEMP = 0.4;
|
|
8208
8398
|
var ROLE_TURN_SCHEMA = {
|
|
8209
8399
|
type: "object",
|
|
@@ -8258,23 +8448,18 @@ async function runCoordinate(args, opts) {
|
|
|
8258
8448
|
rejectedWorkerTools.push(t);
|
|
8259
8449
|
}
|
|
8260
8450
|
}
|
|
8261
|
-
|
|
8262
|
-
const needsBridge = DEFERRED_OPTS3.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
8263
|
-
if (needsBridge) {
|
|
8451
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
8264
8452
|
if (superRequested) {
|
|
8265
8453
|
return errorEnvelope7(
|
|
8266
8454
|
"COORDINATE_SUPER_NOT_NATIVE",
|
|
8267
|
-
"super mode requested
|
|
8268
|
-
"worker_tools
|
|
8455
|
+
"super mode requested with worker_tools, but innerCallers are not wired",
|
|
8456
|
+
"worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
|
|
8269
8457
|
);
|
|
8270
8458
|
}
|
|
8271
|
-
if (opts.bridge && opts.bridge.toolNames.has("coordinate")) {
|
|
8272
|
-
return await deferCoordinate(args, opts.bridge);
|
|
8273
|
-
}
|
|
8274
8459
|
return errorEnvelope7(
|
|
8275
8460
|
"COORDINATE_OPT_NOT_NATIVE",
|
|
8276
8461
|
"worker_tools requested but innerCallers are not wired",
|
|
8277
|
-
"Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host
|
|
8462
|
+
"Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host."
|
|
8278
8463
|
);
|
|
8279
8464
|
}
|
|
8280
8465
|
const untrusted = Boolean(args["untrusted_input"]);
|
|
@@ -8674,21 +8859,6 @@ function unknownProviderError3(unknownNames, available) {
|
|
|
8674
8859
|
available_now: Object.keys(available).sort()
|
|
8675
8860
|
};
|
|
8676
8861
|
}
|
|
8677
|
-
async function deferCoordinate(args, bridge) {
|
|
8678
|
-
const r = await bridge.callTool("coordinate", args);
|
|
8679
|
-
const text = r.content[0]?.text;
|
|
8680
|
-
if (typeof text === "string") {
|
|
8681
|
-
try {
|
|
8682
|
-
return JSON.parse(text);
|
|
8683
|
-
} catch {
|
|
8684
|
-
}
|
|
8685
|
-
}
|
|
8686
|
-
return errorEnvelope7(
|
|
8687
|
-
"COORDINATE_BRIDGE_BAD_ENVELOPE",
|
|
8688
|
-
"bridge returned an unparseable envelope for coordinate",
|
|
8689
|
-
"Check that the Python child is healthy."
|
|
8690
|
-
);
|
|
8691
|
-
}
|
|
8692
8862
|
function errorEnvelope7(code, message, hint) {
|
|
8693
8863
|
return {
|
|
8694
8864
|
tool: "coordinate",
|
|
@@ -9016,10 +9186,6 @@ function buildModeratorTranscript(transcript) {
|
|
|
9016
9186
|
|
|
9017
9187
|
// src/tools/debate.ts
|
|
9018
9188
|
var import_node_perf_hooks9 = require("perf_hooks");
|
|
9019
|
-
var DEFERRED_OPTS4 = [
|
|
9020
|
-
// empty — every debate opt runs natively when its deps
|
|
9021
|
-
// (storage / innerCallers) are wired.
|
|
9022
|
-
];
|
|
9023
9189
|
async function runDebate(args, opts) {
|
|
9024
9190
|
const callStartedWall = import_node_perf_hooks9.performance.now();
|
|
9025
9191
|
const callStartedCpu = process.cpuUsage();
|
|
@@ -9037,23 +9203,18 @@ async function runDebate(args, opts) {
|
|
|
9037
9203
|
rejectedWorkerTools.push(t);
|
|
9038
9204
|
}
|
|
9039
9205
|
}
|
|
9040
|
-
|
|
9041
|
-
const needsBridge = DEFERRED_OPTS4.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
9042
|
-
if (needsBridge) {
|
|
9206
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
9043
9207
|
if (superRequested) {
|
|
9044
9208
|
return errorEnvelope9(
|
|
9045
9209
|
"DEBATE_SUPER_NOT_NATIVE",
|
|
9046
|
-
"super mode requested
|
|
9047
|
-
"worker_tools
|
|
9210
|
+
"super mode requested with worker_tools, but innerCallers are not wired",
|
|
9211
|
+
"worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
|
|
9048
9212
|
);
|
|
9049
9213
|
}
|
|
9050
|
-
if (opts.bridge && opts.bridge.toolNames.has("debate")) {
|
|
9051
|
-
return await deferDebate(args, opts.bridge);
|
|
9052
|
-
}
|
|
9053
9214
|
return errorEnvelope9(
|
|
9054
9215
|
"DEBATE_OPT_NOT_NATIVE",
|
|
9055
9216
|
"worker_tools requested but innerCallers are not wired",
|
|
9056
|
-
"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
|
|
9217
|
+
"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."
|
|
9057
9218
|
);
|
|
9058
9219
|
}
|
|
9059
9220
|
const topic = typeof args["topic"] === "string" ? args["topic"] : String(args["topic"] ?? "");
|
|
@@ -9490,21 +9651,6 @@ function unknownProviderError5(unknownNames, available) {
|
|
|
9490
9651
|
available_now: Object.keys(available).sort()
|
|
9491
9652
|
};
|
|
9492
9653
|
}
|
|
9493
|
-
async function deferDebate(args, bridge) {
|
|
9494
|
-
const r = await bridge.callTool("debate", args);
|
|
9495
|
-
const text = r.content[0]?.text;
|
|
9496
|
-
if (typeof text === "string") {
|
|
9497
|
-
try {
|
|
9498
|
-
return JSON.parse(text);
|
|
9499
|
-
} catch {
|
|
9500
|
-
}
|
|
9501
|
-
}
|
|
9502
|
-
return errorEnvelope9(
|
|
9503
|
-
"DEBATE_BRIDGE_BAD_ENVELOPE",
|
|
9504
|
-
"bridge returned an unparseable envelope for debate",
|
|
9505
|
-
"Check that the Python child is healthy."
|
|
9506
|
-
);
|
|
9507
|
-
}
|
|
9508
9654
|
function errorEnvelope9(code, message, hint) {
|
|
9509
9655
|
return {
|
|
9510
9656
|
tool: "debate",
|
|
@@ -9524,9 +9670,6 @@ var DEFAULT_DELEGATION_LIMITS = {
|
|
|
9524
9670
|
};
|
|
9525
9671
|
async function runDelegate(args, opts) {
|
|
9526
9672
|
if (!opts.storage) {
|
|
9527
|
-
if (opts.bridge && opts.bridge.toolNames.has("delegate")) {
|
|
9528
|
-
return await deferDelegate(args, opts.bridge);
|
|
9529
|
-
}
|
|
9530
9673
|
return errorEnvelope10(
|
|
9531
9674
|
"DELEGATE_STORAGE_UNAVAILABLE",
|
|
9532
9675
|
"delegate needs the local database (for quota tracking), which isn't available",
|
|
@@ -9598,7 +9741,6 @@ async function runDelegate(args, opts) {
|
|
|
9598
9741
|
const innerOpts = {
|
|
9599
9742
|
providers: opts.providers,
|
|
9600
9743
|
allowlist: opts.allowlist ?? null,
|
|
9601
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9602
9744
|
...opts.moderator ? { moderator: opts.moderator } : {}
|
|
9603
9745
|
};
|
|
9604
9746
|
let result;
|
|
@@ -9637,21 +9779,6 @@ async function record(storage, sessionId, requester, toolCall, via, accepted, no
|
|
|
9637
9779
|
created_at: nowEpochSeconds
|
|
9638
9780
|
});
|
|
9639
9781
|
}
|
|
9640
|
-
async function deferDelegate(args, bridge) {
|
|
9641
|
-
const r = await bridge.callTool("delegate", args);
|
|
9642
|
-
const text = r.content[0]?.text;
|
|
9643
|
-
if (typeof text === "string") {
|
|
9644
|
-
try {
|
|
9645
|
-
return JSON.parse(text);
|
|
9646
|
-
} catch {
|
|
9647
|
-
}
|
|
9648
|
-
}
|
|
9649
|
-
return errorEnvelope10(
|
|
9650
|
-
"DELEGATE_BRIDGE_BAD_ENVELOPE",
|
|
9651
|
-
"bridge returned an unparseable envelope for delegate",
|
|
9652
|
-
"Check that the Python child is healthy."
|
|
9653
|
-
);
|
|
9654
|
-
}
|
|
9655
9782
|
function errorEnvelope10(code, message, hint) {
|
|
9656
9783
|
return {
|
|
9657
9784
|
tool: "delegate",
|
|
@@ -9694,9 +9821,6 @@ async function runExplain(args, opts) {
|
|
|
9694
9821
|
);
|
|
9695
9822
|
}
|
|
9696
9823
|
if (!opts.storage) {
|
|
9697
|
-
if (opts.bridge && opts.bridge.toolNames.has("explain")) {
|
|
9698
|
-
return await deferExplain(args, opts.bridge);
|
|
9699
|
-
}
|
|
9700
9824
|
return errorEnvelope11(
|
|
9701
9825
|
"EXPLAIN_STORAGE_UNAVAILABLE",
|
|
9702
9826
|
"explain needs the local transcript/stats database, which isn't available",
|
|
@@ -9978,21 +10102,6 @@ function pyRepr5(v) {
|
|
|
9978
10102
|
}
|
|
9979
10103
|
return String(v);
|
|
9980
10104
|
}
|
|
9981
|
-
async function deferExplain(args, bridge) {
|
|
9982
|
-
const r = await bridge.callTool("explain", args);
|
|
9983
|
-
const text = r.content[0]?.text;
|
|
9984
|
-
if (typeof text === "string") {
|
|
9985
|
-
try {
|
|
9986
|
-
return JSON.parse(text);
|
|
9987
|
-
} catch {
|
|
9988
|
-
}
|
|
9989
|
-
}
|
|
9990
|
-
return errorEnvelope11(
|
|
9991
|
-
"EXPLAIN_BRIDGE_BAD_ENVELOPE",
|
|
9992
|
-
"bridge returned an unparseable envelope for explain",
|
|
9993
|
-
"Check that the Python child is healthy."
|
|
9994
|
-
);
|
|
9995
|
-
}
|
|
9996
10105
|
function errorEnvelope11(code, message, hint, kind = "client", extra = {}) {
|
|
9997
10106
|
return {
|
|
9998
10107
|
tool: "explain",
|
|
@@ -10545,9 +10654,6 @@ async function runRecall(args, opts) {
|
|
|
10545
10654
|
if (k < 1) k = 1;
|
|
10546
10655
|
if (k > 50) k = 50;
|
|
10547
10656
|
if (!opts.storage) {
|
|
10548
|
-
if (opts.bridge && opts.bridge.toolNames.has("recall")) {
|
|
10549
|
-
return await deferRecall(args, opts.bridge);
|
|
10550
|
-
}
|
|
10551
10657
|
return errorEnvelope12(
|
|
10552
10658
|
"RECALL_STORAGE_UNAVAILABLE",
|
|
10553
10659
|
"recall needs the local database, which isn't available",
|
|
@@ -10600,21 +10706,6 @@ async function runRecall(args, opts) {
|
|
|
10600
10706
|
applied_filters: applied
|
|
10601
10707
|
};
|
|
10602
10708
|
}
|
|
10603
|
-
async function deferRecall(args, bridge) {
|
|
10604
|
-
const r = await bridge.callTool("recall", args);
|
|
10605
|
-
const text = r.content[0]?.text;
|
|
10606
|
-
if (typeof text === "string") {
|
|
10607
|
-
try {
|
|
10608
|
-
return JSON.parse(text);
|
|
10609
|
-
} catch {
|
|
10610
|
-
}
|
|
10611
|
-
}
|
|
10612
|
-
return errorEnvelope12(
|
|
10613
|
-
"RECALL_BRIDGE_BAD_ENVELOPE",
|
|
10614
|
-
"bridge returned an unparseable envelope for recall",
|
|
10615
|
-
"Check that the Python child is healthy."
|
|
10616
|
-
);
|
|
10617
|
-
}
|
|
10618
10709
|
function errorEnvelope12(code, message, hint) {
|
|
10619
10710
|
return {
|
|
10620
10711
|
tool: "recall",
|
|
@@ -10637,9 +10728,6 @@ async function runRecommendPanel(args, opts) {
|
|
|
10637
10728
|
);
|
|
10638
10729
|
}
|
|
10639
10730
|
if (!opts.storage) {
|
|
10640
|
-
if (opts.bridge && opts.bridge.toolNames.has("recommend_panel")) {
|
|
10641
|
-
return await deferRecommendPanel(args, opts.bridge);
|
|
10642
|
-
}
|
|
10643
10731
|
return errorEnvelope13(
|
|
10644
10732
|
"RECOMMEND_PANEL_STORAGE_UNAVAILABLE",
|
|
10645
10733
|
"recommend_panel needs the local stats database, which isn't available",
|
|
@@ -10702,21 +10790,6 @@ async function runRecommendPanel(args, opts) {
|
|
|
10702
10790
|
meta: result.meta
|
|
10703
10791
|
};
|
|
10704
10792
|
}
|
|
10705
|
-
async function deferRecommendPanel(args, bridge) {
|
|
10706
|
-
const r = await bridge.callTool("recommend_panel", args);
|
|
10707
|
-
const text = r.content[0]?.text;
|
|
10708
|
-
if (typeof text === "string") {
|
|
10709
|
-
try {
|
|
10710
|
-
return JSON.parse(text);
|
|
10711
|
-
} catch {
|
|
10712
|
-
}
|
|
10713
|
-
}
|
|
10714
|
-
return errorEnvelope13(
|
|
10715
|
-
"RECOMMEND_PANEL_BRIDGE_BAD_ENVELOPE",
|
|
10716
|
-
"bridge returned an unparseable envelope for recommend_panel",
|
|
10717
|
-
"Check that the Python child is healthy."
|
|
10718
|
-
);
|
|
10719
|
-
}
|
|
10720
10793
|
function errorEnvelope13(code, message, hint) {
|
|
10721
10794
|
return {
|
|
10722
10795
|
tool: "recommend_panel",
|
|
@@ -10746,9 +10819,6 @@ function toStringArray3(v) {
|
|
|
10746
10819
|
var import_node_fs11 = require("fs");
|
|
10747
10820
|
async function runScoreboard(args, opts) {
|
|
10748
10821
|
if (!opts.storage) {
|
|
10749
|
-
if (opts.bridge && opts.bridge.toolNames.has("scoreboard")) {
|
|
10750
|
-
return await deferScoreboard(args, opts.bridge);
|
|
10751
|
-
}
|
|
10752
10822
|
return errorEnvelope14(
|
|
10753
10823
|
"SCOREBOARD_STORAGE_UNAVAILABLE",
|
|
10754
10824
|
"scoreboard needs the local stats database, which isn't available",
|
|
@@ -10871,21 +10941,6 @@ function clampInt3(raw, min, max, fallback) {
|
|
|
10871
10941
|
if (!Number.isFinite(n)) return fallback;
|
|
10872
10942
|
return Math.min(max, Math.max(min, Math.trunc(n)));
|
|
10873
10943
|
}
|
|
10874
|
-
async function deferScoreboard(args, bridge) {
|
|
10875
|
-
const r = await bridge.callTool("scoreboard", args);
|
|
10876
|
-
const text = r.content[0]?.text;
|
|
10877
|
-
if (typeof text === "string") {
|
|
10878
|
-
try {
|
|
10879
|
-
return JSON.parse(text);
|
|
10880
|
-
} catch {
|
|
10881
|
-
}
|
|
10882
|
-
}
|
|
10883
|
-
return errorEnvelope14(
|
|
10884
|
-
"SCOREBOARD_BRIDGE_BAD_ENVELOPE",
|
|
10885
|
-
"bridge returned an unparseable envelope for scoreboard",
|
|
10886
|
-
"Check that the Python child is healthy."
|
|
10887
|
-
);
|
|
10888
|
-
}
|
|
10889
10944
|
function errorEnvelope14(code, message, hint) {
|
|
10890
10945
|
return {
|
|
10891
10946
|
tool: "scoreboard",
|
|
@@ -10922,9 +10977,6 @@ async function runSessionMemory(args, opts) {
|
|
|
10922
10977
|
);
|
|
10923
10978
|
}
|
|
10924
10979
|
if (!opts.storage) {
|
|
10925
|
-
if (opts.bridge && opts.bridge.toolNames.has("session_memory")) {
|
|
10926
|
-
return await deferSessionMemory(args, opts.bridge);
|
|
10927
|
-
}
|
|
10928
10980
|
return errorEnvelope15(
|
|
10929
10981
|
"SESSION_MEMORY_STORAGE_UNAVAILABLE",
|
|
10930
10982
|
"session_memory needs the local database, which isn't available",
|
|
@@ -11029,21 +11081,6 @@ function clampInt4(raw, min, max, fallback) {
|
|
|
11029
11081
|
if (!Number.isFinite(n)) return fallback;
|
|
11030
11082
|
return Math.min(max, Math.max(min, Math.trunc(n)));
|
|
11031
11083
|
}
|
|
11032
|
-
async function deferSessionMemory(args, bridge) {
|
|
11033
|
-
const r = await bridge.callTool("session_memory", args);
|
|
11034
|
-
const text = r.content[0]?.text;
|
|
11035
|
-
if (typeof text === "string") {
|
|
11036
|
-
try {
|
|
11037
|
-
return JSON.parse(text);
|
|
11038
|
-
} catch {
|
|
11039
|
-
}
|
|
11040
|
-
}
|
|
11041
|
-
return errorEnvelope15(
|
|
11042
|
-
"SESSION_MEMORY_BRIDGE_BAD_ENVELOPE",
|
|
11043
|
-
"bridge returned an unparseable envelope for session_memory",
|
|
11044
|
-
"Check that the Python child is healthy."
|
|
11045
|
-
);
|
|
11046
|
-
}
|
|
11047
11084
|
function errorEnvelope15(code, message, hint) {
|
|
11048
11085
|
return {
|
|
11049
11086
|
tool: "session_memory",
|
|
@@ -11663,7 +11700,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
|
|
|
11663
11700
|
var DEFAULT_PACKAGE = "crosscheck-cli";
|
|
11664
11701
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
11665
11702
|
function engineVersion() {
|
|
11666
|
-
return true ? "0.2.
|
|
11703
|
+
return true ? "0.2.29" : "0.0.0-dev";
|
|
11667
11704
|
}
|
|
11668
11705
|
function defaultUpdateCachePath() {
|
|
11669
11706
|
const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path12.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
|
|
@@ -12435,12 +12472,11 @@ function helpTool() {
|
|
|
12435
12472
|
}
|
|
12436
12473
|
});
|
|
12437
12474
|
}
|
|
12438
|
-
function registerCoreTools(
|
|
12439
|
-
const o = opts && typeof opts === "object" && "toolNames" in opts ? { bridge: opts } : opts;
|
|
12475
|
+
function registerCoreTools(o = {}) {
|
|
12440
12476
|
const tools = /* @__PURE__ */ new Map();
|
|
12441
12477
|
const list = [
|
|
12442
12478
|
pingTool(),
|
|
12443
|
-
verifyTool(o.
|
|
12479
|
+
verifyTool(o.fetchConfig),
|
|
12444
12480
|
pickTool(
|
|
12445
12481
|
o.providers ?? {},
|
|
12446
12482
|
o.providerAllowlist ?? null,
|
|
@@ -12452,7 +12488,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12452
12488
|
auditTool(
|
|
12453
12489
|
o.providers ?? {},
|
|
12454
12490
|
o.providerAllowlist ?? null,
|
|
12455
|
-
o.bridge,
|
|
12456
12491
|
o.transcriptsDir,
|
|
12457
12492
|
o.pricing,
|
|
12458
12493
|
o.storage,
|
|
@@ -12462,7 +12497,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12462
12497
|
conferTool(
|
|
12463
12498
|
o.providers ?? {},
|
|
12464
12499
|
o.providerAllowlist ?? null,
|
|
12465
|
-
o.bridge,
|
|
12466
12500
|
o.moderatorDefault ?? "anthropic",
|
|
12467
12501
|
o.pricing,
|
|
12468
12502
|
o.storage,
|
|
@@ -12475,7 +12509,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12475
12509
|
debateTool(
|
|
12476
12510
|
o.providers ?? {},
|
|
12477
12511
|
o.providerAllowlist ?? null,
|
|
12478
|
-
o.bridge,
|
|
12479
12512
|
buildInnerCallers(o),
|
|
12480
12513
|
o.storage,
|
|
12481
12514
|
o.pricing,
|
|
@@ -12487,7 +12520,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12487
12520
|
coordinateTool(
|
|
12488
12521
|
o.providers ?? {},
|
|
12489
12522
|
o.providerAllowlist ?? null,
|
|
12490
|
-
o.bridge,
|
|
12491
12523
|
buildInnerCallers(o),
|
|
12492
12524
|
o.storage,
|
|
12493
12525
|
o.circuitBreakers,
|
|
@@ -12498,7 +12530,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12498
12530
|
triangulateTool(
|
|
12499
12531
|
o.providers ?? {},
|
|
12500
12532
|
o.providerAllowlist ?? null,
|
|
12501
|
-
o.bridge,
|
|
12502
12533
|
o.storage,
|
|
12503
12534
|
o.circuitBreakers,
|
|
12504
12535
|
o.transcriptsDir,
|
|
@@ -12507,7 +12538,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12507
12538
|
planTool(
|
|
12508
12539
|
o.providers ?? {},
|
|
12509
12540
|
o.providerAllowlist ?? null,
|
|
12510
|
-
o.bridge,
|
|
12511
12541
|
o.storage,
|
|
12512
12542
|
o.circuitBreakers,
|
|
12513
12543
|
o.transcriptsDir,
|
|
@@ -12516,7 +12546,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12516
12546
|
critiqueTool(
|
|
12517
12547
|
o.providers ?? {},
|
|
12518
12548
|
o.providerAllowlist ?? null,
|
|
12519
|
-
o.bridge,
|
|
12520
12549
|
o.storage,
|
|
12521
12550
|
o.circuitBreakers,
|
|
12522
12551
|
o.transcriptsDir,
|
|
@@ -12525,7 +12554,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12525
12554
|
reviewTool(
|
|
12526
12555
|
o.providers ?? {},
|
|
12527
12556
|
o.providerAllowlist ?? null,
|
|
12528
|
-
o.bridge,
|
|
12529
12557
|
o.storage,
|
|
12530
12558
|
o.circuitBreakers,
|
|
12531
12559
|
o.transcriptsDir,
|
|
@@ -12533,25 +12561,23 @@ function registerCoreTools(opts = {}) {
|
|
|
12533
12561
|
),
|
|
12534
12562
|
listProvidersTool(o.providers ?? {}, o.activeProviders ?? null, o.moderatorDefault ?? "anthropic"),
|
|
12535
12563
|
modelsTool(o.providers ?? {}, o.activeProviders ?? null),
|
|
12536
|
-
recallTool(o.storage
|
|
12537
|
-
sessionMemoryTool(o.storage
|
|
12538
|
-
scoreboardTool(o.storage, o.
|
|
12539
|
-
explainTool(o.storage, o.
|
|
12564
|
+
recallTool(o.storage),
|
|
12565
|
+
sessionMemoryTool(o.storage),
|
|
12566
|
+
scoreboardTool(o.storage, o.eventsPath),
|
|
12567
|
+
explainTool(o.storage, o.transcriptsDir),
|
|
12540
12568
|
delegateTool(
|
|
12541
12569
|
o.providers ?? {},
|
|
12542
12570
|
o.providerAllowlist ?? null,
|
|
12543
12571
|
o.storage,
|
|
12544
|
-
o.bridge,
|
|
12545
12572
|
o.moderatorDefault ?? "anthropic"
|
|
12546
12573
|
),
|
|
12547
12574
|
fetchTool(o.storage, o.fetchConfig, o.repoRoot),
|
|
12548
|
-
recommendPanelTool(o.providers ?? {}, o.storage
|
|
12575
|
+
recommendPanelTool(o.providers ?? {}, o.storage),
|
|
12549
12576
|
updateCrosscheckTool(o.repoRoot ?? null),
|
|
12550
12577
|
benchTool(
|
|
12551
12578
|
o.providers ?? {},
|
|
12552
12579
|
o.providerAllowlist ?? null,
|
|
12553
12580
|
o.storage,
|
|
12554
|
-
o.bridge,
|
|
12555
12581
|
o.moderatorDefault ?? "anthropic",
|
|
12556
12582
|
o.benchGoldensDir,
|
|
12557
12583
|
o.circuitBreakers,
|
|
@@ -12562,7 +12588,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12562
12588
|
solveTool(
|
|
12563
12589
|
o.providers ?? {},
|
|
12564
12590
|
o.providerAllowlist ?? null,
|
|
12565
|
-
o.bridge,
|
|
12566
12591
|
o.storage,
|
|
12567
12592
|
o.circuitBreakers,
|
|
12568
12593
|
o.transcriptsDir,
|
|
@@ -12571,7 +12596,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12571
12596
|
orchestrateTool(
|
|
12572
12597
|
o.providers ?? {},
|
|
12573
12598
|
o.providerAllowlist ?? null,
|
|
12574
|
-
o.bridge,
|
|
12575
12599
|
o.moderatorDefault ?? "anthropic",
|
|
12576
12600
|
o.storage,
|
|
12577
12601
|
o.pricing,
|
|
@@ -12618,7 +12642,6 @@ function createTool(o, toolName, cheapDefault) {
|
|
|
12618
12642
|
providers: o.providers ?? {},
|
|
12619
12643
|
allowlist: o.providerAllowlist ?? null,
|
|
12620
12644
|
...o.storage ? { storage: o.storage } : {},
|
|
12621
|
-
...o.bridge ? { bridge: o.bridge } : {},
|
|
12622
12645
|
...o.moderatorDefault ? { moderator: o.moderatorDefault } : {},
|
|
12623
12646
|
...o.fetchConfig ? { fetchConfig: o.fetchConfig } : {},
|
|
12624
12647
|
...o.repoRoot ? { repoRoot: o.repoRoot } : {},
|
|
@@ -12627,7 +12650,7 @@ function createTool(o, toolName, cheapDefault) {
|
|
|
12627
12650
|
})
|
|
12628
12651
|
};
|
|
12629
12652
|
}
|
|
12630
|
-
function orchestrateTool(providers, allowlist,
|
|
12653
|
+
function orchestrateTool(providers, allowlist, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
|
|
12631
12654
|
return {
|
|
12632
12655
|
name: "orchestrate",
|
|
12633
12656
|
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.",
|
|
@@ -12652,7 +12675,6 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
|
|
|
12652
12675
|
providers,
|
|
12653
12676
|
allowlist,
|
|
12654
12677
|
moderator,
|
|
12655
|
-
...bridge ? { bridge } : {},
|
|
12656
12678
|
...storage ? { storage } : {},
|
|
12657
12679
|
...pricing ? { pricing } : {},
|
|
12658
12680
|
...breakers ? { breakers } : {},
|
|
@@ -12662,7 +12684,7 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
|
|
|
12662
12684
|
})
|
|
12663
12685
|
};
|
|
12664
12686
|
}
|
|
12665
|
-
function solveTool(providers, allowlist,
|
|
12687
|
+
function solveTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
12666
12688
|
return {
|
|
12667
12689
|
name: "solve",
|
|
12668
12690
|
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.",
|
|
@@ -12684,7 +12706,6 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
|
|
|
12684
12706
|
handler: (args) => runSolve(args, {
|
|
12685
12707
|
providers,
|
|
12686
12708
|
allowlist,
|
|
12687
|
-
...bridge ? { bridge } : {},
|
|
12688
12709
|
...storage ? { storage } : {},
|
|
12689
12710
|
...breakers ? { breakers } : {},
|
|
12690
12711
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -12723,7 +12744,7 @@ function configPinTool(repoRoot, config2, rejectDriftEnv) {
|
|
|
12723
12744
|
}
|
|
12724
12745
|
};
|
|
12725
12746
|
}
|
|
12726
|
-
function benchTool(providers, allowlist, storage,
|
|
12747
|
+
function benchTool(providers, allowlist, storage, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
|
|
12727
12748
|
return {
|
|
12728
12749
|
name: "bench",
|
|
12729
12750
|
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).",
|
|
@@ -12742,7 +12763,6 @@ function benchTool(providers, allowlist, storage, bridge, moderator, defaultGold
|
|
|
12742
12763
|
allowlist,
|
|
12743
12764
|
moderator,
|
|
12744
12765
|
...storage ? { storage } : {},
|
|
12745
|
-
...bridge ? { bridge } : {},
|
|
12746
12766
|
...defaultGoldensDir ? { defaultGoldensDir } : {},
|
|
12747
12767
|
...breakers ? { breakers } : {},
|
|
12748
12768
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -12769,7 +12789,7 @@ function updateCrosscheckTool(repoRoot) {
|
|
|
12769
12789
|
}
|
|
12770
12790
|
};
|
|
12771
12791
|
}
|
|
12772
|
-
function recommendPanelTool(providers, storage
|
|
12792
|
+
function recommendPanelTool(providers, storage) {
|
|
12773
12793
|
return {
|
|
12774
12794
|
name: "recommend_panel",
|
|
12775
12795
|
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.",
|
|
@@ -12787,8 +12807,7 @@ function recommendPanelTool(providers, storage, bridge) {
|
|
|
12787
12807
|
},
|
|
12788
12808
|
handler: (args) => runRecommendPanel(args, {
|
|
12789
12809
|
providers,
|
|
12790
|
-
...storage ? { storage } : {}
|
|
12791
|
-
...bridge ? { bridge } : {}
|
|
12810
|
+
...storage ? { storage } : {}
|
|
12792
12811
|
})
|
|
12793
12812
|
};
|
|
12794
12813
|
}
|
|
@@ -12813,7 +12832,7 @@ function fetchTool(storage, fetchConfig, repoRoot) {
|
|
|
12813
12832
|
})
|
|
12814
12833
|
};
|
|
12815
12834
|
}
|
|
12816
|
-
function delegateTool(providers, allowlist, storage,
|
|
12835
|
+
function delegateTool(providers, allowlist, storage, moderator) {
|
|
12817
12836
|
return {
|
|
12818
12837
|
name: "delegate",
|
|
12819
12838
|
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.",
|
|
@@ -12833,12 +12852,11 @@ function delegateTool(providers, allowlist, storage, bridge, moderator) {
|
|
|
12833
12852
|
providers,
|
|
12834
12853
|
allowlist,
|
|
12835
12854
|
moderator,
|
|
12836
|
-
...storage ? { storage } : {}
|
|
12837
|
-
...bridge ? { bridge } : {}
|
|
12855
|
+
...storage ? { storage } : {}
|
|
12838
12856
|
})
|
|
12839
12857
|
};
|
|
12840
12858
|
}
|
|
12841
|
-
function explainTool(storage,
|
|
12859
|
+
function explainTool(storage, transcriptsDir) {
|
|
12842
12860
|
return {
|
|
12843
12861
|
name: "explain",
|
|
12844
12862
|
description: "Replay a session as a navigable tree with cost/latency annotations. Reads usage_log + optionally walks the transcripts directory for per-tool summaries.",
|
|
@@ -12856,12 +12874,11 @@ function explainTool(storage, bridge, transcriptsDir) {
|
|
|
12856
12874
|
},
|
|
12857
12875
|
handler: (args) => runExplain(args, {
|
|
12858
12876
|
...storage ? { storage } : {},
|
|
12859
|
-
...bridge ? { bridge } : {},
|
|
12860
12877
|
...transcriptsDir ? { transcriptsDir } : {}
|
|
12861
12878
|
})
|
|
12862
12879
|
};
|
|
12863
12880
|
}
|
|
12864
|
-
function scoreboardTool(storage,
|
|
12881
|
+
function scoreboardTool(storage, eventsPath) {
|
|
12865
12882
|
return {
|
|
12866
12883
|
name: "scoreboard",
|
|
12867
12884
|
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).",
|
|
@@ -12875,12 +12892,11 @@ function scoreboardTool(storage, bridge, eventsPath) {
|
|
|
12875
12892
|
},
|
|
12876
12893
|
handler: (args) => runScoreboard(args, {
|
|
12877
12894
|
...storage ? { storage } : {},
|
|
12878
|
-
...bridge ? { bridge } : {},
|
|
12879
12895
|
...eventsPath ? { eventsPath } : {}
|
|
12880
12896
|
})
|
|
12881
12897
|
};
|
|
12882
12898
|
}
|
|
12883
|
-
function sessionMemoryTool(storage
|
|
12899
|
+
function sessionMemoryTool(storage) {
|
|
12884
12900
|
return {
|
|
12885
12901
|
name: "session_memory",
|
|
12886
12902
|
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).",
|
|
@@ -12903,15 +12919,14 @@ function sessionMemoryTool(storage, bridge) {
|
|
|
12903
12919
|
required: ["action", "session_id"]
|
|
12904
12920
|
},
|
|
12905
12921
|
handler: (args) => runSessionMemory(args, {
|
|
12906
|
-
...storage ? { storage } : {}
|
|
12907
|
-
...bridge ? { bridge } : {}
|
|
12922
|
+
...storage ? { storage } : {}
|
|
12908
12923
|
})
|
|
12909
12924
|
};
|
|
12910
12925
|
}
|
|
12911
|
-
function recallTool(storage
|
|
12926
|
+
function recallTool(storage) {
|
|
12912
12927
|
return {
|
|
12913
12928
|
name: "recall",
|
|
12914
|
-
description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter
|
|
12929
|
+
description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter.",
|
|
12915
12930
|
inputSchema: {
|
|
12916
12931
|
type: "object",
|
|
12917
12932
|
additionalProperties: true,
|
|
@@ -12925,8 +12940,7 @@ function recallTool(storage, bridge) {
|
|
|
12925
12940
|
required: ["query"]
|
|
12926
12941
|
},
|
|
12927
12942
|
handler: (args) => runRecall(args, {
|
|
12928
|
-
...storage ? { storage } : {}
|
|
12929
|
-
...bridge ? { bridge } : {}
|
|
12943
|
+
...storage ? { storage } : {}
|
|
12930
12944
|
})
|
|
12931
12945
|
};
|
|
12932
12946
|
}
|
|
@@ -12962,7 +12976,7 @@ function modelsTool(providers, activeProviders) {
|
|
|
12962
12976
|
handler: async (args) => runModels(args, { providers, activeProviders })
|
|
12963
12977
|
};
|
|
12964
12978
|
}
|
|
12965
|
-
function reviewTool(providers, allowlist,
|
|
12979
|
+
function reviewTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
12966
12980
|
return {
|
|
12967
12981
|
name: "review",
|
|
12968
12982
|
description: "Have an LLM panel peer-review a code or proposal snippet. Returns the confer envelope (one answer per provider).",
|
|
@@ -12981,7 +12995,6 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
|
|
|
12981
12995
|
handler: (args) => runReview(args, {
|
|
12982
12996
|
providers,
|
|
12983
12997
|
allowlist,
|
|
12984
|
-
...bridge ? { bridge } : {},
|
|
12985
12998
|
...storage ? { storage } : {},
|
|
12986
12999
|
...breakers ? { breakers } : {},
|
|
12987
13000
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -12989,7 +13002,7 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
|
|
|
12989
13002
|
})
|
|
12990
13003
|
};
|
|
12991
13004
|
}
|
|
12992
|
-
function critiqueTool(providers, allowlist,
|
|
13005
|
+
function critiqueTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
12993
13006
|
return {
|
|
12994
13007
|
name: "critique",
|
|
12995
13008
|
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.",
|
|
@@ -13009,7 +13022,6 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
|
|
|
13009
13022
|
handler: (args) => runCritique(args, {
|
|
13010
13023
|
providers,
|
|
13011
13024
|
allowlist,
|
|
13012
|
-
...bridge ? { bridge } : {},
|
|
13013
13025
|
...storage ? { storage } : {},
|
|
13014
13026
|
...breakers ? { breakers } : {},
|
|
13015
13027
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -13017,7 +13029,7 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
|
|
|
13017
13029
|
})
|
|
13018
13030
|
};
|
|
13019
13031
|
}
|
|
13020
|
-
function planTool(providers, allowlist,
|
|
13032
|
+
function planTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
13021
13033
|
return {
|
|
13022
13034
|
name: "plan",
|
|
13023
13035
|
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.',
|
|
@@ -13044,7 +13056,6 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
|
|
|
13044
13056
|
handler: (args) => runPlan(args, {
|
|
13045
13057
|
providers,
|
|
13046
13058
|
allowlist,
|
|
13047
|
-
...bridge ? { bridge } : {},
|
|
13048
13059
|
...storage ? { storage } : {},
|
|
13049
13060
|
...breakers ? { breakers } : {},
|
|
13050
13061
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -13052,7 +13063,7 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
|
|
|
13052
13063
|
})
|
|
13053
13064
|
};
|
|
13054
13065
|
}
|
|
13055
|
-
function triangulateTool(providers, allowlist,
|
|
13066
|
+
function triangulateTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
13056
13067
|
return {
|
|
13057
13068
|
name: "triangulate",
|
|
13058
13069
|
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.",
|
|
@@ -13073,7 +13084,6 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
|
|
|
13073
13084
|
handler: (args) => runTriangulate(args, {
|
|
13074
13085
|
providers,
|
|
13075
13086
|
allowlist,
|
|
13076
|
-
...bridge ? { bridge } : {},
|
|
13077
13087
|
...storage ? { storage } : {},
|
|
13078
13088
|
...breakers ? { breakers } : {},
|
|
13079
13089
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -13081,7 +13091,7 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
|
|
|
13081
13091
|
})
|
|
13082
13092
|
};
|
|
13083
13093
|
}
|
|
13084
|
-
function coordinateTool(providers, allowlist,
|
|
13094
|
+
function coordinateTool(providers, allowlist, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
13085
13095
|
return {
|
|
13086
13096
|
name: "coordinate",
|
|
13087
13097
|
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).",
|
|
@@ -13106,7 +13116,6 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
|
|
|
13106
13116
|
handler: (args) => runCoordinate(args, {
|
|
13107
13117
|
providers,
|
|
13108
13118
|
allowlist,
|
|
13109
|
-
...bridge ? { bridge } : {},
|
|
13110
13119
|
innerCallers,
|
|
13111
13120
|
...storage ? { storage } : {},
|
|
13112
13121
|
...breakers ? { breakers } : {},
|
|
@@ -13116,7 +13125,7 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
|
|
|
13116
13125
|
})
|
|
13117
13126
|
};
|
|
13118
13127
|
}
|
|
13119
|
-
function debateTool(providers, allowlist,
|
|
13128
|
+
function debateTool(providers, allowlist, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
13120
13129
|
return {
|
|
13121
13130
|
name: "debate",
|
|
13122
13131
|
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).",
|
|
@@ -13146,7 +13155,6 @@ function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing
|
|
|
13146
13155
|
handler: (args) => runDebate(args, {
|
|
13147
13156
|
providers,
|
|
13148
13157
|
allowlist,
|
|
13149
|
-
...bridge ? { bridge } : {},
|
|
13150
13158
|
innerCallers,
|
|
13151
13159
|
...storage ? { storage } : {},
|
|
13152
13160
|
...pricing ? { pricing } : {},
|
|
@@ -13166,10 +13174,10 @@ function buildInnerCallers(o) {
|
|
|
13166
13174
|
...o.repoRoot ? { repoRoot: o.repoRoot } : {}
|
|
13167
13175
|
});
|
|
13168
13176
|
}
|
|
13169
|
-
out.verify = (args) => runVerify(args, o.
|
|
13177
|
+
out.verify = (args) => runVerify(args, o.fetchConfig);
|
|
13170
13178
|
return out;
|
|
13171
13179
|
}
|
|
13172
|
-
function conferTool(providers, allowlist,
|
|
13180
|
+
function conferTool(providers, allowlist, moderator, pricing, storage, innerCallers, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
13173
13181
|
return {
|
|
13174
13182
|
name: "confer",
|
|
13175
13183
|
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).",
|
|
@@ -13196,7 +13204,6 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
|
|
|
13196
13204
|
handler: (args) => runConfer(args, {
|
|
13197
13205
|
providers,
|
|
13198
13206
|
allowlist,
|
|
13199
|
-
...bridge ? { bridge } : {},
|
|
13200
13207
|
moderator,
|
|
13201
13208
|
...pricing ? { pricing } : {},
|
|
13202
13209
|
...storage ? { storage } : {},
|
|
@@ -13208,7 +13215,7 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
|
|
|
13208
13215
|
})
|
|
13209
13216
|
};
|
|
13210
13217
|
}
|
|
13211
|
-
function auditTool(providers, allowlist,
|
|
13218
|
+
function auditTool(providers, allowlist, transcriptsDir, pricing, storage, breakers, repoRoot) {
|
|
13212
13219
|
return {
|
|
13213
13220
|
name: "audit",
|
|
13214
13221
|
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.",
|
|
@@ -13234,7 +13241,6 @@ function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storag
|
|
|
13234
13241
|
handler: (args) => runAudit(args, {
|
|
13235
13242
|
providers,
|
|
13236
13243
|
allowlist,
|
|
13237
|
-
...bridge ? { bridge } : {},
|
|
13238
13244
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
13239
13245
|
...pricing ? { pricing } : {},
|
|
13240
13246
|
...storage ? { storage } : {},
|
|
@@ -13298,7 +13304,7 @@ function pickTool(providers, allowlist, storage, breakers, transcriptsDir, repoR
|
|
|
13298
13304
|
})
|
|
13299
13305
|
};
|
|
13300
13306
|
}
|
|
13301
|
-
function verifyTool(
|
|
13307
|
+
function verifyTool(fetchConfig) {
|
|
13302
13308
|
return {
|
|
13303
13309
|
name: "verify",
|
|
13304
13310
|
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.",
|
|
@@ -13316,7 +13322,7 @@ function verifyTool(bridge, fetchConfig) {
|
|
|
13316
13322
|
},
|
|
13317
13323
|
required: ["checks"]
|
|
13318
13324
|
},
|
|
13319
|
-
handler: (args) => runVerify(args,
|
|
13325
|
+
handler: (args) => runVerify(args, fetchConfig)
|
|
13320
13326
|
};
|
|
13321
13327
|
}
|
|
13322
13328
|
function pingTool() {
|
|
@@ -13336,7 +13342,7 @@ function pingTool() {
|
|
|
13336
13342
|
}
|
|
13337
13343
|
|
|
13338
13344
|
// src/core/telemetry.ts
|
|
13339
|
-
var
|
|
13345
|
+
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
13340
13346
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13341
13347
|
var BATCH_MAX = 100;
|
|
13342
13348
|
var MAX_QUEUE = 500;
|
|
@@ -13400,6 +13406,64 @@ async function flush() {
|
|
|
13400
13406
|
}
|
|
13401
13407
|
}
|
|
13402
13408
|
|
|
13409
|
+
// src/core/process-registry.ts
|
|
13410
|
+
var import_node_fs15 = require("fs");
|
|
13411
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
13412
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
13413
|
+
function registryDir(env = process.env) {
|
|
13414
|
+
const base = env["CROSSCHECK_DATA_DIR"] || import_node_path14.default.join(env["HOME"] ?? env["USERPROFILE"] ?? import_node_os3.default.homedir(), ".crosscheck");
|
|
13415
|
+
return import_node_path14.default.join(base, "procs");
|
|
13416
|
+
}
|
|
13417
|
+
function isAlive(pid) {
|
|
13418
|
+
try {
|
|
13419
|
+
process.kill(pid, 0);
|
|
13420
|
+
return true;
|
|
13421
|
+
} catch (err) {
|
|
13422
|
+
return err.code === "EPERM";
|
|
13423
|
+
}
|
|
13424
|
+
}
|
|
13425
|
+
function listProcesses(installedVersion, env = process.env, now = Date.now()) {
|
|
13426
|
+
const dir = registryDir(env);
|
|
13427
|
+
let files;
|
|
13428
|
+
try {
|
|
13429
|
+
files = (0, import_node_fs15.readdirSync)(dir).filter((f) => f.endsWith(".json"));
|
|
13430
|
+
} catch {
|
|
13431
|
+
return [];
|
|
13432
|
+
}
|
|
13433
|
+
const out = [];
|
|
13434
|
+
for (const f of files) {
|
|
13435
|
+
let rec;
|
|
13436
|
+
try {
|
|
13437
|
+
rec = JSON.parse((0, import_node_fs15.readFileSync)(import_node_path14.default.join(dir, f), "utf8"));
|
|
13438
|
+
} catch {
|
|
13439
|
+
try {
|
|
13440
|
+
(0, import_node_fs15.rmSync)(import_node_path14.default.join(dir, f), { force: true });
|
|
13441
|
+
} catch {
|
|
13442
|
+
}
|
|
13443
|
+
continue;
|
|
13444
|
+
}
|
|
13445
|
+
if (typeof rec.pid !== "number") continue;
|
|
13446
|
+
const alive = isAlive(rec.pid);
|
|
13447
|
+
if (!alive) {
|
|
13448
|
+
try {
|
|
13449
|
+
(0, import_node_fs15.rmSync)(import_node_path14.default.join(dir, f), { force: true });
|
|
13450
|
+
} catch {
|
|
13451
|
+
}
|
|
13452
|
+
continue;
|
|
13453
|
+
}
|
|
13454
|
+
out.push({
|
|
13455
|
+
...rec,
|
|
13456
|
+
alive,
|
|
13457
|
+
outdated: Boolean(rec.version) && rec.version !== installedVersion,
|
|
13458
|
+
ageMs: Math.max(0, now - (rec.startedAt ?? now))
|
|
13459
|
+
});
|
|
13460
|
+
}
|
|
13461
|
+
return out.sort((a, b) => a.startedAt - b.startedAt);
|
|
13462
|
+
}
|
|
13463
|
+
function processRegistryPath(env = process.env) {
|
|
13464
|
+
return registryDir(env);
|
|
13465
|
+
}
|
|
13466
|
+
|
|
13403
13467
|
// src/entrypoints/embed.ts
|
|
13404
13468
|
var KEY_ENV = {
|
|
13405
13469
|
anthropic: "ANTHROPIC_API_KEY",
|
|
@@ -13427,6 +13491,107 @@ var ENGINE_TO_VAULT = { xai: "grok" };
|
|
|
13427
13491
|
function vaultId(engineName) {
|
|
13428
13492
|
return ENGINE_TO_VAULT[engineName] ?? engineName;
|
|
13429
13493
|
}
|
|
13494
|
+
var ACTIVITY_TEXT_CAP = 8e3;
|
|
13495
|
+
var ASKED_CAP = 280;
|
|
13496
|
+
var runContext = new import_node_async_hooks2.AsyncLocalStorage();
|
|
13497
|
+
var SYNTHESIS_PURPOSES = /* @__PURE__ */ new Set(["synth", "moderator", "recombine", "judge", "unify"]);
|
|
13498
|
+
function exemptFromSkip(ctx, provider, purpose) {
|
|
13499
|
+
return provider === ctx.moderator && SYNTHESIS_PURPOSES.has(purpose);
|
|
13500
|
+
}
|
|
13501
|
+
function skippedError(provider, why, limitMs) {
|
|
13502
|
+
return new ProviderError(
|
|
13503
|
+
"client",
|
|
13504
|
+
why === "timeout" ? `${provider}: stopped after ${Math.round((limitMs ?? 0) / 1e3)}s (your per-model time limit)` : `${provider}: stopped waiting (you skipped it)`,
|
|
13505
|
+
{ transient: false }
|
|
13506
|
+
);
|
|
13507
|
+
}
|
|
13508
|
+
function lastUserText(args) {
|
|
13509
|
+
const msgs = args.messages;
|
|
13510
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
13511
|
+
const m = msgs[i];
|
|
13512
|
+
if (m && m.role === "user" && typeof m.content === "string") {
|
|
13513
|
+
const t = m.content.replace(/\s+/g, " ").trim();
|
|
13514
|
+
return t.length > ASKED_CAP ? `${t.slice(0, ASKED_CAP - 1)}\u2026` : t;
|
|
13515
|
+
}
|
|
13516
|
+
}
|
|
13517
|
+
return "";
|
|
13518
|
+
}
|
|
13519
|
+
function withActivity(p) {
|
|
13520
|
+
const send = p.send.bind(p);
|
|
13521
|
+
return {
|
|
13522
|
+
name: p.name,
|
|
13523
|
+
model: p.model,
|
|
13524
|
+
...p.fallbackModels ? { fallbackModels: p.fallbackModels } : {},
|
|
13525
|
+
send: async (args) => {
|
|
13526
|
+
const ctx = runContext.getStore();
|
|
13527
|
+
if (!ctx) return send(args);
|
|
13528
|
+
const callId = ctx.nextCallId();
|
|
13529
|
+
const provider = vaultId(p.name);
|
|
13530
|
+
const model = args.modelOverride ?? p.model;
|
|
13531
|
+
const purpose = args.purpose ?? "worker";
|
|
13532
|
+
const started = Date.now();
|
|
13533
|
+
const exempt = exemptFromSkip(ctx, provider, purpose);
|
|
13534
|
+
if (!exempt && ctx.skipped.has(provider)) throw skippedError(provider, "user");
|
|
13535
|
+
ctx.emit({ type: "call.start", runId: ctx.runId, at: started, callId, provider, model, purpose, asked: lastUserText(args) });
|
|
13536
|
+
const controller = new AbortController();
|
|
13537
|
+
if (args.signal) {
|
|
13538
|
+
if (args.signal.aborted) controller.abort(args.signal.reason);
|
|
13539
|
+
else args.signal.addEventListener("abort", () => controller.abort(args.signal.reason), { once: true });
|
|
13540
|
+
}
|
|
13541
|
+
let stopped;
|
|
13542
|
+
if (!exempt) ctx.inflight.set(callId, { provider, purpose, controller });
|
|
13543
|
+
const timer = !exempt && ctx.callTimeoutMs && ctx.callTimeoutMs > 0 ? setTimeout(() => {
|
|
13544
|
+
stopped = "timeout";
|
|
13545
|
+
controller.abort("timeout");
|
|
13546
|
+
}, ctx.callTimeoutMs) : void 0;
|
|
13547
|
+
controller.signal.addEventListener("abort", () => {
|
|
13548
|
+
if (!stopped && controller.signal.reason === "skip") stopped = "user";
|
|
13549
|
+
}, { once: true });
|
|
13550
|
+
try {
|
|
13551
|
+
const res = await send({ ...args, signal: controller.signal });
|
|
13552
|
+
const text = typeof res.text === "string" ? res.text : "";
|
|
13553
|
+
ctx.emit({
|
|
13554
|
+
type: "call.done",
|
|
13555
|
+
runId: ctx.runId,
|
|
13556
|
+
at: Date.now(),
|
|
13557
|
+
callId,
|
|
13558
|
+
provider,
|
|
13559
|
+
model,
|
|
13560
|
+
purpose,
|
|
13561
|
+
ok: true,
|
|
13562
|
+
ms: Date.now() - started,
|
|
13563
|
+
text: text.slice(0, ACTIVITY_TEXT_CAP),
|
|
13564
|
+
truncated: text.length > ACTIVITY_TEXT_CAP,
|
|
13565
|
+
error: null,
|
|
13566
|
+
usage: usageOf(res)
|
|
13567
|
+
});
|
|
13568
|
+
return res;
|
|
13569
|
+
} catch (err) {
|
|
13570
|
+
const out = stopped ? skippedError(provider, stopped, ctx.callTimeoutMs) : err;
|
|
13571
|
+
ctx.emit({
|
|
13572
|
+
type: "call.done",
|
|
13573
|
+
runId: ctx.runId,
|
|
13574
|
+
at: Date.now(),
|
|
13575
|
+
callId,
|
|
13576
|
+
provider,
|
|
13577
|
+
model,
|
|
13578
|
+
purpose,
|
|
13579
|
+
ok: false,
|
|
13580
|
+
ms: Date.now() - started,
|
|
13581
|
+
text: "",
|
|
13582
|
+
truncated: false,
|
|
13583
|
+
error: out instanceof Error ? out.message : String(out),
|
|
13584
|
+
usage: null,
|
|
13585
|
+
...stopped ? { stopped } : {}
|
|
13586
|
+
});
|
|
13587
|
+
throw out;
|
|
13588
|
+
} finally {
|
|
13589
|
+
if (timer) clearTimeout(timer);
|
|
13590
|
+
ctx.inflight.delete(callId);
|
|
13591
|
+
}
|
|
13592
|
+
}
|
|
13593
|
+
};
|
|
13594
|
+
}
|
|
13430
13595
|
function usageOf(answer) {
|
|
13431
13596
|
const u = answer["usage"];
|
|
13432
13597
|
if (!u || typeof u !== "object") return null;
|
|
@@ -13456,12 +13621,14 @@ function errorOf(answer) {
|
|
|
13456
13621
|
}
|
|
13457
13622
|
function bundledPricingPath() {
|
|
13458
13623
|
try {
|
|
13459
|
-
return
|
|
13624
|
+
return import_node_path15.default.join(import_node_path15.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl)), "pricing.json");
|
|
13460
13625
|
} catch {
|
|
13461
13626
|
return void 0;
|
|
13462
13627
|
}
|
|
13463
13628
|
}
|
|
13464
13629
|
var runCounter = 0;
|
|
13630
|
+
var callCounter = 0;
|
|
13631
|
+
var nextCallId = () => ++callCounter;
|
|
13465
13632
|
function nextRunId() {
|
|
13466
13633
|
runCounter += 1;
|
|
13467
13634
|
return `run_${Date.now().toString(36)}_${runCounter}`;
|
|
@@ -13477,10 +13644,12 @@ function createEmbeddedEngine(opts) {
|
|
|
13477
13644
|
if (varName && model) env[varName] = model;
|
|
13478
13645
|
}
|
|
13479
13646
|
const pricingPath = [opts.pricingPath, bundledPricingPath()].find(
|
|
13480
|
-
(p) => Boolean(p) && (0,
|
|
13647
|
+
(p) => Boolean(p) && (0, import_node_fs16.existsSync)(p)
|
|
13481
13648
|
);
|
|
13482
13649
|
const pricing = pricingPath ? loadPricing(pricingPath) : {};
|
|
13483
|
-
const built =
|
|
13650
|
+
const built = Object.fromEntries(
|
|
13651
|
+
Object.entries(buildProviders({ env, pricing })).map(([name, p]) => [name, withActivity(p)])
|
|
13652
|
+
);
|
|
13484
13653
|
const moderator = opts.moderator ?? "anthropic";
|
|
13485
13654
|
const tools = registerCoreTools({ providers: built, pricing });
|
|
13486
13655
|
const providerIds = Object.keys(built).map(vaultId).sort();
|
|
@@ -13497,7 +13666,8 @@ function createEmbeddedEngine(opts) {
|
|
|
13497
13666
|
if (!tool) return Promise.reject(new Error(`unknown tool: ${name}`));
|
|
13498
13667
|
return Promise.resolve(tool.handler(args));
|
|
13499
13668
|
};
|
|
13500
|
-
const
|
|
13669
|
+
const liveRuns = /* @__PURE__ */ new Map();
|
|
13670
|
+
const run = async (name, args, onEvent, runOpts = {}) => {
|
|
13501
13671
|
const runId = nextRunId();
|
|
13502
13672
|
const started = Date.now();
|
|
13503
13673
|
const emit = (e) => {
|
|
@@ -13506,6 +13676,78 @@ function createEmbeddedEngine(opts) {
|
|
|
13506
13676
|
} catch {
|
|
13507
13677
|
}
|
|
13508
13678
|
};
|
|
13679
|
+
const ctx = {
|
|
13680
|
+
runId,
|
|
13681
|
+
emit,
|
|
13682
|
+
nextCallId,
|
|
13683
|
+
skipped: /* @__PURE__ */ new Set(),
|
|
13684
|
+
inflight: /* @__PURE__ */ new Map(),
|
|
13685
|
+
moderator: vaultId(moderator),
|
|
13686
|
+
...runOpts.callTimeoutMs && runOpts.callTimeoutMs > 0 ? { callTimeoutMs: runOpts.callTimeoutMs } : {}
|
|
13687
|
+
};
|
|
13688
|
+
liveRuns.set(runId, ctx);
|
|
13689
|
+
try {
|
|
13690
|
+
return await runContext.run(ctx, () => withProgress(runId, (n) => {
|
|
13691
|
+
if (n.params.message) emit({ type: "progress", runId, at: Date.now(), message: n.params.message });
|
|
13692
|
+
}, () => runInner(name, args, runId, started, emit)));
|
|
13693
|
+
} finally {
|
|
13694
|
+
liveRuns.delete(runId);
|
|
13695
|
+
}
|
|
13696
|
+
};
|
|
13697
|
+
const skip = (runId, provider) => {
|
|
13698
|
+
const ctx = liveRuns.get(runId);
|
|
13699
|
+
if (!ctx) return 0;
|
|
13700
|
+
ctx.skipped.add(provider);
|
|
13701
|
+
let stopped = 0;
|
|
13702
|
+
for (const call2 of ctx.inflight.values()) {
|
|
13703
|
+
if (call2.provider === provider && !exemptFromSkip(ctx, call2.provider, call2.purpose)) {
|
|
13704
|
+
call2.controller.abort("skip");
|
|
13705
|
+
stopped += 1;
|
|
13706
|
+
}
|
|
13707
|
+
}
|
|
13708
|
+
return stopped;
|
|
13709
|
+
};
|
|
13710
|
+
const ask = async (o) => {
|
|
13711
|
+
const engineName = Object.keys(built).find((n) => vaultId(n) === o.provider);
|
|
13712
|
+
const base = engineName ? built[engineName] : void 0;
|
|
13713
|
+
if (!base) {
|
|
13714
|
+
return { ok: false, text: "", json: null, model: o.model ?? "", error: `No ${o.provider} key is configured, so it can't be asked.` };
|
|
13715
|
+
}
|
|
13716
|
+
const provider = o.model && o.model !== base.model ? retargetProvider(base, o.model) : base;
|
|
13717
|
+
const maxTokens = o.maxTokens ?? 8e3;
|
|
13718
|
+
const doAsk = async () => {
|
|
13719
|
+
if (o.schema) {
|
|
13720
|
+
const res = await requestStructured(provider, o.messages, o.schema, { maxTokens, purpose: o.purpose, maxRetries: 1 });
|
|
13721
|
+
return {
|
|
13722
|
+
ok: res.obj !== null,
|
|
13723
|
+
text: res.answer.response ?? "",
|
|
13724
|
+
json: res.obj,
|
|
13725
|
+
error: res.obj !== null ? null : res.answer.error ?? res.errors.join("; ") ?? "invalid reply",
|
|
13726
|
+
model: provider.model
|
|
13727
|
+
};
|
|
13728
|
+
}
|
|
13729
|
+
const a = await askOne(provider, o.messages, { maxTokens, temperature: 0.3, purpose: o.purpose });
|
|
13730
|
+
return { ok: !a.error, text: a.response ?? "", json: null, error: a.error ?? null, model: provider.model };
|
|
13731
|
+
};
|
|
13732
|
+
if (!o.runId || !o.onEvent) return doAsk();
|
|
13733
|
+
const sink = o.onEvent;
|
|
13734
|
+
const emit = (e) => {
|
|
13735
|
+
try {
|
|
13736
|
+
sink(e);
|
|
13737
|
+
} catch {
|
|
13738
|
+
}
|
|
13739
|
+
};
|
|
13740
|
+
const ctx = {
|
|
13741
|
+
runId: o.runId,
|
|
13742
|
+
emit,
|
|
13743
|
+
nextCallId,
|
|
13744
|
+
skipped: /* @__PURE__ */ new Set(),
|
|
13745
|
+
inflight: /* @__PURE__ */ new Map(),
|
|
13746
|
+
moderator: o.provider
|
|
13747
|
+
};
|
|
13748
|
+
return runContext.run(ctx, doAsk);
|
|
13749
|
+
};
|
|
13750
|
+
const runInner = async (name, args, runId, started, emit) => {
|
|
13509
13751
|
emit({
|
|
13510
13752
|
type: "run.start",
|
|
13511
13753
|
runId,
|
|
@@ -13583,8 +13825,16 @@ function createEmbeddedEngine(opts) {
|
|
|
13583
13825
|
providers: providerIds,
|
|
13584
13826
|
models,
|
|
13585
13827
|
listTools: () => [...tools.keys()],
|
|
13828
|
+
requiredArgs: (name) => {
|
|
13829
|
+
const tool = tools.get(name);
|
|
13830
|
+
if (!tool) return null;
|
|
13831
|
+
const req = tool.inputSchema?.required;
|
|
13832
|
+
return Array.isArray(req) ? req.filter((x) => typeof x === "string") : [];
|
|
13833
|
+
},
|
|
13586
13834
|
call,
|
|
13587
13835
|
run,
|
|
13836
|
+
skip,
|
|
13837
|
+
ask,
|
|
13588
13838
|
close: async () => {
|
|
13589
13839
|
await flush().catch(() => {
|
|
13590
13840
|
});
|
|
@@ -13594,12 +13844,16 @@ function createEmbeddedEngine(opts) {
|
|
|
13594
13844
|
var __test_internals = { usageOf, textOf, errorOf, vaultId };
|
|
13595
13845
|
// Annotate the CommonJS export names for ESM import in node:
|
|
13596
13846
|
0 && (module.exports = {
|
|
13847
|
+
ACTIVITY_TEXT_CAP,
|
|
13597
13848
|
DEFAULT_EXCLUDED_PROVIDERS,
|
|
13598
13849
|
DEFAULT_FALLBACKS,
|
|
13599
13850
|
DEFAULT_MODELS,
|
|
13600
13851
|
__KEY_ENV,
|
|
13601
13852
|
__MODEL_ENV,
|
|
13602
13853
|
__test_internals,
|
|
13603
|
-
createEmbeddedEngine
|
|
13854
|
+
createEmbeddedEngine,
|
|
13855
|
+
isAlive,
|
|
13856
|
+
listProcesses,
|
|
13857
|
+
processRegistryPath
|
|
13604
13858
|
});
|
|
13605
13859
|
//# sourceMappingURL=embed.cjs.map
|