crosscheck-mcp 0.2.15 → 0.2.16
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/browser-ext.cjs +2 -2
- package/dist/browser-ext.js +2 -2
- package/dist/node-stdio.cjs +425 -192
- package/dist/node-stdio.cjs.map +1 -1
- package/dist/node-stdio.js +424 -191
- package/dist/node-stdio.js.map +1 -1
- package/package.json +1 -1
package/dist/node-stdio.cjs
CHANGED
|
@@ -958,8 +958,8 @@ __export(node_stdio_exports, {
|
|
|
958
958
|
});
|
|
959
959
|
module.exports = __toCommonJS(node_stdio_exports);
|
|
960
960
|
init_cjs_shims();
|
|
961
|
-
var
|
|
962
|
-
var
|
|
961
|
+
var import_node_fs19 = require("fs");
|
|
962
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
963
963
|
var import_node_url2 = require("url");
|
|
964
964
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
965
965
|
|
|
@@ -976,10 +976,10 @@ var StderrEmitter = class {
|
|
|
976
976
|
}
|
|
977
977
|
};
|
|
978
978
|
var FileEmitter = class {
|
|
979
|
-
constructor(
|
|
980
|
-
this.path =
|
|
979
|
+
constructor(path15) {
|
|
980
|
+
this.path = path15;
|
|
981
981
|
try {
|
|
982
|
-
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(
|
|
982
|
+
(0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(path15), { recursive: true });
|
|
983
983
|
} catch {
|
|
984
984
|
}
|
|
985
985
|
}
|
|
@@ -1012,13 +1012,13 @@ var NullEmitter = class {
|
|
|
1012
1012
|
function buildDefaultEmitter(env) {
|
|
1013
1013
|
const mode = (env["CROSSCHECK_EVENTS"] ?? "stderr").toLowerCase();
|
|
1014
1014
|
if (mode === "off") return new NullEmitter();
|
|
1015
|
-
const
|
|
1015
|
+
const path15 = env["CROSSCHECK_EVENTS_PATH"];
|
|
1016
1016
|
if (mode === "file") {
|
|
1017
|
-
return
|
|
1017
|
+
return path15 ? new FileEmitter(path15) : new NullEmitter();
|
|
1018
1018
|
}
|
|
1019
1019
|
if (mode === "both") {
|
|
1020
1020
|
const ems = [new StderrEmitter()];
|
|
1021
|
-
if (
|
|
1021
|
+
if (path15) ems.push(new FileEmitter(path15));
|
|
1022
1022
|
return new TeeEmitter(ems);
|
|
1023
1023
|
}
|
|
1024
1024
|
return new StderrEmitter();
|
|
@@ -1067,10 +1067,10 @@ function envelopeBytes(v) {
|
|
|
1067
1067
|
// src/core/pricing.ts
|
|
1068
1068
|
init_cjs_shims();
|
|
1069
1069
|
var import_node_fs2 = require("fs");
|
|
1070
|
-
function loadPricing(
|
|
1070
|
+
function loadPricing(path15) {
|
|
1071
1071
|
let raw;
|
|
1072
1072
|
try {
|
|
1073
|
-
raw = (0, import_node_fs2.readFileSync)(
|
|
1073
|
+
raw = (0, import_node_fs2.readFileSync)(path15, "utf8");
|
|
1074
1074
|
} catch {
|
|
1075
1075
|
return {};
|
|
1076
1076
|
}
|
|
@@ -1326,8 +1326,8 @@ function httpFailureToProviderError(provider, status, bodyText, retryAfterS, mod
|
|
|
1326
1326
|
// src/providers/retry.ts
|
|
1327
1327
|
init_cjs_shims();
|
|
1328
1328
|
var override = null;
|
|
1329
|
-
function setRetryConfig(
|
|
1330
|
-
override =
|
|
1329
|
+
function setRetryConfig(cfg2) {
|
|
1330
|
+
override = cfg2;
|
|
1331
1331
|
}
|
|
1332
1332
|
function resolveRetryConfig() {
|
|
1333
1333
|
const envInt = (k, d) => {
|
|
@@ -1389,21 +1389,21 @@ function defaultSleep(ms, signal) {
|
|
|
1389
1389
|
signal?.addEventListener?.("abort", onAbort);
|
|
1390
1390
|
});
|
|
1391
1391
|
}
|
|
1392
|
-
async function sendWithRetry(attemptOnce,
|
|
1392
|
+
async function sendWithRetry(attemptOnce, cfg2, signal, deps) {
|
|
1393
1393
|
const sleep = deps?.sleepImpl ?? ((ms) => defaultSleep(ms, signal));
|
|
1394
1394
|
const rand = deps?.random ?? Math.random;
|
|
1395
1395
|
let lastErr;
|
|
1396
|
-
for (let attempt = 1; attempt <=
|
|
1396
|
+
for (let attempt = 1; attempt <= cfg2.maxAttempts; attempt += 1) {
|
|
1397
1397
|
try {
|
|
1398
1398
|
const result = await attemptOnce();
|
|
1399
1399
|
return { ...result, attempts: attempt };
|
|
1400
1400
|
} catch (e) {
|
|
1401
1401
|
lastErr = e;
|
|
1402
1402
|
const pe = e instanceof ProviderError ? e : null;
|
|
1403
|
-
if (pe?.transient !== true || attempt >=
|
|
1404
|
-
let backoffMs = pe.retryAfterS !== void 0 ? pe.retryAfterS * 1e3 :
|
|
1405
|
-
backoffMs += rand() *
|
|
1406
|
-
backoffMs = Math.min(backoffMs,
|
|
1403
|
+
if (pe?.transient !== true || attempt >= cfg2.maxAttempts) throw e;
|
|
1404
|
+
let backoffMs = pe.retryAfterS !== void 0 ? pe.retryAfterS * 1e3 : cfg2.backoffBaseMs * 2 ** (attempt - 1);
|
|
1405
|
+
backoffMs += rand() * cfg2.backoffBaseMs;
|
|
1406
|
+
backoffMs = Math.min(backoffMs, cfg2.maxBackoffMs);
|
|
1407
1407
|
await sleep(backoffMs);
|
|
1408
1408
|
}
|
|
1409
1409
|
}
|
|
@@ -1415,8 +1415,8 @@ init_cjs_shims();
|
|
|
1415
1415
|
var DEFAULT_SPEC = { capacity: 5, refillPerSec: 5 };
|
|
1416
1416
|
var MAX_WAIT_SLICE_MS = 250;
|
|
1417
1417
|
var override2 = null;
|
|
1418
|
-
function setRateLimitConfig(
|
|
1419
|
-
override2 =
|
|
1418
|
+
function setRateLimitConfig(cfg2) {
|
|
1419
|
+
override2 = cfg2;
|
|
1420
1420
|
buckets.clear();
|
|
1421
1421
|
}
|
|
1422
1422
|
function disabled() {
|
|
@@ -2042,9 +2042,9 @@ function detectStalePins(env) {
|
|
|
2042
2042
|
const out = [];
|
|
2043
2043
|
for (const [provider, envVar] of Object.entries(MODEL_ENV_VARS)) {
|
|
2044
2044
|
const pinned = env[envVar];
|
|
2045
|
-
const
|
|
2046
|
-
if (pinned &&
|
|
2047
|
-
out.push({ provider, envVar, pinned, current });
|
|
2045
|
+
const current2 = DEFAULT_MODELS[provider];
|
|
2046
|
+
if (pinned && current2 && pinned !== current2) {
|
|
2047
|
+
out.push({ provider, envVar, pinned, current: current2 });
|
|
2048
2048
|
}
|
|
2049
2049
|
}
|
|
2050
2050
|
return out;
|
|
@@ -2275,7 +2275,7 @@ var import_zod = require("zod");
|
|
|
2275
2275
|
// src/server-meta.ts
|
|
2276
2276
|
init_cjs_shims();
|
|
2277
2277
|
var SERVER_NAME = "crosscheck-agent";
|
|
2278
|
-
var SERVER_VERSION = true ? "0.2.
|
|
2278
|
+
var SERVER_VERSION = true ? "0.2.16" : "0.0.0-dev";
|
|
2279
2279
|
|
|
2280
2280
|
// src/tools/audit.ts
|
|
2281
2281
|
init_cjs_shims();
|
|
@@ -2342,27 +2342,27 @@ function extractJson(text) {
|
|
|
2342
2342
|
|
|
2343
2343
|
// src/core/json-schema.ts
|
|
2344
2344
|
init_cjs_shims();
|
|
2345
|
-
function validateSchema(value, schema,
|
|
2345
|
+
function validateSchema(value, schema, path15 = "") {
|
|
2346
2346
|
const errs = [];
|
|
2347
2347
|
if ("anyOf" in schema) {
|
|
2348
2348
|
const subs = schema["anyOf"].map(
|
|
2349
|
-
(s) => validateSchema(value, s,
|
|
2349
|
+
(s) => validateSchema(value, s, path15)
|
|
2350
2350
|
);
|
|
2351
2351
|
if (!subs.some((e) => e.length === 0)) {
|
|
2352
|
-
errs.push(`${
|
|
2352
|
+
errs.push(`${path15 || "<root>"}: did not match anyOf`);
|
|
2353
2353
|
}
|
|
2354
2354
|
return errs;
|
|
2355
2355
|
}
|
|
2356
2356
|
if ("oneOf" in schema) {
|
|
2357
|
-
const passed = schema["oneOf"].filter((s) => validateSchema(value, s,
|
|
2357
|
+
const passed = schema["oneOf"].filter((s) => validateSchema(value, s, path15).length === 0).length;
|
|
2358
2358
|
if (passed !== 1) {
|
|
2359
|
-
errs.push(`${
|
|
2359
|
+
errs.push(`${path15 || "<root>"}: matched ${passed} of oneOf, expected 1`);
|
|
2360
2360
|
}
|
|
2361
2361
|
return errs;
|
|
2362
2362
|
}
|
|
2363
2363
|
if ("const" in schema && !deepEqual(value, schema["const"])) {
|
|
2364
2364
|
errs.push(
|
|
2365
|
-
`${
|
|
2365
|
+
`${path15 || "<root>"}: expected const ${pyRepr(schema["const"])}, got ${pyRepr(value)}`
|
|
2366
2366
|
);
|
|
2367
2367
|
return errs;
|
|
2368
2368
|
}
|
|
@@ -2372,7 +2372,7 @@ function validateSchema(value, schema, path14 = "") {
|
|
|
2372
2372
|
const ok = types.some((tt) => matchesType(value, String(tt)));
|
|
2373
2373
|
if (!ok) {
|
|
2374
2374
|
errs.push(
|
|
2375
|
-
`${
|
|
2375
|
+
`${path15 || "<root>"}: expected type ${pyReprType(t)}, got ${pyTypeName(value)}`
|
|
2376
2376
|
);
|
|
2377
2377
|
return errs;
|
|
2378
2378
|
}
|
|
@@ -2381,29 +2381,29 @@ function validateSchema(value, schema, path14 = "") {
|
|
|
2381
2381
|
if ("enum" in schema) {
|
|
2382
2382
|
const en = schema["enum"];
|
|
2383
2383
|
if (!en.some((x) => deepEqual(x, value))) {
|
|
2384
|
-
errs.push(`${
|
|
2384
|
+
errs.push(`${path15 || "<root>"}: value ${pyRepr(value)} not in enum`);
|
|
2385
2385
|
}
|
|
2386
2386
|
}
|
|
2387
2387
|
if ("minLength" in schema && value.length < schema["minLength"]) {
|
|
2388
|
-
errs.push(`${
|
|
2388
|
+
errs.push(`${path15 || "<root>"}: shorter than minLength ${schema["minLength"]}`);
|
|
2389
2389
|
}
|
|
2390
2390
|
}
|
|
2391
2391
|
if (typeof value === "number" && !Number.isNaN(value)) {
|
|
2392
2392
|
if ("minimum" in schema && value < schema["minimum"]) {
|
|
2393
|
-
errs.push(`${
|
|
2393
|
+
errs.push(`${path15 || "<root>"}: ${value} < minimum ${schema["minimum"]}`);
|
|
2394
2394
|
}
|
|
2395
2395
|
if ("maximum" in schema && value > schema["maximum"]) {
|
|
2396
|
-
errs.push(`${
|
|
2396
|
+
errs.push(`${path15 || "<root>"}: ${value} > maximum ${schema["maximum"]}`);
|
|
2397
2397
|
}
|
|
2398
2398
|
}
|
|
2399
2399
|
if (Array.isArray(value)) {
|
|
2400
2400
|
if ("minItems" in schema && value.length < schema["minItems"]) {
|
|
2401
|
-
errs.push(`${
|
|
2401
|
+
errs.push(`${path15 || "<root>"}: fewer items than minItems ${schema["minItems"]}`);
|
|
2402
2402
|
}
|
|
2403
2403
|
const itemSchema = schema["items"];
|
|
2404
2404
|
if (isObj(itemSchema)) {
|
|
2405
2405
|
for (let i = 0; i < value.length; i++) {
|
|
2406
|
-
errs.push(...validateSchema(value[i], itemSchema, `${
|
|
2406
|
+
errs.push(...validateSchema(value[i], itemSchema, `${path15}[${i}]`));
|
|
2407
2407
|
}
|
|
2408
2408
|
}
|
|
2409
2409
|
}
|
|
@@ -2412,19 +2412,19 @@ function validateSchema(value, schema, path14 = "") {
|
|
|
2412
2412
|
const required = schema["required"] ?? [];
|
|
2413
2413
|
for (const r of required) {
|
|
2414
2414
|
if (!(r in value)) {
|
|
2415
|
-
errs.push(`${
|
|
2415
|
+
errs.push(`${path15 || "<root>"}: missing required key ${pyRepr(r)}`);
|
|
2416
2416
|
}
|
|
2417
2417
|
}
|
|
2418
2418
|
if (schema["additionalProperties"] === false) {
|
|
2419
2419
|
for (const k of Object.keys(value)) {
|
|
2420
2420
|
if (!(k in props)) {
|
|
2421
|
-
errs.push(`${
|
|
2421
|
+
errs.push(`${path15 || "<root>"}: unknown key ${pyRepr(k)}`);
|
|
2422
2422
|
}
|
|
2423
2423
|
}
|
|
2424
2424
|
}
|
|
2425
2425
|
for (const [k, v] of Object.entries(value)) {
|
|
2426
2426
|
const ps = props[k];
|
|
2427
|
-
if (ps) errs.push(...validateSchema(v, ps,
|
|
2427
|
+
if (ps) errs.push(...validateSchema(v, ps, path15 ? `${path15}.${k}` : k));
|
|
2428
2428
|
}
|
|
2429
2429
|
}
|
|
2430
2430
|
return errs;
|
|
@@ -2925,8 +2925,8 @@ async function recordSessionCall(storage, sessionId, answers, wallMs, cpuMs, now
|
|
|
2925
2925
|
// src/core/budgets.ts
|
|
2926
2926
|
init_cjs_shims();
|
|
2927
2927
|
var operatorBudgets = null;
|
|
2928
|
-
function setOperatorBudgets(
|
|
2929
|
-
operatorBudgets =
|
|
2928
|
+
function setOperatorBudgets(cfg2) {
|
|
2929
|
+
operatorBudgets = cfg2;
|
|
2930
2930
|
}
|
|
2931
2931
|
function operatorCeiling(purpose, provider) {
|
|
2932
2932
|
const direct = operatorBudgets?.token_budgets?.[purpose];
|
|
@@ -3127,8 +3127,8 @@ function isPersonaId(s) {
|
|
|
3127
3127
|
return PERSONA_IDS.includes(s);
|
|
3128
3128
|
}
|
|
3129
3129
|
var personaConfig = null;
|
|
3130
|
-
function setPersonaConfig(
|
|
3131
|
-
personaConfig =
|
|
3130
|
+
function setPersonaConfig(cfg2) {
|
|
3131
|
+
personaConfig = cfg2;
|
|
3132
3132
|
}
|
|
3133
3133
|
var processFirstCallConsumed = false;
|
|
3134
3134
|
var sessionsSeen = /* @__PURE__ */ new Set();
|
|
@@ -3195,8 +3195,8 @@ function routePersona(prompt, toolName) {
|
|
|
3195
3195
|
return { id: "engineering", scores };
|
|
3196
3196
|
}
|
|
3197
3197
|
function resolvePersona(opts) {
|
|
3198
|
-
const
|
|
3199
|
-
if (
|
|
3198
|
+
const cfg2 = opts.config ?? personaConfig;
|
|
3199
|
+
if (cfg2?.enabled === false) return { id: null, source: "disabled", bypassed: true };
|
|
3200
3200
|
const explicit = opts.explicit?.trim().toLowerCase();
|
|
3201
3201
|
if (explicit === "none" || explicit === "off") {
|
|
3202
3202
|
return { id: null, source: "none", bypassed: true };
|
|
@@ -3242,12 +3242,12 @@ function readIfExists(p) {
|
|
|
3242
3242
|
}
|
|
3243
3243
|
}
|
|
3244
3244
|
function loadPersonaBody(id, opts) {
|
|
3245
|
-
const
|
|
3246
|
-
const cacheKey = `${id}|${opts?.repoRoot ?? ""}|${
|
|
3245
|
+
const cfg2 = opts?.config ?? personaConfig;
|
|
3246
|
+
const cacheKey = `${id}|${opts?.repoRoot ?? ""}|${cfg2?.dir ?? ""}`;
|
|
3247
3247
|
const cached = bodyCache.get(cacheKey);
|
|
3248
3248
|
if (cached !== void 0) return cached;
|
|
3249
3249
|
const candidates = [];
|
|
3250
|
-
if (
|
|
3250
|
+
if (cfg2?.dir) candidates.push(import_node_path2.default.join(cfg2.dir, `${id}.md`));
|
|
3251
3251
|
if (opts?.repoRoot) candidates.push(import_node_path2.default.join(opts.repoRoot, ".crosscheck", "personas", `${id}.md`));
|
|
3252
3252
|
if (id === "engineering" && opts?.repoRoot) candidates.push(import_node_path2.default.join(opts.repoRoot, "CLAUDE.md"));
|
|
3253
3253
|
const bundled = bundledPersonasDir();
|
|
@@ -3297,9 +3297,9 @@ function buildPersonaInjection(opts) {
|
|
|
3297
3297
|
|
|
3298
3298
|
// src/core/utils.ts
|
|
3299
3299
|
init_cjs_shims();
|
|
3300
|
-
function checkSessionBreakers(session,
|
|
3300
|
+
function checkSessionBreakers(session, cfg2) {
|
|
3301
3301
|
if (!session || typeof session !== "object") return null;
|
|
3302
|
-
const c =
|
|
3302
|
+
const c = cfg2 ?? {};
|
|
3303
3303
|
const costCap = Number(c.max_session_cost_usd ?? 0);
|
|
3304
3304
|
if (costCap > 0 && Number(session.total_cost_usd ?? 0) >= costCap) {
|
|
3305
3305
|
return {
|
|
@@ -3323,10 +3323,10 @@ function checkSessionBreakers(session, cfg) {
|
|
|
3323
3323
|
}
|
|
3324
3324
|
return null;
|
|
3325
3325
|
}
|
|
3326
|
-
function checkDagBreakers(dag,
|
|
3326
|
+
function checkDagBreakers(dag, cfg2) {
|
|
3327
3327
|
if (!dag || typeof dag !== "object") return null;
|
|
3328
3328
|
const nodes = Array.isArray(dag.nodes) ? dag.nodes : [];
|
|
3329
|
-
const c =
|
|
3329
|
+
const c = cfg2 ?? {};
|
|
3330
3330
|
const maxNodes = Math.trunc(Number(c.max_dag_nodes ?? 0));
|
|
3331
3331
|
if (maxNodes > 0 && nodes.length > maxNodes) {
|
|
3332
3332
|
return {
|
|
@@ -3411,8 +3411,8 @@ function breakerEnvelope(toolName, trip, sessionId) {
|
|
|
3411
3411
|
transient: false
|
|
3412
3412
|
};
|
|
3413
3413
|
}
|
|
3414
|
-
async function maybeBreakerEnvelope(storage, sessionId, toolName,
|
|
3415
|
-
if (!sessionId || !storage || !
|
|
3414
|
+
async function maybeBreakerEnvelope(storage, sessionId, toolName, cfg2, extras) {
|
|
3415
|
+
if (!sessionId || !storage || !cfg2) return null;
|
|
3416
3416
|
let session;
|
|
3417
3417
|
try {
|
|
3418
3418
|
session = await storage.getSession(sessionId) ?? null;
|
|
@@ -3420,13 +3420,13 @@ async function maybeBreakerEnvelope(storage, sessionId, toolName, cfg, extras) {
|
|
|
3420
3420
|
return null;
|
|
3421
3421
|
}
|
|
3422
3422
|
const target = extras && extras.length > 0 ? projectSessionWithAnswers(session, extras) : session;
|
|
3423
|
-
const trip = checkSessionBreakers(target,
|
|
3423
|
+
const trip = checkSessionBreakers(target, cfg2);
|
|
3424
3424
|
if (!trip) return null;
|
|
3425
3425
|
return breakerEnvelope(toolName, trip, sessionId);
|
|
3426
3426
|
}
|
|
3427
|
-
function maybeDagBreakerEnvelope(dag, toolName,
|
|
3428
|
-
if (!
|
|
3429
|
-
const trip = checkDagBreakers(dag ?? null,
|
|
3427
|
+
function maybeDagBreakerEnvelope(dag, toolName, cfg2, sessionId) {
|
|
3428
|
+
if (!cfg2) return null;
|
|
3429
|
+
const trip = checkDagBreakers(dag ?? null, cfg2);
|
|
3430
3430
|
if (!trip) return null;
|
|
3431
3431
|
return breakerEnvelope(toolName, trip, sessionId);
|
|
3432
3432
|
}
|
|
@@ -3449,9 +3449,9 @@ function builtinRedactionRules() {
|
|
|
3449
3449
|
{ pattern: /\b(?:\d{4}[ -]?){3}\d{4}\b/g, label: "CARD", prefix_group: false }
|
|
3450
3450
|
];
|
|
3451
3451
|
}
|
|
3452
|
-
function compileRules(
|
|
3452
|
+
function compileRules(cfg2) {
|
|
3453
3453
|
const rules = builtinRedactionRules();
|
|
3454
|
-
const extras =
|
|
3454
|
+
const extras = cfg2?.patterns_extra ?? [];
|
|
3455
3455
|
for (const src of extras) {
|
|
3456
3456
|
try {
|
|
3457
3457
|
rules.push({ pattern: new RegExp(src, "g"), label: "EXTRA", prefix_group: false });
|
|
@@ -3460,25 +3460,25 @@ function compileRules(cfg) {
|
|
|
3460
3460
|
}
|
|
3461
3461
|
return { rules };
|
|
3462
3462
|
}
|
|
3463
|
-
function hmacSuffix(
|
|
3464
|
-
const secret =
|
|
3465
|
-
const sid =
|
|
3463
|
+
function hmacSuffix(cfg2, label, value) {
|
|
3464
|
+
const secret = cfg2.hmac_secret ?? Buffer.alloc(0);
|
|
3465
|
+
const sid = cfg2.session_id ?? "";
|
|
3466
3466
|
const sidBytes = Buffer.from(sid, "utf8");
|
|
3467
3467
|
const key = Buffer.concat([Buffer.from(secret), sidBytes]);
|
|
3468
3468
|
const digest = (0, import_node_crypto2.createHmac)("sha256", key).update(`${label}:${value}`, "utf8").digest("hex");
|
|
3469
3469
|
return digest.slice(0, 8);
|
|
3470
3470
|
}
|
|
3471
|
-
function redactText(s,
|
|
3471
|
+
function redactText(s, cfg2) {
|
|
3472
3472
|
if (typeof s !== "string" || s.length === 0) return s;
|
|
3473
|
-
if (
|
|
3474
|
-
const { rules } = compileRules(
|
|
3475
|
-
const hmacMode = Boolean(
|
|
3473
|
+
if (cfg2 && cfg2.enabled === false) return s;
|
|
3474
|
+
const { rules } = compileRules(cfg2);
|
|
3475
|
+
const hmacMode = Boolean(cfg2?.hmac_tokens);
|
|
3476
3476
|
let out = s;
|
|
3477
3477
|
for (const { pattern, label, prefix_group } of rules) {
|
|
3478
3478
|
pattern.lastIndex = 0;
|
|
3479
3479
|
if (hmacMode) {
|
|
3480
3480
|
out = out.replace(pattern, (match, ...args) => {
|
|
3481
|
-
const suffix = hmacSuffix(
|
|
3481
|
+
const suffix = hmacSuffix(cfg2 ?? {}, label, match);
|
|
3482
3482
|
const token = `[REDACTED_${label}:${suffix}]`;
|
|
3483
3483
|
if (prefix_group) {
|
|
3484
3484
|
const g1 = args[0];
|
|
@@ -3498,23 +3498,23 @@ function redactText(s, cfg) {
|
|
|
3498
3498
|
}
|
|
3499
3499
|
return out;
|
|
3500
3500
|
}
|
|
3501
|
-
function redactObj(obj,
|
|
3502
|
-
if (typeof obj === "string") return redactText(obj,
|
|
3501
|
+
function redactObj(obj, cfg2) {
|
|
3502
|
+
if (typeof obj === "string") return redactText(obj, cfg2);
|
|
3503
3503
|
if (Array.isArray(obj)) {
|
|
3504
|
-
return obj.map((v) => redactObj(v,
|
|
3504
|
+
return obj.map((v) => redactObj(v, cfg2));
|
|
3505
3505
|
}
|
|
3506
3506
|
if (obj && typeof obj === "object") {
|
|
3507
3507
|
const out = {};
|
|
3508
3508
|
for (const [k, v] of Object.entries(obj)) {
|
|
3509
|
-
out[k] = redactObj(v,
|
|
3509
|
+
out[k] = redactObj(v, cfg2);
|
|
3510
3510
|
}
|
|
3511
3511
|
return out;
|
|
3512
3512
|
}
|
|
3513
3513
|
return obj;
|
|
3514
3514
|
}
|
|
3515
3515
|
var globalRedaction = null;
|
|
3516
|
-
function setRedactionConfig(
|
|
3517
|
-
globalRedaction =
|
|
3516
|
+
function setRedactionConfig(cfg2) {
|
|
3517
|
+
globalRedaction = cfg2;
|
|
3518
3518
|
}
|
|
3519
3519
|
function getRedactionConfig() {
|
|
3520
3520
|
return globalRedaction ?? void 0;
|
|
@@ -4764,8 +4764,8 @@ function neutralizeInjection(s) {
|
|
|
4764
4764
|
|
|
4765
4765
|
// src/core/worker.ts
|
|
4766
4766
|
var WORKER_TOOL_COST_CAP_MODES = ["warn", "enforce", "off"];
|
|
4767
|
-
function workerToolCostCapDefaults(callerCapUsd, callerMode,
|
|
4768
|
-
const cfgObj =
|
|
4767
|
+
function workerToolCostCapDefaults(callerCapUsd, callerMode, cfg2) {
|
|
4768
|
+
const cfgObj = cfg2 ?? {};
|
|
4769
4769
|
let capRaw = callerCapUsd !== void 0 && callerCapUsd !== null ? callerCapUsd : cfgObj.cost_cap_usd;
|
|
4770
4770
|
let cap;
|
|
4771
4771
|
if (capRaw === void 0 || capRaw === null) {
|
|
@@ -6376,7 +6376,7 @@ function tryKill(child, signal, isUnix) {
|
|
|
6376
6376
|
init_cjs_shims();
|
|
6377
6377
|
function shlexSplit(s) {
|
|
6378
6378
|
const out = [];
|
|
6379
|
-
let
|
|
6379
|
+
let current2 = "";
|
|
6380
6380
|
let hasCurrent = false;
|
|
6381
6381
|
let mode = "normal";
|
|
6382
6382
|
for (let i = 0; i < s.length; i++) {
|
|
@@ -6394,7 +6394,7 @@ function shlexSplit(s) {
|
|
|
6394
6394
|
}
|
|
6395
6395
|
if (ch === "\\") {
|
|
6396
6396
|
if (i + 1 < s.length) {
|
|
6397
|
-
|
|
6397
|
+
current2 += s[i + 1];
|
|
6398
6398
|
i++;
|
|
6399
6399
|
hasCurrent = true;
|
|
6400
6400
|
}
|
|
@@ -6402,13 +6402,13 @@ function shlexSplit(s) {
|
|
|
6402
6402
|
}
|
|
6403
6403
|
if (ch === " " || ch === " " || ch === "\n" || ch === "\r") {
|
|
6404
6404
|
if (hasCurrent) {
|
|
6405
|
-
out.push(
|
|
6406
|
-
|
|
6405
|
+
out.push(current2);
|
|
6406
|
+
current2 = "";
|
|
6407
6407
|
hasCurrent = false;
|
|
6408
6408
|
}
|
|
6409
6409
|
continue;
|
|
6410
6410
|
}
|
|
6411
|
-
|
|
6411
|
+
current2 += ch;
|
|
6412
6412
|
hasCurrent = true;
|
|
6413
6413
|
continue;
|
|
6414
6414
|
}
|
|
@@ -6417,7 +6417,7 @@ function shlexSplit(s) {
|
|
|
6417
6417
|
mode = "normal";
|
|
6418
6418
|
continue;
|
|
6419
6419
|
}
|
|
6420
|
-
|
|
6420
|
+
current2 += ch;
|
|
6421
6421
|
continue;
|
|
6422
6422
|
}
|
|
6423
6423
|
if (mode === "double") {
|
|
@@ -6428,21 +6428,21 @@ function shlexSplit(s) {
|
|
|
6428
6428
|
if (ch === "\\") {
|
|
6429
6429
|
const nxt = s[i + 1];
|
|
6430
6430
|
if (nxt === "$" || nxt === "`" || nxt === '"' || nxt === "\\" || nxt === "\n") {
|
|
6431
|
-
|
|
6431
|
+
current2 += nxt;
|
|
6432
6432
|
i++;
|
|
6433
6433
|
continue;
|
|
6434
6434
|
}
|
|
6435
|
-
|
|
6435
|
+
current2 += "\\";
|
|
6436
6436
|
continue;
|
|
6437
6437
|
}
|
|
6438
|
-
|
|
6438
|
+
current2 += ch;
|
|
6439
6439
|
continue;
|
|
6440
6440
|
}
|
|
6441
6441
|
}
|
|
6442
6442
|
if (mode !== "normal") {
|
|
6443
6443
|
throw new Error("unmatched quote");
|
|
6444
6444
|
}
|
|
6445
|
-
if (hasCurrent) out.push(
|
|
6445
|
+
if (hasCurrent) out.push(current2);
|
|
6446
6446
|
return out;
|
|
6447
6447
|
}
|
|
6448
6448
|
|
|
@@ -7150,16 +7150,16 @@ function computeDrift(opts) {
|
|
|
7150
7150
|
const absPath = resolvePinPath(opts);
|
|
7151
7151
|
const doc = loadDoc(absPath);
|
|
7152
7152
|
const pinned = doc && typeof doc === "object" && doc["pins"] && typeof doc["pins"] === "object" ? doc["pins"] : {};
|
|
7153
|
-
const
|
|
7153
|
+
const current2 = computeCurrent(opts);
|
|
7154
7154
|
const drift = [];
|
|
7155
7155
|
for (const [p, h] of Object.entries(pinned)) {
|
|
7156
|
-
if (
|
|
7156
|
+
if (current2[p] && current2[p] !== h) drift.push(p);
|
|
7157
7157
|
}
|
|
7158
|
-
const missingFromPin = Object.keys(
|
|
7159
|
-
const missingFiles = Object.keys(pinned).filter((p) => !(p in
|
|
7158
|
+
const missingFromPin = Object.keys(current2).filter((p) => !(p in pinned));
|
|
7159
|
+
const missingFiles = Object.keys(pinned).filter((p) => !(p in current2));
|
|
7160
7160
|
return {
|
|
7161
7161
|
pinned,
|
|
7162
|
-
current,
|
|
7162
|
+
current: current2,
|
|
7163
7163
|
drift: drift.sort(),
|
|
7164
7164
|
missing_from_pin: missingFromPin.sort(),
|
|
7165
7165
|
missing_files: missingFiles.sort(),
|
|
@@ -7444,19 +7444,19 @@ function sortKeyJsonifyTopLevel(json) {
|
|
|
7444
7444
|
for (const k of Object.keys(obj).sort()) sorted[k] = obj[k];
|
|
7445
7445
|
return JSON.stringify(sorted);
|
|
7446
7446
|
}
|
|
7447
|
-
function resolveCacheDir(
|
|
7448
|
-
const raw =
|
|
7447
|
+
function resolveCacheDir(cfg2, repoRoot) {
|
|
7448
|
+
const raw = cfg2.dir ?? ".crosscheck/node_cache";
|
|
7449
7449
|
if ((0, import_node_path8.isAbsolute)(raw)) return raw;
|
|
7450
7450
|
return (0, import_node_path8.resolve)(repoRoot ?? process.cwd(), raw);
|
|
7451
7451
|
}
|
|
7452
|
-
function cachePath(
|
|
7453
|
-
return (0, import_node_path8.join)(resolveCacheDir(
|
|
7452
|
+
function cachePath(cfg2, repoRoot, key) {
|
|
7453
|
+
return (0, import_node_path8.join)(resolveCacheDir(cfg2, repoRoot), key.slice(0, 2), `${key}.json`);
|
|
7454
7454
|
}
|
|
7455
|
-
function getNodeCache(
|
|
7456
|
-
if (!
|
|
7457
|
-
const p = cachePath(
|
|
7455
|
+
function getNodeCache(cfg2, repoRoot, key, nowMs) {
|
|
7456
|
+
if (!cfg2 || cfg2.enabled === false) return null;
|
|
7457
|
+
const p = cachePath(cfg2, repoRoot, key);
|
|
7458
7458
|
if (!(0, import_node_fs8.existsSync)(p)) return null;
|
|
7459
|
-
const ttlS =
|
|
7459
|
+
const ttlS = cfg2.ttl_seconds ?? 604800;
|
|
7460
7460
|
try {
|
|
7461
7461
|
const st = (0, import_node_fs8.statSync)(p);
|
|
7462
7462
|
if (ttlS > 0) {
|
|
@@ -7474,21 +7474,21 @@ function getNodeCache(cfg, repoRoot, key, nowMs) {
|
|
|
7474
7474
|
return null;
|
|
7475
7475
|
}
|
|
7476
7476
|
}
|
|
7477
|
-
function atomicWriteJson(
|
|
7478
|
-
(0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)(
|
|
7479
|
-
const tmp = `${
|
|
7477
|
+
function atomicWriteJson(path15, payload) {
|
|
7478
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)(path15), { recursive: true });
|
|
7479
|
+
const tmp = `${path15}.${process.pid}.${Date.now()}.tmp`;
|
|
7480
7480
|
(0, import_node_fs8.writeFileSync)(tmp, JSON.stringify(payload), "utf8");
|
|
7481
|
-
(0, import_node_fs8.renameSync)(tmp,
|
|
7481
|
+
(0, import_node_fs8.renameSync)(tmp, path15);
|
|
7482
7482
|
}
|
|
7483
|
-
function putNodeCache(
|
|
7484
|
-
if (!
|
|
7483
|
+
function putNodeCache(cfg2, repoRoot, key, value) {
|
|
7484
|
+
if (!cfg2 || cfg2.enabled === false) return;
|
|
7485
7485
|
try {
|
|
7486
|
-
const p = cachePath(
|
|
7486
|
+
const p = cachePath(cfg2, repoRoot, key);
|
|
7487
7487
|
atomicWriteJson(p, value);
|
|
7488
|
-
const maxEntries =
|
|
7489
|
-
const maxBytes =
|
|
7488
|
+
const maxEntries = cfg2.max_entries ?? 2e3;
|
|
7489
|
+
const maxBytes = cfg2.max_cache_bytes ?? 100 * 1024 * 1024;
|
|
7490
7490
|
if (maxEntries <= 0 && maxBytes <= 0) return;
|
|
7491
|
-
const base = resolveCacheDir(
|
|
7491
|
+
const base = resolveCacheDir(cfg2, repoRoot);
|
|
7492
7492
|
if (!(0, import_node_fs8.existsSync)(base)) return;
|
|
7493
7493
|
const entries = [];
|
|
7494
7494
|
let totalBytes = 0;
|
|
@@ -8606,31 +8606,31 @@ async function runFetch(args, opts) {
|
|
|
8606
8606
|
const url = String(args["url"] ?? "");
|
|
8607
8607
|
const force = Boolean(args["force_refresh"]);
|
|
8608
8608
|
const sessionId = typeof args["session_id"] === "string" ? args["session_id"] : null;
|
|
8609
|
-
const
|
|
8609
|
+
const cfg2 = { ...DEFAULT_CONFIG, ...opts.config ?? {} };
|
|
8610
8610
|
const base = { tool: "fetch", url };
|
|
8611
|
-
if (!
|
|
8611
|
+
if (!cfg2.enabled) {
|
|
8612
8612
|
return { ...base, accepted: false, reason: "fetch is disabled" };
|
|
8613
8613
|
}
|
|
8614
8614
|
if (!(url.startsWith("https://") || url.startsWith("http://"))) {
|
|
8615
8615
|
return { ...base, accepted: false, reason: "only http/https schemes are supported" };
|
|
8616
8616
|
}
|
|
8617
|
-
if (
|
|
8617
|
+
if (cfg2.url_allowlist.length === 0) {
|
|
8618
8618
|
return {
|
|
8619
8619
|
...base,
|
|
8620
8620
|
accepted: false,
|
|
8621
8621
|
reason: "fetch.url_allowlist is empty; no URLs may be fetched"
|
|
8622
8622
|
};
|
|
8623
8623
|
}
|
|
8624
|
-
if (!isUrlAllowed(url,
|
|
8624
|
+
if (!isUrlAllowed(url, cfg2.url_allowlist)) {
|
|
8625
8625
|
return {
|
|
8626
8626
|
...base,
|
|
8627
8627
|
accepted: false,
|
|
8628
8628
|
reason: "url is not covered by fetch.url_allowlist",
|
|
8629
|
-
allowlist:
|
|
8629
|
+
allowlist: cfg2.url_allowlist
|
|
8630
8630
|
};
|
|
8631
8631
|
}
|
|
8632
|
-
const maxBytesSession = Math.max(0,
|
|
8633
|
-
const maxUniqueHosts = Math.max(0,
|
|
8632
|
+
const maxBytesSession = Math.max(0, cfg2.max_bytes_per_session);
|
|
8633
|
+
const maxUniqueHosts = Math.max(0, cfg2.max_unique_hosts_per_session);
|
|
8634
8634
|
const host = extractHost(url);
|
|
8635
8635
|
if (sessionId && opts.storage && (maxBytesSession > 0 || maxUniqueHosts > 0)) {
|
|
8636
8636
|
const { total_bytes, unique_hosts } = await opts.storage.getFetchEgressTotals(sessionId);
|
|
@@ -8670,7 +8670,7 @@ async function runFetch(args, opts) {
|
|
|
8670
8670
|
}
|
|
8671
8671
|
}
|
|
8672
8672
|
}
|
|
8673
|
-
const evDir = resolveEvidenceDir(
|
|
8673
|
+
const evDir = resolveEvidenceDir(cfg2.evidence_dir, opts.repoRoot);
|
|
8674
8674
|
const urlHash16 = sha256Hex2(url).slice(0, 16);
|
|
8675
8675
|
const metaPath = import_node_path9.default.join(evDir, `by-url-${urlHash16}.json`);
|
|
8676
8676
|
if ((0, import_node_fs9.existsSync)(metaPath) && !force) {
|
|
@@ -8692,7 +8692,7 @@ async function runFetch(args, opts) {
|
|
|
8692
8692
|
try {
|
|
8693
8693
|
response = await withTimeout(
|
|
8694
8694
|
fetchFn(url, { headers: { "User-Agent": "crosscheck-agent/0.1" } }),
|
|
8695
|
-
|
|
8695
|
+
cfg2.timeout_s * 1e3
|
|
8696
8696
|
);
|
|
8697
8697
|
} catch (e) {
|
|
8698
8698
|
return {
|
|
@@ -8718,8 +8718,8 @@ async function runFetch(args, opts) {
|
|
|
8718
8718
|
const reader = response.body?.getReader?.();
|
|
8719
8719
|
if (!reader) {
|
|
8720
8720
|
const buf = await response.arrayBuffer();
|
|
8721
|
-
if (buf.byteLength >
|
|
8722
|
-
return { ...base, accepted: false, reason: `response exceeds max_bytes=${
|
|
8721
|
+
if (buf.byteLength > cfg2.max_bytes) {
|
|
8722
|
+
return { ...base, accepted: false, reason: `response exceeds max_bytes=${cfg2.max_bytes}` };
|
|
8723
8723
|
}
|
|
8724
8724
|
data = new Uint8Array(buf);
|
|
8725
8725
|
} else {
|
|
@@ -8731,7 +8731,7 @@ async function runFetch(args, opts) {
|
|
|
8731
8731
|
if (done) break;
|
|
8732
8732
|
if (value) {
|
|
8733
8733
|
total += value.byteLength;
|
|
8734
|
-
if (total >
|
|
8734
|
+
if (total > cfg2.max_bytes) {
|
|
8735
8735
|
exceeded = true;
|
|
8736
8736
|
await reader.cancel().catch(() => {
|
|
8737
8737
|
});
|
|
@@ -8741,7 +8741,7 @@ async function runFetch(args, opts) {
|
|
|
8741
8741
|
}
|
|
8742
8742
|
}
|
|
8743
8743
|
if (exceeded) {
|
|
8744
|
-
return { ...base, accepted: false, reason: `response exceeds max_bytes=${
|
|
8744
|
+
return { ...base, accepted: false, reason: `response exceeds max_bytes=${cfg2.max_bytes}` };
|
|
8745
8745
|
}
|
|
8746
8746
|
data = new Uint8Array(total);
|
|
8747
8747
|
let offset = 0;
|
|
@@ -12595,15 +12595,15 @@ var CHECK_INTERVAL_SECONDS = 3 * 24 * 60 * 60;
|
|
|
12595
12595
|
var DEFAULT_PACKAGE = "crosscheck-cli";
|
|
12596
12596
|
var FETCH_TIMEOUT_MS = 3e3;
|
|
12597
12597
|
function engineVersion() {
|
|
12598
|
-
return true ? "0.2.
|
|
12598
|
+
return true ? "0.2.16" : "0.0.0-dev";
|
|
12599
12599
|
}
|
|
12600
12600
|
function defaultUpdateCachePath() {
|
|
12601
12601
|
const base = process.env["CROSSCHECK_DATA_DIR"] || import_node_path13.default.join(import_node_os2.default.homedir() || import_node_os2.default.tmpdir(), ".crosscheck");
|
|
12602
12602
|
return import_node_path13.default.join(base, "update_check.json");
|
|
12603
12603
|
}
|
|
12604
|
-
function isNewer(latest,
|
|
12604
|
+
function isNewer(latest, current2) {
|
|
12605
12605
|
const a = parseTriple(latest);
|
|
12606
|
-
const b = parseTriple(
|
|
12606
|
+
const b = parseTriple(current2);
|
|
12607
12607
|
for (let i = 0; i < 3; i += 1) {
|
|
12608
12608
|
if (a[i] !== b[i]) return a[i] > b[i];
|
|
12609
12609
|
}
|
|
@@ -12613,13 +12613,13 @@ function parseTriple(v) {
|
|
|
12613
12613
|
const parts = (v.split("-")[0] ?? "").split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
12614
12614
|
return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
|
|
12615
12615
|
}
|
|
12616
|
-
function buildNotice(pkg,
|
|
12616
|
+
function buildNotice(pkg, current2, latest) {
|
|
12617
12617
|
return {
|
|
12618
12618
|
update_available: true,
|
|
12619
12619
|
package: pkg,
|
|
12620
|
-
current_version:
|
|
12620
|
+
current_version: current2,
|
|
12621
12621
|
latest_version: latest,
|
|
12622
|
-
message: `crosscheck ${latest} is available \u2014 you're on ${
|
|
12622
|
+
message: `crosscheck ${latest} is available \u2014 you're on ${current2}. To upgrade, run:
|
|
12623
12623
|
|
|
12624
12624
|
npm install -g crosscheck-cli@latest
|
|
12625
12625
|
|
|
@@ -14306,13 +14306,214 @@ function attachUpdateNotice(result, toolName, opts) {
|
|
|
14306
14306
|
|
|
14307
14307
|
// src/core/telemetry.ts
|
|
14308
14308
|
init_cjs_shims();
|
|
14309
|
+
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
14310
|
+
|
|
14311
|
+
// src/core/segments.ts
|
|
14312
|
+
init_cjs_shims();
|
|
14313
|
+
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
14314
|
+
var import_node_fs17 = require("fs");
|
|
14315
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
14316
|
+
|
|
14317
|
+
// src/core/git-context.ts
|
|
14318
|
+
init_cjs_shims();
|
|
14319
|
+
var import_node_child_process3 = require("child_process");
|
|
14309
14320
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
14321
|
+
var TRUNK_BRANCHES = /* @__PURE__ */ new Set([
|
|
14322
|
+
"main",
|
|
14323
|
+
"master",
|
|
14324
|
+
"dev",
|
|
14325
|
+
"develop",
|
|
14326
|
+
"trunk"
|
|
14327
|
+
]);
|
|
14328
|
+
function git(args, cwd) {
|
|
14329
|
+
try {
|
|
14330
|
+
return (0, import_node_child_process3.execFileSync)("git", args, {
|
|
14331
|
+
cwd,
|
|
14332
|
+
encoding: "utf8",
|
|
14333
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
14334
|
+
timeout: 2e3
|
|
14335
|
+
}).trim();
|
|
14336
|
+
} catch {
|
|
14337
|
+
return null;
|
|
14338
|
+
}
|
|
14339
|
+
}
|
|
14340
|
+
function repoIdentity(cwd) {
|
|
14341
|
+
const root = git(["rev-list", "--max-parents=0", "HEAD"], cwd);
|
|
14342
|
+
if (root) return `root:${root.split("\n").pop().trim()}`;
|
|
14343
|
+
const remote = git(["config", "--get", "remote.origin.url"], cwd);
|
|
14344
|
+
if (remote) return `remote:${remote}`;
|
|
14345
|
+
const top = git(["rev-parse", "--show-toplevel"], cwd);
|
|
14346
|
+
return top ? `path:${top}` : null;
|
|
14347
|
+
}
|
|
14348
|
+
function fingerprintOf(seatKey, parts) {
|
|
14349
|
+
return import_node_crypto8.default.createHmac("sha256", seatKey).update(parts.join("\0")).digest("hex");
|
|
14350
|
+
}
|
|
14351
|
+
function readGitContext(seatKey, cwd) {
|
|
14352
|
+
try {
|
|
14353
|
+
const inside = git(["rev-parse", "--is-inside-work-tree"], cwd);
|
|
14354
|
+
if (inside !== "true") return { signal: "no_repo" };
|
|
14355
|
+
const repo = repoIdentity(cwd);
|
|
14356
|
+
if (!repo) return { signal: "no_repo" };
|
|
14357
|
+
const branch = git(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
|
|
14358
|
+
if (!branch || branch === "HEAD") {
|
|
14359
|
+
const wt = git(["rev-parse", "--show-toplevel"], cwd) ?? cwd;
|
|
14360
|
+
return {
|
|
14361
|
+
fingerprint: fingerprintOf(seatKey, [repo, "worktree", wt]),
|
|
14362
|
+
signal: "worktree",
|
|
14363
|
+
localLabel: `worktree:${wt}`
|
|
14364
|
+
};
|
|
14365
|
+
}
|
|
14366
|
+
if (TRUNK_BRANCHES.has(branch)) {
|
|
14367
|
+
return {
|
|
14368
|
+
fingerprint: fingerprintOf(seatKey, [repo, "trunk"]),
|
|
14369
|
+
signal: "trunk",
|
|
14370
|
+
localLabel: `${branch} (maintenance)`
|
|
14371
|
+
};
|
|
14372
|
+
}
|
|
14373
|
+
return {
|
|
14374
|
+
fingerprint: fingerprintOf(seatKey, [repo, "branch", branch]),
|
|
14375
|
+
signal: "branch",
|
|
14376
|
+
localLabel: branch
|
|
14377
|
+
};
|
|
14378
|
+
} catch {
|
|
14379
|
+
return { signal: "no_repo" };
|
|
14380
|
+
}
|
|
14381
|
+
}
|
|
14382
|
+
function sameContext(a, b) {
|
|
14383
|
+
return a.fingerprint === b.fingerprint && a.signal === b.signal;
|
|
14384
|
+
}
|
|
14385
|
+
|
|
14386
|
+
// src/core/segments.ts
|
|
14387
|
+
var POST_TIMEOUT_MS = 5e3;
|
|
14388
|
+
function canonicalSegmentBody(s) {
|
|
14389
|
+
return [
|
|
14390
|
+
s.segmentId,
|
|
14391
|
+
s.seatId,
|
|
14392
|
+
s.orgId,
|
|
14393
|
+
s.sessionId,
|
|
14394
|
+
String(s.seq),
|
|
14395
|
+
s.fingerprint ?? "",
|
|
14396
|
+
s.signal,
|
|
14397
|
+
s.startedAt,
|
|
14398
|
+
s.endedAt ?? ""
|
|
14399
|
+
].join("|");
|
|
14400
|
+
}
|
|
14401
|
+
function signSegment(seatKey, s) {
|
|
14402
|
+
return import_node_crypto9.default.createHmac("sha256", seatKey).update(canonicalSegmentBody(s)).digest("hex");
|
|
14403
|
+
}
|
|
14404
|
+
var cfgResolved = false;
|
|
14405
|
+
var cfg = null;
|
|
14310
14406
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
14407
|
+
function getConfig() {
|
|
14408
|
+
if (cfgResolved) return cfg;
|
|
14409
|
+
cfgResolved = true;
|
|
14410
|
+
if (process.env["CROSSCHECK_TELEMETRY"] === "off") return cfg = null;
|
|
14411
|
+
const base = process.env["CROSSCHECK_TELEMETRY_URL"];
|
|
14412
|
+
const seatId = process.env["CROSSCHECK_SEAT_ID"];
|
|
14413
|
+
const orgId = process.env["CROSSCHECK_ORG_ID"];
|
|
14414
|
+
const seatKey = process.env["CROSSCHECK_SEAT_HMAC_KEY"];
|
|
14415
|
+
if (!base || !seatId || !orgId || !seatKey) return cfg = null;
|
|
14416
|
+
if (!UUID_RE.test(seatId) || !UUID_RE.test(orgId)) return cfg = null;
|
|
14417
|
+
const sessionId = process.env["CLAUDE_SESSION_ID"] || process.env["CLAUDE_CODE_SESSION_ID"] || `engine-${import_node_crypto9.default.randomUUID()}`;
|
|
14418
|
+
cfg = {
|
|
14419
|
+
url: base.replace(/\/telemetry\/?$/, "/segments"),
|
|
14420
|
+
seatId,
|
|
14421
|
+
orgId,
|
|
14422
|
+
seatKey,
|
|
14423
|
+
sessionId
|
|
14424
|
+
};
|
|
14425
|
+
return cfg;
|
|
14426
|
+
}
|
|
14427
|
+
var current = null;
|
|
14428
|
+
var nextSeq = 0;
|
|
14429
|
+
function currentFingerprint() {
|
|
14430
|
+
return current?.context.fingerprint;
|
|
14431
|
+
}
|
|
14432
|
+
function rememberLabel(context) {
|
|
14433
|
+
if (!context.fingerprint || !context.localLabel) return;
|
|
14434
|
+
try {
|
|
14435
|
+
const dir = process.env["CROSSCHECK_DATA_DIR"] || import_node_path16.default.join(process.env["HOME"] ?? process.env["USERPROFILE"] ?? ".", ".crosscheck");
|
|
14436
|
+
const file = import_node_path16.default.join(dir, "features.json");
|
|
14437
|
+
let map = {};
|
|
14438
|
+
if ((0, import_node_fs17.existsSync)(file)) {
|
|
14439
|
+
try {
|
|
14440
|
+
const parsed = JSON.parse((0, import_node_fs17.readFileSync)(file, "utf8"));
|
|
14441
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) map = parsed;
|
|
14442
|
+
} catch {
|
|
14443
|
+
}
|
|
14444
|
+
}
|
|
14445
|
+
map[context.fingerprint] = {
|
|
14446
|
+
label: context.localLabel,
|
|
14447
|
+
lastSeen: (/* @__PURE__ */ new Date()).toISOString()
|
|
14448
|
+
};
|
|
14449
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
14450
|
+
(0, import_node_fs17.writeFileSync)(file, `${JSON.stringify(map, null, 2)}
|
|
14451
|
+
`, "utf8");
|
|
14452
|
+
} catch {
|
|
14453
|
+
}
|
|
14454
|
+
}
|
|
14455
|
+
async function post(url, segments) {
|
|
14456
|
+
try {
|
|
14457
|
+
await fetch(url, {
|
|
14458
|
+
method: "POST",
|
|
14459
|
+
headers: { "content-type": "application/json" },
|
|
14460
|
+
body: JSON.stringify({ segments }),
|
|
14461
|
+
signal: AbortSignal.timeout(POST_TIMEOUT_MS)
|
|
14462
|
+
});
|
|
14463
|
+
} catch {
|
|
14464
|
+
}
|
|
14465
|
+
}
|
|
14466
|
+
function emit(c, seg, endedAt) {
|
|
14467
|
+
const payload = {
|
|
14468
|
+
segmentId: seg.segmentId,
|
|
14469
|
+
seatId: c.seatId,
|
|
14470
|
+
orgId: c.orgId,
|
|
14471
|
+
sessionId: c.sessionId,
|
|
14472
|
+
seq: seg.seq,
|
|
14473
|
+
...seg.context.fingerprint ? { fingerprint: seg.context.fingerprint } : {},
|
|
14474
|
+
signal: seg.context.signal,
|
|
14475
|
+
startedAt: seg.startedAt,
|
|
14476
|
+
...endedAt ? { endedAt } : {}
|
|
14477
|
+
};
|
|
14478
|
+
const signatureHmac = signSegment(c.seatKey, payload);
|
|
14479
|
+
void post(c.url, [{ ...payload, signatureHmac }]);
|
|
14480
|
+
}
|
|
14481
|
+
function syncSegment(cwd) {
|
|
14482
|
+
try {
|
|
14483
|
+
const c = getConfig();
|
|
14484
|
+
if (!c) return;
|
|
14485
|
+
const context = readGitContext(c.seatKey, cwd ?? process.cwd());
|
|
14486
|
+
if (current && sameContext(current.context, context)) return;
|
|
14487
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14488
|
+
if (current) emit(c, current, now);
|
|
14489
|
+
current = {
|
|
14490
|
+
segmentId: import_node_crypto9.default.randomUUID(),
|
|
14491
|
+
seq: nextSeq++,
|
|
14492
|
+
context,
|
|
14493
|
+
startedAt: now
|
|
14494
|
+
};
|
|
14495
|
+
rememberLabel(context);
|
|
14496
|
+
emit(c, current);
|
|
14497
|
+
} catch {
|
|
14498
|
+
}
|
|
14499
|
+
}
|
|
14500
|
+
function closeSegment() {
|
|
14501
|
+
try {
|
|
14502
|
+
const c = getConfig();
|
|
14503
|
+
if (!c || !current) return;
|
|
14504
|
+
emit(c, current, (/* @__PURE__ */ new Date()).toISOString());
|
|
14505
|
+
current = null;
|
|
14506
|
+
} catch {
|
|
14507
|
+
}
|
|
14508
|
+
}
|
|
14509
|
+
|
|
14510
|
+
// src/core/telemetry.ts
|
|
14511
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
14311
14512
|
var BATCH_MAX = 100;
|
|
14312
14513
|
var FLUSH_BATCH_AT = 25;
|
|
14313
14514
|
var FLUSH_INTERVAL_MS = 15e3;
|
|
14314
14515
|
var MAX_QUEUE = 500;
|
|
14315
|
-
var
|
|
14516
|
+
var POST_TIMEOUT_MS2 = 5e3;
|
|
14316
14517
|
var PROVIDER_TO_SCHEMA = {
|
|
14317
14518
|
anthropic: "anthropic",
|
|
14318
14519
|
openai: "openai",
|
|
@@ -14342,7 +14543,7 @@ function toolToPattern(toolName) {
|
|
|
14342
14543
|
return TOOL_TO_PATTERN[String(toolName).toLowerCase()] ?? "other";
|
|
14343
14544
|
}
|
|
14344
14545
|
function canonicalEventBody(e) {
|
|
14345
|
-
|
|
14546
|
+
const base = [
|
|
14346
14547
|
e.eventId,
|
|
14347
14548
|
e.seatId,
|
|
14348
14549
|
e.orgId,
|
|
@@ -14357,13 +14558,22 @@ function canonicalEventBody(e) {
|
|
|
14357
14558
|
e.status,
|
|
14358
14559
|
e.errorClass ?? ""
|
|
14359
14560
|
].join("|");
|
|
14561
|
+
if (e.runId === void 0 && e.purpose === void 0 && e.fingerprint === void 0) {
|
|
14562
|
+
return base;
|
|
14563
|
+
}
|
|
14564
|
+
return [base, e.runId ?? "", e.purpose ?? "", e.fingerprint ?? ""].join("|");
|
|
14565
|
+
}
|
|
14566
|
+
function normalizePurpose(v) {
|
|
14567
|
+
if (typeof v !== "string") return void 0;
|
|
14568
|
+
const slug = v.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-").slice(0, 32);
|
|
14569
|
+
return /^[a-z0-9][a-z0-9_-]*$/.test(slug) ? slug : void 0;
|
|
14360
14570
|
}
|
|
14361
14571
|
function signEvent(seatSigningKey, e) {
|
|
14362
|
-
return
|
|
14572
|
+
return import_node_crypto10.default.createHmac("sha256", seatSigningKey).update(canonicalEventBody(e)).digest("hex");
|
|
14363
14573
|
}
|
|
14364
14574
|
var configResolved = false;
|
|
14365
14575
|
var config = null;
|
|
14366
|
-
function
|
|
14576
|
+
function getConfig2() {
|
|
14367
14577
|
if (configResolved) return config;
|
|
14368
14578
|
configResolved = true;
|
|
14369
14579
|
if (process.env["CROSSCHECK_TELEMETRY"] === "off") return config = null;
|
|
@@ -14372,7 +14582,7 @@ function getConfig() {
|
|
|
14372
14582
|
const orgId = process.env["CROSSCHECK_ORG_ID"];
|
|
14373
14583
|
const seatKey = process.env["CROSSCHECK_SEAT_HMAC_KEY"];
|
|
14374
14584
|
if (!url || !seatId || !orgId || !seatKey) return config = null;
|
|
14375
|
-
if (!
|
|
14585
|
+
if (!UUID_RE2.test(seatId) || !UUID_RE2.test(orgId)) return config = null;
|
|
14376
14586
|
config = { url, seatId, orgId, seatKey };
|
|
14377
14587
|
return config;
|
|
14378
14588
|
}
|
|
@@ -14407,7 +14617,10 @@ function usageEventsFromEnvelope(out, toolName) {
|
|
|
14407
14617
|
completionTokens: intNonNeg(u.completion_tokens),
|
|
14408
14618
|
costUsdEstimate: cost,
|
|
14409
14619
|
latencyMs,
|
|
14410
|
-
status: "ok"
|
|
14620
|
+
status: "ok",
|
|
14621
|
+
// Envelopes have carried `purpose` per call all along (debate /
|
|
14622
|
+
// debate-coreason / synth / worker); it just was never forwarded.
|
|
14623
|
+
purpose: normalizePurpose(u.purpose)
|
|
14411
14624
|
});
|
|
14412
14625
|
}
|
|
14413
14626
|
return events;
|
|
@@ -14422,11 +14635,11 @@ function scheduleFlush() {
|
|
|
14422
14635
|
}, FLUSH_INTERVAL_MS);
|
|
14423
14636
|
if (typeof flushTimer.unref === "function") flushTimer.unref();
|
|
14424
14637
|
}
|
|
14425
|
-
function enqueue(
|
|
14638
|
+
function enqueue(cfg2, input, runId, fingerprint) {
|
|
14426
14639
|
const base = {
|
|
14427
|
-
eventId:
|
|
14428
|
-
seatId:
|
|
14429
|
-
orgId:
|
|
14640
|
+
eventId: import_node_crypto10.default.randomUUID(),
|
|
14641
|
+
seatId: cfg2.seatId,
|
|
14642
|
+
orgId: cfg2.orgId,
|
|
14430
14643
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14431
14644
|
provider: input.provider,
|
|
14432
14645
|
model: input.model,
|
|
@@ -14435,9 +14648,17 @@ function enqueue(cfg, input) {
|
|
|
14435
14648
|
completionTokens: input.completionTokens,
|
|
14436
14649
|
costUsdEstimate: input.costUsdEstimate,
|
|
14437
14650
|
latencyMs: input.latencyMs,
|
|
14438
|
-
status: input.status
|
|
14439
|
-
|
|
14440
|
-
|
|
14651
|
+
status: input.status,
|
|
14652
|
+
runId,
|
|
14653
|
+
// Omit entirely (not "") when unknown, so the canonical body stays
|
|
14654
|
+
// consistent with what the server reconstructs from the JSON.
|
|
14655
|
+
...input.purpose === void 0 ? {} : { purpose: input.purpose },
|
|
14656
|
+
// Panel attribution is EXACT: we know the active git segment at emit
|
|
14657
|
+
// time, so there is no time-join and no ambiguity window — unlike host
|
|
14658
|
+
// tokens, which can only be matched by session and timestamp.
|
|
14659
|
+
...fingerprint === void 0 ? {} : { fingerprint }
|
|
14660
|
+
};
|
|
14661
|
+
const signatureHmac = signEvent(cfg2.seatKey, base);
|
|
14441
14662
|
queue.push({ ...base, signatureHmac });
|
|
14442
14663
|
if (queue.length > MAX_QUEUE) queue.splice(0, queue.length - MAX_QUEUE);
|
|
14443
14664
|
if (queue.length >= FLUSH_BATCH_AT) void flush();
|
|
@@ -14445,10 +14666,14 @@ function enqueue(cfg, input) {
|
|
|
14445
14666
|
}
|
|
14446
14667
|
function recordUsage(out, toolName) {
|
|
14447
14668
|
try {
|
|
14448
|
-
const
|
|
14449
|
-
if (!
|
|
14669
|
+
const cfg2 = getConfig2();
|
|
14670
|
+
if (!cfg2) return;
|
|
14450
14671
|
if (toolName === "update_crosscheck") return;
|
|
14451
|
-
|
|
14672
|
+
const runId = import_node_crypto10.default.randomUUID();
|
|
14673
|
+
const fingerprint = currentFingerprint();
|
|
14674
|
+
for (const ev of usageEventsFromEnvelope(out, toolName)) {
|
|
14675
|
+
enqueue(cfg2, ev, runId, fingerprint);
|
|
14676
|
+
}
|
|
14452
14677
|
} catch {
|
|
14453
14678
|
}
|
|
14454
14679
|
}
|
|
@@ -14459,7 +14684,7 @@ async function postBatch(url, batch) {
|
|
|
14459
14684
|
method: "POST",
|
|
14460
14685
|
headers: { "content-type": "application/json" },
|
|
14461
14686
|
body: JSON.stringify({ events: batch }),
|
|
14462
|
-
signal: AbortSignal.timeout(
|
|
14687
|
+
signal: AbortSignal.timeout(POST_TIMEOUT_MS2)
|
|
14463
14688
|
});
|
|
14464
14689
|
} catch {
|
|
14465
14690
|
queue.unshift(...batch);
|
|
@@ -14481,15 +14706,15 @@ async function postBatch(url, batch) {
|
|
|
14481
14706
|
if (queue.length > MAX_QUEUE) queue.splice(0, queue.length - MAX_QUEUE);
|
|
14482
14707
|
}
|
|
14483
14708
|
async function flush() {
|
|
14484
|
-
const
|
|
14485
|
-
if (!
|
|
14709
|
+
const cfg2 = getConfig2();
|
|
14710
|
+
if (!cfg2) return;
|
|
14486
14711
|
if (flushTimer) {
|
|
14487
14712
|
clearTimeout(flushTimer);
|
|
14488
14713
|
flushTimer = null;
|
|
14489
14714
|
}
|
|
14490
14715
|
while (queue.length > 0) {
|
|
14491
14716
|
const batch = queue.splice(0, BATCH_MAX);
|
|
14492
|
-
await postBatch(
|
|
14717
|
+
await postBatch(cfg2.url, batch);
|
|
14493
14718
|
if (queue.length > 0 && queue[0] === batch[0]) break;
|
|
14494
14719
|
}
|
|
14495
14720
|
}
|
|
@@ -14557,6 +14782,7 @@ function createServer(opts = {}) {
|
|
|
14557
14782
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
14558
14783
|
const startedHr = process.hrtime.bigint();
|
|
14559
14784
|
const id = nextEventId();
|
|
14785
|
+
syncSegment(opts.repoRoot);
|
|
14560
14786
|
const gateBlock = configPinGate(name, {
|
|
14561
14787
|
...opts.repoRoot ? { repoRoot: opts.repoRoot } : {},
|
|
14562
14788
|
...opts.configPinning ? { config: opts.configPinning } : {},
|
|
@@ -14638,6 +14864,13 @@ function createServer(opts = {}) {
|
|
|
14638
14864
|
async function connectAndServe(transport, opts = {}) {
|
|
14639
14865
|
const server = createServer(opts);
|
|
14640
14866
|
await server.connect(transport);
|
|
14867
|
+
for (const sig of ["SIGINT", "SIGTERM"]) {
|
|
14868
|
+
process.once(sig, () => {
|
|
14869
|
+
closeSegment();
|
|
14870
|
+
process.exit(0);
|
|
14871
|
+
});
|
|
14872
|
+
}
|
|
14873
|
+
process.once("beforeExit", () => closeSegment());
|
|
14641
14874
|
const cliVersion = process.env["CROSSCHECK_CLI_VERSION"];
|
|
14642
14875
|
void maybeCheckForUpdate({
|
|
14643
14876
|
currentVersion: cliVersion ?? SERVER_VERSION,
|
|
@@ -14675,9 +14908,9 @@ function buildToolRegistry(opts) {
|
|
|
14675
14908
|
|
|
14676
14909
|
// src/core/config-file.ts
|
|
14677
14910
|
init_cjs_shims();
|
|
14678
|
-
var
|
|
14679
|
-
var
|
|
14680
|
-
var
|
|
14911
|
+
var import_node_fs18 = require("fs");
|
|
14912
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
14913
|
+
var import_node_crypto11 = require("crypto");
|
|
14681
14914
|
function asObj(v) {
|
|
14682
14915
|
return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
|
|
14683
14916
|
}
|
|
@@ -14704,18 +14937,18 @@ function pickNums(src, keys) {
|
|
|
14704
14937
|
}
|
|
14705
14938
|
function findConfigFile(opts) {
|
|
14706
14939
|
const direct = opts.explicitPath ?? process.env["CROSSCHECK_CONFIG_PATH"];
|
|
14707
|
-
if (direct) return (0,
|
|
14940
|
+
if (direct) return (0, import_node_fs18.existsSync)(direct) ? direct : void 0;
|
|
14708
14941
|
const candidates = [];
|
|
14709
14942
|
let dir = opts.startDir;
|
|
14710
14943
|
for (let i = 0; dir && i < 8; i += 1) {
|
|
14711
|
-
candidates.push(
|
|
14712
|
-
const parent =
|
|
14944
|
+
candidates.push(import_node_path17.default.join(dir, "crosscheck.config.json"));
|
|
14945
|
+
const parent = import_node_path17.default.dirname(dir);
|
|
14713
14946
|
if (parent === dir) break;
|
|
14714
14947
|
dir = parent;
|
|
14715
14948
|
}
|
|
14716
|
-
if (opts.repoRoot) candidates.push(
|
|
14717
|
-
if (opts.dataDir) candidates.push(
|
|
14718
|
-
return candidates.find((p) => (0,
|
|
14949
|
+
if (opts.repoRoot) candidates.push(import_node_path17.default.join(opts.repoRoot, "crosscheck.config.json"));
|
|
14950
|
+
if (opts.dataDir) candidates.push(import_node_path17.default.join(opts.dataDir, "crosscheck.config.json"));
|
|
14951
|
+
return candidates.find((p) => (0, import_node_fs18.existsSync)(p));
|
|
14719
14952
|
}
|
|
14720
14953
|
function mapConfig(raw, sourcePath) {
|
|
14721
14954
|
const result = { sourcePath };
|
|
@@ -14732,16 +14965,16 @@ function mapConfig(raw, sourcePath) {
|
|
|
14732
14965
|
}
|
|
14733
14966
|
const nc = asObj(raw["node_cache"]);
|
|
14734
14967
|
if (nc) {
|
|
14735
|
-
const
|
|
14968
|
+
const cfg2 = {
|
|
14736
14969
|
...pickNums(nc, ["ttl_seconds", "max_entries", "max_cache_bytes"])
|
|
14737
14970
|
};
|
|
14738
|
-
if (bool(nc["enabled"]) !== void 0)
|
|
14739
|
-
if (str(nc["dir"]) !== void 0)
|
|
14740
|
-
result.nodeCache =
|
|
14971
|
+
if (bool(nc["enabled"]) !== void 0) cfg2.enabled = bool(nc["enabled"]);
|
|
14972
|
+
if (str(nc["dir"]) !== void 0) cfg2.dir = str(nc["dir"]);
|
|
14973
|
+
result.nodeCache = cfg2;
|
|
14741
14974
|
}
|
|
14742
14975
|
const f = asObj(raw["fetch"]);
|
|
14743
14976
|
if (f) {
|
|
14744
|
-
const
|
|
14977
|
+
const cfg2 = {
|
|
14745
14978
|
...pickNums(f, [
|
|
14746
14979
|
"max_bytes",
|
|
14747
14980
|
"max_bytes_per_session",
|
|
@@ -14749,10 +14982,10 @@ function mapConfig(raw, sourcePath) {
|
|
|
14749
14982
|
"timeout_s"
|
|
14750
14983
|
])
|
|
14751
14984
|
};
|
|
14752
|
-
if (bool(f["enabled"]) !== void 0)
|
|
14753
|
-
if (strArr(f["url_allowlist"]) !== void 0)
|
|
14754
|
-
if (str(f["evidence_dir"]) !== void 0)
|
|
14755
|
-
result.fetchConfig =
|
|
14985
|
+
if (bool(f["enabled"]) !== void 0) cfg2.enabled = bool(f["enabled"]);
|
|
14986
|
+
if (strArr(f["url_allowlist"]) !== void 0) cfg2.url_allowlist = strArr(f["url_allowlist"]);
|
|
14987
|
+
if (str(f["evidence_dir"]) !== void 0) cfg2.evidence_dir = str(f["evidence_dir"]);
|
|
14988
|
+
result.fetchConfig = cfg2;
|
|
14756
14989
|
}
|
|
14757
14990
|
if ("provider_allowlist" in raw) {
|
|
14758
14991
|
const pa = raw["provider_allowlist"];
|
|
@@ -14776,10 +15009,10 @@ function mapConfig(raw, sourcePath) {
|
|
|
14776
15009
|
if (retries) {
|
|
14777
15010
|
const maxAttempts = num(retries["max_attempts"]);
|
|
14778
15011
|
const baseS = num(retries["backoff_base_s"]);
|
|
14779
|
-
const
|
|
14780
|
-
if (maxAttempts !== void 0)
|
|
14781
|
-
if (baseS !== void 0)
|
|
14782
|
-
if (Object.keys(
|
|
15012
|
+
const cfg2 = {};
|
|
15013
|
+
if (maxAttempts !== void 0) cfg2.maxAttempts = Math.max(1, Math.trunc(maxAttempts));
|
|
15014
|
+
if (baseS !== void 0) cfg2.backoffBaseMs = Math.round(baseS * 1e3);
|
|
15015
|
+
if (Object.keys(cfg2).length > 0) setRetryConfig(cfg2);
|
|
14783
15016
|
}
|
|
14784
15017
|
const rl = asObj(raw["rate_limits"]);
|
|
14785
15018
|
if (rl) {
|
|
@@ -14805,22 +15038,22 @@ function mapConfig(raw, sourcePath) {
|
|
|
14805
15038
|
}
|
|
14806
15039
|
const red = asObj(raw["redaction"]);
|
|
14807
15040
|
if (red) {
|
|
14808
|
-
const
|
|
14809
|
-
if (bool(red["enabled"]) !== void 0)
|
|
15041
|
+
const cfg2 = {};
|
|
15042
|
+
if (bool(red["enabled"]) !== void 0) cfg2.enabled = bool(red["enabled"]);
|
|
14810
15043
|
const extras = strArr(red["patterns_extra"]);
|
|
14811
|
-
if (extras && extras.length > 0)
|
|
15044
|
+
if (extras && extras.length > 0) cfg2.patterns_extra = extras;
|
|
14812
15045
|
if (bool(red["hmac_tokens"]) === true) {
|
|
14813
|
-
|
|
14814
|
-
|
|
15046
|
+
cfg2.hmac_tokens = true;
|
|
15047
|
+
cfg2.hmac_secret = (0, import_node_crypto11.randomBytes)(32);
|
|
14815
15048
|
}
|
|
14816
|
-
if (Object.keys(
|
|
15049
|
+
if (Object.keys(cfg2).length > 0) setRedactionConfig(cfg2);
|
|
14817
15050
|
}
|
|
14818
15051
|
const personas = asObj(raw["personas"]);
|
|
14819
15052
|
if (personas) {
|
|
14820
|
-
const
|
|
14821
|
-
if (bool(personas["enabled"]) !== void 0)
|
|
14822
|
-
if (str(personas["dir"]) !== void 0)
|
|
14823
|
-
if (Object.keys(
|
|
15053
|
+
const cfg2 = {};
|
|
15054
|
+
if (bool(personas["enabled"]) !== void 0) cfg2.enabled = bool(personas["enabled"]);
|
|
15055
|
+
if (str(personas["dir"]) !== void 0) cfg2.dir = str(personas["dir"]);
|
|
15056
|
+
if (Object.keys(cfg2).length > 0) setPersonaConfig(cfg2);
|
|
14824
15057
|
}
|
|
14825
15058
|
return result;
|
|
14826
15059
|
}
|
|
@@ -14829,7 +15062,7 @@ function loadConfigFile(opts) {
|
|
|
14829
15062
|
if (!file) return null;
|
|
14830
15063
|
let raw;
|
|
14831
15064
|
try {
|
|
14832
|
-
raw = JSON.parse((0,
|
|
15065
|
+
raw = JSON.parse((0, import_node_fs18.readFileSync)(file, "utf8"));
|
|
14833
15066
|
} catch (e) {
|
|
14834
15067
|
try {
|
|
14835
15068
|
process.stderr.write(
|
|
@@ -14849,7 +15082,7 @@ function loadConfigFile(opts) {
|
|
|
14849
15082
|
var SHUTDOWN_TIMEOUT_MS = 2e3;
|
|
14850
15083
|
async function main() {
|
|
14851
15084
|
enforceLicenseOrExit();
|
|
14852
|
-
const cfgDataDir = process.env["CROSSCHECK_DATA_DIR"] ||
|
|
15085
|
+
const cfgDataDir = process.env["CROSSCHECK_DATA_DIR"] || import_node_path18.default.join(process.env["HOME"] ?? process.env["USERPROFILE"] ?? "", ".crosscheck");
|
|
14853
15086
|
const configFile = loadConfigFile({
|
|
14854
15087
|
startDir: process.cwd(),
|
|
14855
15088
|
repoRoot: findGitRoot(__dirname),
|
|
@@ -14874,7 +15107,7 @@ async function main() {
|
|
|
14874
15107
|
installShutdownHandlers();
|
|
14875
15108
|
const bundledPricing = (() => {
|
|
14876
15109
|
try {
|
|
14877
|
-
return
|
|
15110
|
+
return import_node_path18.default.join(import_node_path18.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl)), "pricing.json");
|
|
14878
15111
|
} catch {
|
|
14879
15112
|
return void 0;
|
|
14880
15113
|
}
|
|
@@ -14883,7 +15116,7 @@ async function main() {
|
|
|
14883
15116
|
process.env["CROSSCHECK_PRICING_PATH"],
|
|
14884
15117
|
resolveRepoFile("config/pricing.json"),
|
|
14885
15118
|
bundledPricing
|
|
14886
|
-
].find((p) => p && (0,
|
|
15119
|
+
].find((p) => p && (0, import_node_fs19.existsSync)(p));
|
|
14887
15120
|
const pricing = pricingPath ? loadPricing(pricingPath) : {};
|
|
14888
15121
|
const providers = buildProviders({ env: process.env, pricing });
|
|
14889
15122
|
if (Object.keys(providers).length > 0) {
|
|
@@ -14901,10 +15134,10 @@ async function main() {
|
|
|
14901
15134
|
}
|
|
14902
15135
|
let storage;
|
|
14903
15136
|
if (process.env["CROSSCHECK_DB_DISABLED"] !== "1") {
|
|
14904
|
-
const dbPath = process.env["CROSSCHECK_DB_PATH"] ?? resolveRepoFile(".crosscheck/db.sqlite") ??
|
|
15137
|
+
const dbPath = process.env["CROSSCHECK_DB_PATH"] ?? resolveRepoFile(".crosscheck/db.sqlite") ?? import_node_path18.default.join(cfgDataDir, "db.sqlite");
|
|
14905
15138
|
if (dbPath) {
|
|
14906
15139
|
try {
|
|
14907
|
-
(0,
|
|
15140
|
+
(0, import_node_fs19.mkdirSync)(import_node_path18.default.dirname(dbPath), { recursive: true });
|
|
14908
15141
|
const { openBetterSqliteStorage: openBetterSqliteStorage2 } = await Promise.resolve().then(() => (init_better_sqlite3(), better_sqlite3_exports));
|
|
14909
15142
|
storage = openBetterSqliteStorage2({ path: dbPath });
|
|
14910
15143
|
await storage.migrate();
|
|
@@ -14972,9 +15205,9 @@ function installShutdownHandlers() {
|
|
|
14972
15205
|
function resolveRepoFile(rel) {
|
|
14973
15206
|
let dir = __dirname;
|
|
14974
15207
|
for (let i = 0; i < 8; i++) {
|
|
14975
|
-
const candidate =
|
|
14976
|
-
if ((0,
|
|
14977
|
-
const parent =
|
|
15208
|
+
const candidate = import_node_path18.default.join(dir, rel);
|
|
15209
|
+
if ((0, import_node_fs19.existsSync)(candidate)) return candidate;
|
|
15210
|
+
const parent = import_node_path18.default.dirname(dir);
|
|
14978
15211
|
if (parent === dir) break;
|
|
14979
15212
|
dir = parent;
|
|
14980
15213
|
}
|
|
@@ -14983,8 +15216,8 @@ function resolveRepoFile(rel) {
|
|
|
14983
15216
|
function findGitRoot(startDir) {
|
|
14984
15217
|
let dir = startDir;
|
|
14985
15218
|
for (let i = 0; i < 12; i++) {
|
|
14986
|
-
if ((0,
|
|
14987
|
-
const parent =
|
|
15219
|
+
if ((0, import_node_fs19.existsSync)(import_node_path18.default.join(dir, ".git"))) return dir;
|
|
15220
|
+
const parent = import_node_path18.default.dirname(dir);
|
|
14988
15221
|
if (parent === dir) break;
|
|
14989
15222
|
dir = parent;
|
|
14990
15223
|
}
|