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.js
CHANGED
|
@@ -7,16 +7,17 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/entrypoints/embed.ts
|
|
10
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
10
11
|
import { existsSync as existsSync11 } from "fs";
|
|
11
|
-
import
|
|
12
|
+
import path12 from "path";
|
|
12
13
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13
14
|
|
|
14
15
|
// src/core/pricing.ts
|
|
15
16
|
import { readFileSync } from "fs";
|
|
16
|
-
function loadPricing(
|
|
17
|
+
function loadPricing(path13) {
|
|
17
18
|
let raw;
|
|
18
19
|
try {
|
|
19
|
-
raw = readFileSync(
|
|
20
|
+
raw = readFileSync(path13, "utf8");
|
|
20
21
|
} catch {
|
|
21
22
|
return {};
|
|
22
23
|
}
|
|
@@ -33,20 +34,30 @@ function modelPricing(pricing, provider, model) {
|
|
|
33
34
|
const block = pricing[provider];
|
|
34
35
|
if (!block || typeof block !== "object" || Array.isArray(block)) return null;
|
|
35
36
|
const table = block;
|
|
37
|
+
if (model.startsWith("_")) return null;
|
|
36
38
|
let entry = table[model];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
let match = "exact";
|
|
40
|
+
if (!isRates(entry)) {
|
|
41
|
+
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];
|
|
42
|
+
if (best !== void 0) {
|
|
43
|
+
entry = table[best];
|
|
44
|
+
match = "stamp";
|
|
45
|
+
}
|
|
40
46
|
}
|
|
41
|
-
if (!
|
|
47
|
+
if (!isRates(entry)) return null;
|
|
42
48
|
const e = entry;
|
|
43
49
|
return {
|
|
44
50
|
prompt_per_1k: numberOrZero(e["prompt_per_1k"]),
|
|
45
51
|
completion_per_1k: numberOrZero(e["completion_per_1k"]),
|
|
46
52
|
cached_per_1k: numberOrZero(e["cached_per_1k"]),
|
|
47
|
-
...e["estimated"] === true ? { estimated: true } : {}
|
|
53
|
+
...e["estimated"] === true ? { estimated: true } : {},
|
|
54
|
+
match
|
|
48
55
|
};
|
|
49
56
|
}
|
|
57
|
+
var DATE_STAMP = /^-\d{8}$/;
|
|
58
|
+
function isRates(v) {
|
|
59
|
+
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
60
|
+
}
|
|
50
61
|
function numberOrZero(v) {
|
|
51
62
|
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
52
63
|
if (typeof v === "string") {
|
|
@@ -126,8 +137,20 @@ var PROVIDER_CAPS = {
|
|
|
126
137
|
gemini: {
|
|
127
138
|
family: "gemini",
|
|
128
139
|
system_role: "separate",
|
|
129
|
-
|
|
130
|
-
|
|
140
|
+
// No sampling, on any Gemini model. Ignored since 3.6 Flash and rejected
|
|
141
|
+
// by upcoming models (Google, 2026-10). "model" means "omit for reasoning
|
|
142
|
+
// models", and every Gemini model is reasoning-class (below) — so this
|
|
143
|
+
// resolves to never, through the same rule the other providers use. The
|
|
144
|
+
// adapter also never sends it; this keeps the record honest for anything
|
|
145
|
+
// else that reads it.
|
|
146
|
+
supports_temperature: "model",
|
|
147
|
+
// EVERY Gemini model is reasoning-class. The old list named three
|
|
148
|
+
// families and missed gemini-3.8-flash — the DEFAULT — so the default
|
|
149
|
+
// model got the small non-reasoning budgets (768 tokens for an audit)
|
|
150
|
+
// while spending up to ~480 tokens of each call thinking. Google's docs
|
|
151
|
+
// say thinking cannot be switched off on current models, so a list of
|
|
152
|
+
// which ones think is a list that can only ever be incomplete.
|
|
153
|
+
reasoning_prefixes: ["gemini-"]
|
|
131
154
|
},
|
|
132
155
|
// Qwen's "Max" tier (qwen-v3.8, qwen-v3.7) is a standard instruct/chat
|
|
133
156
|
// model, not a visible-reasoning model like QwQ — normal temperature and
|
|
@@ -250,6 +273,73 @@ function httpFailureToProviderError(provider, status, bodyText, retryAfterS, mod
|
|
|
250
273
|
);
|
|
251
274
|
}
|
|
252
275
|
|
|
276
|
+
// src/providers/network-errors.ts
|
|
277
|
+
function codeOf(e) {
|
|
278
|
+
if (!e || typeof e !== "object") return null;
|
|
279
|
+
const c = e.code;
|
|
280
|
+
return typeof c === "string" && c.length > 0 ? c : null;
|
|
281
|
+
}
|
|
282
|
+
function rootCause(e, depth = 0) {
|
|
283
|
+
if (depth > 5 || !e || typeof e !== "object") return e;
|
|
284
|
+
const o = e;
|
|
285
|
+
if (Array.isArray(o.errors) && o.errors.length > 0) {
|
|
286
|
+
const coded = o.errors.find((x) => codeOf(x) !== null);
|
|
287
|
+
return rootCause(coded ?? o.errors[0], depth + 1);
|
|
288
|
+
}
|
|
289
|
+
if (o.cause !== void 0 && o.cause !== null) return rootCause(o.cause, depth + 1);
|
|
290
|
+
return e;
|
|
291
|
+
}
|
|
292
|
+
var BY_CODE = {
|
|
293
|
+
ENOTFOUND: { cause: "dns", detail: "the provider's hostname did not resolve \u2014 DNS, or a typo'd base URL", transient: false, kind: "network" },
|
|
294
|
+
EAI_AGAIN: { cause: "dns", detail: "DNS lookup failed temporarily \u2014 resolver or network is flapping", transient: true, kind: "network" },
|
|
295
|
+
ECONNREFUSED: { cause: "refused", detail: "the connection was refused \u2014 nothing is listening, or a proxy blocked it", transient: false, kind: "network" },
|
|
296
|
+
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" },
|
|
297
|
+
EPIPE: { cause: "reset", detail: "the connection closed while we were still writing", transient: true, kind: "network" },
|
|
298
|
+
ETIMEDOUT: { cause: "connect_timeout", detail: "the connection timed out before it was established", transient: true, kind: "timeout" },
|
|
299
|
+
EHOSTUNREACH: { cause: "unreachable", detail: "no route to the provider \u2014 VPN, or offline", transient: true, kind: "network" },
|
|
300
|
+
ENETUNREACH: { cause: "unreachable", detail: "the network is unreachable \u2014 offline, or a routing change", transient: true, kind: "network" },
|
|
301
|
+
ENETDOWN: { cause: "unreachable", detail: "the local network is down", transient: true, kind: "network" },
|
|
302
|
+
EPROTO: { cause: "tls", detail: "the TLS handshake failed \u2014 an intercepting proxy, or a protocol mismatch", transient: false, kind: "network" },
|
|
303
|
+
ERR_TLS_CERT_ALTNAME_INVALID: { cause: "tls", detail: "the certificate did not match the hostname \u2014 traffic is being intercepted", transient: false, kind: "network" },
|
|
304
|
+
CERT_HAS_EXPIRED: { cause: "tls", detail: "the server certificate has expired, or this machine's clock is wrong", transient: false, kind: "network" },
|
|
305
|
+
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" },
|
|
306
|
+
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" },
|
|
307
|
+
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" },
|
|
308
|
+
UND_ERR_BODY_TIMEOUT: { cause: "read_timeout", detail: "the response body stalled mid-stream", transient: true, kind: "timeout" },
|
|
309
|
+
UND_ERR_SOCKET: { cause: "reset", detail: "the socket closed unexpectedly", transient: true, kind: "network" },
|
|
310
|
+
UND_ERR_ABORTED: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" },
|
|
311
|
+
ABORT_ERR: { cause: "aborted", detail: "the request was cancelled", transient: false, kind: "network" }
|
|
312
|
+
};
|
|
313
|
+
function diagnoseNetworkError(e) {
|
|
314
|
+
const root = rootCause(e);
|
|
315
|
+
const code = codeOf(root) ?? codeOf(e);
|
|
316
|
+
if (code && BY_CODE[code]) return { ...BY_CODE[code], code };
|
|
317
|
+
const name = root && typeof root === "object" ? root.name : void 0;
|
|
318
|
+
if (name === "AbortError" || name === "TimeoutError") {
|
|
319
|
+
return {
|
|
320
|
+
cause: name === "TimeoutError" ? "read_timeout" : "aborted",
|
|
321
|
+
code: code ?? String(name),
|
|
322
|
+
detail: name === "TimeoutError" ? "the request exceeded its timeout" : "the request was cancelled",
|
|
323
|
+
transient: name === "TimeoutError",
|
|
324
|
+
kind: name === "TimeoutError" ? "timeout" : "network"
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
cause: "unknown",
|
|
329
|
+
code,
|
|
330
|
+
detail: code ? `the connection failed with ${code}` : "the connection failed and the underlying error carried no code",
|
|
331
|
+
transient: true,
|
|
332
|
+
kind: "network"
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function looksLikeNetworkFailure(d) {
|
|
336
|
+
return d.code !== null || d.cause !== "unknown";
|
|
337
|
+
}
|
|
338
|
+
function networkErrorMessage(provider, d) {
|
|
339
|
+
const code = d.code ? ` [${d.code}]` : "";
|
|
340
|
+
return `${provider}: ${d.detail}${code}`;
|
|
341
|
+
}
|
|
342
|
+
|
|
253
343
|
// src/providers/retry.ts
|
|
254
344
|
var override = null;
|
|
255
345
|
function resolveRetryConfig() {
|
|
@@ -402,6 +492,52 @@ function rejectsDisabledThinking(model) {
|
|
|
402
492
|
const m = model.toLowerCase();
|
|
403
493
|
return ADAPTIVE_THINKING_PREFIXES.some((p) => m.startsWith(p));
|
|
404
494
|
}
|
|
495
|
+
var NO_FORCED_TOOL_PREFIXES = [
|
|
496
|
+
"claude-fable-5-1",
|
|
497
|
+
"claude-mythos-5-1",
|
|
498
|
+
"claude-opus-5-5",
|
|
499
|
+
"claude-sonnet-5-5"
|
|
500
|
+
];
|
|
501
|
+
function rejectsForcedToolUse(model) {
|
|
502
|
+
const m = model.toLowerCase();
|
|
503
|
+
return NO_FORCED_TOOL_PREFIXES.some((p) => m.startsWith(p));
|
|
504
|
+
}
|
|
505
|
+
var UNSUPPORTED_SCHEMA_KEYS = /* @__PURE__ */ new Set([
|
|
506
|
+
"minimum",
|
|
507
|
+
"maximum",
|
|
508
|
+
"exclusiveMinimum",
|
|
509
|
+
"exclusiveMaximum",
|
|
510
|
+
"multipleOf",
|
|
511
|
+
"minLength",
|
|
512
|
+
"maxLength",
|
|
513
|
+
"pattern",
|
|
514
|
+
"minItems",
|
|
515
|
+
"maxItems",
|
|
516
|
+
"uniqueItems",
|
|
517
|
+
"minProperties",
|
|
518
|
+
"maxProperties",
|
|
519
|
+
"$schema"
|
|
520
|
+
]);
|
|
521
|
+
function toStructuredOutputSchema(schema) {
|
|
522
|
+
const walk = (node) => {
|
|
523
|
+
if (Array.isArray(node)) return node.map(walk);
|
|
524
|
+
if (!node || typeof node !== "object") return node;
|
|
525
|
+
const out = {};
|
|
526
|
+
for (const [k, v] of Object.entries(node)) {
|
|
527
|
+
if (UNSUPPORTED_SCHEMA_KEYS.has(k)) continue;
|
|
528
|
+
if (k === "properties" && v && typeof v === "object") {
|
|
529
|
+
out[k] = Object.fromEntries(Object.entries(v).map(([pk, pv]) => [pk, walk(pv)]));
|
|
530
|
+
} else if (["items", "anyOf", "allOf", "oneOf", "not", "$defs", "definitions"].includes(k)) {
|
|
531
|
+
out[k] = k === "$defs" || k === "definitions" ? Object.fromEntries(Object.entries(v ?? {}).map(([dk, dv]) => [dk, walk(dv)])) : walk(v);
|
|
532
|
+
} else {
|
|
533
|
+
out[k] = v;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
if (out["type"] === "object" || "properties" in out) out["additionalProperties"] = false;
|
|
537
|
+
return out;
|
|
538
|
+
};
|
|
539
|
+
return walk(schema);
|
|
540
|
+
}
|
|
405
541
|
var ANTHROPIC_STRUCTURED_TOOL_NAME = "structured_output";
|
|
406
542
|
function applyPromptCaching(body, env = process.env) {
|
|
407
543
|
const flag = (env["CROSSCHECK_ANTHROPIC_PROMPT_CACHE"] ?? "").trim();
|
|
@@ -453,7 +589,12 @@ function buildAnthropicRequest(opts) {
|
|
|
453
589
|
body.thinking = { type: "disabled" };
|
|
454
590
|
}
|
|
455
591
|
}
|
|
456
|
-
if (opts.jsonSchema) {
|
|
592
|
+
if (opts.jsonSchema && rejectsForcedToolUse(opts.model)) {
|
|
593
|
+
body.output_config = {
|
|
594
|
+
...body.output_config ?? {},
|
|
595
|
+
format: { type: "json_schema", schema: toStructuredOutputSchema(opts.jsonSchema) }
|
|
596
|
+
};
|
|
597
|
+
} else if (opts.jsonSchema) {
|
|
457
598
|
body.tools = [{
|
|
458
599
|
name: ANTHROPIC_STRUCTURED_TOOL_NAME,
|
|
459
600
|
description: "Emit a single JSON object matching the requested schema.",
|
|
@@ -572,7 +713,11 @@ async function sendAnthropic(args) {
|
|
|
572
713
|
try {
|
|
573
714
|
respLike = await doFetch(url, init);
|
|
574
715
|
} catch (e) {
|
|
575
|
-
|
|
716
|
+
const d = diagnoseNetworkError(e);
|
|
717
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
718
|
+
throw new ProviderError(d.kind, networkErrorMessage("anthropic", d), {
|
|
719
|
+
transient: d.transient
|
|
720
|
+
});
|
|
576
721
|
}
|
|
577
722
|
const status = respLike.status;
|
|
578
723
|
if (status >= 200 && status < 300) {
|
|
@@ -645,6 +790,11 @@ function jsonSchemaToGeminiSchema(schema) {
|
|
|
645
790
|
}
|
|
646
791
|
return out;
|
|
647
792
|
}
|
|
793
|
+
var GEMINI_THINKING_HEADROOM_TOKENS = 16384;
|
|
794
|
+
function thinkingHeadroom() {
|
|
795
|
+
const raw = Number(process.env["CROSSCHECK_GEMINI_THINKING_HEADROOM_TOKENS"]);
|
|
796
|
+
return Number.isFinite(raw) && raw >= 0 ? Math.trunc(raw) : GEMINI_THINKING_HEADROOM_TOKENS;
|
|
797
|
+
}
|
|
648
798
|
function buildGeminiRequest(opts) {
|
|
649
799
|
const contents = [];
|
|
650
800
|
let systemText = null;
|
|
@@ -663,8 +813,9 @@ function buildGeminiRequest(opts) {
|
|
|
663
813
|
const body = {
|
|
664
814
|
contents,
|
|
665
815
|
generationConfig: {
|
|
666
|
-
|
|
667
|
-
|
|
816
|
+
// Answer budget + thinking headroom. No temperature / topP / topK /
|
|
817
|
+
// thinkingBudget, on any model — see the header note.
|
|
818
|
+
maxOutputTokens: opts.maxTokens + thinkingHeadroom()
|
|
668
819
|
}
|
|
669
820
|
};
|
|
670
821
|
if (systemText !== null && systemText !== "") {
|
|
@@ -674,8 +825,8 @@ function buildGeminiRequest(opts) {
|
|
|
674
825
|
body.generationConfig.responseMimeType = "application/json";
|
|
675
826
|
body.generationConfig.responseSchema = jsonSchemaToGeminiSchema(opts.jsonSchema);
|
|
676
827
|
}
|
|
677
|
-
const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent
|
|
678
|
-
return { url, headers: {}, body };
|
|
828
|
+
const url = `${GEMINI_API_URL_BASE}/${encodeURIComponent(opts.model)}:generateContent`;
|
|
829
|
+
return { url, headers: { "x-goog-api-key": opts.apiKey }, body };
|
|
679
830
|
}
|
|
680
831
|
function parseGeminiResponse(opts) {
|
|
681
832
|
const r = opts.resp ?? {};
|
|
@@ -705,16 +856,19 @@ function parseGeminiResponse(opts) {
|
|
|
705
856
|
}
|
|
706
857
|
try {
|
|
707
858
|
const first = cands[0];
|
|
708
|
-
const
|
|
709
|
-
const
|
|
859
|
+
const finishReason = typeof first["finishReason"] === "string" ? first["finishReason"] : void 0;
|
|
860
|
+
const content = first["content"] ?? {};
|
|
861
|
+
const parts = Array.isArray(content["parts"]) ? content["parts"] : [];
|
|
710
862
|
let text = "";
|
|
711
863
|
for (const p of parts) {
|
|
712
864
|
if (p && typeof p === "object") {
|
|
713
|
-
const
|
|
865
|
+
const part = p;
|
|
866
|
+
if (part["thought"] === true) continue;
|
|
867
|
+
const t = part["text"];
|
|
714
868
|
if (typeof t === "string") text += t;
|
|
715
869
|
}
|
|
716
870
|
}
|
|
717
|
-
return { text, usage };
|
|
871
|
+
return { text, usage, ...finishReason ? { finishReason } : {} };
|
|
718
872
|
} catch (e) {
|
|
719
873
|
throw new ProviderError(
|
|
720
874
|
"parse",
|
|
@@ -743,7 +897,8 @@ async function sendGemini(args) {
|
|
|
743
897
|
apiKey: args.apiKey,
|
|
744
898
|
messages: args.messages,
|
|
745
899
|
maxTokens: args.maxTokens,
|
|
746
|
-
|
|
900
|
+
// args.temperature is deliberately NOT forwarded: Gemini ignores it and
|
|
901
|
+
// upcoming models reject it. See the header note.
|
|
747
902
|
...args.jsonSchema ? { jsonSchema: args.jsonSchema } : {}
|
|
748
903
|
});
|
|
749
904
|
const doFetch = args.fetchImpl ?? globalThis.fetch;
|
|
@@ -758,7 +913,11 @@ async function sendGemini(args) {
|
|
|
758
913
|
try {
|
|
759
914
|
respLike = await doFetch(url, init);
|
|
760
915
|
} catch (e) {
|
|
761
|
-
|
|
916
|
+
const d = diagnoseNetworkError(e);
|
|
917
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
918
|
+
throw new ProviderError(d.kind, networkErrorMessage("gemini", d), {
|
|
919
|
+
transient: d.transient
|
|
920
|
+
});
|
|
762
921
|
}
|
|
763
922
|
const status = respLike.status;
|
|
764
923
|
if (status >= 200 && status < 300) {
|
|
@@ -768,11 +927,18 @@ async function sendGemini(args) {
|
|
|
768
927
|
} catch (e) {
|
|
769
928
|
throw new ProviderError("parse", `gemini: response body not JSON: ${e.message}`);
|
|
770
929
|
}
|
|
771
|
-
const { text, usage } = parseGeminiResponse({
|
|
930
|
+
const { text, usage, finishReason } = parseGeminiResponse({
|
|
772
931
|
resp: parsed,
|
|
773
932
|
model: args.model,
|
|
774
933
|
purpose: args.purpose ?? "worker"
|
|
775
934
|
});
|
|
935
|
+
if (text.trim() === "" && finishReason === "MAX_TOKENS") {
|
|
936
|
+
throw new ProviderError(
|
|
937
|
+
"parse",
|
|
938
|
+
`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.`,
|
|
939
|
+
{ transient: false }
|
|
940
|
+
);
|
|
941
|
+
}
|
|
776
942
|
return { text, attempts: 1, usage: applyPricing2(usage, args.pricing) };
|
|
777
943
|
}
|
|
778
944
|
const bodyText = await respLike.text().catch(() => "");
|
|
@@ -829,7 +995,15 @@ function buildOpenAICompatibleRequest(opts) {
|
|
|
829
995
|
json_schema: {
|
|
830
996
|
name: "structured_output",
|
|
831
997
|
schema: opts.jsonSchema,
|
|
832
|
-
strict:
|
|
998
|
+
// NOT strict. Strict mode requires `additionalProperties: false` on
|
|
999
|
+
// every object and every property listed in `required` — the
|
|
1000
|
+
// engine's schemas don't meet that, so every structured OpenAI call
|
|
1001
|
+
// (planner, judges, synthesis) was a 400, unnoticed until the canary
|
|
1002
|
+
// grew a structured check (2026-10-11). Non-strict still shapes the
|
|
1003
|
+
// reply to the schema, and structured.ts validates it against the
|
|
1004
|
+
// full schema regardless, so strictness added a failure mode and no
|
|
1005
|
+
// safety.
|
|
1006
|
+
strict: false
|
|
833
1007
|
}
|
|
834
1008
|
};
|
|
835
1009
|
}
|
|
@@ -939,7 +1113,11 @@ async function sendOpenAICompatible(args) {
|
|
|
939
1113
|
try {
|
|
940
1114
|
respLike = await doFetch(url, init);
|
|
941
1115
|
} catch (e) {
|
|
942
|
-
|
|
1116
|
+
const d = diagnoseNetworkError(e);
|
|
1117
|
+
if (!looksLikeNetworkFailure(d)) throw e;
|
|
1118
|
+
throw new ProviderError(d.kind, networkErrorMessage(args.provider, d), {
|
|
1119
|
+
transient: d.transient
|
|
1120
|
+
});
|
|
943
1121
|
}
|
|
944
1122
|
const status = respLike.status;
|
|
945
1123
|
if (status >= 200 && status < 300) {
|
|
@@ -1113,7 +1291,7 @@ import { z } from "zod";
|
|
|
1113
1291
|
|
|
1114
1292
|
// src/server-meta.ts
|
|
1115
1293
|
var SERVER_NAME = "crosscheck-agent";
|
|
1116
|
-
var SERVER_VERSION = true ? "0.2.
|
|
1294
|
+
var SERVER_VERSION = true ? "0.2.29" : "0.0.0-dev";
|
|
1117
1295
|
|
|
1118
1296
|
// src/tools/audit.ts
|
|
1119
1297
|
import { readdirSync, readFileSync as readFileSync3, statSync } from "fs";
|
|
@@ -1174,27 +1352,27 @@ function extractJson(text) {
|
|
|
1174
1352
|
}
|
|
1175
1353
|
|
|
1176
1354
|
// src/core/json-schema.ts
|
|
1177
|
-
function validateSchema(value, schema,
|
|
1355
|
+
function validateSchema(value, schema, path13 = "") {
|
|
1178
1356
|
const errs = [];
|
|
1179
1357
|
if ("anyOf" in schema) {
|
|
1180
1358
|
const subs = schema["anyOf"].map(
|
|
1181
|
-
(s) => validateSchema(value, s,
|
|
1359
|
+
(s) => validateSchema(value, s, path13)
|
|
1182
1360
|
);
|
|
1183
1361
|
if (!subs.some((e) => e.length === 0)) {
|
|
1184
|
-
errs.push(`${
|
|
1362
|
+
errs.push(`${path13 || "<root>"}: did not match anyOf`);
|
|
1185
1363
|
}
|
|
1186
1364
|
return errs;
|
|
1187
1365
|
}
|
|
1188
1366
|
if ("oneOf" in schema) {
|
|
1189
|
-
const passed = schema["oneOf"].filter((s) => validateSchema(value, s,
|
|
1367
|
+
const passed = schema["oneOf"].filter((s) => validateSchema(value, s, path13).length === 0).length;
|
|
1190
1368
|
if (passed !== 1) {
|
|
1191
|
-
errs.push(`${
|
|
1369
|
+
errs.push(`${path13 || "<root>"}: matched ${passed} of oneOf, expected 1`);
|
|
1192
1370
|
}
|
|
1193
1371
|
return errs;
|
|
1194
1372
|
}
|
|
1195
1373
|
if ("const" in schema && !deepEqual(value, schema["const"])) {
|
|
1196
1374
|
errs.push(
|
|
1197
|
-
`${
|
|
1375
|
+
`${path13 || "<root>"}: expected const ${pyRepr(schema["const"])}, got ${pyRepr(value)}`
|
|
1198
1376
|
);
|
|
1199
1377
|
return errs;
|
|
1200
1378
|
}
|
|
@@ -1204,7 +1382,7 @@ function validateSchema(value, schema, path12 = "") {
|
|
|
1204
1382
|
const ok = types.some((tt) => matchesType(value, String(tt)));
|
|
1205
1383
|
if (!ok) {
|
|
1206
1384
|
errs.push(
|
|
1207
|
-
`${
|
|
1385
|
+
`${path13 || "<root>"}: expected type ${pyReprType(t)}, got ${pyTypeName(value)}`
|
|
1208
1386
|
);
|
|
1209
1387
|
return errs;
|
|
1210
1388
|
}
|
|
@@ -1213,29 +1391,29 @@ function validateSchema(value, schema, path12 = "") {
|
|
|
1213
1391
|
if ("enum" in schema) {
|
|
1214
1392
|
const en = schema["enum"];
|
|
1215
1393
|
if (!en.some((x) => deepEqual(x, value))) {
|
|
1216
|
-
errs.push(`${
|
|
1394
|
+
errs.push(`${path13 || "<root>"}: value ${pyRepr(value)} not in enum`);
|
|
1217
1395
|
}
|
|
1218
1396
|
}
|
|
1219
1397
|
if ("minLength" in schema && value.length < schema["minLength"]) {
|
|
1220
|
-
errs.push(`${
|
|
1398
|
+
errs.push(`${path13 || "<root>"}: shorter than minLength ${schema["minLength"]}`);
|
|
1221
1399
|
}
|
|
1222
1400
|
}
|
|
1223
1401
|
if (typeof value === "number" && !Number.isNaN(value)) {
|
|
1224
1402
|
if ("minimum" in schema && value < schema["minimum"]) {
|
|
1225
|
-
errs.push(`${
|
|
1403
|
+
errs.push(`${path13 || "<root>"}: ${value} < minimum ${schema["minimum"]}`);
|
|
1226
1404
|
}
|
|
1227
1405
|
if ("maximum" in schema && value > schema["maximum"]) {
|
|
1228
|
-
errs.push(`${
|
|
1406
|
+
errs.push(`${path13 || "<root>"}: ${value} > maximum ${schema["maximum"]}`);
|
|
1229
1407
|
}
|
|
1230
1408
|
}
|
|
1231
1409
|
if (Array.isArray(value)) {
|
|
1232
1410
|
if ("minItems" in schema && value.length < schema["minItems"]) {
|
|
1233
|
-
errs.push(`${
|
|
1411
|
+
errs.push(`${path13 || "<root>"}: fewer items than minItems ${schema["minItems"]}`);
|
|
1234
1412
|
}
|
|
1235
1413
|
const itemSchema = schema["items"];
|
|
1236
1414
|
if (isObj(itemSchema)) {
|
|
1237
1415
|
for (let i = 0; i < value.length; i++) {
|
|
1238
|
-
errs.push(...validateSchema(value[i], itemSchema, `${
|
|
1416
|
+
errs.push(...validateSchema(value[i], itemSchema, `${path13}[${i}]`));
|
|
1239
1417
|
}
|
|
1240
1418
|
}
|
|
1241
1419
|
}
|
|
@@ -1244,19 +1422,19 @@ function validateSchema(value, schema, path12 = "") {
|
|
|
1244
1422
|
const required = schema["required"] ?? [];
|
|
1245
1423
|
for (const r of required) {
|
|
1246
1424
|
if (!(r in value)) {
|
|
1247
|
-
errs.push(`${
|
|
1425
|
+
errs.push(`${path13 || "<root>"}: missing required key ${pyRepr(r)}`);
|
|
1248
1426
|
}
|
|
1249
1427
|
}
|
|
1250
1428
|
if (schema["additionalProperties"] === false) {
|
|
1251
1429
|
for (const k of Object.keys(value)) {
|
|
1252
1430
|
if (!(k in props)) {
|
|
1253
|
-
errs.push(`${
|
|
1431
|
+
errs.push(`${path13 || "<root>"}: unknown key ${pyRepr(k)}`);
|
|
1254
1432
|
}
|
|
1255
1433
|
}
|
|
1256
1434
|
}
|
|
1257
1435
|
for (const [k, v] of Object.entries(value)) {
|
|
1258
1436
|
const ps = props[k];
|
|
1259
|
-
if (ps) errs.push(...validateSchema(v, ps,
|
|
1437
|
+
if (ps) errs.push(...validateSchema(v, ps, path13 ? `${path13}.${k}` : k));
|
|
1260
1438
|
}
|
|
1261
1439
|
}
|
|
1262
1440
|
return errs;
|
|
@@ -1336,6 +1514,31 @@ function pyReprType(t) {
|
|
|
1336
1514
|
return String(t);
|
|
1337
1515
|
}
|
|
1338
1516
|
|
|
1517
|
+
// src/core/session.ts
|
|
1518
|
+
import { randomUUID } from "crypto";
|
|
1519
|
+
var processSessionId = null;
|
|
1520
|
+
var startedAt = null;
|
|
1521
|
+
function engineSessionId() {
|
|
1522
|
+
if (processSessionId === null) {
|
|
1523
|
+
processSessionId = randomUUID();
|
|
1524
|
+
startedAt = Date.now();
|
|
1525
|
+
}
|
|
1526
|
+
return processSessionId;
|
|
1527
|
+
}
|
|
1528
|
+
function resolveSessionId(callerSupplied) {
|
|
1529
|
+
const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
|
|
1530
|
+
return trimmed.length > 0 ? trimmed : engineSessionId();
|
|
1531
|
+
}
|
|
1532
|
+
function localSessionRecordingEnabled(env = globalThis.process?.env ?? {}) {
|
|
1533
|
+
const v = (env["CROSSCHECK_RECORD_SESSIONS"] ?? "").trim().toLowerCase();
|
|
1534
|
+
return !["0", "false", "off", "no"].includes(v);
|
|
1535
|
+
}
|
|
1536
|
+
function recordingSessionId(callerSupplied) {
|
|
1537
|
+
if (localSessionRecordingEnabled()) return resolveSessionId(callerSupplied);
|
|
1538
|
+
const trimmed = typeof callerSupplied === "string" ? callerSupplied.trim() : "";
|
|
1539
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1339
1542
|
// src/core/usage.ts
|
|
1340
1543
|
function emptyUsage(provider, model, purpose = "worker") {
|
|
1341
1544
|
return {
|
|
@@ -1441,11 +1644,11 @@ function withCommas(n) {
|
|
|
1441
1644
|
function renderRunSummary(opts) {
|
|
1442
1645
|
const endedAt = opts.endedAtS ?? Math.trunc(Date.now() / 1e3);
|
|
1443
1646
|
let scope = "call";
|
|
1444
|
-
let
|
|
1647
|
+
let startedAt2 = null;
|
|
1445
1648
|
let rows = [];
|
|
1446
1649
|
if (opts.sessionScope && opts.sessionScope.rows.length > 0) {
|
|
1447
1650
|
scope = "session";
|
|
1448
|
-
|
|
1651
|
+
startedAt2 = opts.sessionScope.startedAt;
|
|
1449
1652
|
rows = opts.sessionScope.rows.map((r) => ({ ...r }));
|
|
1450
1653
|
} else {
|
|
1451
1654
|
const byPurpose = /* @__PURE__ */ new Map();
|
|
@@ -1476,6 +1679,7 @@ function renderRunSummary(opts) {
|
|
|
1476
1679
|
row.cpu_ms += a.cpu_ms ?? 0;
|
|
1477
1680
|
if (a.cache_hit) row.cache_hits += 1;
|
|
1478
1681
|
if (a.error) row.errors += 1;
|
|
1682
|
+
if (a.usage?.estimated) row.estimated = true;
|
|
1479
1683
|
}
|
|
1480
1684
|
rows = Array.from(byPurpose.values());
|
|
1481
1685
|
}
|
|
@@ -1488,16 +1692,18 @@ function renderRunSummary(opts) {
|
|
|
1488
1692
|
wall_ms: rows.reduce((s, r) => s + r.wall_ms, 0),
|
|
1489
1693
|
cpu_ms: rows.reduce((s, r) => s + r.cpu_ms, 0),
|
|
1490
1694
|
cache_hits: rows.reduce((s, r) => s + r.cache_hits, 0),
|
|
1491
|
-
errors: rows.reduce((s, r) => s + r.errors, 0)
|
|
1695
|
+
errors: rows.reduce((s, r) => s + r.errors, 0),
|
|
1696
|
+
...rows.some((r) => r.estimated) ? { estimated: true } : {}
|
|
1492
1697
|
};
|
|
1493
1698
|
const titleLeft = scope === "session" ? `session: ${opts.sessionId ?? ""}` : `call: ${opts.toolName}`;
|
|
1494
|
-
const
|
|
1699
|
+
const costText = totals.estimated ? `$${totals.cost_usd.toFixed(4)}+ (some calls unpriced)` : `$${totals.cost_usd.toFixed(4)}`;
|
|
1700
|
+
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)`;
|
|
1495
1701
|
const bodyLines = [];
|
|
1496
1702
|
for (let i = 0; i < rows.length; i++) {
|
|
1497
1703
|
const r = rows[i];
|
|
1498
1704
|
const glyph = i === rows.length - 1 ? "`-" : "|-";
|
|
1499
1705
|
bodyLines.push(
|
|
1500
|
-
`${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)`
|
|
1706
|
+
`${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)`
|
|
1501
1707
|
);
|
|
1502
1708
|
}
|
|
1503
1709
|
const callByModel = rollupSpendByModel(
|
|
@@ -1545,7 +1751,7 @@ function renderRunSummary(opts) {
|
|
|
1545
1751
|
tool: opts.toolName,
|
|
1546
1752
|
scope,
|
|
1547
1753
|
currency: "USD",
|
|
1548
|
-
started_at:
|
|
1754
|
+
started_at: startedAt2,
|
|
1549
1755
|
ended_at: endedAt,
|
|
1550
1756
|
rows,
|
|
1551
1757
|
totals,
|
|
@@ -1670,14 +1876,15 @@ async function attachUsageBlock(result, answers, opts) {
|
|
|
1670
1876
|
delete result["_suppress_run_summary"];
|
|
1671
1877
|
}
|
|
1672
1878
|
async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
|
|
1673
|
-
|
|
1879
|
+
const sid = recordingSessionId(sessionId);
|
|
1880
|
+
if (!sid || answers.length === 0) return;
|
|
1674
1881
|
const now = nowS ?? Math.trunc(Date.now() / 1e3);
|
|
1675
1882
|
const rows = [];
|
|
1676
1883
|
for (const a of answers) {
|
|
1677
1884
|
const u = a.usage;
|
|
1678
1885
|
if (!u || typeof u.provider !== "string" || u.provider === "") continue;
|
|
1679
1886
|
rows.push({
|
|
1680
|
-
session_id:
|
|
1887
|
+
session_id: sid,
|
|
1681
1888
|
ts: now,
|
|
1682
1889
|
tool: toolName,
|
|
1683
1890
|
purpose: u.purpose ?? "worker",
|
|
@@ -1700,13 +1907,14 @@ async function appendUsageLog(storage, sessionId, toolName, answers, nowS) {
|
|
|
1700
1907
|
}
|
|
1701
1908
|
}
|
|
1702
1909
|
async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, nowS) {
|
|
1703
|
-
|
|
1910
|
+
const sid = recordingSessionId(sessionId);
|
|
1911
|
+
if (!sid) return;
|
|
1704
1912
|
const now = nowS ?? Math.trunc(Date.now() / 1e3);
|
|
1705
1913
|
try {
|
|
1706
|
-
let existing = await storage.getSession(
|
|
1914
|
+
let existing = await storage.getSession(sid);
|
|
1707
1915
|
if (!existing) {
|
|
1708
1916
|
await storage.upsertSession({
|
|
1709
|
-
session_id:
|
|
1917
|
+
session_id: sid,
|
|
1710
1918
|
started_at: now,
|
|
1711
1919
|
last_at: now,
|
|
1712
1920
|
calls: 0,
|
|
@@ -1719,7 +1927,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
|
|
|
1719
1927
|
total_cost_usd: 0,
|
|
1720
1928
|
total_cpu_ms: 0
|
|
1721
1929
|
});
|
|
1722
|
-
existing = await storage.getSession(
|
|
1930
|
+
existing = await storage.getSession(sid);
|
|
1723
1931
|
}
|
|
1724
1932
|
if (!existing) return;
|
|
1725
1933
|
let promptDelta = 0;
|
|
@@ -1739,7 +1947,7 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
|
|
|
1739
1947
|
}
|
|
1740
1948
|
if (a.cache_hit) cacheHitDelta += 1;
|
|
1741
1949
|
}
|
|
1742
|
-
await storage.accumulateSessionTotals(
|
|
1950
|
+
await storage.accumulateSessionTotals(sid, {
|
|
1743
1951
|
calls: answers.length,
|
|
1744
1952
|
wall_ms: wallMs,
|
|
1745
1953
|
cache_hits: cacheHitDelta,
|
|
@@ -4671,10 +4879,6 @@ If you need supporting evidence, you may emit ONE \`<tool_call>...</tool_call>\`
|
|
|
4671
4879
|
}
|
|
4672
4880
|
|
|
4673
4881
|
// src/tools/confer.ts
|
|
4674
|
-
var DEFERRED_OPTS = [
|
|
4675
|
-
// empty — every confer opt runs natively except worker_tools, which
|
|
4676
|
-
// is gated below (non-empty list → defer).
|
|
4677
|
-
];
|
|
4678
4882
|
async function runConfer(args, opts) {
|
|
4679
4883
|
const callStartedWall = performance3.now();
|
|
4680
4884
|
const callStartedCpu = process.cpuUsage();
|
|
@@ -4690,16 +4894,11 @@ async function runConfer(args, opts) {
|
|
|
4690
4894
|
rejectedWorkerTools.push(t);
|
|
4691
4895
|
}
|
|
4692
4896
|
}
|
|
4693
|
-
|
|
4694
|
-
const needsBridge = DEFERRED_OPTS.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
4695
|
-
if (needsBridge) {
|
|
4696
|
-
if (opts.bridge && opts.bridge.toolNames.has("confer")) {
|
|
4697
|
-
return await deferConfer(args, opts.bridge);
|
|
4698
|
-
}
|
|
4897
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
4699
4898
|
return errorEnvelope2(
|
|
4700
4899
|
"CONFER_OPT_NOT_NATIVE",
|
|
4701
4900
|
"worker_tools requested but innerCallers are not wired",
|
|
4702
|
-
"Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host
|
|
4901
|
+
"Native confer covers untrusted_input + early_stop + extract_claims + inject_session_memory + auto_panel. worker_tools needs innerCallers wired by the host."
|
|
4703
4902
|
);
|
|
4704
4903
|
}
|
|
4705
4904
|
const question = typeof args["question"] === "string" ? args["question"] : String(args["question"] ?? "");
|
|
@@ -5050,21 +5249,6 @@ function unknownProviderError(unknownNames, available) {
|
|
|
5050
5249
|
available_now: Object.keys(available).sort()
|
|
5051
5250
|
};
|
|
5052
5251
|
}
|
|
5053
|
-
async function deferConfer(args, bridge) {
|
|
5054
|
-
const r = await bridge.callTool("confer", args);
|
|
5055
|
-
const text = r.content[0]?.text;
|
|
5056
|
-
if (typeof text === "string") {
|
|
5057
|
-
try {
|
|
5058
|
-
return JSON.parse(text);
|
|
5059
|
-
} catch {
|
|
5060
|
-
}
|
|
5061
|
-
}
|
|
5062
|
-
return errorEnvelope2(
|
|
5063
|
-
"CONFER_BRIDGE_BAD_ENVELOPE",
|
|
5064
|
-
"bridge returned an unparseable envelope for confer",
|
|
5065
|
-
"Check that the Python child is healthy."
|
|
5066
|
-
);
|
|
5067
|
-
}
|
|
5068
5252
|
function errorEnvelope2(code, message, hint) {
|
|
5069
5253
|
return {
|
|
5070
5254
|
tool: "confer",
|
|
@@ -5436,7 +5620,7 @@ function errorEnvelope3(code, message, hint) {
|
|
|
5436
5620
|
transient: false
|
|
5437
5621
|
};
|
|
5438
5622
|
}
|
|
5439
|
-
async function runVerify(args,
|
|
5623
|
+
async function runVerify(args, fetchConfig) {
|
|
5440
5624
|
const checks = args["checks"];
|
|
5441
5625
|
if (!Array.isArray(checks) || checks.length === 0) {
|
|
5442
5626
|
return {
|
|
@@ -5448,7 +5632,6 @@ async function runVerify(args, bridge, fetchConfig) {
|
|
|
5448
5632
|
)
|
|
5449
5633
|
};
|
|
5450
5634
|
}
|
|
5451
|
-
void bridge;
|
|
5452
5635
|
const allowShell = Boolean(args["allow_shell"] ?? false);
|
|
5453
5636
|
const wallStart = performance4.now();
|
|
5454
5637
|
const cpuStart = process.cpuUsage();
|
|
@@ -5750,7 +5933,6 @@ async function runBench(args, opts) {
|
|
|
5750
5933
|
const innerOpts = {
|
|
5751
5934
|
providers: opts.providers,
|
|
5752
5935
|
allowlist: opts.allowlist ?? null,
|
|
5753
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
5754
5936
|
...opts.moderator ? { moderator: opts.moderator } : {}
|
|
5755
5937
|
};
|
|
5756
5938
|
let inner;
|
|
@@ -6212,6 +6394,19 @@ import { performance as performance7 } from "perf_hooks";
|
|
|
6212
6394
|
import { AsyncLocalStorage } from "async_hooks";
|
|
6213
6395
|
import { performance as performance6 } from "perf_hooks";
|
|
6214
6396
|
var progressStorage = new AsyncLocalStorage();
|
|
6397
|
+
async function withProgress(token, sendNotification, fn) {
|
|
6398
|
+
if (token === void 0 || token === null) {
|
|
6399
|
+
return fn();
|
|
6400
|
+
}
|
|
6401
|
+
const ctx = {
|
|
6402
|
+
token,
|
|
6403
|
+
wallStart: performance6.now(),
|
|
6404
|
+
cpuStart: process.cpuUsage(),
|
|
6405
|
+
step: { value: 0 },
|
|
6406
|
+
sendNotification
|
|
6407
|
+
};
|
|
6408
|
+
return progressStorage.run(ctx, fn);
|
|
6409
|
+
}
|
|
6215
6410
|
async function emitProgress(message, opts) {
|
|
6216
6411
|
const ctx = progressStorage.getStore();
|
|
6217
6412
|
const wallStart = ctx ? ctx.wallStart : performance6.now();
|
|
@@ -6382,11 +6577,11 @@ function getNodeCache(cfg, repoRoot, key, nowMs) {
|
|
|
6382
6577
|
return null;
|
|
6383
6578
|
}
|
|
6384
6579
|
}
|
|
6385
|
-
function atomicWriteJson(
|
|
6386
|
-
mkdirSync3(dirname(
|
|
6387
|
-
const tmp = `${
|
|
6580
|
+
function atomicWriteJson(path13, payload) {
|
|
6581
|
+
mkdirSync3(dirname(path13), { recursive: true });
|
|
6582
|
+
const tmp = `${path13}.${process.pid}.${Date.now()}.tmp`;
|
|
6388
6583
|
writeFileSync3(tmp, JSON.stringify(payload), "utf8");
|
|
6389
|
-
renameSync(tmp,
|
|
6584
|
+
renameSync(tmp, path13);
|
|
6390
6585
|
}
|
|
6391
6586
|
function putNodeCache(cfg, repoRoot, key, value) {
|
|
6392
6587
|
if (!cfg || cfg.enabled === false) return;
|
|
@@ -6444,7 +6639,6 @@ var EST_TOKENS = {
|
|
|
6444
6639
|
med: [1500, 800],
|
|
6445
6640
|
high: [2500, 1500]
|
|
6446
6641
|
};
|
|
6447
|
-
var DEFERRED_OPTS2 = [];
|
|
6448
6642
|
var REACTIVE_SIGNAL_RE = /<signals>\s*(\{[\s\S]*?\})\s*<\/signals>/g;
|
|
6449
6643
|
function parseReactiveSignals(output) {
|
|
6450
6644
|
if (typeof output !== "string" || !output.includes("<signals>")) return [];
|
|
@@ -6484,17 +6678,6 @@ async function runOrchestrate(args, opts) {
|
|
|
6484
6678
|
);
|
|
6485
6679
|
if (breakerEnv) return breakerEnv;
|
|
6486
6680
|
}
|
|
6487
|
-
const needsBridge = DEFERRED_OPTS2.some((k) => Boolean(args[k]));
|
|
6488
|
-
if (needsBridge) {
|
|
6489
|
-
if (opts.bridge && opts.bridge.toolNames.has("orchestrate")) {
|
|
6490
|
-
return await deferOrchestrate(args, opts.bridge);
|
|
6491
|
-
}
|
|
6492
|
-
return errorEnvelope5(
|
|
6493
|
-
"ORCHESTRATE_OPT_NOT_NATIVE",
|
|
6494
|
-
"this orchestrate opt-in requires the Python bridge in v1",
|
|
6495
|
-
"v1 native covers the plain DAG flow + cheap_mode. reactive (mid-flight DAG updates) still defers. Set CROSSCHECK_BRIDGE_PYTHON=1 to enable."
|
|
6496
|
-
);
|
|
6497
|
-
}
|
|
6498
6681
|
const goal = typeof args["goal"] === "string" ? args["goal"] : null;
|
|
6499
6682
|
const dagIn = isObj5(args["dag"]) ? args["dag"] : null;
|
|
6500
6683
|
if (goal === null === (dagIn === null)) {
|
|
@@ -7436,21 +7619,6 @@ function resolveProviders3(names, available, allowlist) {
|
|
|
7436
7619
|
}
|
|
7437
7620
|
return out;
|
|
7438
7621
|
}
|
|
7439
|
-
async function deferOrchestrate(args, bridge) {
|
|
7440
|
-
const r = await bridge.callTool("orchestrate", args);
|
|
7441
|
-
const text = r.content[0]?.text;
|
|
7442
|
-
if (typeof text === "string") {
|
|
7443
|
-
try {
|
|
7444
|
-
return JSON.parse(text);
|
|
7445
|
-
} catch {
|
|
7446
|
-
}
|
|
7447
|
-
}
|
|
7448
|
-
return errorEnvelope5(
|
|
7449
|
-
"ORCHESTRATE_BRIDGE_BAD_ENVELOPE",
|
|
7450
|
-
"bridge returned an unparseable envelope for orchestrate",
|
|
7451
|
-
"Check that the Python child is healthy."
|
|
7452
|
-
);
|
|
7453
|
-
}
|
|
7454
7622
|
function errorEnvelope5(code, message, hint, kind = "client") {
|
|
7455
7623
|
return {
|
|
7456
7624
|
tool: "orchestrate",
|
|
@@ -7768,6 +7936,16 @@ function buildCallContext(args) {
|
|
|
7768
7936
|
var CREATE_DOC_MAX_BYTES = 32 * 1024;
|
|
7769
7937
|
var CREATE_AUDIT_THRESHOLD = 0.7;
|
|
7770
7938
|
async function runCreate(args, opts) {
|
|
7939
|
+
const subEnvelopes = [];
|
|
7940
|
+
const tracked = (fn) => async (...a) => {
|
|
7941
|
+
const out = await fn(...a);
|
|
7942
|
+
subEnvelopes.push(out);
|
|
7943
|
+
return out;
|
|
7944
|
+
};
|
|
7945
|
+
const confer = tracked(runConfer);
|
|
7946
|
+
const orchestrate = tracked(runOrchestrate);
|
|
7947
|
+
const review = tracked(runReview);
|
|
7948
|
+
const audit = tracked(runAudit);
|
|
7771
7949
|
const instruction = typeof args["instruction"] === "string" ? args["instruction"] : String(args["instruction"] ?? "");
|
|
7772
7950
|
if (!instruction) {
|
|
7773
7951
|
return errorEnvelope6(
|
|
@@ -7804,7 +7982,7 @@ ${constraints}
|
|
|
7804
7982
|
|
|
7805
7983
|
` : "") + `DOCUMENTS (${okCount} of ${descriptors.length} ingested):
|
|
7806
7984
|
${documentsPayload}`;
|
|
7807
|
-
const scope = await
|
|
7985
|
+
const scope = await confer({
|
|
7808
7986
|
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,
|
|
7809
7987
|
context: contextBlock,
|
|
7810
7988
|
...providers !== void 0 ? { providers } : {},
|
|
@@ -7813,7 +7991,6 @@ ${documentsPayload}`;
|
|
|
7813
7991
|
}, {
|
|
7814
7992
|
providers: opts.providers,
|
|
7815
7993
|
allowlist: opts.allowlist ?? null,
|
|
7816
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7817
7994
|
ctx
|
|
7818
7995
|
});
|
|
7819
7996
|
const scopeAnswer = Array.isArray(scope["answers"]) ? scope["answers"].filter((a) => typeof a["response"] === "string" && a["response"]).map((a) => `[${a["provider"]}]
|
|
@@ -7832,11 +8009,10 @@ ${scopeAnswer || "(none)"}
|
|
|
7832
8009
|
};
|
|
7833
8010
|
if (providers !== void 0) orchestrateArgs["providers"] = providers;
|
|
7834
8011
|
if (planOnly) orchestrateArgs["plan_only"] = true;
|
|
7835
|
-
let orchestration = await
|
|
8012
|
+
let orchestration = await orchestrate(orchestrateArgs, {
|
|
7836
8013
|
providers: opts.providers,
|
|
7837
8014
|
allowlist: opts.allowlist ?? null,
|
|
7838
8015
|
moderator,
|
|
7839
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7840
8016
|
ctx
|
|
7841
8017
|
});
|
|
7842
8018
|
let attempts = 1;
|
|
@@ -7862,7 +8038,7 @@ ${scopeAnswer || "(none)"}
|
|
|
7862
8038
|
}
|
|
7863
8039
|
let reviewEnvelope = null;
|
|
7864
8040
|
if (!skipReview && typeof orchestration["final"] === "string" && orchestration["final"]) {
|
|
7865
|
-
reviewEnvelope = await
|
|
8041
|
+
reviewEnvelope = await review({
|
|
7866
8042
|
snippet: orchestration["final"],
|
|
7867
8043
|
intent: `final deliverable for: ${instruction}`,
|
|
7868
8044
|
...providers !== void 0 ? { providers } : {},
|
|
@@ -7871,7 +8047,6 @@ ${scopeAnswer || "(none)"}
|
|
|
7871
8047
|
}, {
|
|
7872
8048
|
providers: opts.providers,
|
|
7873
8049
|
allowlist: opts.allowlist ?? null,
|
|
7874
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7875
8050
|
ctx
|
|
7876
8051
|
});
|
|
7877
8052
|
}
|
|
@@ -7883,7 +8058,7 @@ ${scopeAnswer || "(none)"}
|
|
|
7883
8058
|
const panelExhausted = producingPanel.length > 0 && producingPanel.every(
|
|
7884
8059
|
(p) => p in opts.providers || Object.keys(opts.providers).includes(p.toLowerCase())
|
|
7885
8060
|
) && producingPanel.length >= Object.keys(opts.providers).length;
|
|
7886
|
-
auditEnvelope = await
|
|
8061
|
+
auditEnvelope = await audit({
|
|
7887
8062
|
output_to_audit: orchestration["final"],
|
|
7888
8063
|
producing_panelists: producingPanel,
|
|
7889
8064
|
...auditRubric !== void 0 ? { rubric: auditRubric } : {},
|
|
@@ -7894,7 +8069,6 @@ ${scopeAnswer || "(none)"}
|
|
|
7894
8069
|
}, {
|
|
7895
8070
|
providers: opts.providers,
|
|
7896
8071
|
allowlist: opts.allowlist ?? null,
|
|
7897
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7898
8072
|
ctx
|
|
7899
8073
|
});
|
|
7900
8074
|
let overallF = toNumberOrNull(auditEnvelope["overall_score"]);
|
|
@@ -7913,13 +8087,12 @@ ${retryConstraints}
|
|
|
7913
8087
|
DOCUMENTS:
|
|
7914
8088
|
${documentsPayload}`
|
|
7915
8089
|
};
|
|
7916
|
-
const retryOrchestration = await
|
|
8090
|
+
const retryOrchestration = await orchestrate(
|
|
7917
8091
|
retryOrchestrateArgs,
|
|
7918
8092
|
{
|
|
7919
8093
|
providers: opts.providers,
|
|
7920
8094
|
allowlist: opts.allowlist ?? null,
|
|
7921
8095
|
moderator,
|
|
7922
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7923
8096
|
ctx
|
|
7924
8097
|
}
|
|
7925
8098
|
);
|
|
@@ -7928,7 +8101,7 @@ ${documentsPayload}`
|
|
|
7928
8101
|
if (typeof retryOrchestration["final"] === "string" && retryOrchestration["final"]) {
|
|
7929
8102
|
const retryPanel = computeProducingPanel(retryOrchestration);
|
|
7930
8103
|
const retryPanelExhausted = retryPanel.length > 0 && retryPanel.length >= Object.keys(opts.providers).length;
|
|
7931
|
-
auditEnvelope = await
|
|
8104
|
+
auditEnvelope = await audit({
|
|
7932
8105
|
output_to_audit: retryOrchestration["final"],
|
|
7933
8106
|
producing_panelists: retryPanel,
|
|
7934
8107
|
...auditRubric !== void 0 ? { rubric: auditRubric } : {},
|
|
@@ -7939,7 +8112,6 @@ ${documentsPayload}`
|
|
|
7939
8112
|
}, {
|
|
7940
8113
|
providers: opts.providers,
|
|
7941
8114
|
allowlist: opts.allowlist ?? null,
|
|
7942
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
7943
8115
|
ctx
|
|
7944
8116
|
});
|
|
7945
8117
|
overallF = toNumberOrNull(auditEnvelope["overall_score"]);
|
|
@@ -8004,9 +8176,28 @@ ${documentsPayload}`
|
|
|
8004
8176
|
["auditor", "items", "overall_score", "passed", "rubric"]
|
|
8005
8177
|
),
|
|
8006
8178
|
artifacts,
|
|
8007
|
-
warnings
|
|
8179
|
+
warnings,
|
|
8180
|
+
...combinedUsage(subEnvelopes)
|
|
8008
8181
|
};
|
|
8009
8182
|
}
|
|
8183
|
+
function combinedUsage(envelopes) {
|
|
8184
|
+
const usages = [];
|
|
8185
|
+
const byCallTiming = [];
|
|
8186
|
+
let wall = 0, cpu = 0;
|
|
8187
|
+
for (const env of envelopes) {
|
|
8188
|
+
const e = env ?? {};
|
|
8189
|
+
const calls = e["usage"]?.["by_call"] ?? [];
|
|
8190
|
+
const t = e["timing"] ?? {};
|
|
8191
|
+
const timing = Array.isArray(t["by_call"]) ? t["by_call"] : [];
|
|
8192
|
+
if (!Array.isArray(calls) || calls.length === 0) continue;
|
|
8193
|
+
usages.push(...calls);
|
|
8194
|
+
if (timing.length === calls.length) byCallTiming.push(...timing);
|
|
8195
|
+
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 });
|
|
8196
|
+
wall += Number(t["wall_ms"] ?? 0) || 0;
|
|
8197
|
+
cpu += Number(t["cpu_ms"] ?? 0) || 0;
|
|
8198
|
+
}
|
|
8199
|
+
return { usage: aggregateUsage(usages), timing: { wall_ms: wall, cpu_ms: cpu, by_call: byCallTiming } };
|
|
8200
|
+
}
|
|
8010
8201
|
async function ingestDocuments(documents, sessionId, opts) {
|
|
8011
8202
|
if (documents.length === 0) return [];
|
|
8012
8203
|
const out = [];
|
|
@@ -8177,11 +8368,6 @@ function errorEnvelope6(toolName, code, message, hint) {
|
|
|
8177
8368
|
|
|
8178
8369
|
// src/tools/coordinate.ts
|
|
8179
8370
|
import { performance as performance8 } from "perf_hooks";
|
|
8180
|
-
var DEFERRED_OPTS3 = [
|
|
8181
|
-
// empty — every coordinate opt runs natively when its deps
|
|
8182
|
-
// (storage / innerCallers) are wired. Without them the
|
|
8183
|
-
// worker_tools gate still triggers a bridge defer.
|
|
8184
|
-
];
|
|
8185
8371
|
var COORDINATE_DEFAULT_TEMP = 0.4;
|
|
8186
8372
|
var ROLE_TURN_SCHEMA = {
|
|
8187
8373
|
type: "object",
|
|
@@ -8236,23 +8422,18 @@ async function runCoordinate(args, opts) {
|
|
|
8236
8422
|
rejectedWorkerTools.push(t);
|
|
8237
8423
|
}
|
|
8238
8424
|
}
|
|
8239
|
-
|
|
8240
|
-
const needsBridge = DEFERRED_OPTS3.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
8241
|
-
if (needsBridge) {
|
|
8425
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
8242
8426
|
if (superRequested) {
|
|
8243
8427
|
return errorEnvelope7(
|
|
8244
8428
|
"COORDINATE_SUPER_NOT_NATIVE",
|
|
8245
|
-
"super mode requested
|
|
8246
|
-
"worker_tools
|
|
8429
|
+
"super mode requested with worker_tools, but innerCallers are not wired",
|
|
8430
|
+
"worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
|
|
8247
8431
|
);
|
|
8248
8432
|
}
|
|
8249
|
-
if (opts.bridge && opts.bridge.toolNames.has("coordinate")) {
|
|
8250
|
-
return await deferCoordinate(args, opts.bridge);
|
|
8251
|
-
}
|
|
8252
8433
|
return errorEnvelope7(
|
|
8253
8434
|
"COORDINATE_OPT_NOT_NATIVE",
|
|
8254
8435
|
"worker_tools requested but innerCallers are not wired",
|
|
8255
|
-
"Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host
|
|
8436
|
+
"Native coordinate covers the three-role flow + untrusted_input + inject_session_memory. worker_tools needs innerCallers wired by the host."
|
|
8256
8437
|
);
|
|
8257
8438
|
}
|
|
8258
8439
|
const untrusted = Boolean(args["untrusted_input"]);
|
|
@@ -8652,21 +8833,6 @@ function unknownProviderError3(unknownNames, available) {
|
|
|
8652
8833
|
available_now: Object.keys(available).sort()
|
|
8653
8834
|
};
|
|
8654
8835
|
}
|
|
8655
|
-
async function deferCoordinate(args, bridge) {
|
|
8656
|
-
const r = await bridge.callTool("coordinate", args);
|
|
8657
|
-
const text = r.content[0]?.text;
|
|
8658
|
-
if (typeof text === "string") {
|
|
8659
|
-
try {
|
|
8660
|
-
return JSON.parse(text);
|
|
8661
|
-
} catch {
|
|
8662
|
-
}
|
|
8663
|
-
}
|
|
8664
|
-
return errorEnvelope7(
|
|
8665
|
-
"COORDINATE_BRIDGE_BAD_ENVELOPE",
|
|
8666
|
-
"bridge returned an unparseable envelope for coordinate",
|
|
8667
|
-
"Check that the Python child is healthy."
|
|
8668
|
-
);
|
|
8669
|
-
}
|
|
8670
8836
|
function errorEnvelope7(code, message, hint) {
|
|
8671
8837
|
return {
|
|
8672
8838
|
tool: "coordinate",
|
|
@@ -8994,10 +9160,6 @@ function buildModeratorTranscript(transcript) {
|
|
|
8994
9160
|
|
|
8995
9161
|
// src/tools/debate.ts
|
|
8996
9162
|
import { performance as performance10 } from "perf_hooks";
|
|
8997
|
-
var DEFERRED_OPTS4 = [
|
|
8998
|
-
// empty — every debate opt runs natively when its deps
|
|
8999
|
-
// (storage / innerCallers) are wired.
|
|
9000
|
-
];
|
|
9001
9163
|
async function runDebate(args, opts) {
|
|
9002
9164
|
const callStartedWall = performance10.now();
|
|
9003
9165
|
const callStartedCpu = process.cpuUsage();
|
|
@@ -9015,23 +9177,18 @@ async function runDebate(args, opts) {
|
|
|
9015
9177
|
rejectedWorkerTools.push(t);
|
|
9016
9178
|
}
|
|
9017
9179
|
}
|
|
9018
|
-
|
|
9019
|
-
const needsBridge = DEFERRED_OPTS4.some((k) => Boolean(args[k])) || workerToolsNeedsBridge;
|
|
9020
|
-
if (needsBridge) {
|
|
9180
|
+
if (acceptedWorkerTools.length > 0 && !opts.innerCallers) {
|
|
9021
9181
|
if (superRequested) {
|
|
9022
9182
|
return errorEnvelope9(
|
|
9023
9183
|
"DEBATE_SUPER_NOT_NATIVE",
|
|
9024
|
-
"super mode requested
|
|
9025
|
-
"worker_tools
|
|
9184
|
+
"super mode requested with worker_tools, but innerCallers are not wired",
|
|
9185
|
+
"worker_tools needs innerCallers wired by the host. Drop worker_tools, or wire innerCallers, to use super."
|
|
9026
9186
|
);
|
|
9027
9187
|
}
|
|
9028
|
-
if (opts.bridge && opts.bridge.toolNames.has("debate")) {
|
|
9029
|
-
return await deferDebate(args, opts.bridge);
|
|
9030
|
-
}
|
|
9031
9188
|
return errorEnvelope9(
|
|
9032
9189
|
"DEBATE_OPT_NOT_NATIVE",
|
|
9033
9190
|
"worker_tools requested but innerCallers are not wired",
|
|
9034
|
-
"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
|
|
9191
|
+
"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."
|
|
9035
9192
|
);
|
|
9036
9193
|
}
|
|
9037
9194
|
const topic = typeof args["topic"] === "string" ? args["topic"] : String(args["topic"] ?? "");
|
|
@@ -9468,21 +9625,6 @@ function unknownProviderError5(unknownNames, available) {
|
|
|
9468
9625
|
available_now: Object.keys(available).sort()
|
|
9469
9626
|
};
|
|
9470
9627
|
}
|
|
9471
|
-
async function deferDebate(args, bridge) {
|
|
9472
|
-
const r = await bridge.callTool("debate", args);
|
|
9473
|
-
const text = r.content[0]?.text;
|
|
9474
|
-
if (typeof text === "string") {
|
|
9475
|
-
try {
|
|
9476
|
-
return JSON.parse(text);
|
|
9477
|
-
} catch {
|
|
9478
|
-
}
|
|
9479
|
-
}
|
|
9480
|
-
return errorEnvelope9(
|
|
9481
|
-
"DEBATE_BRIDGE_BAD_ENVELOPE",
|
|
9482
|
-
"bridge returned an unparseable envelope for debate",
|
|
9483
|
-
"Check that the Python child is healthy."
|
|
9484
|
-
);
|
|
9485
|
-
}
|
|
9486
9628
|
function errorEnvelope9(code, message, hint) {
|
|
9487
9629
|
return {
|
|
9488
9630
|
tool: "debate",
|
|
@@ -9502,9 +9644,6 @@ var DEFAULT_DELEGATION_LIMITS = {
|
|
|
9502
9644
|
};
|
|
9503
9645
|
async function runDelegate(args, opts) {
|
|
9504
9646
|
if (!opts.storage) {
|
|
9505
|
-
if (opts.bridge && opts.bridge.toolNames.has("delegate")) {
|
|
9506
|
-
return await deferDelegate(args, opts.bridge);
|
|
9507
|
-
}
|
|
9508
9647
|
return errorEnvelope10(
|
|
9509
9648
|
"DELEGATE_STORAGE_UNAVAILABLE",
|
|
9510
9649
|
"delegate needs the local database (for quota tracking), which isn't available",
|
|
@@ -9576,7 +9715,6 @@ async function runDelegate(args, opts) {
|
|
|
9576
9715
|
const innerOpts = {
|
|
9577
9716
|
providers: opts.providers,
|
|
9578
9717
|
allowlist: opts.allowlist ?? null,
|
|
9579
|
-
...opts.bridge ? { bridge: opts.bridge } : {},
|
|
9580
9718
|
...opts.moderator ? { moderator: opts.moderator } : {}
|
|
9581
9719
|
};
|
|
9582
9720
|
let result;
|
|
@@ -9615,21 +9753,6 @@ async function record(storage, sessionId, requester, toolCall, via, accepted, no
|
|
|
9615
9753
|
created_at: nowEpochSeconds
|
|
9616
9754
|
});
|
|
9617
9755
|
}
|
|
9618
|
-
async function deferDelegate(args, bridge) {
|
|
9619
|
-
const r = await bridge.callTool("delegate", args);
|
|
9620
|
-
const text = r.content[0]?.text;
|
|
9621
|
-
if (typeof text === "string") {
|
|
9622
|
-
try {
|
|
9623
|
-
return JSON.parse(text);
|
|
9624
|
-
} catch {
|
|
9625
|
-
}
|
|
9626
|
-
}
|
|
9627
|
-
return errorEnvelope10(
|
|
9628
|
-
"DELEGATE_BRIDGE_BAD_ENVELOPE",
|
|
9629
|
-
"bridge returned an unparseable envelope for delegate",
|
|
9630
|
-
"Check that the Python child is healthy."
|
|
9631
|
-
);
|
|
9632
|
-
}
|
|
9633
9756
|
function errorEnvelope10(code, message, hint) {
|
|
9634
9757
|
return {
|
|
9635
9758
|
tool: "delegate",
|
|
@@ -9672,9 +9795,6 @@ async function runExplain(args, opts) {
|
|
|
9672
9795
|
);
|
|
9673
9796
|
}
|
|
9674
9797
|
if (!opts.storage) {
|
|
9675
|
-
if (opts.bridge && opts.bridge.toolNames.has("explain")) {
|
|
9676
|
-
return await deferExplain(args, opts.bridge);
|
|
9677
|
-
}
|
|
9678
9798
|
return errorEnvelope11(
|
|
9679
9799
|
"EXPLAIN_STORAGE_UNAVAILABLE",
|
|
9680
9800
|
"explain needs the local transcript/stats database, which isn't available",
|
|
@@ -9956,21 +10076,6 @@ function pyRepr5(v) {
|
|
|
9956
10076
|
}
|
|
9957
10077
|
return String(v);
|
|
9958
10078
|
}
|
|
9959
|
-
async function deferExplain(args, bridge) {
|
|
9960
|
-
const r = await bridge.callTool("explain", args);
|
|
9961
|
-
const text = r.content[0]?.text;
|
|
9962
|
-
if (typeof text === "string") {
|
|
9963
|
-
try {
|
|
9964
|
-
return JSON.parse(text);
|
|
9965
|
-
} catch {
|
|
9966
|
-
}
|
|
9967
|
-
}
|
|
9968
|
-
return errorEnvelope11(
|
|
9969
|
-
"EXPLAIN_BRIDGE_BAD_ENVELOPE",
|
|
9970
|
-
"bridge returned an unparseable envelope for explain",
|
|
9971
|
-
"Check that the Python child is healthy."
|
|
9972
|
-
);
|
|
9973
|
-
}
|
|
9974
10079
|
function errorEnvelope11(code, message, hint, kind = "client", extra = {}) {
|
|
9975
10080
|
return {
|
|
9976
10081
|
tool: "explain",
|
|
@@ -10523,9 +10628,6 @@ async function runRecall(args, opts) {
|
|
|
10523
10628
|
if (k < 1) k = 1;
|
|
10524
10629
|
if (k > 50) k = 50;
|
|
10525
10630
|
if (!opts.storage) {
|
|
10526
|
-
if (opts.bridge && opts.bridge.toolNames.has("recall")) {
|
|
10527
|
-
return await deferRecall(args, opts.bridge);
|
|
10528
|
-
}
|
|
10529
10631
|
return errorEnvelope12(
|
|
10530
10632
|
"RECALL_STORAGE_UNAVAILABLE",
|
|
10531
10633
|
"recall needs the local database, which isn't available",
|
|
@@ -10578,21 +10680,6 @@ async function runRecall(args, opts) {
|
|
|
10578
10680
|
applied_filters: applied
|
|
10579
10681
|
};
|
|
10580
10682
|
}
|
|
10581
|
-
async function deferRecall(args, bridge) {
|
|
10582
|
-
const r = await bridge.callTool("recall", args);
|
|
10583
|
-
const text = r.content[0]?.text;
|
|
10584
|
-
if (typeof text === "string") {
|
|
10585
|
-
try {
|
|
10586
|
-
return JSON.parse(text);
|
|
10587
|
-
} catch {
|
|
10588
|
-
}
|
|
10589
|
-
}
|
|
10590
|
-
return errorEnvelope12(
|
|
10591
|
-
"RECALL_BRIDGE_BAD_ENVELOPE",
|
|
10592
|
-
"bridge returned an unparseable envelope for recall",
|
|
10593
|
-
"Check that the Python child is healthy."
|
|
10594
|
-
);
|
|
10595
|
-
}
|
|
10596
10683
|
function errorEnvelope12(code, message, hint) {
|
|
10597
10684
|
return {
|
|
10598
10685
|
tool: "recall",
|
|
@@ -10615,9 +10702,6 @@ async function runRecommendPanel(args, opts) {
|
|
|
10615
10702
|
);
|
|
10616
10703
|
}
|
|
10617
10704
|
if (!opts.storage) {
|
|
10618
|
-
if (opts.bridge && opts.bridge.toolNames.has("recommend_panel")) {
|
|
10619
|
-
return await deferRecommendPanel(args, opts.bridge);
|
|
10620
|
-
}
|
|
10621
10705
|
return errorEnvelope13(
|
|
10622
10706
|
"RECOMMEND_PANEL_STORAGE_UNAVAILABLE",
|
|
10623
10707
|
"recommend_panel needs the local stats database, which isn't available",
|
|
@@ -10680,21 +10764,6 @@ async function runRecommendPanel(args, opts) {
|
|
|
10680
10764
|
meta: result.meta
|
|
10681
10765
|
};
|
|
10682
10766
|
}
|
|
10683
|
-
async function deferRecommendPanel(args, bridge) {
|
|
10684
|
-
const r = await bridge.callTool("recommend_panel", args);
|
|
10685
|
-
const text = r.content[0]?.text;
|
|
10686
|
-
if (typeof text === "string") {
|
|
10687
|
-
try {
|
|
10688
|
-
return JSON.parse(text);
|
|
10689
|
-
} catch {
|
|
10690
|
-
}
|
|
10691
|
-
}
|
|
10692
|
-
return errorEnvelope13(
|
|
10693
|
-
"RECOMMEND_PANEL_BRIDGE_BAD_ENVELOPE",
|
|
10694
|
-
"bridge returned an unparseable envelope for recommend_panel",
|
|
10695
|
-
"Check that the Python child is healthy."
|
|
10696
|
-
);
|
|
10697
|
-
}
|
|
10698
10767
|
function errorEnvelope13(code, message, hint) {
|
|
10699
10768
|
return {
|
|
10700
10769
|
tool: "recommend_panel",
|
|
@@ -10724,9 +10793,6 @@ function toStringArray3(v) {
|
|
|
10724
10793
|
import { readFileSync as readFileSync10, existsSync as existsSync8 } from "fs";
|
|
10725
10794
|
async function runScoreboard(args, opts) {
|
|
10726
10795
|
if (!opts.storage) {
|
|
10727
|
-
if (opts.bridge && opts.bridge.toolNames.has("scoreboard")) {
|
|
10728
|
-
return await deferScoreboard(args, opts.bridge);
|
|
10729
|
-
}
|
|
10730
10796
|
return errorEnvelope14(
|
|
10731
10797
|
"SCOREBOARD_STORAGE_UNAVAILABLE",
|
|
10732
10798
|
"scoreboard needs the local stats database, which isn't available",
|
|
@@ -10849,21 +10915,6 @@ function clampInt3(raw, min, max, fallback) {
|
|
|
10849
10915
|
if (!Number.isFinite(n)) return fallback;
|
|
10850
10916
|
return Math.min(max, Math.max(min, Math.trunc(n)));
|
|
10851
10917
|
}
|
|
10852
|
-
async function deferScoreboard(args, bridge) {
|
|
10853
|
-
const r = await bridge.callTool("scoreboard", args);
|
|
10854
|
-
const text = r.content[0]?.text;
|
|
10855
|
-
if (typeof text === "string") {
|
|
10856
|
-
try {
|
|
10857
|
-
return JSON.parse(text);
|
|
10858
|
-
} catch {
|
|
10859
|
-
}
|
|
10860
|
-
}
|
|
10861
|
-
return errorEnvelope14(
|
|
10862
|
-
"SCOREBOARD_BRIDGE_BAD_ENVELOPE",
|
|
10863
|
-
"bridge returned an unparseable envelope for scoreboard",
|
|
10864
|
-
"Check that the Python child is healthy."
|
|
10865
|
-
);
|
|
10866
|
-
}
|
|
10867
10918
|
function errorEnvelope14(code, message, hint) {
|
|
10868
10919
|
return {
|
|
10869
10920
|
tool: "scoreboard",
|
|
@@ -10900,9 +10951,6 @@ async function runSessionMemory(args, opts) {
|
|
|
10900
10951
|
);
|
|
10901
10952
|
}
|
|
10902
10953
|
if (!opts.storage) {
|
|
10903
|
-
if (opts.bridge && opts.bridge.toolNames.has("session_memory")) {
|
|
10904
|
-
return await deferSessionMemory(args, opts.bridge);
|
|
10905
|
-
}
|
|
10906
10954
|
return errorEnvelope15(
|
|
10907
10955
|
"SESSION_MEMORY_STORAGE_UNAVAILABLE",
|
|
10908
10956
|
"session_memory needs the local database, which isn't available",
|
|
@@ -11007,21 +11055,6 @@ function clampInt4(raw, min, max, fallback) {
|
|
|
11007
11055
|
if (!Number.isFinite(n)) return fallback;
|
|
11008
11056
|
return Math.min(max, Math.max(min, Math.trunc(n)));
|
|
11009
11057
|
}
|
|
11010
|
-
async function deferSessionMemory(args, bridge) {
|
|
11011
|
-
const r = await bridge.callTool("session_memory", args);
|
|
11012
|
-
const text = r.content[0]?.text;
|
|
11013
|
-
if (typeof text === "string") {
|
|
11014
|
-
try {
|
|
11015
|
-
return JSON.parse(text);
|
|
11016
|
-
} catch {
|
|
11017
|
-
}
|
|
11018
|
-
}
|
|
11019
|
-
return errorEnvelope15(
|
|
11020
|
-
"SESSION_MEMORY_BRIDGE_BAD_ENVELOPE",
|
|
11021
|
-
"bridge returned an unparseable envelope for session_memory",
|
|
11022
|
-
"Check that the Python child is healthy."
|
|
11023
|
-
);
|
|
11024
|
-
}
|
|
11025
11058
|
function errorEnvelope15(code, message, hint) {
|
|
11026
11059
|
return {
|
|
11027
11060
|
tool: "session_memory",
|
|
@@ -11641,7 +11674,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
|
|
|
11641
11674
|
var DEFAULT_PACKAGE = "crosscheck-cli";
|
|
11642
11675
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
11643
11676
|
function engineVersion() {
|
|
11644
|
-
return true ? "0.2.
|
|
11677
|
+
return true ? "0.2.29" : "0.0.0-dev";
|
|
11645
11678
|
}
|
|
11646
11679
|
function defaultUpdateCachePath() {
|
|
11647
11680
|
const base = process.env["CROSSCHECK_DATA_DIR"] || path9.join(os.homedir() || os.tmpdir(), ".crosscheck");
|
|
@@ -12413,12 +12446,11 @@ function helpTool() {
|
|
|
12413
12446
|
}
|
|
12414
12447
|
});
|
|
12415
12448
|
}
|
|
12416
|
-
function registerCoreTools(
|
|
12417
|
-
const o = opts && typeof opts === "object" && "toolNames" in opts ? { bridge: opts } : opts;
|
|
12449
|
+
function registerCoreTools(o = {}) {
|
|
12418
12450
|
const tools = /* @__PURE__ */ new Map();
|
|
12419
12451
|
const list = [
|
|
12420
12452
|
pingTool(),
|
|
12421
|
-
verifyTool(o.
|
|
12453
|
+
verifyTool(o.fetchConfig),
|
|
12422
12454
|
pickTool(
|
|
12423
12455
|
o.providers ?? {},
|
|
12424
12456
|
o.providerAllowlist ?? null,
|
|
@@ -12430,7 +12462,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12430
12462
|
auditTool(
|
|
12431
12463
|
o.providers ?? {},
|
|
12432
12464
|
o.providerAllowlist ?? null,
|
|
12433
|
-
o.bridge,
|
|
12434
12465
|
o.transcriptsDir,
|
|
12435
12466
|
o.pricing,
|
|
12436
12467
|
o.storage,
|
|
@@ -12440,7 +12471,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12440
12471
|
conferTool(
|
|
12441
12472
|
o.providers ?? {},
|
|
12442
12473
|
o.providerAllowlist ?? null,
|
|
12443
|
-
o.bridge,
|
|
12444
12474
|
o.moderatorDefault ?? "anthropic",
|
|
12445
12475
|
o.pricing,
|
|
12446
12476
|
o.storage,
|
|
@@ -12453,7 +12483,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12453
12483
|
debateTool(
|
|
12454
12484
|
o.providers ?? {},
|
|
12455
12485
|
o.providerAllowlist ?? null,
|
|
12456
|
-
o.bridge,
|
|
12457
12486
|
buildInnerCallers(o),
|
|
12458
12487
|
o.storage,
|
|
12459
12488
|
o.pricing,
|
|
@@ -12465,7 +12494,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12465
12494
|
coordinateTool(
|
|
12466
12495
|
o.providers ?? {},
|
|
12467
12496
|
o.providerAllowlist ?? null,
|
|
12468
|
-
o.bridge,
|
|
12469
12497
|
buildInnerCallers(o),
|
|
12470
12498
|
o.storage,
|
|
12471
12499
|
o.circuitBreakers,
|
|
@@ -12476,7 +12504,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12476
12504
|
triangulateTool(
|
|
12477
12505
|
o.providers ?? {},
|
|
12478
12506
|
o.providerAllowlist ?? null,
|
|
12479
|
-
o.bridge,
|
|
12480
12507
|
o.storage,
|
|
12481
12508
|
o.circuitBreakers,
|
|
12482
12509
|
o.transcriptsDir,
|
|
@@ -12485,7 +12512,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12485
12512
|
planTool(
|
|
12486
12513
|
o.providers ?? {},
|
|
12487
12514
|
o.providerAllowlist ?? null,
|
|
12488
|
-
o.bridge,
|
|
12489
12515
|
o.storage,
|
|
12490
12516
|
o.circuitBreakers,
|
|
12491
12517
|
o.transcriptsDir,
|
|
@@ -12494,7 +12520,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12494
12520
|
critiqueTool(
|
|
12495
12521
|
o.providers ?? {},
|
|
12496
12522
|
o.providerAllowlist ?? null,
|
|
12497
|
-
o.bridge,
|
|
12498
12523
|
o.storage,
|
|
12499
12524
|
o.circuitBreakers,
|
|
12500
12525
|
o.transcriptsDir,
|
|
@@ -12503,7 +12528,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12503
12528
|
reviewTool(
|
|
12504
12529
|
o.providers ?? {},
|
|
12505
12530
|
o.providerAllowlist ?? null,
|
|
12506
|
-
o.bridge,
|
|
12507
12531
|
o.storage,
|
|
12508
12532
|
o.circuitBreakers,
|
|
12509
12533
|
o.transcriptsDir,
|
|
@@ -12511,25 +12535,23 @@ function registerCoreTools(opts = {}) {
|
|
|
12511
12535
|
),
|
|
12512
12536
|
listProvidersTool(o.providers ?? {}, o.activeProviders ?? null, o.moderatorDefault ?? "anthropic"),
|
|
12513
12537
|
modelsTool(o.providers ?? {}, o.activeProviders ?? null),
|
|
12514
|
-
recallTool(o.storage
|
|
12515
|
-
sessionMemoryTool(o.storage
|
|
12516
|
-
scoreboardTool(o.storage, o.
|
|
12517
|
-
explainTool(o.storage, o.
|
|
12538
|
+
recallTool(o.storage),
|
|
12539
|
+
sessionMemoryTool(o.storage),
|
|
12540
|
+
scoreboardTool(o.storage, o.eventsPath),
|
|
12541
|
+
explainTool(o.storage, o.transcriptsDir),
|
|
12518
12542
|
delegateTool(
|
|
12519
12543
|
o.providers ?? {},
|
|
12520
12544
|
o.providerAllowlist ?? null,
|
|
12521
12545
|
o.storage,
|
|
12522
|
-
o.bridge,
|
|
12523
12546
|
o.moderatorDefault ?? "anthropic"
|
|
12524
12547
|
),
|
|
12525
12548
|
fetchTool(o.storage, o.fetchConfig, o.repoRoot),
|
|
12526
|
-
recommendPanelTool(o.providers ?? {}, o.storage
|
|
12549
|
+
recommendPanelTool(o.providers ?? {}, o.storage),
|
|
12527
12550
|
updateCrosscheckTool(o.repoRoot ?? null),
|
|
12528
12551
|
benchTool(
|
|
12529
12552
|
o.providers ?? {},
|
|
12530
12553
|
o.providerAllowlist ?? null,
|
|
12531
12554
|
o.storage,
|
|
12532
|
-
o.bridge,
|
|
12533
12555
|
o.moderatorDefault ?? "anthropic",
|
|
12534
12556
|
o.benchGoldensDir,
|
|
12535
12557
|
o.circuitBreakers,
|
|
@@ -12540,7 +12562,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12540
12562
|
solveTool(
|
|
12541
12563
|
o.providers ?? {},
|
|
12542
12564
|
o.providerAllowlist ?? null,
|
|
12543
|
-
o.bridge,
|
|
12544
12565
|
o.storage,
|
|
12545
12566
|
o.circuitBreakers,
|
|
12546
12567
|
o.transcriptsDir,
|
|
@@ -12549,7 +12570,6 @@ function registerCoreTools(opts = {}) {
|
|
|
12549
12570
|
orchestrateTool(
|
|
12550
12571
|
o.providers ?? {},
|
|
12551
12572
|
o.providerAllowlist ?? null,
|
|
12552
|
-
o.bridge,
|
|
12553
12573
|
o.moderatorDefault ?? "anthropic",
|
|
12554
12574
|
o.storage,
|
|
12555
12575
|
o.pricing,
|
|
@@ -12596,7 +12616,6 @@ function createTool(o, toolName, cheapDefault) {
|
|
|
12596
12616
|
providers: o.providers ?? {},
|
|
12597
12617
|
allowlist: o.providerAllowlist ?? null,
|
|
12598
12618
|
...o.storage ? { storage: o.storage } : {},
|
|
12599
|
-
...o.bridge ? { bridge: o.bridge } : {},
|
|
12600
12619
|
...o.moderatorDefault ? { moderator: o.moderatorDefault } : {},
|
|
12601
12620
|
...o.fetchConfig ? { fetchConfig: o.fetchConfig } : {},
|
|
12602
12621
|
...o.repoRoot ? { repoRoot: o.repoRoot } : {},
|
|
@@ -12605,7 +12624,7 @@ function createTool(o, toolName, cheapDefault) {
|
|
|
12605
12624
|
})
|
|
12606
12625
|
};
|
|
12607
12626
|
}
|
|
12608
|
-
function orchestrateTool(providers, allowlist,
|
|
12627
|
+
function orchestrateTool(providers, allowlist, moderator, storage, pricing, breakers, transcriptsDir, repoRoot, nodeCache) {
|
|
12609
12628
|
return {
|
|
12610
12629
|
name: "orchestrate",
|
|
12611
12630
|
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.",
|
|
@@ -12630,7 +12649,6 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
|
|
|
12630
12649
|
providers,
|
|
12631
12650
|
allowlist,
|
|
12632
12651
|
moderator,
|
|
12633
|
-
...bridge ? { bridge } : {},
|
|
12634
12652
|
...storage ? { storage } : {},
|
|
12635
12653
|
...pricing ? { pricing } : {},
|
|
12636
12654
|
...breakers ? { breakers } : {},
|
|
@@ -12640,7 +12658,7 @@ function orchestrateTool(providers, allowlist, bridge, moderator, storage, prici
|
|
|
12640
12658
|
})
|
|
12641
12659
|
};
|
|
12642
12660
|
}
|
|
12643
|
-
function solveTool(providers, allowlist,
|
|
12661
|
+
function solveTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
12644
12662
|
return {
|
|
12645
12663
|
name: "solve",
|
|
12646
12664
|
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.",
|
|
@@ -12662,7 +12680,6 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
|
|
|
12662
12680
|
handler: (args) => runSolve(args, {
|
|
12663
12681
|
providers,
|
|
12664
12682
|
allowlist,
|
|
12665
|
-
...bridge ? { bridge } : {},
|
|
12666
12683
|
...storage ? { storage } : {},
|
|
12667
12684
|
...breakers ? { breakers } : {},
|
|
12668
12685
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -12701,7 +12718,7 @@ function configPinTool(repoRoot, config2, rejectDriftEnv) {
|
|
|
12701
12718
|
}
|
|
12702
12719
|
};
|
|
12703
12720
|
}
|
|
12704
|
-
function benchTool(providers, allowlist, storage,
|
|
12721
|
+
function benchTool(providers, allowlist, storage, moderator, defaultGoldensDir, breakers, transcriptsDir, repoRoot) {
|
|
12705
12722
|
return {
|
|
12706
12723
|
name: "bench",
|
|
12707
12724
|
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).",
|
|
@@ -12720,7 +12737,6 @@ function benchTool(providers, allowlist, storage, bridge, moderator, defaultGold
|
|
|
12720
12737
|
allowlist,
|
|
12721
12738
|
moderator,
|
|
12722
12739
|
...storage ? { storage } : {},
|
|
12723
|
-
...bridge ? { bridge } : {},
|
|
12724
12740
|
...defaultGoldensDir ? { defaultGoldensDir } : {},
|
|
12725
12741
|
...breakers ? { breakers } : {},
|
|
12726
12742
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -12747,7 +12763,7 @@ function updateCrosscheckTool(repoRoot) {
|
|
|
12747
12763
|
}
|
|
12748
12764
|
};
|
|
12749
12765
|
}
|
|
12750
|
-
function recommendPanelTool(providers, storage
|
|
12766
|
+
function recommendPanelTool(providers, storage) {
|
|
12751
12767
|
return {
|
|
12752
12768
|
name: "recommend_panel",
|
|
12753
12769
|
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.",
|
|
@@ -12765,8 +12781,7 @@ function recommendPanelTool(providers, storage, bridge) {
|
|
|
12765
12781
|
},
|
|
12766
12782
|
handler: (args) => runRecommendPanel(args, {
|
|
12767
12783
|
providers,
|
|
12768
|
-
...storage ? { storage } : {}
|
|
12769
|
-
...bridge ? { bridge } : {}
|
|
12784
|
+
...storage ? { storage } : {}
|
|
12770
12785
|
})
|
|
12771
12786
|
};
|
|
12772
12787
|
}
|
|
@@ -12791,7 +12806,7 @@ function fetchTool(storage, fetchConfig, repoRoot) {
|
|
|
12791
12806
|
})
|
|
12792
12807
|
};
|
|
12793
12808
|
}
|
|
12794
|
-
function delegateTool(providers, allowlist, storage,
|
|
12809
|
+
function delegateTool(providers, allowlist, storage, moderator) {
|
|
12795
12810
|
return {
|
|
12796
12811
|
name: "delegate",
|
|
12797
12812
|
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.",
|
|
@@ -12811,12 +12826,11 @@ function delegateTool(providers, allowlist, storage, bridge, moderator) {
|
|
|
12811
12826
|
providers,
|
|
12812
12827
|
allowlist,
|
|
12813
12828
|
moderator,
|
|
12814
|
-
...storage ? { storage } : {}
|
|
12815
|
-
...bridge ? { bridge } : {}
|
|
12829
|
+
...storage ? { storage } : {}
|
|
12816
12830
|
})
|
|
12817
12831
|
};
|
|
12818
12832
|
}
|
|
12819
|
-
function explainTool(storage,
|
|
12833
|
+
function explainTool(storage, transcriptsDir) {
|
|
12820
12834
|
return {
|
|
12821
12835
|
name: "explain",
|
|
12822
12836
|
description: "Replay a session as a navigable tree with cost/latency annotations. Reads usage_log + optionally walks the transcripts directory for per-tool summaries.",
|
|
@@ -12834,12 +12848,11 @@ function explainTool(storage, bridge, transcriptsDir) {
|
|
|
12834
12848
|
},
|
|
12835
12849
|
handler: (args) => runExplain(args, {
|
|
12836
12850
|
...storage ? { storage } : {},
|
|
12837
|
-
...bridge ? { bridge } : {},
|
|
12838
12851
|
...transcriptsDir ? { transcriptsDir } : {}
|
|
12839
12852
|
})
|
|
12840
12853
|
};
|
|
12841
12854
|
}
|
|
12842
|
-
function scoreboardTool(storage,
|
|
12855
|
+
function scoreboardTool(storage, eventsPath) {
|
|
12843
12856
|
return {
|
|
12844
12857
|
name: "scoreboard",
|
|
12845
12858
|
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).",
|
|
@@ -12853,12 +12866,11 @@ function scoreboardTool(storage, bridge, eventsPath) {
|
|
|
12853
12866
|
},
|
|
12854
12867
|
handler: (args) => runScoreboard(args, {
|
|
12855
12868
|
...storage ? { storage } : {},
|
|
12856
|
-
...bridge ? { bridge } : {},
|
|
12857
12869
|
...eventsPath ? { eventsPath } : {}
|
|
12858
12870
|
})
|
|
12859
12871
|
};
|
|
12860
12872
|
}
|
|
12861
|
-
function sessionMemoryTool(storage
|
|
12873
|
+
function sessionMemoryTool(storage) {
|
|
12862
12874
|
return {
|
|
12863
12875
|
name: "session_memory",
|
|
12864
12876
|
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).",
|
|
@@ -12881,15 +12893,14 @@ function sessionMemoryTool(storage, bridge) {
|
|
|
12881
12893
|
required: ["action", "session_id"]
|
|
12882
12894
|
},
|
|
12883
12895
|
handler: (args) => runSessionMemory(args, {
|
|
12884
|
-
...storage ? { storage } : {}
|
|
12885
|
-
...bridge ? { bridge } : {}
|
|
12896
|
+
...storage ? { storage } : {}
|
|
12886
12897
|
})
|
|
12887
12898
|
};
|
|
12888
12899
|
}
|
|
12889
|
-
function recallTool(storage
|
|
12900
|
+
function recallTool(storage) {
|
|
12890
12901
|
return {
|
|
12891
12902
|
name: "recall",
|
|
12892
|
-
description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter
|
|
12903
|
+
description: "Full-text search across persisted transcripts via SQLite FTS5. Returns rows ordered by relevance with a windowed snippet. Requires a wired Storage adapter.",
|
|
12893
12904
|
inputSchema: {
|
|
12894
12905
|
type: "object",
|
|
12895
12906
|
additionalProperties: true,
|
|
@@ -12903,8 +12914,7 @@ function recallTool(storage, bridge) {
|
|
|
12903
12914
|
required: ["query"]
|
|
12904
12915
|
},
|
|
12905
12916
|
handler: (args) => runRecall(args, {
|
|
12906
|
-
...storage ? { storage } : {}
|
|
12907
|
-
...bridge ? { bridge } : {}
|
|
12917
|
+
...storage ? { storage } : {}
|
|
12908
12918
|
})
|
|
12909
12919
|
};
|
|
12910
12920
|
}
|
|
@@ -12940,7 +12950,7 @@ function modelsTool(providers, activeProviders) {
|
|
|
12940
12950
|
handler: async (args) => runModels(args, { providers, activeProviders })
|
|
12941
12951
|
};
|
|
12942
12952
|
}
|
|
12943
|
-
function reviewTool(providers, allowlist,
|
|
12953
|
+
function reviewTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
12944
12954
|
return {
|
|
12945
12955
|
name: "review",
|
|
12946
12956
|
description: "Have an LLM panel peer-review a code or proposal snippet. Returns the confer envelope (one answer per provider).",
|
|
@@ -12959,7 +12969,6 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
|
|
|
12959
12969
|
handler: (args) => runReview(args, {
|
|
12960
12970
|
providers,
|
|
12961
12971
|
allowlist,
|
|
12962
|
-
...bridge ? { bridge } : {},
|
|
12963
12972
|
...storage ? { storage } : {},
|
|
12964
12973
|
...breakers ? { breakers } : {},
|
|
12965
12974
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -12967,7 +12976,7 @@ function reviewTool(providers, allowlist, bridge, storage, breakers, transcripts
|
|
|
12967
12976
|
})
|
|
12968
12977
|
};
|
|
12969
12978
|
}
|
|
12970
|
-
function critiqueTool(providers, allowlist,
|
|
12979
|
+
function critiqueTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
12971
12980
|
return {
|
|
12972
12981
|
name: "critique",
|
|
12973
12982
|
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.",
|
|
@@ -12987,7 +12996,6 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
|
|
|
12987
12996
|
handler: (args) => runCritique(args, {
|
|
12988
12997
|
providers,
|
|
12989
12998
|
allowlist,
|
|
12990
|
-
...bridge ? { bridge } : {},
|
|
12991
12999
|
...storage ? { storage } : {},
|
|
12992
13000
|
...breakers ? { breakers } : {},
|
|
12993
13001
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -12995,7 +13003,7 @@ function critiqueTool(providers, allowlist, bridge, storage, breakers, transcrip
|
|
|
12995
13003
|
})
|
|
12996
13004
|
};
|
|
12997
13005
|
}
|
|
12998
|
-
function planTool(providers, allowlist,
|
|
13006
|
+
function planTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
12999
13007
|
return {
|
|
13000
13008
|
name: "plan",
|
|
13001
13009
|
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.',
|
|
@@ -13022,7 +13030,6 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
|
|
|
13022
13030
|
handler: (args) => runPlan(args, {
|
|
13023
13031
|
providers,
|
|
13024
13032
|
allowlist,
|
|
13025
|
-
...bridge ? { bridge } : {},
|
|
13026
13033
|
...storage ? { storage } : {},
|
|
13027
13034
|
...breakers ? { breakers } : {},
|
|
13028
13035
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -13030,7 +13037,7 @@ function planTool(providers, allowlist, bridge, storage, breakers, transcriptsDi
|
|
|
13030
13037
|
})
|
|
13031
13038
|
};
|
|
13032
13039
|
}
|
|
13033
|
-
function triangulateTool(providers, allowlist,
|
|
13040
|
+
function triangulateTool(providers, allowlist, storage, breakers, transcriptsDir, repoRoot) {
|
|
13034
13041
|
return {
|
|
13035
13042
|
name: "triangulate",
|
|
13036
13043
|
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.",
|
|
@@ -13051,7 +13058,6 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
|
|
|
13051
13058
|
handler: (args) => runTriangulate(args, {
|
|
13052
13059
|
providers,
|
|
13053
13060
|
allowlist,
|
|
13054
|
-
...bridge ? { bridge } : {},
|
|
13055
13061
|
...storage ? { storage } : {},
|
|
13056
13062
|
...breakers ? { breakers } : {},
|
|
13057
13063
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
@@ -13059,7 +13065,7 @@ function triangulateTool(providers, allowlist, bridge, storage, breakers, transc
|
|
|
13059
13065
|
})
|
|
13060
13066
|
};
|
|
13061
13067
|
}
|
|
13062
|
-
function coordinateTool(providers, allowlist,
|
|
13068
|
+
function coordinateTool(providers, allowlist, innerCallers, storage, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
13063
13069
|
return {
|
|
13064
13070
|
name: "coordinate",
|
|
13065
13071
|
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).",
|
|
@@ -13084,7 +13090,6 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
|
|
|
13084
13090
|
handler: (args) => runCoordinate(args, {
|
|
13085
13091
|
providers,
|
|
13086
13092
|
allowlist,
|
|
13087
|
-
...bridge ? { bridge } : {},
|
|
13088
13093
|
innerCallers,
|
|
13089
13094
|
...storage ? { storage } : {},
|
|
13090
13095
|
...breakers ? { breakers } : {},
|
|
@@ -13094,7 +13099,7 @@ function coordinateTool(providers, allowlist, bridge, innerCallers, storage, bre
|
|
|
13094
13099
|
})
|
|
13095
13100
|
};
|
|
13096
13101
|
}
|
|
13097
|
-
function debateTool(providers, allowlist,
|
|
13102
|
+
function debateTool(providers, allowlist, innerCallers, storage, pricing, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
13098
13103
|
return {
|
|
13099
13104
|
name: "debate",
|
|
13100
13105
|
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).",
|
|
@@ -13124,7 +13129,6 @@ function debateTool(providers, allowlist, bridge, innerCallers, storage, pricing
|
|
|
13124
13129
|
handler: (args) => runDebate(args, {
|
|
13125
13130
|
providers,
|
|
13126
13131
|
allowlist,
|
|
13127
|
-
...bridge ? { bridge } : {},
|
|
13128
13132
|
innerCallers,
|
|
13129
13133
|
...storage ? { storage } : {},
|
|
13130
13134
|
...pricing ? { pricing } : {},
|
|
@@ -13144,10 +13148,10 @@ function buildInnerCallers(o) {
|
|
|
13144
13148
|
...o.repoRoot ? { repoRoot: o.repoRoot } : {}
|
|
13145
13149
|
});
|
|
13146
13150
|
}
|
|
13147
|
-
out.verify = (args) => runVerify(args, o.
|
|
13151
|
+
out.verify = (args) => runVerify(args, o.fetchConfig);
|
|
13148
13152
|
return out;
|
|
13149
13153
|
}
|
|
13150
|
-
function conferTool(providers, allowlist,
|
|
13154
|
+
function conferTool(providers, allowlist, moderator, pricing, storage, innerCallers, breakers, transcriptsDir, repoRoot, workerToolsCfg) {
|
|
13151
13155
|
return {
|
|
13152
13156
|
name: "confer",
|
|
13153
13157
|
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).",
|
|
@@ -13174,7 +13178,6 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
|
|
|
13174
13178
|
handler: (args) => runConfer(args, {
|
|
13175
13179
|
providers,
|
|
13176
13180
|
allowlist,
|
|
13177
|
-
...bridge ? { bridge } : {},
|
|
13178
13181
|
moderator,
|
|
13179
13182
|
...pricing ? { pricing } : {},
|
|
13180
13183
|
...storage ? { storage } : {},
|
|
@@ -13186,7 +13189,7 @@ function conferTool(providers, allowlist, bridge, moderator, pricing, storage, i
|
|
|
13186
13189
|
})
|
|
13187
13190
|
};
|
|
13188
13191
|
}
|
|
13189
|
-
function auditTool(providers, allowlist,
|
|
13192
|
+
function auditTool(providers, allowlist, transcriptsDir, pricing, storage, breakers, repoRoot) {
|
|
13190
13193
|
return {
|
|
13191
13194
|
name: "audit",
|
|
13192
13195
|
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.",
|
|
@@ -13212,7 +13215,6 @@ function auditTool(providers, allowlist, bridge, transcriptsDir, pricing, storag
|
|
|
13212
13215
|
handler: (args) => runAudit(args, {
|
|
13213
13216
|
providers,
|
|
13214
13217
|
allowlist,
|
|
13215
|
-
...bridge ? { bridge } : {},
|
|
13216
13218
|
...transcriptsDir ? { transcriptsDir } : {},
|
|
13217
13219
|
...pricing ? { pricing } : {},
|
|
13218
13220
|
...storage ? { storage } : {},
|
|
@@ -13276,7 +13278,7 @@ function pickTool(providers, allowlist, storage, breakers, transcriptsDir, repoR
|
|
|
13276
13278
|
})
|
|
13277
13279
|
};
|
|
13278
13280
|
}
|
|
13279
|
-
function verifyTool(
|
|
13281
|
+
function verifyTool(fetchConfig) {
|
|
13280
13282
|
return {
|
|
13281
13283
|
name: "verify",
|
|
13282
13284
|
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.",
|
|
@@ -13294,7 +13296,7 @@ function verifyTool(bridge, fetchConfig) {
|
|
|
13294
13296
|
},
|
|
13295
13297
|
required: ["checks"]
|
|
13296
13298
|
},
|
|
13297
|
-
handler: (args) => runVerify(args,
|
|
13299
|
+
handler: (args) => runVerify(args, fetchConfig)
|
|
13298
13300
|
};
|
|
13299
13301
|
}
|
|
13300
13302
|
function pingTool() {
|
|
@@ -13378,6 +13380,64 @@ async function flush() {
|
|
|
13378
13380
|
}
|
|
13379
13381
|
}
|
|
13380
13382
|
|
|
13383
|
+
// src/core/process-registry.ts
|
|
13384
|
+
import { mkdirSync as mkdirSync8, readdirSync as readdirSync5, readFileSync as readFileSync13, rmSync, writeFileSync as writeFileSync8 } from "fs";
|
|
13385
|
+
import os2 from "os";
|
|
13386
|
+
import path11 from "path";
|
|
13387
|
+
function registryDir(env = process.env) {
|
|
13388
|
+
const base = env["CROSSCHECK_DATA_DIR"] || path11.join(env["HOME"] ?? env["USERPROFILE"] ?? os2.homedir(), ".crosscheck");
|
|
13389
|
+
return path11.join(base, "procs");
|
|
13390
|
+
}
|
|
13391
|
+
function isAlive(pid) {
|
|
13392
|
+
try {
|
|
13393
|
+
process.kill(pid, 0);
|
|
13394
|
+
return true;
|
|
13395
|
+
} catch (err) {
|
|
13396
|
+
return err.code === "EPERM";
|
|
13397
|
+
}
|
|
13398
|
+
}
|
|
13399
|
+
function listProcesses(installedVersion, env = process.env, now = Date.now()) {
|
|
13400
|
+
const dir = registryDir(env);
|
|
13401
|
+
let files;
|
|
13402
|
+
try {
|
|
13403
|
+
files = readdirSync5(dir).filter((f) => f.endsWith(".json"));
|
|
13404
|
+
} catch {
|
|
13405
|
+
return [];
|
|
13406
|
+
}
|
|
13407
|
+
const out = [];
|
|
13408
|
+
for (const f of files) {
|
|
13409
|
+
let rec;
|
|
13410
|
+
try {
|
|
13411
|
+
rec = JSON.parse(readFileSync13(path11.join(dir, f), "utf8"));
|
|
13412
|
+
} catch {
|
|
13413
|
+
try {
|
|
13414
|
+
rmSync(path11.join(dir, f), { force: true });
|
|
13415
|
+
} catch {
|
|
13416
|
+
}
|
|
13417
|
+
continue;
|
|
13418
|
+
}
|
|
13419
|
+
if (typeof rec.pid !== "number") continue;
|
|
13420
|
+
const alive = isAlive(rec.pid);
|
|
13421
|
+
if (!alive) {
|
|
13422
|
+
try {
|
|
13423
|
+
rmSync(path11.join(dir, f), { force: true });
|
|
13424
|
+
} catch {
|
|
13425
|
+
}
|
|
13426
|
+
continue;
|
|
13427
|
+
}
|
|
13428
|
+
out.push({
|
|
13429
|
+
...rec,
|
|
13430
|
+
alive,
|
|
13431
|
+
outdated: Boolean(rec.version) && rec.version !== installedVersion,
|
|
13432
|
+
ageMs: Math.max(0, now - (rec.startedAt ?? now))
|
|
13433
|
+
});
|
|
13434
|
+
}
|
|
13435
|
+
return out.sort((a, b) => a.startedAt - b.startedAt);
|
|
13436
|
+
}
|
|
13437
|
+
function processRegistryPath(env = process.env) {
|
|
13438
|
+
return registryDir(env);
|
|
13439
|
+
}
|
|
13440
|
+
|
|
13381
13441
|
// src/entrypoints/embed.ts
|
|
13382
13442
|
var KEY_ENV = {
|
|
13383
13443
|
anthropic: "ANTHROPIC_API_KEY",
|
|
@@ -13405,6 +13465,107 @@ var ENGINE_TO_VAULT = { xai: "grok" };
|
|
|
13405
13465
|
function vaultId(engineName) {
|
|
13406
13466
|
return ENGINE_TO_VAULT[engineName] ?? engineName;
|
|
13407
13467
|
}
|
|
13468
|
+
var ACTIVITY_TEXT_CAP = 8e3;
|
|
13469
|
+
var ASKED_CAP = 280;
|
|
13470
|
+
var runContext = new AsyncLocalStorage2();
|
|
13471
|
+
var SYNTHESIS_PURPOSES = /* @__PURE__ */ new Set(["synth", "moderator", "recombine", "judge", "unify"]);
|
|
13472
|
+
function exemptFromSkip(ctx, provider, purpose) {
|
|
13473
|
+
return provider === ctx.moderator && SYNTHESIS_PURPOSES.has(purpose);
|
|
13474
|
+
}
|
|
13475
|
+
function skippedError(provider, why, limitMs) {
|
|
13476
|
+
return new ProviderError(
|
|
13477
|
+
"client",
|
|
13478
|
+
why === "timeout" ? `${provider}: stopped after ${Math.round((limitMs ?? 0) / 1e3)}s (your per-model time limit)` : `${provider}: stopped waiting (you skipped it)`,
|
|
13479
|
+
{ transient: false }
|
|
13480
|
+
);
|
|
13481
|
+
}
|
|
13482
|
+
function lastUserText(args) {
|
|
13483
|
+
const msgs = args.messages;
|
|
13484
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
13485
|
+
const m = msgs[i];
|
|
13486
|
+
if (m && m.role === "user" && typeof m.content === "string") {
|
|
13487
|
+
const t = m.content.replace(/\s+/g, " ").trim();
|
|
13488
|
+
return t.length > ASKED_CAP ? `${t.slice(0, ASKED_CAP - 1)}\u2026` : t;
|
|
13489
|
+
}
|
|
13490
|
+
}
|
|
13491
|
+
return "";
|
|
13492
|
+
}
|
|
13493
|
+
function withActivity(p) {
|
|
13494
|
+
const send = p.send.bind(p);
|
|
13495
|
+
return {
|
|
13496
|
+
name: p.name,
|
|
13497
|
+
model: p.model,
|
|
13498
|
+
...p.fallbackModels ? { fallbackModels: p.fallbackModels } : {},
|
|
13499
|
+
send: async (args) => {
|
|
13500
|
+
const ctx = runContext.getStore();
|
|
13501
|
+
if (!ctx) return send(args);
|
|
13502
|
+
const callId = ctx.nextCallId();
|
|
13503
|
+
const provider = vaultId(p.name);
|
|
13504
|
+
const model = args.modelOverride ?? p.model;
|
|
13505
|
+
const purpose = args.purpose ?? "worker";
|
|
13506
|
+
const started = Date.now();
|
|
13507
|
+
const exempt = exemptFromSkip(ctx, provider, purpose);
|
|
13508
|
+
if (!exempt && ctx.skipped.has(provider)) throw skippedError(provider, "user");
|
|
13509
|
+
ctx.emit({ type: "call.start", runId: ctx.runId, at: started, callId, provider, model, purpose, asked: lastUserText(args) });
|
|
13510
|
+
const controller = new AbortController();
|
|
13511
|
+
if (args.signal) {
|
|
13512
|
+
if (args.signal.aborted) controller.abort(args.signal.reason);
|
|
13513
|
+
else args.signal.addEventListener("abort", () => controller.abort(args.signal.reason), { once: true });
|
|
13514
|
+
}
|
|
13515
|
+
let stopped;
|
|
13516
|
+
if (!exempt) ctx.inflight.set(callId, { provider, purpose, controller });
|
|
13517
|
+
const timer = !exempt && ctx.callTimeoutMs && ctx.callTimeoutMs > 0 ? setTimeout(() => {
|
|
13518
|
+
stopped = "timeout";
|
|
13519
|
+
controller.abort("timeout");
|
|
13520
|
+
}, ctx.callTimeoutMs) : void 0;
|
|
13521
|
+
controller.signal.addEventListener("abort", () => {
|
|
13522
|
+
if (!stopped && controller.signal.reason === "skip") stopped = "user";
|
|
13523
|
+
}, { once: true });
|
|
13524
|
+
try {
|
|
13525
|
+
const res = await send({ ...args, signal: controller.signal });
|
|
13526
|
+
const text = typeof res.text === "string" ? res.text : "";
|
|
13527
|
+
ctx.emit({
|
|
13528
|
+
type: "call.done",
|
|
13529
|
+
runId: ctx.runId,
|
|
13530
|
+
at: Date.now(),
|
|
13531
|
+
callId,
|
|
13532
|
+
provider,
|
|
13533
|
+
model,
|
|
13534
|
+
purpose,
|
|
13535
|
+
ok: true,
|
|
13536
|
+
ms: Date.now() - started,
|
|
13537
|
+
text: text.slice(0, ACTIVITY_TEXT_CAP),
|
|
13538
|
+
truncated: text.length > ACTIVITY_TEXT_CAP,
|
|
13539
|
+
error: null,
|
|
13540
|
+
usage: usageOf(res)
|
|
13541
|
+
});
|
|
13542
|
+
return res;
|
|
13543
|
+
} catch (err) {
|
|
13544
|
+
const out = stopped ? skippedError(provider, stopped, ctx.callTimeoutMs) : err;
|
|
13545
|
+
ctx.emit({
|
|
13546
|
+
type: "call.done",
|
|
13547
|
+
runId: ctx.runId,
|
|
13548
|
+
at: Date.now(),
|
|
13549
|
+
callId,
|
|
13550
|
+
provider,
|
|
13551
|
+
model,
|
|
13552
|
+
purpose,
|
|
13553
|
+
ok: false,
|
|
13554
|
+
ms: Date.now() - started,
|
|
13555
|
+
text: "",
|
|
13556
|
+
truncated: false,
|
|
13557
|
+
error: out instanceof Error ? out.message : String(out),
|
|
13558
|
+
usage: null,
|
|
13559
|
+
...stopped ? { stopped } : {}
|
|
13560
|
+
});
|
|
13561
|
+
throw out;
|
|
13562
|
+
} finally {
|
|
13563
|
+
if (timer) clearTimeout(timer);
|
|
13564
|
+
ctx.inflight.delete(callId);
|
|
13565
|
+
}
|
|
13566
|
+
}
|
|
13567
|
+
};
|
|
13568
|
+
}
|
|
13408
13569
|
function usageOf(answer) {
|
|
13409
13570
|
const u = answer["usage"];
|
|
13410
13571
|
if (!u || typeof u !== "object") return null;
|
|
@@ -13434,12 +13595,14 @@ function errorOf(answer) {
|
|
|
13434
13595
|
}
|
|
13435
13596
|
function bundledPricingPath() {
|
|
13436
13597
|
try {
|
|
13437
|
-
return
|
|
13598
|
+
return path12.join(path12.dirname(fileURLToPath2(import.meta.url)), "pricing.json");
|
|
13438
13599
|
} catch {
|
|
13439
13600
|
return void 0;
|
|
13440
13601
|
}
|
|
13441
13602
|
}
|
|
13442
13603
|
var runCounter = 0;
|
|
13604
|
+
var callCounter = 0;
|
|
13605
|
+
var nextCallId = () => ++callCounter;
|
|
13443
13606
|
function nextRunId() {
|
|
13444
13607
|
runCounter += 1;
|
|
13445
13608
|
return `run_${Date.now().toString(36)}_${runCounter}`;
|
|
@@ -13458,7 +13621,9 @@ function createEmbeddedEngine(opts) {
|
|
|
13458
13621
|
(p) => Boolean(p) && existsSync11(p)
|
|
13459
13622
|
);
|
|
13460
13623
|
const pricing = pricingPath ? loadPricing(pricingPath) : {};
|
|
13461
|
-
const built =
|
|
13624
|
+
const built = Object.fromEntries(
|
|
13625
|
+
Object.entries(buildProviders({ env, pricing })).map(([name, p]) => [name, withActivity(p)])
|
|
13626
|
+
);
|
|
13462
13627
|
const moderator = opts.moderator ?? "anthropic";
|
|
13463
13628
|
const tools = registerCoreTools({ providers: built, pricing });
|
|
13464
13629
|
const providerIds = Object.keys(built).map(vaultId).sort();
|
|
@@ -13475,7 +13640,8 @@ function createEmbeddedEngine(opts) {
|
|
|
13475
13640
|
if (!tool) return Promise.reject(new Error(`unknown tool: ${name}`));
|
|
13476
13641
|
return Promise.resolve(tool.handler(args));
|
|
13477
13642
|
};
|
|
13478
|
-
const
|
|
13643
|
+
const liveRuns = /* @__PURE__ */ new Map();
|
|
13644
|
+
const run = async (name, args, onEvent, runOpts = {}) => {
|
|
13479
13645
|
const runId = nextRunId();
|
|
13480
13646
|
const started = Date.now();
|
|
13481
13647
|
const emit = (e) => {
|
|
@@ -13484,6 +13650,78 @@ function createEmbeddedEngine(opts) {
|
|
|
13484
13650
|
} catch {
|
|
13485
13651
|
}
|
|
13486
13652
|
};
|
|
13653
|
+
const ctx = {
|
|
13654
|
+
runId,
|
|
13655
|
+
emit,
|
|
13656
|
+
nextCallId,
|
|
13657
|
+
skipped: /* @__PURE__ */ new Set(),
|
|
13658
|
+
inflight: /* @__PURE__ */ new Map(),
|
|
13659
|
+
moderator: vaultId(moderator),
|
|
13660
|
+
...runOpts.callTimeoutMs && runOpts.callTimeoutMs > 0 ? { callTimeoutMs: runOpts.callTimeoutMs } : {}
|
|
13661
|
+
};
|
|
13662
|
+
liveRuns.set(runId, ctx);
|
|
13663
|
+
try {
|
|
13664
|
+
return await runContext.run(ctx, () => withProgress(runId, (n) => {
|
|
13665
|
+
if (n.params.message) emit({ type: "progress", runId, at: Date.now(), message: n.params.message });
|
|
13666
|
+
}, () => runInner(name, args, runId, started, emit)));
|
|
13667
|
+
} finally {
|
|
13668
|
+
liveRuns.delete(runId);
|
|
13669
|
+
}
|
|
13670
|
+
};
|
|
13671
|
+
const skip = (runId, provider) => {
|
|
13672
|
+
const ctx = liveRuns.get(runId);
|
|
13673
|
+
if (!ctx) return 0;
|
|
13674
|
+
ctx.skipped.add(provider);
|
|
13675
|
+
let stopped = 0;
|
|
13676
|
+
for (const call2 of ctx.inflight.values()) {
|
|
13677
|
+
if (call2.provider === provider && !exemptFromSkip(ctx, call2.provider, call2.purpose)) {
|
|
13678
|
+
call2.controller.abort("skip");
|
|
13679
|
+
stopped += 1;
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13682
|
+
return stopped;
|
|
13683
|
+
};
|
|
13684
|
+
const ask = async (o) => {
|
|
13685
|
+
const engineName = Object.keys(built).find((n) => vaultId(n) === o.provider);
|
|
13686
|
+
const base = engineName ? built[engineName] : void 0;
|
|
13687
|
+
if (!base) {
|
|
13688
|
+
return { ok: false, text: "", json: null, model: o.model ?? "", error: `No ${o.provider} key is configured, so it can't be asked.` };
|
|
13689
|
+
}
|
|
13690
|
+
const provider = o.model && o.model !== base.model ? retargetProvider(base, o.model) : base;
|
|
13691
|
+
const maxTokens = o.maxTokens ?? 8e3;
|
|
13692
|
+
const doAsk = async () => {
|
|
13693
|
+
if (o.schema) {
|
|
13694
|
+
const res = await requestStructured(provider, o.messages, o.schema, { maxTokens, purpose: o.purpose, maxRetries: 1 });
|
|
13695
|
+
return {
|
|
13696
|
+
ok: res.obj !== null,
|
|
13697
|
+
text: res.answer.response ?? "",
|
|
13698
|
+
json: res.obj,
|
|
13699
|
+
error: res.obj !== null ? null : res.answer.error ?? res.errors.join("; ") ?? "invalid reply",
|
|
13700
|
+
model: provider.model
|
|
13701
|
+
};
|
|
13702
|
+
}
|
|
13703
|
+
const a = await askOne(provider, o.messages, { maxTokens, temperature: 0.3, purpose: o.purpose });
|
|
13704
|
+
return { ok: !a.error, text: a.response ?? "", json: null, error: a.error ?? null, model: provider.model };
|
|
13705
|
+
};
|
|
13706
|
+
if (!o.runId || !o.onEvent) return doAsk();
|
|
13707
|
+
const sink = o.onEvent;
|
|
13708
|
+
const emit = (e) => {
|
|
13709
|
+
try {
|
|
13710
|
+
sink(e);
|
|
13711
|
+
} catch {
|
|
13712
|
+
}
|
|
13713
|
+
};
|
|
13714
|
+
const ctx = {
|
|
13715
|
+
runId: o.runId,
|
|
13716
|
+
emit,
|
|
13717
|
+
nextCallId,
|
|
13718
|
+
skipped: /* @__PURE__ */ new Set(),
|
|
13719
|
+
inflight: /* @__PURE__ */ new Map(),
|
|
13720
|
+
moderator: o.provider
|
|
13721
|
+
};
|
|
13722
|
+
return runContext.run(ctx, doAsk);
|
|
13723
|
+
};
|
|
13724
|
+
const runInner = async (name, args, runId, started, emit) => {
|
|
13487
13725
|
emit({
|
|
13488
13726
|
type: "run.start",
|
|
13489
13727
|
runId,
|
|
@@ -13561,8 +13799,16 @@ function createEmbeddedEngine(opts) {
|
|
|
13561
13799
|
providers: providerIds,
|
|
13562
13800
|
models,
|
|
13563
13801
|
listTools: () => [...tools.keys()],
|
|
13802
|
+
requiredArgs: (name) => {
|
|
13803
|
+
const tool = tools.get(name);
|
|
13804
|
+
if (!tool) return null;
|
|
13805
|
+
const req = tool.inputSchema?.required;
|
|
13806
|
+
return Array.isArray(req) ? req.filter((x) => typeof x === "string") : [];
|
|
13807
|
+
},
|
|
13564
13808
|
call,
|
|
13565
13809
|
run,
|
|
13810
|
+
skip,
|
|
13811
|
+
ask,
|
|
13566
13812
|
close: async () => {
|
|
13567
13813
|
await flush().catch(() => {
|
|
13568
13814
|
});
|
|
@@ -13571,12 +13817,16 @@ function createEmbeddedEngine(opts) {
|
|
|
13571
13817
|
}
|
|
13572
13818
|
var __test_internals = { usageOf, textOf, errorOf, vaultId };
|
|
13573
13819
|
export {
|
|
13820
|
+
ACTIVITY_TEXT_CAP,
|
|
13574
13821
|
DEFAULT_EXCLUDED_PROVIDERS,
|
|
13575
13822
|
DEFAULT_FALLBACKS,
|
|
13576
13823
|
DEFAULT_MODELS,
|
|
13577
13824
|
KEY_ENV as __KEY_ENV,
|
|
13578
13825
|
MODEL_ENV as __MODEL_ENV,
|
|
13579
13826
|
__test_internals,
|
|
13580
|
-
createEmbeddedEngine
|
|
13827
|
+
createEmbeddedEngine,
|
|
13828
|
+
isAlive,
|
|
13829
|
+
listProcesses,
|
|
13830
|
+
processRegistryPath
|
|
13581
13831
|
};
|
|
13582
13832
|
//# sourceMappingURL=embed.js.map
|