@node9/proxy 2.22.1 → 2.23.0
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/cli.js +1282 -948
- package/dist/cli.mjs +1253 -919
- package/dist/dashboard.mjs +458 -88
- package/dist/index.js +293 -24
- package/dist/index.mjs +293 -24
- package/dist/scan-ink.mjs +12 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -995,6 +995,7 @@ function normalizeCommandForPolicyImpl(command) {
|
|
|
995
995
|
const source = command.slice(s, e);
|
|
996
996
|
if (resolved === source) continue;
|
|
997
997
|
if (resolved === "" || /\s/.test(resolved)) continue;
|
|
998
|
+
if (/^[;&|()<>]+$/.test(resolved)) continue;
|
|
998
999
|
rewrites.push([s, e, resolved]);
|
|
999
1000
|
const quoteOnly = source.replace(/['"]/g, "");
|
|
1000
1001
|
if (quoteOnly !== source) quoteOnlyRewrites.push([s, e, quoteOnly]);
|
|
@@ -1344,23 +1345,147 @@ function extractLiteralArgs(callExpr) {
|
|
|
1344
1345
|
const args = positionedArgs(words);
|
|
1345
1346
|
return { name, flags, paths: args.map((a) => a.value), words, args };
|
|
1346
1347
|
}
|
|
1348
|
+
function payloadKey(payload) {
|
|
1349
|
+
if (!assignmentTable || assignmentTable.size === 0) return payload;
|
|
1350
|
+
const bindings = [];
|
|
1351
|
+
for (const [name, rec] of assignmentTable) {
|
|
1352
|
+
if (rec.value !== null) bindings.push(`${name}=${rec.value}`);
|
|
1353
|
+
}
|
|
1354
|
+
return `${payload}\0${bindings.sort().join("")}`;
|
|
1355
|
+
}
|
|
1356
|
+
function claimPayload(payload) {
|
|
1357
|
+
if (!seenPayloads) return "ok";
|
|
1358
|
+
const key = payloadKey(payload);
|
|
1359
|
+
if (seenPayloads.has(key)) return "seen";
|
|
1360
|
+
if (payloadBudget <= 0) return "exhausted";
|
|
1361
|
+
payloadBudget--;
|
|
1362
|
+
seenPayloads.add(key);
|
|
1363
|
+
return "ok";
|
|
1364
|
+
}
|
|
1365
|
+
function recordTopLevelAssignments(f) {
|
|
1366
|
+
const stmts = Array.isArray(f?.Stmts) ? f.Stmts : [];
|
|
1367
|
+
for (const stmt of stmts) recordTopLevelStmt(stmt);
|
|
1368
|
+
}
|
|
1369
|
+
function probeBinOp(src) {
|
|
1370
|
+
try {
|
|
1371
|
+
const cmd = syntax.NewParser().Parse(src, "probe")?.Stmts?.[0]?.Cmd;
|
|
1372
|
+
if (cmd && syntax.NodeType(cmd) === "BinaryCmd") return cmd.Op;
|
|
1373
|
+
} catch {
|
|
1374
|
+
}
|
|
1375
|
+
return null;
|
|
1376
|
+
}
|
|
1377
|
+
function recordTopLevelStmt(stmt) {
|
|
1378
|
+
if (!stmt || !stmt.Cmd) return false;
|
|
1379
|
+
const t = syntax.NodeType(stmt.Cmd);
|
|
1380
|
+
if (t === "BinaryCmd") {
|
|
1381
|
+
if (!AND_OR_OPS.has(stmt.Cmd.Op)) return false;
|
|
1382
|
+
if (!recordTopLevelStmt(stmt.Cmd.X)) return false;
|
|
1383
|
+
if (stmt.Cmd.Op === AND_OP) return recordTopLevelStmt(stmt.Cmd.Y);
|
|
1384
|
+
return true;
|
|
1385
|
+
}
|
|
1386
|
+
if (t !== "CallExpr" && t !== "DeclClause") return false;
|
|
1387
|
+
let at = 0;
|
|
1388
|
+
try {
|
|
1389
|
+
at = stmt.Pos().Offset();
|
|
1390
|
+
} catch {
|
|
1391
|
+
at = 0;
|
|
1392
|
+
}
|
|
1393
|
+
recordAssignments(stmt.Cmd, at);
|
|
1394
|
+
if (stmt.Negated) return false;
|
|
1395
|
+
if (t === "DeclClause") return ASSIGNMENT_HEADS.has(stmt.Cmd.Variant?.Value ?? "");
|
|
1396
|
+
return (stmt.Cmd.Args || []).length === 0 && (stmt.Cmd.Assigns || []).length > 0;
|
|
1397
|
+
}
|
|
1398
|
+
function recordAssignments(n, at) {
|
|
1399
|
+
if (!assignmentTable) return;
|
|
1400
|
+
const t = syntax.NodeType(n);
|
|
1401
|
+
let assigns = [];
|
|
1402
|
+
if (t === "CallExpr") {
|
|
1403
|
+
if ((n.Args || []).length > 0) return;
|
|
1404
|
+
assigns = n.Assigns || [];
|
|
1405
|
+
} else if (t === "DeclClause") {
|
|
1406
|
+
if (!ASSIGNMENT_HEADS.has(n.Variant?.Value ?? "")) return;
|
|
1407
|
+
assigns = (n.Args || []).filter((a) => syntax.NodeType(a) === "Assign");
|
|
1408
|
+
} else return;
|
|
1409
|
+
for (const a of assigns) {
|
|
1410
|
+
const name = a?.Name?.Value;
|
|
1411
|
+
if (!name || !a.Value || a.Append) continue;
|
|
1412
|
+
assignmentTable.set(name, { value: resolveWordLiteral(a.Value), at });
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
function resolveTrivialSubst(part) {
|
|
1416
|
+
if (syntax.NodeType(part) !== "CmdSubst") return void 0;
|
|
1417
|
+
const stmts = part.Stmts || [];
|
|
1418
|
+
if (stmts.length !== 1) return void 0;
|
|
1419
|
+
const st = stmts[0];
|
|
1420
|
+
if ((st.Redirs || []).length > 0 || st.Negated || st.Background) return void 0;
|
|
1421
|
+
const cmd = st.Cmd;
|
|
1422
|
+
if (!cmd || syntax.NodeType(cmd) !== "CallExpr") return void 0;
|
|
1423
|
+
if ((cmd.Assigns || []).length > 0) return void 0;
|
|
1424
|
+
const words = (cmd.Args || []).map((a) => resolveWordLiteral(a));
|
|
1425
|
+
if (words.length === 0 || words.some((w) => w === null)) return void 0;
|
|
1426
|
+
const head = baseWord(words[0]);
|
|
1427
|
+
const rest = words.slice(1);
|
|
1428
|
+
if (head === "echo") {
|
|
1429
|
+
let i = 0;
|
|
1430
|
+
while (i < rest.length && /^-[neE]+$/.test(rest[i])) i++;
|
|
1431
|
+
return rest.slice(i).join(" ");
|
|
1432
|
+
}
|
|
1433
|
+
if (head === "printf") {
|
|
1434
|
+
if (rest.length !== 2) return void 0;
|
|
1435
|
+
if (!/^%s(\\n)?$/.test(rest[0])) return void 0;
|
|
1436
|
+
return rest[1];
|
|
1437
|
+
}
|
|
1438
|
+
return void 0;
|
|
1439
|
+
}
|
|
1440
|
+
function recordedExpansion(name) {
|
|
1441
|
+
if (!assignmentTable || !name) return void 0;
|
|
1442
|
+
const rec = assignmentTable.get(name);
|
|
1443
|
+
if (rec === void 0 || rec.at >= currentStmtOffset) return void 0;
|
|
1444
|
+
return rec.value;
|
|
1445
|
+
}
|
|
1446
|
+
function isPlainParam(p) {
|
|
1447
|
+
if (syntax.NodeType(p) !== "ParamExp") return false;
|
|
1448
|
+
return !(p.Excl || p.Length || p.Width || p.Index || p.Slice || p.Repl || p.Exp);
|
|
1449
|
+
}
|
|
1450
|
+
function expandPlainParam(p) {
|
|
1451
|
+
if (!assignmentTable) return void 0;
|
|
1452
|
+
if (!isPlainParam(p)) return void 0;
|
|
1453
|
+
const recorded = recordedExpansion(p.Param?.Value);
|
|
1454
|
+
if (recorded !== void 0) return recorded;
|
|
1455
|
+
return HOME_VARIABLES.has(p.Param?.Value) ? "~" : void 0;
|
|
1456
|
+
}
|
|
1347
1457
|
function resolveWordLiteral(w) {
|
|
1348
1458
|
const parts = w?.Parts || [];
|
|
1349
1459
|
let s = "";
|
|
1350
1460
|
for (const p of parts) {
|
|
1351
|
-
const
|
|
1352
|
-
if (
|
|
1353
|
-
|
|
1354
|
-
else if (t === "DblQuoted") {
|
|
1355
|
-
const inner = p.Parts || [];
|
|
1356
|
-
if (!inner.every((ip) => syntax.NodeType(ip) === "Lit")) return null;
|
|
1357
|
-
s += inner.map((ip) => ip.Value ?? "").join("");
|
|
1358
|
-
} else {
|
|
1359
|
-
return null;
|
|
1360
|
-
}
|
|
1461
|
+
const piece = resolvePart(p, false);
|
|
1462
|
+
if (piece === void 0 || piece === null) return null;
|
|
1463
|
+
s += piece;
|
|
1361
1464
|
}
|
|
1362
1465
|
return s;
|
|
1363
1466
|
}
|
|
1467
|
+
function resolvePart(p, inQuotes) {
|
|
1468
|
+
const t = syntax.NodeType(p);
|
|
1469
|
+
if (t === "Lit") {
|
|
1470
|
+
const raw = p.Value ?? "";
|
|
1471
|
+
if (!inQuotes) return raw.replace(/\\(.)/g, "$1");
|
|
1472
|
+
return assignmentTable ? raw.replace(/\\([$`"\\])/g, "$1") : raw;
|
|
1473
|
+
}
|
|
1474
|
+
if (t === "SglQuoted") return p.Value ?? "";
|
|
1475
|
+
if (t === "ParamExp") return expandPlainParam(p);
|
|
1476
|
+
if (t === "CmdSubst") return assignmentTable ? resolveTrivialSubst(p) : void 0;
|
|
1477
|
+
if (t === "DblQuoted" && !inQuotes) {
|
|
1478
|
+
const inner = p.Parts || [];
|
|
1479
|
+
let out = "";
|
|
1480
|
+
for (const ip of inner) {
|
|
1481
|
+
const piece = resolvePart(ip, true);
|
|
1482
|
+
if (piece === void 0 || piece === null) return piece;
|
|
1483
|
+
out += piece;
|
|
1484
|
+
}
|
|
1485
|
+
return out;
|
|
1486
|
+
}
|
|
1487
|
+
return void 0;
|
|
1488
|
+
}
|
|
1364
1489
|
function parseDestHost(token) {
|
|
1365
1490
|
if (!token) return null;
|
|
1366
1491
|
let t = token.trim();
|
|
@@ -1415,6 +1540,7 @@ function destTokensForBinary(binary, args) {
|
|
|
1415
1540
|
case "ssh":
|
|
1416
1541
|
return positionals.slice(0, 1);
|
|
1417
1542
|
case "scp":
|
|
1543
|
+
case "rsync":
|
|
1418
1544
|
return positionals.filter((p) => p.includes(":") || p.includes("@"));
|
|
1419
1545
|
case "nc":
|
|
1420
1546
|
case "ncat":
|
|
@@ -1604,17 +1730,35 @@ function analyzeFsOperationImpl(command, depth = 0) {
|
|
|
1604
1730
|
const f = parseShared(command);
|
|
1605
1731
|
if (f === PARSE_FAIL) return null;
|
|
1606
1732
|
let result = null;
|
|
1733
|
+
const outerTable = assignmentTable;
|
|
1734
|
+
const outerOffset = currentStmtOffset;
|
|
1735
|
+
const outerSeen = seenPayloads;
|
|
1736
|
+
const outerBudget = payloadBudget;
|
|
1737
|
+
if (depth === 0) {
|
|
1738
|
+
seenPayloads = /* @__PURE__ */ new Set();
|
|
1739
|
+
payloadBudget = PAYLOAD_BUDGET;
|
|
1740
|
+
}
|
|
1741
|
+
assignmentTable = new Map(
|
|
1742
|
+
[...outerTable ?? []].map(([k, r]) => [k, { value: r.value, at: -1 }])
|
|
1743
|
+
);
|
|
1744
|
+
currentStmtOffset = Number.MAX_SAFE_INTEGER;
|
|
1607
1745
|
try {
|
|
1746
|
+
recordTopLevelAssignments(f);
|
|
1608
1747
|
syntax.Walk(f, (node) => {
|
|
1609
1748
|
if (!node || result?.verdict === "block") return false;
|
|
1610
1749
|
const n = node;
|
|
1611
1750
|
const nodeType = syntax.NodeType(n);
|
|
1612
1751
|
if (nodeType === "Stmt") {
|
|
1752
|
+
try {
|
|
1753
|
+
currentStmtOffset = n.Pos().Offset();
|
|
1754
|
+
} catch {
|
|
1755
|
+
currentStmtOffset = Number.MAX_SAFE_INTEGER;
|
|
1756
|
+
}
|
|
1613
1757
|
result = stricter(result, jailedRedirectRead(n));
|
|
1614
1758
|
return result?.verdict !== "block";
|
|
1615
1759
|
}
|
|
1616
1760
|
if (nodeType !== "CallExpr") return true;
|
|
1617
|
-
const { name, flags, paths, words
|
|
1761
|
+
const { name, flags, paths, words } = extractLiteralArgs(n);
|
|
1618
1762
|
if (!name) return true;
|
|
1619
1763
|
if (name === "rm") {
|
|
1620
1764
|
const flagStr = flags.join("").toLowerCase();
|
|
@@ -1643,9 +1787,30 @@ function analyzeFsOperationImpl(command, depth = 0) {
|
|
|
1643
1787
|
}
|
|
1644
1788
|
}
|
|
1645
1789
|
}
|
|
1646
|
-
if (depth <
|
|
1790
|
+
if (depth < 24 && name === "find") {
|
|
1791
|
+
for (const action of findActions(words, 0)) {
|
|
1792
|
+
const h = unwrapCommandHead(action);
|
|
1793
|
+
const inner = literalShellPayload(action.slice(h), baseWord(action[h]));
|
|
1794
|
+
if (inner === null) continue;
|
|
1795
|
+
const claim = claimPayload(inner);
|
|
1796
|
+
if (claim === "exhausted") {
|
|
1797
|
+
result = stricter(result, UNANALYSABLE_NESTING);
|
|
1798
|
+
continue;
|
|
1799
|
+
}
|
|
1800
|
+
if (claim === "seen") continue;
|
|
1801
|
+
const v = analyzeFsOperationImpl(inner, depth + 1);
|
|
1802
|
+
result = stricter(result, v);
|
|
1803
|
+
if (result?.verdict === "block") return false;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
if (depth < 24) {
|
|
1647
1807
|
const payload = literalShellPayload(words, name);
|
|
1648
|
-
|
|
1808
|
+
const claim = payload === null ? "seen" : claimPayload(payload);
|
|
1809
|
+
if (claim === "exhausted") {
|
|
1810
|
+
result = stricter(result, UNANALYSABLE_NESTING);
|
|
1811
|
+
return true;
|
|
1812
|
+
}
|
|
1813
|
+
if (payload !== null && claim === "ok") {
|
|
1649
1814
|
const inner = analyzeFsOperationImpl(payload, depth + 1);
|
|
1650
1815
|
if (inner) {
|
|
1651
1816
|
result = inner;
|
|
@@ -1654,7 +1819,7 @@ function analyzeFsOperationImpl(command, depth = 0) {
|
|
|
1654
1819
|
return true;
|
|
1655
1820
|
}
|
|
1656
1821
|
}
|
|
1657
|
-
const readPaths = FS_READ_TOOLS.has(name) ?
|
|
1822
|
+
const readPaths = FS_READ_TOOLS.has(name) ? readerPaths(words, 0) : wrappedReadPaths(words, name);
|
|
1658
1823
|
if (readPaths) {
|
|
1659
1824
|
for (const p of readPaths) {
|
|
1660
1825
|
result = stricter(result, matchSensitivePath2(p));
|
|
@@ -1669,6 +1834,11 @@ function analyzeFsOperationImpl(command, depth = 0) {
|
|
|
1669
1834
|
return result;
|
|
1670
1835
|
} catch {
|
|
1671
1836
|
return null;
|
|
1837
|
+
} finally {
|
|
1838
|
+
assignmentTable = outerTable;
|
|
1839
|
+
currentStmtOffset = outerOffset;
|
|
1840
|
+
seenPayloads = outerSeen;
|
|
1841
|
+
if (depth === 0) payloadBudget = outerBudget;
|
|
1672
1842
|
}
|
|
1673
1843
|
}
|
|
1674
1844
|
function stricter(a, b) {
|
|
@@ -1725,6 +1895,18 @@ function resolveCopyShape(words, h) {
|
|
|
1725
1895
|
}
|
|
1726
1896
|
return null;
|
|
1727
1897
|
}
|
|
1898
|
+
function findAction(words, k) {
|
|
1899
|
+
const end = words.findIndex((w, i) => i > k && (w === ";" || w === "+"));
|
|
1900
|
+
return words.slice(k + 1, end < 0 ? words.length : end);
|
|
1901
|
+
}
|
|
1902
|
+
function findActions(words, h) {
|
|
1903
|
+
const out = [];
|
|
1904
|
+
for (let i = h + 1; i < words.length; i++) {
|
|
1905
|
+
const w = words[i];
|
|
1906
|
+
if (w !== null && FIND_EXEC_FLAGS.has(w)) out.push(findAction(words, i));
|
|
1907
|
+
}
|
|
1908
|
+
return out;
|
|
1909
|
+
}
|
|
1728
1910
|
function findStartPoints(words, h) {
|
|
1729
1911
|
const k = words.findIndex((w, i) => i > h && w !== null && FIND_EXEC_FLAGS.has(w));
|
|
1730
1912
|
if (k < 0) return { k, starts: [] };
|
|
@@ -1740,8 +1922,13 @@ function copySourcePaths(words) {
|
|
|
1740
1922
|
if (fi >= 0) {
|
|
1741
1923
|
const { k, starts } = findStartPoints(words, fi);
|
|
1742
1924
|
if (k < 0) return [];
|
|
1743
|
-
const
|
|
1744
|
-
|
|
1925
|
+
const out = [];
|
|
1926
|
+
for (const action of findActions(words, fi)) {
|
|
1927
|
+
const h2 = unwrapCommandHead(action);
|
|
1928
|
+
if (!resolveCopyShape(action, h2)) continue;
|
|
1929
|
+
out.push(...starts, ...copySourcePaths(action));
|
|
1930
|
+
}
|
|
1931
|
+
return out;
|
|
1745
1932
|
}
|
|
1746
1933
|
if (!COPY_VERB_HEADS.has(baseWord(words[h]))) return [];
|
|
1747
1934
|
const r = resolveCopyShape(words, h);
|
|
@@ -1918,6 +2105,15 @@ function flagEffect(token, shape, known) {
|
|
|
1918
2105
|
}
|
|
1919
2106
|
return NONE;
|
|
1920
2107
|
}
|
|
2108
|
+
function readerPaths(words, h) {
|
|
2109
|
+
const head = baseWord(words[h]);
|
|
2110
|
+
const from = h + 1;
|
|
2111
|
+
const flags = words.slice(from).filter((w) => w !== null && w.startsWith("-"));
|
|
2112
|
+
return [
|
|
2113
|
+
...readTargets(head, positionedArgs(words, from), flags, words, from),
|
|
2114
|
+
...flagOperandFiles(head, words, from)
|
|
2115
|
+
];
|
|
2116
|
+
}
|
|
1921
2117
|
function readTargets(verb, args, flags, words = [], from = 1) {
|
|
1922
2118
|
const shape = PATTERN_VERBS[verb];
|
|
1923
2119
|
if (!shape) return args.map((a) => a.value);
|
|
@@ -1999,18 +2195,21 @@ function flagOperandFiles(verb, words, from) {
|
|
|
1999
2195
|
function wrappedReadPaths(words, name) {
|
|
2000
2196
|
if (name === "find") {
|
|
2001
2197
|
const { k, starts } = findStartPoints(words, 0);
|
|
2002
|
-
|
|
2198
|
+
if (k < 0) return null;
|
|
2199
|
+
const paths = [];
|
|
2200
|
+
let reads = false;
|
|
2201
|
+
for (const action of findActions(words, 0)) {
|
|
2202
|
+
const h2 = unwrapCommandHead(action);
|
|
2203
|
+
if (!isReaderWord(action[h2] ?? null)) continue;
|
|
2204
|
+
reads = true;
|
|
2205
|
+
paths.push(...readerPaths(action, h2));
|
|
2206
|
+
}
|
|
2207
|
+
return reads ? [...starts, ...paths] : paths;
|
|
2003
2208
|
}
|
|
2004
2209
|
if (!COMMAND_WRAPPERS.has(name) && !RUNNER_WRAPPERS.has(name)) return null;
|
|
2005
2210
|
const h = unwrapCommandHead(words);
|
|
2006
2211
|
if (h <= 0 || !isReaderWord(words[h] ?? null)) return null;
|
|
2007
|
-
|
|
2008
|
-
const rest = words.slice(h + 1);
|
|
2009
|
-
const restFlags = rest.filter((w) => w !== null && w.startsWith("-"));
|
|
2010
|
-
return [
|
|
2011
|
-
...readTargets(head, positionedArgs(words, h + 1), restFlags, words, h + 1),
|
|
2012
|
-
...flagOperandFiles(head, words, h + 1)
|
|
2013
|
-
];
|
|
2212
|
+
return readerPaths(words, h);
|
|
2014
2213
|
}
|
|
2015
2214
|
function literalShellPayload(words, name) {
|
|
2016
2215
|
const h = COMMAND_WRAPPERS.has(name) || RUNNER_WRAPPERS.has(name) ? unwrapCommandHead(words) : 0;
|
|
@@ -3773,7 +3972,7 @@ function* stringValues(obj, depth = 0) {
|
|
|
3773
3972
|
}
|
|
3774
3973
|
for (const v of Object.values(obj)) yield* stringValues(v, depth + 1);
|
|
3775
3974
|
}
|
|
3776
|
-
var import_safe_regex2, import_crypto3, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto4, IBAN_LENGTH, B58, B58_INDEX, XPRV_VERSIONS, MAX, UNTRUSTED_TOOLS, SIGNALS, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, MAX_DEPTH, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, DLP_SCAN_LIMITS, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, GREP_SHAPE, PATTERN_VERBS, PATTERN_VERB_NAMES, GREP_FILE_OPERANDS, READER_VALUE_LETTERS, FILE_OPERAND_FLAGS, SCP_VALUE_FLAGS, TAR_VALUE_LETTERS, ZIP_VALUE_LETTERS, RSYNC_VALUE_LETTERS, RSYNC_SKIP, CP_VALUE_LETTERS, INSTALL_VALUE_LETTERS, COPY_VERBS, TAR_MODE_WORD, COPY_VERB_HEADS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, BASH_TOOL_NAMES, AST_FS_REGEX_RULES, SQL_DB_CLIS, SQL_DDL_RE, CHMOD_OPEN_PERM_TOKENS, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _redirStdinOps, _listOps, WRAPPER_TAKES_TARGET, FIND_EXEC_FLAGS, INTERP_LEADING_TARGET, NET_BINARIES, VALUE_FLAGS, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, SSRF_MAX_HOST, METADATA_ADDRESSES, STRICT_TIERS, METADATA_HOSTNAMES, v4Octets, TIER_REASON, DEFAULT_EGRESS_ALLOWLIST, PRIVATE_HOST_SUFFIXES, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, DESTINATION_ARGS, VERDICT_RANK, SQL_DML_KEYWORDS, TERMINAL_ESCAPE_RE, CONTROL_CHAR_RE, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE, MAX_BLAST_PATH, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC16_RE, PII_CC15_RE, PII_IBAN_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, CANARY_MIN_LENGTH, MAX_TEXT, MAX_DEPTH2, MAX_JSON_PARSE, URL_DEPTH, B64_DEPTH, MIN_SEGMENT, SEPARATORS, stripSeparators, looksText, CANARY_DECODERS, VIEWS, LONG_OUTPUT_THRESHOLD_BYTES, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, ENGINE_VERSION;
|
|
3975
|
+
var import_safe_regex2, import_crypto3, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto4, IBAN_LENGTH, B58, B58_INDEX, XPRV_VERSIONS, MAX, UNTRUSTED_TOOLS, SIGNALS, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, MAX_DEPTH, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, DLP_SCAN_LIMITS, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, GREP_SHAPE, PATTERN_VERBS, PATTERN_VERB_NAMES, GREP_FILE_OPERANDS, READER_VALUE_LETTERS, FILE_OPERAND_FLAGS, SCP_VALUE_FLAGS, TAR_VALUE_LETTERS, ZIP_VALUE_LETTERS, RSYNC_VALUE_LETTERS, RSYNC_SKIP, CP_VALUE_LETTERS, INSTALL_VALUE_LETTERS, COPY_VERBS, TAR_MODE_WORD, COPY_VERB_HEADS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, BASH_TOOL_NAMES, AST_FS_REGEX_RULES, SQL_DB_CLIS, SQL_DDL_RE, CHMOD_OPEN_PERM_TOKENS, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _redirStdinOps, _listOps, WRAPPER_TAKES_TARGET, FIND_EXEC_FLAGS, INTERP_LEADING_TARGET, NET_BINARIES, VALUE_FLAGS, HOME_VARIABLES, assignmentTable, currentStmtOffset, PAYLOAD_BUDGET, payloadBudget, seenPayloads, UNANALYSABLE_NESTING, ASSIGNMENT_HEADS, AND_OP, OR_OP, AND_OR_OPS, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, SSRF_MAX_HOST, METADATA_ADDRESSES, STRICT_TIERS, METADATA_HOSTNAMES, v4Octets, TIER_REASON, DEFAULT_EGRESS_ALLOWLIST, PRIVATE_HOST_SUFFIXES, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, DESTINATION_ARGS, VERDICT_RANK, SQL_DML_KEYWORDS, TERMINAL_ESCAPE_RE, CONTROL_CHAR_RE, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, LOOP_MAX_RECORDS, FINDING_TO_SIGNAL, SCAN_SIGNAL_WEIGHTS, LOOP_THRESHOLD_FOR_WASTE, MAX_BLAST_PATH, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC16_RE, PII_CC15_RE, PII_IBAN_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, CANARY_MIN_LENGTH, MAX_TEXT, MAX_DEPTH2, MAX_JSON_PARSE, URL_DEPTH, B64_DEPTH, MIN_SEGMENT, SEPARATORS, stripSeparators, looksText, CANARY_DECODERS, VIEWS, LONG_OUTPUT_THRESHOLD_BYTES, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, ENGINE_VERSION;
|
|
3777
3976
|
var init_dist = __esm({
|
|
3778
3977
|
"packages/policy-engine/dist/index.mjs"() {
|
|
3779
3978
|
"use strict";
|
|
@@ -5158,6 +5357,60 @@ var init_dist = __esm({
|
|
|
5158
5357
|
"rsync"
|
|
5159
5358
|
]);
|
|
5160
5359
|
VALUE_FLAGS = {
|
|
5360
|
+
// rsync 3.2.7, its own --help: every flag whose operand could be mistaken for
|
|
5361
|
+
// a host. `-e ssh` is the one that matters most (`ssh` is not the destination).
|
|
5362
|
+
rsync: /* @__PURE__ */ new Set([
|
|
5363
|
+
"-e",
|
|
5364
|
+
"--rsh",
|
|
5365
|
+
"-f",
|
|
5366
|
+
"--filter",
|
|
5367
|
+
"-T",
|
|
5368
|
+
"--temp-dir",
|
|
5369
|
+
"-B",
|
|
5370
|
+
"--block-size",
|
|
5371
|
+
"-M",
|
|
5372
|
+
"--remote-option",
|
|
5373
|
+
"--exclude",
|
|
5374
|
+
"--exclude-from",
|
|
5375
|
+
"--include",
|
|
5376
|
+
"--include-from",
|
|
5377
|
+
"--files-from",
|
|
5378
|
+
"--compare-dest",
|
|
5379
|
+
"--copy-dest",
|
|
5380
|
+
"--link-dest",
|
|
5381
|
+
"--partial-dir",
|
|
5382
|
+
"--log-file",
|
|
5383
|
+
"--password-file",
|
|
5384
|
+
"--bwlimit",
|
|
5385
|
+
"--timeout",
|
|
5386
|
+
"--contimeout",
|
|
5387
|
+
"--port",
|
|
5388
|
+
"--sockopts",
|
|
5389
|
+
"--address",
|
|
5390
|
+
"--chmod",
|
|
5391
|
+
"--chown",
|
|
5392
|
+
"--max-size",
|
|
5393
|
+
"--min-size",
|
|
5394
|
+
"--modify-window",
|
|
5395
|
+
"--out-format",
|
|
5396
|
+
"--log-file-format",
|
|
5397
|
+
"--backup-dir",
|
|
5398
|
+
"--suffix",
|
|
5399
|
+
"--iconv",
|
|
5400
|
+
"--max-delete",
|
|
5401
|
+
"--checksum-choice",
|
|
5402
|
+
"--info",
|
|
5403
|
+
"--debug",
|
|
5404
|
+
"--stderr",
|
|
5405
|
+
"--outbuf",
|
|
5406
|
+
"--skip-compress",
|
|
5407
|
+
"--usermap",
|
|
5408
|
+
"--groupmap",
|
|
5409
|
+
"--mkpath",
|
|
5410
|
+
"--write-batch",
|
|
5411
|
+
"--read-batch",
|
|
5412
|
+
"--only-write-batch"
|
|
5413
|
+
]),
|
|
5161
5414
|
curl: /* @__PURE__ */ new Set([
|
|
5162
5415
|
"-d",
|
|
5163
5416
|
"--data",
|
|
@@ -5241,6 +5494,22 @@ var init_dist = __esm({
|
|
|
5241
5494
|
]),
|
|
5242
5495
|
nc: /* @__PURE__ */ new Set(["-p", "-s", "-w", "-X", "-x", "-e", "-g", "-G", "-i", "-O", "-T", "-q", "-m"])
|
|
5243
5496
|
};
|
|
5497
|
+
HOME_VARIABLES = /* @__PURE__ */ new Set(["HOME", "USERPROFILE"]);
|
|
5498
|
+
assignmentTable = null;
|
|
5499
|
+
currentStmtOffset = Number.MAX_SAFE_INTEGER;
|
|
5500
|
+
PAYLOAD_BUDGET = 256;
|
|
5501
|
+
payloadBudget = 0;
|
|
5502
|
+
seenPayloads = null;
|
|
5503
|
+
UNANALYSABLE_NESTING = {
|
|
5504
|
+
ruleName: "review-unanalysable-nesting",
|
|
5505
|
+
verdict: "review",
|
|
5506
|
+
reason: "This command nests more wrapped shell payloads than the policy engine will unwrap, so some of what it runs was not read.",
|
|
5507
|
+
path: ""
|
|
5508
|
+
};
|
|
5509
|
+
ASSIGNMENT_HEADS = /* @__PURE__ */ new Set(["export", "declare", "local", "readonly", "typeset"]);
|
|
5510
|
+
AND_OP = probeBinOp("a && b");
|
|
5511
|
+
OR_OP = probeBinOp("a || b");
|
|
5512
|
+
AND_OR_OPS = new Set([AND_OP, OR_OP].filter((o) => o !== null));
|
|
5244
5513
|
FS_OP_CACHE_MAX = 5e3;
|
|
5245
5514
|
fsOpCache = /* @__PURE__ */ new Map();
|
|
5246
5515
|
stripDotSlash = (p) => p.replace(/^\.\//, "");
|
|
@@ -6317,7 +6586,7 @@ var init_dist = __esm({
|
|
|
6317
6586
|
{ view: "separators-stripped", decoder: "separators", stripped: true }
|
|
6318
6587
|
];
|
|
6319
6588
|
LONG_OUTPUT_THRESHOLD_BYTES = 100 * 1024;
|
|
6320
|
-
CANONICAL_EXTRACTOR_VERSION = "canonical-
|
|
6589
|
+
CANONICAL_EXTRACTOR_VERSION = "canonical-v18";
|
|
6321
6590
|
DEDUPE_PREVIEW_LEN = 120;
|
|
6322
6591
|
ENGINE_VERSION = "1.4.0";
|
|
6323
6592
|
}
|
|
@@ -10710,116 +10979,284 @@ var init_core = __esm({
|
|
|
10710
10979
|
}
|
|
10711
10980
|
});
|
|
10712
10981
|
|
|
10713
|
-
// src/
|
|
10714
|
-
function
|
|
10715
|
-
|
|
10716
|
-
}
|
|
10717
|
-
function shellInvocation(command) {
|
|
10718
|
-
if (process.platform === "win32") {
|
|
10719
|
-
return {
|
|
10720
|
-
file: process.env.ComSpec || "cmd.exe",
|
|
10721
|
-
args: ["/d", "/s", "/c", command]
|
|
10722
|
-
};
|
|
10723
|
-
}
|
|
10724
|
-
return { file: "/bin/bash", args: ["-c", command] };
|
|
10725
|
-
}
|
|
10726
|
-
var init_platform_shell = __esm({
|
|
10727
|
-
"src/utils/platform-shell.ts"() {
|
|
10728
|
-
"use strict";
|
|
10729
|
-
}
|
|
10730
|
-
});
|
|
10731
|
-
|
|
10732
|
-
// src/codex-trust.ts
|
|
10733
|
-
function readTomlSafe(filePath) {
|
|
10982
|
+
// src/agent-wiring.ts
|
|
10983
|
+
function readJson(filePath) {
|
|
10984
|
+
if (!import_fs16.default.existsSync(filePath)) return null;
|
|
10734
10985
|
try {
|
|
10735
|
-
return
|
|
10986
|
+
return JSON.parse(import_fs16.default.readFileSync(filePath, "utf-8"));
|
|
10736
10987
|
} catch {
|
|
10737
|
-
return
|
|
10988
|
+
return "invalid";
|
|
10738
10989
|
}
|
|
10739
10990
|
}
|
|
10740
|
-
function
|
|
10741
|
-
|
|
10991
|
+
function matchersHaveNode9Hook(matchers) {
|
|
10992
|
+
return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
|
|
10993
|
+
}
|
|
10994
|
+
function flatHaveNode9Hook(entries) {
|
|
10995
|
+
return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
|
|
10996
|
+
}
|
|
10997
|
+
function readHookRoot(filePath, format) {
|
|
10998
|
+
if (!import_fs16.default.existsSync(filePath)) return "absent";
|
|
10999
|
+
let raw;
|
|
10742
11000
|
try {
|
|
10743
|
-
|
|
11001
|
+
raw = import_fs16.default.readFileSync(filePath, "utf-8");
|
|
10744
11002
|
} catch {
|
|
10745
|
-
return
|
|
11003
|
+
return "absent";
|
|
10746
11004
|
}
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
if (row.agent !== "Codex" || typeof row.ts !== "string") continue;
|
|
10753
|
-
if (newest === null || row.ts > newest) newest = row.ts;
|
|
10754
|
-
} catch {
|
|
10755
|
-
}
|
|
11005
|
+
try {
|
|
11006
|
+
const parsed = format === "yaml" ? yaml.parse(raw) : JSON.parse(raw);
|
|
11007
|
+
return parsed?.hooks ?? {};
|
|
11008
|
+
} catch {
|
|
11009
|
+
return "invalid";
|
|
10756
11010
|
}
|
|
10757
|
-
return newest;
|
|
10758
11011
|
}
|
|
10759
|
-
function
|
|
10760
|
-
const
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
else if (trustEntries === 0) state = "never-trusted";
|
|
10764
|
-
else if (hooksWrittenAt && lastCodexActivityAt && lastCodexActivityAt > hooksWrittenAt) {
|
|
10765
|
-
state = "observed";
|
|
10766
|
-
} else state = "unverified";
|
|
10767
|
-
return { state, hooksWrittenAt, lastCodexActivityAt, trustEntries };
|
|
11012
|
+
function eventWired(root, ev, format) {
|
|
11013
|
+
const arr = root[ev.key];
|
|
11014
|
+
if (format === "matcher") return matchersHaveNode9Hook(arr);
|
|
11015
|
+
return flatHaveNode9Hook(arr);
|
|
10768
11016
|
}
|
|
10769
|
-
function
|
|
10770
|
-
const
|
|
10771
|
-
const
|
|
10772
|
-
|
|
11017
|
+
function detectMcp(servers) {
|
|
11018
|
+
const entries = Object.entries(servers ?? {});
|
|
11019
|
+
const present = entries.some(([, s]) => s?.command === "node9");
|
|
11020
|
+
const wrapped = entries.filter(([, s]) => s?.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
|
|
11021
|
+
return { wrapped, present };
|
|
11022
|
+
}
|
|
11023
|
+
function readMcpServers(filePath, format) {
|
|
11024
|
+
if (!import_fs16.default.existsSync(filePath)) return {};
|
|
10773
11025
|
try {
|
|
10774
|
-
|
|
11026
|
+
if (format === "toml") {
|
|
11027
|
+
const parsed2 = (0, import_smol_toml.parse)(import_fs16.default.readFileSync(filePath, "utf-8"));
|
|
11028
|
+
return parsed2?.mcp_servers ?? {};
|
|
11029
|
+
}
|
|
11030
|
+
const parsed = readJson(filePath);
|
|
11031
|
+
if (parsed === null || parsed === "invalid") return {};
|
|
11032
|
+
return parsed.mcpServers ?? {};
|
|
10775
11033
|
} catch {
|
|
10776
|
-
|
|
11034
|
+
return {};
|
|
10777
11035
|
}
|
|
10778
|
-
const config = readTomlSafe(configPath);
|
|
10779
|
-
const hooksDisabled = config?.features?.hooks === false || config?.codex_hooks === false;
|
|
10780
|
-
const trustEntries = Object.keys(config?.hooks?.state ?? {}).length;
|
|
10781
|
-
return assessCodexTrustFrom({
|
|
10782
|
-
hooksDisabled,
|
|
10783
|
-
trustEntries,
|
|
10784
|
-
hooksWrittenAt,
|
|
10785
|
-
lastCodexActivityAt: lastCodexAuditTs(auditLogPath)
|
|
10786
|
-
});
|
|
10787
11036
|
}
|
|
10788
|
-
function
|
|
11037
|
+
function readMcp(filePath, format) {
|
|
11038
|
+
if (!import_fs16.default.existsSync(filePath)) return { wrapped: [], present: false };
|
|
10789
11039
|
try {
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
} catch {
|
|
10794
|
-
}
|
|
10795
|
-
if (process.platform === "win32" && env.LOCALAPPDATA) {
|
|
10796
|
-
const binDir = import_path17.default.join(env.LOCALAPPDATA, "OpenAI", "Codex", "bin");
|
|
10797
|
-
try {
|
|
10798
|
-
for (const d of import_fs16.default.readdirSync(binDir)) {
|
|
10799
|
-
const exe = import_path17.default.join(binDir, d, "codex.exe");
|
|
10800
|
-
if (import_fs16.default.existsSync(exe)) return `"${exe}"`;
|
|
10801
|
-
}
|
|
10802
|
-
} catch {
|
|
11040
|
+
if (format === "toml") {
|
|
11041
|
+
const parsed2 = (0, import_smol_toml.parse)(import_fs16.default.readFileSync(filePath, "utf-8"));
|
|
11042
|
+
return detectMcp(parsed2?.mcp_servers);
|
|
10803
11043
|
}
|
|
11044
|
+
const parsed = readJson(filePath);
|
|
11045
|
+
if (parsed === null || parsed === "invalid") return { wrapped: [], present: false };
|
|
11046
|
+
return detectMcp(parsed.mcpServers);
|
|
11047
|
+
} catch {
|
|
11048
|
+
return { wrapped: [], present: false };
|
|
10804
11049
|
}
|
|
10805
|
-
return null;
|
|
10806
11050
|
}
|
|
10807
|
-
function
|
|
10808
|
-
const
|
|
10809
|
-
return
|
|
10810
|
-
|
|
10811
|
-
|
|
11051
|
+
function getAgentWiring(home = import_os13.default.homedir()) {
|
|
11052
|
+
const detected = detectAgents(home);
|
|
11053
|
+
return AGENT_SPECS.map((spec) => {
|
|
11054
|
+
const present = spec.present(home);
|
|
11055
|
+
const pad = spec.labelPad ?? DEFAULT_LABEL_PAD;
|
|
11056
|
+
let hooks;
|
|
11057
|
+
let wireState;
|
|
11058
|
+
let hookLabel;
|
|
11059
|
+
let settingsPath;
|
|
11060
|
+
if (spec.shimFile) {
|
|
11061
|
+
const shimWired = exists(spec.shimFile(home));
|
|
11062
|
+
hooks = [{ label: "node9 plugin (node9 check)", wired: shimWired }];
|
|
11063
|
+
wireState = shimWired ? "wired" : present ? "unwired" : "absent";
|
|
11064
|
+
hookLabel = "node9 plugin";
|
|
11065
|
+
settingsPath = spec.shimFile(home);
|
|
11066
|
+
} else {
|
|
11067
|
+
const root = spec.hookFile ? readHookRoot(spec.hookFile(home), spec.hookFormat) : "absent";
|
|
11068
|
+
const primary = spec.hookEvents[0];
|
|
11069
|
+
const rootPresent = root !== "absent" && root !== "invalid";
|
|
11070
|
+
hooks = spec.hookEvents.map((ev) => ({
|
|
11071
|
+
label: hookLabelOf(ev, pad),
|
|
11072
|
+
wired: rootPresent && eventWired(root, ev, spec.hookFormat)
|
|
11073
|
+
}));
|
|
11074
|
+
if (root === "absent") wireState = "absent";
|
|
11075
|
+
else if (root === "invalid") wireState = "invalid";
|
|
11076
|
+
else wireState = primary && eventWired(root, primary, spec.hookFormat) ? "wired" : "unwired";
|
|
11077
|
+
hookLabel = primary ? `${primary.key} hook` : "MCP proxy";
|
|
11078
|
+
settingsPath = spec.hookFile ? spec.hookFile(home) : spec.mcpFile ? spec.mcpFile(home) : "";
|
|
11079
|
+
}
|
|
11080
|
+
const mcp = spec.mcpFile ? readMcp(spec.mcpFile(home), spec.mcpFormat ?? "json") : null;
|
|
11081
|
+
const anyHookWired = hooks.some((h) => h.wired);
|
|
11082
|
+
return {
|
|
11083
|
+
id: spec.id,
|
|
11084
|
+
label: spec.label,
|
|
11085
|
+
setupCommand: spec.setupCommand,
|
|
11086
|
+
installed: detected[spec.id],
|
|
11087
|
+
present,
|
|
11088
|
+
hooks,
|
|
11089
|
+
wireState,
|
|
11090
|
+
hookLabel,
|
|
11091
|
+
settingsPath,
|
|
11092
|
+
configFormat: spec.hookFormat === "yaml" ? "YAML" : "JSON",
|
|
11093
|
+
mcpServers: mcp ? mcp.wrapped : null,
|
|
11094
|
+
mcpProtected: mcp ? mcp.present : false,
|
|
11095
|
+
isProtected: anyHookWired || (mcp?.present ?? false)
|
|
11096
|
+
};
|
|
11097
|
+
});
|
|
10812
11098
|
}
|
|
10813
|
-
var import_fs16, import_path17, import_os13,
|
|
10814
|
-
var
|
|
10815
|
-
"src/
|
|
11099
|
+
var import_fs16, import_path17, import_os13, yaml, import_smol_toml, exists, ck, lg, DEFAULT_LABEL_PAD, hookLabelOf, AGENT_SPECS;
|
|
11100
|
+
var init_agent_wiring = __esm({
|
|
11101
|
+
"src/agent-wiring.ts"() {
|
|
10816
11102
|
"use strict";
|
|
10817
11103
|
import_fs16 = __toESM(require("fs"));
|
|
10818
11104
|
import_path17 = __toESM(require("path"));
|
|
10819
11105
|
import_os13 = __toESM(require("os"));
|
|
10820
|
-
|
|
11106
|
+
yaml = __toESM(require("yaml"));
|
|
10821
11107
|
import_smol_toml = require("smol-toml");
|
|
10822
|
-
|
|
11108
|
+
init_setup();
|
|
11109
|
+
exists = (p) => {
|
|
11110
|
+
try {
|
|
11111
|
+
return import_fs16.default.existsSync(p);
|
|
11112
|
+
} catch {
|
|
11113
|
+
return false;
|
|
11114
|
+
}
|
|
11115
|
+
};
|
|
11116
|
+
ck = (key) => ({ key, kind: "check" });
|
|
11117
|
+
lg = (key) => ({ key, kind: "log" });
|
|
11118
|
+
DEFAULT_LABEL_PAD = 11;
|
|
11119
|
+
hookLabelOf = (ev, pad) => `${ev.key.padEnd(pad)} (node9 ${ev.kind})`;
|
|
11120
|
+
AGENT_SPECS = [
|
|
11121
|
+
{
|
|
11122
|
+
id: "claude",
|
|
11123
|
+
label: "Claude Code",
|
|
11124
|
+
setupCommand: "node9 agents add claude",
|
|
11125
|
+
hookFile: (h) => import_path17.default.join(h, ".claude", "settings.json"),
|
|
11126
|
+
hookFormat: "matcher",
|
|
11127
|
+
// UserPromptSubmit is prompt DLP. setup.ts has written it for Claude since
|
|
11128
|
+
// that shipped; the spec must name it too, or status/doctor never show the
|
|
11129
|
+
// row and heal (which repairs via setupAgent) has no signal it is missing.
|
|
11130
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
11131
|
+
mcpFile: (h) => import_path17.default.join(h, ".claude.json"),
|
|
11132
|
+
present: (h) => exists(import_path17.default.join(h, ".claude", "settings.json")) || exists(import_path17.default.join(h, ".claude.json"))
|
|
11133
|
+
},
|
|
11134
|
+
{
|
|
11135
|
+
id: "gemini",
|
|
11136
|
+
label: "Gemini CLI",
|
|
11137
|
+
setupCommand: "node9 agents add gemini",
|
|
11138
|
+
hookFile: (h) => import_path17.default.join(h, ".gemini", "settings.json"),
|
|
11139
|
+
hookFormat: "matcher",
|
|
11140
|
+
hookEvents: [ck("BeforeTool"), lg("AfterTool")],
|
|
11141
|
+
mcpFile: (h) => import_path17.default.join(h, ".gemini", "settings.json"),
|
|
11142
|
+
present: (h) => exists(import_path17.default.join(h, ".gemini", "settings.json"))
|
|
11143
|
+
},
|
|
11144
|
+
{
|
|
11145
|
+
id: "codex",
|
|
11146
|
+
label: "Codex",
|
|
11147
|
+
setupCommand: "node9 agents add codex",
|
|
11148
|
+
hookFile: (h) => import_path17.default.join(h, ".codex", "hooks.json"),
|
|
11149
|
+
hookFormat: "matcher",
|
|
11150
|
+
hookEvents: [ck("PreToolUse"), ck("UserPromptSubmit")],
|
|
11151
|
+
mcpFile: (h) => import_path17.default.join(h, ".codex", "config.toml"),
|
|
11152
|
+
mcpFormat: "toml",
|
|
11153
|
+
present: (h) => exists(import_path17.default.join(h, ".codex"))
|
|
11154
|
+
},
|
|
11155
|
+
{
|
|
11156
|
+
id: "antigravity",
|
|
11157
|
+
label: "Antigravity",
|
|
11158
|
+
setupCommand: "node9 agents add antigravity",
|
|
11159
|
+
hookFile: (h) => import_path17.default.join(h, ".gemini", "config", "hooks.json"),
|
|
11160
|
+
hookFormat: "matcher",
|
|
11161
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
11162
|
+
mcpFile: (h) => import_path17.default.join(h, ".gemini", "config", "mcp_config.json"),
|
|
11163
|
+
present: (h) => exists(import_path17.default.join(h, ".gemini", "config", "hooks.json")) || exists(import_path17.default.join(h, ".gemini", "antigravity-cli")) || exists(import_path17.default.join(h, ".gemini", "antigravity-ide"))
|
|
11164
|
+
},
|
|
11165
|
+
{
|
|
11166
|
+
id: "copilot",
|
|
11167
|
+
label: "GitHub Copilot",
|
|
11168
|
+
setupCommand: "node9 agents add copilot",
|
|
11169
|
+
hookFile: (h) => import_path17.default.join(h, ".copilot", "hooks", "node9.json"),
|
|
11170
|
+
hookFormat: "flat",
|
|
11171
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
11172
|
+
mcpFile: (h) => import_path17.default.join(h, ".copilot", "mcp-config.json"),
|
|
11173
|
+
present: (h) => exists(import_path17.default.join(h, ".copilot"))
|
|
11174
|
+
},
|
|
11175
|
+
{
|
|
11176
|
+
id: "cursor",
|
|
11177
|
+
label: "Cursor",
|
|
11178
|
+
setupCommand: "node9 agents add cursor",
|
|
11179
|
+
// MCP-only — no hook file (see note above).
|
|
11180
|
+
hookFormat: "flat",
|
|
11181
|
+
hookEvents: [],
|
|
11182
|
+
mcpFile: (h) => import_path17.default.join(h, ".cursor", "mcp.json"),
|
|
11183
|
+
present: (h) => exists(import_path17.default.join(h, ".cursor", "mcp.json"))
|
|
11184
|
+
},
|
|
11185
|
+
{
|
|
11186
|
+
id: "hermes",
|
|
11187
|
+
label: "Hermes Agent",
|
|
11188
|
+
setupCommand: "node9 agents add hermes",
|
|
11189
|
+
hookFile: (h) => hermesConfigPath(h),
|
|
11190
|
+
hookFormat: "yaml",
|
|
11191
|
+
hookEvents: [ck("pre_tool_call"), lg("post_tool_call")],
|
|
11192
|
+
labelPad: 14,
|
|
11193
|
+
// 'post_tool_call' is wider than the default
|
|
11194
|
+
present: (h) => exists(hermesConfigPath(h))
|
|
11195
|
+
},
|
|
11196
|
+
{
|
|
11197
|
+
// Plugin-shim agents — protected by a node9-authored plugin/extension file
|
|
11198
|
+
// (no hooks, no MCP). hookFormat is unused for these (shimFile drives it).
|
|
11199
|
+
id: "opencode",
|
|
11200
|
+
label: "OpenCode",
|
|
11201
|
+
setupCommand: "node9 agents add opencode",
|
|
11202
|
+
hookFormat: "flat",
|
|
11203
|
+
hookEvents: [],
|
|
11204
|
+
shimFile: (h) => import_path17.default.join(opencodeConfigDir(h), "plugins", "node9.js"),
|
|
11205
|
+
present: (h) => exists(opencodeConfigDir(h)) || exists(import_path17.default.join(opencodeConfigDir(h), "plugins", "node9.js"))
|
|
11206
|
+
},
|
|
11207
|
+
{
|
|
11208
|
+
id: "pi",
|
|
11209
|
+
label: "Pi",
|
|
11210
|
+
setupCommand: "node9 agents add pi",
|
|
11211
|
+
hookFormat: "flat",
|
|
11212
|
+
hookEvents: [],
|
|
11213
|
+
shimFile: (h) => import_path17.default.join(h, ".pi", "agent", "extensions", "node9.js"),
|
|
11214
|
+
present: (h) => exists(import_path17.default.join(h, ".pi", "agent")) || exists(import_path17.default.join(h, ".pi", "agent", "extensions", "node9.js"))
|
|
11215
|
+
}
|
|
11216
|
+
];
|
|
11217
|
+
}
|
|
11218
|
+
});
|
|
11219
|
+
|
|
11220
|
+
// src/mcp-cmd.ts
|
|
11221
|
+
function tokenize4(cmd) {
|
|
11222
|
+
const tokens = [];
|
|
11223
|
+
let current = "";
|
|
11224
|
+
let inDouble = false;
|
|
11225
|
+
let quoted = false;
|
|
11226
|
+
let i = 0;
|
|
11227
|
+
while (i < cmd.length) {
|
|
11228
|
+
const ch = cmd[i];
|
|
11229
|
+
if (inDouble) {
|
|
11230
|
+
if (ch === '"') inDouble = false;
|
|
11231
|
+
else if (ch === "\\" && i + 1 < cmd.length) current += cmd[++i];
|
|
11232
|
+
else current += ch;
|
|
11233
|
+
} else if (ch === '"') {
|
|
11234
|
+
inDouble = true;
|
|
11235
|
+
quoted = true;
|
|
11236
|
+
} else if (ch === " " || ch === " ") {
|
|
11237
|
+
if (current || quoted) {
|
|
11238
|
+
tokens.push(current);
|
|
11239
|
+
current = "";
|
|
11240
|
+
quoted = false;
|
|
11241
|
+
}
|
|
11242
|
+
} else if (ch === "\\" && i + 1 < cmd.length) {
|
|
11243
|
+
current += cmd[++i];
|
|
11244
|
+
} else {
|
|
11245
|
+
current += ch;
|
|
11246
|
+
}
|
|
11247
|
+
i++;
|
|
11248
|
+
}
|
|
11249
|
+
if (current || quoted && !inDouble) tokens.push(current);
|
|
11250
|
+
return tokens;
|
|
11251
|
+
}
|
|
11252
|
+
function quoteArg(s) {
|
|
11253
|
+
if (s === "") return '""';
|
|
11254
|
+
if (/[\s"\\]/.test(s)) return `"${s.replace(/(["\\])/g, "\\$1")}"`;
|
|
11255
|
+
return s;
|
|
11256
|
+
}
|
|
11257
|
+
var init_mcp_cmd = __esm({
|
|
11258
|
+
"src/mcp-cmd.ts"() {
|
|
11259
|
+
"use strict";
|
|
10823
11260
|
}
|
|
10824
11261
|
});
|
|
10825
11262
|
|
|
@@ -10981,10 +11418,252 @@ var init_mcp_pin = __esm({
|
|
|
10981
11418
|
}
|
|
10982
11419
|
});
|
|
10983
11420
|
|
|
11421
|
+
// src/mcp-wrap.ts
|
|
11422
|
+
function isNode9Command(command) {
|
|
11423
|
+
return /(^|[\\/])node9(\.(exe|cmd|ps1|bat))?$/i.test(command ?? "");
|
|
11424
|
+
}
|
|
11425
|
+
function classifyMcp(s) {
|
|
11426
|
+
if (isNode9Command(s.command)) {
|
|
11427
|
+
return (s.args ?? [])[0] === "mcp-gateway" ? "gatewayed" : "node9-self";
|
|
11428
|
+
}
|
|
11429
|
+
if (typeof s.command !== "string" || s.command.trim() === "") return "remote";
|
|
11430
|
+
return "ungoverned";
|
|
11431
|
+
}
|
|
11432
|
+
function mcpUpstreamString(s) {
|
|
11433
|
+
return [s.command ?? "", ...s.args ?? []].map(quoteArg).join(" ");
|
|
11434
|
+
}
|
|
11435
|
+
function toGateway(s, configName) {
|
|
11436
|
+
const upstream = mcpUpstreamString(s);
|
|
11437
|
+
const nameArgs = configName && !configName.startsWith("-") ? ["--config-name", configName] : [];
|
|
11438
|
+
return {
|
|
11439
|
+
...s,
|
|
11440
|
+
command: "node9",
|
|
11441
|
+
args: ["mcp-gateway", ...nameArgs, "--upstream", upstream]
|
|
11442
|
+
};
|
|
11443
|
+
}
|
|
11444
|
+
function fromGateway(s) {
|
|
11445
|
+
if (!isNode9Command(s.command) || (s.args ?? [])[0] !== "mcp-gateway") return null;
|
|
11446
|
+
const args = s.args ?? [];
|
|
11447
|
+
const i = args.indexOf("--upstream");
|
|
11448
|
+
if (i < 0 || !args[i + 1]) return null;
|
|
11449
|
+
const [command, ...rest] = tokenize4(args[i + 1]);
|
|
11450
|
+
if (!command) return null;
|
|
11451
|
+
return { ...s, command, args: rest };
|
|
11452
|
+
}
|
|
11453
|
+
function inventoryMcp(home = import_os15.default.homedir()) {
|
|
11454
|
+
const out = [];
|
|
11455
|
+
for (const spec of AGENT_SPECS) {
|
|
11456
|
+
if (!spec.mcpFile) continue;
|
|
11457
|
+
const mcpFile = spec.mcpFile(home);
|
|
11458
|
+
const format = spec.mcpFormat ?? "json";
|
|
11459
|
+
const servers = readMcpServers(mcpFile, format);
|
|
11460
|
+
for (const [name, s] of Object.entries(servers)) {
|
|
11461
|
+
if (!s || typeof s !== "object") continue;
|
|
11462
|
+
out.push({
|
|
11463
|
+
agent: String(spec.id),
|
|
11464
|
+
agentLabel: spec.label,
|
|
11465
|
+
mcpFile,
|
|
11466
|
+
format,
|
|
11467
|
+
name,
|
|
11468
|
+
command: s.command ?? "",
|
|
11469
|
+
args: Array.isArray(s.args) ? s.args : [],
|
|
11470
|
+
state: classifyMcp(s),
|
|
11471
|
+
raw: s
|
|
11472
|
+
});
|
|
11473
|
+
}
|
|
11474
|
+
}
|
|
11475
|
+
return out;
|
|
11476
|
+
}
|
|
11477
|
+
function isCorruptedUpstream(upstream) {
|
|
11478
|
+
if (!upstream) return false;
|
|
11479
|
+
if (upstream.includes("\\") || upstream.includes("/")) return false;
|
|
11480
|
+
return /(^|\s)[A-Za-z]:[^\s]/.test(upstream);
|
|
11481
|
+
}
|
|
11482
|
+
function findCorruptedMcpWraps(home = import_os15.default.homedir()) {
|
|
11483
|
+
const out = [];
|
|
11484
|
+
for (const e of inventoryMcp(home)) {
|
|
11485
|
+
if (e.state !== "gatewayed") continue;
|
|
11486
|
+
const i = e.args.indexOf("--upstream");
|
|
11487
|
+
const upstream = i >= 0 ? e.args[i + 1] ?? "" : "";
|
|
11488
|
+
if (!isCorruptedUpstream(upstream)) continue;
|
|
11489
|
+
out.push({
|
|
11490
|
+
agent: e.agent,
|
|
11491
|
+
agentLabel: e.agentLabel,
|
|
11492
|
+
mcpFile: e.mcpFile,
|
|
11493
|
+
name: e.name,
|
|
11494
|
+
upstream
|
|
11495
|
+
});
|
|
11496
|
+
}
|
|
11497
|
+
return out;
|
|
11498
|
+
}
|
|
11499
|
+
function inventoryServerKeys(inv) {
|
|
11500
|
+
const keys = /* @__PURE__ */ new Set();
|
|
11501
|
+
for (const e of inv) {
|
|
11502
|
+
if (e.state === "gatewayed") {
|
|
11503
|
+
const i = e.args.indexOf("--upstream");
|
|
11504
|
+
if (i >= 0 && e.args[i + 1]) {
|
|
11505
|
+
keys.add(getServerKey(e.args[i + 1]));
|
|
11506
|
+
}
|
|
11507
|
+
} else if (e.state === "ungoverned") {
|
|
11508
|
+
const cmd = [e.command, ...e.args].map(quoteArg).join(" ");
|
|
11509
|
+
keys.add(getServerKey(cmd));
|
|
11510
|
+
}
|
|
11511
|
+
}
|
|
11512
|
+
return keys;
|
|
11513
|
+
}
|
|
11514
|
+
function writeMcpEntry(mcpFile, format, name, entry) {
|
|
11515
|
+
const key = format === "toml" ? "mcp_servers" : "mcpServers";
|
|
11516
|
+
let root = {};
|
|
11517
|
+
if (import_fs18.default.existsSync(mcpFile)) {
|
|
11518
|
+
const raw = import_fs18.default.readFileSync(mcpFile, "utf-8");
|
|
11519
|
+
root = format === "toml" ? (0, import_smol_toml2.parse)(raw) : JSON.parse(raw);
|
|
11520
|
+
const bak = `${mcpFile}.node9-bak`;
|
|
11521
|
+
try {
|
|
11522
|
+
import_fs18.default.writeFileSync(bak, raw, { mode: 384, flag: "wx" });
|
|
11523
|
+
} catch (e) {
|
|
11524
|
+
if (e.code !== "EEXIST") throw e;
|
|
11525
|
+
}
|
|
11526
|
+
}
|
|
11527
|
+
const existing = root[key];
|
|
11528
|
+
const servers = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
11529
|
+
servers[name] = entry;
|
|
11530
|
+
root[key] = servers;
|
|
11531
|
+
const serialized = format === "toml" ? (0, import_smol_toml2.stringify)(root) : JSON.stringify(root, null, 2);
|
|
11532
|
+
const tmp = `${mcpFile}.${process.pid}.tmp`;
|
|
11533
|
+
import_fs18.default.writeFileSync(tmp, serialized, { mode: 384 });
|
|
11534
|
+
import_fs18.default.renameSync(tmp, mcpFile);
|
|
11535
|
+
}
|
|
11536
|
+
var import_fs18, import_os15, import_smol_toml2;
|
|
11537
|
+
var init_mcp_wrap = __esm({
|
|
11538
|
+
"src/mcp-wrap.ts"() {
|
|
11539
|
+
"use strict";
|
|
11540
|
+
import_fs18 = __toESM(require("fs"));
|
|
11541
|
+
import_os15 = __toESM(require("os"));
|
|
11542
|
+
import_smol_toml2 = require("smol-toml");
|
|
11543
|
+
init_agent_wiring();
|
|
11544
|
+
init_mcp_cmd();
|
|
11545
|
+
init_mcp_pin();
|
|
11546
|
+
init_mcp_cmd();
|
|
11547
|
+
}
|
|
11548
|
+
});
|
|
11549
|
+
|
|
11550
|
+
// src/utils/platform-shell.ts
|
|
11551
|
+
function locatorCommand() {
|
|
11552
|
+
return process.platform === "win32" ? "where" : "which";
|
|
11553
|
+
}
|
|
11554
|
+
function shellInvocation(command) {
|
|
11555
|
+
if (process.platform === "win32") {
|
|
11556
|
+
return {
|
|
11557
|
+
file: process.env.ComSpec || "cmd.exe",
|
|
11558
|
+
args: ["/d", "/s", "/c", command]
|
|
11559
|
+
};
|
|
11560
|
+
}
|
|
11561
|
+
return { file: "/bin/bash", args: ["-c", command] };
|
|
11562
|
+
}
|
|
11563
|
+
var init_platform_shell = __esm({
|
|
11564
|
+
"src/utils/platform-shell.ts"() {
|
|
11565
|
+
"use strict";
|
|
11566
|
+
}
|
|
11567
|
+
});
|
|
11568
|
+
|
|
11569
|
+
// src/codex-trust.ts
|
|
11570
|
+
function readTomlSafe(filePath) {
|
|
11571
|
+
try {
|
|
11572
|
+
return (0, import_smol_toml3.parse)(import_fs19.default.readFileSync(filePath, "utf-8"));
|
|
11573
|
+
} catch {
|
|
11574
|
+
return null;
|
|
11575
|
+
}
|
|
11576
|
+
}
|
|
11577
|
+
function lastCodexAuditTs(auditLogPath) {
|
|
11578
|
+
let text;
|
|
11579
|
+
try {
|
|
11580
|
+
text = import_fs19.default.readFileSync(auditLogPath, "utf-8");
|
|
11581
|
+
} catch {
|
|
11582
|
+
return null;
|
|
11583
|
+
}
|
|
11584
|
+
let newest = null;
|
|
11585
|
+
for (const line of text.split("\n")) {
|
|
11586
|
+
if (!line.includes('"Codex"')) continue;
|
|
11587
|
+
try {
|
|
11588
|
+
const row = JSON.parse(line);
|
|
11589
|
+
if (row.agent !== "Codex" || typeof row.ts !== "string") continue;
|
|
11590
|
+
if (newest === null || row.ts > newest) newest = row.ts;
|
|
11591
|
+
} catch {
|
|
11592
|
+
}
|
|
11593
|
+
}
|
|
11594
|
+
return newest;
|
|
11595
|
+
}
|
|
11596
|
+
function assessCodexTrustFrom(input) {
|
|
11597
|
+
const { hooksDisabled, trustEntries, hooksWrittenAt, lastCodexActivityAt } = input;
|
|
11598
|
+
let state;
|
|
11599
|
+
if (hooksDisabled) state = "disabled";
|
|
11600
|
+
else if (trustEntries === 0) state = "never-trusted";
|
|
11601
|
+
else if (hooksWrittenAt && lastCodexActivityAt && lastCodexActivityAt > hooksWrittenAt) {
|
|
11602
|
+
state = "observed";
|
|
11603
|
+
} else state = "unverified";
|
|
11604
|
+
return { state, hooksWrittenAt, lastCodexActivityAt, trustEntries };
|
|
11605
|
+
}
|
|
11606
|
+
function assessCodexTrust(home = import_os16.default.homedir(), auditLogPath = import_path19.default.join(home, ".node9", "audit.log")) {
|
|
11607
|
+
const hooksPath = import_path19.default.join(home, ".codex", "hooks.json");
|
|
11608
|
+
const configPath = import_path19.default.join(home, ".codex", "config.toml");
|
|
11609
|
+
let hooksWrittenAt = null;
|
|
11610
|
+
try {
|
|
11611
|
+
hooksWrittenAt = import_fs19.default.statSync(hooksPath).mtime.toISOString();
|
|
11612
|
+
} catch {
|
|
11613
|
+
hooksWrittenAt = null;
|
|
11614
|
+
}
|
|
11615
|
+
const config = readTomlSafe(configPath);
|
|
11616
|
+
const hooksDisabled = config?.features?.hooks === false || config?.codex_hooks === false;
|
|
11617
|
+
const trustEntries = Object.keys(config?.hooks?.state ?? {}).length;
|
|
11618
|
+
return assessCodexTrustFrom({
|
|
11619
|
+
hooksDisabled,
|
|
11620
|
+
trustEntries,
|
|
11621
|
+
hooksWrittenAt,
|
|
11622
|
+
lastCodexActivityAt: lastCodexAuditTs(auditLogPath)
|
|
11623
|
+
});
|
|
11624
|
+
}
|
|
11625
|
+
function findCodexTui(env = process.env) {
|
|
11626
|
+
try {
|
|
11627
|
+
const r = (0, import_child_process2.spawnSync)(locatorCommand(), ["codex"], { encoding: "utf-8", timeout: 3e3 });
|
|
11628
|
+
const first = (r.stdout ?? "").split(/\r?\n/).find((l) => l.trim());
|
|
11629
|
+
if (r.status === 0 && first) return "codex";
|
|
11630
|
+
} catch {
|
|
11631
|
+
}
|
|
11632
|
+
if (process.platform === "win32" && env.LOCALAPPDATA) {
|
|
11633
|
+
const binDir = import_path19.default.join(env.LOCALAPPDATA, "OpenAI", "Codex", "bin");
|
|
11634
|
+
try {
|
|
11635
|
+
for (const d of import_fs19.default.readdirSync(binDir)) {
|
|
11636
|
+
const exe = import_path19.default.join(binDir, d, "codex.exe");
|
|
11637
|
+
if (import_fs19.default.existsSync(exe)) return `"${exe}"`;
|
|
11638
|
+
}
|
|
11639
|
+
} catch {
|
|
11640
|
+
}
|
|
11641
|
+
}
|
|
11642
|
+
return null;
|
|
11643
|
+
}
|
|
11644
|
+
function codexTrustInstruction(tui = findCodexTui()) {
|
|
11645
|
+
const where = tui ? `run ${tui} in a terminal` : "run the Codex CLI (`codex`) in a terminal \u2014 the desktop app has no hook review screen";
|
|
11646
|
+
return ` \u279C Codex must trust these hooks once: ${where},
|
|
11647
|
+
then choose "Trust all and continue" when Codex asks to review them.
|
|
11648
|
+
Until then Codex runs unprotected. Every rewrite of hooks.json needs this again.`;
|
|
11649
|
+
}
|
|
11650
|
+
var import_fs19, import_path19, import_os16, import_child_process2, import_smol_toml3;
|
|
11651
|
+
var init_codex_trust = __esm({
|
|
11652
|
+
"src/codex-trust.ts"() {
|
|
11653
|
+
"use strict";
|
|
11654
|
+
import_fs19 = __toESM(require("fs"));
|
|
11655
|
+
import_path19 = __toESM(require("path"));
|
|
11656
|
+
import_os16 = __toESM(require("os"));
|
|
11657
|
+
import_child_process2 = require("child_process");
|
|
11658
|
+
import_smol_toml3 = require("smol-toml");
|
|
11659
|
+
init_platform_shell();
|
|
11660
|
+
}
|
|
11661
|
+
});
|
|
11662
|
+
|
|
10984
11663
|
// src/daemon/hook-baseline.ts
|
|
10985
11664
|
function loadHookBaseline() {
|
|
10986
11665
|
try {
|
|
10987
|
-
const raw = JSON.parse(
|
|
11666
|
+
const raw = JSON.parse(import_fs20.default.readFileSync(BASELINE_FILE, "utf-8"));
|
|
10988
11667
|
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
10989
11668
|
} catch {
|
|
10990
11669
|
return {};
|
|
@@ -10992,9 +11671,9 @@ function loadHookBaseline() {
|
|
|
10992
11671
|
}
|
|
10993
11672
|
function saveHookBaseline(b) {
|
|
10994
11673
|
try {
|
|
10995
|
-
const dir =
|
|
10996
|
-
if (!
|
|
10997
|
-
|
|
11674
|
+
const dir = import_path20.default.dirname(BASELINE_FILE);
|
|
11675
|
+
if (!import_fs20.default.existsSync(dir)) import_fs20.default.mkdirSync(dir, { recursive: true });
|
|
11676
|
+
import_fs20.default.writeFileSync(BASELINE_FILE, JSON.stringify(b, null, 2), { mode: 384 });
|
|
10998
11677
|
} catch {
|
|
10999
11678
|
}
|
|
11000
11679
|
}
|
|
@@ -11016,14 +11695,14 @@ function seedHookBaselineIfEmpty(governedNow, now) {
|
|
|
11016
11695
|
function clearHookBaseline() {
|
|
11017
11696
|
for (const f of [BASELINE_FILE, NOTIFIED_FILE]) {
|
|
11018
11697
|
try {
|
|
11019
|
-
|
|
11698
|
+
import_fs20.default.rmSync(f, { force: true });
|
|
11020
11699
|
} catch {
|
|
11021
11700
|
}
|
|
11022
11701
|
}
|
|
11023
11702
|
}
|
|
11024
11703
|
function loadNotified() {
|
|
11025
11704
|
try {
|
|
11026
|
-
const raw = JSON.parse(
|
|
11705
|
+
const raw = JSON.parse(import_fs20.default.readFileSync(NOTIFIED_FILE, "utf-8"));
|
|
11027
11706
|
return new Set(Array.isArray(raw) ? raw : []);
|
|
11028
11707
|
} catch {
|
|
11029
11708
|
return /* @__PURE__ */ new Set();
|
|
@@ -11031,21 +11710,21 @@ function loadNotified() {
|
|
|
11031
11710
|
}
|
|
11032
11711
|
function saveNotified(s) {
|
|
11033
11712
|
try {
|
|
11034
|
-
const dir =
|
|
11035
|
-
if (!
|
|
11036
|
-
|
|
11713
|
+
const dir = import_path20.default.dirname(NOTIFIED_FILE);
|
|
11714
|
+
if (!import_fs20.default.existsSync(dir)) import_fs20.default.mkdirSync(dir, { recursive: true });
|
|
11715
|
+
import_fs20.default.writeFileSync(NOTIFIED_FILE, JSON.stringify([...s]), { mode: 384 });
|
|
11037
11716
|
} catch {
|
|
11038
11717
|
}
|
|
11039
11718
|
}
|
|
11040
|
-
var
|
|
11719
|
+
var import_fs20, import_path20, import_os17, BASELINE_FILE, NOTIFIED_FILE;
|
|
11041
11720
|
var init_hook_baseline = __esm({
|
|
11042
11721
|
"src/daemon/hook-baseline.ts"() {
|
|
11043
11722
|
"use strict";
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
BASELINE_FILE =
|
|
11048
|
-
NOTIFIED_FILE =
|
|
11723
|
+
import_fs20 = __toESM(require("fs"));
|
|
11724
|
+
import_path20 = __toESM(require("path"));
|
|
11725
|
+
import_os17 = __toESM(require("os"));
|
|
11726
|
+
BASELINE_FILE = import_path20.default.join(import_os17.default.homedir(), ".node9", "hooks-baseline.json");
|
|
11727
|
+
NOTIFIED_FILE = import_path20.default.join(import_os17.default.homedir(), ".node9", "hook-heal-notified.json");
|
|
11049
11728
|
}
|
|
11050
11729
|
});
|
|
11051
11730
|
|
|
@@ -11453,7 +12132,7 @@ function printInlineAskNotice() {
|
|
|
11453
12132
|
)
|
|
11454
12133
|
);
|
|
11455
12134
|
}
|
|
11456
|
-
function fullPathCommand(subcommand, platform = process.platform, home =
|
|
12135
|
+
function fullPathCommand(subcommand, platform = process.platform, home = import_os18.default.homedir()) {
|
|
11457
12136
|
if (process.env.NODE9_TESTING === "1") return `node9 ${subcommand}`;
|
|
11458
12137
|
const nodeExec = toForwardSlashes(process.execPath);
|
|
11459
12138
|
const cliScript = toForwardSlashes(process.argv[1]);
|
|
@@ -11465,8 +12144,8 @@ function fullPathCommand(subcommand, platform = process.platform, home = import_
|
|
|
11465
12144
|
ensureHookShim(home, nodeExec, cliScript);
|
|
11466
12145
|
return `"${toForwardSlashes(hookShimPath(home))}" ${subcommand}`;
|
|
11467
12146
|
}
|
|
11468
|
-
function hookShimPath(home =
|
|
11469
|
-
return
|
|
12147
|
+
function hookShimPath(home = import_os18.default.homedir()) {
|
|
12148
|
+
return import_path21.default.join(home, ".node9", "bin", "hook");
|
|
11470
12149
|
}
|
|
11471
12150
|
function hookShimBody(nodeExec, cliScript) {
|
|
11472
12151
|
return `#!/bin/sh
|
|
@@ -11480,12 +12159,12 @@ function ensureHookShim(home, nodeExec, cliScript) {
|
|
|
11480
12159
|
const shim = hookShimPath(home);
|
|
11481
12160
|
const body = hookShimBody(nodeExec, cliScript);
|
|
11482
12161
|
try {
|
|
11483
|
-
if (
|
|
12162
|
+
if (import_fs21.default.readFileSync(shim, "utf-8") === body) return false;
|
|
11484
12163
|
} catch {
|
|
11485
12164
|
}
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
12165
|
+
import_fs21.default.mkdirSync(import_path21.default.dirname(shim), { recursive: true });
|
|
12166
|
+
import_fs21.default.writeFileSync(shim, body, { mode: 493 });
|
|
12167
|
+
import_fs21.default.chmodSync(shim, 493);
|
|
11489
12168
|
return true;
|
|
11490
12169
|
}
|
|
11491
12170
|
function toForwardSlashes(p) {
|
|
@@ -11504,7 +12183,7 @@ function isStaleHookCommand(command) {
|
|
|
11504
12183
|
while ((m = re.exec(command)) !== null) tokens.push(m[1] ?? m[2] ?? "");
|
|
11505
12184
|
for (const tok of tokens) {
|
|
11506
12185
|
if (!tok.startsWith("/") && !/^[A-Za-z]:\//.test(tok)) continue;
|
|
11507
|
-
if (!
|
|
12186
|
+
if (!import_fs21.default.existsSync(tok)) return true;
|
|
11508
12187
|
}
|
|
11509
12188
|
return false;
|
|
11510
12189
|
}
|
|
@@ -11524,19 +12203,19 @@ function isChurnProneHookForm(command, platform = process.platform) {
|
|
|
11524
12203
|
function needsRewrite(command, platform = process.platform) {
|
|
11525
12204
|
return isStaleHookCommand(command) || isLegacyHookFormat(command) || isWindowsQuoteBrokenHook(command, platform) || isChurnProneHookForm(command, platform);
|
|
11526
12205
|
}
|
|
11527
|
-
function
|
|
12206
|
+
function readJson2(filePath) {
|
|
11528
12207
|
try {
|
|
11529
|
-
if (
|
|
11530
|
-
return JSON.parse(
|
|
12208
|
+
if (import_fs21.default.existsSync(filePath)) {
|
|
12209
|
+
return JSON.parse(import_fs21.default.readFileSync(filePath, "utf-8"));
|
|
11531
12210
|
}
|
|
11532
12211
|
} catch {
|
|
11533
12212
|
}
|
|
11534
12213
|
return null;
|
|
11535
12214
|
}
|
|
11536
12215
|
function writeJson(filePath, data) {
|
|
11537
|
-
const dir =
|
|
11538
|
-
if (!
|
|
11539
|
-
|
|
12216
|
+
const dir = import_path21.default.dirname(filePath);
|
|
12217
|
+
if (!import_fs21.default.existsSync(dir)) import_fs21.default.mkdirSync(dir, { recursive: true });
|
|
12218
|
+
import_fs21.default.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n");
|
|
11540
12219
|
}
|
|
11541
12220
|
function mcpWrapArgs(upstream) {
|
|
11542
12221
|
return [MCP_WRAP_SUBCOMMAND, "--upstream", upstream];
|
|
@@ -11556,6 +12235,14 @@ function repairLegacyMcpWraps(servers) {
|
|
|
11556
12235
|
}
|
|
11557
12236
|
return repaired;
|
|
11558
12237
|
}
|
|
12238
|
+
function isCodexAppManagedServer(name, server) {
|
|
12239
|
+
if (!server) return false;
|
|
12240
|
+
const cmd = (server.command ?? "").replace(/\\/g, "/").toLowerCase();
|
|
12241
|
+
if (cmd.includes("/openai/codex/runtimes/")) return true;
|
|
12242
|
+
const envKeys = Object.keys(server.env ?? {});
|
|
12243
|
+
if (envKeys.some((k) => k.startsWith("NODE_REPL_") || k === "CODEX_CLI_PATH")) return true;
|
|
12244
|
+
return name === "node_repl";
|
|
12245
|
+
}
|
|
11559
12246
|
function isNode9Hook(cmd) {
|
|
11560
12247
|
if (!cmd) return false;
|
|
11561
12248
|
return /(?:^|[\s/\\"])node9"? (?:check|log)/.test(cmd) || /(?:^|[\s/\\])cli\.js"? (?:check|log)/.test(cmd) || // The shim form: "<home>/.node9/bin/hook" check. Without this alternative a
|
|
@@ -11565,11 +12252,11 @@ function isNode9Hook(cmd) {
|
|
|
11565
12252
|
/[/\\]\.node9[/\\]bin[/\\]hook"? (?:check|log)/.test(cmd);
|
|
11566
12253
|
}
|
|
11567
12254
|
function teardownClaude() {
|
|
11568
|
-
const homeDir2 =
|
|
11569
|
-
const hooksPath =
|
|
11570
|
-
const mcpPath =
|
|
12255
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12256
|
+
const hooksPath = import_path21.default.join(homeDir2, ".claude", "settings.json");
|
|
12257
|
+
const mcpPath = import_path21.default.join(homeDir2, ".claude", ".mcp.json");
|
|
11571
12258
|
let changed = false;
|
|
11572
|
-
const settings =
|
|
12259
|
+
const settings = readJson2(hooksPath);
|
|
11573
12260
|
if (settings?.hooks) {
|
|
11574
12261
|
for (const event of ["PreToolUse", "PostToolUse", "UserPromptSubmit"]) {
|
|
11575
12262
|
const before = settings.hooks[event]?.length ?? 0;
|
|
@@ -11588,7 +12275,7 @@ function teardownClaude() {
|
|
|
11588
12275
|
console.log(import_chalk.default.blue(" \u2139\uFE0F No Node9 hooks found in ~/.claude/settings.json"));
|
|
11589
12276
|
}
|
|
11590
12277
|
}
|
|
11591
|
-
const claudeConfig =
|
|
12278
|
+
const claudeConfig = readJson2(mcpPath);
|
|
11592
12279
|
if (claudeConfig?.mcpServers) {
|
|
11593
12280
|
let mcpChanged = false;
|
|
11594
12281
|
if (removeNode9McpServer(claudeConfig.mcpServers)) {
|
|
@@ -11615,9 +12302,9 @@ function teardownClaude() {
|
|
|
11615
12302
|
}
|
|
11616
12303
|
}
|
|
11617
12304
|
function teardownGemini() {
|
|
11618
|
-
const homeDir2 =
|
|
11619
|
-
const settingsPath =
|
|
11620
|
-
const settings =
|
|
12305
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12306
|
+
const settingsPath = import_path21.default.join(homeDir2, ".gemini", "settings.json");
|
|
12307
|
+
const settings = readJson2(settingsPath);
|
|
11621
12308
|
if (!settings) {
|
|
11622
12309
|
console.log(import_chalk.default.blue(" \u2139\uFE0F ~/.gemini/settings.json not found \u2014 nothing to remove"));
|
|
11623
12310
|
return;
|
|
@@ -11659,9 +12346,9 @@ function teardownGemini() {
|
|
|
11659
12346
|
}
|
|
11660
12347
|
}
|
|
11661
12348
|
function teardownCursor() {
|
|
11662
|
-
const homeDir2 =
|
|
11663
|
-
const mcpPath =
|
|
11664
|
-
const mcpConfig =
|
|
12349
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12350
|
+
const mcpPath = import_path21.default.join(homeDir2, ".cursor", "mcp.json");
|
|
12351
|
+
const mcpConfig = readJson2(mcpPath);
|
|
11665
12352
|
if (!mcpConfig?.mcpServers) {
|
|
11666
12353
|
console.log(import_chalk.default.blue(" \u2139\uFE0F ~/.cursor/mcp.json not found \u2014 nothing to remove"));
|
|
11667
12354
|
return;
|
|
@@ -11692,11 +12379,11 @@ function teardownCursor() {
|
|
|
11692
12379
|
}
|
|
11693
12380
|
async function setupClaude() {
|
|
11694
12381
|
seedMcpPinsIfMissing();
|
|
11695
|
-
const homeDir2 =
|
|
11696
|
-
const mcpPath =
|
|
11697
|
-
const hooksPath =
|
|
11698
|
-
const claudeConfig =
|
|
11699
|
-
const settings =
|
|
12382
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12383
|
+
const mcpPath = import_path21.default.join(homeDir2, ".claude", ".mcp.json");
|
|
12384
|
+
const hooksPath = import_path21.default.join(homeDir2, ".claude", "settings.json");
|
|
12385
|
+
const claudeConfig = readJson2(mcpPath) ?? {};
|
|
12386
|
+
const settings = readJson2(hooksPath) ?? {};
|
|
11700
12387
|
const servers = claudeConfig.mcpServers ?? {};
|
|
11701
12388
|
let hooksChanged = false;
|
|
11702
12389
|
let anythingChanged = false;
|
|
@@ -11817,7 +12504,7 @@ async function setupClaude() {
|
|
|
11817
12504
|
const serversToWrap = [];
|
|
11818
12505
|
for (const [name, server] of Object.entries(servers)) {
|
|
11819
12506
|
if (!server.command || server.command === "node9") continue;
|
|
11820
|
-
const upstream =
|
|
12507
|
+
const upstream = mcpUpstreamString(server);
|
|
11821
12508
|
serversToWrap.push({ name, upstream });
|
|
11822
12509
|
}
|
|
11823
12510
|
if (serversToWrap.length > 0) {
|
|
@@ -11870,9 +12557,9 @@ async function setupGemini() {
|
|
|
11870
12557
|
);
|
|
11871
12558
|
console.log("");
|
|
11872
12559
|
seedMcpPinsIfMissing();
|
|
11873
|
-
const homeDir2 =
|
|
11874
|
-
const settingsPath =
|
|
11875
|
-
const settings =
|
|
12560
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12561
|
+
const settingsPath = import_path21.default.join(homeDir2, ".gemini", "settings.json");
|
|
12562
|
+
const settings = readJson2(settingsPath) ?? {};
|
|
11876
12563
|
const servers = settings.mcpServers ?? {};
|
|
11877
12564
|
let hooksChanged = false;
|
|
11878
12565
|
let anythingChanged = false;
|
|
@@ -11939,7 +12626,7 @@ async function setupGemini() {
|
|
|
11939
12626
|
const serversToWrap = [];
|
|
11940
12627
|
for (const [name, server] of Object.entries(servers)) {
|
|
11941
12628
|
if (!server.command || server.command === "node9") continue;
|
|
11942
|
-
const upstream =
|
|
12629
|
+
const upstream = mcpUpstreamString(server);
|
|
11943
12630
|
serversToWrap.push({ name, upstream });
|
|
11944
12631
|
}
|
|
11945
12632
|
if (serversToWrap.length > 0) {
|
|
@@ -11985,11 +12672,11 @@ async function setupGemini() {
|
|
|
11985
12672
|
}
|
|
11986
12673
|
async function setupAntigravity() {
|
|
11987
12674
|
seedMcpPinsIfMissing();
|
|
11988
|
-
const homeDir2 =
|
|
11989
|
-
const hooksPath =
|
|
11990
|
-
const mcpPath =
|
|
11991
|
-
const hooksFile =
|
|
11992
|
-
const mcpConfig =
|
|
12675
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12676
|
+
const hooksPath = import_path21.default.join(homeDir2, ".gemini", "config", "hooks.json");
|
|
12677
|
+
const mcpPath = import_path21.default.join(homeDir2, ".gemini", "config", "mcp_config.json");
|
|
12678
|
+
const hooksFile = readJson2(hooksPath) ?? {};
|
|
12679
|
+
const mcpConfig = readJson2(mcpPath) ?? {};
|
|
11993
12680
|
const servers = mcpConfig.mcpServers ?? {};
|
|
11994
12681
|
let hooksChanged = false;
|
|
11995
12682
|
let anythingChanged = false;
|
|
@@ -12082,7 +12769,7 @@ async function setupAntigravity() {
|
|
|
12082
12769
|
}
|
|
12083
12770
|
anythingChanged = true;
|
|
12084
12771
|
}
|
|
12085
|
-
const legacySettings =
|
|
12772
|
+
const legacySettings = readJson2(import_path21.default.join(homeDir2, ".gemini", "settings.json"));
|
|
12086
12773
|
const legacyHasNode9 = ["BeforeTool", "AfterTool"].some(
|
|
12087
12774
|
(ev) => legacySettings?.hooks?.[ev]?.some((m) => m.hooks.some((h) => isNode9Hook(h.command)))
|
|
12088
12775
|
);
|
|
@@ -12153,11 +12840,11 @@ async function setupAntigravity() {
|
|
|
12153
12840
|
}
|
|
12154
12841
|
}
|
|
12155
12842
|
function teardownAntigravity() {
|
|
12156
|
-
const homeDir2 =
|
|
12157
|
-
const hooksPath =
|
|
12158
|
-
const mcpPath =
|
|
12843
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12844
|
+
const hooksPath = import_path21.default.join(homeDir2, ".gemini", "config", "hooks.json");
|
|
12845
|
+
const mcpPath = import_path21.default.join(homeDir2, ".gemini", "config", "mcp_config.json");
|
|
12159
12846
|
let changed = false;
|
|
12160
|
-
const hooksFile =
|
|
12847
|
+
const hooksFile = readJson2(hooksPath);
|
|
12161
12848
|
if (hooksFile?.hooks) {
|
|
12162
12849
|
for (const event of ["PreToolUse", "PostToolUse"]) {
|
|
12163
12850
|
const before = hooksFile.hooks[event]?.length ?? 0;
|
|
@@ -12178,7 +12865,7 @@ function teardownAntigravity() {
|
|
|
12178
12865
|
} else {
|
|
12179
12866
|
console.log(import_chalk.default.blue(" \u2139\uFE0F ~/.gemini/config/hooks.json not found \u2014 nothing to remove"));
|
|
12180
12867
|
}
|
|
12181
|
-
const mcpConfig =
|
|
12868
|
+
const mcpConfig = readJson2(mcpPath);
|
|
12182
12869
|
if (mcpConfig?.mcpServers) {
|
|
12183
12870
|
let mcpChanged = false;
|
|
12184
12871
|
if (removeNode9McpServer(mcpConfig.mcpServers)) {
|
|
@@ -12207,13 +12894,13 @@ function teardownAntigravity() {
|
|
|
12207
12894
|
}
|
|
12208
12895
|
async function setupCopilot() {
|
|
12209
12896
|
seedMcpPinsIfMissing();
|
|
12210
|
-
const homeDir2 =
|
|
12211
|
-
const hooksPath =
|
|
12212
|
-
const mcpPath =
|
|
12213
|
-
const hooksFile =
|
|
12897
|
+
const homeDir2 = import_os18.default.homedir();
|
|
12898
|
+
const hooksPath = import_path21.default.join(homeDir2, ".copilot", "hooks", "node9.json");
|
|
12899
|
+
const mcpPath = import_path21.default.join(homeDir2, ".copilot", "mcp-config.json");
|
|
12900
|
+
const hooksFile = readJson2(hooksPath) ?? { version: 1 };
|
|
12214
12901
|
if (!hooksFile.version) hooksFile.version = 1;
|
|
12215
12902
|
if (!hooksFile.hooks) hooksFile.hooks = {};
|
|
12216
|
-
const mcpConfig =
|
|
12903
|
+
const mcpConfig = readJson2(mcpPath) ?? {};
|
|
12217
12904
|
const servers = mcpConfig.mcpServers ?? {};
|
|
12218
12905
|
let hooksChanged = false;
|
|
12219
12906
|
let anythingChanged = false;
|
|
@@ -12310,10 +12997,10 @@ async function setupCopilot() {
|
|
|
12310
12997
|
printInlineAskNotice();
|
|
12311
12998
|
}
|
|
12312
12999
|
function teardownCopilot() {
|
|
12313
|
-
const homeDir2 =
|
|
12314
|
-
const hooksPath =
|
|
12315
|
-
const mcpPath =
|
|
12316
|
-
const hooksFile =
|
|
13000
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13001
|
+
const hooksPath = import_path21.default.join(homeDir2, ".copilot", "hooks", "node9.json");
|
|
13002
|
+
const mcpPath = import_path21.default.join(homeDir2, ".copilot", "mcp-config.json");
|
|
13003
|
+
const hooksFile = readJson2(hooksPath);
|
|
12317
13004
|
let changed = false;
|
|
12318
13005
|
if (hooksFile?.hooks) {
|
|
12319
13006
|
for (const event of ["PreToolUse", "PostToolUse", "UserPromptSubmit"]) {
|
|
@@ -12325,7 +13012,7 @@ function teardownCopilot() {
|
|
|
12325
13012
|
if (changed) {
|
|
12326
13013
|
if (Object.keys(hooksFile.hooks).length === 0) {
|
|
12327
13014
|
try {
|
|
12328
|
-
|
|
13015
|
+
import_fs21.default.unlinkSync(hooksPath);
|
|
12329
13016
|
console.log(import_chalk.default.green(" \u2705 Removed ~/.copilot/hooks/node9.json"));
|
|
12330
13017
|
} catch {
|
|
12331
13018
|
writeJson(hooksPath, hooksFile);
|
|
@@ -12340,7 +13027,7 @@ function teardownCopilot() {
|
|
|
12340
13027
|
} else {
|
|
12341
13028
|
console.log(import_chalk.default.blue(" \u2139\uFE0F ~/.copilot/hooks/node9.json not found \u2014 nothing to remove"));
|
|
12342
13029
|
}
|
|
12343
|
-
const mcpConfig =
|
|
13030
|
+
const mcpConfig = readJson2(mcpPath);
|
|
12344
13031
|
if (mcpConfig?.mcpServers) {
|
|
12345
13032
|
let mcpChanged = false;
|
|
12346
13033
|
if (removeNode9McpServer(mcpConfig.mcpServers)) {
|
|
@@ -12367,9 +13054,9 @@ function teardownCopilot() {
|
|
|
12367
13054
|
}
|
|
12368
13055
|
}
|
|
12369
13056
|
}
|
|
12370
|
-
function claudeDesktopConfigPath(homeDir2 =
|
|
13057
|
+
function claudeDesktopConfigPath(homeDir2 = import_os18.default.homedir()) {
|
|
12371
13058
|
if (process.platform === "darwin") {
|
|
12372
|
-
return
|
|
13059
|
+
return import_path21.default.join(
|
|
12373
13060
|
homeDir2,
|
|
12374
13061
|
"Library",
|
|
12375
13062
|
"Application Support",
|
|
@@ -12378,47 +13065,47 @@ function claudeDesktopConfigPath(homeDir2 = import_os16.default.homedir()) {
|
|
|
12378
13065
|
);
|
|
12379
13066
|
}
|
|
12380
13067
|
if (process.platform === "linux") {
|
|
12381
|
-
return
|
|
13068
|
+
return import_path21.default.join(homeDir2, ".config", "Claude", "claude_desktop_config.json");
|
|
12382
13069
|
}
|
|
12383
13070
|
if (process.platform === "win32") {
|
|
12384
|
-
const appData = process.env.APPDATA ||
|
|
12385
|
-
return
|
|
13071
|
+
const appData = process.env.APPDATA || import_path21.default.join(homeDir2, "AppData", "Roaming");
|
|
13072
|
+
return import_path21.default.join(appData, "Claude", "claude_desktop_config.json");
|
|
12386
13073
|
}
|
|
12387
13074
|
return null;
|
|
12388
13075
|
}
|
|
12389
|
-
function opencodeConfigDir(home =
|
|
13076
|
+
function opencodeConfigDir(home = import_os18.default.homedir()) {
|
|
12390
13077
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
12391
|
-
const base = xdg &&
|
|
12392
|
-
return
|
|
13078
|
+
const base = xdg && import_path21.default.isAbsolute(xdg) ? xdg : import_path21.default.join(home, ".config");
|
|
13079
|
+
return import_path21.default.join(base, "opencode");
|
|
12393
13080
|
}
|
|
12394
13081
|
function commonBinDirs(home) {
|
|
12395
13082
|
return [
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
13083
|
+
import_path21.default.join(home, ".local", "bin"),
|
|
13084
|
+
import_path21.default.join(home, ".bun", "bin"),
|
|
13085
|
+
import_path21.default.join(home, ".npm-global", "bin"),
|
|
12399
13086
|
"/usr/local/bin",
|
|
12400
13087
|
"/opt/homebrew/bin"
|
|
12401
13088
|
];
|
|
12402
13089
|
}
|
|
12403
|
-
function binaryInPath(binary, home =
|
|
13090
|
+
function binaryInPath(binary, home = import_os18.default.homedir()) {
|
|
12404
13091
|
const pathEnv = process.env.PATH ?? "";
|
|
12405
|
-
const dirs = [...pathEnv.split(
|
|
13092
|
+
const dirs = [...pathEnv.split(import_path21.default.delimiter), ...commonBinDirs(home)];
|
|
12406
13093
|
const seen = /* @__PURE__ */ new Set();
|
|
12407
13094
|
for (const dir of dirs) {
|
|
12408
13095
|
if (!dir || seen.has(dir)) continue;
|
|
12409
13096
|
seen.add(dir);
|
|
12410
13097
|
try {
|
|
12411
|
-
|
|
13098
|
+
import_fs21.default.accessSync(import_path21.default.join(dir, binary), import_fs21.default.constants.X_OK);
|
|
12412
13099
|
return true;
|
|
12413
13100
|
} catch {
|
|
12414
13101
|
}
|
|
12415
13102
|
}
|
|
12416
13103
|
return false;
|
|
12417
13104
|
}
|
|
12418
|
-
function detectAgents(homeDir2 =
|
|
13105
|
+
function detectAgents(homeDir2 = import_os18.default.homedir()) {
|
|
12419
13106
|
const exists2 = (p) => {
|
|
12420
13107
|
try {
|
|
12421
|
-
return
|
|
13108
|
+
return import_fs21.default.existsSync(p);
|
|
12422
13109
|
} catch (err2) {
|
|
12423
13110
|
const code = err2.code;
|
|
12424
13111
|
if (code !== "ENOENT") {
|
|
@@ -12430,7 +13117,7 @@ function detectAgents(homeDir2 = import_os16.default.homedir()) {
|
|
|
12430
13117
|
};
|
|
12431
13118
|
const desktopPath = claudeDesktopConfigPath(homeDir2);
|
|
12432
13119
|
return {
|
|
12433
|
-
claude: exists2(
|
|
13120
|
+
claude: exists2(import_path21.default.join(homeDir2, ".claude")) || exists2(import_path21.default.join(homeDir2, ".claude.json")),
|
|
12434
13121
|
// Antigravity (agy) shares the ~/.gemini root, so a bare
|
|
12435
13122
|
// `exists(~/.gemini)` would report the (EOL'd) Gemini CLI as
|
|
12436
13123
|
// installed on every agy machine — and `node9 init` would then
|
|
@@ -12440,19 +13127,19 @@ function detectAgents(homeDir2 = import_os16.default.homedir()) {
|
|
|
12440
13127
|
// creates ~/.gemini/settings.json on first run; agy does not touch
|
|
12441
13128
|
// it (it uses antigravity-cli/settings.json) — that file is the
|
|
12442
13129
|
// legacy-CLI discriminator.
|
|
12443
|
-
gemini: exists2(
|
|
13130
|
+
gemini: exists2(import_path21.default.join(homeDir2, ".gemini", "settings.json")) || binaryInPath("gemini", homeDir2),
|
|
12444
13131
|
// agy creates ~/.gemini/antigravity-cli/ on first launch; the IDE
|
|
12445
13132
|
// creates antigravity-ide/. PATH fallback covers installed-but-
|
|
12446
13133
|
// never-launched (same class as opencode #186).
|
|
12447
|
-
antigravity: exists2(
|
|
13134
|
+
antigravity: exists2(import_path21.default.join(homeDir2, ".gemini", "antigravity-cli")) || exists2(import_path21.default.join(homeDir2, ".gemini", "antigravity-ide")) || binaryInPath("agy", homeDir2),
|
|
12448
13135
|
// GitHub Copilot CLI creates ~/.copilot on first launch; PATH
|
|
12449
13136
|
// fallback covers installed-but-never-launched (same as opencode #186).
|
|
12450
|
-
copilot: exists2(
|
|
12451
|
-
cursor: exists2(
|
|
12452
|
-
codex: exists2(
|
|
12453
|
-
windsurf: exists2(
|
|
12454
|
-
vscode: exists2(
|
|
12455
|
-
claudeDesktop: desktopPath !== null && exists2(
|
|
13137
|
+
copilot: exists2(import_path21.default.join(homeDir2, ".copilot")) || binaryInPath("copilot", homeDir2),
|
|
13138
|
+
cursor: exists2(import_path21.default.join(homeDir2, ".cursor")),
|
|
13139
|
+
codex: exists2(import_path21.default.join(homeDir2, ".codex")),
|
|
13140
|
+
windsurf: exists2(import_path21.default.join(homeDir2, ".codeium", "windsurf")),
|
|
13141
|
+
vscode: exists2(import_path21.default.join(homeDir2, ".vscode")),
|
|
13142
|
+
claudeDesktop: desktopPath !== null && exists2(import_path21.default.dirname(desktopPath)),
|
|
12456
13143
|
// Opencode creates its config dir lazily on first launch — fall back to a
|
|
12457
13144
|
// PATH lookup so installed-but-never-launched CLIs are still wired. Config
|
|
12458
13145
|
// dir honors $XDG_CONFIG_HOME via opencodeConfigDir (#186, custom-XDG).
|
|
@@ -12463,7 +13150,7 @@ function detectAgents(homeDir2 = import_os16.default.homedir()) {
|
|
|
12463
13150
|
// dir lazily on first launch — same class of bug as opencode's #186
|
|
12464
13151
|
// (design R6) — so fall back to PATH lookup for installed-but-never-
|
|
12465
13152
|
// launched pi.
|
|
12466
|
-
pi: exists2(
|
|
13153
|
+
pi: exists2(import_path21.default.join(homeDir2, ".pi", "agent")) || binaryInPath("pi", homeDir2),
|
|
12467
13154
|
// Hermes Agent (https://github.com/NousResearch/hermes-agent): home dir
|
|
12468
13155
|
// is $HERMES_HOME (default ~/.hermes) per hermes_constants.py:30. config.yaml
|
|
12469
13156
|
// appears after `hermes setup` has run; the directory alone exists from
|
|
@@ -12474,9 +13161,9 @@ function detectAgents(homeDir2 = import_os16.default.homedir()) {
|
|
|
12474
13161
|
}
|
|
12475
13162
|
async function setupCursor() {
|
|
12476
13163
|
seedMcpPinsIfMissing();
|
|
12477
|
-
const homeDir2 =
|
|
12478
|
-
const mcpPath =
|
|
12479
|
-
const mcpConfig =
|
|
13164
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13165
|
+
const mcpPath = import_path21.default.join(homeDir2, ".cursor", "mcp.json");
|
|
13166
|
+
const mcpConfig = readJson2(mcpPath) ?? {};
|
|
12480
13167
|
const servers = mcpConfig.mcpServers ?? {};
|
|
12481
13168
|
let anythingChanged = false;
|
|
12482
13169
|
const repairedMcpWraps = repairLegacyMcpWraps(
|
|
@@ -12502,7 +13189,7 @@ async function setupCursor() {
|
|
|
12502
13189
|
const serversToWrap = [];
|
|
12503
13190
|
for (const [name, server] of Object.entries(servers)) {
|
|
12504
13191
|
if (!server.command || server.command === "node9") continue;
|
|
12505
|
-
const upstream =
|
|
13192
|
+
const upstream = mcpUpstreamString(server);
|
|
12506
13193
|
serversToWrap.push({ name, upstream });
|
|
12507
13194
|
}
|
|
12508
13195
|
if (serversToWrap.length > 0) {
|
|
@@ -12558,27 +13245,27 @@ async function setupCursor() {
|
|
|
12558
13245
|
}
|
|
12559
13246
|
function readToml(filePath) {
|
|
12560
13247
|
try {
|
|
12561
|
-
if (
|
|
12562
|
-
return (0,
|
|
13248
|
+
if (import_fs21.default.existsSync(filePath)) {
|
|
13249
|
+
return (0, import_smol_toml4.parse)(import_fs21.default.readFileSync(filePath, "utf-8"));
|
|
12563
13250
|
}
|
|
12564
13251
|
} catch {
|
|
12565
13252
|
}
|
|
12566
13253
|
return null;
|
|
12567
13254
|
}
|
|
12568
13255
|
function writeToml(filePath, data) {
|
|
12569
|
-
const dir =
|
|
12570
|
-
if (!
|
|
12571
|
-
|
|
13256
|
+
const dir = import_path21.default.dirname(filePath);
|
|
13257
|
+
if (!import_fs21.default.existsSync(dir)) import_fs21.default.mkdirSync(dir, { recursive: true });
|
|
13258
|
+
import_fs21.default.writeFileSync(filePath, (0, import_smol_toml4.stringify)(data));
|
|
12572
13259
|
}
|
|
12573
13260
|
async function setupCodex() {
|
|
12574
13261
|
seedMcpPinsIfMissing();
|
|
12575
|
-
const homeDir2 =
|
|
12576
|
-
const configPath =
|
|
12577
|
-
const hooksPath =
|
|
13262
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13263
|
+
const configPath = import_path21.default.join(homeDir2, ".codex", "config.toml");
|
|
13264
|
+
const hooksPath = import_path21.default.join(homeDir2, ".codex", "hooks.json");
|
|
12578
13265
|
const config = readToml(configPath) ?? {};
|
|
12579
13266
|
const servers = config.mcp_servers ?? {};
|
|
12580
13267
|
let anythingChanged = false;
|
|
12581
|
-
const hooksFile =
|
|
13268
|
+
const hooksFile = readJson2(hooksPath) ?? {};
|
|
12582
13269
|
if (!hooksFile.hooks) hooksFile.hooks = {};
|
|
12583
13270
|
let hooksChanged = false;
|
|
12584
13271
|
if (!hooksFile.hooks.PreToolUse) hooksFile.hooks.PreToolUse = [];
|
|
@@ -12671,11 +13358,21 @@ async function setupCodex() {
|
|
|
12671
13358
|
anythingChanged = true;
|
|
12672
13359
|
}
|
|
12673
13360
|
const serversToWrap = [];
|
|
13361
|
+
const appManaged = [];
|
|
12674
13362
|
for (const [name, server] of Object.entries(servers)) {
|
|
12675
13363
|
if (!server.command || server.command === "node9") continue;
|
|
12676
|
-
|
|
13364
|
+
if (isCodexAppManagedServer(name, server)) {
|
|
13365
|
+
appManaged.push(name);
|
|
13366
|
+
continue;
|
|
13367
|
+
}
|
|
13368
|
+
const upstream = mcpUpstreamString(server);
|
|
12677
13369
|
serversToWrap.push({ name, upstream });
|
|
12678
13370
|
}
|
|
13371
|
+
if (appManaged.length > 0) {
|
|
13372
|
+
console.log(
|
|
13373
|
+
import_chalk.default.gray(` \u2139\uFE0F Managed by the Codex app \u2014 not wrapped: ${appManaged.join(", ")}`)
|
|
13374
|
+
);
|
|
13375
|
+
}
|
|
12679
13376
|
if (serversToWrap.length > 0) {
|
|
12680
13377
|
console.log(import_chalk.default.bold("The following existing entries will be modified:\n"));
|
|
12681
13378
|
console.log(import_chalk.default.white(` ${configPath}`));
|
|
@@ -12740,10 +13437,10 @@ async function setupCodex() {
|
|
|
12740
13437
|
}
|
|
12741
13438
|
}
|
|
12742
13439
|
function teardownCodex() {
|
|
12743
|
-
const homeDir2 =
|
|
12744
|
-
const configPath =
|
|
12745
|
-
const hooksPath =
|
|
12746
|
-
const hooksFile =
|
|
13440
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13441
|
+
const configPath = import_path21.default.join(homeDir2, ".codex", "config.toml");
|
|
13442
|
+
const hooksPath = import_path21.default.join(homeDir2, ".codex", "hooks.json");
|
|
13443
|
+
const hooksFile = readJson2(hooksPath);
|
|
12747
13444
|
if (hooksFile?.hooks) {
|
|
12748
13445
|
let hooksChanged = false;
|
|
12749
13446
|
for (const event of ["PreToolUse", "PostToolUse", "UserPromptSubmit"]) {
|
|
@@ -12789,9 +13486,9 @@ function teardownCodex() {
|
|
|
12789
13486
|
}
|
|
12790
13487
|
}
|
|
12791
13488
|
function setupHud() {
|
|
12792
|
-
const homeDir2 =
|
|
12793
|
-
const hooksPath =
|
|
12794
|
-
const settings =
|
|
13489
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13490
|
+
const hooksPath = import_path21.default.join(homeDir2, ".claude", "settings.json");
|
|
13491
|
+
const settings = readJson2(hooksPath) ?? {};
|
|
12795
13492
|
const hudCommand = fullPathCommand("hud");
|
|
12796
13493
|
const statusLineObj = { type: "command", command: hudCommand };
|
|
12797
13494
|
const existing = settings.statusLine;
|
|
@@ -12818,9 +13515,9 @@ function setupHud() {
|
|
|
12818
13515
|
console.log(import_chalk.default.gray(" Restart Claude Code to activate."));
|
|
12819
13516
|
}
|
|
12820
13517
|
function teardownHud() {
|
|
12821
|
-
const homeDir2 =
|
|
12822
|
-
const hooksPath =
|
|
12823
|
-
const settings =
|
|
13518
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13519
|
+
const hooksPath = import_path21.default.join(homeDir2, ".claude", "settings.json");
|
|
13520
|
+
const settings = readJson2(hooksPath);
|
|
12824
13521
|
if (!settings) {
|
|
12825
13522
|
console.log(import_chalk.default.blue(" \u2139\uFE0F ~/.claude/settings.json not found \u2014 nothing to remove"));
|
|
12826
13523
|
return;
|
|
@@ -12838,9 +13535,9 @@ function teardownHud() {
|
|
|
12838
13535
|
}
|
|
12839
13536
|
async function setupWindsurf() {
|
|
12840
13537
|
seedMcpPinsIfMissing();
|
|
12841
|
-
const homeDir2 =
|
|
12842
|
-
const mcpPath =
|
|
12843
|
-
const mcpConfig =
|
|
13538
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13539
|
+
const mcpPath = import_path21.default.join(homeDir2, ".codeium", "windsurf", "mcp_config.json");
|
|
13540
|
+
const mcpConfig = readJson2(mcpPath) ?? {};
|
|
12844
13541
|
const servers = mcpConfig.mcpServers ?? {};
|
|
12845
13542
|
let anythingChanged = false;
|
|
12846
13543
|
const repairedMcpWraps = repairLegacyMcpWraps(
|
|
@@ -12916,9 +13613,9 @@ async function setupWindsurf() {
|
|
|
12916
13613
|
}
|
|
12917
13614
|
}
|
|
12918
13615
|
function teardownWindsurf() {
|
|
12919
|
-
const homeDir2 =
|
|
12920
|
-
const mcpPath =
|
|
12921
|
-
const mcpConfig =
|
|
13616
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13617
|
+
const mcpPath = import_path21.default.join(homeDir2, ".codeium", "windsurf", "mcp_config.json");
|
|
13618
|
+
const mcpConfig = readJson2(mcpPath);
|
|
12922
13619
|
if (!mcpConfig?.mcpServers) {
|
|
12923
13620
|
console.log(
|
|
12924
13621
|
import_chalk.default.blue(" \u2139\uFE0F ~/.codeium/windsurf/mcp_config.json not found \u2014 nothing to remove")
|
|
@@ -12959,9 +13656,9 @@ function hasNode9McpServerVSCode(servers) {
|
|
|
12959
13656
|
}
|
|
12960
13657
|
async function setupVSCode() {
|
|
12961
13658
|
seedMcpPinsIfMissing();
|
|
12962
|
-
const homeDir2 =
|
|
12963
|
-
const mcpPath =
|
|
12964
|
-
const mcpConfig =
|
|
13659
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13660
|
+
const mcpPath = import_path21.default.join(homeDir2, ".vscode", "mcp.json");
|
|
13661
|
+
const mcpConfig = readJson2(mcpPath) ?? {};
|
|
12965
13662
|
const servers = mcpConfig.servers ?? {};
|
|
12966
13663
|
let anythingChanged = false;
|
|
12967
13664
|
const repairedMcpWraps = repairLegacyMcpWraps(
|
|
@@ -13040,9 +13737,9 @@ async function setupVSCode() {
|
|
|
13040
13737
|
}
|
|
13041
13738
|
}
|
|
13042
13739
|
function teardownVSCode() {
|
|
13043
|
-
const homeDir2 =
|
|
13044
|
-
const mcpPath =
|
|
13045
|
-
const mcpConfig =
|
|
13740
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13741
|
+
const mcpPath = import_path21.default.join(homeDir2, ".vscode", "mcp.json");
|
|
13742
|
+
const mcpConfig = readJson2(mcpPath);
|
|
13046
13743
|
if (!mcpConfig?.servers) {
|
|
13047
13744
|
console.log(import_chalk.default.blue(" \u2139\uFE0F ~/.vscode/mcp.json not found \u2014 nothing to remove"));
|
|
13048
13745
|
return;
|
|
@@ -13080,7 +13777,7 @@ async function setupClaudeDesktop() {
|
|
|
13080
13777
|
console.log(import_chalk.default.yellow(" \u26A0\uFE0F Claude Desktop is not supported on this platform."));
|
|
13081
13778
|
return;
|
|
13082
13779
|
}
|
|
13083
|
-
const config =
|
|
13780
|
+
const config = readJson2(configPath) ?? {};
|
|
13084
13781
|
const servers = config.mcpServers ?? {};
|
|
13085
13782
|
let anythingChanged = false;
|
|
13086
13783
|
const repairedMcpWraps = repairLegacyMcpWraps(
|
|
@@ -13161,7 +13858,7 @@ function teardownClaudeDesktop() {
|
|
|
13161
13858
|
console.log(import_chalk.default.yellow(" \u26A0\uFE0F Claude Desktop is not supported on this platform."));
|
|
13162
13859
|
return;
|
|
13163
13860
|
}
|
|
13164
|
-
const config =
|
|
13861
|
+
const config = readJson2(configPath);
|
|
13165
13862
|
if (!config?.mcpServers) {
|
|
13166
13863
|
console.log(import_chalk.default.blue(" \u2139\uFE0F Claude Desktop config not found \u2014 nothing to remove"));
|
|
13167
13864
|
return;
|
|
@@ -13200,7 +13897,7 @@ function node9ArgvForShim() {
|
|
|
13200
13897
|
function node9Version() {
|
|
13201
13898
|
try {
|
|
13202
13899
|
const pkg = JSON.parse(
|
|
13203
|
-
|
|
13900
|
+
import_fs21.default.readFileSync(import_path21.default.join(__dirname, "..", "package.json"), "utf-8")
|
|
13204
13901
|
);
|
|
13205
13902
|
return pkg.version ?? "0.0.0";
|
|
13206
13903
|
} catch {
|
|
@@ -13209,13 +13906,13 @@ function node9Version() {
|
|
|
13209
13906
|
}
|
|
13210
13907
|
async function setupOpencode() {
|
|
13211
13908
|
seedMcpPinsIfMissing();
|
|
13212
|
-
const homeDir2 =
|
|
13909
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13213
13910
|
const configDir = opencodeConfigDir(homeDir2);
|
|
13214
|
-
const pluginsDir =
|
|
13215
|
-
const configPath =
|
|
13216
|
-
const pluginPath =
|
|
13911
|
+
const pluginsDir = import_path21.default.join(configDir, "plugins");
|
|
13912
|
+
const configPath = import_path21.default.join(configDir, "opencode.json");
|
|
13913
|
+
const pluginPath = import_path21.default.join(pluginsDir, OPENCODE_PLUGIN_NAME);
|
|
13217
13914
|
try {
|
|
13218
|
-
|
|
13915
|
+
import_fs21.default.mkdirSync(pluginsDir, { recursive: true });
|
|
13219
13916
|
} catch (err2) {
|
|
13220
13917
|
const code = err2.code;
|
|
13221
13918
|
if (code !== "EEXIST") {
|
|
@@ -13230,13 +13927,13 @@ async function setupOpencode() {
|
|
|
13230
13927
|
let pluginChanged = false;
|
|
13231
13928
|
const existingShim = (() => {
|
|
13232
13929
|
try {
|
|
13233
|
-
return
|
|
13930
|
+
return import_fs21.default.readFileSync(pluginPath, "utf-8");
|
|
13234
13931
|
} catch {
|
|
13235
13932
|
return null;
|
|
13236
13933
|
}
|
|
13237
13934
|
})();
|
|
13238
13935
|
if (existingShim !== shimContent) {
|
|
13239
|
-
|
|
13936
|
+
import_fs21.default.writeFileSync(pluginPath, shimContent);
|
|
13240
13937
|
pluginChanged = true;
|
|
13241
13938
|
if (existingShim) {
|
|
13242
13939
|
console.log(import_chalk.default.yellow(" \u{1F527} Opencode plugin shim updated to current version"));
|
|
@@ -13246,7 +13943,7 @@ async function setupOpencode() {
|
|
|
13246
13943
|
);
|
|
13247
13944
|
}
|
|
13248
13945
|
}
|
|
13249
|
-
const config =
|
|
13946
|
+
const config = readJson2(configPath) ?? {};
|
|
13250
13947
|
const mcp = config.mcp ?? {};
|
|
13251
13948
|
let configChanged = false;
|
|
13252
13949
|
const desiredCommand = [...node9ArgvForShim(), "mcp-server"];
|
|
@@ -13277,20 +13974,20 @@ async function setupOpencode() {
|
|
|
13277
13974
|
}
|
|
13278
13975
|
}
|
|
13279
13976
|
function teardownOpencode() {
|
|
13280
|
-
const homeDir2 =
|
|
13977
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13281
13978
|
const configDir = opencodeConfigDir(homeDir2);
|
|
13282
|
-
const pluginsDir =
|
|
13283
|
-
const configPath =
|
|
13284
|
-
const pluginPath =
|
|
13979
|
+
const pluginsDir = import_path21.default.join(configDir, "plugins");
|
|
13980
|
+
const configPath = import_path21.default.join(configDir, "opencode.json");
|
|
13981
|
+
const pluginPath = import_path21.default.join(pluginsDir, OPENCODE_PLUGIN_NAME);
|
|
13285
13982
|
try {
|
|
13286
|
-
if (
|
|
13287
|
-
|
|
13983
|
+
if (import_fs21.default.existsSync(pluginPath)) {
|
|
13984
|
+
import_fs21.default.unlinkSync(pluginPath);
|
|
13288
13985
|
console.log(import_chalk.default.green(" \u2705 Removed node9 plugin from ~/.config/opencode/plugins/"));
|
|
13289
13986
|
}
|
|
13290
13987
|
} catch (err2) {
|
|
13291
13988
|
console.log(import_chalk.default.yellow(` \u26A0\uFE0F Could not remove ${pluginPath}: ${String(err2)}`));
|
|
13292
13989
|
}
|
|
13293
|
-
const config =
|
|
13990
|
+
const config = readJson2(configPath);
|
|
13294
13991
|
if (!config) {
|
|
13295
13992
|
console.log(import_chalk.default.blue(" \u2139\uFE0F ~/.config/opencode/opencode.json not found \u2014 nothing to remove"));
|
|
13296
13993
|
return;
|
|
@@ -13313,11 +14010,11 @@ function teardownOpencode() {
|
|
|
13313
14010
|
}
|
|
13314
14011
|
async function setupPi() {
|
|
13315
14012
|
seedMcpPinsIfMissing();
|
|
13316
|
-
const homeDir2 =
|
|
13317
|
-
const extensionsDir =
|
|
13318
|
-
const extensionPath =
|
|
14013
|
+
const homeDir2 = import_os18.default.homedir();
|
|
14014
|
+
const extensionsDir = import_path21.default.join(homeDir2, ".pi", "agent", "extensions");
|
|
14015
|
+
const extensionPath = import_path21.default.join(extensionsDir, PI_EXTENSION_NAME);
|
|
13319
14016
|
try {
|
|
13320
|
-
|
|
14017
|
+
import_fs21.default.mkdirSync(extensionsDir, { recursive: true });
|
|
13321
14018
|
} catch (err2) {
|
|
13322
14019
|
const code = err2.code;
|
|
13323
14020
|
console.log(import_chalk.default.yellow(` \u26A0\uFE0F Could not create ${extensionsDir}: ${code ?? String(err2)}`));
|
|
@@ -13329,7 +14026,7 @@ async function setupPi() {
|
|
|
13329
14026
|
});
|
|
13330
14027
|
const existingShim = (() => {
|
|
13331
14028
|
try {
|
|
13332
|
-
return
|
|
14029
|
+
return import_fs21.default.readFileSync(extensionPath, "utf-8");
|
|
13333
14030
|
} catch {
|
|
13334
14031
|
return null;
|
|
13335
14032
|
}
|
|
@@ -13338,7 +14035,7 @@ async function setupPi() {
|
|
|
13338
14035
|
console.log(import_chalk.default.blue(" \u2139\uFE0F Node9 is already fully configured for Pi."));
|
|
13339
14036
|
return;
|
|
13340
14037
|
}
|
|
13341
|
-
|
|
14038
|
+
import_fs21.default.writeFileSync(extensionPath, shimContent);
|
|
13342
14039
|
if (existingShim) {
|
|
13343
14040
|
console.log(import_chalk.default.yellow(" \u{1F527} Pi extension shim updated to current version"));
|
|
13344
14041
|
} else {
|
|
@@ -13351,11 +14048,11 @@ async function setupPi() {
|
|
|
13351
14048
|
printDaemonTip();
|
|
13352
14049
|
}
|
|
13353
14050
|
function teardownPi() {
|
|
13354
|
-
const homeDir2 =
|
|
13355
|
-
const extensionPath =
|
|
14051
|
+
const homeDir2 = import_os18.default.homedir();
|
|
14052
|
+
const extensionPath = import_path21.default.join(homeDir2, ".pi", "agent", "extensions", PI_EXTENSION_NAME);
|
|
13356
14053
|
try {
|
|
13357
|
-
if (
|
|
13358
|
-
|
|
14054
|
+
if (import_fs21.default.existsSync(extensionPath)) {
|
|
14055
|
+
import_fs21.default.unlinkSync(extensionPath);
|
|
13359
14056
|
console.log(import_chalk.default.green(" \u2705 Removed node9 extension from ~/.pi/agent/extensions/"));
|
|
13360
14057
|
} else {
|
|
13361
14058
|
console.log(import_chalk.default.blue(" \u2139\uFE0F No Pi extension installed \u2014 nothing to remove"));
|
|
@@ -13364,29 +14061,29 @@ function teardownPi() {
|
|
|
13364
14061
|
console.log(import_chalk.default.yellow(` \u26A0\uFE0F Could not remove ${extensionPath}: ${String(err2)}`));
|
|
13365
14062
|
}
|
|
13366
14063
|
}
|
|
13367
|
-
function hermesHomeDir(homeDir2 =
|
|
14064
|
+
function hermesHomeDir(homeDir2 = import_os18.default.homedir()) {
|
|
13368
14065
|
const env = process.env.HERMES_HOME?.trim();
|
|
13369
|
-
if (env &&
|
|
13370
|
-
return
|
|
14066
|
+
if (env && import_path21.default.isAbsolute(env)) return env;
|
|
14067
|
+
return import_path21.default.join(homeDir2, ".hermes");
|
|
13371
14068
|
}
|
|
13372
|
-
function hermesConfigPath(homeDir2 =
|
|
13373
|
-
return
|
|
14069
|
+
function hermesConfigPath(homeDir2 = import_os18.default.homedir()) {
|
|
14070
|
+
return import_path21.default.join(hermesHomeDir(homeDir2), HERMES_CONFIG_FILENAME);
|
|
13374
14071
|
}
|
|
13375
|
-
function hermesAllowlistPath(homeDir2 =
|
|
13376
|
-
return
|
|
14072
|
+
function hermesAllowlistPath(homeDir2 = import_os18.default.homedir()) {
|
|
14073
|
+
return import_path21.default.join(hermesHomeDir(homeDir2), HERMES_ALLOWLIST_FILENAME);
|
|
13377
14074
|
}
|
|
13378
14075
|
function setupHermes() {
|
|
13379
|
-
const homeDir2 =
|
|
14076
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13380
14077
|
const configPath = hermesConfigPath(homeDir2);
|
|
13381
14078
|
const allowlistPath = hermesAllowlistPath(homeDir2);
|
|
13382
|
-
if (!
|
|
14079
|
+
if (!import_fs21.default.existsSync(configPath)) {
|
|
13383
14080
|
console.log(import_chalk.default.yellow(` \u26A0\uFE0F Hermes config not found at ${configPath}`));
|
|
13384
14081
|
console.log(import_chalk.default.gray(" Run `hermes setup` first, then re-run node9 agents add hermes."));
|
|
13385
14082
|
return;
|
|
13386
14083
|
}
|
|
13387
14084
|
let anythingChanged = false;
|
|
13388
|
-
const raw =
|
|
13389
|
-
const doc =
|
|
14085
|
+
const raw = import_fs21.default.readFileSync(configPath, "utf-8");
|
|
14086
|
+
const doc = yaml2.parseDocument(raw);
|
|
13390
14087
|
if (doc.errors.length > 0) {
|
|
13391
14088
|
console.log(import_chalk.default.yellow(` \u26A0\uFE0F Hermes config.yaml has YAML parse errors:`));
|
|
13392
14089
|
for (const err2 of doc.errors.slice(0, 3)) {
|
|
@@ -13428,9 +14125,9 @@ function setupHermes() {
|
|
|
13428
14125
|
atomicWriteSync(configPath, doc.toString());
|
|
13429
14126
|
}
|
|
13430
14127
|
let allowlist = {};
|
|
13431
|
-
if (
|
|
14128
|
+
if (import_fs21.default.existsSync(allowlistPath)) {
|
|
13432
14129
|
try {
|
|
13433
|
-
allowlist = JSON.parse(
|
|
14130
|
+
allowlist = JSON.parse(import_fs21.default.readFileSync(allowlistPath, "utf-8"));
|
|
13434
14131
|
} catch {
|
|
13435
14132
|
allowlist = {};
|
|
13436
14133
|
}
|
|
@@ -13466,15 +14163,15 @@ function setupHermes() {
|
|
|
13466
14163
|
}
|
|
13467
14164
|
}
|
|
13468
14165
|
function teardownHermes() {
|
|
13469
|
-
const homeDir2 =
|
|
14166
|
+
const homeDir2 = import_os18.default.homedir();
|
|
13470
14167
|
const configPath = hermesConfigPath(homeDir2);
|
|
13471
14168
|
const allowlistPath = hermesAllowlistPath(homeDir2);
|
|
13472
|
-
if (!
|
|
14169
|
+
if (!import_fs21.default.existsSync(configPath)) {
|
|
13473
14170
|
console.log(import_chalk.default.blue(` \u2139\uFE0F ${configPath} not found \u2014 nothing to remove`));
|
|
13474
14171
|
return;
|
|
13475
14172
|
}
|
|
13476
|
-
const raw =
|
|
13477
|
-
const doc =
|
|
14173
|
+
const raw = import_fs21.default.readFileSync(configPath, "utf-8");
|
|
14174
|
+
const doc = yaml2.parseDocument(raw);
|
|
13478
14175
|
if (doc.errors.length > 0) {
|
|
13479
14176
|
console.log(
|
|
13480
14177
|
import_chalk.default.yellow(` \u26A0\uFE0F Skipping ${configPath} \u2014 file has YAML parse errors, fix it manually.`)
|
|
@@ -13506,16 +14203,16 @@ function teardownHermesConfigDoc(doc, configPath) {
|
|
|
13506
14203
|
anythingChanged = true;
|
|
13507
14204
|
}
|
|
13508
14205
|
if (anythingChanged) {
|
|
13509
|
-
|
|
14206
|
+
import_fs21.default.writeFileSync(configPath, doc.toString());
|
|
13510
14207
|
console.log(import_chalk.default.green(` \u2705 Removed Node9 hooks from ${configPath}`));
|
|
13511
14208
|
} else {
|
|
13512
14209
|
console.log(import_chalk.default.blue(` \u2139\uFE0F No Node9 hooks found in ${configPath}`));
|
|
13513
14210
|
}
|
|
13514
14211
|
}
|
|
13515
14212
|
function teardownHermesAllowlist(allowlistPath) {
|
|
13516
|
-
if (!
|
|
14213
|
+
if (!import_fs21.default.existsSync(allowlistPath)) return;
|
|
13517
14214
|
try {
|
|
13518
|
-
const raw =
|
|
14215
|
+
const raw = import_fs21.default.readFileSync(allowlistPath, "utf-8");
|
|
13519
14216
|
const allowlist = JSON.parse(raw);
|
|
13520
14217
|
if (!Array.isArray(allowlist.approvals)) return;
|
|
13521
14218
|
const before = allowlist.approvals.length;
|
|
@@ -13528,44 +14225,44 @@ function teardownHermesAllowlist(allowlistPath) {
|
|
|
13528
14225
|
} catch {
|
|
13529
14226
|
}
|
|
13530
14227
|
}
|
|
13531
|
-
function getAgentsStatus(homeDir2 =
|
|
14228
|
+
function getAgentsStatus(homeDir2 = import_os18.default.homedir()) {
|
|
13532
14229
|
const detected = detectAgents(homeDir2);
|
|
13533
14230
|
const claudeWired = (() => {
|
|
13534
|
-
const settings =
|
|
14231
|
+
const settings = readJson2(import_path21.default.join(homeDir2, ".claude", "settings.json"));
|
|
13535
14232
|
return !!settings?.hooks?.PreToolUse?.some((m) => m.hooks.some((h) => isNode9Hook(h.command)));
|
|
13536
14233
|
})();
|
|
13537
14234
|
const geminiWired = (() => {
|
|
13538
|
-
const settings =
|
|
14235
|
+
const settings = readJson2(import_path21.default.join(homeDir2, ".gemini", "settings.json"));
|
|
13539
14236
|
return !!settings?.hooks?.BeforeTool?.some((m) => m.hooks.some((h) => isNode9Hook(h.command)));
|
|
13540
14237
|
})();
|
|
13541
14238
|
const antigravityWired = (() => {
|
|
13542
|
-
const hooksFile =
|
|
13543
|
-
|
|
14239
|
+
const hooksFile = readJson2(
|
|
14240
|
+
import_path21.default.join(homeDir2, ".gemini", "config", "hooks.json")
|
|
13544
14241
|
);
|
|
13545
14242
|
return !!hooksFile?.hooks?.PreToolUse?.some((m) => m.hooks.some((h) => isNode9Hook(h.command)));
|
|
13546
14243
|
})();
|
|
13547
14244
|
const copilotWired = (() => {
|
|
13548
|
-
const hooksFile =
|
|
13549
|
-
|
|
14245
|
+
const hooksFile = readJson2(
|
|
14246
|
+
import_path21.default.join(homeDir2, ".copilot", "hooks", "node9.json")
|
|
13550
14247
|
);
|
|
13551
14248
|
return !!hooksFile?.hooks?.PreToolUse?.some((h) => isNode9Hook(h.command));
|
|
13552
14249
|
})();
|
|
13553
14250
|
const cursorWired = (() => {
|
|
13554
|
-
const cfg =
|
|
14251
|
+
const cfg = readJson2(import_path21.default.join(homeDir2, ".cursor", "mcp.json"));
|
|
13555
14252
|
return !!(cfg?.mcpServers && hasNode9McpServer(cfg.mcpServers));
|
|
13556
14253
|
})();
|
|
13557
14254
|
const codexWired = (() => {
|
|
13558
|
-
const cfg = readToml(
|
|
14255
|
+
const cfg = readToml(import_path21.default.join(homeDir2, ".codex", "config.toml"));
|
|
13559
14256
|
return !!(cfg?.mcp_servers && hasNode9McpServer(cfg.mcp_servers));
|
|
13560
14257
|
})();
|
|
13561
14258
|
const windsurfWired = (() => {
|
|
13562
|
-
const cfg =
|
|
13563
|
-
|
|
14259
|
+
const cfg = readJson2(
|
|
14260
|
+
import_path21.default.join(homeDir2, ".codeium", "windsurf", "mcp_config.json")
|
|
13564
14261
|
);
|
|
13565
14262
|
return !!(cfg?.mcpServers && hasNode9McpServer(cfg.mcpServers));
|
|
13566
14263
|
})();
|
|
13567
14264
|
const vscodeWired = (() => {
|
|
13568
|
-
const cfg =
|
|
14265
|
+
const cfg = readJson2(import_path21.default.join(homeDir2, ".vscode", "mcp.json"));
|
|
13569
14266
|
return !!(cfg?.servers && hasNode9McpServerVSCode(cfg.servers));
|
|
13570
14267
|
})();
|
|
13571
14268
|
return [
|
|
@@ -13632,7 +14329,7 @@ function getAgentsStatus(homeDir2 = import_os16.default.homedir()) {
|
|
|
13632
14329
|
wired: (() => {
|
|
13633
14330
|
const cfgPath = claudeDesktopConfigPath(homeDir2);
|
|
13634
14331
|
if (!cfgPath) return false;
|
|
13635
|
-
const cfg =
|
|
14332
|
+
const cfg = readJson2(cfgPath);
|
|
13636
14333
|
return !!(cfg?.mcpServers && hasNode9McpServer(cfg.mcpServers));
|
|
13637
14334
|
})(),
|
|
13638
14335
|
mode: detected.claudeDesktop ? "mcp" : null
|
|
@@ -13642,16 +14339,16 @@ function getAgentsStatus(homeDir2 = import_os16.default.homedir()) {
|
|
|
13642
14339
|
label: "Opencode",
|
|
13643
14340
|
installed: detected.opencode,
|
|
13644
14341
|
wired: (() => {
|
|
13645
|
-
const pluginPath =
|
|
14342
|
+
const pluginPath = import_path21.default.join(
|
|
13646
14343
|
homeDir2,
|
|
13647
14344
|
".config",
|
|
13648
14345
|
"opencode",
|
|
13649
14346
|
"plugins",
|
|
13650
14347
|
OPENCODE_PLUGIN_NAME
|
|
13651
14348
|
);
|
|
13652
|
-
if (
|
|
13653
|
-
const cfg =
|
|
13654
|
-
|
|
14349
|
+
if (import_fs21.default.existsSync(pluginPath)) return true;
|
|
14350
|
+
const cfg = readJson2(
|
|
14351
|
+
import_path21.default.join(homeDir2, ".config", "opencode", "opencode.json")
|
|
13655
14352
|
);
|
|
13656
14353
|
return !!cfg?.mcp?.["node9"];
|
|
13657
14354
|
})(),
|
|
@@ -13663,7 +14360,7 @@ function getAgentsStatus(homeDir2 = import_os16.default.homedir()) {
|
|
|
13663
14360
|
installed: detected.pi,
|
|
13664
14361
|
// Pi has no MCP path — only the extension file. "wired" is a
|
|
13665
14362
|
// simple existence check on the canonical install location.
|
|
13666
|
-
wired:
|
|
14363
|
+
wired: import_fs21.default.existsSync(import_path21.default.join(homeDir2, ".pi", "agent", "extensions", PI_EXTENSION_NAME)),
|
|
13667
14364
|
mode: detected.pi ? "hooks" : null
|
|
13668
14365
|
},
|
|
13669
14366
|
{
|
|
@@ -13675,8 +14372,8 @@ function getAgentsStatus(homeDir2 = import_os16.default.homedir()) {
|
|
|
13675
14372
|
// Document API for a boolean status check.
|
|
13676
14373
|
wired: (() => {
|
|
13677
14374
|
try {
|
|
13678
|
-
const raw =
|
|
13679
|
-
const cfg =
|
|
14375
|
+
const raw = import_fs21.default.readFileSync(hermesConfigPath(homeDir2), "utf-8");
|
|
14376
|
+
const cfg = yaml2.parse(raw);
|
|
13680
14377
|
const pre = cfg?.hooks?.["pre_tool_call"] ?? [];
|
|
13681
14378
|
return pre.some((e) => typeof e?.command === "string" && isNode9Hook(e.command));
|
|
13682
14379
|
} catch {
|
|
@@ -13687,18 +14384,19 @@ function getAgentsStatus(homeDir2 = import_os16.default.homedir()) {
|
|
|
13687
14384
|
}
|
|
13688
14385
|
];
|
|
13689
14386
|
}
|
|
13690
|
-
var
|
|
14387
|
+
var import_fs21, import_path21, import_os18, import_chalk, import_prompts, import_smol_toml4, yaml2, NODE9_MCP_SERVER_ENTRY, MCP_WRAP_SUBCOMMAND, LEGACY_MCP_WRAP_SUBCOMMAND, CODEX_PRE_TOOL_MATCHERS, OPENCODE_PLUGIN_NAME, PI_EXTENSION_NAME, HERMES_CONFIG_FILENAME, HERMES_ALLOWLIST_FILENAME, HERMES_HOOK_PLAN;
|
|
13691
14388
|
var init_setup = __esm({
|
|
13692
14389
|
"src/setup.ts"() {
|
|
13693
14390
|
"use strict";
|
|
13694
|
-
|
|
13695
|
-
|
|
13696
|
-
|
|
14391
|
+
import_fs21 = __toESM(require("fs"));
|
|
14392
|
+
import_path21 = __toESM(require("path"));
|
|
14393
|
+
import_os18 = __toESM(require("os"));
|
|
13697
14394
|
import_chalk = __toESM(require("chalk"));
|
|
13698
14395
|
import_prompts = require("@inquirer/prompts");
|
|
13699
|
-
|
|
14396
|
+
import_smol_toml4 = require("smol-toml");
|
|
14397
|
+
init_mcp_wrap();
|
|
13700
14398
|
init_codex_trust();
|
|
13701
|
-
|
|
14399
|
+
yaml2 = __toESM(require("yaml"));
|
|
13702
14400
|
init_mcp_pin();
|
|
13703
14401
|
init_hook_baseline();
|
|
13704
14402
|
init_setup_opencode_shim();
|
|
@@ -13719,244 +14417,6 @@ var init_setup = __esm({
|
|
|
13719
14417
|
}
|
|
13720
14418
|
});
|
|
13721
14419
|
|
|
13722
|
-
// src/agent-wiring.ts
|
|
13723
|
-
function readJson2(filePath) {
|
|
13724
|
-
if (!import_fs20.default.existsSync(filePath)) return null;
|
|
13725
|
-
try {
|
|
13726
|
-
return JSON.parse(import_fs20.default.readFileSync(filePath, "utf-8"));
|
|
13727
|
-
} catch {
|
|
13728
|
-
return "invalid";
|
|
13729
|
-
}
|
|
13730
|
-
}
|
|
13731
|
-
function matchersHaveNode9Hook(matchers) {
|
|
13732
|
-
return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
|
|
13733
|
-
}
|
|
13734
|
-
function flatHaveNode9Hook(entries) {
|
|
13735
|
-
return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
|
|
13736
|
-
}
|
|
13737
|
-
function readHookRoot(filePath, format) {
|
|
13738
|
-
if (!import_fs20.default.existsSync(filePath)) return "absent";
|
|
13739
|
-
let raw;
|
|
13740
|
-
try {
|
|
13741
|
-
raw = import_fs20.default.readFileSync(filePath, "utf-8");
|
|
13742
|
-
} catch {
|
|
13743
|
-
return "absent";
|
|
13744
|
-
}
|
|
13745
|
-
try {
|
|
13746
|
-
const parsed = format === "yaml" ? yaml2.parse(raw) : JSON.parse(raw);
|
|
13747
|
-
return parsed?.hooks ?? {};
|
|
13748
|
-
} catch {
|
|
13749
|
-
return "invalid";
|
|
13750
|
-
}
|
|
13751
|
-
}
|
|
13752
|
-
function eventWired(root, ev, format) {
|
|
13753
|
-
const arr = root[ev.key];
|
|
13754
|
-
if (format === "matcher") return matchersHaveNode9Hook(arr);
|
|
13755
|
-
return flatHaveNode9Hook(arr);
|
|
13756
|
-
}
|
|
13757
|
-
function detectMcp(servers) {
|
|
13758
|
-
const entries = Object.entries(servers ?? {});
|
|
13759
|
-
const present = entries.some(([, s]) => s?.command === "node9");
|
|
13760
|
-
const wrapped = entries.filter(([, s]) => s?.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
|
|
13761
|
-
return { wrapped, present };
|
|
13762
|
-
}
|
|
13763
|
-
function readMcpServers(filePath, format) {
|
|
13764
|
-
if (!import_fs20.default.existsSync(filePath)) return {};
|
|
13765
|
-
try {
|
|
13766
|
-
if (format === "toml") {
|
|
13767
|
-
const parsed2 = (0, import_smol_toml3.parse)(import_fs20.default.readFileSync(filePath, "utf-8"));
|
|
13768
|
-
return parsed2?.mcp_servers ?? {};
|
|
13769
|
-
}
|
|
13770
|
-
const parsed = readJson2(filePath);
|
|
13771
|
-
if (parsed === null || parsed === "invalid") return {};
|
|
13772
|
-
return parsed.mcpServers ?? {};
|
|
13773
|
-
} catch {
|
|
13774
|
-
return {};
|
|
13775
|
-
}
|
|
13776
|
-
}
|
|
13777
|
-
function readMcp(filePath, format) {
|
|
13778
|
-
if (!import_fs20.default.existsSync(filePath)) return { wrapped: [], present: false };
|
|
13779
|
-
try {
|
|
13780
|
-
if (format === "toml") {
|
|
13781
|
-
const parsed2 = (0, import_smol_toml3.parse)(import_fs20.default.readFileSync(filePath, "utf-8"));
|
|
13782
|
-
return detectMcp(parsed2?.mcp_servers);
|
|
13783
|
-
}
|
|
13784
|
-
const parsed = readJson2(filePath);
|
|
13785
|
-
if (parsed === null || parsed === "invalid") return { wrapped: [], present: false };
|
|
13786
|
-
return detectMcp(parsed.mcpServers);
|
|
13787
|
-
} catch {
|
|
13788
|
-
return { wrapped: [], present: false };
|
|
13789
|
-
}
|
|
13790
|
-
}
|
|
13791
|
-
function getAgentWiring(home = import_os17.default.homedir()) {
|
|
13792
|
-
const detected = detectAgents(home);
|
|
13793
|
-
return AGENT_SPECS.map((spec) => {
|
|
13794
|
-
const present = spec.present(home);
|
|
13795
|
-
const pad = spec.labelPad ?? DEFAULT_LABEL_PAD;
|
|
13796
|
-
let hooks;
|
|
13797
|
-
let wireState;
|
|
13798
|
-
let hookLabel;
|
|
13799
|
-
let settingsPath;
|
|
13800
|
-
if (spec.shimFile) {
|
|
13801
|
-
const shimWired = exists(spec.shimFile(home));
|
|
13802
|
-
hooks = [{ label: "node9 plugin (node9 check)", wired: shimWired }];
|
|
13803
|
-
wireState = shimWired ? "wired" : present ? "unwired" : "absent";
|
|
13804
|
-
hookLabel = "node9 plugin";
|
|
13805
|
-
settingsPath = spec.shimFile(home);
|
|
13806
|
-
} else {
|
|
13807
|
-
const root = spec.hookFile ? readHookRoot(spec.hookFile(home), spec.hookFormat) : "absent";
|
|
13808
|
-
const primary = spec.hookEvents[0];
|
|
13809
|
-
const rootPresent = root !== "absent" && root !== "invalid";
|
|
13810
|
-
hooks = spec.hookEvents.map((ev) => ({
|
|
13811
|
-
label: hookLabelOf(ev, pad),
|
|
13812
|
-
wired: rootPresent && eventWired(root, ev, spec.hookFormat)
|
|
13813
|
-
}));
|
|
13814
|
-
if (root === "absent") wireState = "absent";
|
|
13815
|
-
else if (root === "invalid") wireState = "invalid";
|
|
13816
|
-
else wireState = primary && eventWired(root, primary, spec.hookFormat) ? "wired" : "unwired";
|
|
13817
|
-
hookLabel = primary ? `${primary.key} hook` : "MCP proxy";
|
|
13818
|
-
settingsPath = spec.hookFile ? spec.hookFile(home) : spec.mcpFile ? spec.mcpFile(home) : "";
|
|
13819
|
-
}
|
|
13820
|
-
const mcp = spec.mcpFile ? readMcp(spec.mcpFile(home), spec.mcpFormat ?? "json") : null;
|
|
13821
|
-
const anyHookWired = hooks.some((h) => h.wired);
|
|
13822
|
-
return {
|
|
13823
|
-
id: spec.id,
|
|
13824
|
-
label: spec.label,
|
|
13825
|
-
setupCommand: spec.setupCommand,
|
|
13826
|
-
installed: detected[spec.id],
|
|
13827
|
-
present,
|
|
13828
|
-
hooks,
|
|
13829
|
-
wireState,
|
|
13830
|
-
hookLabel,
|
|
13831
|
-
settingsPath,
|
|
13832
|
-
configFormat: spec.hookFormat === "yaml" ? "YAML" : "JSON",
|
|
13833
|
-
mcpServers: mcp ? mcp.wrapped : null,
|
|
13834
|
-
mcpProtected: mcp ? mcp.present : false,
|
|
13835
|
-
isProtected: anyHookWired || (mcp?.present ?? false)
|
|
13836
|
-
};
|
|
13837
|
-
});
|
|
13838
|
-
}
|
|
13839
|
-
var import_fs20, import_path21, import_os17, yaml2, import_smol_toml3, exists, ck, lg, DEFAULT_LABEL_PAD, hookLabelOf, AGENT_SPECS;
|
|
13840
|
-
var init_agent_wiring = __esm({
|
|
13841
|
-
"src/agent-wiring.ts"() {
|
|
13842
|
-
"use strict";
|
|
13843
|
-
import_fs20 = __toESM(require("fs"));
|
|
13844
|
-
import_path21 = __toESM(require("path"));
|
|
13845
|
-
import_os17 = __toESM(require("os"));
|
|
13846
|
-
yaml2 = __toESM(require("yaml"));
|
|
13847
|
-
import_smol_toml3 = require("smol-toml");
|
|
13848
|
-
init_setup();
|
|
13849
|
-
exists = (p) => {
|
|
13850
|
-
try {
|
|
13851
|
-
return import_fs20.default.existsSync(p);
|
|
13852
|
-
} catch {
|
|
13853
|
-
return false;
|
|
13854
|
-
}
|
|
13855
|
-
};
|
|
13856
|
-
ck = (key) => ({ key, kind: "check" });
|
|
13857
|
-
lg = (key) => ({ key, kind: "log" });
|
|
13858
|
-
DEFAULT_LABEL_PAD = 11;
|
|
13859
|
-
hookLabelOf = (ev, pad) => `${ev.key.padEnd(pad)} (node9 ${ev.kind})`;
|
|
13860
|
-
AGENT_SPECS = [
|
|
13861
|
-
{
|
|
13862
|
-
id: "claude",
|
|
13863
|
-
label: "Claude Code",
|
|
13864
|
-
setupCommand: "node9 agents add claude",
|
|
13865
|
-
hookFile: (h) => import_path21.default.join(h, ".claude", "settings.json"),
|
|
13866
|
-
hookFormat: "matcher",
|
|
13867
|
-
// UserPromptSubmit is prompt DLP. setup.ts has written it for Claude since
|
|
13868
|
-
// that shipped; the spec must name it too, or status/doctor never show the
|
|
13869
|
-
// row and heal (which repairs via setupAgent) has no signal it is missing.
|
|
13870
|
-
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
13871
|
-
mcpFile: (h) => import_path21.default.join(h, ".claude.json"),
|
|
13872
|
-
present: (h) => exists(import_path21.default.join(h, ".claude", "settings.json")) || exists(import_path21.default.join(h, ".claude.json"))
|
|
13873
|
-
},
|
|
13874
|
-
{
|
|
13875
|
-
id: "gemini",
|
|
13876
|
-
label: "Gemini CLI",
|
|
13877
|
-
setupCommand: "node9 agents add gemini",
|
|
13878
|
-
hookFile: (h) => import_path21.default.join(h, ".gemini", "settings.json"),
|
|
13879
|
-
hookFormat: "matcher",
|
|
13880
|
-
hookEvents: [ck("BeforeTool"), lg("AfterTool")],
|
|
13881
|
-
mcpFile: (h) => import_path21.default.join(h, ".gemini", "settings.json"),
|
|
13882
|
-
present: (h) => exists(import_path21.default.join(h, ".gemini", "settings.json"))
|
|
13883
|
-
},
|
|
13884
|
-
{
|
|
13885
|
-
id: "codex",
|
|
13886
|
-
label: "Codex",
|
|
13887
|
-
setupCommand: "node9 agents add codex",
|
|
13888
|
-
hookFile: (h) => import_path21.default.join(h, ".codex", "hooks.json"),
|
|
13889
|
-
hookFormat: "matcher",
|
|
13890
|
-
hookEvents: [ck("PreToolUse"), ck("UserPromptSubmit")],
|
|
13891
|
-
mcpFile: (h) => import_path21.default.join(h, ".codex", "config.toml"),
|
|
13892
|
-
mcpFormat: "toml",
|
|
13893
|
-
present: (h) => exists(import_path21.default.join(h, ".codex"))
|
|
13894
|
-
},
|
|
13895
|
-
{
|
|
13896
|
-
id: "antigravity",
|
|
13897
|
-
label: "Antigravity",
|
|
13898
|
-
setupCommand: "node9 agents add antigravity",
|
|
13899
|
-
hookFile: (h) => import_path21.default.join(h, ".gemini", "config", "hooks.json"),
|
|
13900
|
-
hookFormat: "matcher",
|
|
13901
|
-
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
13902
|
-
mcpFile: (h) => import_path21.default.join(h, ".gemini", "config", "mcp_config.json"),
|
|
13903
|
-
present: (h) => exists(import_path21.default.join(h, ".gemini", "config", "hooks.json")) || exists(import_path21.default.join(h, ".gemini", "antigravity-cli")) || exists(import_path21.default.join(h, ".gemini", "antigravity-ide"))
|
|
13904
|
-
},
|
|
13905
|
-
{
|
|
13906
|
-
id: "copilot",
|
|
13907
|
-
label: "GitHub Copilot",
|
|
13908
|
-
setupCommand: "node9 agents add copilot",
|
|
13909
|
-
hookFile: (h) => import_path21.default.join(h, ".copilot", "hooks", "node9.json"),
|
|
13910
|
-
hookFormat: "flat",
|
|
13911
|
-
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
13912
|
-
mcpFile: (h) => import_path21.default.join(h, ".copilot", "mcp-config.json"),
|
|
13913
|
-
present: (h) => exists(import_path21.default.join(h, ".copilot"))
|
|
13914
|
-
},
|
|
13915
|
-
{
|
|
13916
|
-
id: "cursor",
|
|
13917
|
-
label: "Cursor",
|
|
13918
|
-
setupCommand: "node9 agents add cursor",
|
|
13919
|
-
// MCP-only — no hook file (see note above).
|
|
13920
|
-
hookFormat: "flat",
|
|
13921
|
-
hookEvents: [],
|
|
13922
|
-
mcpFile: (h) => import_path21.default.join(h, ".cursor", "mcp.json"),
|
|
13923
|
-
present: (h) => exists(import_path21.default.join(h, ".cursor", "mcp.json"))
|
|
13924
|
-
},
|
|
13925
|
-
{
|
|
13926
|
-
id: "hermes",
|
|
13927
|
-
label: "Hermes Agent",
|
|
13928
|
-
setupCommand: "node9 agents add hermes",
|
|
13929
|
-
hookFile: (h) => hermesConfigPath(h),
|
|
13930
|
-
hookFormat: "yaml",
|
|
13931
|
-
hookEvents: [ck("pre_tool_call"), lg("post_tool_call")],
|
|
13932
|
-
labelPad: 14,
|
|
13933
|
-
// 'post_tool_call' is wider than the default
|
|
13934
|
-
present: (h) => exists(hermesConfigPath(h))
|
|
13935
|
-
},
|
|
13936
|
-
{
|
|
13937
|
-
// Plugin-shim agents — protected by a node9-authored plugin/extension file
|
|
13938
|
-
// (no hooks, no MCP). hookFormat is unused for these (shimFile drives it).
|
|
13939
|
-
id: "opencode",
|
|
13940
|
-
label: "OpenCode",
|
|
13941
|
-
setupCommand: "node9 agents add opencode",
|
|
13942
|
-
hookFormat: "flat",
|
|
13943
|
-
hookEvents: [],
|
|
13944
|
-
shimFile: (h) => import_path21.default.join(opencodeConfigDir(h), "plugins", "node9.js"),
|
|
13945
|
-
present: (h) => exists(opencodeConfigDir(h)) || exists(import_path21.default.join(opencodeConfigDir(h), "plugins", "node9.js"))
|
|
13946
|
-
},
|
|
13947
|
-
{
|
|
13948
|
-
id: "pi",
|
|
13949
|
-
label: "Pi",
|
|
13950
|
-
setupCommand: "node9 agents add pi",
|
|
13951
|
-
hookFormat: "flat",
|
|
13952
|
-
hookEvents: [],
|
|
13953
|
-
shimFile: (h) => import_path21.default.join(h, ".pi", "agent", "extensions", "node9.js"),
|
|
13954
|
-
present: (h) => exists(import_path21.default.join(h, ".pi", "agent")) || exists(import_path21.default.join(h, ".pi", "agent", "extensions", "node9.js"))
|
|
13955
|
-
}
|
|
13956
|
-
];
|
|
13957
|
-
}
|
|
13958
|
-
});
|
|
13959
|
-
|
|
13960
14420
|
// src/config/keyed-guard.ts
|
|
13961
14421
|
function isKeyedForPolicy() {
|
|
13962
14422
|
try {
|
|
@@ -13994,7 +14454,7 @@ function normalizeModel(raw) {
|
|
|
13994
14454
|
}
|
|
13995
14455
|
function readCache(opts) {
|
|
13996
14456
|
try {
|
|
13997
|
-
const raw = JSON.parse(
|
|
14457
|
+
const raw = JSON.parse(import_fs22.default.readFileSync(CACHE_FILE(), "utf-8"));
|
|
13998
14458
|
if (typeof raw.fetchedAt !== "string" || typeof raw.prices !== "object" || raw.prices === null) {
|
|
13999
14459
|
return null;
|
|
14000
14460
|
}
|
|
@@ -14010,17 +14470,17 @@ function writeCache(prices) {
|
|
|
14010
14470
|
try {
|
|
14011
14471
|
const target = CACHE_FILE();
|
|
14012
14472
|
const dir = import_path22.default.dirname(target);
|
|
14013
|
-
if (!
|
|
14473
|
+
if (!import_fs22.default.existsSync(dir)) import_fs22.default.mkdirSync(dir, { recursive: true });
|
|
14014
14474
|
const tmp = target + ".tmp";
|
|
14015
14475
|
const body = {
|
|
14016
14476
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14017
14477
|
prices
|
|
14018
14478
|
};
|
|
14019
|
-
|
|
14020
|
-
|
|
14479
|
+
import_fs22.default.writeFileSync(tmp, JSON.stringify(body) + "\n", "utf-8");
|
|
14480
|
+
import_fs22.default.renameSync(tmp, target);
|
|
14021
14481
|
} catch (err2) {
|
|
14022
14482
|
try {
|
|
14023
|
-
|
|
14483
|
+
import_fs22.default.appendFileSync(
|
|
14024
14484
|
HOOK_DEBUG_LOG,
|
|
14025
14485
|
`[pricing] cache write failed: ${err2.message}
|
|
14026
14486
|
`
|
|
@@ -14123,13 +14583,13 @@ function pricingFor(model, options = {}) {
|
|
|
14123
14583
|
lookupCache.set(lookupKey, resolved);
|
|
14124
14584
|
return resolved;
|
|
14125
14585
|
}
|
|
14126
|
-
var
|
|
14586
|
+
var import_fs22, import_path22, import_os19, LITELLM_URL, BUNDLED_PRICING, CACHE_FILE, TTL_MS, memCache, memCacheAt, diskChecked, lookupCache;
|
|
14127
14587
|
var init_litellm = __esm({
|
|
14128
14588
|
"src/pricing/litellm.ts"() {
|
|
14129
14589
|
"use strict";
|
|
14130
|
-
|
|
14590
|
+
import_fs22 = __toESM(require("fs"));
|
|
14131
14591
|
import_path22 = __toESM(require("path"));
|
|
14132
|
-
|
|
14592
|
+
import_os19 = __toESM(require("os"));
|
|
14133
14593
|
init_audit();
|
|
14134
14594
|
LITELLM_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
|
|
14135
14595
|
BUNDLED_PRICING = {
|
|
@@ -14181,7 +14641,7 @@ var init_litellm = __esm({
|
|
|
14181
14641
|
"gemini-2.0-flash": [75e-9, 3e-7, 0, 0],
|
|
14182
14642
|
"gemini-1.5-pro": [125e-8, 5e-6, 0, 0]
|
|
14183
14643
|
};
|
|
14184
|
-
CACHE_FILE = () => import_path22.default.join(
|
|
14644
|
+
CACHE_FILE = () => import_path22.default.join(import_os19.default.homedir(), ".node9", "model-pricing.json");
|
|
14185
14645
|
TTL_MS = 24 * 60 * 60 * 1e3;
|
|
14186
14646
|
memCache = null;
|
|
14187
14647
|
memCacheAt = 0;
|
|
@@ -14192,7 +14652,7 @@ var init_litellm = __esm({
|
|
|
14192
14652
|
|
|
14193
14653
|
// src/cost-gemini.ts
|
|
14194
14654
|
function geminiTmpDir() {
|
|
14195
|
-
return import_path23.default.join(
|
|
14655
|
+
return import_path23.default.join(import_os20.default.homedir(), ".gemini", "tmp");
|
|
14196
14656
|
}
|
|
14197
14657
|
function geminiPriceFor(model) {
|
|
14198
14658
|
let tuple = pricingFor(model);
|
|
@@ -14207,14 +14667,14 @@ function geminiPriceFor(model) {
|
|
|
14207
14667
|
}
|
|
14208
14668
|
function safeReaddir(dir) {
|
|
14209
14669
|
try {
|
|
14210
|
-
return
|
|
14670
|
+
return import_fs23.default.readdirSync(dir);
|
|
14211
14671
|
} catch {
|
|
14212
14672
|
return [];
|
|
14213
14673
|
}
|
|
14214
14674
|
}
|
|
14215
14675
|
function isDir(p) {
|
|
14216
14676
|
try {
|
|
14217
|
-
return
|
|
14677
|
+
return import_fs23.default.statSync(p).isDirectory();
|
|
14218
14678
|
} catch {
|
|
14219
14679
|
return false;
|
|
14220
14680
|
}
|
|
@@ -14283,12 +14743,12 @@ function parseGeminiSession(lines, project) {
|
|
|
14283
14743
|
if (runId) for (const e of byKey.values()) e.runId = runId;
|
|
14284
14744
|
return [...byKey.values()];
|
|
14285
14745
|
}
|
|
14286
|
-
var
|
|
14746
|
+
var import_fs23, import_os20, import_path23, GEMINI_FALLBACK_MODELS, geminiSource;
|
|
14287
14747
|
var init_cost_gemini = __esm({
|
|
14288
14748
|
"src/cost-gemini.ts"() {
|
|
14289
14749
|
"use strict";
|
|
14290
|
-
|
|
14291
|
-
|
|
14750
|
+
import_fs23 = __toESM(require("fs"));
|
|
14751
|
+
import_os20 = __toESM(require("os"));
|
|
14292
14752
|
import_path23 = __toESM(require("path"));
|
|
14293
14753
|
init_litellm();
|
|
14294
14754
|
GEMINI_FALLBACK_MODELS = ["gemini-2.5-flash", "gemini-2.0-flash"];
|
|
@@ -14296,7 +14756,7 @@ var init_cost_gemini = __esm({
|
|
|
14296
14756
|
id: "gemini",
|
|
14297
14757
|
available() {
|
|
14298
14758
|
try {
|
|
14299
|
-
return
|
|
14759
|
+
return import_fs23.default.existsSync(geminiTmpDir());
|
|
14300
14760
|
} catch {
|
|
14301
14761
|
return false;
|
|
14302
14762
|
}
|
|
@@ -14305,13 +14765,13 @@ var init_cost_gemini = __esm({
|
|
|
14305
14765
|
const combined = /* @__PURE__ */ new Map();
|
|
14306
14766
|
for (const { file, project } of listGeminiSessionFiles(geminiTmpDir())) {
|
|
14307
14767
|
try {
|
|
14308
|
-
if (sinceMs !== void 0 &&
|
|
14768
|
+
if (sinceMs !== void 0 && import_fs23.default.statSync(file).mtimeMs < sinceMs) continue;
|
|
14309
14769
|
} catch {
|
|
14310
14770
|
continue;
|
|
14311
14771
|
}
|
|
14312
14772
|
let content;
|
|
14313
14773
|
try {
|
|
14314
|
-
content =
|
|
14774
|
+
content = import_fs23.default.readFileSync(file, "utf8");
|
|
14315
14775
|
} catch {
|
|
14316
14776
|
continue;
|
|
14317
14777
|
}
|
|
@@ -14337,7 +14797,7 @@ var init_cost_gemini = __esm({
|
|
|
14337
14797
|
|
|
14338
14798
|
// src/cost-codex.ts
|
|
14339
14799
|
function codexSessionsDir() {
|
|
14340
|
-
return import_path24.default.join(process.env.CODEX_HOME?.trim() || import_path24.default.join(
|
|
14800
|
+
return import_path24.default.join(process.env.CODEX_HOME?.trim() || import_path24.default.join(import_os21.default.homedir(), ".codex"), "sessions");
|
|
14341
14801
|
}
|
|
14342
14802
|
function codexPriceFor(model) {
|
|
14343
14803
|
return pricingFor(codexModel(model), { exact: true }) ?? CODEX_FALLBACK;
|
|
@@ -14369,14 +14829,14 @@ function codexSessionCost(model, tokens, request2) {
|
|
|
14369
14829
|
function statAndFirstLine(file) {
|
|
14370
14830
|
const CAP = 4 * 1024 * 1024;
|
|
14371
14831
|
const CHUNK = 64 * 1024;
|
|
14372
|
-
const fd =
|
|
14832
|
+
const fd = import_fs24.default.openSync(file, "r");
|
|
14373
14833
|
try {
|
|
14374
|
-
const stat =
|
|
14834
|
+
const stat = import_fs24.default.fstatSync(fd);
|
|
14375
14835
|
const limit = Math.min(stat.size, CAP);
|
|
14376
14836
|
const parts = [];
|
|
14377
14837
|
for (let pos = 0; pos < limit; pos += CHUNK) {
|
|
14378
14838
|
const buf = Buffer.alloc(Math.min(CHUNK, limit - pos));
|
|
14379
|
-
const read2 =
|
|
14839
|
+
const read2 = import_fs24.default.readSync(fd, buf, 0, buf.length, pos);
|
|
14380
14840
|
if (read2 <= 0) break;
|
|
14381
14841
|
const slice = buf.subarray(0, read2);
|
|
14382
14842
|
const nl = slice.indexOf(10);
|
|
@@ -14385,14 +14845,14 @@ function statAndFirstLine(file) {
|
|
|
14385
14845
|
}
|
|
14386
14846
|
return { stat, first: Buffer.concat(parts).toString("utf8") };
|
|
14387
14847
|
} finally {
|
|
14388
|
-
|
|
14848
|
+
import_fs24.default.closeSync(fd);
|
|
14389
14849
|
}
|
|
14390
14850
|
}
|
|
14391
14851
|
function listCodexSessionFiles(base = codexSessionsDir()) {
|
|
14392
14852
|
const files = [];
|
|
14393
14853
|
const walk = (dir) => {
|
|
14394
14854
|
try {
|
|
14395
|
-
for (const entry of
|
|
14855
|
+
for (const entry of import_fs24.default.readdirSync(dir, { withFileTypes: true })) {
|
|
14396
14856
|
const file = import_path24.default.join(dir, entry.name);
|
|
14397
14857
|
if (entry.isDirectory()) walk(file);
|
|
14398
14858
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) files.push(file);
|
|
@@ -14591,24 +15051,24 @@ function parseCodexSession(lines) {
|
|
|
14591
15051
|
}
|
|
14592
15052
|
return [...rows.values()];
|
|
14593
15053
|
}
|
|
14594
|
-
var
|
|
15054
|
+
var import_fs24, import_os21, import_path24, CODEX_FALLBACK, codexSource;
|
|
14595
15055
|
var init_cost_codex = __esm({
|
|
14596
15056
|
"src/cost-codex.ts"() {
|
|
14597
15057
|
"use strict";
|
|
14598
|
-
|
|
14599
|
-
|
|
15058
|
+
import_fs24 = __toESM(require("fs"));
|
|
15059
|
+
import_os21 = __toESM(require("os"));
|
|
14600
15060
|
import_path24 = __toESM(require("path"));
|
|
14601
15061
|
init_litellm();
|
|
14602
15062
|
CODEX_FALLBACK = [5e-6, 15e-6, 0, 25e-7];
|
|
14603
15063
|
codexSource = {
|
|
14604
15064
|
id: "codex",
|
|
14605
|
-
available: () =>
|
|
15065
|
+
available: () => import_fs24.default.existsSync(codexSessionsDir()) || import_fs24.default.existsSync(import_path24.default.join(import_path24.default.dirname(codexSessionsDir()), "archived_sessions")),
|
|
14606
15066
|
collect(sinceMs) {
|
|
14607
15067
|
const entries = [];
|
|
14608
15068
|
for (const file of listCodexSessionFiles()) {
|
|
14609
15069
|
try {
|
|
14610
|
-
if (sinceMs !== void 0 &&
|
|
14611
|
-
entries.push(...parseCodexSession(
|
|
15070
|
+
if (sinceMs !== void 0 && import_fs24.default.statSync(file).mtimeMs < sinceMs) continue;
|
|
15071
|
+
entries.push(...parseCodexSession(import_fs24.default.readFileSync(file, "utf8").split("\n")));
|
|
14612
15072
|
} catch {
|
|
14613
15073
|
}
|
|
14614
15074
|
}
|
|
@@ -14620,11 +15080,11 @@ var init_cost_codex = __esm({
|
|
|
14620
15080
|
|
|
14621
15081
|
// src/cost-copilot.ts
|
|
14622
15082
|
function copilotSessionsDir() {
|
|
14623
|
-
return import_path25.default.join(
|
|
15083
|
+
return import_path25.default.join(import_os22.default.homedir(), ".copilot", "session-state");
|
|
14624
15084
|
}
|
|
14625
15085
|
function safeReaddir2(dir) {
|
|
14626
15086
|
try {
|
|
14627
|
-
return
|
|
15087
|
+
return import_fs25.default.readdirSync(dir);
|
|
14628
15088
|
} catch {
|
|
14629
15089
|
return [];
|
|
14630
15090
|
}
|
|
@@ -14691,19 +15151,19 @@ function parseCopilotSession(lines) {
|
|
|
14691
15151
|
}
|
|
14692
15152
|
return rows;
|
|
14693
15153
|
}
|
|
14694
|
-
var
|
|
15154
|
+
var import_fs25, import_os22, import_path25, copilotSource;
|
|
14695
15155
|
var init_cost_copilot = __esm({
|
|
14696
15156
|
"src/cost-copilot.ts"() {
|
|
14697
15157
|
"use strict";
|
|
14698
|
-
|
|
14699
|
-
|
|
15158
|
+
import_fs25 = __toESM(require("fs"));
|
|
15159
|
+
import_os22 = __toESM(require("os"));
|
|
14700
15160
|
import_path25 = __toESM(require("path"));
|
|
14701
15161
|
init_litellm();
|
|
14702
15162
|
copilotSource = {
|
|
14703
15163
|
id: "copilot",
|
|
14704
15164
|
available() {
|
|
14705
15165
|
try {
|
|
14706
|
-
return
|
|
15166
|
+
return import_fs25.default.existsSync(copilotSessionsDir());
|
|
14707
15167
|
} catch {
|
|
14708
15168
|
return false;
|
|
14709
15169
|
}
|
|
@@ -14714,13 +15174,13 @@ var init_cost_copilot = __esm({
|
|
|
14714
15174
|
for (const sid of safeReaddir2(base)) {
|
|
14715
15175
|
const file = import_path25.default.join(base, sid, "events.jsonl");
|
|
14716
15176
|
try {
|
|
14717
|
-
if (sinceMs !== void 0 &&
|
|
15177
|
+
if (sinceMs !== void 0 && import_fs25.default.statSync(file).mtimeMs < sinceMs) continue;
|
|
14718
15178
|
} catch {
|
|
14719
15179
|
continue;
|
|
14720
15180
|
}
|
|
14721
15181
|
let content;
|
|
14722
15182
|
try {
|
|
14723
|
-
content =
|
|
15183
|
+
content = import_fs25.default.readFileSync(file, "utf8");
|
|
14724
15184
|
} catch {
|
|
14725
15185
|
continue;
|
|
14726
15186
|
}
|
|
@@ -15157,7 +15617,7 @@ function buildSensitivePaths(home, cwd) {
|
|
|
15157
15617
|
}
|
|
15158
15618
|
function isReadable(filePath) {
|
|
15159
15619
|
try {
|
|
15160
|
-
|
|
15620
|
+
import_fs26.default.accessSync(filePath, import_fs26.default.constants.R_OK);
|
|
15161
15621
|
return true;
|
|
15162
15622
|
} catch {
|
|
15163
15623
|
return false;
|
|
@@ -15170,13 +15630,13 @@ function scoreLabel(score) {
|
|
|
15170
15630
|
return import_chalk3.default.red.bold(`${score}/100 Critical`);
|
|
15171
15631
|
}
|
|
15172
15632
|
function runBlast() {
|
|
15173
|
-
const home =
|
|
15633
|
+
const home = import_os23.default.homedir();
|
|
15174
15634
|
const cwd = process.cwd();
|
|
15175
15635
|
const paths = buildSensitivePaths(home, cwd);
|
|
15176
15636
|
let scoreDeduction = 0;
|
|
15177
15637
|
const reachable = [];
|
|
15178
15638
|
for (const p of paths) {
|
|
15179
|
-
if (
|
|
15639
|
+
if (import_fs26.default.existsSync(p.full) && isReadable(p.full)) {
|
|
15180
15640
|
reachable.push(p);
|
|
15181
15641
|
scoreDeduction += p.score;
|
|
15182
15642
|
}
|
|
@@ -15194,7 +15654,7 @@ function runBlast() {
|
|
|
15194
15654
|
}
|
|
15195
15655
|
function registerBlastCommand(program2) {
|
|
15196
15656
|
program2.command("blast").description("Map what an AI agent can currently reach on this machine").action(() => {
|
|
15197
|
-
const home =
|
|
15657
|
+
const home = import_os23.default.homedir();
|
|
15198
15658
|
const cwd = process.cwd();
|
|
15199
15659
|
const { reachable, envFindings, score } = runBlast();
|
|
15200
15660
|
console.log("");
|
|
@@ -15241,14 +15701,14 @@ function registerBlastCommand(program2) {
|
|
|
15241
15701
|
console.log("");
|
|
15242
15702
|
});
|
|
15243
15703
|
}
|
|
15244
|
-
var import_chalk3,
|
|
15704
|
+
var import_chalk3, import_fs26, import_path26, import_os23;
|
|
15245
15705
|
var init_blast = __esm({
|
|
15246
15706
|
"src/cli/commands/blast.ts"() {
|
|
15247
15707
|
"use strict";
|
|
15248
15708
|
import_chalk3 = __toESM(require("chalk"));
|
|
15249
|
-
|
|
15709
|
+
import_fs26 = __toESM(require("fs"));
|
|
15250
15710
|
import_path26 = __toESM(require("path"));
|
|
15251
|
-
|
|
15711
|
+
import_os23 = __toESM(require("os"));
|
|
15252
15712
|
init_dlp();
|
|
15253
15713
|
}
|
|
15254
15714
|
});
|
|
@@ -15394,7 +15854,7 @@ function listSessionFiles(dir, maxDepth = 6) {
|
|
|
15394
15854
|
if (depth > maxDepth) return;
|
|
15395
15855
|
let entries;
|
|
15396
15856
|
try {
|
|
15397
|
-
entries =
|
|
15857
|
+
entries = fs28.readdirSync(d, { withFileTypes: true });
|
|
15398
15858
|
} catch {
|
|
15399
15859
|
return;
|
|
15400
15860
|
}
|
|
@@ -15410,24 +15870,24 @@ function listSessionFiles(dir, maxDepth = 6) {
|
|
|
15410
15870
|
function sessionIdOf(relPath) {
|
|
15411
15871
|
return path28.basename(relPath).replace(/\.jsonl$/, "");
|
|
15412
15872
|
}
|
|
15413
|
-
var
|
|
15873
|
+
var fs28, path28;
|
|
15414
15874
|
var init_session_files = __esm({
|
|
15415
15875
|
"src/session-files.ts"() {
|
|
15416
15876
|
"use strict";
|
|
15417
|
-
|
|
15877
|
+
fs28 = __toESM(require("fs"));
|
|
15418
15878
|
path28 = __toESM(require("path"));
|
|
15419
15879
|
}
|
|
15420
15880
|
});
|
|
15421
15881
|
|
|
15422
15882
|
// src/cli/render/scan-history.ts
|
|
15423
15883
|
function defaultHistoryPath() {
|
|
15424
|
-
return import_path27.default.join(
|
|
15884
|
+
return import_path27.default.join(import_os24.default.homedir(), ".node9", "scan-history.json");
|
|
15425
15885
|
}
|
|
15426
15886
|
function readPreviousScan(opts = {}) {
|
|
15427
15887
|
const filePath = opts.path ?? defaultHistoryPath();
|
|
15428
15888
|
try {
|
|
15429
|
-
if (!
|
|
15430
|
-
const raw =
|
|
15889
|
+
if (!import_fs27.default.existsSync(filePath)) return null;
|
|
15890
|
+
const raw = import_fs27.default.readFileSync(filePath, "utf8");
|
|
15431
15891
|
const parsed = JSON.parse(raw);
|
|
15432
15892
|
if (!Array.isArray(parsed) || parsed.length === 0) return null;
|
|
15433
15893
|
const last = parsed[parsed.length - 1];
|
|
@@ -15441,11 +15901,11 @@ function appendScanHistory(record2, opts = {}) {
|
|
|
15441
15901
|
const filePath = opts.path ?? defaultHistoryPath();
|
|
15442
15902
|
const cap = opts.cap ?? SCAN_HISTORY_CAP;
|
|
15443
15903
|
try {
|
|
15444
|
-
|
|
15904
|
+
import_fs27.default.mkdirSync(import_path27.default.dirname(filePath), { recursive: true });
|
|
15445
15905
|
let history = [];
|
|
15446
|
-
if (
|
|
15906
|
+
if (import_fs27.default.existsSync(filePath)) {
|
|
15447
15907
|
try {
|
|
15448
|
-
const parsed = JSON.parse(
|
|
15908
|
+
const parsed = JSON.parse(import_fs27.default.readFileSync(filePath, "utf8"));
|
|
15449
15909
|
if (Array.isArray(parsed)) {
|
|
15450
15910
|
history = parsed.filter(isValidRecord);
|
|
15451
15911
|
}
|
|
@@ -15478,13 +15938,13 @@ function isValidRecord(x) {
|
|
|
15478
15938
|
const r = x;
|
|
15479
15939
|
return typeof r.timestamp === "string" && typeof r.score === "number" && typeof r.blocked === "number" && typeof r.review === "number" && typeof r.leaks === "number" && typeof r.loops === "number" && typeof r.totalCalls === "number";
|
|
15480
15940
|
}
|
|
15481
|
-
var
|
|
15941
|
+
var import_fs27, import_path27, import_os24, SCAN_HISTORY_CAP;
|
|
15482
15942
|
var init_scan_history = __esm({
|
|
15483
15943
|
"src/cli/render/scan-history.ts"() {
|
|
15484
15944
|
"use strict";
|
|
15485
|
-
|
|
15945
|
+
import_fs27 = __toESM(require("fs"));
|
|
15486
15946
|
import_path27 = __toESM(require("path"));
|
|
15487
|
-
|
|
15947
|
+
import_os24 = __toESM(require("os"));
|
|
15488
15948
|
init_atomic_write();
|
|
15489
15949
|
SCAN_HISTORY_CAP = 30;
|
|
15490
15950
|
}
|
|
@@ -15498,7 +15958,7 @@ function parseJSONLFile(filePath, fallbackWorkingDir) {
|
|
|
15498
15958
|
const runId = import_path28.default.basename(filePath, ".jsonl");
|
|
15499
15959
|
let content;
|
|
15500
15960
|
try {
|
|
15501
|
-
content =
|
|
15961
|
+
content = import_fs28.default.readFileSync(filePath, "utf8");
|
|
15502
15962
|
} catch {
|
|
15503
15963
|
return /* @__PURE__ */ new Map();
|
|
15504
15964
|
}
|
|
@@ -15598,7 +16058,7 @@ async function postCostBatches(apiUrl, apiKey, machineId, entries) {
|
|
|
15598
16058
|
signal: AbortSignal.timeout(15e3)
|
|
15599
16059
|
});
|
|
15600
16060
|
if (!res.ok) {
|
|
15601
|
-
|
|
16061
|
+
import_fs28.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] HTTP ${res.status}
|
|
15602
16062
|
`);
|
|
15603
16063
|
} else {
|
|
15604
16064
|
let stored;
|
|
@@ -15608,7 +16068,7 @@ async function postCostBatches(apiUrl, apiKey, machineId, entries) {
|
|
|
15608
16068
|
} catch {
|
|
15609
16069
|
}
|
|
15610
16070
|
if (typeof stored === "number" && stored < batch.length) {
|
|
15611
|
-
|
|
16071
|
+
import_fs28.default.appendFileSync(
|
|
15612
16072
|
HOOK_DEBUG_LOG,
|
|
15613
16073
|
`[cost-sync] dropped ${batch.length - stored} of ${batch.length} rows
|
|
15614
16074
|
`
|
|
@@ -15616,7 +16076,7 @@ async function postCostBatches(apiUrl, apiKey, machineId, entries) {
|
|
|
15616
16076
|
}
|
|
15617
16077
|
}
|
|
15618
16078
|
} catch (err2) {
|
|
15619
|
-
|
|
16079
|
+
import_fs28.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] ${safeMessage(err2)}
|
|
15620
16080
|
`);
|
|
15621
16081
|
}
|
|
15622
16082
|
}
|
|
@@ -15629,10 +16089,10 @@ async function syncCost() {
|
|
|
15629
16089
|
if (entries.length === 0) return;
|
|
15630
16090
|
let username = "unknown";
|
|
15631
16091
|
try {
|
|
15632
|
-
username =
|
|
16092
|
+
username = import_os25.default.userInfo().username;
|
|
15633
16093
|
} catch {
|
|
15634
16094
|
}
|
|
15635
|
-
const machineId = `${
|
|
16095
|
+
const machineId = `${import_os25.default.hostname()}:${username}`;
|
|
15636
16096
|
await postCostBatches(creds.apiUrl, creds.apiKey, machineId, entries);
|
|
15637
16097
|
}
|
|
15638
16098
|
function startCostSync() {
|
|
@@ -15644,13 +16104,13 @@ function startCostSync() {
|
|
|
15644
16104
|
}, SYNC_INTERVAL_MS);
|
|
15645
16105
|
timer.unref();
|
|
15646
16106
|
}
|
|
15647
|
-
var
|
|
16107
|
+
var import_fs28, import_path28, import_os25, SYNC_INTERVAL_MS, claudeSource, COST_SOURCES, COST_BATCH_SIZE;
|
|
15648
16108
|
var init_costSync = __esm({
|
|
15649
16109
|
"src/costSync.ts"() {
|
|
15650
16110
|
"use strict";
|
|
15651
|
-
|
|
16111
|
+
import_fs28 = __toESM(require("fs"));
|
|
15652
16112
|
import_path28 = __toESM(require("path"));
|
|
15653
|
-
|
|
16113
|
+
import_os25 = __toESM(require("os"));
|
|
15654
16114
|
init_config();
|
|
15655
16115
|
init_audit();
|
|
15656
16116
|
init_litellm();
|
|
@@ -15663,22 +16123,22 @@ var init_costSync = __esm({
|
|
|
15663
16123
|
claudeSource = {
|
|
15664
16124
|
id: "claude",
|
|
15665
16125
|
available() {
|
|
15666
|
-
return
|
|
16126
|
+
return import_fs28.default.existsSync(import_path28.default.join(import_os25.default.homedir(), ".claude", "projects"));
|
|
15667
16127
|
},
|
|
15668
16128
|
collect(sinceMs) {
|
|
15669
|
-
const projectsDir = import_path28.default.join(
|
|
15670
|
-
if (!
|
|
16129
|
+
const projectsDir = import_path28.default.join(import_os25.default.homedir(), ".claude", "projects");
|
|
16130
|
+
if (!import_fs28.default.existsSync(projectsDir)) return [];
|
|
15671
16131
|
const combined = /* @__PURE__ */ new Map();
|
|
15672
16132
|
let dirs;
|
|
15673
16133
|
try {
|
|
15674
|
-
dirs =
|
|
16134
|
+
dirs = import_fs28.default.readdirSync(projectsDir);
|
|
15675
16135
|
} catch {
|
|
15676
16136
|
return [];
|
|
15677
16137
|
}
|
|
15678
16138
|
for (const dir of dirs) {
|
|
15679
16139
|
const dirPath = import_path28.default.join(projectsDir, dir);
|
|
15680
16140
|
try {
|
|
15681
|
-
if (!
|
|
16141
|
+
if (!import_fs28.default.statSync(dirPath).isDirectory()) continue;
|
|
15682
16142
|
} catch {
|
|
15683
16143
|
continue;
|
|
15684
16144
|
}
|
|
@@ -15693,7 +16153,7 @@ var init_costSync = __esm({
|
|
|
15693
16153
|
const filePath = import_path28.default.join(dirPath, file);
|
|
15694
16154
|
if (sinceMs !== void 0) {
|
|
15695
16155
|
try {
|
|
15696
|
-
if (
|
|
16156
|
+
if (import_fs28.default.statSync(filePath).mtimeMs < sinceMs) continue;
|
|
15697
16157
|
} catch {
|
|
15698
16158
|
continue;
|
|
15699
16159
|
}
|
|
@@ -15744,7 +16204,7 @@ function freshWatermark() {
|
|
|
15744
16204
|
function loadWatermark() {
|
|
15745
16205
|
let raw;
|
|
15746
16206
|
try {
|
|
15747
|
-
raw =
|
|
16207
|
+
raw = import_fs29.default.readFileSync(WATERMARK_FILE(), "utf-8");
|
|
15748
16208
|
} catch {
|
|
15749
16209
|
return { status: "fresh", wm: freshWatermark() };
|
|
15750
16210
|
}
|
|
@@ -15797,21 +16257,21 @@ function saveWatermark(wm) {
|
|
|
15797
16257
|
if (wm.schemaVersion > WATERMARK_SCHEMA_VERSION) return;
|
|
15798
16258
|
const target = WATERMARK_FILE();
|
|
15799
16259
|
const dir = import_path29.default.dirname(target);
|
|
15800
|
-
if (!
|
|
16260
|
+
if (!import_fs29.default.existsSync(dir)) import_fs29.default.mkdirSync(dir, { recursive: true });
|
|
15801
16261
|
const tmp = target + ".tmp";
|
|
15802
|
-
|
|
15803
|
-
|
|
16262
|
+
import_fs29.default.writeFileSync(tmp, JSON.stringify(wm, null, 2) + "\n", "utf-8");
|
|
16263
|
+
import_fs29.default.renameSync(tmp, target);
|
|
15804
16264
|
}
|
|
15805
16265
|
function listJsonlFiles() {
|
|
15806
16266
|
const root = PROJECTS_DIR();
|
|
15807
|
-
if (!
|
|
16267
|
+
if (!import_fs29.default.existsSync(root)) return [];
|
|
15808
16268
|
const out = [];
|
|
15809
|
-
for (const entry of
|
|
16269
|
+
for (const entry of import_fs29.default.readdirSync(root, { withFileTypes: true })) {
|
|
15810
16270
|
if (!entry.isDirectory()) continue;
|
|
15811
16271
|
const projectDir = import_path29.default.join(root, entry.name);
|
|
15812
16272
|
let inner;
|
|
15813
16273
|
try {
|
|
15814
|
-
inner =
|
|
16274
|
+
inner = import_fs29.default.readdirSync(projectDir, { withFileTypes: true });
|
|
15815
16275
|
} catch {
|
|
15816
16276
|
continue;
|
|
15817
16277
|
}
|
|
@@ -15825,7 +16285,7 @@ function listJsonlFiles() {
|
|
|
15825
16285
|
}
|
|
15826
16286
|
function fileSize(p) {
|
|
15827
16287
|
try {
|
|
15828
|
-
return
|
|
16288
|
+
return import_fs29.default.statSync(p).size;
|
|
15829
16289
|
} catch {
|
|
15830
16290
|
return 0;
|
|
15831
16291
|
}
|
|
@@ -15835,7 +16295,7 @@ async function scanDelta(filePath, fromByte, onLine) {
|
|
|
15835
16295
|
if (size <= fromByte) return fromByte;
|
|
15836
16296
|
const lastNl = findLastNewline(filePath, fromByte, size);
|
|
15837
16297
|
const endsWithNewline = lastNl === size - 1;
|
|
15838
|
-
const stream =
|
|
16298
|
+
const stream = import_fs29.default.createReadStream(filePath, {
|
|
15839
16299
|
start: fromByte,
|
|
15840
16300
|
end: size - 1,
|
|
15841
16301
|
highWaterMark: 64 * 1024
|
|
@@ -15864,7 +16324,7 @@ function findLastNewline(filePath, from, size) {
|
|
|
15864
16324
|
const CHUNK = 64 * 1024;
|
|
15865
16325
|
let fd;
|
|
15866
16326
|
try {
|
|
15867
|
-
fd =
|
|
16327
|
+
fd = import_fs29.default.openSync(filePath, "r");
|
|
15868
16328
|
} catch {
|
|
15869
16329
|
return -1;
|
|
15870
16330
|
}
|
|
@@ -15873,7 +16333,7 @@ function findLastNewline(filePath, from, size) {
|
|
|
15873
16333
|
let end = size;
|
|
15874
16334
|
while (end > from) {
|
|
15875
16335
|
const start = Math.max(from, end - CHUNK);
|
|
15876
|
-
const n =
|
|
16336
|
+
const n = import_fs29.default.readSync(fd, buf, 0, end - start, start);
|
|
15877
16337
|
const idx = buf.subarray(0, n).lastIndexOf(10);
|
|
15878
16338
|
if (idx !== -1) return start + idx;
|
|
15879
16339
|
end = start;
|
|
@@ -15882,7 +16342,7 @@ function findLastNewline(filePath, from, size) {
|
|
|
15882
16342
|
} catch {
|
|
15883
16343
|
return -1;
|
|
15884
16344
|
} finally {
|
|
15885
|
-
|
|
16345
|
+
import_fs29.default.closeSync(fd);
|
|
15886
16346
|
}
|
|
15887
16347
|
}
|
|
15888
16348
|
function safeCanaryCtxValues() {
|
|
@@ -16047,7 +16507,7 @@ function emptyTick(uploadAs) {
|
|
|
16047
16507
|
function readRawWatermarkPreservingOffsets() {
|
|
16048
16508
|
let raw;
|
|
16049
16509
|
try {
|
|
16050
|
-
raw =
|
|
16510
|
+
raw = import_fs29.default.readFileSync(WATERMARK_FILE(), "utf-8");
|
|
16051
16511
|
} catch {
|
|
16052
16512
|
return null;
|
|
16053
16513
|
}
|
|
@@ -16082,7 +16542,7 @@ async function runActualTick(wm) {
|
|
|
16082
16542
|
if (!known) {
|
|
16083
16543
|
let mtimeMs = 0;
|
|
16084
16544
|
try {
|
|
16085
|
-
mtimeMs =
|
|
16545
|
+
mtimeMs = import_fs29.default.statSync(filePath).mtime.getTime();
|
|
16086
16546
|
} catch {
|
|
16087
16547
|
continue;
|
|
16088
16548
|
}
|
|
@@ -16133,20 +16593,20 @@ async function runActualTick(wm) {
|
|
|
16133
16593
|
}
|
|
16134
16594
|
return result;
|
|
16135
16595
|
}
|
|
16136
|
-
var
|
|
16596
|
+
var import_fs29, import_os26, import_path29, import_readline, PROJECTS_DIR, WATERMARK_FILE, MAX_LINE_BYTES, WATERMARK_SCHEMA_VERSION, LONG_OUTPUT_THRESHOLD_BYTES2;
|
|
16137
16597
|
var init_scan_watermark = __esm({
|
|
16138
16598
|
"src/daemon/scan-watermark.ts"() {
|
|
16139
16599
|
"use strict";
|
|
16140
|
-
|
|
16141
|
-
|
|
16600
|
+
import_fs29 = __toESM(require("fs"));
|
|
16601
|
+
import_os26 = __toESM(require("os"));
|
|
16142
16602
|
import_path29 = __toESM(require("path"));
|
|
16143
16603
|
import_readline = __toESM(require("readline"));
|
|
16144
16604
|
init_dlp();
|
|
16145
16605
|
init_registry();
|
|
16146
16606
|
init_config();
|
|
16147
16607
|
init_dist();
|
|
16148
|
-
PROJECTS_DIR = () => import_path29.default.join(
|
|
16149
|
-
WATERMARK_FILE = () => import_path29.default.join(
|
|
16608
|
+
PROJECTS_DIR = () => import_path29.default.join(import_os26.default.homedir(), ".claude", "projects");
|
|
16609
|
+
WATERMARK_FILE = () => import_path29.default.join(import_os26.default.homedir(), ".node9", "scan-watermark.json");
|
|
16150
16610
|
MAX_LINE_BYTES = 2 * 1024 * 1024;
|
|
16151
16611
|
WATERMARK_SCHEMA_VERSION = 2;
|
|
16152
16612
|
LONG_OUTPUT_THRESHOLD_BYTES2 = LONG_OUTPUT_THRESHOLD_BYTES;
|
|
@@ -16195,10 +16655,10 @@ function parseSinceCutoff(raw, now = /* @__PURE__ */ new Date()) {
|
|
|
16195
16655
|
return now.getTime() - 90 * 864e5;
|
|
16196
16656
|
}
|
|
16197
16657
|
function* iterateJsonlFiles(cutoffMs) {
|
|
16198
|
-
const projectsDir = import_path30.default.join(
|
|
16658
|
+
const projectsDir = import_path30.default.join(import_os27.default.homedir(), ".claude", "projects");
|
|
16199
16659
|
let dirs;
|
|
16200
16660
|
try {
|
|
16201
|
-
dirs =
|
|
16661
|
+
dirs = import_fs30.default.readdirSync(projectsDir);
|
|
16202
16662
|
} catch {
|
|
16203
16663
|
return;
|
|
16204
16664
|
}
|
|
@@ -16206,14 +16666,14 @@ function* iterateJsonlFiles(cutoffMs) {
|
|
|
16206
16666
|
const dirPath = import_path30.default.join(projectsDir, dir);
|
|
16207
16667
|
let stats;
|
|
16208
16668
|
try {
|
|
16209
|
-
stats =
|
|
16669
|
+
stats = import_fs30.default.statSync(dirPath);
|
|
16210
16670
|
} catch {
|
|
16211
16671
|
continue;
|
|
16212
16672
|
}
|
|
16213
16673
|
if (!stats.isDirectory()) continue;
|
|
16214
16674
|
let files;
|
|
16215
16675
|
try {
|
|
16216
|
-
files =
|
|
16676
|
+
files = import_fs30.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
|
|
16217
16677
|
} catch {
|
|
16218
16678
|
continue;
|
|
16219
16679
|
}
|
|
@@ -16221,7 +16681,7 @@ function* iterateJsonlFiles(cutoffMs) {
|
|
|
16221
16681
|
const filePath = import_path30.default.join(dirPath, file);
|
|
16222
16682
|
let mtime = 0;
|
|
16223
16683
|
try {
|
|
16224
|
-
mtime =
|
|
16684
|
+
mtime = import_fs30.default.statSync(filePath).mtimeMs;
|
|
16225
16685
|
} catch {
|
|
16226
16686
|
continue;
|
|
16227
16687
|
}
|
|
@@ -16296,7 +16756,7 @@ async function runUploadHistory(opts) {
|
|
|
16296
16756
|
filesScanned++;
|
|
16297
16757
|
let content;
|
|
16298
16758
|
try {
|
|
16299
|
-
content =
|
|
16759
|
+
content = import_fs30.default.readFileSync(filePath, "utf8");
|
|
16300
16760
|
} catch {
|
|
16301
16761
|
continue;
|
|
16302
16762
|
}
|
|
@@ -16370,10 +16830,10 @@ async function runUploadHistory(opts) {
|
|
|
16370
16830
|
const costUrl = creds.apiUrl.endsWith("/policies/sync") ? creds.apiUrl.replace(/\/policies\/sync$/, "/cost-sync") : `${creds.apiUrl.replace(/\/$/, "")}/cost-sync`;
|
|
16371
16831
|
let username = "unknown";
|
|
16372
16832
|
try {
|
|
16373
|
-
username =
|
|
16833
|
+
username = import_os27.default.userInfo().username;
|
|
16374
16834
|
} catch {
|
|
16375
16835
|
}
|
|
16376
|
-
const machineId = `${
|
|
16836
|
+
const machineId = `${import_os27.default.hostname()}:${username}`;
|
|
16377
16837
|
await postJson(costUrl, creds.apiKey, {
|
|
16378
16838
|
machineId,
|
|
16379
16839
|
entries: dailyEntries
|
|
@@ -16423,13 +16883,13 @@ async function postJson(url, apiKey, body) {
|
|
|
16423
16883
|
req.end();
|
|
16424
16884
|
});
|
|
16425
16885
|
}
|
|
16426
|
-
var
|
|
16886
|
+
var import_fs30, import_https, import_os27, import_path30, import_chalk5, FINDING_TO_SIGNAL2;
|
|
16427
16887
|
var init_scan_upload_history = __esm({
|
|
16428
16888
|
"src/scan-upload-history.ts"() {
|
|
16429
16889
|
"use strict";
|
|
16430
|
-
|
|
16890
|
+
import_fs30 = __toESM(require("fs"));
|
|
16431
16891
|
import_https = __toESM(require("https"));
|
|
16432
|
-
|
|
16892
|
+
import_os27 = __toESM(require("os"));
|
|
16433
16893
|
import_path30 = __toESM(require("path"));
|
|
16434
16894
|
import_chalk5 = __toESM(require("chalk"));
|
|
16435
16895
|
init_dist();
|
|
@@ -16537,7 +16997,7 @@ function findingKey(ruleName, inputPreview, projLabel) {
|
|
|
16537
16997
|
return `${ruleName ?? "<unnamed>"}|${inputPreview}|${projLabel}`;
|
|
16538
16998
|
}
|
|
16539
16999
|
function displayHome(p) {
|
|
16540
|
-
const home =
|
|
17000
|
+
const home = import_os28.default.homedir();
|
|
16541
17001
|
return p.startsWith(home) ? "~" + p.slice(home.length) : p;
|
|
16542
17002
|
}
|
|
16543
17003
|
function dlpKey(patternName, redactedSample, projLabel) {
|
|
@@ -16734,14 +17194,14 @@ function buildRuleSources() {
|
|
|
16734
17194
|
}
|
|
16735
17195
|
function countScanFiles() {
|
|
16736
17196
|
let total = 0;
|
|
16737
|
-
const claudeDir = import_path31.default.join(
|
|
16738
|
-
if (
|
|
17197
|
+
const claudeDir = import_path31.default.join(import_os28.default.homedir(), ".claude", "projects");
|
|
17198
|
+
if (import_fs31.default.existsSync(claudeDir)) {
|
|
16739
17199
|
try {
|
|
16740
|
-
for (const proj of
|
|
17200
|
+
for (const proj of import_fs31.default.readdirSync(claudeDir)) {
|
|
16741
17201
|
const p = import_path31.default.join(claudeDir, proj);
|
|
16742
17202
|
try {
|
|
16743
|
-
if (!
|
|
16744
|
-
total +=
|
|
17203
|
+
if (!import_fs31.default.statSync(p).isDirectory()) continue;
|
|
17204
|
+
total += import_fs31.default.readdirSync(p).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-")).length;
|
|
16745
17205
|
} catch {
|
|
16746
17206
|
continue;
|
|
16747
17207
|
}
|
|
@@ -16749,17 +17209,17 @@ function countScanFiles() {
|
|
|
16749
17209
|
} catch {
|
|
16750
17210
|
}
|
|
16751
17211
|
}
|
|
16752
|
-
const geminiDir = import_path31.default.join(
|
|
16753
|
-
if (
|
|
17212
|
+
const geminiDir = import_path31.default.join(import_os28.default.homedir(), ".gemini", "tmp");
|
|
17213
|
+
if (import_fs31.default.existsSync(geminiDir)) {
|
|
16754
17214
|
try {
|
|
16755
|
-
for (const slug2 of
|
|
17215
|
+
for (const slug2 of import_fs31.default.readdirSync(geminiDir)) {
|
|
16756
17216
|
const p = import_path31.default.join(geminiDir, slug2);
|
|
16757
17217
|
try {
|
|
16758
|
-
if (!
|
|
17218
|
+
if (!import_fs31.default.statSync(p).isDirectory()) continue;
|
|
16759
17219
|
const chatsDir = import_path31.default.join(p, "chats");
|
|
16760
|
-
if (
|
|
17220
|
+
if (import_fs31.default.existsSync(chatsDir)) {
|
|
16761
17221
|
try {
|
|
16762
|
-
total +=
|
|
17222
|
+
total += import_fs31.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json")).length;
|
|
16763
17223
|
} catch {
|
|
16764
17224
|
}
|
|
16765
17225
|
}
|
|
@@ -16771,15 +17231,15 @@ function countScanFiles() {
|
|
|
16771
17231
|
}
|
|
16772
17232
|
}
|
|
16773
17233
|
for (const surface of ["antigravity-cli", "antigravity-ide"]) {
|
|
16774
|
-
const brainDir = import_path31.default.join(
|
|
16775
|
-
if (!
|
|
17234
|
+
const brainDir = import_path31.default.join(import_os28.default.homedir(), ".gemini", surface, "brain");
|
|
17235
|
+
if (!import_fs31.default.existsSync(brainDir)) continue;
|
|
16776
17236
|
try {
|
|
16777
|
-
for (const conv of
|
|
17237
|
+
for (const conv of import_fs31.default.readdirSync(brainDir)) {
|
|
16778
17238
|
const convPath = import_path31.default.join(brainDir, conv);
|
|
16779
17239
|
try {
|
|
16780
|
-
if (!
|
|
17240
|
+
if (!import_fs31.default.statSync(convPath).isDirectory()) continue;
|
|
16781
17241
|
const logsDir = import_path31.default.join(convPath, ".system_generated", "logs");
|
|
16782
|
-
if (
|
|
17242
|
+
if (import_fs31.default.existsSync(import_path31.default.join(logsDir, "transcript_full.jsonl")) || import_fs31.default.existsSync(import_path31.default.join(logsDir, "transcript.jsonl"))) {
|
|
16783
17243
|
total += 1;
|
|
16784
17244
|
}
|
|
16785
17245
|
} catch {
|
|
@@ -16789,11 +17249,11 @@ function countScanFiles() {
|
|
|
16789
17249
|
} catch {
|
|
16790
17250
|
}
|
|
16791
17251
|
}
|
|
16792
|
-
const copilotDir = import_path31.default.join(
|
|
16793
|
-
if (
|
|
17252
|
+
const copilotDir = import_path31.default.join(import_os28.default.homedir(), ".copilot", "session-state");
|
|
17253
|
+
if (import_fs31.default.existsSync(copilotDir)) {
|
|
16794
17254
|
try {
|
|
16795
|
-
for (const sid of
|
|
16796
|
-
if (
|
|
17255
|
+
for (const sid of import_fs31.default.readdirSync(copilotDir)) {
|
|
17256
|
+
if (import_fs31.default.existsSync(import_path31.default.join(copilotDir, sid, "events.jsonl"))) total += 1;
|
|
16797
17257
|
}
|
|
16798
17258
|
} catch {
|
|
16799
17259
|
}
|
|
@@ -16820,7 +17280,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
16820
17280
|
const session = { sessionId, costUSD: 0, toolCalls: 0 };
|
|
16821
17281
|
let raw;
|
|
16822
17282
|
try {
|
|
16823
|
-
raw =
|
|
17283
|
+
raw = import_fs31.default.readFileSync(import_path31.default.join(projPath, file), "utf-8");
|
|
16824
17284
|
} catch {
|
|
16825
17285
|
return;
|
|
16826
17286
|
}
|
|
@@ -17064,11 +17524,11 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
17064
17524
|
function processClaudeProject(proj, projectsDir, ruleSources, startDate, result, dedup, canaryVals, onProgress, onLine) {
|
|
17065
17525
|
const projPath = import_path31.default.join(projectsDir, proj);
|
|
17066
17526
|
try {
|
|
17067
|
-
if (!
|
|
17527
|
+
if (!import_fs31.default.statSync(projPath).isDirectory()) return;
|
|
17068
17528
|
} catch {
|
|
17069
17529
|
return;
|
|
17070
17530
|
}
|
|
17071
|
-
const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(
|
|
17531
|
+
const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(import_os28.default.homedir(), "~")).slice(
|
|
17072
17532
|
0,
|
|
17073
17533
|
40
|
|
17074
17534
|
);
|
|
@@ -17111,12 +17571,12 @@ function emptyClaudeScan() {
|
|
|
17111
17571
|
};
|
|
17112
17572
|
}
|
|
17113
17573
|
function scanClaudeHistory(startDate, onProgress, onLine) {
|
|
17114
|
-
const projectsDir = import_path31.default.join(
|
|
17574
|
+
const projectsDir = import_path31.default.join(import_os28.default.homedir(), ".claude", "projects");
|
|
17115
17575
|
const result = emptyClaudeScan();
|
|
17116
|
-
if (!
|
|
17576
|
+
if (!import_fs31.default.existsSync(projectsDir)) return result;
|
|
17117
17577
|
let projDirs;
|
|
17118
17578
|
try {
|
|
17119
|
-
projDirs =
|
|
17579
|
+
projDirs = import_fs31.default.readdirSync(projectsDir);
|
|
17120
17580
|
} catch {
|
|
17121
17581
|
return result;
|
|
17122
17582
|
}
|
|
@@ -17140,7 +17600,7 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
|
|
|
17140
17600
|
}
|
|
17141
17601
|
function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
17142
17602
|
const canaryVals = safeCanaryScanValues();
|
|
17143
|
-
const tmpDir = import_path31.default.join(
|
|
17603
|
+
const tmpDir = import_path31.default.join(import_os28.default.homedir(), ".gemini", "tmp");
|
|
17144
17604
|
const result = {
|
|
17145
17605
|
filesScanned: 0,
|
|
17146
17606
|
sessions: 0,
|
|
@@ -17157,10 +17617,10 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
17157
17617
|
perSession: []
|
|
17158
17618
|
};
|
|
17159
17619
|
const dedup = emptyScanDedup();
|
|
17160
|
-
if (!
|
|
17620
|
+
if (!import_fs31.default.existsSync(tmpDir)) return result;
|
|
17161
17621
|
let slugDirs;
|
|
17162
17622
|
try {
|
|
17163
|
-
slugDirs =
|
|
17623
|
+
slugDirs = import_fs31.default.readdirSync(tmpDir);
|
|
17164
17624
|
} catch {
|
|
17165
17625
|
return result;
|
|
17166
17626
|
}
|
|
@@ -17168,22 +17628,22 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
17168
17628
|
for (const slug2 of slugDirs) {
|
|
17169
17629
|
const slugPath = import_path31.default.join(tmpDir, slug2);
|
|
17170
17630
|
try {
|
|
17171
|
-
if (!
|
|
17631
|
+
if (!import_fs31.default.statSync(slugPath).isDirectory()) continue;
|
|
17172
17632
|
} catch {
|
|
17173
17633
|
continue;
|
|
17174
17634
|
}
|
|
17175
17635
|
let projLabel = stripTerminalEscapes(slug2).slice(0, 40);
|
|
17176
17636
|
try {
|
|
17177
17637
|
projLabel = stripTerminalEscapes(
|
|
17178
|
-
|
|
17179
|
-
).replace(
|
|
17638
|
+
import_fs31.default.readFileSync(import_path31.default.join(slugPath, ".project_root"), "utf-8").trim()
|
|
17639
|
+
).replace(import_os28.default.homedir(), "~").slice(0, 40);
|
|
17180
17640
|
} catch {
|
|
17181
17641
|
}
|
|
17182
17642
|
const chatsDir = import_path31.default.join(slugPath, "chats");
|
|
17183
|
-
if (!
|
|
17643
|
+
if (!import_fs31.default.existsSync(chatsDir)) continue;
|
|
17184
17644
|
let chatFiles;
|
|
17185
17645
|
try {
|
|
17186
|
-
chatFiles =
|
|
17646
|
+
chatFiles = import_fs31.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json") || f.endsWith(".jsonl")).sort((a, b) => Number(b.endsWith(".jsonl")) - Number(a.endsWith(".jsonl")));
|
|
17187
17647
|
} catch {
|
|
17188
17648
|
continue;
|
|
17189
17649
|
}
|
|
@@ -17196,7 +17656,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
17196
17656
|
onProgress?.(result.filesScanned);
|
|
17197
17657
|
let raw;
|
|
17198
17658
|
try {
|
|
17199
|
-
raw =
|
|
17659
|
+
raw = import_fs31.default.readFileSync(import_path31.default.join(chatsDir, chatFile), "utf-8");
|
|
17200
17660
|
} catch {
|
|
17201
17661
|
continue;
|
|
17202
17662
|
}
|
|
@@ -17391,13 +17851,13 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
17391
17851
|
return result;
|
|
17392
17852
|
}
|
|
17393
17853
|
function antigravityBrainDirs() {
|
|
17394
|
-
return ["antigravity-cli", "antigravity-ide"].map((surface) => import_path31.default.join(
|
|
17854
|
+
return ["antigravity-cli", "antigravity-ide"].map((surface) => import_path31.default.join(import_os28.default.homedir(), ".gemini", surface, "brain")).filter((p) => import_fs31.default.existsSync(p));
|
|
17395
17855
|
}
|
|
17396
17856
|
function antigravityTranscriptPath(convPath) {
|
|
17397
17857
|
const logsDir = import_path31.default.join(convPath, ".system_generated", "logs");
|
|
17398
17858
|
for (const name of ["transcript_full.jsonl", "transcript.jsonl"]) {
|
|
17399
17859
|
const p = import_path31.default.join(logsDir, name);
|
|
17400
|
-
if (
|
|
17860
|
+
if (import_fs31.default.existsSync(p)) return p;
|
|
17401
17861
|
}
|
|
17402
17862
|
return null;
|
|
17403
17863
|
}
|
|
@@ -17426,14 +17886,14 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
17426
17886
|
for (const brainDir of brainDirs) {
|
|
17427
17887
|
let convDirs;
|
|
17428
17888
|
try {
|
|
17429
|
-
convDirs =
|
|
17889
|
+
convDirs = import_fs31.default.readdirSync(brainDir);
|
|
17430
17890
|
} catch {
|
|
17431
17891
|
continue;
|
|
17432
17892
|
}
|
|
17433
17893
|
for (const conv of convDirs) {
|
|
17434
17894
|
const convPath = import_path31.default.join(brainDir, conv);
|
|
17435
17895
|
try {
|
|
17436
|
-
if (!
|
|
17896
|
+
if (!import_fs31.default.statSync(convPath).isDirectory()) continue;
|
|
17437
17897
|
} catch {
|
|
17438
17898
|
continue;
|
|
17439
17899
|
}
|
|
@@ -17443,7 +17903,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
17443
17903
|
onProgress?.(result.filesScanned);
|
|
17444
17904
|
let raw;
|
|
17445
17905
|
try {
|
|
17446
|
-
raw =
|
|
17906
|
+
raw = import_fs31.default.readFileSync(transcriptFile, "utf-8");
|
|
17447
17907
|
} catch {
|
|
17448
17908
|
continue;
|
|
17449
17909
|
}
|
|
@@ -17511,7 +17971,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
17511
17971
|
result.bashCalls++;
|
|
17512
17972
|
const cwd = String(input.cwd ?? "");
|
|
17513
17973
|
if (cwd && projLabel === conv.slice(0, 8)) {
|
|
17514
|
-
projLabel = stripTerminalEscapes(cwd).replace(
|
|
17974
|
+
projLabel = stripTerminalEscapes(cwd).replace(import_os28.default.homedir(), "~").slice(0, 40);
|
|
17515
17975
|
}
|
|
17516
17976
|
}
|
|
17517
17977
|
const rawCmd = String(input.command ?? "").trimStart();
|
|
@@ -17623,7 +18083,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
17623
18083
|
}
|
|
17624
18084
|
function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
17625
18085
|
const canaryVals = safeCanaryScanValues();
|
|
17626
|
-
const sessionDir = import_path31.default.join(
|
|
18086
|
+
const sessionDir = import_path31.default.join(import_os28.default.homedir(), ".copilot", "session-state");
|
|
17627
18087
|
const result = {
|
|
17628
18088
|
filesScanned: 0,
|
|
17629
18089
|
sessions: 0,
|
|
@@ -17641,22 +18101,22 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
|
17641
18101
|
perSession: []
|
|
17642
18102
|
};
|
|
17643
18103
|
const dedup = emptyScanDedup();
|
|
17644
|
-
if (!
|
|
18104
|
+
if (!import_fs31.default.existsSync(sessionDir)) return result;
|
|
17645
18105
|
let sessionIds;
|
|
17646
18106
|
try {
|
|
17647
|
-
sessionIds =
|
|
18107
|
+
sessionIds = import_fs31.default.readdirSync(sessionDir);
|
|
17648
18108
|
} catch {
|
|
17649
18109
|
return result;
|
|
17650
18110
|
}
|
|
17651
18111
|
const ruleSources = buildRuleSources();
|
|
17652
18112
|
for (const sessionId of sessionIds) {
|
|
17653
18113
|
const eventsPath = import_path31.default.join(sessionDir, sessionId, "events.jsonl");
|
|
17654
|
-
if (!
|
|
18114
|
+
if (!import_fs31.default.existsSync(eventsPath)) continue;
|
|
17655
18115
|
result.filesScanned++;
|
|
17656
18116
|
onProgress?.(result.filesScanned);
|
|
17657
18117
|
let raw;
|
|
17658
18118
|
try {
|
|
17659
|
-
raw =
|
|
18119
|
+
raw = import_fs31.default.readFileSync(eventsPath, "utf-8");
|
|
17660
18120
|
} catch {
|
|
17661
18121
|
continue;
|
|
17662
18122
|
}
|
|
@@ -17680,7 +18140,7 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
|
17680
18140
|
if (ev.type === "session.start") {
|
|
17681
18141
|
const cwd = ev.data?.context?.cwd;
|
|
17682
18142
|
if (typeof cwd === "string" && cwd) {
|
|
17683
|
-
projLabel = stripTerminalEscapes(cwd).replace(
|
|
18143
|
+
projLabel = stripTerminalEscapes(cwd).replace(import_os28.default.homedir(), "~").slice(0, 40);
|
|
17684
18144
|
}
|
|
17685
18145
|
continue;
|
|
17686
18146
|
}
|
|
@@ -17858,7 +18318,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
17858
18318
|
onProgress?.(result.filesScanned);
|
|
17859
18319
|
let lines;
|
|
17860
18320
|
try {
|
|
17861
|
-
lines =
|
|
18321
|
+
lines = import_fs31.default.readFileSync(filePath, "utf-8").split("\n");
|
|
17862
18322
|
} catch {
|
|
17863
18323
|
continue;
|
|
17864
18324
|
}
|
|
@@ -17881,7 +18341,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
17881
18341
|
sessionId = String(payload["id"] ?? filePath);
|
|
17882
18342
|
startTime = String(payload["timestamp"] ?? "");
|
|
17883
18343
|
const cwd = String(payload["cwd"] ?? "");
|
|
17884
|
-
projLabel = stripTerminalEscapes(cwd.replace(
|
|
18344
|
+
projLabel = stripTerminalEscapes(cwd.replace(import_os28.default.homedir(), "~")).slice(0, 40);
|
|
17885
18345
|
continue;
|
|
17886
18346
|
}
|
|
17887
18347
|
if (entry.type === "event_msg" && payload["type"] === "user_message") {
|
|
@@ -18048,17 +18508,17 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
18048
18508
|
return result;
|
|
18049
18509
|
}
|
|
18050
18510
|
function scanShellConfig() {
|
|
18051
|
-
const home =
|
|
18511
|
+
const home = import_os28.default.homedir();
|
|
18052
18512
|
const configFiles = [".zshrc", ".bashrc", ".bash_profile", ".profile"].map(
|
|
18053
18513
|
(f) => import_path31.default.join(home, f)
|
|
18054
18514
|
);
|
|
18055
18515
|
const findings = [];
|
|
18056
18516
|
const seen = /* @__PURE__ */ new Set();
|
|
18057
18517
|
for (const filePath of configFiles) {
|
|
18058
|
-
if (!
|
|
18518
|
+
if (!import_fs31.default.existsSync(filePath)) continue;
|
|
18059
18519
|
let lines;
|
|
18060
18520
|
try {
|
|
18061
|
-
lines =
|
|
18521
|
+
lines = import_fs31.default.readFileSync(filePath, "utf-8").split("\n");
|
|
18062
18522
|
} catch {
|
|
18063
18523
|
continue;
|
|
18064
18524
|
}
|
|
@@ -19203,15 +19663,15 @@ function registerScanCommand(program2) {
|
|
|
19203
19663
|
}
|
|
19204
19664
|
);
|
|
19205
19665
|
}
|
|
19206
|
-
var import_chalk6,
|
|
19666
|
+
var import_chalk6, import_fs31, import_path31, import_os28, import_string_width2, toolInspectionMap, CODE_EXTENSIONS, SELF_OUTPUT_MARKERS, LOOP_TOOLS, LOOP_THRESHOLD, LOOP_TIMESPAN_THRESHOLD_MS, STUCK_TOOLS_MIN_WASTE, STUCK_TOOLS_LIMIT, RECURRING_SESSION_THRESHOLD, STALE_AGE_DAYS, classifyRuleSeverity2, narrativeRuleLabel2;
|
|
19207
19667
|
var init_scan = __esm({
|
|
19208
19668
|
"src/cli/commands/scan.ts"() {
|
|
19209
19669
|
"use strict";
|
|
19210
19670
|
init_keyed_guard();
|
|
19211
19671
|
import_chalk6 = __toESM(require("chalk"));
|
|
19212
|
-
|
|
19672
|
+
import_fs31 = __toESM(require("fs"));
|
|
19213
19673
|
import_path31 = __toESM(require("path"));
|
|
19214
|
-
|
|
19674
|
+
import_os28 = __toESM(require("os"));
|
|
19215
19675
|
init_shields();
|
|
19216
19676
|
init_config();
|
|
19217
19677
|
init_policy();
|
|
@@ -19296,7 +19756,7 @@ var init_scan = __esm({
|
|
|
19296
19756
|
function readOwnVersion() {
|
|
19297
19757
|
for (const rel of ["../package.json", "../../package.json"]) {
|
|
19298
19758
|
try {
|
|
19299
|
-
const raw =
|
|
19759
|
+
const raw = import_fs32.default.readFileSync(import_path32.default.join(__dirname, rel), "utf-8");
|
|
19300
19760
|
const v = JSON.parse(raw).version;
|
|
19301
19761
|
if (typeof v === "string" && v.length > 0) return v;
|
|
19302
19762
|
} catch {
|
|
@@ -19307,7 +19767,7 @@ function readOwnVersion() {
|
|
|
19307
19767
|
function computeBuildId(entry = process.argv[1] ?? "") {
|
|
19308
19768
|
let mtimeMs = 0;
|
|
19309
19769
|
try {
|
|
19310
|
-
if (entry) mtimeMs =
|
|
19770
|
+
if (entry) mtimeMs = import_fs32.default.statSync(entry).mtimeMs;
|
|
19311
19771
|
} catch {
|
|
19312
19772
|
}
|
|
19313
19773
|
return { version: readOwnVersion(), mtimeMs };
|
|
@@ -19349,11 +19809,11 @@ function describeBuildDrift(running, installed) {
|
|
|
19349
19809
|
const theirVersion = typeof running.version === "string" ? running.version : "unknown";
|
|
19350
19810
|
return `running daemon is v${theirVersion} (build ${theirs}) but installed is v${installed.version} (build ${mine}) \u2014 it is enforcing a different build`;
|
|
19351
19811
|
}
|
|
19352
|
-
var
|
|
19812
|
+
var import_fs32, import_path32, CURRENT_BUILD;
|
|
19353
19813
|
var init_build_id = __esm({
|
|
19354
19814
|
"src/daemon/build-id.ts"() {
|
|
19355
19815
|
"use strict";
|
|
19356
|
-
|
|
19816
|
+
import_fs32 = __toESM(require("fs"));
|
|
19357
19817
|
import_path32 = __toESM(require("path"));
|
|
19358
19818
|
CURRENT_BUILD = parseBuildId(process.env.NODE9_BUILD_ID_OVERRIDE) ?? computeBuildId();
|
|
19359
19819
|
}
|
|
@@ -19450,11 +19910,11 @@ var init_suggestion_tracker = __esm({
|
|
|
19450
19910
|
});
|
|
19451
19911
|
|
|
19452
19912
|
// src/daemon/taint-store.ts
|
|
19453
|
-
var
|
|
19913
|
+
var import_fs33, import_path33, DEFAULT_TTL_MS, TaintStore, SESSION_TAINT_TTL_MS, SessionTaintStore;
|
|
19454
19914
|
var init_taint_store = __esm({
|
|
19455
19915
|
"src/daemon/taint-store.ts"() {
|
|
19456
19916
|
"use strict";
|
|
19457
|
-
|
|
19917
|
+
import_fs33 = __toESM(require("fs"));
|
|
19458
19918
|
import_path33 = __toESM(require("path"));
|
|
19459
19919
|
DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
19460
19920
|
TaintStore = class {
|
|
@@ -19521,7 +19981,7 @@ var init_taint_store = __esm({
|
|
|
19521
19981
|
/** Resolve to absolute path, falling back to path.resolve if file doesn't exist yet. */
|
|
19522
19982
|
_resolve(filePath) {
|
|
19523
19983
|
try {
|
|
19524
|
-
return
|
|
19984
|
+
return import_fs33.default.realpathSync.native(import_path33.default.resolve(filePath));
|
|
19525
19985
|
} catch {
|
|
19526
19986
|
return import_path33.default.resolve(filePath);
|
|
19527
19987
|
}
|
|
@@ -19689,8 +20149,8 @@ var init_session_history = __esm({
|
|
|
19689
20149
|
// src/daemon/state.ts
|
|
19690
20150
|
function loadInsightCounts() {
|
|
19691
20151
|
try {
|
|
19692
|
-
if (!
|
|
19693
|
-
const data = JSON.parse(
|
|
20152
|
+
if (!import_fs34.default.existsSync(INSIGHT_COUNTS_FILE)) return;
|
|
20153
|
+
const data = JSON.parse(import_fs34.default.readFileSync(INSIGHT_COUNTS_FILE, "utf-8"));
|
|
19694
20154
|
for (const [tool, count] of Object.entries(data)) {
|
|
19695
20155
|
if (typeof count === "number" && count > 0) insightCounts.set(tool, count);
|
|
19696
20156
|
}
|
|
@@ -19747,15 +20207,15 @@ function appendAuditLog(data) {
|
|
|
19747
20207
|
source: "daemon"
|
|
19748
20208
|
};
|
|
19749
20209
|
const dir = import_path34.default.dirname(AUDIT_LOG_FILE);
|
|
19750
|
-
if (!
|
|
19751
|
-
|
|
20210
|
+
if (!import_fs34.default.existsSync(dir)) import_fs34.default.mkdirSync(dir, { recursive: true });
|
|
20211
|
+
import_fs34.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
|
|
19752
20212
|
} catch {
|
|
19753
20213
|
}
|
|
19754
20214
|
}
|
|
19755
20215
|
function getAuditHistory(limit = 20) {
|
|
19756
20216
|
try {
|
|
19757
|
-
if (!
|
|
19758
|
-
const lines =
|
|
20217
|
+
if (!import_fs34.default.existsSync(AUDIT_LOG_FILE)) return [];
|
|
20218
|
+
const lines = import_fs34.default.readFileSync(AUDIT_LOG_FILE, "utf-8").trim().split("\n");
|
|
19759
20219
|
if (lines.length === 1 && lines[0] === "") return [];
|
|
19760
20220
|
return lines.slice(-limit).map((l) => JSON.parse(l)).reverse();
|
|
19761
20221
|
} catch {
|
|
@@ -19764,7 +20224,7 @@ function getAuditHistory(limit = 20) {
|
|
|
19764
20224
|
}
|
|
19765
20225
|
function getOrgName() {
|
|
19766
20226
|
try {
|
|
19767
|
-
if (
|
|
20227
|
+
if (import_fs34.default.existsSync(CREDENTIALS_FILE)) return "Node9 Cloud";
|
|
19768
20228
|
} catch {
|
|
19769
20229
|
}
|
|
19770
20230
|
return null;
|
|
@@ -19772,8 +20232,8 @@ function getOrgName() {
|
|
|
19772
20232
|
function writeGlobalSetting(key, value) {
|
|
19773
20233
|
let config = {};
|
|
19774
20234
|
try {
|
|
19775
|
-
if (
|
|
19776
|
-
config = JSON.parse(
|
|
20235
|
+
if (import_fs34.default.existsSync(GLOBAL_CONFIG_FILE)) {
|
|
20236
|
+
config = JSON.parse(import_fs34.default.readFileSync(GLOBAL_CONFIG_FILE, "utf-8"));
|
|
19777
20237
|
}
|
|
19778
20238
|
} catch {
|
|
19779
20239
|
}
|
|
@@ -19785,8 +20245,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
|
|
|
19785
20245
|
try {
|
|
19786
20246
|
let trust = { entries: [] };
|
|
19787
20247
|
try {
|
|
19788
|
-
if (
|
|
19789
|
-
trust = JSON.parse(
|
|
20248
|
+
if (import_fs34.default.existsSync(TRUST_FILE2))
|
|
20249
|
+
trust = JSON.parse(import_fs34.default.readFileSync(TRUST_FILE2, "utf-8"));
|
|
19790
20250
|
} catch {
|
|
19791
20251
|
}
|
|
19792
20252
|
trust.entries = trust.entries.filter(
|
|
@@ -19803,8 +20263,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
|
|
|
19803
20263
|
}
|
|
19804
20264
|
function readPersistentDecisions() {
|
|
19805
20265
|
try {
|
|
19806
|
-
if (
|
|
19807
|
-
return JSON.parse(
|
|
20266
|
+
if (import_fs34.default.existsSync(DECISIONS_FILE)) {
|
|
20267
|
+
return JSON.parse(import_fs34.default.readFileSync(DECISIONS_FILE, "utf-8"));
|
|
19808
20268
|
}
|
|
19809
20269
|
} catch {
|
|
19810
20270
|
}
|
|
@@ -19832,7 +20292,7 @@ function estimateToolCost(tool, args) {
|
|
|
19832
20292
|
const filePath = a.file_path ?? a.path;
|
|
19833
20293
|
if (filePath) {
|
|
19834
20294
|
try {
|
|
19835
|
-
const bytes =
|
|
20295
|
+
const bytes = import_fs34.default.statSync(filePath).size;
|
|
19836
20296
|
return bytes / BYTES_PER_TOKEN / 1e6 * INPUT_PRICE_PER_1M;
|
|
19837
20297
|
} catch {
|
|
19838
20298
|
}
|
|
@@ -19906,7 +20366,7 @@ function abandonPending() {
|
|
|
19906
20366
|
});
|
|
19907
20367
|
if (autoStarted) {
|
|
19908
20368
|
try {
|
|
19909
|
-
|
|
20369
|
+
import_fs34.default.unlinkSync(DAEMON_PID_FILE);
|
|
19910
20370
|
} catch {
|
|
19911
20371
|
}
|
|
19912
20372
|
setTimeout(() => {
|
|
@@ -19917,7 +20377,7 @@ function abandonPending() {
|
|
|
19917
20377
|
}
|
|
19918
20378
|
function logActivitySocket(msg) {
|
|
19919
20379
|
try {
|
|
19920
|
-
|
|
20380
|
+
import_fs34.default.appendFileSync(
|
|
19921
20381
|
import_path34.default.join(homeDir, ".node9", "hook-debug.log"),
|
|
19922
20382
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] [activity-socket] ${msg}
|
|
19923
20383
|
`
|
|
@@ -19940,13 +20400,13 @@ function shouldRebind(now = Date.now()) {
|
|
|
19940
20400
|
function startActivitySocket() {
|
|
19941
20401
|
bindActivitySocket();
|
|
19942
20402
|
activityHealthInterval = setInterval(() => {
|
|
19943
|
-
if (!
|
|
20403
|
+
if (!import_fs34.default.existsSync(ACTIVITY_SOCKET_PATH2)) attemptRebind("health-probe");
|
|
19944
20404
|
}, ACTIVITY_HEALTH_PROBE_MS);
|
|
19945
20405
|
activityHealthInterval.unref();
|
|
19946
20406
|
process.on("exit", () => {
|
|
19947
20407
|
if (activityHealthInterval) clearInterval(activityHealthInterval);
|
|
19948
20408
|
try {
|
|
19949
|
-
|
|
20409
|
+
import_fs34.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
|
|
19950
20410
|
} catch {
|
|
19951
20411
|
}
|
|
19952
20412
|
});
|
|
@@ -19974,7 +20434,7 @@ function attemptRebind(reason) {
|
|
|
19974
20434
|
}
|
|
19975
20435
|
function bindActivitySocket() {
|
|
19976
20436
|
try {
|
|
19977
|
-
|
|
20437
|
+
import_fs34.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
|
|
19978
20438
|
} catch {
|
|
19979
20439
|
}
|
|
19980
20440
|
const ACTIVITY_MAX_BYTES = 1024 * 1024;
|
|
@@ -20068,14 +20528,14 @@ function bindActivitySocket() {
|
|
|
20068
20528
|
});
|
|
20069
20529
|
activitySocketServer = unixServer;
|
|
20070
20530
|
}
|
|
20071
|
-
var import_net2,
|
|
20531
|
+
var import_net2, import_fs34, import_path34, import_os29, import_crypto11, homeDir, DAEMON_PID_FILE, DECISIONS_FILE, AUDIT_LOG_FILE, TRUST_FILE2, GLOBAL_CONFIG_FILE, CREDENTIALS_FILE, INSIGHT_COUNTS_FILE, pending, sseClients, suggestionTracker, taintStore, sessionTaintStore, insightCounts, _abandonTimer, _hadBrowserClient, _daemonServer, daemonRejectionHandlerRegistered, AUTO_DENY_MS, TRUST_DURATIONS, autoStarted, ACTIVITY_SOCKET_PATH2, ACTIVITY_RING_SIZE, activityRing, LARGE_RESPONSE_RING_SIZE, largeResponseRing, cachedScanResult, cachedScanTs, SCAN_CACHE_TTL_MS, SECRET_KEY_RE, INPUT_PRICE_PER_1M, OUTPUT_PRICE_PER_1M, BYTES_PER_TOKEN, CRITICAL_FORENSIC_CATEGORIES, WRITE_TOOL_NAMES, ACTIVITY_REBIND_MAX_ATTEMPTS, ACTIVITY_REBIND_WINDOW_MS, ACTIVITY_HEALTH_PROBE_MS, activitySocketServer, activityHealthInterval, activityRebindAttempts, activityCircuitTripped;
|
|
20072
20532
|
var init_state2 = __esm({
|
|
20073
20533
|
"src/daemon/state.ts"() {
|
|
20074
20534
|
"use strict";
|
|
20075
20535
|
import_net2 = __toESM(require("net"));
|
|
20076
|
-
|
|
20536
|
+
import_fs34 = __toESM(require("fs"));
|
|
20077
20537
|
import_path34 = __toESM(require("path"));
|
|
20078
|
-
|
|
20538
|
+
import_os29 = __toESM(require("os"));
|
|
20079
20539
|
import_crypto11 = require("crypto");
|
|
20080
20540
|
init_daemon();
|
|
20081
20541
|
init_suggestion_tracker();
|
|
@@ -20083,7 +20543,7 @@ var init_state2 = __esm({
|
|
|
20083
20543
|
init_session_counters();
|
|
20084
20544
|
init_session_history();
|
|
20085
20545
|
init_atomic_write();
|
|
20086
|
-
homeDir =
|
|
20546
|
+
homeDir = import_os29.default.homedir();
|
|
20087
20547
|
DAEMON_PID_FILE = import_path34.default.join(homeDir, ".node9", "daemon.pid");
|
|
20088
20548
|
DECISIONS_FILE = import_path34.default.join(homeDir, ".node9", "decisions.json");
|
|
20089
20549
|
AUDIT_LOG_FILE = import_path34.default.join(homeDir, ".node9", "audit.log");
|
|
@@ -20108,7 +20568,7 @@ var init_state2 = __esm({
|
|
|
20108
20568
|
"2h": 2 * 60 * 6e4
|
|
20109
20569
|
};
|
|
20110
20570
|
autoStarted = process.env.NODE9_AUTO_STARTED === "1";
|
|
20111
|
-
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path34.default.join(
|
|
20571
|
+
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path34.default.join(import_os29.default.tmpdir(), "node9-activity.sock");
|
|
20112
20572
|
ACTIVITY_RING_SIZE = 100;
|
|
20113
20573
|
activityRing = [];
|
|
20114
20574
|
LARGE_RESPONSE_RING_SIZE = 20;
|
|
@@ -20161,7 +20621,7 @@ function safeRead(file) {
|
|
|
20161
20621
|
function candidateFiles(home, cwd) {
|
|
20162
20622
|
const files = /* @__PURE__ */ new Set();
|
|
20163
20623
|
try {
|
|
20164
|
-
for (const name of
|
|
20624
|
+
for (const name of import_fs35.default.readdirSync(cwd)) {
|
|
20165
20625
|
if (name === ".env" || name.startsWith(".env.")) files.add(import_path35.default.join(cwd, name));
|
|
20166
20626
|
}
|
|
20167
20627
|
} catch {
|
|
@@ -20191,7 +20651,7 @@ function plantedDecoyPaths() {
|
|
|
20191
20651
|
}
|
|
20192
20652
|
}
|
|
20193
20653
|
function checkSecrets(ctx) {
|
|
20194
|
-
const home = ctx.home ||
|
|
20654
|
+
const home = ctx.home || import_os30.default.homedir();
|
|
20195
20655
|
const findings = [];
|
|
20196
20656
|
const planted = plantedDecoyPaths();
|
|
20197
20657
|
const plaintext = [];
|
|
@@ -20227,7 +20687,7 @@ function checkSecrets(ctx) {
|
|
|
20227
20687
|
for (const file of credentialMaterial(home)) {
|
|
20228
20688
|
if (planted.has(file)) continue;
|
|
20229
20689
|
try {
|
|
20230
|
-
if (
|
|
20690
|
+
if (import_fs35.default.statSync(file).isFile()) {
|
|
20231
20691
|
creds.push(displayPath(file, home));
|
|
20232
20692
|
credPaths.push(file);
|
|
20233
20693
|
}
|
|
@@ -20261,13 +20721,13 @@ function checkSecrets(ctx) {
|
|
|
20261
20721
|
}
|
|
20262
20722
|
return findings;
|
|
20263
20723
|
}
|
|
20264
|
-
var
|
|
20724
|
+
var import_fs35, import_path35, import_os30, MAX_FILE_BYTES;
|
|
20265
20725
|
var init_secrets = __esm({
|
|
20266
20726
|
"src/posture/secrets.ts"() {
|
|
20267
20727
|
"use strict";
|
|
20268
|
-
|
|
20728
|
+
import_fs35 = __toESM(require("fs"));
|
|
20269
20729
|
import_path35 = __toESM(require("path"));
|
|
20270
|
-
|
|
20730
|
+
import_os30 = __toESM(require("os"));
|
|
20271
20731
|
init_dist();
|
|
20272
20732
|
init_agent_wiring();
|
|
20273
20733
|
init_registry();
|
|
@@ -20401,7 +20861,7 @@ var init_templates = __esm({
|
|
|
20401
20861
|
// src/posture/egress.ts
|
|
20402
20862
|
function sandboxEgressWallActive() {
|
|
20403
20863
|
try {
|
|
20404
|
-
return
|
|
20864
|
+
return import_fs36.default.existsSync(ALLOWED_DOMAINS_PATH);
|
|
20405
20865
|
} catch {
|
|
20406
20866
|
return false;
|
|
20407
20867
|
}
|
|
@@ -20522,11 +20982,11 @@ function checkEgress(ctx) {
|
|
|
20522
20982
|
})
|
|
20523
20983
|
];
|
|
20524
20984
|
}
|
|
20525
|
-
var
|
|
20985
|
+
var import_fs36;
|
|
20526
20986
|
var init_egress = __esm({
|
|
20527
20987
|
"src/posture/egress.ts"() {
|
|
20528
20988
|
"use strict";
|
|
20529
|
-
|
|
20989
|
+
import_fs36 = __toESM(require("fs"));
|
|
20530
20990
|
init_config();
|
|
20531
20991
|
init_templates();
|
|
20532
20992
|
}
|
|
@@ -20586,7 +21046,7 @@ function readServers(file, format, agent) {
|
|
|
20586
21046
|
const capped = readCappedText(file, MAX_CONFIG_BYTES);
|
|
20587
21047
|
if (!capped || capped.truncated) return [];
|
|
20588
21048
|
const text = capped.text;
|
|
20589
|
-
const map = format === "toml" ? (0,
|
|
21049
|
+
const map = format === "toml" ? (0, import_smol_toml5.parse)(text)?.mcp_servers : JSON.parse(text)?.mcpServers;
|
|
20590
21050
|
if (!map || typeof map !== "object") return [];
|
|
20591
21051
|
return Object.entries(map).map(([name, v]) => ({
|
|
20592
21052
|
name,
|
|
@@ -20599,7 +21059,7 @@ function readServers(file, format, agent) {
|
|
|
20599
21059
|
}
|
|
20600
21060
|
}
|
|
20601
21061
|
function checkSupplyChain(ctx) {
|
|
20602
|
-
const home = ctx.home ||
|
|
21062
|
+
const home = ctx.home || import_os31.default.homedir();
|
|
20603
21063
|
const servers = [];
|
|
20604
21064
|
for (const spec of AGENT_SPECS) {
|
|
20605
21065
|
if (!spec.mcpFile) continue;
|
|
@@ -20639,13 +21099,13 @@ function checkSupplyChain(ctx) {
|
|
|
20639
21099
|
}
|
|
20640
21100
|
return findings;
|
|
20641
21101
|
}
|
|
20642
|
-
var
|
|
21102
|
+
var import_os31, import_path36, import_smol_toml5, PACKAGE_RUNNERS, MAX_CONFIG_BYTES;
|
|
20643
21103
|
var init_supply_chain = __esm({
|
|
20644
21104
|
"src/posture/supply-chain.ts"() {
|
|
20645
21105
|
"use strict";
|
|
20646
|
-
|
|
21106
|
+
import_os31 = __toESM(require("os"));
|
|
20647
21107
|
import_path36 = __toESM(require("path"));
|
|
20648
|
-
|
|
21108
|
+
import_smol_toml5 = require("smol-toml");
|
|
20649
21109
|
init_provenance();
|
|
20650
21110
|
init_agent_wiring();
|
|
20651
21111
|
init_read_capped();
|
|
@@ -20702,9 +21162,9 @@ var init_privilege = __esm({
|
|
|
20702
21162
|
|
|
20703
21163
|
// src/posture/containment.ts
|
|
20704
21164
|
function inContainer() {
|
|
20705
|
-
if (
|
|
21165
|
+
if (import_fs37.default.existsSync("/.dockerenv") || import_fs37.default.existsSync("/run/.containerenv")) return true;
|
|
20706
21166
|
try {
|
|
20707
|
-
const cgroup =
|
|
21167
|
+
const cgroup = import_fs37.default.readFileSync("/proc/1/cgroup", "utf8");
|
|
20708
21168
|
if (/docker|kubepods|containerd|lxc|libpod/.test(cgroup)) return true;
|
|
20709
21169
|
} catch {
|
|
20710
21170
|
}
|
|
@@ -20741,11 +21201,11 @@ Lighter \u2014 harden in place, keep full host access (about +${Math.round(
|
|
|
20741
21201
|
}
|
|
20742
21202
|
];
|
|
20743
21203
|
}
|
|
20744
|
-
var
|
|
21204
|
+
var import_fs37, ISOLATION_WEIGHT;
|
|
20745
21205
|
var init_containment = __esm({
|
|
20746
21206
|
"src/posture/containment.ts"() {
|
|
20747
21207
|
"use strict";
|
|
20748
|
-
|
|
21208
|
+
import_fs37 = __toESM(require("fs"));
|
|
20749
21209
|
ISOLATION_WEIGHT = 12;
|
|
20750
21210
|
}
|
|
20751
21211
|
});
|
|
@@ -20808,7 +21268,7 @@ function collectListeners() {
|
|
|
20808
21268
|
const byPort = /* @__PURE__ */ new Map();
|
|
20809
21269
|
for (const file of ["/proc/net/tcp", "/proc/net/tcp6"]) {
|
|
20810
21270
|
try {
|
|
20811
|
-
for (const l of parseListeners(
|
|
21271
|
+
for (const l of parseListeners(import_fs38.default.readFileSync(file, "utf8"))) {
|
|
20812
21272
|
if (!byPort.has(l.port)) byPort.set(l.port, l);
|
|
20813
21273
|
}
|
|
20814
21274
|
} catch {
|
|
@@ -20820,11 +21280,11 @@ function readProc(pid) {
|
|
|
20820
21280
|
let comm = "unknown";
|
|
20821
21281
|
let cmdline = "";
|
|
20822
21282
|
try {
|
|
20823
|
-
comm =
|
|
21283
|
+
comm = import_fs38.default.readFileSync(`/proc/${pid}/comm`, "utf8").trim().replace(/-MainThread$/, "") || "unknown";
|
|
20824
21284
|
} catch {
|
|
20825
21285
|
}
|
|
20826
21286
|
try {
|
|
20827
|
-
cmdline =
|
|
21287
|
+
cmdline = import_fs38.default.readFileSync(`/proc/${pid}/cmdline`).toString().replace(/\0/g, " ").trim();
|
|
20828
21288
|
} catch {
|
|
20829
21289
|
}
|
|
20830
21290
|
return { comm, cmdline };
|
|
@@ -20834,21 +21294,21 @@ function resolveProcesses(inodes) {
|
|
|
20834
21294
|
if (inodes.size === 0) return map;
|
|
20835
21295
|
let pids;
|
|
20836
21296
|
try {
|
|
20837
|
-
pids =
|
|
21297
|
+
pids = import_fs38.default.readdirSync("/proc").filter((d) => /^\d+$/.test(d));
|
|
20838
21298
|
} catch {
|
|
20839
21299
|
return map;
|
|
20840
21300
|
}
|
|
20841
21301
|
for (const pid of pids) {
|
|
20842
21302
|
let fds;
|
|
20843
21303
|
try {
|
|
20844
|
-
fds =
|
|
21304
|
+
fds = import_fs38.default.readdirSync(`/proc/${pid}/fd`);
|
|
20845
21305
|
} catch {
|
|
20846
21306
|
continue;
|
|
20847
21307
|
}
|
|
20848
21308
|
for (const fd of fds) {
|
|
20849
21309
|
let link;
|
|
20850
21310
|
try {
|
|
20851
|
-
link =
|
|
21311
|
+
link = import_fs38.default.readlinkSync(`/proc/${pid}/fd/${fd}`);
|
|
20852
21312
|
} catch {
|
|
20853
21313
|
continue;
|
|
20854
21314
|
}
|
|
@@ -20916,11 +21376,11 @@ function checkInbound(ctx) {
|
|
|
20916
21376
|
}
|
|
20917
21377
|
return findings;
|
|
20918
21378
|
}
|
|
20919
|
-
var
|
|
21379
|
+
var import_fs38, DB_EXPOSURE_WEIGHT, KNOWN_SERVICE_PORTS, KNOWN_SERVICE_COMMS, DB_LABEL, SHIELD_FOR_SERVICE;
|
|
20920
21380
|
var init_inbound = __esm({
|
|
20921
21381
|
"src/posture/inbound.ts"() {
|
|
20922
21382
|
"use strict";
|
|
20923
|
-
|
|
21383
|
+
import_fs38 = __toESM(require("fs"));
|
|
20924
21384
|
DB_EXPOSURE_WEIGHT = 4;
|
|
20925
21385
|
KNOWN_SERVICE_PORTS = {
|
|
20926
21386
|
5432: "PostgreSQL",
|
|
@@ -20955,7 +21415,7 @@ var init_inbound = __esm({
|
|
|
20955
21415
|
|
|
20956
21416
|
// src/posture/coverage.ts
|
|
20957
21417
|
function checkCoverage(ctx) {
|
|
20958
|
-
const home = ctx.home ||
|
|
21418
|
+
const home = ctx.home || import_os32.default.homedir();
|
|
20959
21419
|
const findings = [];
|
|
20960
21420
|
const protectedAgents = getAgentWiring(home).filter((r) => r.isProtected);
|
|
20961
21421
|
if (protectedAgents.length === 0) {
|
|
@@ -20988,11 +21448,11 @@ function checkCoverage(ctx) {
|
|
|
20988
21448
|
}
|
|
20989
21449
|
return findings;
|
|
20990
21450
|
}
|
|
20991
|
-
var
|
|
21451
|
+
var import_os32;
|
|
20992
21452
|
var init_coverage = __esm({
|
|
20993
21453
|
"src/posture/coverage.ts"() {
|
|
20994
21454
|
"use strict";
|
|
20995
|
-
|
|
21455
|
+
import_os32 = __toESM(require("os"));
|
|
20996
21456
|
init_config();
|
|
20997
21457
|
init_agent_wiring();
|
|
20998
21458
|
}
|
|
@@ -21344,7 +21804,7 @@ async function runChecks(checks, ctx) {
|
|
|
21344
21804
|
}
|
|
21345
21805
|
async function runPosture(opts = {}) {
|
|
21346
21806
|
const ctx = {
|
|
21347
|
-
home: opts.home ??
|
|
21807
|
+
home: opts.home ?? import_os33.default.homedir(),
|
|
21348
21808
|
cwd: opts.cwd ?? process.cwd(),
|
|
21349
21809
|
agent: opts.agent
|
|
21350
21810
|
};
|
|
@@ -21370,11 +21830,11 @@ async function runPosture(opts = {}) {
|
|
|
21370
21830
|
checksRun: POSTURE_CHECKS.length
|
|
21371
21831
|
};
|
|
21372
21832
|
}
|
|
21373
|
-
var
|
|
21833
|
+
var import_os33, POSTURE_CHECKS;
|
|
21374
21834
|
var init_posture = __esm({
|
|
21375
21835
|
"src/posture/index.ts"() {
|
|
21376
21836
|
"use strict";
|
|
21377
|
-
|
|
21837
|
+
import_os33 = __toESM(require("os"));
|
|
21378
21838
|
init_secrets();
|
|
21379
21839
|
init_egress();
|
|
21380
21840
|
init_gate();
|
|
@@ -21573,49 +22033,6 @@ var init_build2 = __esm({
|
|
|
21573
22033
|
}
|
|
21574
22034
|
});
|
|
21575
22035
|
|
|
21576
|
-
// src/mcp-cmd.ts
|
|
21577
|
-
function tokenize4(cmd) {
|
|
21578
|
-
const tokens = [];
|
|
21579
|
-
let current = "";
|
|
21580
|
-
let inDouble = false;
|
|
21581
|
-
let quoted = false;
|
|
21582
|
-
let i = 0;
|
|
21583
|
-
while (i < cmd.length) {
|
|
21584
|
-
const ch = cmd[i];
|
|
21585
|
-
if (inDouble) {
|
|
21586
|
-
if (ch === '"') inDouble = false;
|
|
21587
|
-
else if (ch === "\\" && i + 1 < cmd.length) current += cmd[++i];
|
|
21588
|
-
else current += ch;
|
|
21589
|
-
} else if (ch === '"') {
|
|
21590
|
-
inDouble = true;
|
|
21591
|
-
quoted = true;
|
|
21592
|
-
} else if (ch === " " || ch === " ") {
|
|
21593
|
-
if (current || quoted) {
|
|
21594
|
-
tokens.push(current);
|
|
21595
|
-
current = "";
|
|
21596
|
-
quoted = false;
|
|
21597
|
-
}
|
|
21598
|
-
} else if (ch === "\\" && i + 1 < cmd.length) {
|
|
21599
|
-
current += cmd[++i];
|
|
21600
|
-
} else {
|
|
21601
|
-
current += ch;
|
|
21602
|
-
}
|
|
21603
|
-
i++;
|
|
21604
|
-
}
|
|
21605
|
-
if (current || quoted && !inDouble) tokens.push(current);
|
|
21606
|
-
return tokens;
|
|
21607
|
-
}
|
|
21608
|
-
function quoteArg(s) {
|
|
21609
|
-
if (s === "") return '""';
|
|
21610
|
-
if (/[\s"\\]/.test(s)) return `"${s.replace(/(["\\])/g, "\\$1")}"`;
|
|
21611
|
-
return s;
|
|
21612
|
-
}
|
|
21613
|
-
var init_mcp_cmd = __esm({
|
|
21614
|
-
"src/mcp-cmd.ts"() {
|
|
21615
|
-
"use strict";
|
|
21616
|
-
}
|
|
21617
|
-
});
|
|
21618
|
-
|
|
21619
22036
|
// src/daemon/mcp-tools.ts
|
|
21620
22037
|
function deriveServerName(cmd) {
|
|
21621
22038
|
if (!cmd || typeof cmd !== "string") return "MCP Server";
|
|
@@ -21642,13 +22059,13 @@ function deriveServerName(cmd) {
|
|
|
21642
22059
|
return strip(base) || "MCP Server";
|
|
21643
22060
|
}
|
|
21644
22061
|
function getMcpToolsFile() {
|
|
21645
|
-
return import_path38.default.join(
|
|
22062
|
+
return import_path38.default.join(import_os34.default.homedir(), ".node9", "mcp-tools.json");
|
|
21646
22063
|
}
|
|
21647
22064
|
function readMcpToolsConfig() {
|
|
21648
22065
|
try {
|
|
21649
22066
|
const file = getMcpToolsFile();
|
|
21650
|
-
if (!
|
|
21651
|
-
const raw =
|
|
22067
|
+
if (!import_fs39.default.existsSync(file)) return {};
|
|
22068
|
+
const raw = import_fs39.default.readFileSync(file, "utf-8");
|
|
21652
22069
|
return JSON.parse(raw);
|
|
21653
22070
|
} catch {
|
|
21654
22071
|
return {};
|
|
@@ -21658,10 +22075,10 @@ function writeMcpToolsConfig(config) {
|
|
|
21658
22075
|
try {
|
|
21659
22076
|
const file = getMcpToolsFile();
|
|
21660
22077
|
const dir = import_path38.default.dirname(file);
|
|
21661
|
-
if (!
|
|
21662
|
-
const tmpPath = `${file}.${
|
|
21663
|
-
|
|
21664
|
-
|
|
22078
|
+
if (!import_fs39.default.existsSync(dir)) import_fs39.default.mkdirSync(dir, { recursive: true });
|
|
22079
|
+
const tmpPath = `${file}.${import_os34.default.hostname()}.${process.pid}.tmp`;
|
|
22080
|
+
import_fs39.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2));
|
|
22081
|
+
import_fs39.default.renameSync(tmpPath, file);
|
|
21665
22082
|
} catch (e) {
|
|
21666
22083
|
console.error("Failed to write mcp-tools.json", e);
|
|
21667
22084
|
}
|
|
@@ -21708,117 +22125,13 @@ function approveServer(serverKey, disabledTools) {
|
|
|
21708
22125
|
writeMcpToolsConfig(config);
|
|
21709
22126
|
}
|
|
21710
22127
|
}
|
|
21711
|
-
var
|
|
22128
|
+
var import_fs39, import_path38, import_os34;
|
|
21712
22129
|
var init_mcp_tools = __esm({
|
|
21713
22130
|
"src/daemon/mcp-tools.ts"() {
|
|
21714
|
-
"use strict";
|
|
21715
|
-
import_fs38 = __toESM(require("fs"));
|
|
21716
|
-
import_path38 = __toESM(require("path"));
|
|
21717
|
-
import_os33 = __toESM(require("os"));
|
|
21718
|
-
init_mcp_cmd();
|
|
21719
|
-
}
|
|
21720
|
-
});
|
|
21721
|
-
|
|
21722
|
-
// src/mcp-wrap.ts
|
|
21723
|
-
function isNode9Command(command) {
|
|
21724
|
-
return /(^|[\\/])node9(\.(exe|cmd|ps1|bat))?$/i.test(command ?? "");
|
|
21725
|
-
}
|
|
21726
|
-
function classifyMcp(s) {
|
|
21727
|
-
if (isNode9Command(s.command)) {
|
|
21728
|
-
return (s.args ?? [])[0] === "mcp-gateway" ? "gatewayed" : "node9-self";
|
|
21729
|
-
}
|
|
21730
|
-
if (typeof s.command !== "string" || s.command.trim() === "") return "remote";
|
|
21731
|
-
return "ungoverned";
|
|
21732
|
-
}
|
|
21733
|
-
function toGateway(s, configName) {
|
|
21734
|
-
const upstream = [s.command ?? "", ...s.args ?? []].map(quoteArg).join(" ");
|
|
21735
|
-
const nameArgs = configName && !configName.startsWith("-") ? ["--config-name", configName] : [];
|
|
21736
|
-
return {
|
|
21737
|
-
...s,
|
|
21738
|
-
command: "node9",
|
|
21739
|
-
args: ["mcp-gateway", ...nameArgs, "--upstream", upstream]
|
|
21740
|
-
};
|
|
21741
|
-
}
|
|
21742
|
-
function fromGateway(s) {
|
|
21743
|
-
if (!isNode9Command(s.command) || (s.args ?? [])[0] !== "mcp-gateway") return null;
|
|
21744
|
-
const args = s.args ?? [];
|
|
21745
|
-
const i = args.indexOf("--upstream");
|
|
21746
|
-
if (i < 0 || !args[i + 1]) return null;
|
|
21747
|
-
const [command, ...rest] = tokenize4(args[i + 1]);
|
|
21748
|
-
if (!command) return null;
|
|
21749
|
-
return { ...s, command, args: rest };
|
|
21750
|
-
}
|
|
21751
|
-
function inventoryMcp(home = import_os34.default.homedir()) {
|
|
21752
|
-
const out = [];
|
|
21753
|
-
for (const spec of AGENT_SPECS) {
|
|
21754
|
-
if (!spec.mcpFile) continue;
|
|
21755
|
-
const mcpFile = spec.mcpFile(home);
|
|
21756
|
-
const format = spec.mcpFormat ?? "json";
|
|
21757
|
-
const servers = readMcpServers(mcpFile, format);
|
|
21758
|
-
for (const [name, s] of Object.entries(servers)) {
|
|
21759
|
-
if (!s || typeof s !== "object") continue;
|
|
21760
|
-
out.push({
|
|
21761
|
-
agent: String(spec.id),
|
|
21762
|
-
agentLabel: spec.label,
|
|
21763
|
-
mcpFile,
|
|
21764
|
-
format,
|
|
21765
|
-
name,
|
|
21766
|
-
command: s.command ?? "",
|
|
21767
|
-
args: Array.isArray(s.args) ? s.args : [],
|
|
21768
|
-
state: classifyMcp(s),
|
|
21769
|
-
raw: s
|
|
21770
|
-
});
|
|
21771
|
-
}
|
|
21772
|
-
}
|
|
21773
|
-
return out;
|
|
21774
|
-
}
|
|
21775
|
-
function inventoryServerKeys(inv) {
|
|
21776
|
-
const keys = /* @__PURE__ */ new Set();
|
|
21777
|
-
for (const e of inv) {
|
|
21778
|
-
if (e.state === "gatewayed") {
|
|
21779
|
-
const i = e.args.indexOf("--upstream");
|
|
21780
|
-
if (i >= 0 && e.args[i + 1]) {
|
|
21781
|
-
keys.add(getServerKey(e.args[i + 1]));
|
|
21782
|
-
}
|
|
21783
|
-
} else if (e.state === "ungoverned") {
|
|
21784
|
-
const cmd = [e.command, ...e.args].map(quoteArg).join(" ");
|
|
21785
|
-
keys.add(getServerKey(cmd));
|
|
21786
|
-
}
|
|
21787
|
-
}
|
|
21788
|
-
return keys;
|
|
21789
|
-
}
|
|
21790
|
-
function writeMcpEntry(mcpFile, format, name, entry) {
|
|
21791
|
-
const key = format === "toml" ? "mcp_servers" : "mcpServers";
|
|
21792
|
-
let root = {};
|
|
21793
|
-
if (import_fs39.default.existsSync(mcpFile)) {
|
|
21794
|
-
const raw = import_fs39.default.readFileSync(mcpFile, "utf-8");
|
|
21795
|
-
root = format === "toml" ? (0, import_smol_toml5.parse)(raw) : JSON.parse(raw);
|
|
21796
|
-
const bak = `${mcpFile}.node9-bak`;
|
|
21797
|
-
try {
|
|
21798
|
-
import_fs39.default.writeFileSync(bak, raw, { mode: 384, flag: "wx" });
|
|
21799
|
-
} catch (e) {
|
|
21800
|
-
if (e.code !== "EEXIST") throw e;
|
|
21801
|
-
}
|
|
21802
|
-
}
|
|
21803
|
-
const existing = root[key];
|
|
21804
|
-
const servers = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
21805
|
-
servers[name] = entry;
|
|
21806
|
-
root[key] = servers;
|
|
21807
|
-
const serialized = format === "toml" ? (0, import_smol_toml5.stringify)(root) : JSON.stringify(root, null, 2);
|
|
21808
|
-
const tmp = `${mcpFile}.${process.pid}.tmp`;
|
|
21809
|
-
import_fs39.default.writeFileSync(tmp, serialized, { mode: 384 });
|
|
21810
|
-
import_fs39.default.renameSync(tmp, mcpFile);
|
|
21811
|
-
}
|
|
21812
|
-
var import_fs39, import_os34, import_smol_toml5;
|
|
21813
|
-
var init_mcp_wrap = __esm({
|
|
21814
|
-
"src/mcp-wrap.ts"() {
|
|
21815
22131
|
"use strict";
|
|
21816
22132
|
import_fs39 = __toESM(require("fs"));
|
|
22133
|
+
import_path38 = __toESM(require("path"));
|
|
21817
22134
|
import_os34 = __toESM(require("os"));
|
|
21818
|
-
import_smol_toml5 = require("smol-toml");
|
|
21819
|
-
init_agent_wiring();
|
|
21820
|
-
init_mcp_cmd();
|
|
21821
|
-
init_mcp_pin();
|
|
21822
22135
|
init_mcp_cmd();
|
|
21823
22136
|
}
|
|
21824
22137
|
});
|
|
@@ -52291,22 +52604,22 @@ init_hook_baseline();
|
|
|
52291
52604
|
init_agent_wiring();
|
|
52292
52605
|
|
|
52293
52606
|
// src/credentials.ts
|
|
52294
|
-
var
|
|
52295
|
-
var
|
|
52607
|
+
var fs22 = __toESM(require("fs"));
|
|
52608
|
+
var os19 = __toESM(require("os"));
|
|
52296
52609
|
var path22 = __toESM(require("path"));
|
|
52297
52610
|
init_config();
|
|
52298
52611
|
init_api_url();
|
|
52299
52612
|
function writeCredentialsAndConfig(apiKey, opts = {}) {
|
|
52300
52613
|
const profileName = opts.profileName || "default";
|
|
52301
|
-
const home = opts.homeDir ??
|
|
52614
|
+
const home = opts.homeDir ?? os19.homedir();
|
|
52302
52615
|
const credPath = path22.join(home, ".node9", "credentials.json");
|
|
52303
|
-
if (!
|
|
52304
|
-
|
|
52616
|
+
if (!fs22.existsSync(path22.dirname(credPath))) {
|
|
52617
|
+
fs22.mkdirSync(path22.dirname(credPath), { recursive: true });
|
|
52305
52618
|
}
|
|
52306
52619
|
let existingCreds = {};
|
|
52307
52620
|
try {
|
|
52308
|
-
if (
|
|
52309
|
-
const raw = JSON.parse(
|
|
52621
|
+
if (fs22.existsSync(credPath)) {
|
|
52622
|
+
const raw = JSON.parse(fs22.readFileSync(credPath, "utf-8"));
|
|
52310
52623
|
existingCreds = raw.apiKey ? { default: { apiKey: raw.apiKey, apiUrl: raw.apiUrl || DEFAULT_API_URL } } : raw;
|
|
52311
52624
|
}
|
|
52312
52625
|
} catch {
|
|
@@ -52316,7 +52629,7 @@ function writeCredentialsAndConfig(apiKey, opts = {}) {
|
|
|
52316
52629
|
apiUrl: DEFAULT_API_URL,
|
|
52317
52630
|
...opts.isLocal ? { localOnly: true } : {}
|
|
52318
52631
|
};
|
|
52319
|
-
|
|
52632
|
+
fs22.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), {
|
|
52320
52633
|
mode: 384
|
|
52321
52634
|
});
|
|
52322
52635
|
let effectiveCloud = null;
|
|
@@ -52324,8 +52637,8 @@ function writeCredentialsAndConfig(apiKey, opts = {}) {
|
|
|
52324
52637
|
const configPath = path22.join(home, ".node9", "config.json");
|
|
52325
52638
|
let config = {};
|
|
52326
52639
|
try {
|
|
52327
|
-
if (
|
|
52328
|
-
config = JSON.parse(
|
|
52640
|
+
if (fs22.existsSync(configPath)) {
|
|
52641
|
+
config = JSON.parse(fs22.readFileSync(configPath, "utf-8"));
|
|
52329
52642
|
}
|
|
52330
52643
|
} catch {
|
|
52331
52644
|
}
|
|
@@ -52340,10 +52653,10 @@ function writeCredentialsAndConfig(apiKey, opts = {}) {
|
|
|
52340
52653
|
terminal: typeof existing.terminal === "boolean" ? existing.terminal : d.terminal,
|
|
52341
52654
|
cloud: !opts.isLocal
|
|
52342
52655
|
};
|
|
52343
|
-
if (!
|
|
52344
|
-
|
|
52656
|
+
if (!fs22.existsSync(path22.dirname(configPath))) {
|
|
52657
|
+
fs22.mkdirSync(path22.dirname(configPath), { recursive: true });
|
|
52345
52658
|
}
|
|
52346
|
-
|
|
52659
|
+
fs22.writeFileSync(configPath, JSON.stringify(config, null, 2), {
|
|
52347
52660
|
mode: 384
|
|
52348
52661
|
});
|
|
52349
52662
|
effectiveCloud = !opts.isLocal;
|
|
@@ -56769,6 +57082,7 @@ function registerInitCommand(program2) {
|
|
|
56769
57082
|
var import_chalk21 = __toESM(require("chalk"));
|
|
56770
57083
|
var import_fs62 = __toESM(require("fs"));
|
|
56771
57084
|
init_agent_wiring();
|
|
57085
|
+
init_mcp_wrap();
|
|
56772
57086
|
init_setup();
|
|
56773
57087
|
init_hook_baseline();
|
|
56774
57088
|
var hasHookSurface = (a) => a.hooks.length > 0;
|
|
@@ -56778,8 +57092,28 @@ function backupForHeal(file) {
|
|
|
56778
57092
|
} catch {
|
|
56779
57093
|
}
|
|
56780
57094
|
}
|
|
57095
|
+
function reportCorruptedMcpWraps() {
|
|
57096
|
+
const corrupted = findCorruptedMcpWraps();
|
|
57097
|
+
if (corrupted.length === 0) return;
|
|
57098
|
+
console.log(
|
|
57099
|
+
import_chalk21.default.yellow(
|
|
57100
|
+
` \u26A0\uFE0F ${corrupted.length} MCP server(s) were corrupted by an older node9 and cannot start:`
|
|
57101
|
+
)
|
|
57102
|
+
);
|
|
57103
|
+
for (const c of corrupted) {
|
|
57104
|
+
console.log(import_chalk21.default.yellow(` \u2022 ${c.name} (${c.agentLabel})`));
|
|
57105
|
+
console.log(import_chalk21.default.gray(` ${c.mcpFile}`));
|
|
57106
|
+
console.log(import_chalk21.default.gray(` stored upstream: ${c.upstream}`));
|
|
57107
|
+
}
|
|
57108
|
+
console.log(
|
|
57109
|
+
import_chalk21.default.gray(
|
|
57110
|
+
"\n The original command lost its path separators, so node9 cannot recover it.\n Remove and re-add each server in the agent, then run `node9 init` to re-wrap.\n"
|
|
57111
|
+
)
|
|
57112
|
+
);
|
|
57113
|
+
}
|
|
56781
57114
|
async function runHeal(name) {
|
|
56782
57115
|
console.log(import_chalk21.default.cyan.bold("\n\u{1FA79} Node9 Heal\n"));
|
|
57116
|
+
reportCorruptedMcpWraps();
|
|
56783
57117
|
const baseline = loadHookBaseline();
|
|
56784
57118
|
const wiring = getAgentWiring();
|
|
56785
57119
|
let candidates2 = wiring.filter(
|