crosscheck-mcp 0.1.9 → 0.1.11
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/dist/node-stdio.cjs +214 -15
- package/dist/node-stdio.cjs.map +1 -1
- package/dist/node-stdio.js +214 -15
- package/dist/node-stdio.js.map +1 -1
- package/package.json +1 -1
package/dist/node-stdio.cjs
CHANGED
|
@@ -1815,6 +1815,11 @@ async function sendOpenAICompatible(args) {
|
|
|
1815
1815
|
body.reasoning_effort = effort;
|
|
1816
1816
|
}
|
|
1817
1817
|
}
|
|
1818
|
+
if (isReasoningModel(args.provider, args.model) && typeof body.max_completion_tokens === "number") {
|
|
1819
|
+
const raw = Number(process.env["CROSSCHECK_OPENAI_REASONING_HEADROOM_TOKENS"]);
|
|
1820
|
+
const headroom = Number.isFinite(raw) && raw >= 0 ? Math.trunc(raw) : 25e3;
|
|
1821
|
+
body.max_completion_tokens += headroom;
|
|
1822
|
+
}
|
|
1818
1823
|
const doFetch = args.fetchImpl ?? globalThis.fetch;
|
|
1819
1824
|
const init = {
|
|
1820
1825
|
method: "POST",
|
|
@@ -7449,14 +7454,14 @@ function detectCycle(nodes) {
|
|
|
7449
7454
|
indeg[id] = (indeg[id] ?? 0) + 1;
|
|
7450
7455
|
}
|
|
7451
7456
|
}
|
|
7452
|
-
const
|
|
7457
|
+
const queue2 = Object.keys(indeg).filter((id) => indeg[id] === 0);
|
|
7453
7458
|
let processed = 0;
|
|
7454
|
-
while (
|
|
7455
|
-
const id =
|
|
7459
|
+
while (queue2.length > 0) {
|
|
7460
|
+
const id = queue2.shift();
|
|
7456
7461
|
processed++;
|
|
7457
7462
|
for (const next of consumers[id] ?? []) {
|
|
7458
7463
|
indeg[next] = (indeg[next] ?? 0) - 1;
|
|
7459
|
-
if (indeg[next] === 0)
|
|
7464
|
+
if (indeg[next] === 0) queue2.push(next);
|
|
7460
7465
|
}
|
|
7461
7466
|
}
|
|
7462
7467
|
return processed === Object.keys(byId).length ? null : "cycle detected (Kahn's algorithm didn't process all nodes)";
|
|
@@ -7495,13 +7500,13 @@ function topologicalSort(nodesById) {
|
|
|
7495
7500
|
}
|
|
7496
7501
|
}
|
|
7497
7502
|
const order = [];
|
|
7498
|
-
const
|
|
7499
|
-
while (
|
|
7500
|
-
const id =
|
|
7503
|
+
const queue2 = Object.keys(indeg).filter((id) => indeg[id] === 0);
|
|
7504
|
+
while (queue2.length > 0) {
|
|
7505
|
+
const id = queue2.shift();
|
|
7501
7506
|
order.push(id);
|
|
7502
7507
|
for (const next of consumers[id] ?? []) {
|
|
7503
7508
|
indeg[next] = (indeg[next] ?? 0) - 1;
|
|
7504
|
-
if (indeg[next] === 0)
|
|
7509
|
+
if (indeg[next] === 0) queue2.push(next);
|
|
7505
7510
|
}
|
|
7506
7511
|
}
|
|
7507
7512
|
return order;
|
|
@@ -11343,7 +11348,7 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
|
|
|
11343
11348
|
var DEFAULT_PACKAGE = "crosscheck-cli";
|
|
11344
11349
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
11345
11350
|
function engineVersion() {
|
|
11346
|
-
return true ? "0.1.
|
|
11351
|
+
return true ? "0.1.11" : "0.0.0-dev";
|
|
11347
11352
|
}
|
|
11348
11353
|
function defaultUpdateCachePath() {
|
|
11349
11354
|
const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path12.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
|
|
@@ -12023,7 +12028,7 @@ function solveTool(providers, allowlist, bridge, storage, breakers, transcriptsD
|
|
|
12023
12028
|
})
|
|
12024
12029
|
};
|
|
12025
12030
|
}
|
|
12026
|
-
function configPinTool(repoRoot,
|
|
12031
|
+
function configPinTool(repoRoot, config2, rejectDriftEnv) {
|
|
12027
12032
|
return {
|
|
12028
12033
|
name: "config_pin",
|
|
12029
12034
|
description: "CRUD over the config-pinning ledger. Tracks SHA256s of the canonical config files (config/pricing.json, etc.) and detects drift. Actions: show, set, accept_drift, clear. The actual drift-rejection gate is wired separately in the host.",
|
|
@@ -12048,7 +12053,7 @@ function configPinTool(repoRoot, config, rejectDriftEnv) {
|
|
|
12048
12053
|
}
|
|
12049
12054
|
return runConfigPin(args, {
|
|
12050
12055
|
repoRoot,
|
|
12051
|
-
...
|
|
12056
|
+
...config2 ? { config: config2 } : {},
|
|
12052
12057
|
rejectDriftEnv
|
|
12053
12058
|
});
|
|
12054
12059
|
}
|
|
@@ -12688,9 +12693,194 @@ function attachUpdateNotice(result, toolName, opts) {
|
|
|
12688
12693
|
}
|
|
12689
12694
|
}
|
|
12690
12695
|
|
|
12696
|
+
// src/core/telemetry.ts
|
|
12697
|
+
init_cjs_shims();
|
|
12698
|
+
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
12699
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
12700
|
+
var BATCH_MAX = 100;
|
|
12701
|
+
var FLUSH_BATCH_AT = 25;
|
|
12702
|
+
var FLUSH_INTERVAL_MS = 15e3;
|
|
12703
|
+
var MAX_QUEUE = 500;
|
|
12704
|
+
var POST_TIMEOUT_MS = 5e3;
|
|
12705
|
+
var PROVIDER_TO_SCHEMA = {
|
|
12706
|
+
anthropic: "anthropic",
|
|
12707
|
+
openai: "openai",
|
|
12708
|
+
gemini: "gemini",
|
|
12709
|
+
xai: "grok",
|
|
12710
|
+
grok: "grok"
|
|
12711
|
+
};
|
|
12712
|
+
var TOOL_TO_PATTERN = {
|
|
12713
|
+
confer: "confer",
|
|
12714
|
+
debate: "debate",
|
|
12715
|
+
audit: "audit",
|
|
12716
|
+
plan: "plan",
|
|
12717
|
+
pick: "panel_pick",
|
|
12718
|
+
verify: "verify",
|
|
12719
|
+
critique: "critique",
|
|
12720
|
+
solve: "solve"
|
|
12721
|
+
};
|
|
12722
|
+
function providerToSchema(provider) {
|
|
12723
|
+
return PROVIDER_TO_SCHEMA[String(provider).toLowerCase()] ?? null;
|
|
12724
|
+
}
|
|
12725
|
+
function toolToPattern(toolName) {
|
|
12726
|
+
return TOOL_TO_PATTERN[String(toolName).toLowerCase()] ?? "other";
|
|
12727
|
+
}
|
|
12728
|
+
function canonicalEventBody(e) {
|
|
12729
|
+
return [
|
|
12730
|
+
e.eventId,
|
|
12731
|
+
e.seatId,
|
|
12732
|
+
e.orgId,
|
|
12733
|
+
e.ts,
|
|
12734
|
+
e.provider,
|
|
12735
|
+
e.model,
|
|
12736
|
+
e.pattern,
|
|
12737
|
+
String(e.promptTokens),
|
|
12738
|
+
String(e.completionTokens),
|
|
12739
|
+
e.costUsdEstimate.toFixed(6),
|
|
12740
|
+
String(e.latencyMs),
|
|
12741
|
+
e.status,
|
|
12742
|
+
e.errorClass ?? ""
|
|
12743
|
+
].join("|");
|
|
12744
|
+
}
|
|
12745
|
+
function signEvent(seatSigningKey, e) {
|
|
12746
|
+
return import_node_crypto7.default.createHmac("sha256", seatSigningKey).update(canonicalEventBody(e)).digest("hex");
|
|
12747
|
+
}
|
|
12748
|
+
var configResolved = false;
|
|
12749
|
+
var config = null;
|
|
12750
|
+
function getConfig() {
|
|
12751
|
+
if (configResolved) return config;
|
|
12752
|
+
configResolved = true;
|
|
12753
|
+
if (process.env["CROSSCHECK_TELEMETRY"] === "off") return config = null;
|
|
12754
|
+
const url = process.env["CROSSCHECK_TELEMETRY_URL"];
|
|
12755
|
+
const seatId = process.env["CROSSCHECK_SEAT_ID"];
|
|
12756
|
+
const orgId = process.env["CROSSCHECK_ORG_ID"];
|
|
12757
|
+
const seatKey = process.env["CROSSCHECK_SEAT_HMAC_KEY"];
|
|
12758
|
+
if (!url || !seatId || !orgId || !seatKey) return config = null;
|
|
12759
|
+
if (!UUID_RE.test(seatId) || !UUID_RE.test(orgId)) return config = null;
|
|
12760
|
+
config = { url, seatId, orgId, seatKey };
|
|
12761
|
+
return config;
|
|
12762
|
+
}
|
|
12763
|
+
function intNonNeg(v) {
|
|
12764
|
+
const n = Math.trunc(Number(v));
|
|
12765
|
+
return Number.isFinite(n) && n > 0 ? n : 0;
|
|
12766
|
+
}
|
|
12767
|
+
function usageEventsFromEnvelope(out, toolName) {
|
|
12768
|
+
if (!out || typeof out !== "object" || Array.isArray(out)) return [];
|
|
12769
|
+
const usage = out["usage"];
|
|
12770
|
+
if (!usage || typeof usage !== "object") return [];
|
|
12771
|
+
const byCall = usage["by_call"];
|
|
12772
|
+
if (!Array.isArray(byCall) || byCall.length === 0) return [];
|
|
12773
|
+
const timing = out["timing"];
|
|
12774
|
+
const timingByCall = timing && typeof timing === "object" ? timing["by_call"] : void 0;
|
|
12775
|
+
const latencies = Array.isArray(timingByCall) ? timingByCall : [];
|
|
12776
|
+
const aligned = latencies.length === byCall.length;
|
|
12777
|
+
const pattern = toolToPattern(toolName);
|
|
12778
|
+
const events = [];
|
|
12779
|
+
for (let i = 0; i < byCall.length; i += 1) {
|
|
12780
|
+
const u = byCall[i];
|
|
12781
|
+
const provider = providerToSchema(String(u.provider ?? ""));
|
|
12782
|
+
if (!provider) continue;
|
|
12783
|
+
const model = String(u.model ?? "").slice(0, 128) || "unknown";
|
|
12784
|
+
const cost = Math.max(0, Number(u.cost_usd) || 0);
|
|
12785
|
+
const latencyMs = aligned ? intNonNeg(latencies[i]?.["wall_ms"]) : 0;
|
|
12786
|
+
events.push({
|
|
12787
|
+
provider,
|
|
12788
|
+
model,
|
|
12789
|
+
pattern,
|
|
12790
|
+
promptTokens: intNonNeg(u.prompt_tokens),
|
|
12791
|
+
completionTokens: intNonNeg(u.completion_tokens),
|
|
12792
|
+
costUsdEstimate: cost,
|
|
12793
|
+
latencyMs,
|
|
12794
|
+
status: "ok"
|
|
12795
|
+
});
|
|
12796
|
+
}
|
|
12797
|
+
return events;
|
|
12798
|
+
}
|
|
12799
|
+
var queue = [];
|
|
12800
|
+
var flushTimer = null;
|
|
12801
|
+
function scheduleFlush() {
|
|
12802
|
+
if (flushTimer) return;
|
|
12803
|
+
flushTimer = setTimeout(() => {
|
|
12804
|
+
flushTimer = null;
|
|
12805
|
+
void flush();
|
|
12806
|
+
}, FLUSH_INTERVAL_MS);
|
|
12807
|
+
if (typeof flushTimer.unref === "function") flushTimer.unref();
|
|
12808
|
+
}
|
|
12809
|
+
function enqueue(cfg, input) {
|
|
12810
|
+
const base = {
|
|
12811
|
+
eventId: import_node_crypto7.default.randomUUID(),
|
|
12812
|
+
seatId: cfg.seatId,
|
|
12813
|
+
orgId: cfg.orgId,
|
|
12814
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12815
|
+
provider: input.provider,
|
|
12816
|
+
model: input.model,
|
|
12817
|
+
pattern: input.pattern,
|
|
12818
|
+
promptTokens: input.promptTokens,
|
|
12819
|
+
completionTokens: input.completionTokens,
|
|
12820
|
+
costUsdEstimate: input.costUsdEstimate,
|
|
12821
|
+
latencyMs: input.latencyMs,
|
|
12822
|
+
status: input.status
|
|
12823
|
+
};
|
|
12824
|
+
const signatureHmac = signEvent(cfg.seatKey, base);
|
|
12825
|
+
queue.push({ ...base, signatureHmac });
|
|
12826
|
+
if (queue.length > MAX_QUEUE) queue.splice(0, queue.length - MAX_QUEUE);
|
|
12827
|
+
if (queue.length >= FLUSH_BATCH_AT) void flush();
|
|
12828
|
+
else scheduleFlush();
|
|
12829
|
+
}
|
|
12830
|
+
function recordUsage(out, toolName) {
|
|
12831
|
+
try {
|
|
12832
|
+
const cfg = getConfig();
|
|
12833
|
+
if (!cfg) return;
|
|
12834
|
+
if (toolName === "update_crosscheck") return;
|
|
12835
|
+
for (const ev of usageEventsFromEnvelope(out, toolName)) enqueue(cfg, ev);
|
|
12836
|
+
} catch {
|
|
12837
|
+
}
|
|
12838
|
+
}
|
|
12839
|
+
async function postBatch(url, batch) {
|
|
12840
|
+
let resp;
|
|
12841
|
+
try {
|
|
12842
|
+
resp = await fetch(url, {
|
|
12843
|
+
method: "POST",
|
|
12844
|
+
headers: { "content-type": "application/json" },
|
|
12845
|
+
body: JSON.stringify({ events: batch }),
|
|
12846
|
+
signal: AbortSignal.timeout(POST_TIMEOUT_MS)
|
|
12847
|
+
});
|
|
12848
|
+
} catch {
|
|
12849
|
+
queue.unshift(...batch);
|
|
12850
|
+
if (queue.length > MAX_QUEUE) queue.splice(0, queue.length - MAX_QUEUE);
|
|
12851
|
+
return;
|
|
12852
|
+
}
|
|
12853
|
+
if (resp.ok) return;
|
|
12854
|
+
if (resp.status === 400) {
|
|
12855
|
+
try {
|
|
12856
|
+
process.stderr.write(
|
|
12857
|
+
`crosscheck-agent: telemetry batch rejected (400), dropped ${batch.length} event(s)
|
|
12858
|
+
`
|
|
12859
|
+
);
|
|
12860
|
+
} catch {
|
|
12861
|
+
}
|
|
12862
|
+
return;
|
|
12863
|
+
}
|
|
12864
|
+
queue.unshift(...batch);
|
|
12865
|
+
if (queue.length > MAX_QUEUE) queue.splice(0, queue.length - MAX_QUEUE);
|
|
12866
|
+
}
|
|
12867
|
+
async function flush() {
|
|
12868
|
+
const cfg = getConfig();
|
|
12869
|
+
if (!cfg) return;
|
|
12870
|
+
if (flushTimer) {
|
|
12871
|
+
clearTimeout(flushTimer);
|
|
12872
|
+
flushTimer = null;
|
|
12873
|
+
}
|
|
12874
|
+
while (queue.length > 0) {
|
|
12875
|
+
const batch = queue.splice(0, BATCH_MAX);
|
|
12876
|
+
await postBatch(cfg.url, batch);
|
|
12877
|
+
if (queue.length > 0 && queue[0] === batch[0]) break;
|
|
12878
|
+
}
|
|
12879
|
+
}
|
|
12880
|
+
|
|
12691
12881
|
// src/server.ts
|
|
12692
12882
|
var SERVER_NAME = "crosscheck-agent";
|
|
12693
|
-
var SERVER_VERSION = true ? "0.1.
|
|
12883
|
+
var SERVER_VERSION = true ? "0.1.11" : "0.0.0-dev";
|
|
12694
12884
|
function extractRunSummaryText(out) {
|
|
12695
12885
|
if (out === null || typeof out !== "object" || Array.isArray(out)) return void 0;
|
|
12696
12886
|
const rs = out["run_summary"];
|
|
@@ -12772,10 +12962,9 @@ function createServer(opts = {}) {
|
|
|
12772
12962
|
() => tool.handler(args)
|
|
12773
12963
|
);
|
|
12774
12964
|
if (out && typeof out === "object" && !Array.isArray(out)) {
|
|
12775
|
-
attachUpdateNotice(out, name
|
|
12776
|
-
...opts.repoRoot ? { repoRoot: opts.repoRoot } : {}
|
|
12777
|
-
});
|
|
12965
|
+
attachUpdateNotice(out, name);
|
|
12778
12966
|
}
|
|
12967
|
+
recordUsage(out, name);
|
|
12779
12968
|
const durationMs = Number(
|
|
12780
12969
|
(process.hrtime.bigint() - startedHr) / 1000000n
|
|
12781
12970
|
);
|
|
@@ -12822,6 +13011,11 @@ function createServer(opts = {}) {
|
|
|
12822
13011
|
async function connectAndServe(transport, opts = {}) {
|
|
12823
13012
|
const server = createServer(opts);
|
|
12824
13013
|
await server.connect(transport);
|
|
13014
|
+
const cliVersion = process.env["CROSSCHECK_CLI_VERSION"];
|
|
13015
|
+
void maybeCheckForUpdate({
|
|
13016
|
+
currentVersion: cliVersion ?? SERVER_VERSION,
|
|
13017
|
+
packageName: cliVersion ? "crosscheck-cli" : "crosscheck-mcp"
|
|
13018
|
+
});
|
|
12825
13019
|
return server;
|
|
12826
13020
|
}
|
|
12827
13021
|
function buildToolRegistry(opts) {
|
|
@@ -12937,6 +13131,11 @@ function installShutdownHandlers(bridge) {
|
|
|
12937
13131
|
]).catch(() => {
|
|
12938
13132
|
});
|
|
12939
13133
|
}
|
|
13134
|
+
await Promise.race([
|
|
13135
|
+
flush(),
|
|
13136
|
+
new Promise((resolve2) => setTimeout(resolve2, SHUTDOWN_TIMEOUT_MS))
|
|
13137
|
+
]).catch(() => {
|
|
13138
|
+
});
|
|
12940
13139
|
process.stderr.write(`crosscheck-agent: shutdown (${reason})
|
|
12941
13140
|
`);
|
|
12942
13141
|
process.exit(0);
|