@node9/proxy 1.45.0 → 1.46.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 +984 -792
- package/dist/cli.mjs +958 -767
- package/dist/index.js +15 -1
- package/dist/index.mjs +15 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -240,8 +240,8 @@ function sanitizeConfig(raw) {
|
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
const lines = result.error.issues.map((issue) => {
|
|
243
|
-
const
|
|
244
|
-
return ` \u2022 ${
|
|
243
|
+
const path65 = issue.path.length > 0 ? issue.path.join(".") : "root";
|
|
244
|
+
return ` \u2022 ${path65}: ${issue.message}`;
|
|
245
245
|
});
|
|
246
246
|
return {
|
|
247
247
|
sanitized,
|
|
@@ -1357,9 +1357,9 @@ function matchesPattern(text, patterns) {
|
|
|
1357
1357
|
const withoutDotSlash = text.replace(/^\.\//, "");
|
|
1358
1358
|
return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
|
|
1359
1359
|
}
|
|
1360
|
-
function getNestedValue(obj,
|
|
1360
|
+
function getNestedValue(obj, path65) {
|
|
1361
1361
|
if (!obj || typeof obj !== "object") return null;
|
|
1362
|
-
const segments =
|
|
1362
|
+
const segments = path65.split(".");
|
|
1363
1363
|
for (const seg of segments) {
|
|
1364
1364
|
if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
|
|
1365
1365
|
}
|
|
@@ -1412,6 +1412,14 @@ function evaluateSmartConditions(args, rule) {
|
|
|
1412
1412
|
});
|
|
1413
1413
|
return mode === "any" ? results.some((r) => r) : results.every((r) => r);
|
|
1414
1414
|
}
|
|
1415
|
+
function resolvePinned(matches) {
|
|
1416
|
+
if (matches.length === 0) return void 0;
|
|
1417
|
+
const pinned = matches.filter((r) => r.pinned);
|
|
1418
|
+
if (pinned.length === 0) return matches[0];
|
|
1419
|
+
return pinned.reduce(
|
|
1420
|
+
(best, r) => VERDICT_RANK[r.verdict] > VERDICT_RANK[best.verdict] ? r : best
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1415
1423
|
function tokenize2(toolName) {
|
|
1416
1424
|
return toolName.toLowerCase().split(/[_.\-\s]+/).filter(Boolean);
|
|
1417
1425
|
}
|
|
@@ -1523,9 +1531,10 @@ async function evaluatePolicy(config, toolName, args, context = {}, hooks = {})
|
|
|
1523
1531
|
}
|
|
1524
1532
|
}
|
|
1525
1533
|
if (config.policy.smartRules.length > 0) {
|
|
1526
|
-
const
|
|
1534
|
+
const matches = config.policy.smartRules.filter(
|
|
1527
1535
|
(rule) => matchesPattern(toolName, rule.tool) && !(bashCommand !== null && rule.name && AST_FS_REGEX_RULES.has(rule.name)) && evaluateSmartConditions(args, rule)
|
|
1528
1536
|
);
|
|
1537
|
+
const matchedRule = resolvePinned(matches);
|
|
1529
1538
|
if (matchedRule) {
|
|
1530
1539
|
if (matchedRule.verdict === "allow")
|
|
1531
1540
|
return { decision: "allow", ruleName: matchedRule.name ?? matchedRule.tool };
|
|
@@ -2264,7 +2273,7 @@ function* stringValues(obj, depth = 0) {
|
|
|
2264
2273
|
}
|
|
2265
2274
|
for (const v of Object.values(obj)) yield* stringValues(v, depth + 1);
|
|
2266
2275
|
}
|
|
2267
|
-
var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto3, 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, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, 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, NET_BINARIES, VALUE_FLAGS, FS_OP_CACHE_MAX, fsOpCache, DEFAULT_EGRESS_ALLOWLIST, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, SQL_DML_KEYWORDS, 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, COST_PER_LOOP_ITER_USD, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, LONG_OUTPUT_THRESHOLD_BYTES, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, TERMINAL_ESCAPE_RE;
|
|
2276
|
+
var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto3, 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, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, FS_READ_TOOLS, 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, NET_BINARIES, VALUE_FLAGS, FS_OP_CACHE_MAX, fsOpCache, DEFAULT_EGRESS_ALLOWLIST, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, VERDICT_RANK, SQL_DML_KEYWORDS, 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, COST_PER_LOOP_ITER_USD, DESTRUCTIVE_OP_RE, SENSITIVE_PATH_RE, FILE_TOOLS, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, LONG_OUTPUT_THRESHOLD_BYTES, CANONICAL_EXTRACTOR_VERSION, DEDUPE_PREVIEW_LEN, TERMINAL_ESCAPE_RE, ENGINE_VERSION;
|
|
2268
2277
|
var init_dist = __esm({
|
|
2269
2278
|
"packages/policy-engine/dist/index.mjs"() {
|
|
2270
2279
|
"use strict";
|
|
@@ -3195,6 +3204,11 @@ var init_dist = __esm({
|
|
|
3195
3204
|
REGEX_CACHE_MAX = 500;
|
|
3196
3205
|
regexCache = /* @__PURE__ */ new Map();
|
|
3197
3206
|
FORBIDDEN_PATH_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
3207
|
+
VERDICT_RANK = {
|
|
3208
|
+
allow: 0,
|
|
3209
|
+
review: 1,
|
|
3210
|
+
block: 2
|
|
3211
|
+
};
|
|
3198
3212
|
SQL_DML_KEYWORDS = /* @__PURE__ */ new Set(["select", "insert", "update", "delete", "merge", "upsert"]);
|
|
3199
3213
|
aws_default = {
|
|
3200
3214
|
name: "aws",
|
|
@@ -3999,6 +4013,7 @@ var init_dist = __esm({
|
|
|
3999
4013
|
DEDUPE_PREVIEW_LEN = 120;
|
|
4000
4014
|
TERMINAL_ESCAPE_RE = // eslint-disable-next-line no-control-regex
|
|
4001
4015
|
/\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-_]|[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
|
|
4016
|
+
ENGINE_VERSION = "1.4.0";
|
|
4002
4017
|
}
|
|
4003
4018
|
});
|
|
4004
4019
|
|
|
@@ -9725,13 +9740,234 @@ var init_setup = __esm({
|
|
|
9725
9740
|
}
|
|
9726
9741
|
});
|
|
9727
9742
|
|
|
9743
|
+
// src/agent-wiring.ts
|
|
9744
|
+
function readJson2(filePath) {
|
|
9745
|
+
if (!import_fs14.default.existsSync(filePath)) return null;
|
|
9746
|
+
try {
|
|
9747
|
+
return JSON.parse(import_fs14.default.readFileSync(filePath, "utf-8"));
|
|
9748
|
+
} catch {
|
|
9749
|
+
return "invalid";
|
|
9750
|
+
}
|
|
9751
|
+
}
|
|
9752
|
+
function matchersHaveNode9Hook(matchers) {
|
|
9753
|
+
return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
|
|
9754
|
+
}
|
|
9755
|
+
function flatHaveNode9Hook(entries) {
|
|
9756
|
+
return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
|
|
9757
|
+
}
|
|
9758
|
+
function readHookRoot(filePath, format) {
|
|
9759
|
+
if (!import_fs14.default.existsSync(filePath)) return "absent";
|
|
9760
|
+
let raw;
|
|
9761
|
+
try {
|
|
9762
|
+
raw = import_fs14.default.readFileSync(filePath, "utf-8");
|
|
9763
|
+
} catch {
|
|
9764
|
+
return "absent";
|
|
9765
|
+
}
|
|
9766
|
+
try {
|
|
9767
|
+
const parsed = format === "yaml" ? yaml2.parse(raw) : JSON.parse(raw);
|
|
9768
|
+
return parsed?.hooks ?? {};
|
|
9769
|
+
} catch {
|
|
9770
|
+
return "invalid";
|
|
9771
|
+
}
|
|
9772
|
+
}
|
|
9773
|
+
function eventWired(root, ev, format) {
|
|
9774
|
+
const arr = root[ev.key];
|
|
9775
|
+
if (format === "matcher") return matchersHaveNode9Hook(arr);
|
|
9776
|
+
return flatHaveNode9Hook(arr);
|
|
9777
|
+
}
|
|
9778
|
+
function detectMcp(servers) {
|
|
9779
|
+
const entries = Object.entries(servers ?? {});
|
|
9780
|
+
const present = entries.some(([, s]) => s?.command === "node9");
|
|
9781
|
+
const wrapped = entries.filter(([, s]) => s?.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
|
|
9782
|
+
return { wrapped, present };
|
|
9783
|
+
}
|
|
9784
|
+
function readMcp(filePath, format) {
|
|
9785
|
+
if (!import_fs14.default.existsSync(filePath)) return { wrapped: [], present: false };
|
|
9786
|
+
try {
|
|
9787
|
+
if (format === "toml") {
|
|
9788
|
+
const parsed2 = (0, import_smol_toml2.parse)(import_fs14.default.readFileSync(filePath, "utf-8"));
|
|
9789
|
+
return detectMcp(parsed2?.mcp_servers);
|
|
9790
|
+
}
|
|
9791
|
+
const parsed = readJson2(filePath);
|
|
9792
|
+
if (parsed === null || parsed === "invalid") return { wrapped: [], present: false };
|
|
9793
|
+
return detectMcp(parsed.mcpServers);
|
|
9794
|
+
} catch {
|
|
9795
|
+
return { wrapped: [], present: false };
|
|
9796
|
+
}
|
|
9797
|
+
}
|
|
9798
|
+
function getAgentWiring(home = import_os13.default.homedir()) {
|
|
9799
|
+
const detected = detectAgents(home);
|
|
9800
|
+
return AGENT_SPECS.map((spec) => {
|
|
9801
|
+
const present = spec.present(home);
|
|
9802
|
+
const pad = spec.labelPad ?? DEFAULT_LABEL_PAD;
|
|
9803
|
+
let hooks;
|
|
9804
|
+
let wireState;
|
|
9805
|
+
let hookLabel;
|
|
9806
|
+
let settingsPath;
|
|
9807
|
+
if (spec.shimFile) {
|
|
9808
|
+
const shimWired = exists(spec.shimFile(home));
|
|
9809
|
+
hooks = [{ label: "node9 plugin (node9 check)", wired: shimWired }];
|
|
9810
|
+
wireState = shimWired ? "wired" : present ? "unwired" : "absent";
|
|
9811
|
+
hookLabel = "node9 plugin";
|
|
9812
|
+
settingsPath = spec.shimFile(home);
|
|
9813
|
+
} else {
|
|
9814
|
+
const root = spec.hookFile ? readHookRoot(spec.hookFile(home), spec.hookFormat) : "absent";
|
|
9815
|
+
const primary = spec.hookEvents[0];
|
|
9816
|
+
const rootPresent = root !== "absent" && root !== "invalid";
|
|
9817
|
+
hooks = spec.hookEvents.map((ev) => ({
|
|
9818
|
+
label: hookLabelOf(ev, pad),
|
|
9819
|
+
wired: rootPresent && eventWired(root, ev, spec.hookFormat)
|
|
9820
|
+
}));
|
|
9821
|
+
if (root === "absent") wireState = "absent";
|
|
9822
|
+
else if (root === "invalid") wireState = "invalid";
|
|
9823
|
+
else wireState = primary && eventWired(root, primary, spec.hookFormat) ? "wired" : "unwired";
|
|
9824
|
+
hookLabel = primary ? `${primary.key} hook` : "MCP proxy";
|
|
9825
|
+
settingsPath = spec.hookFile ? spec.hookFile(home) : spec.mcpFile ? spec.mcpFile(home) : "";
|
|
9826
|
+
}
|
|
9827
|
+
const mcp = spec.mcpFile ? readMcp(spec.mcpFile(home), spec.mcpFormat ?? "json") : null;
|
|
9828
|
+
const anyHookWired = hooks.some((h) => h.wired);
|
|
9829
|
+
return {
|
|
9830
|
+
id: spec.id,
|
|
9831
|
+
label: spec.label,
|
|
9832
|
+
setupCommand: spec.setupCommand,
|
|
9833
|
+
installed: detected[spec.id],
|
|
9834
|
+
present,
|
|
9835
|
+
hooks,
|
|
9836
|
+
wireState,
|
|
9837
|
+
hookLabel,
|
|
9838
|
+
settingsPath,
|
|
9839
|
+
configFormat: spec.hookFormat === "yaml" ? "YAML" : "JSON",
|
|
9840
|
+
mcpServers: mcp ? mcp.wrapped : null,
|
|
9841
|
+
mcpProtected: mcp ? mcp.present : false,
|
|
9842
|
+
isProtected: anyHookWired || (mcp?.present ?? false)
|
|
9843
|
+
};
|
|
9844
|
+
});
|
|
9845
|
+
}
|
|
9846
|
+
var import_fs14, import_path16, import_os13, yaml2, import_smol_toml2, exists, ck, lg, DEFAULT_LABEL_PAD, hookLabelOf, AGENT_SPECS;
|
|
9847
|
+
var init_agent_wiring = __esm({
|
|
9848
|
+
"src/agent-wiring.ts"() {
|
|
9849
|
+
"use strict";
|
|
9850
|
+
import_fs14 = __toESM(require("fs"));
|
|
9851
|
+
import_path16 = __toESM(require("path"));
|
|
9852
|
+
import_os13 = __toESM(require("os"));
|
|
9853
|
+
yaml2 = __toESM(require("yaml"));
|
|
9854
|
+
import_smol_toml2 = require("smol-toml");
|
|
9855
|
+
init_setup();
|
|
9856
|
+
exists = (p) => {
|
|
9857
|
+
try {
|
|
9858
|
+
return import_fs14.default.existsSync(p);
|
|
9859
|
+
} catch {
|
|
9860
|
+
return false;
|
|
9861
|
+
}
|
|
9862
|
+
};
|
|
9863
|
+
ck = (key) => ({ key, kind: "check" });
|
|
9864
|
+
lg = (key) => ({ key, kind: "log" });
|
|
9865
|
+
DEFAULT_LABEL_PAD = 11;
|
|
9866
|
+
hookLabelOf = (ev, pad) => `${ev.key.padEnd(pad)} (node9 ${ev.kind})`;
|
|
9867
|
+
AGENT_SPECS = [
|
|
9868
|
+
{
|
|
9869
|
+
id: "claude",
|
|
9870
|
+
label: "Claude Code",
|
|
9871
|
+
setupCommand: "node9 agents add claude",
|
|
9872
|
+
hookFile: (h) => import_path16.default.join(h, ".claude", "settings.json"),
|
|
9873
|
+
hookFormat: "matcher",
|
|
9874
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
9875
|
+
mcpFile: (h) => import_path16.default.join(h, ".claude.json"),
|
|
9876
|
+
present: (h) => exists(import_path16.default.join(h, ".claude", "settings.json")) || exists(import_path16.default.join(h, ".claude.json"))
|
|
9877
|
+
},
|
|
9878
|
+
{
|
|
9879
|
+
id: "gemini",
|
|
9880
|
+
label: "Gemini CLI",
|
|
9881
|
+
setupCommand: "node9 agents add gemini",
|
|
9882
|
+
hookFile: (h) => import_path16.default.join(h, ".gemini", "settings.json"),
|
|
9883
|
+
hookFormat: "matcher",
|
|
9884
|
+
hookEvents: [ck("BeforeTool"), lg("AfterTool")],
|
|
9885
|
+
mcpFile: (h) => import_path16.default.join(h, ".gemini", "settings.json"),
|
|
9886
|
+
present: (h) => exists(import_path16.default.join(h, ".gemini", "settings.json"))
|
|
9887
|
+
},
|
|
9888
|
+
{
|
|
9889
|
+
id: "codex",
|
|
9890
|
+
label: "Codex",
|
|
9891
|
+
setupCommand: "node9 agents add codex",
|
|
9892
|
+
hookFile: (h) => import_path16.default.join(h, ".codex", "hooks.json"),
|
|
9893
|
+
hookFormat: "matcher",
|
|
9894
|
+
hookEvents: [ck("PreToolUse"), ck("UserPromptSubmit")],
|
|
9895
|
+
mcpFile: (h) => import_path16.default.join(h, ".codex", "config.toml"),
|
|
9896
|
+
mcpFormat: "toml",
|
|
9897
|
+
present: (h) => exists(import_path16.default.join(h, ".codex"))
|
|
9898
|
+
},
|
|
9899
|
+
{
|
|
9900
|
+
id: "antigravity",
|
|
9901
|
+
label: "Antigravity",
|
|
9902
|
+
setupCommand: "node9 agents add antigravity",
|
|
9903
|
+
hookFile: (h) => import_path16.default.join(h, ".gemini", "config", "hooks.json"),
|
|
9904
|
+
hookFormat: "matcher",
|
|
9905
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
9906
|
+
mcpFile: (h) => import_path16.default.join(h, ".gemini", "config", "mcp_config.json"),
|
|
9907
|
+
present: (h) => exists(import_path16.default.join(h, ".gemini", "config", "hooks.json")) || exists(import_path16.default.join(h, ".gemini", "antigravity-cli")) || exists(import_path16.default.join(h, ".gemini", "antigravity-ide"))
|
|
9908
|
+
},
|
|
9909
|
+
{
|
|
9910
|
+
id: "copilot",
|
|
9911
|
+
label: "GitHub Copilot",
|
|
9912
|
+
setupCommand: "node9 agents add copilot",
|
|
9913
|
+
hookFile: (h) => import_path16.default.join(h, ".copilot", "hooks", "node9.json"),
|
|
9914
|
+
hookFormat: "flat",
|
|
9915
|
+
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
9916
|
+
mcpFile: (h) => import_path16.default.join(h, ".copilot", "mcp-config.json"),
|
|
9917
|
+
present: (h) => exists(import_path16.default.join(h, ".copilot"))
|
|
9918
|
+
},
|
|
9919
|
+
{
|
|
9920
|
+
id: "cursor",
|
|
9921
|
+
label: "Cursor",
|
|
9922
|
+
setupCommand: "node9 agents add cursor",
|
|
9923
|
+
// MCP-only — no hook file (see note above).
|
|
9924
|
+
hookFormat: "flat",
|
|
9925
|
+
hookEvents: [],
|
|
9926
|
+
mcpFile: (h) => import_path16.default.join(h, ".cursor", "mcp.json"),
|
|
9927
|
+
present: (h) => exists(import_path16.default.join(h, ".cursor", "mcp.json"))
|
|
9928
|
+
},
|
|
9929
|
+
{
|
|
9930
|
+
id: "hermes",
|
|
9931
|
+
label: "Hermes Agent",
|
|
9932
|
+
setupCommand: "node9 agents add hermes",
|
|
9933
|
+
hookFile: (h) => hermesConfigPath(h),
|
|
9934
|
+
hookFormat: "yaml",
|
|
9935
|
+
hookEvents: [ck("pre_tool_call"), lg("post_tool_call")],
|
|
9936
|
+
labelPad: 14,
|
|
9937
|
+
// 'post_tool_call' is wider than the default
|
|
9938
|
+
present: (h) => exists(hermesConfigPath(h))
|
|
9939
|
+
},
|
|
9940
|
+
{
|
|
9941
|
+
// Plugin-shim agents — protected by a node9-authored plugin/extension file
|
|
9942
|
+
// (no hooks, no MCP). hookFormat is unused for these (shimFile drives it).
|
|
9943
|
+
id: "opencode",
|
|
9944
|
+
label: "OpenCode",
|
|
9945
|
+
setupCommand: "node9 agents add opencode",
|
|
9946
|
+
hookFormat: "flat",
|
|
9947
|
+
hookEvents: [],
|
|
9948
|
+
shimFile: (h) => import_path16.default.join(h, ".config", "opencode", "plugins", "node9.js"),
|
|
9949
|
+
present: (h) => exists(import_path16.default.join(h, ".config", "opencode")) || exists(import_path16.default.join(h, ".config", "opencode", "plugins", "node9.js"))
|
|
9950
|
+
},
|
|
9951
|
+
{
|
|
9952
|
+
id: "pi",
|
|
9953
|
+
label: "Pi",
|
|
9954
|
+
setupCommand: "node9 agents add pi",
|
|
9955
|
+
hookFormat: "flat",
|
|
9956
|
+
hookEvents: [],
|
|
9957
|
+
shimFile: (h) => import_path16.default.join(h, ".pi", "agent", "extensions", "node9.js"),
|
|
9958
|
+
present: (h) => exists(import_path16.default.join(h, ".pi", "agent")) || exists(import_path16.default.join(h, ".pi", "agent", "extensions", "node9.js"))
|
|
9959
|
+
}
|
|
9960
|
+
];
|
|
9961
|
+
}
|
|
9962
|
+
});
|
|
9963
|
+
|
|
9728
9964
|
// src/pricing/litellm.ts
|
|
9729
9965
|
function normalizeModel(raw) {
|
|
9730
9966
|
return raw.replace(/-\d{8}$/, "").toLowerCase();
|
|
9731
9967
|
}
|
|
9732
9968
|
function readCache() {
|
|
9733
9969
|
try {
|
|
9734
|
-
const raw = JSON.parse(
|
|
9970
|
+
const raw = JSON.parse(import_fs15.default.readFileSync(CACHE_FILE(), "utf-8"));
|
|
9735
9971
|
if (typeof raw.fetchedAt !== "string" || typeof raw.prices !== "object" || raw.prices === null) {
|
|
9736
9972
|
return null;
|
|
9737
9973
|
}
|
|
@@ -9745,18 +9981,18 @@ function readCache() {
|
|
|
9745
9981
|
function writeCache(prices) {
|
|
9746
9982
|
try {
|
|
9747
9983
|
const target = CACHE_FILE();
|
|
9748
|
-
const dir =
|
|
9749
|
-
if (!
|
|
9984
|
+
const dir = import_path17.default.dirname(target);
|
|
9985
|
+
if (!import_fs15.default.existsSync(dir)) import_fs15.default.mkdirSync(dir, { recursive: true });
|
|
9750
9986
|
const tmp = target + ".tmp";
|
|
9751
9987
|
const body = {
|
|
9752
9988
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9753
9989
|
prices
|
|
9754
9990
|
};
|
|
9755
|
-
|
|
9756
|
-
|
|
9991
|
+
import_fs15.default.writeFileSync(tmp, JSON.stringify(body) + "\n", "utf-8");
|
|
9992
|
+
import_fs15.default.renameSync(tmp, target);
|
|
9757
9993
|
} catch (err2) {
|
|
9758
9994
|
try {
|
|
9759
|
-
|
|
9995
|
+
import_fs15.default.appendFileSync(
|
|
9760
9996
|
HOOK_DEBUG_LOG,
|
|
9761
9997
|
`[pricing] cache write failed: ${err2.message}
|
|
9762
9998
|
`
|
|
@@ -9857,13 +10093,13 @@ function pricingFor(model) {
|
|
|
9857
10093
|
lookupCache.set(norm, resolved);
|
|
9858
10094
|
return resolved;
|
|
9859
10095
|
}
|
|
9860
|
-
var
|
|
10096
|
+
var import_fs15, import_path17, import_os14, LITELLM_URL, BUNDLED_PRICING, CACHE_FILE, TTL_MS, memCache, memCacheAt, diskChecked, lookupCache;
|
|
9861
10097
|
var init_litellm = __esm({
|
|
9862
10098
|
"src/pricing/litellm.ts"() {
|
|
9863
10099
|
"use strict";
|
|
9864
|
-
|
|
9865
|
-
|
|
9866
|
-
|
|
10100
|
+
import_fs15 = __toESM(require("fs"));
|
|
10101
|
+
import_path17 = __toESM(require("path"));
|
|
10102
|
+
import_os14 = __toESM(require("os"));
|
|
9867
10103
|
init_audit();
|
|
9868
10104
|
LITELLM_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
|
|
9869
10105
|
BUNDLED_PRICING = {
|
|
@@ -9903,7 +10139,7 @@ var init_litellm = __esm({
|
|
|
9903
10139
|
"gemini-2.0-flash": [75e-9, 3e-7, 0, 0],
|
|
9904
10140
|
"gemini-1.5-pro": [125e-8, 5e-6, 0, 0]
|
|
9905
10141
|
};
|
|
9906
|
-
CACHE_FILE = () =>
|
|
10142
|
+
CACHE_FILE = () => import_path17.default.join(import_os14.default.homedir(), ".node9", "model-pricing.json");
|
|
9907
10143
|
TTL_MS = 24 * 60 * 60 * 1e3;
|
|
9908
10144
|
memCache = null;
|
|
9909
10145
|
memCacheAt = 0;
|
|
@@ -9914,7 +10150,7 @@ var init_litellm = __esm({
|
|
|
9914
10150
|
|
|
9915
10151
|
// src/cost-gemini.ts
|
|
9916
10152
|
function geminiTmpDir() {
|
|
9917
|
-
return
|
|
10153
|
+
return import_path18.default.join(import_os15.default.homedir(), ".gemini", "tmp");
|
|
9918
10154
|
}
|
|
9919
10155
|
function geminiPriceFor(model) {
|
|
9920
10156
|
let tuple = pricingFor(model);
|
|
@@ -9929,14 +10165,14 @@ function geminiPriceFor(model) {
|
|
|
9929
10165
|
}
|
|
9930
10166
|
function safeReaddir(dir) {
|
|
9931
10167
|
try {
|
|
9932
|
-
return
|
|
10168
|
+
return import_fs16.default.readdirSync(dir);
|
|
9933
10169
|
} catch {
|
|
9934
10170
|
return [];
|
|
9935
10171
|
}
|
|
9936
10172
|
}
|
|
9937
10173
|
function isDir(p) {
|
|
9938
10174
|
try {
|
|
9939
|
-
return
|
|
10175
|
+
return import_fs16.default.statSync(p).isDirectory();
|
|
9940
10176
|
} catch {
|
|
9941
10177
|
return false;
|
|
9942
10178
|
}
|
|
@@ -9944,11 +10180,11 @@ function isDir(p) {
|
|
|
9944
10180
|
function listGeminiSessionFiles(base) {
|
|
9945
10181
|
const out = [];
|
|
9946
10182
|
for (const project of safeReaddir(base)) {
|
|
9947
|
-
const chats =
|
|
10183
|
+
const chats = import_path18.default.join(base, project, "chats");
|
|
9948
10184
|
if (!isDir(chats)) continue;
|
|
9949
10185
|
for (const f of safeReaddir(chats)) {
|
|
9950
10186
|
if (f.startsWith("session-") && f.endsWith(".jsonl")) {
|
|
9951
|
-
out.push({ file:
|
|
10187
|
+
out.push({ file: import_path18.default.join(chats, f), project });
|
|
9952
10188
|
}
|
|
9953
10189
|
}
|
|
9954
10190
|
}
|
|
@@ -10005,20 +10241,20 @@ function parseGeminiSession(lines, project) {
|
|
|
10005
10241
|
if (runId) for (const e of byKey.values()) e.runId = runId;
|
|
10006
10242
|
return [...byKey.values()];
|
|
10007
10243
|
}
|
|
10008
|
-
var
|
|
10244
|
+
var import_fs16, import_os15, import_path18, GEMINI_FALLBACK_MODELS, geminiSource;
|
|
10009
10245
|
var init_cost_gemini = __esm({
|
|
10010
10246
|
"src/cost-gemini.ts"() {
|
|
10011
10247
|
"use strict";
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10248
|
+
import_fs16 = __toESM(require("fs"));
|
|
10249
|
+
import_os15 = __toESM(require("os"));
|
|
10250
|
+
import_path18 = __toESM(require("path"));
|
|
10015
10251
|
init_litellm();
|
|
10016
10252
|
GEMINI_FALLBACK_MODELS = ["gemini-2.5-flash", "gemini-2.0-flash"];
|
|
10017
10253
|
geminiSource = {
|
|
10018
10254
|
id: "gemini",
|
|
10019
10255
|
available() {
|
|
10020
10256
|
try {
|
|
10021
|
-
return
|
|
10257
|
+
return import_fs16.default.existsSync(geminiTmpDir());
|
|
10022
10258
|
} catch {
|
|
10023
10259
|
return false;
|
|
10024
10260
|
}
|
|
@@ -10027,13 +10263,13 @@ var init_cost_gemini = __esm({
|
|
|
10027
10263
|
const combined = /* @__PURE__ */ new Map();
|
|
10028
10264
|
for (const { file, project } of listGeminiSessionFiles(geminiTmpDir())) {
|
|
10029
10265
|
try {
|
|
10030
|
-
if (sinceMs !== void 0 &&
|
|
10266
|
+
if (sinceMs !== void 0 && import_fs16.default.statSync(file).mtimeMs < sinceMs) continue;
|
|
10031
10267
|
} catch {
|
|
10032
10268
|
continue;
|
|
10033
10269
|
}
|
|
10034
10270
|
let content;
|
|
10035
10271
|
try {
|
|
10036
|
-
content =
|
|
10272
|
+
content = import_fs16.default.readFileSync(file, "utf8");
|
|
10037
10273
|
} catch {
|
|
10038
10274
|
continue;
|
|
10039
10275
|
}
|
|
@@ -10059,7 +10295,7 @@ var init_cost_gemini = __esm({
|
|
|
10059
10295
|
|
|
10060
10296
|
// src/cost-codex.ts
|
|
10061
10297
|
function codexSessionsDir() {
|
|
10062
|
-
return
|
|
10298
|
+
return import_path19.default.join(import_os16.default.homedir(), ".codex", "sessions");
|
|
10063
10299
|
}
|
|
10064
10300
|
function codexPriceFor(model) {
|
|
10065
10301
|
return pricingFor(model) ?? CODEX_FALLBACK;
|
|
@@ -10072,16 +10308,16 @@ function codexSessionCost(model, tokens) {
|
|
|
10072
10308
|
function listCodexSessionFiles(base) {
|
|
10073
10309
|
const out = [];
|
|
10074
10310
|
for (const y of safeReaddir2(base)) {
|
|
10075
|
-
const yp =
|
|
10311
|
+
const yp = import_path19.default.join(base, y);
|
|
10076
10312
|
if (!isDir2(yp)) continue;
|
|
10077
10313
|
for (const m of safeReaddir2(yp)) {
|
|
10078
|
-
const mp =
|
|
10314
|
+
const mp = import_path19.default.join(yp, m);
|
|
10079
10315
|
if (!isDir2(mp)) continue;
|
|
10080
10316
|
for (const d of safeReaddir2(mp)) {
|
|
10081
|
-
const dp =
|
|
10317
|
+
const dp = import_path19.default.join(mp, d);
|
|
10082
10318
|
if (!isDir2(dp)) continue;
|
|
10083
10319
|
for (const f of safeReaddir2(dp)) {
|
|
10084
|
-
if (f.endsWith(".jsonl")) out.push(
|
|
10320
|
+
if (f.endsWith(".jsonl")) out.push(import_path19.default.join(dp, f));
|
|
10085
10321
|
}
|
|
10086
10322
|
}
|
|
10087
10323
|
}
|
|
@@ -10090,14 +10326,14 @@ function listCodexSessionFiles(base) {
|
|
|
10090
10326
|
}
|
|
10091
10327
|
function safeReaddir2(dir) {
|
|
10092
10328
|
try {
|
|
10093
|
-
return
|
|
10329
|
+
return import_fs17.default.readdirSync(dir);
|
|
10094
10330
|
} catch {
|
|
10095
10331
|
return [];
|
|
10096
10332
|
}
|
|
10097
10333
|
}
|
|
10098
10334
|
function isDir2(p) {
|
|
10099
10335
|
try {
|
|
10100
|
-
return
|
|
10336
|
+
return import_fs17.default.statSync(p).isDirectory();
|
|
10101
10337
|
} catch {
|
|
10102
10338
|
return false;
|
|
10103
10339
|
}
|
|
@@ -10157,20 +10393,20 @@ function parseCodexSession(lines) {
|
|
|
10157
10393
|
cacheWriteTokens: 0
|
|
10158
10394
|
};
|
|
10159
10395
|
}
|
|
10160
|
-
var
|
|
10396
|
+
var import_fs17, import_os16, import_path19, CODEX_FALLBACK, codexSource;
|
|
10161
10397
|
var init_cost_codex = __esm({
|
|
10162
10398
|
"src/cost-codex.ts"() {
|
|
10163
10399
|
"use strict";
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10400
|
+
import_fs17 = __toESM(require("fs"));
|
|
10401
|
+
import_os16 = __toESM(require("os"));
|
|
10402
|
+
import_path19 = __toESM(require("path"));
|
|
10167
10403
|
init_litellm();
|
|
10168
10404
|
CODEX_FALLBACK = [5e-6, 15e-6, 0, 25e-7];
|
|
10169
10405
|
codexSource = {
|
|
10170
10406
|
id: "codex",
|
|
10171
10407
|
available() {
|
|
10172
10408
|
try {
|
|
10173
|
-
return
|
|
10409
|
+
return import_fs17.default.existsSync(codexSessionsDir());
|
|
10174
10410
|
} catch {
|
|
10175
10411
|
return false;
|
|
10176
10412
|
}
|
|
@@ -10180,13 +10416,13 @@ var init_cost_codex = __esm({
|
|
|
10180
10416
|
const combined = /* @__PURE__ */ new Map();
|
|
10181
10417
|
for (const file of listCodexSessionFiles(base)) {
|
|
10182
10418
|
try {
|
|
10183
|
-
if (sinceMs !== void 0 &&
|
|
10419
|
+
if (sinceMs !== void 0 && import_fs17.default.statSync(file).mtimeMs < sinceMs) continue;
|
|
10184
10420
|
} catch {
|
|
10185
10421
|
continue;
|
|
10186
10422
|
}
|
|
10187
10423
|
let content;
|
|
10188
10424
|
try {
|
|
10189
|
-
content =
|
|
10425
|
+
content = import_fs17.default.readFileSync(file, "utf8");
|
|
10190
10426
|
} catch {
|
|
10191
10427
|
continue;
|
|
10192
10428
|
}
|
|
@@ -10494,79 +10730,79 @@ var init_scan_summary = __esm({
|
|
|
10494
10730
|
function buildSensitivePaths(home, cwd) {
|
|
10495
10731
|
return [
|
|
10496
10732
|
{
|
|
10497
|
-
full:
|
|
10733
|
+
full: import_path20.default.join(home, ".ssh", "id_rsa"),
|
|
10498
10734
|
label: "~/.ssh/id_rsa",
|
|
10499
10735
|
description: "RSA private key \u2014 grants SSH access to your servers",
|
|
10500
10736
|
score: 20
|
|
10501
10737
|
},
|
|
10502
10738
|
{
|
|
10503
|
-
full:
|
|
10739
|
+
full: import_path20.default.join(home, ".ssh", "id_ed25519"),
|
|
10504
10740
|
label: "~/.ssh/id_ed25519",
|
|
10505
10741
|
description: "Ed25519 private key \u2014 grants SSH access to your servers",
|
|
10506
10742
|
score: 20
|
|
10507
10743
|
},
|
|
10508
10744
|
{
|
|
10509
|
-
full:
|
|
10745
|
+
full: import_path20.default.join(home, ".ssh", "id_ecdsa"),
|
|
10510
10746
|
label: "~/.ssh/id_ecdsa",
|
|
10511
10747
|
description: "ECDSA private key \u2014 grants SSH access to your servers",
|
|
10512
10748
|
score: 20
|
|
10513
10749
|
},
|
|
10514
10750
|
{
|
|
10515
|
-
full:
|
|
10751
|
+
full: import_path20.default.join(home, ".aws", "credentials"),
|
|
10516
10752
|
label: "~/.aws/credentials",
|
|
10517
10753
|
description: "AWS access keys \u2014 full cloud account access",
|
|
10518
10754
|
score: 20
|
|
10519
10755
|
},
|
|
10520
10756
|
{
|
|
10521
|
-
full:
|
|
10757
|
+
full: import_path20.default.join(home, ".aws", "config"),
|
|
10522
10758
|
label: "~/.aws/config",
|
|
10523
10759
|
description: "AWS configuration \u2014 account and region settings",
|
|
10524
10760
|
score: 5
|
|
10525
10761
|
},
|
|
10526
10762
|
{
|
|
10527
|
-
full:
|
|
10763
|
+
full: import_path20.default.join(home, ".config", "gcloud", "credentials.db"),
|
|
10528
10764
|
label: "~/.config/gcloud/credentials.db",
|
|
10529
10765
|
description: "Google Cloud credentials",
|
|
10530
10766
|
score: 15
|
|
10531
10767
|
},
|
|
10532
10768
|
{
|
|
10533
|
-
full:
|
|
10769
|
+
full: import_path20.default.join(home, ".docker", "config.json"),
|
|
10534
10770
|
label: "~/.docker/config.json",
|
|
10535
10771
|
description: "Docker registry auth tokens",
|
|
10536
10772
|
score: 10
|
|
10537
10773
|
},
|
|
10538
10774
|
{
|
|
10539
|
-
full:
|
|
10775
|
+
full: import_path20.default.join(home, ".netrc"),
|
|
10540
10776
|
label: "~/.netrc",
|
|
10541
10777
|
description: "FTP/HTTP credentials in plain text",
|
|
10542
10778
|
score: 15
|
|
10543
10779
|
},
|
|
10544
10780
|
{
|
|
10545
|
-
full:
|
|
10781
|
+
full: import_path20.default.join(home, ".npmrc"),
|
|
10546
10782
|
label: "~/.npmrc",
|
|
10547
10783
|
description: "npm auth token \u2014 can publish packages as you",
|
|
10548
10784
|
score: 10
|
|
10549
10785
|
},
|
|
10550
10786
|
{
|
|
10551
|
-
full:
|
|
10787
|
+
full: import_path20.default.join(home, ".node9", "credentials.json"),
|
|
10552
10788
|
label: "~/.node9/credentials.json",
|
|
10553
10789
|
description: "Node9 cloud API key",
|
|
10554
10790
|
score: 10
|
|
10555
10791
|
},
|
|
10556
10792
|
{
|
|
10557
|
-
full:
|
|
10793
|
+
full: import_path20.default.join(cwd, ".env"),
|
|
10558
10794
|
label: ".env (current folder)",
|
|
10559
10795
|
description: "App secrets \u2014 database passwords, API keys",
|
|
10560
10796
|
score: 20
|
|
10561
10797
|
},
|
|
10562
10798
|
{
|
|
10563
|
-
full:
|
|
10799
|
+
full: import_path20.default.join(cwd, ".env.local"),
|
|
10564
10800
|
label: ".env.local (current folder)",
|
|
10565
10801
|
description: "Local overrides \u2014 often contains real credentials",
|
|
10566
10802
|
score: 15
|
|
10567
10803
|
},
|
|
10568
10804
|
{
|
|
10569
|
-
full:
|
|
10805
|
+
full: import_path20.default.join(cwd, ".env.production"),
|
|
10570
10806
|
label: ".env.production (current folder)",
|
|
10571
10807
|
description: "Production secrets",
|
|
10572
10808
|
score: 20
|
|
@@ -10575,7 +10811,7 @@ function buildSensitivePaths(home, cwd) {
|
|
|
10575
10811
|
}
|
|
10576
10812
|
function isReadable(filePath) {
|
|
10577
10813
|
try {
|
|
10578
|
-
|
|
10814
|
+
import_fs18.default.accessSync(filePath, import_fs18.default.constants.R_OK);
|
|
10579
10815
|
return true;
|
|
10580
10816
|
} catch {
|
|
10581
10817
|
return false;
|
|
@@ -10588,13 +10824,13 @@ function scoreLabel(score) {
|
|
|
10588
10824
|
return import_chalk2.default.red.bold(`${score}/100 Critical`);
|
|
10589
10825
|
}
|
|
10590
10826
|
function runBlast() {
|
|
10591
|
-
const home =
|
|
10827
|
+
const home = import_os17.default.homedir();
|
|
10592
10828
|
const cwd = process.cwd();
|
|
10593
10829
|
const paths = buildSensitivePaths(home, cwd);
|
|
10594
10830
|
let scoreDeduction = 0;
|
|
10595
10831
|
const reachable = [];
|
|
10596
10832
|
for (const p of paths) {
|
|
10597
|
-
if (
|
|
10833
|
+
if (import_fs18.default.existsSync(p.full) && isReadable(p.full)) {
|
|
10598
10834
|
reachable.push(p);
|
|
10599
10835
|
scoreDeduction += p.score;
|
|
10600
10836
|
}
|
|
@@ -10612,7 +10848,7 @@ function runBlast() {
|
|
|
10612
10848
|
}
|
|
10613
10849
|
function registerBlastCommand(program2) {
|
|
10614
10850
|
program2.command("blast").description("Map what an AI agent can currently reach on this machine").action(() => {
|
|
10615
|
-
const home =
|
|
10851
|
+
const home = import_os17.default.homedir();
|
|
10616
10852
|
const cwd = process.cwd();
|
|
10617
10853
|
const { reachable, envFindings, score } = runBlast();
|
|
10618
10854
|
console.log("");
|
|
@@ -10659,14 +10895,14 @@ function registerBlastCommand(program2) {
|
|
|
10659
10895
|
console.log("");
|
|
10660
10896
|
});
|
|
10661
10897
|
}
|
|
10662
|
-
var import_chalk2,
|
|
10898
|
+
var import_chalk2, import_fs18, import_path20, import_os17;
|
|
10663
10899
|
var init_blast = __esm({
|
|
10664
10900
|
"src/cli/commands/blast.ts"() {
|
|
10665
10901
|
"use strict";
|
|
10666
10902
|
import_chalk2 = __toESM(require("chalk"));
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10903
|
+
import_fs18 = __toESM(require("fs"));
|
|
10904
|
+
import_path20 = __toESM(require("path"));
|
|
10905
|
+
import_os17 = __toESM(require("os"));
|
|
10670
10906
|
init_dlp();
|
|
10671
10907
|
}
|
|
10672
10908
|
});
|
|
@@ -10794,13 +11030,13 @@ var init_scan_json = __esm({
|
|
|
10794
11030
|
|
|
10795
11031
|
// src/cli/render/scan-history.ts
|
|
10796
11032
|
function defaultHistoryPath() {
|
|
10797
|
-
return
|
|
11033
|
+
return import_path21.default.join(import_os18.default.homedir(), ".node9", "scan-history.json");
|
|
10798
11034
|
}
|
|
10799
11035
|
function readPreviousScan(opts = {}) {
|
|
10800
11036
|
const filePath = opts.path ?? defaultHistoryPath();
|
|
10801
11037
|
try {
|
|
10802
|
-
if (!
|
|
10803
|
-
const raw =
|
|
11038
|
+
if (!import_fs19.default.existsSync(filePath)) return null;
|
|
11039
|
+
const raw = import_fs19.default.readFileSync(filePath, "utf8");
|
|
10804
11040
|
const parsed = JSON.parse(raw);
|
|
10805
11041
|
if (!Array.isArray(parsed) || parsed.length === 0) return null;
|
|
10806
11042
|
const last = parsed[parsed.length - 1];
|
|
@@ -10814,11 +11050,11 @@ function appendScanHistory(record, opts = {}) {
|
|
|
10814
11050
|
const filePath = opts.path ?? defaultHistoryPath();
|
|
10815
11051
|
const cap = opts.cap ?? SCAN_HISTORY_CAP;
|
|
10816
11052
|
try {
|
|
10817
|
-
|
|
11053
|
+
import_fs19.default.mkdirSync(import_path21.default.dirname(filePath), { recursive: true });
|
|
10818
11054
|
let history = [];
|
|
10819
|
-
if (
|
|
11055
|
+
if (import_fs19.default.existsSync(filePath)) {
|
|
10820
11056
|
try {
|
|
10821
|
-
const parsed = JSON.parse(
|
|
11057
|
+
const parsed = JSON.parse(import_fs19.default.readFileSync(filePath, "utf8"));
|
|
10822
11058
|
if (Array.isArray(parsed)) {
|
|
10823
11059
|
history = parsed.filter(isValidRecord);
|
|
10824
11060
|
}
|
|
@@ -10829,7 +11065,7 @@ function appendScanHistory(record, opts = {}) {
|
|
|
10829
11065
|
if (history.length > cap) {
|
|
10830
11066
|
history = history.slice(history.length - cap);
|
|
10831
11067
|
}
|
|
10832
|
-
|
|
11068
|
+
import_fs19.default.writeFileSync(filePath, JSON.stringify(history, null, 2));
|
|
10833
11069
|
} catch (err2) {
|
|
10834
11070
|
process.stderr.write(
|
|
10835
11071
|
`[node9] Warning: could not write scan-history.json: ${err2.message}
|
|
@@ -10851,24 +11087,24 @@ function isValidRecord(x) {
|
|
|
10851
11087
|
const r = x;
|
|
10852
11088
|
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";
|
|
10853
11089
|
}
|
|
10854
|
-
var
|
|
11090
|
+
var import_fs19, import_path21, import_os18, SCAN_HISTORY_CAP;
|
|
10855
11091
|
var init_scan_history = __esm({
|
|
10856
11092
|
"src/cli/render/scan-history.ts"() {
|
|
10857
11093
|
"use strict";
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
11094
|
+
import_fs19 = __toESM(require("fs"));
|
|
11095
|
+
import_path21 = __toESM(require("path"));
|
|
11096
|
+
import_os18 = __toESM(require("os"));
|
|
10861
11097
|
SCAN_HISTORY_CAP = 30;
|
|
10862
11098
|
}
|
|
10863
11099
|
});
|
|
10864
11100
|
|
|
10865
11101
|
// src/cost-copilot.ts
|
|
10866
11102
|
function copilotSessionsDir() {
|
|
10867
|
-
return
|
|
11103
|
+
return import_path22.default.join(import_os19.default.homedir(), ".copilot", "session-state");
|
|
10868
11104
|
}
|
|
10869
11105
|
function safeReaddir3(dir) {
|
|
10870
11106
|
try {
|
|
10871
|
-
return
|
|
11107
|
+
return import_fs20.default.readdirSync(dir);
|
|
10872
11108
|
} catch {
|
|
10873
11109
|
return [];
|
|
10874
11110
|
}
|
|
@@ -10935,19 +11171,19 @@ function parseCopilotSession(lines) {
|
|
|
10935
11171
|
}
|
|
10936
11172
|
return rows;
|
|
10937
11173
|
}
|
|
10938
|
-
var
|
|
11174
|
+
var import_fs20, import_os19, import_path22, copilotSource;
|
|
10939
11175
|
var init_cost_copilot = __esm({
|
|
10940
11176
|
"src/cost-copilot.ts"() {
|
|
10941
11177
|
"use strict";
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
11178
|
+
import_fs20 = __toESM(require("fs"));
|
|
11179
|
+
import_os19 = __toESM(require("os"));
|
|
11180
|
+
import_path22 = __toESM(require("path"));
|
|
10945
11181
|
init_litellm();
|
|
10946
11182
|
copilotSource = {
|
|
10947
11183
|
id: "copilot",
|
|
10948
11184
|
available() {
|
|
10949
11185
|
try {
|
|
10950
|
-
return
|
|
11186
|
+
return import_fs20.default.existsSync(copilotSessionsDir());
|
|
10951
11187
|
} catch {
|
|
10952
11188
|
return false;
|
|
10953
11189
|
}
|
|
@@ -10956,15 +11192,15 @@ var init_cost_copilot = __esm({
|
|
|
10956
11192
|
const base = copilotSessionsDir();
|
|
10957
11193
|
const combined = /* @__PURE__ */ new Map();
|
|
10958
11194
|
for (const sid of safeReaddir3(base)) {
|
|
10959
|
-
const file =
|
|
11195
|
+
const file = import_path22.default.join(base, sid, "events.jsonl");
|
|
10960
11196
|
try {
|
|
10961
|
-
if (sinceMs !== void 0 &&
|
|
11197
|
+
if (sinceMs !== void 0 && import_fs20.default.statSync(file).mtimeMs < sinceMs) continue;
|
|
10962
11198
|
} catch {
|
|
10963
11199
|
continue;
|
|
10964
11200
|
}
|
|
10965
11201
|
let content;
|
|
10966
11202
|
try {
|
|
10967
|
-
content =
|
|
11203
|
+
content = import_fs20.default.readFileSync(file, "utf8");
|
|
10968
11204
|
} catch {
|
|
10969
11205
|
continue;
|
|
10970
11206
|
}
|
|
@@ -10993,10 +11229,10 @@ function decodeProjectDirName(dirName) {
|
|
|
10993
11229
|
return dirName.replace(/-/g, "/");
|
|
10994
11230
|
}
|
|
10995
11231
|
function parseJSONLFile(filePath, fallbackWorkingDir) {
|
|
10996
|
-
const runId =
|
|
11232
|
+
const runId = import_path23.default.basename(filePath, ".jsonl");
|
|
10997
11233
|
let content;
|
|
10998
11234
|
try {
|
|
10999
|
-
content =
|
|
11235
|
+
content = import_fs21.default.readFileSync(filePath, "utf8");
|
|
11000
11236
|
} catch {
|
|
11001
11237
|
return /* @__PURE__ */ new Map();
|
|
11002
11238
|
}
|
|
@@ -11096,7 +11332,7 @@ async function postCostBatches(apiUrl, apiKey, machineId, entries) {
|
|
|
11096
11332
|
signal: AbortSignal.timeout(15e3)
|
|
11097
11333
|
});
|
|
11098
11334
|
if (!res.ok) {
|
|
11099
|
-
|
|
11335
|
+
import_fs21.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] HTTP ${res.status}
|
|
11100
11336
|
`);
|
|
11101
11337
|
} else {
|
|
11102
11338
|
let stored;
|
|
@@ -11106,7 +11342,7 @@ async function postCostBatches(apiUrl, apiKey, machineId, entries) {
|
|
|
11106
11342
|
} catch {
|
|
11107
11343
|
}
|
|
11108
11344
|
if (typeof stored === "number" && stored < batch.length) {
|
|
11109
|
-
|
|
11345
|
+
import_fs21.default.appendFileSync(
|
|
11110
11346
|
HOOK_DEBUG_LOG,
|
|
11111
11347
|
`[cost-sync] dropped ${batch.length - stored} of ${batch.length} rows
|
|
11112
11348
|
`
|
|
@@ -11114,7 +11350,7 @@ async function postCostBatches(apiUrl, apiKey, machineId, entries) {
|
|
|
11114
11350
|
}
|
|
11115
11351
|
}
|
|
11116
11352
|
} catch (err2) {
|
|
11117
|
-
|
|
11353
|
+
import_fs21.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] ${err2.message}
|
|
11118
11354
|
`);
|
|
11119
11355
|
}
|
|
11120
11356
|
}
|
|
@@ -11127,10 +11363,10 @@ async function syncCost() {
|
|
|
11127
11363
|
if (entries.length === 0) return;
|
|
11128
11364
|
let username = "unknown";
|
|
11129
11365
|
try {
|
|
11130
|
-
username =
|
|
11366
|
+
username = import_os20.default.userInfo().username;
|
|
11131
11367
|
} catch {
|
|
11132
11368
|
}
|
|
11133
|
-
const machineId = `${
|
|
11369
|
+
const machineId = `${import_os20.default.hostname()}:${username}`;
|
|
11134
11370
|
await postCostBatches(creds.apiUrl, creds.apiKey, machineId, entries);
|
|
11135
11371
|
}
|
|
11136
11372
|
function startCostSync() {
|
|
@@ -11142,13 +11378,13 @@ function startCostSync() {
|
|
|
11142
11378
|
}, SYNC_INTERVAL_MS);
|
|
11143
11379
|
timer.unref();
|
|
11144
11380
|
}
|
|
11145
|
-
var
|
|
11381
|
+
var import_fs21, import_path23, import_os20, SYNC_INTERVAL_MS, claudeSource, COST_SOURCES, COST_BATCH_SIZE;
|
|
11146
11382
|
var init_costSync = __esm({
|
|
11147
11383
|
"src/costSync.ts"() {
|
|
11148
11384
|
"use strict";
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11385
|
+
import_fs21 = __toESM(require("fs"));
|
|
11386
|
+
import_path23 = __toESM(require("path"));
|
|
11387
|
+
import_os20 = __toESM(require("os"));
|
|
11152
11388
|
init_config();
|
|
11153
11389
|
init_audit();
|
|
11154
11390
|
init_litellm();
|
|
@@ -11159,37 +11395,37 @@ var init_costSync = __esm({
|
|
|
11159
11395
|
claudeSource = {
|
|
11160
11396
|
id: "claude",
|
|
11161
11397
|
available() {
|
|
11162
|
-
return
|
|
11398
|
+
return import_fs21.default.existsSync(import_path23.default.join(import_os20.default.homedir(), ".claude", "projects"));
|
|
11163
11399
|
},
|
|
11164
11400
|
collect(sinceMs) {
|
|
11165
|
-
const projectsDir =
|
|
11166
|
-
if (!
|
|
11401
|
+
const projectsDir = import_path23.default.join(import_os20.default.homedir(), ".claude", "projects");
|
|
11402
|
+
if (!import_fs21.default.existsSync(projectsDir)) return [];
|
|
11167
11403
|
const combined = /* @__PURE__ */ new Map();
|
|
11168
11404
|
let dirs;
|
|
11169
11405
|
try {
|
|
11170
|
-
dirs =
|
|
11406
|
+
dirs = import_fs21.default.readdirSync(projectsDir);
|
|
11171
11407
|
} catch {
|
|
11172
11408
|
return [];
|
|
11173
11409
|
}
|
|
11174
11410
|
for (const dir of dirs) {
|
|
11175
|
-
const dirPath =
|
|
11411
|
+
const dirPath = import_path23.default.join(projectsDir, dir);
|
|
11176
11412
|
try {
|
|
11177
|
-
if (!
|
|
11413
|
+
if (!import_fs21.default.statSync(dirPath).isDirectory()) continue;
|
|
11178
11414
|
} catch {
|
|
11179
11415
|
continue;
|
|
11180
11416
|
}
|
|
11181
11417
|
let files;
|
|
11182
11418
|
try {
|
|
11183
|
-
files =
|
|
11419
|
+
files = import_fs21.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
|
|
11184
11420
|
} catch {
|
|
11185
11421
|
continue;
|
|
11186
11422
|
}
|
|
11187
11423
|
const fallbackWorkingDir = decodeProjectDirName(dir);
|
|
11188
11424
|
for (const file of files) {
|
|
11189
|
-
const filePath =
|
|
11425
|
+
const filePath = import_path23.default.join(dirPath, file);
|
|
11190
11426
|
if (sinceMs !== void 0) {
|
|
11191
11427
|
try {
|
|
11192
|
-
if (
|
|
11428
|
+
if (import_fs21.default.statSync(filePath).mtimeMs < sinceMs) continue;
|
|
11193
11429
|
} catch {
|
|
11194
11430
|
continue;
|
|
11195
11431
|
}
|
|
@@ -11240,7 +11476,7 @@ function freshWatermark() {
|
|
|
11240
11476
|
function loadWatermark() {
|
|
11241
11477
|
let raw;
|
|
11242
11478
|
try {
|
|
11243
|
-
raw =
|
|
11479
|
+
raw = import_fs22.default.readFileSync(WATERMARK_FILE(), "utf-8");
|
|
11244
11480
|
} catch {
|
|
11245
11481
|
return { status: "fresh", wm: freshWatermark() };
|
|
11246
11482
|
}
|
|
@@ -11292,28 +11528,28 @@ function loadWatermark() {
|
|
|
11292
11528
|
function saveWatermark(wm) {
|
|
11293
11529
|
if (wm.schemaVersion > WATERMARK_SCHEMA_VERSION) return;
|
|
11294
11530
|
const target = WATERMARK_FILE();
|
|
11295
|
-
const dir =
|
|
11296
|
-
if (!
|
|
11531
|
+
const dir = import_path24.default.dirname(target);
|
|
11532
|
+
if (!import_fs22.default.existsSync(dir)) import_fs22.default.mkdirSync(dir, { recursive: true });
|
|
11297
11533
|
const tmp = target + ".tmp";
|
|
11298
|
-
|
|
11299
|
-
|
|
11534
|
+
import_fs22.default.writeFileSync(tmp, JSON.stringify(wm, null, 2) + "\n", "utf-8");
|
|
11535
|
+
import_fs22.default.renameSync(tmp, target);
|
|
11300
11536
|
}
|
|
11301
11537
|
function listJsonlFiles() {
|
|
11302
11538
|
const root = PROJECTS_DIR();
|
|
11303
|
-
if (!
|
|
11539
|
+
if (!import_fs22.default.existsSync(root)) return [];
|
|
11304
11540
|
const out = [];
|
|
11305
|
-
for (const entry of
|
|
11541
|
+
for (const entry of import_fs22.default.readdirSync(root, { withFileTypes: true })) {
|
|
11306
11542
|
if (!entry.isDirectory()) continue;
|
|
11307
|
-
const projectDir =
|
|
11543
|
+
const projectDir = import_path24.default.join(root, entry.name);
|
|
11308
11544
|
let inner;
|
|
11309
11545
|
try {
|
|
11310
|
-
inner =
|
|
11546
|
+
inner = import_fs22.default.readdirSync(projectDir, { withFileTypes: true });
|
|
11311
11547
|
} catch {
|
|
11312
11548
|
continue;
|
|
11313
11549
|
}
|
|
11314
11550
|
for (const file of inner) {
|
|
11315
11551
|
if (file.isFile() && file.name.endsWith(".jsonl")) {
|
|
11316
|
-
out.push(
|
|
11552
|
+
out.push(import_path24.default.join(projectDir, file.name));
|
|
11317
11553
|
}
|
|
11318
11554
|
}
|
|
11319
11555
|
}
|
|
@@ -11321,7 +11557,7 @@ function listJsonlFiles() {
|
|
|
11321
11557
|
}
|
|
11322
11558
|
function fileSize(p) {
|
|
11323
11559
|
try {
|
|
11324
|
-
return
|
|
11560
|
+
return import_fs22.default.statSync(p).size;
|
|
11325
11561
|
} catch {
|
|
11326
11562
|
return 0;
|
|
11327
11563
|
}
|
|
@@ -11329,7 +11565,7 @@ function fileSize(p) {
|
|
|
11329
11565
|
async function scanDelta(filePath, fromByte, onLine) {
|
|
11330
11566
|
const size = fileSize(filePath);
|
|
11331
11567
|
if (size <= fromByte) return fromByte;
|
|
11332
|
-
const stream =
|
|
11568
|
+
const stream = import_fs22.default.createReadStream(filePath, {
|
|
11333
11569
|
start: fromByte,
|
|
11334
11570
|
end: size - 1,
|
|
11335
11571
|
highWaterMark: 64 * 1024
|
|
@@ -11441,7 +11677,7 @@ async function tickForensicBroadcast(offsets) {
|
|
|
11441
11677
|
continue;
|
|
11442
11678
|
}
|
|
11443
11679
|
if (size <= offset) continue;
|
|
11444
|
-
const sessionId =
|
|
11680
|
+
const sessionId = import_path24.default.basename(file, ".jsonl");
|
|
11445
11681
|
const newOffset = await scanDelta(file, offset, (obj, lineIndex) => {
|
|
11446
11682
|
out.push(...extractFindingsFromLine(obj, sessionId, lineIndex));
|
|
11447
11683
|
});
|
|
@@ -11500,7 +11736,7 @@ function emptyTick(uploadAs) {
|
|
|
11500
11736
|
function readRawWatermarkPreservingOffsets() {
|
|
11501
11737
|
let raw;
|
|
11502
11738
|
try {
|
|
11503
|
-
raw =
|
|
11739
|
+
raw = import_fs22.default.readFileSync(WATERMARK_FILE(), "utf-8");
|
|
11504
11740
|
} catch {
|
|
11505
11741
|
return null;
|
|
11506
11742
|
}
|
|
@@ -11534,13 +11770,13 @@ async function runActualTick(wm) {
|
|
|
11534
11770
|
if (!known) {
|
|
11535
11771
|
let mtimeMs = 0;
|
|
11536
11772
|
try {
|
|
11537
|
-
mtimeMs =
|
|
11773
|
+
mtimeMs = import_fs22.default.statSync(filePath).mtime.getTime();
|
|
11538
11774
|
} catch {
|
|
11539
11775
|
continue;
|
|
11540
11776
|
}
|
|
11541
11777
|
if (mtimeMs >= watermarkCreatedAt) {
|
|
11542
11778
|
filesNew++;
|
|
11543
|
-
const sessionId2 =
|
|
11779
|
+
const sessionId2 = import_path24.default.basename(filePath, ".jsonl");
|
|
11544
11780
|
const newScannedTo2 = await scanDelta(filePath, 0, (obj, lineIndex) => {
|
|
11545
11781
|
totalToolCalls++;
|
|
11546
11782
|
toolCallsBySession[sessionId2] = (toolCallsBySession[sessionId2] ?? 0) + 1;
|
|
@@ -11558,7 +11794,7 @@ async function runActualTick(wm) {
|
|
|
11558
11794
|
filesSkipped++;
|
|
11559
11795
|
continue;
|
|
11560
11796
|
}
|
|
11561
|
-
const sessionId =
|
|
11797
|
+
const sessionId = import_path24.default.basename(filePath, ".jsonl");
|
|
11562
11798
|
const newScannedTo = await scanDelta(filePath, known.scannedTo, (obj, lineIndex) => {
|
|
11563
11799
|
totalToolCalls++;
|
|
11564
11800
|
toolCallsBySession[sessionId] = (toolCallsBySession[sessionId] ?? 0) + 1;
|
|
@@ -11580,18 +11816,18 @@ async function runActualTick(wm) {
|
|
|
11580
11816
|
schemaFuture: false
|
|
11581
11817
|
};
|
|
11582
11818
|
}
|
|
11583
|
-
var
|
|
11819
|
+
var import_fs22, import_os21, import_path24, import_readline, PROJECTS_DIR, WATERMARK_FILE, MAX_LINE_BYTES, WATERMARK_SCHEMA_VERSION, LONG_OUTPUT_THRESHOLD_BYTES2;
|
|
11584
11820
|
var init_scan_watermark = __esm({
|
|
11585
11821
|
"src/daemon/scan-watermark.ts"() {
|
|
11586
11822
|
"use strict";
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11823
|
+
import_fs22 = __toESM(require("fs"));
|
|
11824
|
+
import_os21 = __toESM(require("os"));
|
|
11825
|
+
import_path24 = __toESM(require("path"));
|
|
11590
11826
|
import_readline = __toESM(require("readline"));
|
|
11591
11827
|
init_dlp();
|
|
11592
11828
|
init_dist();
|
|
11593
|
-
PROJECTS_DIR = () =>
|
|
11594
|
-
WATERMARK_FILE = () =>
|
|
11829
|
+
PROJECTS_DIR = () => import_path24.default.join(import_os21.default.homedir(), ".claude", "projects");
|
|
11830
|
+
WATERMARK_FILE = () => import_path24.default.join(import_os21.default.homedir(), ".node9", "scan-watermark.json");
|
|
11595
11831
|
MAX_LINE_BYTES = 2 * 1024 * 1024;
|
|
11596
11832
|
WATERMARK_SCHEMA_VERSION = 2;
|
|
11597
11833
|
LONG_OUTPUT_THRESHOLD_BYTES2 = LONG_OUTPUT_THRESHOLD_BYTES;
|
|
@@ -11640,40 +11876,40 @@ function parseSinceCutoff(raw, now = /* @__PURE__ */ new Date()) {
|
|
|
11640
11876
|
return now.getTime() - 90 * 864e5;
|
|
11641
11877
|
}
|
|
11642
11878
|
function* iterateJsonlFiles(cutoffMs) {
|
|
11643
|
-
const projectsDir =
|
|
11879
|
+
const projectsDir = import_path25.default.join(import_os22.default.homedir(), ".claude", "projects");
|
|
11644
11880
|
let dirs;
|
|
11645
11881
|
try {
|
|
11646
|
-
dirs =
|
|
11882
|
+
dirs = import_fs23.default.readdirSync(projectsDir);
|
|
11647
11883
|
} catch {
|
|
11648
11884
|
return;
|
|
11649
11885
|
}
|
|
11650
11886
|
for (const dir of dirs) {
|
|
11651
|
-
const dirPath =
|
|
11887
|
+
const dirPath = import_path25.default.join(projectsDir, dir);
|
|
11652
11888
|
let stats;
|
|
11653
11889
|
try {
|
|
11654
|
-
stats =
|
|
11890
|
+
stats = import_fs23.default.statSync(dirPath);
|
|
11655
11891
|
} catch {
|
|
11656
11892
|
continue;
|
|
11657
11893
|
}
|
|
11658
11894
|
if (!stats.isDirectory()) continue;
|
|
11659
11895
|
let files;
|
|
11660
11896
|
try {
|
|
11661
|
-
files =
|
|
11897
|
+
files = import_fs23.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
|
|
11662
11898
|
} catch {
|
|
11663
11899
|
continue;
|
|
11664
11900
|
}
|
|
11665
11901
|
for (const file of files) {
|
|
11666
|
-
const filePath =
|
|
11902
|
+
const filePath = import_path25.default.join(dirPath, file);
|
|
11667
11903
|
let mtime = 0;
|
|
11668
11904
|
try {
|
|
11669
|
-
mtime =
|
|
11905
|
+
mtime = import_fs23.default.statSync(filePath).mtimeMs;
|
|
11670
11906
|
} catch {
|
|
11671
11907
|
continue;
|
|
11672
11908
|
}
|
|
11673
11909
|
if (mtime < cutoffMs) continue;
|
|
11674
11910
|
yield {
|
|
11675
11911
|
filePath,
|
|
11676
|
-
sessionId:
|
|
11912
|
+
sessionId: import_path25.default.basename(file, ".jsonl"),
|
|
11677
11913
|
projectDir: dir
|
|
11678
11914
|
};
|
|
11679
11915
|
}
|
|
@@ -11741,7 +11977,7 @@ async function runUploadHistory(opts) {
|
|
|
11741
11977
|
filesScanned++;
|
|
11742
11978
|
let content;
|
|
11743
11979
|
try {
|
|
11744
|
-
content =
|
|
11980
|
+
content = import_fs23.default.readFileSync(filePath, "utf8");
|
|
11745
11981
|
} catch {
|
|
11746
11982
|
continue;
|
|
11747
11983
|
}
|
|
@@ -11815,10 +12051,10 @@ async function runUploadHistory(opts) {
|
|
|
11815
12051
|
const costUrl = creds.apiUrl.endsWith("/policies/sync") ? creds.apiUrl.replace(/\/policies\/sync$/, "/cost-sync") : `${creds.apiUrl.replace(/\/$/, "")}/cost-sync`;
|
|
11816
12052
|
let username = "unknown";
|
|
11817
12053
|
try {
|
|
11818
|
-
username =
|
|
12054
|
+
username = import_os22.default.userInfo().username;
|
|
11819
12055
|
} catch {
|
|
11820
12056
|
}
|
|
11821
|
-
const machineId = `${
|
|
12057
|
+
const machineId = `${import_os22.default.hostname()}:${username}`;
|
|
11822
12058
|
await postJson(costUrl, creds.apiKey, {
|
|
11823
12059
|
machineId,
|
|
11824
12060
|
entries: dailyEntries
|
|
@@ -11868,14 +12104,14 @@ async function postJson(url, apiKey, body) {
|
|
|
11868
12104
|
req.end();
|
|
11869
12105
|
});
|
|
11870
12106
|
}
|
|
11871
|
-
var
|
|
12107
|
+
var import_fs23, import_https, import_os22, import_path25, import_chalk4, FINDING_TO_SIGNAL2;
|
|
11872
12108
|
var init_scan_upload_history = __esm({
|
|
11873
12109
|
"src/scan-upload-history.ts"() {
|
|
11874
12110
|
"use strict";
|
|
11875
|
-
|
|
12111
|
+
import_fs23 = __toESM(require("fs"));
|
|
11876
12112
|
import_https = __toESM(require("https"));
|
|
11877
|
-
|
|
11878
|
-
|
|
12113
|
+
import_os22 = __toESM(require("os"));
|
|
12114
|
+
import_path25 = __toESM(require("path"));
|
|
11879
12115
|
import_chalk4 = __toESM(require("chalk"));
|
|
11880
12116
|
init_dist();
|
|
11881
12117
|
init_config();
|
|
@@ -12117,14 +12353,14 @@ function buildRuleSources() {
|
|
|
12117
12353
|
}
|
|
12118
12354
|
function countScanFiles() {
|
|
12119
12355
|
let total = 0;
|
|
12120
|
-
const claudeDir =
|
|
12121
|
-
if (
|
|
12356
|
+
const claudeDir = import_path26.default.join(import_os23.default.homedir(), ".claude", "projects");
|
|
12357
|
+
if (import_fs24.default.existsSync(claudeDir)) {
|
|
12122
12358
|
try {
|
|
12123
|
-
for (const proj of
|
|
12124
|
-
const p =
|
|
12359
|
+
for (const proj of import_fs24.default.readdirSync(claudeDir)) {
|
|
12360
|
+
const p = import_path26.default.join(claudeDir, proj);
|
|
12125
12361
|
try {
|
|
12126
|
-
if (!
|
|
12127
|
-
total +=
|
|
12362
|
+
if (!import_fs24.default.statSync(p).isDirectory()) continue;
|
|
12363
|
+
total += import_fs24.default.readdirSync(p).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-")).length;
|
|
12128
12364
|
} catch {
|
|
12129
12365
|
continue;
|
|
12130
12366
|
}
|
|
@@ -12132,17 +12368,17 @@ function countScanFiles() {
|
|
|
12132
12368
|
} catch {
|
|
12133
12369
|
}
|
|
12134
12370
|
}
|
|
12135
|
-
const geminiDir =
|
|
12136
|
-
if (
|
|
12371
|
+
const geminiDir = import_path26.default.join(import_os23.default.homedir(), ".gemini", "tmp");
|
|
12372
|
+
if (import_fs24.default.existsSync(geminiDir)) {
|
|
12137
12373
|
try {
|
|
12138
|
-
for (const slug2 of
|
|
12139
|
-
const p =
|
|
12374
|
+
for (const slug2 of import_fs24.default.readdirSync(geminiDir)) {
|
|
12375
|
+
const p = import_path26.default.join(geminiDir, slug2);
|
|
12140
12376
|
try {
|
|
12141
|
-
if (!
|
|
12142
|
-
const chatsDir =
|
|
12143
|
-
if (
|
|
12377
|
+
if (!import_fs24.default.statSync(p).isDirectory()) continue;
|
|
12378
|
+
const chatsDir = import_path26.default.join(p, "chats");
|
|
12379
|
+
if (import_fs24.default.existsSync(chatsDir)) {
|
|
12144
12380
|
try {
|
|
12145
|
-
total +=
|
|
12381
|
+
total += import_fs24.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json")).length;
|
|
12146
12382
|
} catch {
|
|
12147
12383
|
}
|
|
12148
12384
|
}
|
|
@@ -12154,15 +12390,15 @@ function countScanFiles() {
|
|
|
12154
12390
|
}
|
|
12155
12391
|
}
|
|
12156
12392
|
for (const surface of ["antigravity-cli", "antigravity-ide"]) {
|
|
12157
|
-
const brainDir =
|
|
12158
|
-
if (!
|
|
12393
|
+
const brainDir = import_path26.default.join(import_os23.default.homedir(), ".gemini", surface, "brain");
|
|
12394
|
+
if (!import_fs24.default.existsSync(brainDir)) continue;
|
|
12159
12395
|
try {
|
|
12160
|
-
for (const conv of
|
|
12161
|
-
const convPath =
|
|
12396
|
+
for (const conv of import_fs24.default.readdirSync(brainDir)) {
|
|
12397
|
+
const convPath = import_path26.default.join(brainDir, conv);
|
|
12162
12398
|
try {
|
|
12163
|
-
if (!
|
|
12164
|
-
const logsDir =
|
|
12165
|
-
if (
|
|
12399
|
+
if (!import_fs24.default.statSync(convPath).isDirectory()) continue;
|
|
12400
|
+
const logsDir = import_path26.default.join(convPath, ".system_generated", "logs");
|
|
12401
|
+
if (import_fs24.default.existsSync(import_path26.default.join(logsDir, "transcript_full.jsonl")) || import_fs24.default.existsSync(import_path26.default.join(logsDir, "transcript.jsonl"))) {
|
|
12166
12402
|
total += 1;
|
|
12167
12403
|
}
|
|
12168
12404
|
} catch {
|
|
@@ -12172,31 +12408,31 @@ function countScanFiles() {
|
|
|
12172
12408
|
} catch {
|
|
12173
12409
|
}
|
|
12174
12410
|
}
|
|
12175
|
-
const copilotDir =
|
|
12176
|
-
if (
|
|
12411
|
+
const copilotDir = import_path26.default.join(import_os23.default.homedir(), ".copilot", "session-state");
|
|
12412
|
+
if (import_fs24.default.existsSync(copilotDir)) {
|
|
12177
12413
|
try {
|
|
12178
|
-
for (const sid of
|
|
12179
|
-
if (
|
|
12414
|
+
for (const sid of import_fs24.default.readdirSync(copilotDir)) {
|
|
12415
|
+
if (import_fs24.default.existsSync(import_path26.default.join(copilotDir, sid, "events.jsonl"))) total += 1;
|
|
12180
12416
|
}
|
|
12181
12417
|
} catch {
|
|
12182
12418
|
}
|
|
12183
12419
|
}
|
|
12184
|
-
const codexDir =
|
|
12185
|
-
if (
|
|
12420
|
+
const codexDir = import_path26.default.join(import_os23.default.homedir(), ".codex", "sessions");
|
|
12421
|
+
if (import_fs24.default.existsSync(codexDir)) {
|
|
12186
12422
|
try {
|
|
12187
|
-
for (const year of
|
|
12188
|
-
const yp =
|
|
12423
|
+
for (const year of import_fs24.default.readdirSync(codexDir)) {
|
|
12424
|
+
const yp = import_path26.default.join(codexDir, year);
|
|
12189
12425
|
try {
|
|
12190
|
-
if (!
|
|
12191
|
-
for (const month of
|
|
12192
|
-
const mp =
|
|
12426
|
+
if (!import_fs24.default.statSync(yp).isDirectory()) continue;
|
|
12427
|
+
for (const month of import_fs24.default.readdirSync(yp)) {
|
|
12428
|
+
const mp = import_path26.default.join(yp, month);
|
|
12193
12429
|
try {
|
|
12194
|
-
if (!
|
|
12195
|
-
for (const day of
|
|
12196
|
-
const dp =
|
|
12430
|
+
if (!import_fs24.default.statSync(mp).isDirectory()) continue;
|
|
12431
|
+
for (const day of import_fs24.default.readdirSync(mp)) {
|
|
12432
|
+
const dp = import_path26.default.join(mp, day);
|
|
12197
12433
|
try {
|
|
12198
|
-
if (!
|
|
12199
|
-
total +=
|
|
12434
|
+
if (!import_fs24.default.statSync(dp).isDirectory()) continue;
|
|
12435
|
+
total += import_fs24.default.readdirSync(dp).filter((f) => f.endsWith(".jsonl")).length;
|
|
12200
12436
|
} catch {
|
|
12201
12437
|
continue;
|
|
12202
12438
|
}
|
|
@@ -12232,7 +12468,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
12232
12468
|
const sessionId = file.replace(/\.jsonl$/, "");
|
|
12233
12469
|
let raw;
|
|
12234
12470
|
try {
|
|
12235
|
-
raw =
|
|
12471
|
+
raw = import_fs24.default.readFileSync(import_path26.default.join(projPath, file), "utf-8");
|
|
12236
12472
|
} catch {
|
|
12237
12473
|
return;
|
|
12238
12474
|
}
|
|
@@ -12284,7 +12520,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
12284
12520
|
if (block.type !== "tool_result") continue;
|
|
12285
12521
|
const filePath = block.tool_use_id ? toolUseFilePaths.get(block.tool_use_id) : void 0;
|
|
12286
12522
|
if (filePath) {
|
|
12287
|
-
const ext =
|
|
12523
|
+
const ext = import_path26.default.extname(filePath).toLowerCase();
|
|
12288
12524
|
if (CODE_EXTENSIONS.has(ext)) continue;
|
|
12289
12525
|
}
|
|
12290
12526
|
const resultText = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => c.text ?? "").join("\n") : null;
|
|
@@ -12341,7 +12577,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
12341
12577
|
const rawCmd = String(input.command ?? "").trimStart();
|
|
12342
12578
|
if (/^node9\s+(scan|explain|report|tail|dlp|status|sessions|audit)\b/.test(rawCmd)) continue;
|
|
12343
12579
|
const inputFilePath = typeof input.file_path === "string" ? input.file_path : "";
|
|
12344
|
-
const inputFileExt = inputFilePath ?
|
|
12580
|
+
const inputFileExt = inputFilePath ? import_path26.default.extname(inputFilePath).toLowerCase() : "";
|
|
12345
12581
|
if (CODE_EXTENSIONS.has(inputFileExt)) continue;
|
|
12346
12582
|
const dlpMatch = scanArgs(input);
|
|
12347
12583
|
if (dlpMatch) {
|
|
@@ -12438,19 +12674,19 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
|
|
|
12438
12674
|
}
|
|
12439
12675
|
}
|
|
12440
12676
|
function processClaudeProject(proj, projectsDir, ruleSources, startDate, result, dedup, onProgress, onLine) {
|
|
12441
|
-
const projPath =
|
|
12677
|
+
const projPath = import_path26.default.join(projectsDir, proj);
|
|
12442
12678
|
try {
|
|
12443
|
-
if (!
|
|
12679
|
+
if (!import_fs24.default.statSync(projPath).isDirectory()) return;
|
|
12444
12680
|
} catch {
|
|
12445
12681
|
return;
|
|
12446
12682
|
}
|
|
12447
|
-
const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(
|
|
12683
|
+
const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(import_os23.default.homedir(), "~")).slice(
|
|
12448
12684
|
0,
|
|
12449
12685
|
40
|
|
12450
12686
|
);
|
|
12451
12687
|
let files;
|
|
12452
12688
|
try {
|
|
12453
|
-
files =
|
|
12689
|
+
files = import_fs24.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
|
|
12454
12690
|
} catch {
|
|
12455
12691
|
return;
|
|
12456
12692
|
}
|
|
@@ -12484,12 +12720,12 @@ function emptyClaudeScan() {
|
|
|
12484
12720
|
};
|
|
12485
12721
|
}
|
|
12486
12722
|
function scanClaudeHistory(startDate, onProgress, onLine) {
|
|
12487
|
-
const projectsDir =
|
|
12723
|
+
const projectsDir = import_path26.default.join(import_os23.default.homedir(), ".claude", "projects");
|
|
12488
12724
|
const result = emptyClaudeScan();
|
|
12489
|
-
if (!
|
|
12725
|
+
if (!import_fs24.default.existsSync(projectsDir)) return result;
|
|
12490
12726
|
let projDirs;
|
|
12491
12727
|
try {
|
|
12492
|
-
projDirs =
|
|
12728
|
+
projDirs = import_fs24.default.readdirSync(projectsDir);
|
|
12493
12729
|
} catch {
|
|
12494
12730
|
return result;
|
|
12495
12731
|
}
|
|
@@ -12510,7 +12746,7 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
|
|
|
12510
12746
|
return result;
|
|
12511
12747
|
}
|
|
12512
12748
|
function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
12513
|
-
const tmpDir =
|
|
12749
|
+
const tmpDir = import_path26.default.join(import_os23.default.homedir(), ".gemini", "tmp");
|
|
12514
12750
|
const result = {
|
|
12515
12751
|
filesScanned: 0,
|
|
12516
12752
|
sessions: 0,
|
|
@@ -12525,33 +12761,33 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
12525
12761
|
sessionsWithEarlySecrets: 0
|
|
12526
12762
|
};
|
|
12527
12763
|
const dedup = emptyScanDedup();
|
|
12528
|
-
if (!
|
|
12764
|
+
if (!import_fs24.default.existsSync(tmpDir)) return result;
|
|
12529
12765
|
let slugDirs;
|
|
12530
12766
|
try {
|
|
12531
|
-
slugDirs =
|
|
12767
|
+
slugDirs = import_fs24.default.readdirSync(tmpDir);
|
|
12532
12768
|
} catch {
|
|
12533
12769
|
return result;
|
|
12534
12770
|
}
|
|
12535
12771
|
const ruleSources = buildRuleSources();
|
|
12536
12772
|
for (const slug2 of slugDirs) {
|
|
12537
|
-
const slugPath =
|
|
12773
|
+
const slugPath = import_path26.default.join(tmpDir, slug2);
|
|
12538
12774
|
try {
|
|
12539
|
-
if (!
|
|
12775
|
+
if (!import_fs24.default.statSync(slugPath).isDirectory()) continue;
|
|
12540
12776
|
} catch {
|
|
12541
12777
|
continue;
|
|
12542
12778
|
}
|
|
12543
12779
|
let projLabel = stripTerminalEscapes(slug2).slice(0, 40);
|
|
12544
12780
|
try {
|
|
12545
12781
|
projLabel = stripTerminalEscapes(
|
|
12546
|
-
|
|
12547
|
-
).replace(
|
|
12782
|
+
import_fs24.default.readFileSync(import_path26.default.join(slugPath, ".project_root"), "utf-8").trim()
|
|
12783
|
+
).replace(import_os23.default.homedir(), "~").slice(0, 40);
|
|
12548
12784
|
} catch {
|
|
12549
12785
|
}
|
|
12550
|
-
const chatsDir =
|
|
12551
|
-
if (!
|
|
12786
|
+
const chatsDir = import_path26.default.join(slugPath, "chats");
|
|
12787
|
+
if (!import_fs24.default.existsSync(chatsDir)) continue;
|
|
12552
12788
|
let chatFiles;
|
|
12553
12789
|
try {
|
|
12554
|
-
chatFiles =
|
|
12790
|
+
chatFiles = import_fs24.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json") || f.endsWith(".jsonl")).sort((a, b) => Number(b.endsWith(".jsonl")) - Number(a.endsWith(".jsonl")));
|
|
12555
12791
|
} catch {
|
|
12556
12792
|
continue;
|
|
12557
12793
|
}
|
|
@@ -12564,7 +12800,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
12564
12800
|
onProgress?.(result.filesScanned);
|
|
12565
12801
|
let raw;
|
|
12566
12802
|
try {
|
|
12567
|
-
raw =
|
|
12803
|
+
raw = import_fs24.default.readFileSync(import_path26.default.join(chatsDir, chatFile), "utf-8");
|
|
12568
12804
|
} catch {
|
|
12569
12805
|
continue;
|
|
12570
12806
|
}
|
|
@@ -12737,13 +12973,13 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
|
|
|
12737
12973
|
return result;
|
|
12738
12974
|
}
|
|
12739
12975
|
function antigravityBrainDirs() {
|
|
12740
|
-
return ["antigravity-cli", "antigravity-ide"].map((surface) =>
|
|
12976
|
+
return ["antigravity-cli", "antigravity-ide"].map((surface) => import_path26.default.join(import_os23.default.homedir(), ".gemini", surface, "brain")).filter((p) => import_fs24.default.existsSync(p));
|
|
12741
12977
|
}
|
|
12742
12978
|
function antigravityTranscriptPath(convPath) {
|
|
12743
|
-
const logsDir =
|
|
12979
|
+
const logsDir = import_path26.default.join(convPath, ".system_generated", "logs");
|
|
12744
12980
|
for (const name of ["transcript_full.jsonl", "transcript.jsonl"]) {
|
|
12745
|
-
const p =
|
|
12746
|
-
if (
|
|
12981
|
+
const p = import_path26.default.join(logsDir, name);
|
|
12982
|
+
if (import_fs24.default.existsSync(p)) return p;
|
|
12747
12983
|
}
|
|
12748
12984
|
return null;
|
|
12749
12985
|
}
|
|
@@ -12769,14 +13005,14 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
12769
13005
|
for (const brainDir of brainDirs) {
|
|
12770
13006
|
let convDirs;
|
|
12771
13007
|
try {
|
|
12772
|
-
convDirs =
|
|
13008
|
+
convDirs = import_fs24.default.readdirSync(brainDir);
|
|
12773
13009
|
} catch {
|
|
12774
13010
|
continue;
|
|
12775
13011
|
}
|
|
12776
13012
|
for (const conv of convDirs) {
|
|
12777
|
-
const convPath =
|
|
13013
|
+
const convPath = import_path26.default.join(brainDir, conv);
|
|
12778
13014
|
try {
|
|
12779
|
-
if (!
|
|
13015
|
+
if (!import_fs24.default.statSync(convPath).isDirectory()) continue;
|
|
12780
13016
|
} catch {
|
|
12781
13017
|
continue;
|
|
12782
13018
|
}
|
|
@@ -12786,7 +13022,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
12786
13022
|
onProgress?.(result.filesScanned);
|
|
12787
13023
|
let raw;
|
|
12788
13024
|
try {
|
|
12789
|
-
raw =
|
|
13025
|
+
raw = import_fs24.default.readFileSync(transcriptFile, "utf-8");
|
|
12790
13026
|
} catch {
|
|
12791
13027
|
continue;
|
|
12792
13028
|
}
|
|
@@ -12843,7 +13079,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
12843
13079
|
result.bashCalls++;
|
|
12844
13080
|
const cwd = String(input.cwd ?? "");
|
|
12845
13081
|
if (cwd && projLabel === conv.slice(0, 8)) {
|
|
12846
|
-
projLabel = stripTerminalEscapes(cwd).replace(
|
|
13082
|
+
projLabel = stripTerminalEscapes(cwd).replace(import_os23.default.homedir(), "~").slice(0, 40);
|
|
12847
13083
|
}
|
|
12848
13084
|
}
|
|
12849
13085
|
const rawCmd = String(input.command ?? "").trimStart();
|
|
@@ -12943,7 +13179,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
|
|
|
12943
13179
|
return result;
|
|
12944
13180
|
}
|
|
12945
13181
|
function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
12946
|
-
const sessionDir =
|
|
13182
|
+
const sessionDir = import_path26.default.join(import_os23.default.homedir(), ".copilot", "session-state");
|
|
12947
13183
|
const result = {
|
|
12948
13184
|
filesScanned: 0,
|
|
12949
13185
|
sessions: 0,
|
|
@@ -12959,22 +13195,22 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
|
12959
13195
|
sessionsWithEarlySecrets: 0
|
|
12960
13196
|
};
|
|
12961
13197
|
const dedup = emptyScanDedup();
|
|
12962
|
-
if (!
|
|
13198
|
+
if (!import_fs24.default.existsSync(sessionDir)) return result;
|
|
12963
13199
|
let sessionIds;
|
|
12964
13200
|
try {
|
|
12965
|
-
sessionIds =
|
|
13201
|
+
sessionIds = import_fs24.default.readdirSync(sessionDir);
|
|
12966
13202
|
} catch {
|
|
12967
13203
|
return result;
|
|
12968
13204
|
}
|
|
12969
13205
|
const ruleSources = buildRuleSources();
|
|
12970
13206
|
for (const sessionId of sessionIds) {
|
|
12971
|
-
const eventsPath =
|
|
12972
|
-
if (!
|
|
13207
|
+
const eventsPath = import_path26.default.join(sessionDir, sessionId, "events.jsonl");
|
|
13208
|
+
if (!import_fs24.default.existsSync(eventsPath)) continue;
|
|
12973
13209
|
result.filesScanned++;
|
|
12974
13210
|
onProgress?.(result.filesScanned);
|
|
12975
13211
|
let raw;
|
|
12976
13212
|
try {
|
|
12977
|
-
raw =
|
|
13213
|
+
raw = import_fs24.default.readFileSync(eventsPath, "utf-8");
|
|
12978
13214
|
} catch {
|
|
12979
13215
|
continue;
|
|
12980
13216
|
}
|
|
@@ -12994,7 +13230,7 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
|
12994
13230
|
if (ev.type === "session.start") {
|
|
12995
13231
|
const cwd = ev.data?.context?.cwd;
|
|
12996
13232
|
if (typeof cwd === "string" && cwd) {
|
|
12997
|
-
projLabel = stripTerminalEscapes(cwd).replace(
|
|
13233
|
+
projLabel = stripTerminalEscapes(cwd).replace(import_os23.default.homedir(), "~").slice(0, 40);
|
|
12998
13234
|
}
|
|
12999
13235
|
continue;
|
|
13000
13236
|
}
|
|
@@ -13126,7 +13362,7 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
|
|
|
13126
13362
|
return result;
|
|
13127
13363
|
}
|
|
13128
13364
|
function scanCodexHistory(startDate, onProgress, onLine) {
|
|
13129
|
-
const sessionsBase =
|
|
13365
|
+
const sessionsBase = import_path26.default.join(import_os23.default.homedir(), ".codex", "sessions");
|
|
13130
13366
|
const result = {
|
|
13131
13367
|
filesScanned: 0,
|
|
13132
13368
|
sessions: 0,
|
|
@@ -13141,32 +13377,32 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
13141
13377
|
sessionsWithEarlySecrets: 0
|
|
13142
13378
|
};
|
|
13143
13379
|
const dedup = emptyScanDedup();
|
|
13144
|
-
if (!
|
|
13380
|
+
if (!import_fs24.default.existsSync(sessionsBase)) return result;
|
|
13145
13381
|
const jsonlFiles = [];
|
|
13146
13382
|
try {
|
|
13147
|
-
for (const year of
|
|
13148
|
-
const yearPath =
|
|
13383
|
+
for (const year of import_fs24.default.readdirSync(sessionsBase)) {
|
|
13384
|
+
const yearPath = import_path26.default.join(sessionsBase, year);
|
|
13149
13385
|
try {
|
|
13150
|
-
if (!
|
|
13386
|
+
if (!import_fs24.default.statSync(yearPath).isDirectory()) continue;
|
|
13151
13387
|
} catch {
|
|
13152
13388
|
continue;
|
|
13153
13389
|
}
|
|
13154
|
-
for (const month of
|
|
13155
|
-
const monthPath =
|
|
13390
|
+
for (const month of import_fs24.default.readdirSync(yearPath)) {
|
|
13391
|
+
const monthPath = import_path26.default.join(yearPath, month);
|
|
13156
13392
|
try {
|
|
13157
|
-
if (!
|
|
13393
|
+
if (!import_fs24.default.statSync(monthPath).isDirectory()) continue;
|
|
13158
13394
|
} catch {
|
|
13159
13395
|
continue;
|
|
13160
13396
|
}
|
|
13161
|
-
for (const day of
|
|
13162
|
-
const dayPath =
|
|
13397
|
+
for (const day of import_fs24.default.readdirSync(monthPath)) {
|
|
13398
|
+
const dayPath = import_path26.default.join(monthPath, day);
|
|
13163
13399
|
try {
|
|
13164
|
-
if (!
|
|
13400
|
+
if (!import_fs24.default.statSync(dayPath).isDirectory()) continue;
|
|
13165
13401
|
} catch {
|
|
13166
13402
|
continue;
|
|
13167
13403
|
}
|
|
13168
|
-
for (const file of
|
|
13169
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
13404
|
+
for (const file of import_fs24.default.readdirSync(dayPath)) {
|
|
13405
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path26.default.join(dayPath, file));
|
|
13170
13406
|
}
|
|
13171
13407
|
}
|
|
13172
13408
|
}
|
|
@@ -13180,7 +13416,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
13180
13416
|
onProgress?.(result.filesScanned);
|
|
13181
13417
|
let lines;
|
|
13182
13418
|
try {
|
|
13183
|
-
lines =
|
|
13419
|
+
lines = import_fs24.default.readFileSync(filePath, "utf-8").split("\n");
|
|
13184
13420
|
} catch {
|
|
13185
13421
|
continue;
|
|
13186
13422
|
}
|
|
@@ -13207,7 +13443,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
13207
13443
|
sessionId = String(payload["id"] ?? filePath);
|
|
13208
13444
|
startTime = String(payload["timestamp"] ?? "");
|
|
13209
13445
|
const cwd = String(payload["cwd"] ?? "");
|
|
13210
|
-
projLabel = stripTerminalEscapes(cwd.replace(
|
|
13446
|
+
projLabel = stripTerminalEscapes(cwd.replace(import_os23.default.homedir(), "~")).slice(0, 40);
|
|
13211
13447
|
continue;
|
|
13212
13448
|
}
|
|
13213
13449
|
if (entry.type === "turn_context" && typeof payload["model"] === "string") {
|
|
@@ -13367,17 +13603,17 @@ function scanCodexHistory(startDate, onProgress, onLine) {
|
|
|
13367
13603
|
return result;
|
|
13368
13604
|
}
|
|
13369
13605
|
function scanShellConfig() {
|
|
13370
|
-
const home =
|
|
13606
|
+
const home = import_os23.default.homedir();
|
|
13371
13607
|
const configFiles = [".zshrc", ".bashrc", ".bash_profile", ".profile"].map(
|
|
13372
|
-
(f) =>
|
|
13608
|
+
(f) => import_path26.default.join(home, f)
|
|
13373
13609
|
);
|
|
13374
13610
|
const findings = [];
|
|
13375
13611
|
const seen = /* @__PURE__ */ new Set();
|
|
13376
13612
|
for (const filePath of configFiles) {
|
|
13377
|
-
if (!
|
|
13613
|
+
if (!import_fs24.default.existsSync(filePath)) continue;
|
|
13378
13614
|
let lines;
|
|
13379
13615
|
try {
|
|
13380
|
-
lines =
|
|
13616
|
+
lines = import_fs24.default.readFileSync(filePath, "utf-8").split("\n");
|
|
13381
13617
|
} catch {
|
|
13382
13618
|
continue;
|
|
13383
13619
|
}
|
|
@@ -14183,7 +14419,7 @@ function registerScanCommand(program2) {
|
|
|
14183
14419
|
if (!drillDown) {
|
|
14184
14420
|
const useInk2 = !options.classic;
|
|
14185
14421
|
if (useInk2) {
|
|
14186
|
-
const scanInkPath =
|
|
14422
|
+
const scanInkPath = import_path26.default.join(__dirname, "scan-ink.mjs");
|
|
14187
14423
|
const dynamicImport = new Function("id", "return import(id)");
|
|
14188
14424
|
const mod = await dynamicImport(`file://${scanInkPath}`);
|
|
14189
14425
|
const rangeLabel2 = options.all ? "all time" : `last ${options.days ?? 90} days`;
|
|
@@ -14415,14 +14651,14 @@ function registerScanCommand(program2) {
|
|
|
14415
14651
|
}
|
|
14416
14652
|
);
|
|
14417
14653
|
}
|
|
14418
|
-
var import_chalk5,
|
|
14654
|
+
var import_chalk5, import_fs24, import_path26, import_os23, import_string_width2, CODE_EXTENSIONS, SELF_OUTPUT_MARKERS, FIXTURE_TOKEN_PATTERNS, TERMINAL_ESCAPE_RE2, LOOP_TOOLS, LOOP_THRESHOLD, LOOP_TIMESPAN_THRESHOLD_MS, STUCK_TOOLS_MIN_WASTE, STUCK_TOOLS_LIMIT, RECURRING_SESSION_THRESHOLD, STALE_AGE_DAYS, classifyRuleSeverity2, narrativeRuleLabel2;
|
|
14419
14655
|
var init_scan = __esm({
|
|
14420
14656
|
"src/cli/commands/scan.ts"() {
|
|
14421
14657
|
"use strict";
|
|
14422
14658
|
import_chalk5 = __toESM(require("chalk"));
|
|
14423
|
-
|
|
14424
|
-
|
|
14425
|
-
|
|
14659
|
+
import_fs24 = __toESM(require("fs"));
|
|
14660
|
+
import_path26 = __toESM(require("path"));
|
|
14661
|
+
import_os23 = __toESM(require("os"));
|
|
14426
14662
|
init_shields();
|
|
14427
14663
|
init_config();
|
|
14428
14664
|
init_policy();
|
|
@@ -14599,12 +14835,12 @@ var init_suggestion_tracker = __esm({
|
|
|
14599
14835
|
});
|
|
14600
14836
|
|
|
14601
14837
|
// src/daemon/taint-store.ts
|
|
14602
|
-
var
|
|
14838
|
+
var import_fs25, import_path27, DEFAULT_TTL_MS, TaintStore, SESSION_TAINT_TTL_MS, SessionTaintStore;
|
|
14603
14839
|
var init_taint_store = __esm({
|
|
14604
14840
|
"src/daemon/taint-store.ts"() {
|
|
14605
14841
|
"use strict";
|
|
14606
|
-
|
|
14607
|
-
|
|
14842
|
+
import_fs25 = __toESM(require("fs"));
|
|
14843
|
+
import_path27 = __toESM(require("path"));
|
|
14608
14844
|
DEFAULT_TTL_MS = 60 * 60 * 1e3;
|
|
14609
14845
|
TaintStore = class {
|
|
14610
14846
|
records = /* @__PURE__ */ new Map();
|
|
@@ -14670,9 +14906,9 @@ var init_taint_store = __esm({
|
|
|
14670
14906
|
/** Resolve to absolute path, falling back to path.resolve if file doesn't exist yet. */
|
|
14671
14907
|
_resolve(filePath) {
|
|
14672
14908
|
try {
|
|
14673
|
-
return
|
|
14909
|
+
return import_fs25.default.realpathSync.native(import_path27.default.resolve(filePath));
|
|
14674
14910
|
} catch {
|
|
14675
|
-
return
|
|
14911
|
+
return import_path27.default.resolve(filePath);
|
|
14676
14912
|
}
|
|
14677
14913
|
}
|
|
14678
14914
|
};
|
|
@@ -14838,8 +15074,8 @@ var init_session_history = __esm({
|
|
|
14838
15074
|
// src/daemon/state.ts
|
|
14839
15075
|
function loadInsightCounts() {
|
|
14840
15076
|
try {
|
|
14841
|
-
if (!
|
|
14842
|
-
const data = JSON.parse(
|
|
15077
|
+
if (!import_fs26.default.existsSync(INSIGHT_COUNTS_FILE)) return;
|
|
15078
|
+
const data = JSON.parse(import_fs26.default.readFileSync(INSIGHT_COUNTS_FILE, "utf-8"));
|
|
14843
15079
|
for (const [tool, count] of Object.entries(data)) {
|
|
14844
15080
|
if (typeof count === "number" && count > 0) insightCounts.set(tool, count);
|
|
14845
15081
|
}
|
|
@@ -14878,23 +15114,23 @@ function markRejectionHandlerRegistered() {
|
|
|
14878
15114
|
daemonRejectionHandlerRegistered = true;
|
|
14879
15115
|
}
|
|
14880
15116
|
function atomicWriteSync2(filePath, data, options) {
|
|
14881
|
-
const dir =
|
|
14882
|
-
if (!
|
|
15117
|
+
const dir = import_path28.default.dirname(filePath);
|
|
15118
|
+
if (!import_fs26.default.existsSync(dir)) import_fs26.default.mkdirSync(dir, { recursive: true });
|
|
14883
15119
|
const tmpPath = `${filePath}.${(0, import_crypto8.randomUUID)()}.tmp`;
|
|
14884
15120
|
try {
|
|
14885
|
-
|
|
15121
|
+
import_fs26.default.writeFileSync(tmpPath, data, options);
|
|
14886
15122
|
} catch (err2) {
|
|
14887
15123
|
try {
|
|
14888
|
-
|
|
15124
|
+
import_fs26.default.unlinkSync(tmpPath);
|
|
14889
15125
|
} catch {
|
|
14890
15126
|
}
|
|
14891
15127
|
throw err2;
|
|
14892
15128
|
}
|
|
14893
15129
|
try {
|
|
14894
|
-
|
|
15130
|
+
import_fs26.default.renameSync(tmpPath, filePath);
|
|
14895
15131
|
} catch (err2) {
|
|
14896
15132
|
try {
|
|
14897
|
-
|
|
15133
|
+
import_fs26.default.unlinkSync(tmpPath);
|
|
14898
15134
|
} catch {
|
|
14899
15135
|
}
|
|
14900
15136
|
throw err2;
|
|
@@ -14918,16 +15154,16 @@ function appendAuditLog(data) {
|
|
|
14918
15154
|
decision: data.decision,
|
|
14919
15155
|
source: "daemon"
|
|
14920
15156
|
};
|
|
14921
|
-
const dir =
|
|
14922
|
-
if (!
|
|
14923
|
-
|
|
15157
|
+
const dir = import_path28.default.dirname(AUDIT_LOG_FILE);
|
|
15158
|
+
if (!import_fs26.default.existsSync(dir)) import_fs26.default.mkdirSync(dir, { recursive: true });
|
|
15159
|
+
import_fs26.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
|
|
14924
15160
|
} catch {
|
|
14925
15161
|
}
|
|
14926
15162
|
}
|
|
14927
15163
|
function getAuditHistory(limit = 20) {
|
|
14928
15164
|
try {
|
|
14929
|
-
if (!
|
|
14930
|
-
const lines =
|
|
15165
|
+
if (!import_fs26.default.existsSync(AUDIT_LOG_FILE)) return [];
|
|
15166
|
+
const lines = import_fs26.default.readFileSync(AUDIT_LOG_FILE, "utf-8").trim().split("\n");
|
|
14931
15167
|
if (lines.length === 1 && lines[0] === "") return [];
|
|
14932
15168
|
return lines.slice(-limit).map((l) => JSON.parse(l)).reverse();
|
|
14933
15169
|
} catch {
|
|
@@ -14936,7 +15172,7 @@ function getAuditHistory(limit = 20) {
|
|
|
14936
15172
|
}
|
|
14937
15173
|
function getOrgName() {
|
|
14938
15174
|
try {
|
|
14939
|
-
if (
|
|
15175
|
+
if (import_fs26.default.existsSync(CREDENTIALS_FILE)) return "Node9 Cloud";
|
|
14940
15176
|
} catch {
|
|
14941
15177
|
}
|
|
14942
15178
|
return null;
|
|
@@ -14944,8 +15180,8 @@ function getOrgName() {
|
|
|
14944
15180
|
function writeGlobalSetting(key, value) {
|
|
14945
15181
|
let config = {};
|
|
14946
15182
|
try {
|
|
14947
|
-
if (
|
|
14948
|
-
config = JSON.parse(
|
|
15183
|
+
if (import_fs26.default.existsSync(GLOBAL_CONFIG_FILE)) {
|
|
15184
|
+
config = JSON.parse(import_fs26.default.readFileSync(GLOBAL_CONFIG_FILE, "utf-8"));
|
|
14949
15185
|
}
|
|
14950
15186
|
} catch {
|
|
14951
15187
|
}
|
|
@@ -14957,8 +15193,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
|
|
|
14957
15193
|
try {
|
|
14958
15194
|
let trust = { entries: [] };
|
|
14959
15195
|
try {
|
|
14960
|
-
if (
|
|
14961
|
-
trust = JSON.parse(
|
|
15196
|
+
if (import_fs26.default.existsSync(TRUST_FILE2))
|
|
15197
|
+
trust = JSON.parse(import_fs26.default.readFileSync(TRUST_FILE2, "utf-8"));
|
|
14962
15198
|
} catch {
|
|
14963
15199
|
}
|
|
14964
15200
|
trust.entries = trust.entries.filter(
|
|
@@ -14975,8 +15211,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
|
|
|
14975
15211
|
}
|
|
14976
15212
|
function readPersistentDecisions() {
|
|
14977
15213
|
try {
|
|
14978
|
-
if (
|
|
14979
|
-
return JSON.parse(
|
|
15214
|
+
if (import_fs26.default.existsSync(DECISIONS_FILE)) {
|
|
15215
|
+
return JSON.parse(import_fs26.default.readFileSync(DECISIONS_FILE, "utf-8"));
|
|
14980
15216
|
}
|
|
14981
15217
|
} catch {
|
|
14982
15218
|
}
|
|
@@ -15004,7 +15240,7 @@ function estimateToolCost(tool, args) {
|
|
|
15004
15240
|
const filePath = a.file_path ?? a.path;
|
|
15005
15241
|
if (filePath) {
|
|
15006
15242
|
try {
|
|
15007
|
-
const bytes =
|
|
15243
|
+
const bytes = import_fs26.default.statSync(filePath).size;
|
|
15008
15244
|
return bytes / BYTES_PER_TOKEN / 1e6 * INPUT_PRICE_PER_1M;
|
|
15009
15245
|
} catch {
|
|
15010
15246
|
}
|
|
@@ -15075,7 +15311,7 @@ function abandonPending() {
|
|
|
15075
15311
|
});
|
|
15076
15312
|
if (autoStarted) {
|
|
15077
15313
|
try {
|
|
15078
|
-
|
|
15314
|
+
import_fs26.default.unlinkSync(DAEMON_PID_FILE);
|
|
15079
15315
|
} catch {
|
|
15080
15316
|
}
|
|
15081
15317
|
setTimeout(() => {
|
|
@@ -15086,8 +15322,8 @@ function abandonPending() {
|
|
|
15086
15322
|
}
|
|
15087
15323
|
function logActivitySocket(msg) {
|
|
15088
15324
|
try {
|
|
15089
|
-
|
|
15090
|
-
|
|
15325
|
+
import_fs26.default.appendFileSync(
|
|
15326
|
+
import_path28.default.join(homeDir, ".node9", "hook-debug.log"),
|
|
15091
15327
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] [activity-socket] ${msg}
|
|
15092
15328
|
`
|
|
15093
15329
|
);
|
|
@@ -15109,13 +15345,13 @@ function shouldRebind(now = Date.now()) {
|
|
|
15109
15345
|
function startActivitySocket() {
|
|
15110
15346
|
bindActivitySocket();
|
|
15111
15347
|
activityHealthInterval = setInterval(() => {
|
|
15112
|
-
if (!
|
|
15348
|
+
if (!import_fs26.default.existsSync(ACTIVITY_SOCKET_PATH2)) attemptRebind("health-probe");
|
|
15113
15349
|
}, ACTIVITY_HEALTH_PROBE_MS);
|
|
15114
15350
|
activityHealthInterval.unref();
|
|
15115
15351
|
process.on("exit", () => {
|
|
15116
15352
|
if (activityHealthInterval) clearInterval(activityHealthInterval);
|
|
15117
15353
|
try {
|
|
15118
|
-
|
|
15354
|
+
import_fs26.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
|
|
15119
15355
|
} catch {
|
|
15120
15356
|
}
|
|
15121
15357
|
});
|
|
@@ -15143,7 +15379,7 @@ function attemptRebind(reason) {
|
|
|
15143
15379
|
}
|
|
15144
15380
|
function bindActivitySocket() {
|
|
15145
15381
|
try {
|
|
15146
|
-
|
|
15382
|
+
import_fs26.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
|
|
15147
15383
|
} catch {
|
|
15148
15384
|
}
|
|
15149
15385
|
const ACTIVITY_MAX_BYTES = 1024 * 1024;
|
|
@@ -15230,318 +15466,97 @@ function bindActivitySocket() {
|
|
|
15230
15466
|
costEstimate,
|
|
15231
15467
|
agent: data.agent,
|
|
15232
15468
|
mcpServer: data.mcpServer,
|
|
15233
|
-
sessionId: data.sessionId
|
|
15234
|
-
});
|
|
15235
|
-
}
|
|
15236
|
-
} catch {
|
|
15237
|
-
}
|
|
15238
|
-
});
|
|
15239
|
-
socket.on("error", () => {
|
|
15240
|
-
});
|
|
15241
|
-
});
|
|
15242
|
-
unixServer.on("error", (err2) => {
|
|
15243
|
-
logActivitySocket(`server error: ${err2.message}`);
|
|
15244
|
-
});
|
|
15245
|
-
unixServer.listen(ACTIVITY_SOCKET_PATH2, () => {
|
|
15246
|
-
logActivitySocket(`bound to ${ACTIVITY_SOCKET_PATH2}`);
|
|
15247
|
-
});
|
|
15248
|
-
activitySocketServer = unixServer;
|
|
15249
|
-
}
|
|
15250
|
-
var import_net2, import_fs25, import_path27, import_os23, import_crypto8, 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;
|
|
15251
|
-
var init_state2 = __esm({
|
|
15252
|
-
"src/daemon/state.ts"() {
|
|
15253
|
-
"use strict";
|
|
15254
|
-
import_net2 = __toESM(require("net"));
|
|
15255
|
-
import_fs25 = __toESM(require("fs"));
|
|
15256
|
-
import_path27 = __toESM(require("path"));
|
|
15257
|
-
import_os23 = __toESM(require("os"));
|
|
15258
|
-
import_crypto8 = require("crypto");
|
|
15259
|
-
init_daemon();
|
|
15260
|
-
init_suggestion_tracker();
|
|
15261
|
-
init_taint_store();
|
|
15262
|
-
init_session_counters();
|
|
15263
|
-
init_session_history();
|
|
15264
|
-
homeDir = import_os23.default.homedir();
|
|
15265
|
-
DAEMON_PID_FILE = import_path27.default.join(homeDir, ".node9", "daemon.pid");
|
|
15266
|
-
DECISIONS_FILE = import_path27.default.join(homeDir, ".node9", "decisions.json");
|
|
15267
|
-
AUDIT_LOG_FILE = import_path27.default.join(homeDir, ".node9", "audit.log");
|
|
15268
|
-
TRUST_FILE2 = import_path27.default.join(homeDir, ".node9", "trust.json");
|
|
15269
|
-
GLOBAL_CONFIG_FILE = import_path27.default.join(homeDir, ".node9", "config.json");
|
|
15270
|
-
CREDENTIALS_FILE = import_path27.default.join(homeDir, ".node9", "credentials.json");
|
|
15271
|
-
INSIGHT_COUNTS_FILE = import_path27.default.join(homeDir, ".node9", "insight-counts.json");
|
|
15272
|
-
pending = /* @__PURE__ */ new Map();
|
|
15273
|
-
sseClients = /* @__PURE__ */ new Set();
|
|
15274
|
-
suggestionTracker = new SuggestionTracker(3);
|
|
15275
|
-
taintStore = new TaintStore();
|
|
15276
|
-
sessionTaintStore = new SessionTaintStore();
|
|
15277
|
-
insightCounts = /* @__PURE__ */ new Map();
|
|
15278
|
-
_abandonTimer = null;
|
|
15279
|
-
_hadBrowserClient = false;
|
|
15280
|
-
_daemonServer = null;
|
|
15281
|
-
daemonRejectionHandlerRegistered = false;
|
|
15282
|
-
AUTO_DENY_MS = 12e4;
|
|
15283
|
-
TRUST_DURATIONS = {
|
|
15284
|
-
"30m": 30 * 6e4,
|
|
15285
|
-
"1h": 60 * 6e4,
|
|
15286
|
-
"2h": 2 * 60 * 6e4
|
|
15287
|
-
};
|
|
15288
|
-
autoStarted = process.env.NODE9_AUTO_STARTED === "1";
|
|
15289
|
-
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path27.default.join(import_os23.default.tmpdir(), "node9-activity.sock");
|
|
15290
|
-
ACTIVITY_RING_SIZE = 100;
|
|
15291
|
-
activityRing = [];
|
|
15292
|
-
LARGE_RESPONSE_RING_SIZE = 20;
|
|
15293
|
-
largeResponseRing = [];
|
|
15294
|
-
cachedScanResult = null;
|
|
15295
|
-
cachedScanTs = 0;
|
|
15296
|
-
SCAN_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
15297
|
-
SECRET_KEY_RE = /password|secret|token|key|apikey|credential|auth/i;
|
|
15298
|
-
INPUT_PRICE_PER_1M = 3;
|
|
15299
|
-
OUTPUT_PRICE_PER_1M = 15;
|
|
15300
|
-
BYTES_PER_TOKEN = 4;
|
|
15301
|
-
CRITICAL_FORENSIC_CATEGORIES = /* @__PURE__ */ new Set([
|
|
15302
|
-
"privilege-escalation",
|
|
15303
|
-
"destructive-op",
|
|
15304
|
-
"eval-of-remote"
|
|
15305
|
-
]);
|
|
15306
|
-
WRITE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
15307
|
-
"write",
|
|
15308
|
-
"write_file",
|
|
15309
|
-
"create_file",
|
|
15310
|
-
"edit",
|
|
15311
|
-
"multiedit",
|
|
15312
|
-
"str_replace_based_edit_tool",
|
|
15313
|
-
"replace",
|
|
15314
|
-
"notebook_edit",
|
|
15315
|
-
"notebookedit"
|
|
15316
|
-
]);
|
|
15317
|
-
ACTIVITY_REBIND_MAX_ATTEMPTS = 5;
|
|
15318
|
-
ACTIVITY_REBIND_WINDOW_MS = 6e4;
|
|
15319
|
-
ACTIVITY_HEALTH_PROBE_MS = 2e3;
|
|
15320
|
-
activitySocketServer = null;
|
|
15321
|
-
activityHealthInterval = null;
|
|
15322
|
-
activityRebindAttempts = [];
|
|
15323
|
-
activityCircuitTripped = false;
|
|
15324
|
-
}
|
|
15325
|
-
});
|
|
15326
|
-
|
|
15327
|
-
// src/agent-wiring.ts
|
|
15328
|
-
function readJson2(filePath) {
|
|
15329
|
-
if (!import_fs26.default.existsSync(filePath)) return null;
|
|
15330
|
-
try {
|
|
15331
|
-
return JSON.parse(import_fs26.default.readFileSync(filePath, "utf-8"));
|
|
15332
|
-
} catch {
|
|
15333
|
-
return "invalid";
|
|
15334
|
-
}
|
|
15335
|
-
}
|
|
15336
|
-
function matchersHaveNode9Hook(matchers) {
|
|
15337
|
-
return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
|
|
15338
|
-
}
|
|
15339
|
-
function flatHaveNode9Hook(entries) {
|
|
15340
|
-
return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
|
|
15341
|
-
}
|
|
15342
|
-
function readHookRoot(filePath, format) {
|
|
15343
|
-
if (!import_fs26.default.existsSync(filePath)) return "absent";
|
|
15344
|
-
let raw;
|
|
15345
|
-
try {
|
|
15346
|
-
raw = import_fs26.default.readFileSync(filePath, "utf-8");
|
|
15347
|
-
} catch {
|
|
15348
|
-
return "absent";
|
|
15349
|
-
}
|
|
15350
|
-
try {
|
|
15351
|
-
const parsed = format === "yaml" ? yaml2.parse(raw) : JSON.parse(raw);
|
|
15352
|
-
return parsed?.hooks ?? {};
|
|
15353
|
-
} catch {
|
|
15354
|
-
return "invalid";
|
|
15355
|
-
}
|
|
15356
|
-
}
|
|
15357
|
-
function eventWired(root, ev, format) {
|
|
15358
|
-
const arr = root[ev.key];
|
|
15359
|
-
if (format === "matcher") return matchersHaveNode9Hook(arr);
|
|
15360
|
-
return flatHaveNode9Hook(arr);
|
|
15361
|
-
}
|
|
15362
|
-
function detectMcp(servers) {
|
|
15363
|
-
const entries = Object.entries(servers ?? {});
|
|
15364
|
-
const present = entries.some(([, s]) => s?.command === "node9");
|
|
15365
|
-
const wrapped = entries.filter(([, s]) => s?.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
|
|
15366
|
-
return { wrapped, present };
|
|
15367
|
-
}
|
|
15368
|
-
function readMcp(filePath, format) {
|
|
15369
|
-
if (!import_fs26.default.existsSync(filePath)) return { wrapped: [], present: false };
|
|
15370
|
-
try {
|
|
15371
|
-
if (format === "toml") {
|
|
15372
|
-
const parsed2 = (0, import_smol_toml2.parse)(import_fs26.default.readFileSync(filePath, "utf-8"));
|
|
15373
|
-
return detectMcp(parsed2?.mcp_servers);
|
|
15374
|
-
}
|
|
15375
|
-
const parsed = readJson2(filePath);
|
|
15376
|
-
if (parsed === null || parsed === "invalid") return { wrapped: [], present: false };
|
|
15377
|
-
return detectMcp(parsed.mcpServers);
|
|
15378
|
-
} catch {
|
|
15379
|
-
return { wrapped: [], present: false };
|
|
15380
|
-
}
|
|
15381
|
-
}
|
|
15382
|
-
function getAgentWiring(home = import_os24.default.homedir()) {
|
|
15383
|
-
const detected = detectAgents(home);
|
|
15384
|
-
return AGENT_SPECS.map((spec) => {
|
|
15385
|
-
const present = spec.present(home);
|
|
15386
|
-
const pad = spec.labelPad ?? DEFAULT_LABEL_PAD;
|
|
15387
|
-
let hooks;
|
|
15388
|
-
let wireState;
|
|
15389
|
-
let hookLabel;
|
|
15390
|
-
let settingsPath;
|
|
15391
|
-
if (spec.shimFile) {
|
|
15392
|
-
const shimWired = exists(spec.shimFile(home));
|
|
15393
|
-
hooks = [{ label: "node9 plugin (node9 check)", wired: shimWired }];
|
|
15394
|
-
wireState = shimWired ? "wired" : present ? "unwired" : "absent";
|
|
15395
|
-
hookLabel = "node9 plugin";
|
|
15396
|
-
settingsPath = spec.shimFile(home);
|
|
15397
|
-
} else {
|
|
15398
|
-
const root = spec.hookFile ? readHookRoot(spec.hookFile(home), spec.hookFormat) : "absent";
|
|
15399
|
-
const primary = spec.hookEvents[0];
|
|
15400
|
-
const rootPresent = root !== "absent" && root !== "invalid";
|
|
15401
|
-
hooks = spec.hookEvents.map((ev) => ({
|
|
15402
|
-
label: hookLabelOf(ev, pad),
|
|
15403
|
-
wired: rootPresent && eventWired(root, ev, spec.hookFormat)
|
|
15404
|
-
}));
|
|
15405
|
-
if (root === "absent") wireState = "absent";
|
|
15406
|
-
else if (root === "invalid") wireState = "invalid";
|
|
15407
|
-
else wireState = primary && eventWired(root, primary, spec.hookFormat) ? "wired" : "unwired";
|
|
15408
|
-
hookLabel = primary ? `${primary.key} hook` : "MCP proxy";
|
|
15409
|
-
settingsPath = spec.hookFile ? spec.hookFile(home) : spec.mcpFile ? spec.mcpFile(home) : "";
|
|
15410
|
-
}
|
|
15411
|
-
const mcp = spec.mcpFile ? readMcp(spec.mcpFile(home), spec.mcpFormat ?? "json") : null;
|
|
15412
|
-
const anyHookWired = hooks.some((h) => h.wired);
|
|
15413
|
-
return {
|
|
15414
|
-
id: spec.id,
|
|
15415
|
-
label: spec.label,
|
|
15416
|
-
setupCommand: spec.setupCommand,
|
|
15417
|
-
installed: detected[spec.id],
|
|
15418
|
-
present,
|
|
15419
|
-
hooks,
|
|
15420
|
-
wireState,
|
|
15421
|
-
hookLabel,
|
|
15422
|
-
settingsPath,
|
|
15423
|
-
configFormat: spec.hookFormat === "yaml" ? "YAML" : "JSON",
|
|
15424
|
-
mcpServers: mcp ? mcp.wrapped : null,
|
|
15425
|
-
mcpProtected: mcp ? mcp.present : false,
|
|
15426
|
-
isProtected: anyHookWired || (mcp?.present ?? false)
|
|
15427
|
-
};
|
|
15428
|
-
});
|
|
15429
|
-
}
|
|
15430
|
-
var import_fs26, import_path28, import_os24, yaml2, import_smol_toml2, exists, ck, lg, DEFAULT_LABEL_PAD, hookLabelOf, AGENT_SPECS;
|
|
15431
|
-
var init_agent_wiring = __esm({
|
|
15432
|
-
"src/agent-wiring.ts"() {
|
|
15433
|
-
"use strict";
|
|
15434
|
-
import_fs26 = __toESM(require("fs"));
|
|
15435
|
-
import_path28 = __toESM(require("path"));
|
|
15436
|
-
import_os24 = __toESM(require("os"));
|
|
15437
|
-
yaml2 = __toESM(require("yaml"));
|
|
15438
|
-
import_smol_toml2 = require("smol-toml");
|
|
15439
|
-
init_setup();
|
|
15440
|
-
exists = (p) => {
|
|
15441
|
-
try {
|
|
15442
|
-
return import_fs26.default.existsSync(p);
|
|
15443
|
-
} catch {
|
|
15444
|
-
return false;
|
|
15445
|
-
}
|
|
15446
|
-
};
|
|
15447
|
-
ck = (key) => ({ key, kind: "check" });
|
|
15448
|
-
lg = (key) => ({ key, kind: "log" });
|
|
15449
|
-
DEFAULT_LABEL_PAD = 11;
|
|
15450
|
-
hookLabelOf = (ev, pad) => `${ev.key.padEnd(pad)} (node9 ${ev.kind})`;
|
|
15451
|
-
AGENT_SPECS = [
|
|
15452
|
-
{
|
|
15453
|
-
id: "claude",
|
|
15454
|
-
label: "Claude Code",
|
|
15455
|
-
setupCommand: "node9 agents add claude",
|
|
15456
|
-
hookFile: (h) => import_path28.default.join(h, ".claude", "settings.json"),
|
|
15457
|
-
hookFormat: "matcher",
|
|
15458
|
-
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
15459
|
-
mcpFile: (h) => import_path28.default.join(h, ".claude.json"),
|
|
15460
|
-
present: (h) => exists(import_path28.default.join(h, ".claude", "settings.json")) || exists(import_path28.default.join(h, ".claude.json"))
|
|
15461
|
-
},
|
|
15462
|
-
{
|
|
15463
|
-
id: "gemini",
|
|
15464
|
-
label: "Gemini CLI",
|
|
15465
|
-
setupCommand: "node9 agents add gemini",
|
|
15466
|
-
hookFile: (h) => import_path28.default.join(h, ".gemini", "settings.json"),
|
|
15467
|
-
hookFormat: "matcher",
|
|
15468
|
-
hookEvents: [ck("BeforeTool"), lg("AfterTool")],
|
|
15469
|
-
mcpFile: (h) => import_path28.default.join(h, ".gemini", "settings.json"),
|
|
15470
|
-
present: (h) => exists(import_path28.default.join(h, ".gemini", "settings.json"))
|
|
15471
|
-
},
|
|
15472
|
-
{
|
|
15473
|
-
id: "codex",
|
|
15474
|
-
label: "Codex",
|
|
15475
|
-
setupCommand: "node9 agents add codex",
|
|
15476
|
-
hookFile: (h) => import_path28.default.join(h, ".codex", "hooks.json"),
|
|
15477
|
-
hookFormat: "matcher",
|
|
15478
|
-
hookEvents: [ck("PreToolUse"), ck("UserPromptSubmit")],
|
|
15479
|
-
mcpFile: (h) => import_path28.default.join(h, ".codex", "config.toml"),
|
|
15480
|
-
mcpFormat: "toml",
|
|
15481
|
-
present: (h) => exists(import_path28.default.join(h, ".codex"))
|
|
15482
|
-
},
|
|
15483
|
-
{
|
|
15484
|
-
id: "antigravity",
|
|
15485
|
-
label: "Antigravity",
|
|
15486
|
-
setupCommand: "node9 agents add antigravity",
|
|
15487
|
-
hookFile: (h) => import_path28.default.join(h, ".gemini", "config", "hooks.json"),
|
|
15488
|
-
hookFormat: "matcher",
|
|
15489
|
-
hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
|
|
15490
|
-
mcpFile: (h) => import_path28.default.join(h, ".gemini", "config", "mcp_config.json"),
|
|
15491
|
-
present: (h) => exists(import_path28.default.join(h, ".gemini", "config", "hooks.json")) || exists(import_path28.default.join(h, ".gemini", "antigravity-cli")) || exists(import_path28.default.join(h, ".gemini", "antigravity-ide"))
|
|
15492
|
-
},
|
|
15493
|
-
{
|
|
15494
|
-
id: "copilot",
|
|
15495
|
-
label: "GitHub Copilot",
|
|
15496
|
-
setupCommand: "node9 agents add copilot",
|
|
15497
|
-
hookFile: (h) => import_path28.default.join(h, ".copilot", "hooks", "node9.json"),
|
|
15498
|
-
hookFormat: "flat",
|
|
15499
|
-
hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
|
|
15500
|
-
mcpFile: (h) => import_path28.default.join(h, ".copilot", "mcp-config.json"),
|
|
15501
|
-
present: (h) => exists(import_path28.default.join(h, ".copilot"))
|
|
15502
|
-
},
|
|
15503
|
-
{
|
|
15504
|
-
id: "cursor",
|
|
15505
|
-
label: "Cursor",
|
|
15506
|
-
setupCommand: "node9 agents add cursor",
|
|
15507
|
-
// MCP-only — no hook file (see note above).
|
|
15508
|
-
hookFormat: "flat",
|
|
15509
|
-
hookEvents: [],
|
|
15510
|
-
mcpFile: (h) => import_path28.default.join(h, ".cursor", "mcp.json"),
|
|
15511
|
-
present: (h) => exists(import_path28.default.join(h, ".cursor", "mcp.json"))
|
|
15512
|
-
},
|
|
15513
|
-
{
|
|
15514
|
-
id: "hermes",
|
|
15515
|
-
label: "Hermes Agent",
|
|
15516
|
-
setupCommand: "node9 agents add hermes",
|
|
15517
|
-
hookFile: (h) => hermesConfigPath(h),
|
|
15518
|
-
hookFormat: "yaml",
|
|
15519
|
-
hookEvents: [ck("pre_tool_call"), lg("post_tool_call")],
|
|
15520
|
-
labelPad: 14,
|
|
15521
|
-
// 'post_tool_call' is wider than the default
|
|
15522
|
-
present: (h) => exists(hermesConfigPath(h))
|
|
15523
|
-
},
|
|
15524
|
-
{
|
|
15525
|
-
// Plugin-shim agents — protected by a node9-authored plugin/extension file
|
|
15526
|
-
// (no hooks, no MCP). hookFormat is unused for these (shimFile drives it).
|
|
15527
|
-
id: "opencode",
|
|
15528
|
-
label: "OpenCode",
|
|
15529
|
-
setupCommand: "node9 agents add opencode",
|
|
15530
|
-
hookFormat: "flat",
|
|
15531
|
-
hookEvents: [],
|
|
15532
|
-
shimFile: (h) => import_path28.default.join(h, ".config", "opencode", "plugins", "node9.js"),
|
|
15533
|
-
present: (h) => exists(import_path28.default.join(h, ".config", "opencode")) || exists(import_path28.default.join(h, ".config", "opencode", "plugins", "node9.js"))
|
|
15534
|
-
},
|
|
15535
|
-
{
|
|
15536
|
-
id: "pi",
|
|
15537
|
-
label: "Pi",
|
|
15538
|
-
setupCommand: "node9 agents add pi",
|
|
15539
|
-
hookFormat: "flat",
|
|
15540
|
-
hookEvents: [],
|
|
15541
|
-
shimFile: (h) => import_path28.default.join(h, ".pi", "agent", "extensions", "node9.js"),
|
|
15542
|
-
present: (h) => exists(import_path28.default.join(h, ".pi", "agent")) || exists(import_path28.default.join(h, ".pi", "agent", "extensions", "node9.js"))
|
|
15469
|
+
sessionId: data.sessionId
|
|
15470
|
+
});
|
|
15471
|
+
}
|
|
15472
|
+
} catch {
|
|
15543
15473
|
}
|
|
15544
|
-
|
|
15474
|
+
});
|
|
15475
|
+
socket.on("error", () => {
|
|
15476
|
+
});
|
|
15477
|
+
});
|
|
15478
|
+
unixServer.on("error", (err2) => {
|
|
15479
|
+
logActivitySocket(`server error: ${err2.message}`);
|
|
15480
|
+
});
|
|
15481
|
+
unixServer.listen(ACTIVITY_SOCKET_PATH2, () => {
|
|
15482
|
+
logActivitySocket(`bound to ${ACTIVITY_SOCKET_PATH2}`);
|
|
15483
|
+
});
|
|
15484
|
+
activitySocketServer = unixServer;
|
|
15485
|
+
}
|
|
15486
|
+
var import_net2, import_fs26, import_path28, import_os24, import_crypto8, 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;
|
|
15487
|
+
var init_state2 = __esm({
|
|
15488
|
+
"src/daemon/state.ts"() {
|
|
15489
|
+
"use strict";
|
|
15490
|
+
import_net2 = __toESM(require("net"));
|
|
15491
|
+
import_fs26 = __toESM(require("fs"));
|
|
15492
|
+
import_path28 = __toESM(require("path"));
|
|
15493
|
+
import_os24 = __toESM(require("os"));
|
|
15494
|
+
import_crypto8 = require("crypto");
|
|
15495
|
+
init_daemon();
|
|
15496
|
+
init_suggestion_tracker();
|
|
15497
|
+
init_taint_store();
|
|
15498
|
+
init_session_counters();
|
|
15499
|
+
init_session_history();
|
|
15500
|
+
homeDir = import_os24.default.homedir();
|
|
15501
|
+
DAEMON_PID_FILE = import_path28.default.join(homeDir, ".node9", "daemon.pid");
|
|
15502
|
+
DECISIONS_FILE = import_path28.default.join(homeDir, ".node9", "decisions.json");
|
|
15503
|
+
AUDIT_LOG_FILE = import_path28.default.join(homeDir, ".node9", "audit.log");
|
|
15504
|
+
TRUST_FILE2 = import_path28.default.join(homeDir, ".node9", "trust.json");
|
|
15505
|
+
GLOBAL_CONFIG_FILE = import_path28.default.join(homeDir, ".node9", "config.json");
|
|
15506
|
+
CREDENTIALS_FILE = import_path28.default.join(homeDir, ".node9", "credentials.json");
|
|
15507
|
+
INSIGHT_COUNTS_FILE = import_path28.default.join(homeDir, ".node9", "insight-counts.json");
|
|
15508
|
+
pending = /* @__PURE__ */ new Map();
|
|
15509
|
+
sseClients = /* @__PURE__ */ new Set();
|
|
15510
|
+
suggestionTracker = new SuggestionTracker(3);
|
|
15511
|
+
taintStore = new TaintStore();
|
|
15512
|
+
sessionTaintStore = new SessionTaintStore();
|
|
15513
|
+
insightCounts = /* @__PURE__ */ new Map();
|
|
15514
|
+
_abandonTimer = null;
|
|
15515
|
+
_hadBrowserClient = false;
|
|
15516
|
+
_daemonServer = null;
|
|
15517
|
+
daemonRejectionHandlerRegistered = false;
|
|
15518
|
+
AUTO_DENY_MS = 12e4;
|
|
15519
|
+
TRUST_DURATIONS = {
|
|
15520
|
+
"30m": 30 * 6e4,
|
|
15521
|
+
"1h": 60 * 6e4,
|
|
15522
|
+
"2h": 2 * 60 * 6e4
|
|
15523
|
+
};
|
|
15524
|
+
autoStarted = process.env.NODE9_AUTO_STARTED === "1";
|
|
15525
|
+
ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path28.default.join(import_os24.default.tmpdir(), "node9-activity.sock");
|
|
15526
|
+
ACTIVITY_RING_SIZE = 100;
|
|
15527
|
+
activityRing = [];
|
|
15528
|
+
LARGE_RESPONSE_RING_SIZE = 20;
|
|
15529
|
+
largeResponseRing = [];
|
|
15530
|
+
cachedScanResult = null;
|
|
15531
|
+
cachedScanTs = 0;
|
|
15532
|
+
SCAN_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
15533
|
+
SECRET_KEY_RE = /password|secret|token|key|apikey|credential|auth/i;
|
|
15534
|
+
INPUT_PRICE_PER_1M = 3;
|
|
15535
|
+
OUTPUT_PRICE_PER_1M = 15;
|
|
15536
|
+
BYTES_PER_TOKEN = 4;
|
|
15537
|
+
CRITICAL_FORENSIC_CATEGORIES = /* @__PURE__ */ new Set([
|
|
15538
|
+
"privilege-escalation",
|
|
15539
|
+
"destructive-op",
|
|
15540
|
+
"eval-of-remote"
|
|
15541
|
+
]);
|
|
15542
|
+
WRITE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
15543
|
+
"write",
|
|
15544
|
+
"write_file",
|
|
15545
|
+
"create_file",
|
|
15546
|
+
"edit",
|
|
15547
|
+
"multiedit",
|
|
15548
|
+
"str_replace_based_edit_tool",
|
|
15549
|
+
"replace",
|
|
15550
|
+
"notebook_edit",
|
|
15551
|
+
"notebookedit"
|
|
15552
|
+
]);
|
|
15553
|
+
ACTIVITY_REBIND_MAX_ATTEMPTS = 5;
|
|
15554
|
+
ACTIVITY_REBIND_WINDOW_MS = 6e4;
|
|
15555
|
+
ACTIVITY_HEALTH_PROBE_MS = 2e3;
|
|
15556
|
+
activitySocketServer = null;
|
|
15557
|
+
activityHealthInterval = null;
|
|
15558
|
+
activityRebindAttempts = [];
|
|
15559
|
+
activityCircuitTripped = false;
|
|
15545
15560
|
}
|
|
15546
15561
|
});
|
|
15547
15562
|
|
|
@@ -16643,6 +16658,93 @@ var init_ship = __esm({
|
|
|
16643
16658
|
}
|
|
16644
16659
|
});
|
|
16645
16660
|
|
|
16661
|
+
// src/policy-snapshot/build.ts
|
|
16662
|
+
function buildPolicySnapshot(config, activeShields, overrides) {
|
|
16663
|
+
const p = config.policy;
|
|
16664
|
+
return {
|
|
16665
|
+
mode: config.settings.mode,
|
|
16666
|
+
panicMode: config.settings.panicMode === true,
|
|
16667
|
+
// The proxy expresses shadow/observe as mode === 'observe' (cloud shadowMode
|
|
16668
|
+
// forces it); there's no separate settings flag.
|
|
16669
|
+
shadowMode: config.settings.mode === "observe",
|
|
16670
|
+
activeShields,
|
|
16671
|
+
shieldOverrides: overrides,
|
|
16672
|
+
smartRuleCount: p.smartRules.length,
|
|
16673
|
+
smartRules: p.smartRules.slice(0, MAX_RULES).map((r) => ({
|
|
16674
|
+
name: r.name,
|
|
16675
|
+
tool: r.tool,
|
|
16676
|
+
verdict: r.verdict,
|
|
16677
|
+
reason: r.reason
|
|
16678
|
+
})),
|
|
16679
|
+
egress: {
|
|
16680
|
+
enabled: p.egress.enabled,
|
|
16681
|
+
mode: p.egress.mode,
|
|
16682
|
+
allow: p.egress.allow.slice(0, MAX_EGRESS)
|
|
16683
|
+
},
|
|
16684
|
+
dlpEnabled: p.dlp.enabled,
|
|
16685
|
+
engineVersion: ENGINE_VERSION
|
|
16686
|
+
};
|
|
16687
|
+
}
|
|
16688
|
+
var MAX_RULES, MAX_EGRESS;
|
|
16689
|
+
var init_build = __esm({
|
|
16690
|
+
"src/policy-snapshot/build.ts"() {
|
|
16691
|
+
"use strict";
|
|
16692
|
+
init_dist();
|
|
16693
|
+
MAX_RULES = 500;
|
|
16694
|
+
MAX_EGRESS = 200;
|
|
16695
|
+
}
|
|
16696
|
+
});
|
|
16697
|
+
|
|
16698
|
+
// src/policy-snapshot/ship.ts
|
|
16699
|
+
function policySnapshotUrlFrom(apiUrl) {
|
|
16700
|
+
return apiUrl.endsWith("/policies/sync") ? apiUrl.replace(/\/policies\/sync$/, "/policy/snapshot") : null;
|
|
16701
|
+
}
|
|
16702
|
+
async function shipPolicySnapshot(body, creds) {
|
|
16703
|
+
const url = policySnapshotUrlFrom(creds.apiUrl);
|
|
16704
|
+
if (!url) return false;
|
|
16705
|
+
const payload = JSON.stringify(body);
|
|
16706
|
+
const parsed = new import_url2.URL(url);
|
|
16707
|
+
const transport = parsed.protocol === "http:" ? import_http2.default : import_https3.default;
|
|
16708
|
+
return new Promise((resolve) => {
|
|
16709
|
+
const req = transport.request(
|
|
16710
|
+
{
|
|
16711
|
+
hostname: parsed.hostname,
|
|
16712
|
+
port: parsed.port ? parseInt(parsed.port, 10) : void 0,
|
|
16713
|
+
path: parsed.pathname + parsed.search,
|
|
16714
|
+
method: "POST",
|
|
16715
|
+
headers: {
|
|
16716
|
+
"Content-Type": "application/json",
|
|
16717
|
+
"Content-Length": Buffer.byteLength(payload),
|
|
16718
|
+
Authorization: `Bearer ${creds.apiKey}`
|
|
16719
|
+
},
|
|
16720
|
+
timeout: 1e4
|
|
16721
|
+
},
|
|
16722
|
+
(res) => {
|
|
16723
|
+
const ok2 = !!res.statusCode && res.statusCode >= 200 && res.statusCode < 300;
|
|
16724
|
+
res.resume();
|
|
16725
|
+
res.on("end", () => resolve(ok2));
|
|
16726
|
+
res.on("error", () => resolve(false));
|
|
16727
|
+
}
|
|
16728
|
+
);
|
|
16729
|
+
req.on("error", () => resolve(false));
|
|
16730
|
+
req.on("timeout", () => {
|
|
16731
|
+
req.destroy();
|
|
16732
|
+
resolve(false);
|
|
16733
|
+
});
|
|
16734
|
+
req.write(payload);
|
|
16735
|
+
req.end();
|
|
16736
|
+
});
|
|
16737
|
+
}
|
|
16738
|
+
var import_http2, import_https3, import_url2;
|
|
16739
|
+
var init_ship2 = __esm({
|
|
16740
|
+
"src/policy-snapshot/ship.ts"() {
|
|
16741
|
+
"use strict";
|
|
16742
|
+
import_http2 = __toESM(require("http"));
|
|
16743
|
+
import_https3 = __toESM(require("https"));
|
|
16744
|
+
import_url2 = require("url");
|
|
16745
|
+
}
|
|
16746
|
+
});
|
|
16747
|
+
|
|
16646
16748
|
// src/daemon/sync.ts
|
|
16647
16749
|
function emptySignals3() {
|
|
16648
16750
|
return {
|
|
@@ -16724,7 +16826,7 @@ function fetchCloudPolicy(apiKey, apiUrl, ifNoneMatch) {
|
|
|
16724
16826
|
};
|
|
16725
16827
|
if (ifNoneMatch) headers["If-None-Match"] = `"${ifNoneMatch}"`;
|
|
16726
16828
|
return new Promise((resolve, reject) => {
|
|
16727
|
-
const req =
|
|
16829
|
+
const req = import_https4.default.request(
|
|
16728
16830
|
{
|
|
16729
16831
|
hostname: parsed.hostname,
|
|
16730
16832
|
port: parsed.port ? parseInt(parsed.port, 10) : void 0,
|
|
@@ -16804,6 +16906,9 @@ async function syncOnce() {
|
|
|
16804
16906
|
if (process.env.NODE9_POSTURE_DISABLE !== "1") {
|
|
16805
16907
|
void pushPostureSnapshot(creds);
|
|
16806
16908
|
}
|
|
16909
|
+
if (process.env.NODE9_POLICY_MIRROR_DISABLE !== "1") {
|
|
16910
|
+
void pushPolicySnapshot(creds);
|
|
16911
|
+
}
|
|
16807
16912
|
}
|
|
16808
16913
|
async function pushBlastSnapshot(creds) {
|
|
16809
16914
|
try {
|
|
@@ -16813,7 +16918,7 @@ async function pushBlastSnapshot(creds) {
|
|
|
16813
16918
|
if (!blastUrl) return;
|
|
16814
16919
|
const parsed = new URL(blastUrl);
|
|
16815
16920
|
await new Promise((resolve) => {
|
|
16816
|
-
const req =
|
|
16921
|
+
const req = import_https4.default.request(
|
|
16817
16922
|
{
|
|
16818
16923
|
hostname: parsed.hostname,
|
|
16819
16924
|
port: parsed.port ? parseInt(parsed.port, 10) : void 0,
|
|
@@ -16850,6 +16955,29 @@ async function pushPostureSnapshot(creds) {
|
|
|
16850
16955
|
} catch {
|
|
16851
16956
|
}
|
|
16852
16957
|
}
|
|
16958
|
+
async function pushPolicySnapshot(creds) {
|
|
16959
|
+
try {
|
|
16960
|
+
const body = buildPolicySnapshot(getConfig(), readActiveShields(), readShieldOverrides());
|
|
16961
|
+
await shipPolicySnapshot(body, creds);
|
|
16962
|
+
} catch {
|
|
16963
|
+
}
|
|
16964
|
+
}
|
|
16965
|
+
async function runPolicyPush() {
|
|
16966
|
+
const creds = readCredentials();
|
|
16967
|
+
if (!creds) {
|
|
16968
|
+
return {
|
|
16969
|
+
ok: false,
|
|
16970
|
+
reason: "No API key configured. Add credentials with: node9 login"
|
|
16971
|
+
};
|
|
16972
|
+
}
|
|
16973
|
+
try {
|
|
16974
|
+
const body = buildPolicySnapshot(getConfig(), readActiveShields(), readShieldOverrides());
|
|
16975
|
+
const sent = await shipPolicySnapshot(body, creds);
|
|
16976
|
+
return sent ? { ok: true } : { ok: false, reason: "Push failed (network or server error)" };
|
|
16977
|
+
} catch (e) {
|
|
16978
|
+
return { ok: false, reason: e instanceof Error ? e.message : String(e) };
|
|
16979
|
+
}
|
|
16980
|
+
}
|
|
16853
16981
|
async function pushScanSnapshot(creds) {
|
|
16854
16982
|
try {
|
|
16855
16983
|
const tick = await tickScanWatcher();
|
|
@@ -16867,7 +16995,7 @@ async function pushScanSnapshot(creds) {
|
|
|
16867
16995
|
const parsed = new URL(scanUrl);
|
|
16868
16996
|
let posted = false;
|
|
16869
16997
|
await new Promise((resolve) => {
|
|
16870
|
-
const req =
|
|
16998
|
+
const req = import_https4.default.request(
|
|
16871
16999
|
{
|
|
16872
17000
|
hostname: parsed.hostname,
|
|
16873
17001
|
port: parsed.port ? parseInt(parsed.port, 10) : void 0,
|
|
@@ -16917,6 +17045,9 @@ async function runCloudSync() {
|
|
|
16917
17045
|
if (process.env.NODE9_POSTURE_DISABLE !== "1") {
|
|
16918
17046
|
void pushPostureSnapshot(creds);
|
|
16919
17047
|
}
|
|
17048
|
+
if (process.env.NODE9_POLICY_MIRROR_DISABLE !== "1") {
|
|
17049
|
+
void pushPolicySnapshot(creds);
|
|
17050
|
+
}
|
|
16920
17051
|
};
|
|
16921
17052
|
try {
|
|
16922
17053
|
const result = await fetchCloudPolicy(creds.apiKey, creds.apiUrl, readCachedEtag());
|
|
@@ -16995,18 +17126,21 @@ function startForensicBroadcast() {
|
|
|
16995
17126
|
const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
|
|
16996
17127
|
recurring.unref();
|
|
16997
17128
|
}
|
|
16998
|
-
var import_fs32,
|
|
17129
|
+
var import_fs32, import_https4, import_os29, import_path31, FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_HOURS, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
|
|
16999
17130
|
var init_sync = __esm({
|
|
17000
17131
|
"src/daemon/sync.ts"() {
|
|
17001
17132
|
"use strict";
|
|
17002
17133
|
import_fs32 = __toESM(require("fs"));
|
|
17003
|
-
|
|
17134
|
+
import_https4 = __toESM(require("https"));
|
|
17004
17135
|
import_os29 = __toESM(require("os"));
|
|
17005
17136
|
import_path31 = __toESM(require("path"));
|
|
17006
17137
|
init_config();
|
|
17007
17138
|
init_blast();
|
|
17008
17139
|
init_posture();
|
|
17009
17140
|
init_ship();
|
|
17141
|
+
init_build();
|
|
17142
|
+
init_ship2();
|
|
17143
|
+
init_shields();
|
|
17010
17144
|
init_dist();
|
|
17011
17145
|
init_scan_watermark();
|
|
17012
17146
|
init_state2();
|
|
@@ -17509,7 +17643,7 @@ function startDaemon() {
|
|
|
17509
17643
|
}
|
|
17510
17644
|
resetIdleTimer();
|
|
17511
17645
|
const allowedHosts = /* @__PURE__ */ new Set([`127.0.0.1:${DAEMON_PORT}`, `localhost:${DAEMON_PORT}`]);
|
|
17512
|
-
const server =
|
|
17646
|
+
const server = import_http3.default.createServer(async (req, res) => {
|
|
17513
17647
|
const host = req.headers.host ?? "";
|
|
17514
17648
|
if (!allowedHosts.has(host)) {
|
|
17515
17649
|
res.writeHead(421, { "Content-Type": "text/plain" });
|
|
@@ -18411,11 +18545,11 @@ data: ${JSON.stringify(item.data)}
|
|
|
18411
18545
|
}
|
|
18412
18546
|
startActivitySocket();
|
|
18413
18547
|
}
|
|
18414
|
-
var
|
|
18548
|
+
var import_http3, import_fs36, import_path35, import_os33, import_crypto10, import_child_process2, import_chalk6;
|
|
18415
18549
|
var init_server = __esm({
|
|
18416
18550
|
"src/daemon/server.ts"() {
|
|
18417
18551
|
"use strict";
|
|
18418
|
-
|
|
18552
|
+
import_http3 = __toESM(require("http"));
|
|
18419
18553
|
import_fs36 = __toESM(require("fs"));
|
|
18420
18554
|
import_path35 = __toESM(require("path"));
|
|
18421
18555
|
import_os33 = __toESM(require("os"));
|
|
@@ -18772,18 +18906,18 @@ function getModelContextLimit(model) {
|
|
|
18772
18906
|
return 2e5;
|
|
18773
18907
|
}
|
|
18774
18908
|
function readSessionUsage() {
|
|
18775
|
-
const projectsDir =
|
|
18909
|
+
const projectsDir = import_path62.default.join(import_os55.default.homedir(), ".claude", "projects");
|
|
18776
18910
|
if (!import_fs64.default.existsSync(projectsDir)) return null;
|
|
18777
18911
|
let latestFile = null;
|
|
18778
18912
|
let latestMtime = 0;
|
|
18779
18913
|
try {
|
|
18780
18914
|
for (const dir of import_fs64.default.readdirSync(projectsDir)) {
|
|
18781
|
-
const dirPath =
|
|
18915
|
+
const dirPath = import_path62.default.join(projectsDir, dir);
|
|
18782
18916
|
try {
|
|
18783
18917
|
if (!import_fs64.default.statSync(dirPath).isDirectory()) continue;
|
|
18784
18918
|
for (const file of import_fs64.default.readdirSync(dirPath)) {
|
|
18785
18919
|
if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
|
|
18786
|
-
const filePath =
|
|
18920
|
+
const filePath = import_path62.default.join(dirPath, file);
|
|
18787
18921
|
try {
|
|
18788
18922
|
const mtime = import_fs64.default.statSync(filePath).mtimeMs;
|
|
18789
18923
|
if (mtime > latestMtime) {
|
|
@@ -18861,7 +18995,7 @@ function formatBase(activity) {
|
|
|
18861
18995
|
const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
|
|
18862
18996
|
const icon = getIcon(activity.tool);
|
|
18863
18997
|
const toolName = activity.tool.slice(0, 16).padEnd(16);
|
|
18864
|
-
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(
|
|
18998
|
+
const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os55.default.homedir(), "~");
|
|
18865
18999
|
const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
|
|
18866
19000
|
return `${import_chalk35.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk35.default.white.bold(toolName)} ${import_chalk35.default.dim(argsPreview)}`;
|
|
18867
19001
|
}
|
|
@@ -18943,7 +19077,7 @@ function postDecisionHttp(id, decision, authToken, port, opts) {
|
|
|
18943
19077
|
if (opts?.trustDuration) bodyObj.trustDuration = opts.trustDuration;
|
|
18944
19078
|
if (opts?.reason) bodyObj.reason = opts.reason;
|
|
18945
19079
|
const body = JSON.stringify(bodyObj);
|
|
18946
|
-
const req =
|
|
19080
|
+
const req = import_http4.default.request(
|
|
18947
19081
|
{
|
|
18948
19082
|
hostname: "127.0.0.1",
|
|
18949
19083
|
port,
|
|
@@ -19058,7 +19192,7 @@ function buildRecoveryCardLines(req) {
|
|
|
19058
19192
|
];
|
|
19059
19193
|
}
|
|
19060
19194
|
function readApproversFromDisk() {
|
|
19061
|
-
const configPath =
|
|
19195
|
+
const configPath = import_path62.default.join(import_os55.default.homedir(), ".node9", "config.json");
|
|
19062
19196
|
try {
|
|
19063
19197
|
const raw = JSON.parse(import_fs64.default.readFileSync(configPath, "utf-8"));
|
|
19064
19198
|
const settings = raw.settings ?? {};
|
|
@@ -19076,7 +19210,7 @@ function approverStatusLine() {
|
|
|
19076
19210
|
return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
|
|
19077
19211
|
}
|
|
19078
19212
|
function toggleApprover(channel) {
|
|
19079
|
-
const configPath =
|
|
19213
|
+
const configPath = import_path62.default.join(import_os55.default.homedir(), ".node9", "config.json");
|
|
19080
19214
|
try {
|
|
19081
19215
|
const raw = JSON.parse(import_fs64.default.readFileSync(configPath, "utf-8"));
|
|
19082
19216
|
const settings = raw.settings ?? {};
|
|
@@ -19094,7 +19228,7 @@ async function startTail(options = {}) {
|
|
|
19094
19228
|
const port = await ensureDaemon();
|
|
19095
19229
|
if (options.clear) {
|
|
19096
19230
|
const result = await new Promise((resolve) => {
|
|
19097
|
-
const req2 =
|
|
19231
|
+
const req2 = import_http4.default.request(
|
|
19098
19232
|
{ method: "POST", hostname: "127.0.0.1", port, path: "/events/clear" },
|
|
19099
19233
|
(res) => {
|
|
19100
19234
|
const status = res.statusCode ?? 0;
|
|
@@ -19257,7 +19391,7 @@ async function startTail(options = {}) {
|
|
|
19257
19391
|
postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
|
|
19258
19392
|
try {
|
|
19259
19393
|
import_fs64.default.appendFileSync(
|
|
19260
|
-
|
|
19394
|
+
import_path62.default.join(import_os55.default.homedir(), ".node9", "hook-debug.log"),
|
|
19261
19395
|
`[tail] POST /decision failed: ${String(err2)}
|
|
19262
19396
|
`
|
|
19263
19397
|
);
|
|
@@ -19321,7 +19455,7 @@ async function startTail(options = {}) {
|
|
|
19321
19455
|
};
|
|
19322
19456
|
process.stdin.on("keypress", onKeypress);
|
|
19323
19457
|
}
|
|
19324
|
-
const auditLog =
|
|
19458
|
+
const auditLog = import_path62.default.join(import_os55.default.homedir(), ".node9", "audit.log");
|
|
19325
19459
|
try {
|
|
19326
19460
|
const unackedDlp = import_fs64.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
|
|
19327
19461
|
if (unackedDlp > 0) {
|
|
@@ -19377,7 +19511,7 @@ async function startTail(options = {}) {
|
|
|
19377
19511
|
}, STALL_THRESHOLD_MS / 2);
|
|
19378
19512
|
stallWatchdog.unref();
|
|
19379
19513
|
const sseUrl = `http://127.0.0.1:${port}/events?capabilities=input`;
|
|
19380
|
-
const req =
|
|
19514
|
+
const req = import_http4.default.get(
|
|
19381
19515
|
sseUrl,
|
|
19382
19516
|
{
|
|
19383
19517
|
headers: authToken ? { "X-Node9-Internal": authToken } : {}
|
|
@@ -19548,20 +19682,20 @@ async function startTail(options = {}) {
|
|
|
19548
19682
|
process.exit(1);
|
|
19549
19683
|
});
|
|
19550
19684
|
}
|
|
19551
|
-
var
|
|
19685
|
+
var import_http4, import_chalk35, import_fs64, import_os55, import_path62, import_readline6, import_child_process14, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
|
|
19552
19686
|
var init_tail = __esm({
|
|
19553
19687
|
"src/tui/tail.ts"() {
|
|
19554
19688
|
"use strict";
|
|
19555
|
-
|
|
19689
|
+
import_http4 = __toESM(require("http"));
|
|
19556
19690
|
import_chalk35 = __toESM(require("chalk"));
|
|
19557
19691
|
import_fs64 = __toESM(require("fs"));
|
|
19558
|
-
|
|
19559
|
-
|
|
19692
|
+
import_os55 = __toESM(require("os"));
|
|
19693
|
+
import_path62 = __toESM(require("path"));
|
|
19560
19694
|
import_readline6 = __toESM(require("readline"));
|
|
19561
19695
|
import_child_process14 = require("child_process");
|
|
19562
19696
|
init_daemon2();
|
|
19563
19697
|
init_daemon();
|
|
19564
|
-
PID_FILE =
|
|
19698
|
+
PID_FILE = import_path62.default.join(import_os55.default.homedir(), ".node9", "daemon.pid");
|
|
19565
19699
|
ICONS = {
|
|
19566
19700
|
bash: "\u{1F4BB}",
|
|
19567
19701
|
shell: "\u{1F4BB}",
|
|
@@ -19626,7 +19760,7 @@ function queryDaemon() {
|
|
|
19626
19760
|
return new Promise((resolve) => {
|
|
19627
19761
|
const timeout = setTimeout(() => resolve(null), 50);
|
|
19628
19762
|
try {
|
|
19629
|
-
const req =
|
|
19763
|
+
const req = import_http5.default.get(
|
|
19630
19764
|
`http://${DAEMON_HOST}:${DAEMON_PORT}/status`,
|
|
19631
19765
|
{ timeout: 50 },
|
|
19632
19766
|
(res) => {
|
|
@@ -19711,7 +19845,7 @@ function countRulesInDir(rulesDir) {
|
|
|
19711
19845
|
try {
|
|
19712
19846
|
for (const entry of import_fs65.default.readdirSync(rulesDir, { withFileTypes: true })) {
|
|
19713
19847
|
if (entry.isDirectory()) {
|
|
19714
|
-
count += countRulesInDir(
|
|
19848
|
+
count += countRulesInDir(import_path63.default.join(rulesDir, entry.name));
|
|
19715
19849
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
19716
19850
|
count++;
|
|
19717
19851
|
}
|
|
@@ -19722,46 +19856,46 @@ function countRulesInDir(rulesDir) {
|
|
|
19722
19856
|
}
|
|
19723
19857
|
function isSamePath(a, b) {
|
|
19724
19858
|
try {
|
|
19725
|
-
return
|
|
19859
|
+
return import_path63.default.resolve(a) === import_path63.default.resolve(b);
|
|
19726
19860
|
} catch {
|
|
19727
19861
|
return false;
|
|
19728
19862
|
}
|
|
19729
19863
|
}
|
|
19730
19864
|
function countConfigs(cwd) {
|
|
19731
|
-
const homeDir2 =
|
|
19732
|
-
const claudeDir =
|
|
19865
|
+
const homeDir2 = import_os56.default.homedir();
|
|
19866
|
+
const claudeDir = import_path63.default.join(homeDir2, ".claude");
|
|
19733
19867
|
let claudeMdCount = 0;
|
|
19734
19868
|
let rulesCount = 0;
|
|
19735
19869
|
let hooksCount = 0;
|
|
19736
19870
|
const userMcpServers = /* @__PURE__ */ new Set();
|
|
19737
19871
|
const projectMcpServers = /* @__PURE__ */ new Set();
|
|
19738
|
-
if (import_fs65.default.existsSync(
|
|
19739
|
-
rulesCount += countRulesInDir(
|
|
19740
|
-
const userSettings =
|
|
19872
|
+
if (import_fs65.default.existsSync(import_path63.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
19873
|
+
rulesCount += countRulesInDir(import_path63.default.join(claudeDir, "rules"));
|
|
19874
|
+
const userSettings = import_path63.default.join(claudeDir, "settings.json");
|
|
19741
19875
|
for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
|
|
19742
19876
|
hooksCount += countHooksInFile(userSettings);
|
|
19743
|
-
const userClaudeJson =
|
|
19877
|
+
const userClaudeJson = import_path63.default.join(homeDir2, ".claude.json");
|
|
19744
19878
|
for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
|
|
19745
19879
|
for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
|
|
19746
19880
|
userMcpServers.delete(name);
|
|
19747
19881
|
}
|
|
19748
19882
|
if (cwd) {
|
|
19749
|
-
if (import_fs65.default.existsSync(
|
|
19750
|
-
if (import_fs65.default.existsSync(
|
|
19751
|
-
const projectClaudeDir =
|
|
19883
|
+
if (import_fs65.default.existsSync(import_path63.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
|
|
19884
|
+
if (import_fs65.default.existsSync(import_path63.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
|
|
19885
|
+
const projectClaudeDir = import_path63.default.join(cwd, ".claude");
|
|
19752
19886
|
const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
|
|
19753
19887
|
if (!overlapsUserScope) {
|
|
19754
|
-
if (import_fs65.default.existsSync(
|
|
19755
|
-
rulesCount += countRulesInDir(
|
|
19756
|
-
const projSettings =
|
|
19888
|
+
if (import_fs65.default.existsSync(import_path63.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
|
|
19889
|
+
rulesCount += countRulesInDir(import_path63.default.join(projectClaudeDir, "rules"));
|
|
19890
|
+
const projSettings = import_path63.default.join(projectClaudeDir, "settings.json");
|
|
19757
19891
|
for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
|
|
19758
19892
|
hooksCount += countHooksInFile(projSettings);
|
|
19759
19893
|
}
|
|
19760
|
-
if (import_fs65.default.existsSync(
|
|
19761
|
-
const localSettings =
|
|
19894
|
+
if (import_fs65.default.existsSync(import_path63.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
|
|
19895
|
+
const localSettings = import_path63.default.join(projectClaudeDir, "settings.local.json");
|
|
19762
19896
|
for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
|
|
19763
19897
|
hooksCount += countHooksInFile(localSettings);
|
|
19764
|
-
const mcpJsonServers = getMcpServerNames(
|
|
19898
|
+
const mcpJsonServers = getMcpServerNames(import_path63.default.join(cwd, ".mcp.json"));
|
|
19765
19899
|
const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
|
|
19766
19900
|
for (const name of disabledMcpJson) mcpJsonServers.delete(name);
|
|
19767
19901
|
for (const name of mcpJsonServers) projectMcpServers.add(name);
|
|
@@ -19794,7 +19928,7 @@ function readActiveShieldsHud() {
|
|
|
19794
19928
|
return shieldsCache.value;
|
|
19795
19929
|
}
|
|
19796
19930
|
try {
|
|
19797
|
-
const shieldsPath =
|
|
19931
|
+
const shieldsPath = import_path63.default.join(import_os56.default.homedir(), ".node9", "shields.json");
|
|
19798
19932
|
if (!import_fs65.default.existsSync(shieldsPath)) {
|
|
19799
19933
|
shieldsCache = { value: [], ts: now };
|
|
19800
19934
|
return [];
|
|
@@ -19901,9 +20035,9 @@ function renderContextLine(stdin) {
|
|
|
19901
20035
|
async function main() {
|
|
19902
20036
|
try {
|
|
19903
20037
|
const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
|
|
19904
|
-
if (import_fs65.default.existsSync(
|
|
20038
|
+
if (import_fs65.default.existsSync(import_path63.default.join(import_os56.default.homedir(), ".node9", "hud-debug"))) {
|
|
19905
20039
|
try {
|
|
19906
|
-
const logPath =
|
|
20040
|
+
const logPath = import_path63.default.join(import_os56.default.homedir(), ".node9", "hud-debug.log");
|
|
19907
20041
|
const MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
19908
20042
|
let size = 0;
|
|
19909
20043
|
try {
|
|
@@ -19932,8 +20066,8 @@ async function main() {
|
|
|
19932
20066
|
try {
|
|
19933
20067
|
const cwd = stdin.cwd ?? process.cwd();
|
|
19934
20068
|
for (const configPath of [
|
|
19935
|
-
|
|
19936
|
-
|
|
20069
|
+
import_path63.default.join(cwd, "node9.config.json"),
|
|
20070
|
+
import_path63.default.join(import_os56.default.homedir(), ".node9", "config.json")
|
|
19937
20071
|
]) {
|
|
19938
20072
|
if (!import_fs65.default.existsSync(configPath)) continue;
|
|
19939
20073
|
const cfg = JSON.parse(import_fs65.default.readFileSync(configPath, "utf-8"));
|
|
@@ -19954,14 +20088,14 @@ async function main() {
|
|
|
19954
20088
|
renderOffline();
|
|
19955
20089
|
}
|
|
19956
20090
|
}
|
|
19957
|
-
var import_fs65,
|
|
20091
|
+
var import_fs65, import_path63, import_os56, import_http5, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
|
|
19958
20092
|
var init_hud = __esm({
|
|
19959
20093
|
"src/cli/hud.ts"() {
|
|
19960
20094
|
"use strict";
|
|
19961
20095
|
import_fs65 = __toESM(require("fs"));
|
|
19962
|
-
|
|
19963
|
-
|
|
19964
|
-
|
|
20096
|
+
import_path63 = __toESM(require("path"));
|
|
20097
|
+
import_os56 = __toESM(require("os"));
|
|
20098
|
+
import_http5 = __toESM(require("http"));
|
|
19965
20099
|
init_daemon();
|
|
19966
20100
|
RESET3 = "\x1B[0m";
|
|
19967
20101
|
BOLD3 = "\x1B[1m";
|
|
@@ -19985,11 +20119,44 @@ var init_hud = __esm({
|
|
|
19985
20119
|
var import_commander = require("commander");
|
|
19986
20120
|
init_core();
|
|
19987
20121
|
init_setup();
|
|
20122
|
+
|
|
20123
|
+
// src/agent-teardowns.ts
|
|
20124
|
+
init_setup();
|
|
20125
|
+
var AGENT_TEARDOWNS = [
|
|
20126
|
+
{ id: "claude", label: "Claude", fn: teardownClaude },
|
|
20127
|
+
{ id: "gemini", label: "Gemini", fn: teardownGemini },
|
|
20128
|
+
{ id: "codex", label: "Codex", fn: teardownCodex },
|
|
20129
|
+
{ id: "cursor", label: "Cursor", fn: teardownCursor },
|
|
20130
|
+
{ id: "windsurf", label: "Windsurf", fn: teardownWindsurf },
|
|
20131
|
+
{ id: "vscode", label: "VSCode", fn: teardownVSCode },
|
|
20132
|
+
{ id: "hermes", label: "Hermes", fn: teardownHermes },
|
|
20133
|
+
{ id: "antigravity", label: "Antigravity", fn: teardownAntigravity, aliases: ["agy"] },
|
|
20134
|
+
{ id: "copilot", label: "Copilot", fn: teardownCopilot },
|
|
20135
|
+
{ id: "hud", label: "HUD", fn: teardownHud },
|
|
20136
|
+
{
|
|
20137
|
+
id: "claudedesktop",
|
|
20138
|
+
label: "Claude Desktop",
|
|
20139
|
+
fn: teardownClaudeDesktop,
|
|
20140
|
+
aliases: ["claude-desktop"]
|
|
20141
|
+
},
|
|
20142
|
+
{ id: "opencode", label: "OpenCode", fn: teardownOpencode },
|
|
20143
|
+
{ id: "pi", label: "Pi", fn: teardownPi }
|
|
20144
|
+
];
|
|
20145
|
+
function resolveAgentTeardown(target) {
|
|
20146
|
+
const t = target.trim().toLowerCase();
|
|
20147
|
+
return AGENT_TEARDOWNS.find((a) => a.id === t || a.aliases?.includes(t));
|
|
20148
|
+
}
|
|
20149
|
+
function agentTeardownTargets() {
|
|
20150
|
+
return AGENT_TEARDOWNS.flatMap((a) => [a.id, ...a.aliases ?? []]);
|
|
20151
|
+
}
|
|
20152
|
+
|
|
20153
|
+
// src/cli.ts
|
|
20154
|
+
init_agent_wiring();
|
|
19988
20155
|
init_daemon2();
|
|
19989
20156
|
var import_chalk36 = __toESM(require("chalk"));
|
|
19990
20157
|
var import_fs66 = __toESM(require("fs"));
|
|
19991
|
-
var
|
|
19992
|
-
var
|
|
20158
|
+
var import_path64 = __toESM(require("path"));
|
|
20159
|
+
var import_os57 = __toESM(require("os"));
|
|
19993
20160
|
var import_child_process15 = require("child_process");
|
|
19994
20161
|
var import_prompts2 = require("@inquirer/prompts");
|
|
19995
20162
|
|
|
@@ -21619,6 +21786,8 @@ function registerLogCommand(program2) {
|
|
|
21619
21786
|
// src/cli/commands/shield.ts
|
|
21620
21787
|
var import_chalk10 = __toESM(require("chalk"));
|
|
21621
21788
|
var import_fs46 = __toESM(require("fs"));
|
|
21789
|
+
var import_path44 = __toESM(require("path"));
|
|
21790
|
+
var import_os40 = __toESM(require("os"));
|
|
21622
21791
|
init_shields();
|
|
21623
21792
|
|
|
21624
21793
|
// src/shields/build.ts
|
|
@@ -21749,10 +21918,10 @@ init_audit();
|
|
|
21749
21918
|
init_config();
|
|
21750
21919
|
|
|
21751
21920
|
// src/utils/https-fetch.ts
|
|
21752
|
-
var
|
|
21921
|
+
var import_https5 = __toESM(require("https"));
|
|
21753
21922
|
function httpsFetch(url) {
|
|
21754
21923
|
return new Promise((resolve, reject) => {
|
|
21755
|
-
|
|
21924
|
+
import_https5.default.get(url, (res) => {
|
|
21756
21925
|
if (res.statusCode !== 200) {
|
|
21757
21926
|
reject(new Error(`HTTP ${String(res.statusCode)} for ${url}`));
|
|
21758
21927
|
res.resume();
|
|
@@ -21768,6 +21937,22 @@ function httpsFetch(url) {
|
|
|
21768
21937
|
|
|
21769
21938
|
// src/cli/commands/shield.ts
|
|
21770
21939
|
var COMMUNITY_INDEX_URL = "https://raw.githubusercontent.com/node9ai/node9-proxy/main/shields/community/index.json";
|
|
21940
|
+
function readCloudShields() {
|
|
21941
|
+
const out = /* @__PURE__ */ new Set();
|
|
21942
|
+
try {
|
|
21943
|
+
const file = import_path44.default.join(import_os40.default.homedir(), ".node9", "rules-cache.json");
|
|
21944
|
+
const raw = JSON.parse(import_fs46.default.readFileSync(file, "utf-8"));
|
|
21945
|
+
for (const r of raw.rules ?? []) {
|
|
21946
|
+
const rule = r;
|
|
21947
|
+
const fromSource = rule.source?.startsWith("SHIELD:") ? rule.source.slice("SHIELD:".length).toLowerCase() : void 0;
|
|
21948
|
+
const fromDesc = !fromSource && rule.description ? /\b([a-z0-9-]+)\s+shield/i.exec(rule.description)?.[1]?.toLowerCase() : void 0;
|
|
21949
|
+
const name = fromSource ?? fromDesc;
|
|
21950
|
+
if (name) out.add(name);
|
|
21951
|
+
}
|
|
21952
|
+
} catch {
|
|
21953
|
+
}
|
|
21954
|
+
return out;
|
|
21955
|
+
}
|
|
21771
21956
|
function registerShieldCommand(program2) {
|
|
21772
21957
|
const shieldCmd = program2.command("shield").description("Manage pre-packaged security shield templates");
|
|
21773
21958
|
shieldCmd.command("enable <service>").description("Enable a security shield for a specific service").action((service) => {
|
|
@@ -21854,10 +22039,17 @@ function registerShieldCommand(program2) {
|
|
|
21854
22039
|
return;
|
|
21855
22040
|
}
|
|
21856
22041
|
const active = new Set(readActiveShields());
|
|
22042
|
+
const cloud = readCloudShields();
|
|
21857
22043
|
console.log(import_chalk10.default.bold("\n\u{1F6E1}\uFE0F Available Shields\n"));
|
|
22044
|
+
console.log(import_chalk10.default.gray(" \u25CF local \xB7 \u2601 cloud\n"));
|
|
21858
22045
|
for (const shield of listShields()) {
|
|
21859
|
-
const
|
|
21860
|
-
|
|
22046
|
+
const isLocal = active.has(shield.name);
|
|
22047
|
+
const isCloud = cloud.has(shield.name);
|
|
22048
|
+
const status = isLocal && isCloud ? import_chalk10.default.green("\u25CF\u2601 enabled ") : isLocal ? import_chalk10.default.green("\u25CF enabled ") : isCloud ? import_chalk10.default.cyan("\u2601 cloud ") : import_chalk10.default.gray("\u25CB disabled");
|
|
22049
|
+
const via = isCloud && !isLocal ? import_chalk10.default.gray(" (via dashboard)") : "";
|
|
22050
|
+
console.log(
|
|
22051
|
+
` ${status} ${import_chalk10.default.cyan(shield.name.padEnd(12))} ${shield.description}${via}`
|
|
22052
|
+
);
|
|
21861
22053
|
if (shield.aliases.length > 0)
|
|
21862
22054
|
console.log(import_chalk10.default.gray(` aliases: ${shield.aliases.join(", ")}`));
|
|
21863
22055
|
}
|
|
@@ -22187,15 +22379,15 @@ function registerConfigShowCommand(program2) {
|
|
|
22187
22379
|
// src/cli/commands/doctor.ts
|
|
22188
22380
|
var import_chalk11 = __toESM(require("chalk"));
|
|
22189
22381
|
var import_fs47 = __toESM(require("fs"));
|
|
22190
|
-
var
|
|
22191
|
-
var
|
|
22382
|
+
var import_path45 = __toESM(require("path"));
|
|
22383
|
+
var import_os41 = __toESM(require("os"));
|
|
22192
22384
|
var import_child_process8 = require("child_process");
|
|
22193
22385
|
init_daemon();
|
|
22194
22386
|
init_config();
|
|
22195
22387
|
init_agent_wiring();
|
|
22196
22388
|
function registerDoctorCommand(program2, version2) {
|
|
22197
22389
|
program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
|
|
22198
|
-
const homeDir2 =
|
|
22390
|
+
const homeDir2 = import_os41.default.homedir();
|
|
22199
22391
|
let failures = 0;
|
|
22200
22392
|
function pass(msg) {
|
|
22201
22393
|
console.log(import_chalk11.default.green(" \u2705 ") + msg);
|
|
@@ -22241,7 +22433,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
22241
22433
|
);
|
|
22242
22434
|
}
|
|
22243
22435
|
section("Configuration");
|
|
22244
|
-
const globalConfigPath =
|
|
22436
|
+
const globalConfigPath = import_path45.default.join(homeDir2, ".node9", "config.json");
|
|
22245
22437
|
if (import_fs47.default.existsSync(globalConfigPath)) {
|
|
22246
22438
|
try {
|
|
22247
22439
|
JSON.parse(import_fs47.default.readFileSync(globalConfigPath, "utf-8"));
|
|
@@ -22252,7 +22444,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
22252
22444
|
} else {
|
|
22253
22445
|
warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
|
|
22254
22446
|
}
|
|
22255
|
-
const projectConfigPath =
|
|
22447
|
+
const projectConfigPath = import_path45.default.join(process.cwd(), "node9.config.json");
|
|
22256
22448
|
if (import_fs47.default.existsSync(projectConfigPath)) {
|
|
22257
22449
|
try {
|
|
22258
22450
|
JSON.parse(import_fs47.default.readFileSync(projectConfigPath, "utf-8"));
|
|
@@ -22264,7 +22456,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
22264
22456
|
);
|
|
22265
22457
|
}
|
|
22266
22458
|
}
|
|
22267
|
-
const credsPath =
|
|
22459
|
+
const credsPath = import_path45.default.join(homeDir2, ".node9", "credentials.json");
|
|
22268
22460
|
if (import_fs47.default.existsSync(credsPath)) {
|
|
22269
22461
|
pass("Cloud credentials found (~/.node9/credentials.json)");
|
|
22270
22462
|
} else {
|
|
@@ -22309,7 +22501,7 @@ function registerDoctorCommand(program2, version2) {
|
|
|
22309
22501
|
try {
|
|
22310
22502
|
const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
|
|
22311
22503
|
const cfg = getConfig();
|
|
22312
|
-
const creds = import_fs47.default.existsSync(
|
|
22504
|
+
const creds = import_fs47.default.existsSync(import_path45.default.join(import_os41.default.homedir(), ".node9", "credentials.json"));
|
|
22313
22505
|
if (!creds) {
|
|
22314
22506
|
warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
|
|
22315
22507
|
} else if (!cfg.settings.approvers.cloud) {
|
|
@@ -22360,8 +22552,8 @@ function registerDoctorCommand(program2, version2) {
|
|
|
22360
22552
|
// src/cli/commands/audit.ts
|
|
22361
22553
|
var import_chalk12 = __toESM(require("chalk"));
|
|
22362
22554
|
var import_fs48 = __toESM(require("fs"));
|
|
22363
|
-
var
|
|
22364
|
-
var
|
|
22555
|
+
var import_path46 = __toESM(require("path"));
|
|
22556
|
+
var import_os42 = __toESM(require("os"));
|
|
22365
22557
|
function formatRelativeTime(timestamp) {
|
|
22366
22558
|
const diff = Date.now() - new Date(timestamp).getTime();
|
|
22367
22559
|
const sec = Math.floor(diff / 1e3);
|
|
@@ -22374,7 +22566,7 @@ function formatRelativeTime(timestamp) {
|
|
|
22374
22566
|
}
|
|
22375
22567
|
function registerAuditCommand(program2) {
|
|
22376
22568
|
program2.command("audit").description("View local execution audit log").option("--tail <n>", "Number of entries to show", "20").option("--tool <pattern>", "Filter by tool name (substring match)").option("--deny", "Show only denied actions").option("--json", "Output raw JSON").action((options) => {
|
|
22377
|
-
const logPath =
|
|
22569
|
+
const logPath = import_path46.default.join(import_os42.default.homedir(), ".node9", "audit.log");
|
|
22378
22570
|
if (!import_fs48.default.existsSync(logPath)) {
|
|
22379
22571
|
console.log(
|
|
22380
22572
|
import_chalk12.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
|
|
@@ -22438,8 +22630,8 @@ var import_chalk13 = __toESM(require("chalk"));
|
|
|
22438
22630
|
|
|
22439
22631
|
// src/cli/aggregate/report-audit.ts
|
|
22440
22632
|
var import_fs49 = __toESM(require("fs"));
|
|
22441
|
-
var
|
|
22442
|
-
var
|
|
22633
|
+
var import_os43 = __toESM(require("os"));
|
|
22634
|
+
var import_path47 = __toESM(require("path"));
|
|
22443
22635
|
init_costSync();
|
|
22444
22636
|
init_litellm();
|
|
22445
22637
|
init_cost_codex();
|
|
@@ -22570,7 +22762,7 @@ function freezeClaudeCost(acc) {
|
|
|
22570
22762
|
};
|
|
22571
22763
|
}
|
|
22572
22764
|
function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
22573
|
-
const projPath =
|
|
22765
|
+
const projPath = import_path47.default.join(projectsDir, proj);
|
|
22574
22766
|
let files;
|
|
22575
22767
|
try {
|
|
22576
22768
|
const stat = import_fs49.default.statSync(projPath);
|
|
@@ -22581,7 +22773,7 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
|
|
|
22581
22773
|
}
|
|
22582
22774
|
const startMs = start.getTime();
|
|
22583
22775
|
for (const file of files) {
|
|
22584
|
-
const filePath =
|
|
22776
|
+
const filePath = import_path47.default.join(projPath, file);
|
|
22585
22777
|
try {
|
|
22586
22778
|
if (import_fs49.default.statSync(filePath).mtimeMs < startMs) continue;
|
|
22587
22779
|
} catch {
|
|
@@ -22711,28 +22903,28 @@ function listCodexSessionFiles2(sessionsBase) {
|
|
|
22711
22903
|
if (!import_fs49.default.existsSync(sessionsBase)) return jsonlFiles;
|
|
22712
22904
|
try {
|
|
22713
22905
|
for (const year of import_fs49.default.readdirSync(sessionsBase)) {
|
|
22714
|
-
const yearPath =
|
|
22906
|
+
const yearPath = import_path47.default.join(sessionsBase, year);
|
|
22715
22907
|
try {
|
|
22716
22908
|
if (!import_fs49.default.statSync(yearPath).isDirectory()) continue;
|
|
22717
22909
|
} catch {
|
|
22718
22910
|
continue;
|
|
22719
22911
|
}
|
|
22720
22912
|
for (const month of import_fs49.default.readdirSync(yearPath)) {
|
|
22721
|
-
const monthPath =
|
|
22913
|
+
const monthPath = import_path47.default.join(yearPath, month);
|
|
22722
22914
|
try {
|
|
22723
22915
|
if (!import_fs49.default.statSync(monthPath).isDirectory()) continue;
|
|
22724
22916
|
} catch {
|
|
22725
22917
|
continue;
|
|
22726
22918
|
}
|
|
22727
22919
|
for (const day of import_fs49.default.readdirSync(monthPath)) {
|
|
22728
|
-
const dayPath =
|
|
22920
|
+
const dayPath = import_path47.default.join(monthPath, day);
|
|
22729
22921
|
try {
|
|
22730
22922
|
if (!import_fs49.default.statSync(dayPath).isDirectory()) continue;
|
|
22731
22923
|
} catch {
|
|
22732
22924
|
continue;
|
|
22733
22925
|
}
|
|
22734
22926
|
for (const file of import_fs49.default.readdirSync(dayPath)) {
|
|
22735
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
22927
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path47.default.join(dayPath, file));
|
|
22736
22928
|
}
|
|
22737
22929
|
}
|
|
22738
22930
|
}
|
|
@@ -22858,7 +23050,7 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
22858
23050
|
return out;
|
|
22859
23051
|
}
|
|
22860
23052
|
for (const proj of dirs) {
|
|
22861
|
-
const chatsDir =
|
|
23053
|
+
const chatsDir = import_path47.default.join(geminiTmpDir2, proj, "chats");
|
|
22862
23054
|
let files;
|
|
22863
23055
|
try {
|
|
22864
23056
|
if (!import_fs49.default.statSync(chatsDir).isDirectory()) continue;
|
|
@@ -22868,7 +23060,7 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
|
|
|
22868
23060
|
}
|
|
22869
23061
|
for (const f of files) {
|
|
22870
23062
|
if (!f.endsWith(".jsonl")) continue;
|
|
22871
|
-
out.push({ projectKey: proj, file:
|
|
23063
|
+
out.push({ projectKey: proj, file: import_path47.default.join(chatsDir, f) });
|
|
22872
23064
|
}
|
|
22873
23065
|
}
|
|
22874
23066
|
return out;
|
|
@@ -22883,10 +23075,10 @@ function loadGeminiCost(start, end, geminiTmpDir2) {
|
|
|
22883
23075
|
}
|
|
22884
23076
|
function aggregateReportFromAudit(period, opts = {}) {
|
|
22885
23077
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
22886
|
-
const auditLogPath = opts.auditLogPath ??
|
|
22887
|
-
const claudeProjectsDir = opts.claudeProjectsDir ??
|
|
22888
|
-
const codexSessionsDir2 = opts.codexSessionsDir ??
|
|
22889
|
-
const geminiTmpDir2 = opts.geminiTmpDir ??
|
|
23078
|
+
const auditLogPath = opts.auditLogPath ?? import_path47.default.join(import_os43.default.homedir(), ".node9", "audit.log");
|
|
23079
|
+
const claudeProjectsDir = opts.claudeProjectsDir ?? import_path47.default.join(import_os43.default.homedir(), ".claude", "projects");
|
|
23080
|
+
const codexSessionsDir2 = opts.codexSessionsDir ?? import_path47.default.join(import_os43.default.homedir(), ".codex", "sessions");
|
|
23081
|
+
const geminiTmpDir2 = opts.geminiTmpDir ?? import_path47.default.join(import_os43.default.homedir(), ".gemini", "tmp");
|
|
22890
23082
|
const hasAuditFile = import_fs49.default.existsSync(auditLogPath);
|
|
22891
23083
|
const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
|
|
22892
23084
|
const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
|
|
@@ -23584,8 +23776,8 @@ function registerDaemonCommand(program2) {
|
|
|
23584
23776
|
// src/cli/commands/status.ts
|
|
23585
23777
|
var import_chalk15 = __toESM(require("chalk"));
|
|
23586
23778
|
var import_fs50 = __toESM(require("fs"));
|
|
23587
|
-
var
|
|
23588
|
-
var
|
|
23779
|
+
var import_path48 = __toESM(require("path"));
|
|
23780
|
+
var import_os44 = __toESM(require("os"));
|
|
23589
23781
|
init_core();
|
|
23590
23782
|
init_daemon();
|
|
23591
23783
|
init_agent_wiring();
|
|
@@ -23642,8 +23834,8 @@ function registerStatusCommand(program2) {
|
|
|
23642
23834
|
console.log("");
|
|
23643
23835
|
const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
|
|
23644
23836
|
console.log(` Mode: ${modeLabel}`);
|
|
23645
|
-
const projectConfig =
|
|
23646
|
-
const globalConfig =
|
|
23837
|
+
const projectConfig = import_path48.default.join(process.cwd(), "node9.config.json");
|
|
23838
|
+
const globalConfig = import_path48.default.join(import_os44.default.homedir(), ".node9", "config.json");
|
|
23647
23839
|
console.log(
|
|
23648
23840
|
` Local: ${import_fs50.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
|
|
23649
23841
|
);
|
|
@@ -23655,7 +23847,7 @@ function registerStatusCommand(program2) {
|
|
|
23655
23847
|
` Sandbox: ${import_chalk15.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
|
|
23656
23848
|
);
|
|
23657
23849
|
}
|
|
23658
|
-
const wiring = getAgentWiring(
|
|
23850
|
+
const wiring = getAgentWiring(import_os44.default.homedir()).filter((a) => a.present);
|
|
23659
23851
|
if (wiring.length > 0) {
|
|
23660
23852
|
console.log("");
|
|
23661
23853
|
console.log(import_chalk15.default.bold(" Agent Wiring:"));
|
|
@@ -23691,9 +23883,9 @@ function registerStatusCommand(program2) {
|
|
|
23691
23883
|
// src/cli/commands/init.ts
|
|
23692
23884
|
var import_chalk16 = __toESM(require("chalk"));
|
|
23693
23885
|
var import_fs51 = __toESM(require("fs"));
|
|
23694
|
-
var
|
|
23695
|
-
var
|
|
23696
|
-
var
|
|
23886
|
+
var import_path49 = __toESM(require("path"));
|
|
23887
|
+
var import_os45 = __toESM(require("os"));
|
|
23888
|
+
var import_https6 = __toESM(require("https"));
|
|
23697
23889
|
init_core();
|
|
23698
23890
|
init_setup();
|
|
23699
23891
|
init_shields();
|
|
@@ -23711,7 +23903,7 @@ function buildTelemetryPayload(agents, firstInstall) {
|
|
|
23711
23903
|
function fireTelemetryPing(agents, firstInstall) {
|
|
23712
23904
|
try {
|
|
23713
23905
|
const body = JSON.stringify(buildTelemetryPayload(agents, firstInstall));
|
|
23714
|
-
const req =
|
|
23906
|
+
const req = import_https6.default.request(
|
|
23715
23907
|
{
|
|
23716
23908
|
hostname: "api.node9.ai",
|
|
23717
23909
|
path: "/api/v1/telemetry",
|
|
@@ -23782,7 +23974,7 @@ function registerInitCommand(program2) {
|
|
|
23782
23974
|
}
|
|
23783
23975
|
console.log("");
|
|
23784
23976
|
}
|
|
23785
|
-
const configPath =
|
|
23977
|
+
const configPath = import_path49.default.join(import_os45.default.homedir(), ".node9", "config.json");
|
|
23786
23978
|
const isFirstInstall = !import_fs51.default.existsSync(configPath);
|
|
23787
23979
|
if (import_fs51.default.existsSync(configPath) && !options.force) {
|
|
23788
23980
|
try {
|
|
@@ -23804,7 +23996,7 @@ function registerInitCommand(program2) {
|
|
|
23804
23996
|
...DEFAULT_CONFIG,
|
|
23805
23997
|
settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
|
|
23806
23998
|
};
|
|
23807
|
-
const dir =
|
|
23999
|
+
const dir = import_path49.default.dirname(configPath);
|
|
23808
24000
|
if (!import_fs51.default.existsSync(dir)) import_fs51.default.mkdirSync(dir, { recursive: true });
|
|
23809
24001
|
import_fs51.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
|
|
23810
24002
|
console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
|
|
@@ -23911,7 +24103,7 @@ function registerInitCommand(program2) {
|
|
|
23911
24103
|
}
|
|
23912
24104
|
|
|
23913
24105
|
// src/cli/commands/undo.ts
|
|
23914
|
-
var
|
|
24106
|
+
var import_path50 = __toESM(require("path"));
|
|
23915
24107
|
var import_chalk18 = __toESM(require("chalk"));
|
|
23916
24108
|
|
|
23917
24109
|
// src/tui/undo-navigator.ts
|
|
@@ -24070,7 +24262,7 @@ function findMatchingCwd(startDir, history) {
|
|
|
24070
24262
|
let dir = startDir;
|
|
24071
24263
|
while (true) {
|
|
24072
24264
|
if (cwds.has(dir)) return dir;
|
|
24073
|
-
const parent =
|
|
24265
|
+
const parent = import_path50.default.dirname(dir);
|
|
24074
24266
|
if (parent === dir) return null;
|
|
24075
24267
|
dir = parent;
|
|
24076
24268
|
}
|
|
@@ -24706,8 +24898,8 @@ function registerMcpGatewayCommand(program2) {
|
|
|
24706
24898
|
// src/mcp-server/index.ts
|
|
24707
24899
|
var import_readline5 = __toESM(require("readline"));
|
|
24708
24900
|
var import_fs53 = __toESM(require("fs"));
|
|
24709
|
-
var
|
|
24710
|
-
var
|
|
24901
|
+
var import_os47 = __toESM(require("os"));
|
|
24902
|
+
var import_path52 = __toESM(require("path"));
|
|
24711
24903
|
var import_child_process11 = require("child_process");
|
|
24712
24904
|
init_core();
|
|
24713
24905
|
init_daemon();
|
|
@@ -24715,8 +24907,8 @@ init_shields();
|
|
|
24715
24907
|
|
|
24716
24908
|
// src/auth/egress-config.ts
|
|
24717
24909
|
var import_fs52 = __toESM(require("fs"));
|
|
24718
|
-
var
|
|
24719
|
-
var
|
|
24910
|
+
var import_os46 = __toESM(require("os"));
|
|
24911
|
+
var import_path51 = __toESM(require("path"));
|
|
24720
24912
|
var DEFAULT_EGRESS = {
|
|
24721
24913
|
enabled: false,
|
|
24722
24914
|
mode: "review",
|
|
@@ -24725,7 +24917,7 @@ var DEFAULT_EGRESS = {
|
|
|
24725
24917
|
allowPrivate: true
|
|
24726
24918
|
};
|
|
24727
24919
|
function egressConfigPath() {
|
|
24728
|
-
return
|
|
24920
|
+
return import_path51.default.join(import_os46.default.homedir(), ".node9", "config.json");
|
|
24729
24921
|
}
|
|
24730
24922
|
function readEgressRawConfig() {
|
|
24731
24923
|
let text;
|
|
@@ -24745,7 +24937,7 @@ function readEgressRawConfig() {
|
|
|
24745
24937
|
}
|
|
24746
24938
|
function writeEgressRawConfig(config) {
|
|
24747
24939
|
const p = egressConfigPath();
|
|
24748
|
-
import_fs52.default.mkdirSync(
|
|
24940
|
+
import_fs52.default.mkdirSync(import_path51.default.dirname(p), { recursive: true });
|
|
24749
24941
|
import_fs52.default.writeFileSync(p, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
|
|
24750
24942
|
}
|
|
24751
24943
|
function applyEgress(config, change) {
|
|
@@ -25131,8 +25323,8 @@ function handleStatus() {
|
|
|
25131
25323
|
lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
|
|
25132
25324
|
lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
|
|
25133
25325
|
lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
|
|
25134
|
-
const projectConfig =
|
|
25135
|
-
const globalConfig =
|
|
25326
|
+
const projectConfig = import_path52.default.join(process.cwd(), "node9.config.json");
|
|
25327
|
+
const globalConfig = import_path52.default.join(import_os47.default.homedir(), ".node9", "config.json");
|
|
25136
25328
|
lines.push(
|
|
25137
25329
|
`Project config (node9.config.json): ${import_fs53.default.existsSync(projectConfig) ? "present" : "not found"}`
|
|
25138
25330
|
);
|
|
@@ -25243,7 +25435,7 @@ function handleEgressDeny(args) {
|
|
|
25243
25435
|
addEgressHost("deny", host);
|
|
25244
25436
|
return `Denied egress to ${host} (deny always wins over allow).`;
|
|
25245
25437
|
}
|
|
25246
|
-
var GLOBAL_CONFIG_PATH =
|
|
25438
|
+
var GLOBAL_CONFIG_PATH = import_path52.default.join(import_os47.default.homedir(), ".node9", "config.json");
|
|
25247
25439
|
var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
|
|
25248
25440
|
function readGlobalConfigRaw() {
|
|
25249
25441
|
try {
|
|
@@ -25255,7 +25447,7 @@ function readGlobalConfigRaw() {
|
|
|
25255
25447
|
return {};
|
|
25256
25448
|
}
|
|
25257
25449
|
function writeGlobalConfigRaw(data) {
|
|
25258
|
-
const dir =
|
|
25450
|
+
const dir = import_path52.default.dirname(GLOBAL_CONFIG_PATH);
|
|
25259
25451
|
if (!import_fs53.default.existsSync(dir)) import_fs53.default.mkdirSync(dir, { recursive: true });
|
|
25260
25452
|
import_fs53.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
|
|
25261
25453
|
}
|
|
@@ -25301,7 +25493,7 @@ function handleApproverSet(args) {
|
|
|
25301
25493
|
function handleAuditGet(args) {
|
|
25302
25494
|
const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
|
|
25303
25495
|
const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
|
|
25304
|
-
const auditPath =
|
|
25496
|
+
const auditPath = import_path52.default.join(import_os47.default.homedir(), ".node9", "audit.log");
|
|
25305
25497
|
if (!import_fs53.default.existsSync(auditPath)) return "No audit log found.";
|
|
25306
25498
|
const rawLines = import_fs53.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
25307
25499
|
const parsed = [];
|
|
@@ -25809,6 +26001,17 @@ var import_chalk22 = __toESM(require("chalk"));
|
|
|
25809
26001
|
init_sync();
|
|
25810
26002
|
function registerSyncCommand(program2) {
|
|
25811
26003
|
const policy = program2.command("policy").description("Manage cloud policy rules");
|
|
26004
|
+
policy.command("push").description("Push this machine's effective policy to the node9 dashboard").action(async () => {
|
|
26005
|
+
process.stdout.write(import_chalk22.default.cyan("Pushing policy to the dashboard\u2026"));
|
|
26006
|
+
const result = await runPolicyPush();
|
|
26007
|
+
process.stdout.write("\n");
|
|
26008
|
+
if (!result.ok) {
|
|
26009
|
+
console.error(import_chalk22.default.red(`\u2717 ${result.reason}`));
|
|
26010
|
+
process.exit(1);
|
|
26011
|
+
}
|
|
26012
|
+
console.log(import_chalk22.default.green("\u2713 Policy mirrored to the dashboard"));
|
|
26013
|
+
console.log(import_chalk22.default.gray(" See it under Security Policy \u2192 Machines"));
|
|
26014
|
+
});
|
|
25812
26015
|
policy.command("sync").description("Sync cloud policy rules to local cache (~/.node9/rules-cache.json)").action(async () => {
|
|
25813
26016
|
process.stdout.write(import_chalk22.default.cyan("Syncing cloud policy rules\u2026"));
|
|
25814
26017
|
const result = await runCloudSync();
|
|
@@ -26257,12 +26460,12 @@ var import_chalk27 = __toESM(require("chalk"));
|
|
|
26257
26460
|
|
|
26258
26461
|
// src/shields/jail.ts
|
|
26259
26462
|
var import_fs55 = __toESM(require("fs"));
|
|
26260
|
-
var
|
|
26261
|
-
var
|
|
26463
|
+
var import_os48 = __toESM(require("os"));
|
|
26464
|
+
var import_path53 = __toESM(require("path"));
|
|
26262
26465
|
init_shields();
|
|
26263
26466
|
var USER_JAIL_SHIELD = "user-jail";
|
|
26264
26467
|
function jailStorePath() {
|
|
26265
|
-
return
|
|
26468
|
+
return import_path53.default.join(import_os48.default.homedir(), ".node9", "jail-paths.json");
|
|
26266
26469
|
}
|
|
26267
26470
|
function readJailPaths() {
|
|
26268
26471
|
let text;
|
|
@@ -26285,7 +26488,7 @@ function readJailPaths() {
|
|
|
26285
26488
|
}
|
|
26286
26489
|
function writeJailPaths(paths) {
|
|
26287
26490
|
const p = jailStorePath();
|
|
26288
|
-
import_fs55.default.mkdirSync(
|
|
26491
|
+
import_fs55.default.mkdirSync(import_path53.default.dirname(p), { recursive: true });
|
|
26289
26492
|
import_fs55.default.writeFileSync(p, JSON.stringify({ paths }, null, 2) + "\n", { mode: 384 });
|
|
26290
26493
|
}
|
|
26291
26494
|
function addJailPath(rawPath, verdict) {
|
|
@@ -26308,7 +26511,7 @@ function removeJailPath(rawPath) {
|
|
|
26308
26511
|
return { removed, paths: after };
|
|
26309
26512
|
}
|
|
26310
26513
|
function regenerateUserJail(paths) {
|
|
26311
|
-
const file =
|
|
26514
|
+
const file = import_path53.default.join(USER_SHIELDS_DIR_PATH, `${USER_JAIL_SHIELD}.json`);
|
|
26312
26515
|
if (paths.length === 0) {
|
|
26313
26516
|
const active2 = readActiveShields();
|
|
26314
26517
|
if (active2.includes(USER_JAIL_SHIELD)) {
|
|
@@ -26430,13 +26633,13 @@ function registerJailCommand(program2) {
|
|
|
26430
26633
|
// src/cli/commands/sandbox.ts
|
|
26431
26634
|
var import_chalk28 = __toESM(require("chalk"));
|
|
26432
26635
|
var import_fs58 = __toESM(require("fs"));
|
|
26433
|
-
var
|
|
26636
|
+
var import_path56 = __toESM(require("path"));
|
|
26434
26637
|
var import_child_process13 = require("child_process");
|
|
26435
26638
|
init_config();
|
|
26436
26639
|
|
|
26437
26640
|
// src/sandbox/config.ts
|
|
26438
26641
|
var import_fs56 = __toESM(require("fs"));
|
|
26439
|
-
var
|
|
26642
|
+
var import_path54 = __toESM(require("path"));
|
|
26440
26643
|
var import_yaml = require("yaml");
|
|
26441
26644
|
var SANDBOX_CONFIG_FILE = "node9.sandbox.yaml";
|
|
26442
26645
|
var FORBIDDEN_ENV = /* @__PURE__ */ new Set(["NODE9_API_KEY", "NODE9_API_URL"]);
|
|
@@ -26509,7 +26712,7 @@ function scaffoldSandboxYaml(agent) {
|
|
|
26509
26712
|
return header + (0, import_yaml.stringify)(defaultSandboxConfig(agent));
|
|
26510
26713
|
}
|
|
26511
26714
|
function sandboxConfigPath(cwd = process.cwd()) {
|
|
26512
|
-
return
|
|
26715
|
+
return import_path54.default.join(cwd, SANDBOX_CONFIG_FILE);
|
|
26513
26716
|
}
|
|
26514
26717
|
function loadSandboxConfig(cwd = process.cwd(), fallbackAgent = "claude") {
|
|
26515
26718
|
const p = sandboxConfigPath(cwd);
|
|
@@ -26577,13 +26780,13 @@ init_templates();
|
|
|
26577
26780
|
|
|
26578
26781
|
// src/sandbox/runtime.ts
|
|
26579
26782
|
var import_fs57 = __toESM(require("fs"));
|
|
26580
|
-
var
|
|
26581
|
-
var
|
|
26783
|
+
var import_os49 = __toESM(require("os"));
|
|
26784
|
+
var import_path55 = __toESM(require("path"));
|
|
26582
26785
|
var import_crypto13 = __toESM(require("crypto"));
|
|
26583
26786
|
var import_child_process12 = require("child_process");
|
|
26584
26787
|
init_templates();
|
|
26585
26788
|
function sandboxDataDir(cwd = process.cwd()) {
|
|
26586
|
-
return
|
|
26789
|
+
return import_path55.default.join(cwd, ".node9", "sandbox", "data");
|
|
26587
26790
|
}
|
|
26588
26791
|
function detectEngine(engine) {
|
|
26589
26792
|
const r = (0, import_child_process12.spawnSync)(engine, ["--version"], { encoding: "utf-8" });
|
|
@@ -26594,7 +26797,7 @@ function detectEngine(engine) {
|
|
|
26594
26797
|
}
|
|
26595
26798
|
function agentCredentialsMount(agent) {
|
|
26596
26799
|
const rel = agent === "codex" ? ".codex/auth.json" : ".claude/.credentials.json";
|
|
26597
|
-
return { hostPath:
|
|
26800
|
+
return { hostPath: import_path55.default.join(import_os49.default.homedir(), rel), target: `/home/${RUN_AS_USER}/${rel}` };
|
|
26598
26801
|
}
|
|
26599
26802
|
function buildRunArgs(opts) {
|
|
26600
26803
|
const { config, workspaceHostPath, dataHostPath, allowlistHostPath, agentArgs } = opts;
|
|
@@ -26622,30 +26825,30 @@ function imageContentHash(dockerfile, entrypoint) {
|
|
|
26622
26825
|
return import_crypto13.default.createHash("sha256").update(dockerfile).update("\0").update(entrypoint).digest("hex").slice(0, 16);
|
|
26623
26826
|
}
|
|
26624
26827
|
function sandboxBuildDir(cwd = process.cwd()) {
|
|
26625
|
-
return
|
|
26828
|
+
return import_path55.default.join(cwd, ".node9", "sandbox", "build");
|
|
26626
26829
|
}
|
|
26627
26830
|
function writeBuildContext(cwd, dockerfile, entrypoint) {
|
|
26628
26831
|
const dir = sandboxBuildDir(cwd);
|
|
26629
26832
|
import_fs57.default.mkdirSync(dir, { recursive: true });
|
|
26630
|
-
import_fs57.default.writeFileSync(
|
|
26631
|
-
import_fs57.default.writeFileSync(
|
|
26833
|
+
import_fs57.default.writeFileSync(import_path55.default.join(dir, "Dockerfile"), dockerfile);
|
|
26834
|
+
import_fs57.default.writeFileSync(import_path55.default.join(dir, "entrypoint.sh"), entrypoint);
|
|
26632
26835
|
return dir;
|
|
26633
26836
|
}
|
|
26634
26837
|
function writeAllowlist(cwd, hosts) {
|
|
26635
|
-
const dir =
|
|
26838
|
+
const dir = import_path55.default.join(cwd, ".node9", "sandbox");
|
|
26636
26839
|
import_fs57.default.mkdirSync(dir, { recursive: true });
|
|
26637
|
-
const p =
|
|
26840
|
+
const p = import_path55.default.join(dir, "allowed-domains.txt");
|
|
26638
26841
|
import_fs57.default.writeFileSync(p, hosts.join("\n") + "\n");
|
|
26639
26842
|
return p;
|
|
26640
26843
|
}
|
|
26641
26844
|
function resolveHomePath(p) {
|
|
26642
|
-
return p.startsWith("~") ?
|
|
26845
|
+
return p.startsWith("~") ? import_path55.default.join(import_os49.default.homedir(), p.slice(1)) : import_path55.default.resolve(p);
|
|
26643
26846
|
}
|
|
26644
26847
|
|
|
26645
26848
|
// src/cli/commands/sandbox.ts
|
|
26646
26849
|
function seedDataDirConfig(dataDir, sandbox) {
|
|
26647
26850
|
import_fs58.default.mkdirSync(dataDir, { recursive: true });
|
|
26648
|
-
const configPath =
|
|
26851
|
+
const configPath = import_path56.default.join(dataDir, "config.json");
|
|
26649
26852
|
const seed = {
|
|
26650
26853
|
settings: {
|
|
26651
26854
|
approvers: {
|
|
@@ -26710,7 +26913,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
26710
26913
|
const buildDir = writeBuildContext(cwd, dockerfile, entrypoint);
|
|
26711
26914
|
const hash = imageContentHash(dockerfile, entrypoint);
|
|
26712
26915
|
const image = sandbox.runtime.image;
|
|
26713
|
-
const hashFile =
|
|
26916
|
+
const hashFile = import_path56.default.join(sandboxBuildDir(cwd), ".image-hash");
|
|
26714
26917
|
const lastHash = import_fs58.default.existsSync(hashFile) ? import_fs58.default.readFileSync(hashFile, "utf-8").trim() : "";
|
|
26715
26918
|
const imageExists = (0, import_child_process13.spawnSync)(sandbox.runtime.engine, ["image", "inspect", image], { stdio: "ignore" }).status === 0;
|
|
26716
26919
|
const needBuild = sandbox.runtime.rebuild === "always" || !imageExists || sandbox.runtime.rebuild !== "never" && lastHash !== hash;
|
|
@@ -26753,7 +26956,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
26753
26956
|
process.exit(r.status ?? 0);
|
|
26754
26957
|
});
|
|
26755
26958
|
cmd.command("tail").description("Stream the sandbox's audit log (host-side)").action(() => {
|
|
26756
|
-
const auditPath =
|
|
26959
|
+
const auditPath = import_path56.default.join(sandboxDataDir(), "audit.log");
|
|
26757
26960
|
if (!import_fs58.default.existsSync(auditPath)) {
|
|
26758
26961
|
console.log(import_chalk28.default.dim(" no sandbox audit yet."));
|
|
26759
26962
|
return;
|
|
@@ -26761,7 +26964,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
26761
26964
|
(0, import_child_process13.spawnSync)("tail", ["-f", auditPath], { stdio: "inherit" });
|
|
26762
26965
|
});
|
|
26763
26966
|
cmd.command("logs").description("Dump the sandbox's audit log").action(() => {
|
|
26764
|
-
const auditPath =
|
|
26967
|
+
const auditPath = import_path56.default.join(sandboxDataDir(), "audit.log");
|
|
26765
26968
|
if (!import_fs58.default.existsSync(auditPath)) {
|
|
26766
26969
|
console.log(import_chalk28.default.dim(" no sandbox audit yet."));
|
|
26767
26970
|
return;
|
|
@@ -26780,7 +26983,7 @@ function registerSandboxCommand(program2, version2) {
|
|
|
26780
26983
|
stdio: "ignore"
|
|
26781
26984
|
});
|
|
26782
26985
|
}
|
|
26783
|
-
import_fs58.default.rmSync(
|
|
26986
|
+
import_fs58.default.rmSync(import_path56.default.join(cwd, ".node9", "sandbox"), { recursive: true, force: true });
|
|
26784
26987
|
console.log(import_chalk28.default.green(" \u2713 sandbox image + build + data removed."));
|
|
26785
26988
|
});
|
|
26786
26989
|
}
|
|
@@ -26788,8 +26991,8 @@ function registerSandboxCommand(program2, version2) {
|
|
|
26788
26991
|
// src/cli/commands/sessions.ts
|
|
26789
26992
|
var import_chalk29 = __toESM(require("chalk"));
|
|
26790
26993
|
var import_fs59 = __toESM(require("fs"));
|
|
26791
|
-
var
|
|
26792
|
-
var
|
|
26994
|
+
var import_path57 = __toESM(require("path"));
|
|
26995
|
+
var import_os50 = __toESM(require("os"));
|
|
26793
26996
|
init_scan_summary();
|
|
26794
26997
|
init_litellm();
|
|
26795
26998
|
init_cost_gemini();
|
|
@@ -26810,10 +27013,10 @@ function encodeProjectPath(projectPath) {
|
|
|
26810
27013
|
}
|
|
26811
27014
|
function sessionJsonlPath(projectPath, sessionId) {
|
|
26812
27015
|
const encoded = encodeProjectPath(projectPath);
|
|
26813
|
-
return
|
|
27016
|
+
return import_path57.default.join(import_os50.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
|
|
26814
27017
|
}
|
|
26815
27018
|
function projectLabel(projectPath) {
|
|
26816
|
-
return projectPath.replace(
|
|
27019
|
+
return projectPath.replace(import_os50.default.homedir(), "~");
|
|
26817
27020
|
}
|
|
26818
27021
|
function parseHistoryLines(lines) {
|
|
26819
27022
|
const entries = [];
|
|
@@ -26882,7 +27085,7 @@ function parseSessionLines(lines) {
|
|
|
26882
27085
|
return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
|
|
26883
27086
|
}
|
|
26884
27087
|
function loadAuditEntries(auditPath) {
|
|
26885
|
-
const aPath = auditPath ??
|
|
27088
|
+
const aPath = auditPath ?? import_path57.default.join(import_os50.default.homedir(), ".node9", "audit.log");
|
|
26886
27089
|
let raw;
|
|
26887
27090
|
try {
|
|
26888
27091
|
raw = import_fs59.default.readFileSync(aPath, "utf-8");
|
|
@@ -26921,7 +27124,7 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
|
|
|
26921
27124
|
return result;
|
|
26922
27125
|
}
|
|
26923
27126
|
function buildGeminiSessions(days, allAuditEntries) {
|
|
26924
|
-
const tmpDir =
|
|
27127
|
+
const tmpDir = import_path57.default.join(import_os50.default.homedir(), ".gemini", "tmp");
|
|
26925
27128
|
if (!import_fs59.default.existsSync(tmpDir)) return [];
|
|
26926
27129
|
const cutoff = days !== null ? (() => {
|
|
26927
27130
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -26937,18 +27140,18 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
26937
27140
|
}
|
|
26938
27141
|
const summaries = [];
|
|
26939
27142
|
for (const slug2 of slugDirs) {
|
|
26940
|
-
const slugPath =
|
|
27143
|
+
const slugPath = import_path57.default.join(tmpDir, slug2);
|
|
26941
27144
|
try {
|
|
26942
27145
|
if (!import_fs59.default.statSync(slugPath).isDirectory()) continue;
|
|
26943
27146
|
} catch {
|
|
26944
27147
|
continue;
|
|
26945
27148
|
}
|
|
26946
|
-
let projectRoot =
|
|
27149
|
+
let projectRoot = import_path57.default.join(import_os50.default.homedir(), slug2);
|
|
26947
27150
|
try {
|
|
26948
|
-
projectRoot = import_fs59.default.readFileSync(
|
|
27151
|
+
projectRoot = import_fs59.default.readFileSync(import_path57.default.join(slugPath, ".project_root"), "utf-8").trim();
|
|
26949
27152
|
} catch {
|
|
26950
27153
|
}
|
|
26951
|
-
const chatsDir =
|
|
27154
|
+
const chatsDir = import_path57.default.join(slugPath, "chats");
|
|
26952
27155
|
if (!import_fs59.default.existsSync(chatsDir)) continue;
|
|
26953
27156
|
let chatFiles;
|
|
26954
27157
|
try {
|
|
@@ -26959,7 +27162,7 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
26959
27162
|
for (const chatFile of chatFiles) {
|
|
26960
27163
|
let raw;
|
|
26961
27164
|
try {
|
|
26962
|
-
raw = import_fs59.default.readFileSync(
|
|
27165
|
+
raw = import_fs59.default.readFileSync(import_path57.default.join(chatsDir, chatFile), "utf-8");
|
|
26963
27166
|
} catch {
|
|
26964
27167
|
continue;
|
|
26965
27168
|
}
|
|
@@ -27039,7 +27242,7 @@ function buildGeminiSessions(days, allAuditEntries) {
|
|
|
27039
27242
|
return summaries;
|
|
27040
27243
|
}
|
|
27041
27244
|
function buildCodexSessions(days, allAuditEntries) {
|
|
27042
|
-
const sessionsBase =
|
|
27245
|
+
const sessionsBase = import_path57.default.join(import_os50.default.homedir(), ".codex", "sessions");
|
|
27043
27246
|
if (!import_fs59.default.existsSync(sessionsBase)) return [];
|
|
27044
27247
|
const cutoff = days !== null ? (() => {
|
|
27045
27248
|
const d = /* @__PURE__ */ new Date();
|
|
@@ -27050,28 +27253,28 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
27050
27253
|
const jsonlFiles = [];
|
|
27051
27254
|
try {
|
|
27052
27255
|
for (const year of import_fs59.default.readdirSync(sessionsBase)) {
|
|
27053
|
-
const yearPath =
|
|
27256
|
+
const yearPath = import_path57.default.join(sessionsBase, year);
|
|
27054
27257
|
try {
|
|
27055
27258
|
if (!import_fs59.default.statSync(yearPath).isDirectory()) continue;
|
|
27056
27259
|
} catch {
|
|
27057
27260
|
continue;
|
|
27058
27261
|
}
|
|
27059
27262
|
for (const month of import_fs59.default.readdirSync(yearPath)) {
|
|
27060
|
-
const monthPath =
|
|
27263
|
+
const monthPath = import_path57.default.join(yearPath, month);
|
|
27061
27264
|
try {
|
|
27062
27265
|
if (!import_fs59.default.statSync(monthPath).isDirectory()) continue;
|
|
27063
27266
|
} catch {
|
|
27064
27267
|
continue;
|
|
27065
27268
|
}
|
|
27066
27269
|
for (const day of import_fs59.default.readdirSync(monthPath)) {
|
|
27067
|
-
const dayPath =
|
|
27270
|
+
const dayPath = import_path57.default.join(monthPath, day);
|
|
27068
27271
|
try {
|
|
27069
27272
|
if (!import_fs59.default.statSync(dayPath).isDirectory()) continue;
|
|
27070
27273
|
} catch {
|
|
27071
27274
|
continue;
|
|
27072
27275
|
}
|
|
27073
27276
|
for (const file of import_fs59.default.readdirSync(dayPath)) {
|
|
27074
|
-
if (file.endsWith(".jsonl")) jsonlFiles.push(
|
|
27277
|
+
if (file.endsWith(".jsonl")) jsonlFiles.push(import_path57.default.join(dayPath, file));
|
|
27075
27278
|
}
|
|
27076
27279
|
}
|
|
27077
27280
|
}
|
|
@@ -27169,7 +27372,7 @@ function buildCodexSessions(days, allAuditEntries) {
|
|
|
27169
27372
|
return summaries;
|
|
27170
27373
|
}
|
|
27171
27374
|
function buildSessions(days, historyPath) {
|
|
27172
|
-
const hPath = historyPath ??
|
|
27375
|
+
const hPath = historyPath ?? import_path57.default.join(import_os50.default.homedir(), ".claude", "history.jsonl");
|
|
27173
27376
|
let historyRaw = "";
|
|
27174
27377
|
try {
|
|
27175
27378
|
historyRaw = import_fs59.default.readFileSync(hPath, "utf-8");
|
|
@@ -27591,11 +27794,11 @@ function registerSessionTaintCommand(program2) {
|
|
|
27591
27794
|
// src/cli/commands/skill-pin.ts
|
|
27592
27795
|
var import_chalk31 = __toESM(require("chalk"));
|
|
27593
27796
|
var import_fs60 = __toESM(require("fs"));
|
|
27594
|
-
var
|
|
27595
|
-
var
|
|
27797
|
+
var import_os51 = __toESM(require("os"));
|
|
27798
|
+
var import_path58 = __toESM(require("path"));
|
|
27596
27799
|
function wipeSkillSessions() {
|
|
27597
27800
|
try {
|
|
27598
|
-
import_fs60.default.rmSync(
|
|
27801
|
+
import_fs60.default.rmSync(import_path58.default.join(import_os51.default.homedir(), ".node9", "skill-sessions"), {
|
|
27599
27802
|
recursive: true,
|
|
27600
27803
|
force: true
|
|
27601
27804
|
});
|
|
@@ -27678,10 +27881,10 @@ function registerSkillPinCommand(program2) {
|
|
|
27678
27881
|
|
|
27679
27882
|
// src/cli/commands/decisions.ts
|
|
27680
27883
|
var import_fs61 = __toESM(require("fs"));
|
|
27681
|
-
var
|
|
27682
|
-
var
|
|
27884
|
+
var import_os52 = __toESM(require("os"));
|
|
27885
|
+
var import_path59 = __toESM(require("path"));
|
|
27683
27886
|
var import_chalk32 = __toESM(require("chalk"));
|
|
27684
|
-
var DECISIONS_FILE2 =
|
|
27887
|
+
var DECISIONS_FILE2 = import_path59.default.join(import_os52.default.homedir(), ".node9", "decisions.json");
|
|
27685
27888
|
function readDecisions() {
|
|
27686
27889
|
try {
|
|
27687
27890
|
if (!import_fs61.default.existsSync(DECISIONS_FILE2)) return {};
|
|
@@ -27697,7 +27900,7 @@ function readDecisions() {
|
|
|
27697
27900
|
}
|
|
27698
27901
|
}
|
|
27699
27902
|
function writeDecisions(d) {
|
|
27700
|
-
const dir =
|
|
27903
|
+
const dir = import_path59.default.dirname(DECISIONS_FILE2);
|
|
27701
27904
|
if (!import_fs61.default.existsSync(dir)) import_fs61.default.mkdirSync(dir, { recursive: true });
|
|
27702
27905
|
const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
|
|
27703
27906
|
import_fs61.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
|
|
@@ -27759,10 +27962,10 @@ Persistent decisions (${entries.length})
|
|
|
27759
27962
|
// src/cli/commands/dlp.ts
|
|
27760
27963
|
var import_chalk33 = __toESM(require("chalk"));
|
|
27761
27964
|
var import_fs62 = __toESM(require("fs"));
|
|
27762
|
-
var
|
|
27763
|
-
var
|
|
27764
|
-
var AUDIT_LOG =
|
|
27765
|
-
var RESOLVED_FILE =
|
|
27965
|
+
var import_path60 = __toESM(require("path"));
|
|
27966
|
+
var import_os53 = __toESM(require("os"));
|
|
27967
|
+
var AUDIT_LOG = import_path60.default.join(import_os53.default.homedir(), ".node9", "audit.log");
|
|
27968
|
+
var RESOLVED_FILE = import_path60.default.join(import_os53.default.homedir(), ".node9", "dlp-resolved.json");
|
|
27766
27969
|
var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
|
|
27767
27970
|
function stripAnsi(s) {
|
|
27768
27971
|
return s.replace(ANSI_RE, "");
|
|
@@ -27882,14 +28085,14 @@ function registerDlpCommand(program2) {
|
|
|
27882
28085
|
// src/cli/commands/mask.ts
|
|
27883
28086
|
var import_chalk34 = __toESM(require("chalk"));
|
|
27884
28087
|
var import_fs63 = __toESM(require("fs"));
|
|
27885
|
-
var
|
|
27886
|
-
var
|
|
28088
|
+
var import_path61 = __toESM(require("path"));
|
|
28089
|
+
var import_os54 = __toESM(require("os"));
|
|
27887
28090
|
init_dlp();
|
|
27888
28091
|
function findJsonlFiles(dir) {
|
|
27889
28092
|
const results = [];
|
|
27890
28093
|
if (!import_fs63.default.existsSync(dir)) return results;
|
|
27891
28094
|
for (const entry of import_fs63.default.readdirSync(dir, { withFileTypes: true })) {
|
|
27892
|
-
const full =
|
|
28095
|
+
const full = import_path61.default.join(dir, entry.name);
|
|
27893
28096
|
if (entry.isDirectory()) results.push(...findJsonlFiles(full));
|
|
27894
28097
|
else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
|
|
27895
28098
|
}
|
|
@@ -27992,7 +28195,7 @@ function findJsonFiles(dir) {
|
|
|
27992
28195
|
const results = [];
|
|
27993
28196
|
if (!import_fs63.default.existsSync(dir)) return results;
|
|
27994
28197
|
for (const entry of import_fs63.default.readdirSync(dir, { withFileTypes: true })) {
|
|
27995
|
-
const full =
|
|
28198
|
+
const full = import_path61.default.join(dir, entry.name);
|
|
27996
28199
|
if (entry.isDirectory()) results.push(...findJsonFiles(full));
|
|
27997
28200
|
else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
|
|
27998
28201
|
}
|
|
@@ -28001,9 +28204,9 @@ function findJsonFiles(dir) {
|
|
|
28001
28204
|
function registerMaskCommand(program2) {
|
|
28002
28205
|
program2.command("mask").description("Redact plaintext secrets from local AI session history files").option("--dry-run", "show what would be redacted without making changes").option("--all", "scan all history (default: last 30 days)").action(async (options) => {
|
|
28003
28206
|
const dryRun = !!options.dryRun;
|
|
28004
|
-
const home =
|
|
28005
|
-
const claudeDir =
|
|
28006
|
-
const geminiDir =
|
|
28207
|
+
const home = import_os54.default.homedir();
|
|
28208
|
+
const claudeDir = import_path61.default.join(home, ".claude", "projects");
|
|
28209
|
+
const geminiDir = import_path61.default.join(home, ".gemini", "tmp");
|
|
28007
28210
|
const allFiles = [
|
|
28008
28211
|
...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
|
|
28009
28212
|
...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
|
|
@@ -28067,15 +28270,15 @@ function registerMaskCommand(program2) {
|
|
|
28067
28270
|
// src/cli.ts
|
|
28068
28271
|
init_blast();
|
|
28069
28272
|
var { version } = JSON.parse(
|
|
28070
|
-
import_fs66.default.readFileSync(
|
|
28273
|
+
import_fs66.default.readFileSync(import_path64.default.join(__dirname, "../package.json"), "utf-8")
|
|
28071
28274
|
);
|
|
28072
28275
|
var program = new import_commander.Command();
|
|
28073
28276
|
program.name("node9").description("The Sudo Command for AI Agents").version(version);
|
|
28074
28277
|
program.command("login").argument("<apiKey>").option("--local", "Save key for audit/logging only \u2014 local config still controls all decisions").option("--profile <name>", 'Save as a named profile (default: "default")').action((apiKey, options) => {
|
|
28075
28278
|
const DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept";
|
|
28076
|
-
const credPath =
|
|
28077
|
-
if (!import_fs66.default.existsSync(
|
|
28078
|
-
import_fs66.default.mkdirSync(
|
|
28279
|
+
const credPath = import_path64.default.join(import_os57.default.homedir(), ".node9", "credentials.json");
|
|
28280
|
+
if (!import_fs66.default.existsSync(import_path64.default.dirname(credPath)))
|
|
28281
|
+
import_fs66.default.mkdirSync(import_path64.default.dirname(credPath), { recursive: true });
|
|
28079
28282
|
const profileName = options.profile || "default";
|
|
28080
28283
|
let existingCreds = {};
|
|
28081
28284
|
try {
|
|
@@ -28095,7 +28298,7 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
|
|
|
28095
28298
|
import_fs66.default.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), { mode: 384 });
|
|
28096
28299
|
let effectiveCloud = null;
|
|
28097
28300
|
if (profileName === "default") {
|
|
28098
|
-
const configPath =
|
|
28301
|
+
const configPath = import_path64.default.join(import_os57.default.homedir(), ".node9", "config.json");
|
|
28099
28302
|
let config = {};
|
|
28100
28303
|
try {
|
|
28101
28304
|
if (import_fs66.default.existsSync(configPath))
|
|
@@ -28114,8 +28317,8 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
|
|
|
28114
28317
|
approvers.cloud = false;
|
|
28115
28318
|
}
|
|
28116
28319
|
s.approvers = approvers;
|
|
28117
|
-
if (!import_fs66.default.existsSync(
|
|
28118
|
-
import_fs66.default.mkdirSync(
|
|
28320
|
+
if (!import_fs66.default.existsSync(import_path64.default.dirname(configPath)))
|
|
28321
|
+
import_fs66.default.mkdirSync(import_path64.default.dirname(configPath), { recursive: true });
|
|
28119
28322
|
import_fs66.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
28120
28323
|
effectiveCloud = approvers.cloud === true;
|
|
28121
28324
|
}
|
|
@@ -28225,37 +28428,21 @@ program.command("setup", { hidden: true }).description('Alias for "addto" \u2014
|
|
|
28225
28428
|
);
|
|
28226
28429
|
process.exit(1);
|
|
28227
28430
|
});
|
|
28228
|
-
program.command("removefrom", { hidden: true }).description("Remove Node9 hooks from an AI agent configuration").addHelpText(
|
|
28229
|
-
"
|
|
28230
|
-
|
|
28231
|
-
)
|
|
28232
|
-
"<target>",
|
|
28233
|
-
"The agent to remove from: claude | antigravity | copilot | gemini | cursor | codex | windsurf | vscode | hud"
|
|
28234
|
-
).action((target) => {
|
|
28235
|
-
let fn;
|
|
28236
|
-
if (target === "claude") fn = teardownClaude;
|
|
28237
|
-
else if (target === "gemini") fn = teardownGemini;
|
|
28238
|
-
else if (target === "antigravity" || target === "agy") fn = teardownAntigravity;
|
|
28239
|
-
else if (target === "copilot") fn = teardownCopilot;
|
|
28240
|
-
else if (target === "cursor") fn = teardownCursor;
|
|
28241
|
-
else if (target === "codex") fn = teardownCodex;
|
|
28242
|
-
else if (target === "windsurf") fn = teardownWindsurf;
|
|
28243
|
-
else if (target === "vscode") fn = teardownVSCode;
|
|
28244
|
-
else if (target === "hermes") fn = teardownHermes;
|
|
28245
|
-
else if (target === "hud") fn = teardownHud;
|
|
28246
|
-
else {
|
|
28431
|
+
program.command("removefrom", { hidden: true }).description("Remove Node9 hooks from an AI agent configuration").addHelpText("after", `
|
|
28432
|
+
Supported targets: ${agentTeardownTargets().join(" ")}`).argument("<target>", `The agent to remove from: ${agentTeardownTargets().join(" | ")}`).action((target) => {
|
|
28433
|
+
const agent = resolveAgentTeardown(target);
|
|
28434
|
+
if (!agent) {
|
|
28247
28435
|
console.error(
|
|
28248
|
-
import_chalk36.default.red(
|
|
28249
|
-
`Unknown target: "${target}". Supported: claude, antigravity, copilot, gemini, cursor, codex, windsurf, vscode, hermes, hud`
|
|
28250
|
-
)
|
|
28436
|
+
import_chalk36.default.red(`Unknown target: "${target}". Supported: ${agentTeardownTargets().join(", ")}`)
|
|
28251
28437
|
);
|
|
28252
28438
|
process.exit(1);
|
|
28439
|
+
return;
|
|
28253
28440
|
}
|
|
28254
28441
|
console.log(import_chalk36.default.cyan(`
|
|
28255
|
-
\u{1F6E1}\uFE0F Node9: removing hooks from ${
|
|
28442
|
+
\u{1F6E1}\uFE0F Node9: removing hooks from ${agent.label}...
|
|
28256
28443
|
`));
|
|
28257
28444
|
try {
|
|
28258
|
-
fn();
|
|
28445
|
+
agent.fn();
|
|
28259
28446
|
} catch (err2) {
|
|
28260
28447
|
console.error(import_chalk36.default.red(` \u26A0\uFE0F Failed: ${err2 instanceof Error ? err2.message : String(err2)}`));
|
|
28261
28448
|
process.exit(1);
|
|
@@ -28273,15 +28460,7 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
28273
28460
|
}
|
|
28274
28461
|
console.log(import_chalk36.default.bold("\nRemoving hooks..."));
|
|
28275
28462
|
let teardownFailed = false;
|
|
28276
|
-
for (const
|
|
28277
|
-
["Claude", teardownClaude],
|
|
28278
|
-
["Gemini", teardownGemini],
|
|
28279
|
-
["Cursor", teardownCursor],
|
|
28280
|
-
["Codex", teardownCodex],
|
|
28281
|
-
["Windsurf", teardownWindsurf],
|
|
28282
|
-
["VSCode", teardownVSCode],
|
|
28283
|
-
["Hermes", teardownHermes]
|
|
28284
|
-
]) {
|
|
28463
|
+
for (const { label: label2, fn } of AGENT_TEARDOWNS) {
|
|
28285
28464
|
try {
|
|
28286
28465
|
fn();
|
|
28287
28466
|
} catch (err2) {
|
|
@@ -28293,8 +28472,21 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
|
|
|
28293
28472
|
);
|
|
28294
28473
|
}
|
|
28295
28474
|
}
|
|
28475
|
+
try {
|
|
28476
|
+
const residual = getAgentWiring().filter((a) => a.wireState === "wired");
|
|
28477
|
+
if (residual.length === 0) {
|
|
28478
|
+
console.log(import_chalk36.default.green(" \u2705 Verified \u2014 no node9 hooks or plugin shims remain"));
|
|
28479
|
+
} else {
|
|
28480
|
+
teardownFailed = true;
|
|
28481
|
+
console.error(import_chalk36.default.red(" \u26A0\uFE0F Still wired after teardown:"));
|
|
28482
|
+
for (const a of residual) {
|
|
28483
|
+
console.error(import_chalk36.default.red(` \u2022 ${a.label} \u2014 ${a.settingsPath}`));
|
|
28484
|
+
}
|
|
28485
|
+
}
|
|
28486
|
+
} catch {
|
|
28487
|
+
}
|
|
28296
28488
|
if (options.purge) {
|
|
28297
|
-
const node9Dir =
|
|
28489
|
+
const node9Dir = import_path64.default.join(import_os57.default.homedir(), ".node9");
|
|
28298
28490
|
if (import_fs66.default.existsSync(node9Dir)) {
|
|
28299
28491
|
const confirmed = await (0, import_prompts2.confirm)({
|
|
28300
28492
|
message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
|
|
@@ -28425,7 +28617,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
|
|
|
28425
28617
|
});
|
|
28426
28618
|
program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
|
|
28427
28619
|
try {
|
|
28428
|
-
const dashboardPath =
|
|
28620
|
+
const dashboardPath = import_path64.default.join(__dirname, "dashboard.mjs");
|
|
28429
28621
|
const dynamicImport = new Function("id", "return import(id)");
|
|
28430
28622
|
const mod = await dynamicImport(`file://${dashboardPath}`);
|
|
28431
28623
|
await mod.startMonitor();
|
|
@@ -28463,9 +28655,9 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
|
|
|
28463
28655
|
Run "node9 addto claude" to register it as the statusLine.`
|
|
28464
28656
|
).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
|
|
28465
28657
|
if (subcommand === "debug") {
|
|
28466
|
-
const flagFile =
|
|
28658
|
+
const flagFile = import_path64.default.join(import_os57.default.homedir(), ".node9", "hud-debug");
|
|
28467
28659
|
if (state === "on") {
|
|
28468
|
-
import_fs66.default.mkdirSync(
|
|
28660
|
+
import_fs66.default.mkdirSync(import_path64.default.dirname(flagFile), { recursive: true });
|
|
28469
28661
|
import_fs66.default.writeFileSync(flagFile, "");
|
|
28470
28662
|
console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
|
|
28471
28663
|
console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
|
|
@@ -28592,7 +28784,7 @@ if (process.argv[2] !== "daemon") {
|
|
|
28592
28784
|
const isCheckHook = process.argv[2] === "check";
|
|
28593
28785
|
if (isCheckHook) {
|
|
28594
28786
|
if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
|
|
28595
|
-
const logPath =
|
|
28787
|
+
const logPath = import_path64.default.join(import_os57.default.homedir(), ".node9", "hook-debug.log");
|
|
28596
28788
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
28597
28789
|
import_fs66.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
|
|
28598
28790
|
`);
|