@node9/proxy 1.31.0 → 1.33.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 CHANGED
@@ -140,6 +140,9 @@ function appendLocalAudit(toolName, args, decision, checkedBy, meta, auditHashAr
140
140
  const agentToolNameField = meta?.agentToolName ? { agentToolName: meta.agentToolName } : {};
141
141
  const dlpFields = meta?.dlpPattern ? { dlpPattern: meta.dlpPattern, dlpSample: meta.dlpSample } : {};
142
142
  const cloudLinkField = meta?.cloudRequestId ? { cloudRequestId: meta.cloudRequestId } : {};
143
+ const workingDirField = meta?.workingDir ? { workingDir: meta.workingDir } : {};
144
+ const shell = process.env.SHELL ? import_path.default.basename(process.env.SHELL) : void 0;
145
+ const shellTypeField = shell ? { shellType: shell } : {};
143
146
  appendToLog(LOCAL_AUDIT_LOG, {
144
147
  // eid first: the outbox shipper dedups on it, and a fixed leading field
145
148
  // makes the JSONL easy to eyeball.
@@ -153,11 +156,14 @@ function appendLocalAudit(toolName, args, decision, checkedBy, meta, auditHashAr
153
156
  ...ruleNameField,
154
157
  ...dlpFields,
155
158
  ...cloudLinkField,
159
+ ...workingDirField,
160
+ ...shellTypeField,
156
161
  ...testRun,
157
162
  agent: meta?.agent,
158
163
  mcpServer: meta?.mcpServer,
159
164
  sessionId: meta?.sessionId,
160
- hostname: import_os.default.hostname()
165
+ hostname: import_os.default.hostname(),
166
+ platform: import_os.default.platform()
161
167
  });
162
168
  }
163
169
  function appendConfigAudit(entry) {
@@ -200,8 +206,8 @@ function sanitizeConfig(raw) {
200
206
  }
201
207
  }
202
208
  const lines = result.error.issues.map((issue) => {
203
- const path52 = issue.path.length > 0 ? issue.path.join(".") : "root";
204
- return ` \u2022 ${path52}: ${issue.message}`;
209
+ const path54 = issue.path.length > 0 ? issue.path.join(".") : "root";
210
+ return ` \u2022 ${path54}: ${issue.message}`;
205
211
  });
206
212
  return {
207
213
  sanitized,
@@ -548,6 +554,8 @@ function normalizeCommandForPolicyImpl(command) {
548
554
  if (f === PARSE_FAIL) return command;
549
555
  try {
550
556
  const strips = [];
557
+ const rewrites = [];
558
+ const msgSpans = /* @__PURE__ */ new Set();
551
559
  syntax.Walk(f, (node) => {
552
560
  if (!node) return false;
553
561
  const n = node;
@@ -563,25 +571,46 @@ function normalizeCommandForPolicyImpl(command) {
563
571
  if (nextParts.length !== 1) continue;
564
572
  const quotedNode = nextParts[0];
565
573
  const nt = syntax.NodeType(quotedNode);
574
+ const markStrip = () => {
575
+ const s = next.Pos().Offset();
576
+ const e = next.End().Offset();
577
+ strips.push([s, e]);
578
+ msgSpans.add(`${s}:${e}`);
579
+ };
566
580
  if (nt === "SglQuoted") {
567
- strips.push([next.Pos().Offset(), next.End().Offset()]);
581
+ markStrip();
568
582
  } else if (nt === "DblQuoted") {
569
583
  const innerParts = quotedNode.Parts || [];
570
584
  const allLit = innerParts.length === 0 || innerParts.every((p) => syntax.NodeType(p) === "Lit");
571
585
  if (allLit) {
572
- strips.push([next.Pos().Offset(), next.End().Offset()]);
586
+ markStrip();
573
587
  } else if (innerParts.every((p) => isCatHeredocOrLit(p))) {
574
- strips.push([next.Pos().Offset(), next.End().Offset()]);
588
+ markStrip();
575
589
  }
576
590
  }
577
591
  }
592
+ for (const arg of args) {
593
+ const s = arg.Pos().Offset();
594
+ const e = arg.End().Offset();
595
+ if (msgSpans.has(`${s}:${e}`)) continue;
596
+ const resolved = resolveWordLiteral(arg);
597
+ if (resolved === null) continue;
598
+ const source = command.slice(s, e);
599
+ if (resolved === source) continue;
600
+ if (resolved === "" || /\s/.test(resolved)) continue;
601
+ rewrites.push([s, e, resolved]);
602
+ }
578
603
  return true;
579
604
  });
580
- if (strips.length === 0) return command;
581
- strips.sort((a, b) => b[0] - a[0]);
605
+ const edits = [
606
+ ...strips.map(([s, e]) => [s, e, '""']),
607
+ ...rewrites
608
+ ];
609
+ if (edits.length === 0) return command;
610
+ edits.sort((a, b) => b[0] - a[0]);
582
611
  let result = command;
583
- for (const [start, end] of strips) {
584
- result = result.slice(0, start) + '""' + result.slice(end);
612
+ for (const [s, e, rep] of edits) {
613
+ result = result.slice(0, s) + rep + result.slice(e);
585
614
  }
586
615
  return result;
587
616
  } catch {
@@ -643,6 +672,17 @@ function detectDangerousShellExec(command) {
643
672
  function isBashTool(toolName) {
644
673
  return BASH_TOOL_NAMES.has(toolName.toLowerCase());
645
674
  }
675
+ function analyzeSqlDestructive(command) {
676
+ if (!SQL_DDL_RE.test(command)) return null;
677
+ const { actions } = analyzeShellCommand(command);
678
+ if (!actions.some((a) => SQL_DB_CLIS.has(a))) return null;
679
+ return {
680
+ ruleName: "review-drop-truncate-shell",
681
+ verdict: "review",
682
+ reason: "SQL DDL destructive statement inside a shell command",
683
+ description: "The AI wants to drop or truncate a database table via the shell. This permanently deletes the table structure or all its data."
684
+ };
685
+ }
646
686
  function isProtectedHomePath(rawPath) {
647
687
  let p = rawPath.replace(/^\$HOME[\\/]?|^\$\{HOME\}[\\/]?/, "~/");
648
688
  let underHome = false;
@@ -804,19 +844,20 @@ function extractShellDestinations(command) {
804
844
  return out;
805
845
  }
806
846
  function analyzeFsOperation(command) {
807
- if (!FS_OP_PRESCREEN_RE.test(command)) return null;
808
- if (fsOpCache.has(command)) {
809
- const hit = fsOpCache.get(command) ?? null;
810
- fsOpCache.delete(command);
811
- fsOpCache.set(command, hit);
847
+ const normalized = normalizeCommandForPolicy(command);
848
+ if (!FS_OP_PRESCREEN_RE.test(normalized)) return null;
849
+ if (fsOpCache.has(normalized)) {
850
+ const hit = fsOpCache.get(normalized) ?? null;
851
+ fsOpCache.delete(normalized);
852
+ fsOpCache.set(normalized, hit);
812
853
  return hit;
813
854
  }
814
- const computed = analyzeFsOperationImpl(command);
855
+ const computed = analyzeFsOperationImpl(normalized);
815
856
  if (fsOpCache.size >= FS_OP_CACHE_MAX) {
816
857
  const oldest = fsOpCache.keys().next().value;
817
858
  if (oldest !== void 0) fsOpCache.delete(oldest);
818
859
  }
819
- fsOpCache.set(command, computed);
860
+ fsOpCache.set(normalized, computed);
820
861
  return computed;
821
862
  }
822
863
  function analyzeFsOperationImpl(command) {
@@ -1215,9 +1256,9 @@ function matchesPattern(text, patterns) {
1215
1256
  const withoutDotSlash = text.replace(/^\.\//, "");
1216
1257
  return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
1217
1258
  }
1218
- function getNestedValue(obj, path52) {
1259
+ function getNestedValue(obj, path54) {
1219
1260
  if (!obj || typeof obj !== "object") return null;
1220
- const segments = path52.split(".");
1261
+ const segments = path54.split(".");
1221
1262
  for (const seg of segments) {
1222
1263
  if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
1223
1264
  }
@@ -1357,6 +1398,17 @@ async function evaluatePolicy(config, toolName, args, context = {}, hooks = {})
1357
1398
  ruleDescription: fsVerdict.reason
1358
1399
  };
1359
1400
  }
1401
+ const sqlVerdict = analyzeSqlDestructive(bashCommand);
1402
+ if (sqlVerdict) {
1403
+ return {
1404
+ decision: sqlVerdict.verdict,
1405
+ blockedByLabel: `Node9 (AST): ${sqlVerdict.ruleName}`,
1406
+ reason: sqlVerdict.reason,
1407
+ tier: 2,
1408
+ ruleName: sqlVerdict.ruleName,
1409
+ ruleDescription: sqlVerdict.description
1410
+ };
1411
+ }
1360
1412
  }
1361
1413
  if (config.policy.smartRules.length > 0) {
1362
1414
  const matchedRule = config.policy.smartRules.find(
@@ -1937,7 +1989,7 @@ function extractCanonicalFindings(call, ctx) {
1937
1989
  })
1938
1990
  );
1939
1991
  }
1940
- if (DESTRUCTIVE_OP_RE.test(command)) {
1992
+ if (command !== null && DESTRUCTIVE_OP_RE.test(normalizeCommandForPolicy(command))) {
1941
1993
  out.push(
1942
1994
  makeFinding({
1943
1995
  type: "destructive-op",
@@ -2089,7 +2141,7 @@ function* stringValues(obj, depth = 0) {
2089
2141
  }
2090
2142
  for (const v of Object.values(obj)) yield* stringValues(v, depth + 1);
2091
2143
  }
2092
- var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto3, 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, 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;
2144
+ var import_safe_regex2, import_mvdan_sh, import_picomatch, import_safe_regex22, import_safe_regex23, import_crypto3, 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, 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;
2093
2145
  var init_dist = __esm({
2094
2146
  "packages/policy-engine/dist/index.mjs"() {
2095
2147
  "use strict";
@@ -2707,8 +2759,24 @@ var init_dist = __esm({
2707
2759
  "shield:project-jail:block-read-ssh",
2708
2760
  "shield:project-jail:block-read-aws",
2709
2761
  "shield:project-jail:block-read-env",
2710
- "shield:project-jail:review-read-credentials"
2762
+ "shield:project-jail:review-read-credentials",
2763
+ // SQL-DDL is now owned by the AST detector (analyzeSqlDestructive) so the
2764
+ // raw-regex smart rule is suppressed for bash — its cond1 read a grep
2765
+ // alternation's `|` as a shell pipe (`grep "…|mysql…"` → false positive).
2766
+ "review-drop-truncate-shell"
2767
+ ]);
2768
+ SQL_DB_CLIS = /* @__PURE__ */ new Set([
2769
+ "psql",
2770
+ "mysql",
2771
+ "mariadb",
2772
+ "sqlite3",
2773
+ "sqlplus",
2774
+ "cockroach",
2775
+ "clickhouse-client",
2776
+ "mongo",
2777
+ "mongosh"
2711
2778
  ]);
2779
+ SQL_DDL_RE = /\b(DROP|TRUNCATE)\s+(TABLE|DATABASE|SCHEMA|INDEX)\b/i;
2712
2780
  NET_BINARIES = /* @__PURE__ */ new Set(["curl", "wget", "scp", "ssh", "nc", "ncat", "netcat"]);
2713
2781
  VALUE_FLAGS = {
2714
2782
  curl: /* @__PURE__ */ new Set([
@@ -3747,7 +3815,7 @@ var init_dist = __esm({
3747
3815
  REALTIME_PII_PATTERNS = ["SSN", "Credit Card"];
3748
3816
  MAX_PII_SCAN_BYTES = 1e5;
3749
3817
  LONG_OUTPUT_THRESHOLD_BYTES = 100 * 1024;
3750
- CANONICAL_EXTRACTOR_VERSION = "canonical-v4";
3818
+ CANONICAL_EXTRACTOR_VERSION = "canonical-v6";
3751
3819
  DEDUPE_PREVIEW_LEN = 120;
3752
3820
  TERMINAL_ESCAPE_RE = // eslint-disable-next-line no-control-regex
3753
3821
  /\x1b\[[0-9;?]*[A-Za-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-_]|[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
@@ -6079,7 +6147,8 @@ async function authorizeHeadless(toolName, args, meta, options) {
6079
6147
  }
6080
6148
  return _authorizeHeadlessCore(toolName, args, meta, options);
6081
6149
  }
6082
- async function _authorizeHeadlessCore(toolName, args, meta, options) {
6150
+ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
6151
+ const meta = options?.cwd && !metaArg?.workingDir ? { ...metaArg, workingDir: options.cwd } : metaArg;
6083
6152
  if (process.env.NODE9_PAUSED === "1") return { approved: true, checkedBy: "paused" };
6084
6153
  const pauseState = checkPause();
6085
6154
  if (pauseState.paused) return { approved: true, checkedBy: "paused" };
@@ -7235,7 +7304,7 @@ function writeJson(filePath, data) {
7235
7304
  }
7236
7305
  function isNode9Hook(cmd) {
7237
7306
  if (!cmd) return false;
7238
- return /(?:^|[\s/\\"])node9 (?:check|log)/.test(cmd) || /(?:^|[\s/\\"])cli\.js" (?:check|log)/.test(cmd) || /(?:^|[\s/\\])cli\.js (?:check|log)/.test(cmd);
7307
+ return /(?:^|[\s/\\"])node9"? (?:check|log)/.test(cmd) || /(?:^|[\s/\\])cli\.js"? (?:check|log)/.test(cmd);
7239
7308
  }
7240
7309
  function teardownClaude() {
7241
7310
  const homeDir2 = import_os12.default.homedir();
@@ -10027,43 +10096,102 @@ var init_litellm = __esm({
10027
10096
  });
10028
10097
 
10029
10098
  // src/cost-codex.ts
10030
- function codexLogPath() {
10031
- return import_path19.default.join(import_os16.default.homedir(), ".codex", "log", "codex-tui.log");
10032
- }
10033
- function parseCodexUsageLine(line) {
10034
- if (!line.includes("token_usage")) return null;
10035
- const date = line.match(RE_DATE)?.[1];
10036
- if (!date) return null;
10037
- const model = line.match(RE_MODEL)?.[1];
10038
- if (!model) return null;
10039
- const num3 = (re) => {
10040
- const m = line.match(re);
10041
- return m ? Number(m[1]) : 0;
10042
- };
10043
- const totalInput = num3(RE_INPUT);
10044
- const cached = num3(RE_CACHED);
10045
- const nonCached = num3(RE_NON_CACHED);
10046
- const output = num3(RE_OUTPUT);
10047
- const inputTokens = nonCached || Math.max(0, totalInput - cached);
10048
- if (inputTokens === 0 && output === 0 && cached === 0) return null;
10049
- const runId = line.match(RE_THREAD)?.[1] ?? "";
10050
- const norm = normalizeModel(model);
10051
- const p = pricingFor(model);
10052
- const costUSD = p ? inputTokens * p[0] + output * p[1] + cached * p[3] : 0;
10099
+ function codexSessionsDir() {
10100
+ return import_path19.default.join(import_os16.default.homedir(), ".codex", "sessions");
10101
+ }
10102
+ function codexPriceFor(model) {
10103
+ return pricingFor(model) ?? CODEX_FALLBACK;
10104
+ }
10105
+ function listCodexSessionFiles(base) {
10106
+ const out = [];
10107
+ for (const y of safeReaddir(base)) {
10108
+ const yp = import_path19.default.join(base, y);
10109
+ if (!isDir(yp)) continue;
10110
+ for (const m of safeReaddir(yp)) {
10111
+ const mp = import_path19.default.join(yp, m);
10112
+ if (!isDir(mp)) continue;
10113
+ for (const d of safeReaddir(mp)) {
10114
+ const dp = import_path19.default.join(mp, d);
10115
+ if (!isDir(dp)) continue;
10116
+ for (const f of safeReaddir(dp)) {
10117
+ if (f.endsWith(".jsonl")) out.push(import_path19.default.join(dp, f));
10118
+ }
10119
+ }
10120
+ }
10121
+ }
10122
+ return out;
10123
+ }
10124
+ function safeReaddir(dir) {
10125
+ try {
10126
+ return import_fs17.default.readdirSync(dir);
10127
+ } catch {
10128
+ return [];
10129
+ }
10130
+ }
10131
+ function isDir(p) {
10132
+ try {
10133
+ return import_fs17.default.statSync(p).isDirectory();
10134
+ } catch {
10135
+ return false;
10136
+ }
10137
+ }
10138
+ function parseCodexSession(lines) {
10139
+ let sessionStart2 = "";
10140
+ let runId = "";
10141
+ let cwd = "";
10142
+ let model = "";
10143
+ let input = 0;
10144
+ let cached = 0;
10145
+ let output = 0;
10146
+ let sawUsage = false;
10147
+ for (const raw of lines) {
10148
+ if (!raw.trim()) continue;
10149
+ let entry;
10150
+ try {
10151
+ entry = JSON.parse(raw);
10152
+ } catch {
10153
+ continue;
10154
+ }
10155
+ const p = entry.payload ?? {};
10156
+ if (entry.type === "session_meta") {
10157
+ if (!sessionStart2 && typeof p["timestamp"] === "string") sessionStart2 = p["timestamp"];
10158
+ if (!runId && typeof p["id"] === "string") runId = p["id"];
10159
+ if (!cwd && typeof p["cwd"] === "string") cwd = p["cwd"];
10160
+ continue;
10161
+ }
10162
+ if (entry.type === "turn_context") {
10163
+ if (typeof p["model"] === "string") model = p["model"];
10164
+ if (!cwd && typeof p["cwd"] === "string") cwd = p["cwd"];
10165
+ continue;
10166
+ }
10167
+ if (entry.type === "event_msg" && p["type"] === "token_count") {
10168
+ const info = p["info"] ?? {};
10169
+ const usage = info["total_token_usage"] ?? {};
10170
+ if (typeof usage["input_tokens"] === "number") input = usage["input_tokens"];
10171
+ if (typeof usage["cached_input_tokens"] === "number") cached = usage["cached_input_tokens"];
10172
+ if (typeof usage["output_tokens"] === "number") output = usage["output_tokens"];
10173
+ sawUsage = true;
10174
+ }
10175
+ }
10176
+ if (!sessionStart2 || !sawUsage) return null;
10177
+ const nonCached = Math.max(0, input - cached);
10178
+ if (nonCached === 0 && output === 0 && cached === 0) return null;
10179
+ const norm = normalizeModel(model || "gpt-5");
10180
+ const [pin, pout, , pcr] = codexPriceFor(model || "gpt-5");
10181
+ const costUSD = nonCached * pin + output * pout + cached * pcr;
10053
10182
  return {
10054
- date,
10183
+ date: sessionStart2.slice(0, 10),
10055
10184
  model: norm,
10056
- workingDir: "",
10057
- // Codex span carries no cwd — attribution is by runId (thread)
10185
+ workingDir: cwd,
10058
10186
  runId,
10059
10187
  costUSD,
10060
- inputTokens,
10188
+ inputTokens: nonCached,
10061
10189
  outputTokens: output,
10062
10190
  cacheReadTokens: cached,
10063
10191
  cacheWriteTokens: 0
10064
10192
  };
10065
10193
  }
10066
- var import_fs17, import_os16, import_path19, RE_INPUT, RE_CACHED, RE_NON_CACHED, RE_OUTPUT, RE_MODEL, RE_THREAD, RE_DATE, codexSource;
10194
+ var import_fs17, import_os16, import_path19, CODEX_FALLBACK, codexSource;
10067
10195
  var init_cost_codex = __esm({
10068
10196
  "src/cost-codex.ts"() {
10069
10197
  "use strict";
@@ -10071,42 +10199,32 @@ var init_cost_codex = __esm({
10071
10199
  import_os16 = __toESM(require("os"));
10072
10200
  import_path19 = __toESM(require("path"));
10073
10201
  init_litellm();
10074
- RE_INPUT = /token_usage\.input_tokens=(\d+)/;
10075
- RE_CACHED = /token_usage\.cached_input_tokens=(\d+)/;
10076
- RE_NON_CACHED = /token_usage\.non_cached_input_tokens=(\d+)/;
10077
- RE_OUTPUT = /token_usage\.output_tokens=(\d+)/;
10078
- RE_MODEL = /\bmodel=([^\s}]+)/;
10079
- RE_THREAD = /\bthread\.id=([0-9a-fA-F-]+)/;
10080
- RE_DATE = /^(\d{4}-\d{2}-\d{2})T/;
10202
+ CODEX_FALLBACK = [5e-6, 15e-6, 0, 25e-7];
10081
10203
  codexSource = {
10082
10204
  id: "codex",
10083
10205
  available() {
10084
10206
  try {
10085
- return import_fs17.default.existsSync(codexLogPath());
10207
+ return import_fs17.default.existsSync(codexSessionsDir());
10086
10208
  } catch {
10087
10209
  return false;
10088
10210
  }
10089
10211
  },
10090
10212
  collect(sinceMs) {
10091
- const file = codexLogPath();
10092
- let content;
10093
- try {
10094
- if (sinceMs !== void 0 && import_fs17.default.statSync(file).mtimeMs < sinceMs) return [];
10095
- content = import_fs17.default.readFileSync(file, "utf8");
10096
- } catch {
10097
- return [];
10098
- }
10213
+ const base = codexSessionsDir();
10099
10214
  const combined = /* @__PURE__ */ new Map();
10100
- for (const line of content.split("\n")) {
10101
- if (!line.includes("token_usage")) continue;
10102
- if (sinceMs !== void 0) {
10103
- const tsFull = line.match(/^(\S+)\s/)?.[1];
10104
- if (tsFull) {
10105
- const t = Date.parse(tsFull);
10106
- if (!Number.isNaN(t) && t < sinceMs) continue;
10107
- }
10215
+ for (const file of listCodexSessionFiles(base)) {
10216
+ try {
10217
+ if (sinceMs !== void 0 && import_fs17.default.statSync(file).mtimeMs < sinceMs) continue;
10218
+ } catch {
10219
+ continue;
10220
+ }
10221
+ let content;
10222
+ try {
10223
+ content = import_fs17.default.readFileSync(file, "utf8");
10224
+ } catch {
10225
+ continue;
10108
10226
  }
10109
- const e = parseCodexUsageLine(line);
10227
+ const e = parseCodexSession(content.split("\n"));
10110
10228
  if (!e) continue;
10111
10229
  const key = `${e.date}::${e.model}::${e.workingDir ?? ""}::${e.runId ?? ""}`;
10112
10230
  const prev = combined.get(key);
@@ -10126,15 +10244,286 @@ var init_cost_codex = __esm({
10126
10244
  }
10127
10245
  });
10128
10246
 
10247
+ // src/cost-gemini.ts
10248
+ function geminiTmpDir() {
10249
+ return import_path20.default.join(import_os17.default.homedir(), ".gemini", "tmp");
10250
+ }
10251
+ function geminiPriceFor(model) {
10252
+ let tuple = pricingFor(model);
10253
+ if (!tuple && /^gemini-/i.test(model)) {
10254
+ for (const proxy of GEMINI_FALLBACK_MODELS) {
10255
+ tuple = pricingFor(proxy);
10256
+ if (tuple) break;
10257
+ }
10258
+ }
10259
+ if (!tuple) return null;
10260
+ return { input: tuple[0], output: tuple[1], cacheRead: tuple[3] || tuple[0] };
10261
+ }
10262
+ function safeReaddir2(dir) {
10263
+ try {
10264
+ return import_fs18.default.readdirSync(dir);
10265
+ } catch {
10266
+ return [];
10267
+ }
10268
+ }
10269
+ function isDir2(p) {
10270
+ try {
10271
+ return import_fs18.default.statSync(p).isDirectory();
10272
+ } catch {
10273
+ return false;
10274
+ }
10275
+ }
10276
+ function listGeminiSessionFiles(base) {
10277
+ const out = [];
10278
+ for (const project of safeReaddir2(base)) {
10279
+ const chats = import_path20.default.join(base, project, "chats");
10280
+ if (!isDir2(chats)) continue;
10281
+ for (const f of safeReaddir2(chats)) {
10282
+ if (f.startsWith("session-") && f.endsWith(".jsonl")) {
10283
+ out.push({ file: import_path20.default.join(chats, f), project });
10284
+ }
10285
+ }
10286
+ }
10287
+ return out;
10288
+ }
10289
+ function parseGeminiSession(lines, project) {
10290
+ const seenIds = /* @__PURE__ */ new Set();
10291
+ const byKey = /* @__PURE__ */ new Map();
10292
+ let runId = "";
10293
+ for (const raw of lines) {
10294
+ if (!raw.trim()) continue;
10295
+ let obj;
10296
+ try {
10297
+ obj = JSON.parse(raw);
10298
+ } catch {
10299
+ continue;
10300
+ }
10301
+ if (typeof obj.sessionId === "string" && !runId) runId = obj.sessionId;
10302
+ if (!obj.tokens || !obj.model || !obj.timestamp) continue;
10303
+ if (obj.id) {
10304
+ if (seenIds.has(obj.id)) continue;
10305
+ seenIds.add(obj.id);
10306
+ }
10307
+ const price = geminiPriceFor(obj.model);
10308
+ if (!price) continue;
10309
+ const inp = obj.tokens.input ?? 0;
10310
+ const out = obj.tokens.output ?? 0;
10311
+ const cached = Math.min(obj.tokens.cached ?? 0, inp);
10312
+ const fresh = Math.max(0, inp - cached);
10313
+ const cost = fresh * price.input + cached * price.cacheRead + out * price.output;
10314
+ const date = obj.timestamp.slice(0, 10);
10315
+ const model = normalizeModel(obj.model);
10316
+ const key = `${date}::${model}`;
10317
+ const prev = byKey.get(key);
10318
+ if (prev) {
10319
+ prev.costUSD += cost;
10320
+ prev.inputTokens += fresh;
10321
+ prev.outputTokens += out;
10322
+ prev.cacheReadTokens += cached;
10323
+ } else {
10324
+ byKey.set(key, {
10325
+ date,
10326
+ model,
10327
+ workingDir: project,
10328
+ runId,
10329
+ costUSD: cost,
10330
+ inputTokens: fresh,
10331
+ outputTokens: out,
10332
+ cacheReadTokens: cached,
10333
+ cacheWriteTokens: 0
10334
+ });
10335
+ }
10336
+ }
10337
+ if (runId) for (const e of byKey.values()) e.runId = runId;
10338
+ return [...byKey.values()];
10339
+ }
10340
+ var import_fs18, import_os17, import_path20, GEMINI_FALLBACK_MODELS, geminiSource;
10341
+ var init_cost_gemini = __esm({
10342
+ "src/cost-gemini.ts"() {
10343
+ "use strict";
10344
+ import_fs18 = __toESM(require("fs"));
10345
+ import_os17 = __toESM(require("os"));
10346
+ import_path20 = __toESM(require("path"));
10347
+ init_litellm();
10348
+ GEMINI_FALLBACK_MODELS = ["gemini-2.5-flash", "gemini-2.0-flash"];
10349
+ geminiSource = {
10350
+ id: "gemini",
10351
+ available() {
10352
+ try {
10353
+ return import_fs18.default.existsSync(geminiTmpDir());
10354
+ } catch {
10355
+ return false;
10356
+ }
10357
+ },
10358
+ collect(sinceMs) {
10359
+ const combined = /* @__PURE__ */ new Map();
10360
+ for (const { file, project } of listGeminiSessionFiles(geminiTmpDir())) {
10361
+ try {
10362
+ if (sinceMs !== void 0 && import_fs18.default.statSync(file).mtimeMs < sinceMs) continue;
10363
+ } catch {
10364
+ continue;
10365
+ }
10366
+ let content;
10367
+ try {
10368
+ content = import_fs18.default.readFileSync(file, "utf8");
10369
+ } catch {
10370
+ continue;
10371
+ }
10372
+ for (const e of parseGeminiSession(content.split("\n"), project)) {
10373
+ const key = `${e.date}::${e.model}::${e.workingDir ?? ""}::${e.runId ?? ""}`;
10374
+ const prev = combined.get(key);
10375
+ if (prev) {
10376
+ prev.costUSD += e.costUSD;
10377
+ prev.inputTokens += e.inputTokens;
10378
+ prev.outputTokens += e.outputTokens;
10379
+ prev.cacheReadTokens += e.cacheReadTokens;
10380
+ prev.cacheWriteTokens += e.cacheWriteTokens;
10381
+ } else {
10382
+ combined.set(key, { ...e });
10383
+ }
10384
+ }
10385
+ }
10386
+ return [...combined.values()];
10387
+ }
10388
+ };
10389
+ }
10390
+ });
10391
+
10392
+ // src/cost-copilot.ts
10393
+ function copilotSessionsDir() {
10394
+ return import_path21.default.join(import_os18.default.homedir(), ".copilot", "session-state");
10395
+ }
10396
+ function safeReaddir3(dir) {
10397
+ try {
10398
+ return import_fs19.default.readdirSync(dir);
10399
+ } catch {
10400
+ return [];
10401
+ }
10402
+ }
10403
+ function priceTokens(model, u) {
10404
+ const tuple = pricingFor(model);
10405
+ if (!tuple || !u) return 0;
10406
+ const [pin, pout, pcw, pcr] = tuple;
10407
+ return (u.inputTokens ?? 0) * pin + (u.outputTokens ?? 0) * pout + (u.cacheWriteTokens ?? 0) * pcw + (u.cacheReadTokens ?? 0) * pcr;
10408
+ }
10409
+ function parseCopilotSession(lines) {
10410
+ let sessionId = "";
10411
+ let cwd = "";
10412
+ let startDate = "";
10413
+ let shutdownDate = "";
10414
+ let modelMetrics = null;
10415
+ for (const raw of lines) {
10416
+ if (!raw.trim()) continue;
10417
+ let o;
10418
+ try {
10419
+ o = JSON.parse(raw);
10420
+ } catch {
10421
+ continue;
10422
+ }
10423
+ const d = o.data ?? {};
10424
+ if (o.type === "session.start") {
10425
+ if (typeof d["sessionId"] === "string") sessionId = d["sessionId"];
10426
+ if (typeof d["startTime"] === "string") startDate = d["startTime"];
10427
+ const ctx = d["context"] ?? {};
10428
+ if (typeof ctx["cwd"] === "string") cwd = ctx["cwd"];
10429
+ } else if (o.type === "session.shutdown") {
10430
+ if (d["modelMetrics"] && typeof d["modelMetrics"] === "object") {
10431
+ modelMetrics = d["modelMetrics"];
10432
+ }
10433
+ if (typeof o.timestamp === "string") shutdownDate = o.timestamp;
10434
+ }
10435
+ }
10436
+ if (!modelMetrics) return [];
10437
+ const date = (startDate || shutdownDate).slice(0, 10);
10438
+ if (!date) return [];
10439
+ const rows = [];
10440
+ for (const [rawModel, m] of Object.entries(modelMetrics)) {
10441
+ const u = m.usage ?? {};
10442
+ const inputTokens = u.inputTokens ?? 0;
10443
+ const outputTokens = u.outputTokens ?? 0;
10444
+ const cacheReadTokens = u.cacheReadTokens ?? 0;
10445
+ const cacheWriteTokens = u.cacheWriteTokens ?? 0;
10446
+ if (inputTokens === 0 && outputTokens === 0 && cacheReadTokens === 0 && cacheWriteTokens === 0) {
10447
+ continue;
10448
+ }
10449
+ const model = normalizeModel(rawModel);
10450
+ const costUSD = typeof m.requests?.cost === "number" && m.requests.cost > 0 ? m.requests.cost : priceTokens(rawModel, u);
10451
+ rows.push({
10452
+ date,
10453
+ model,
10454
+ workingDir: cwd,
10455
+ runId: sessionId,
10456
+ costUSD,
10457
+ inputTokens,
10458
+ outputTokens,
10459
+ cacheReadTokens,
10460
+ cacheWriteTokens
10461
+ });
10462
+ }
10463
+ return rows;
10464
+ }
10465
+ var import_fs19, import_os18, import_path21, copilotSource;
10466
+ var init_cost_copilot = __esm({
10467
+ "src/cost-copilot.ts"() {
10468
+ "use strict";
10469
+ import_fs19 = __toESM(require("fs"));
10470
+ import_os18 = __toESM(require("os"));
10471
+ import_path21 = __toESM(require("path"));
10472
+ init_litellm();
10473
+ copilotSource = {
10474
+ id: "copilot",
10475
+ available() {
10476
+ try {
10477
+ return import_fs19.default.existsSync(copilotSessionsDir());
10478
+ } catch {
10479
+ return false;
10480
+ }
10481
+ },
10482
+ collect(sinceMs) {
10483
+ const base = copilotSessionsDir();
10484
+ const combined = /* @__PURE__ */ new Map();
10485
+ for (const sid of safeReaddir3(base)) {
10486
+ const file = import_path21.default.join(base, sid, "events.jsonl");
10487
+ try {
10488
+ if (sinceMs !== void 0 && import_fs19.default.statSync(file).mtimeMs < sinceMs) continue;
10489
+ } catch {
10490
+ continue;
10491
+ }
10492
+ let content;
10493
+ try {
10494
+ content = import_fs19.default.readFileSync(file, "utf8");
10495
+ } catch {
10496
+ continue;
10497
+ }
10498
+ for (const e of parseCopilotSession(content.split("\n"))) {
10499
+ const key = `${e.date}::${e.model}::${e.workingDir ?? ""}::${e.runId ?? ""}`;
10500
+ const prev = combined.get(key);
10501
+ if (prev) {
10502
+ prev.costUSD += e.costUSD;
10503
+ prev.inputTokens += e.inputTokens;
10504
+ prev.outputTokens += e.outputTokens;
10505
+ prev.cacheReadTokens += e.cacheReadTokens;
10506
+ prev.cacheWriteTokens += e.cacheWriteTokens;
10507
+ } else {
10508
+ combined.set(key, { ...e });
10509
+ }
10510
+ }
10511
+ }
10512
+ return [...combined.values()];
10513
+ }
10514
+ };
10515
+ }
10516
+ });
10517
+
10129
10518
  // src/costSync.ts
10130
10519
  function decodeProjectDirName(dirName) {
10131
10520
  return dirName.replace(/-/g, "/");
10132
10521
  }
10133
10522
  function parseJSONLFile(filePath, fallbackWorkingDir) {
10134
- const runId = import_path20.default.basename(filePath, ".jsonl");
10523
+ const runId = import_path22.default.basename(filePath, ".jsonl");
10135
10524
  let content;
10136
10525
  try {
10137
- content = import_fs18.default.readFileSync(filePath, "utf8");
10526
+ content = import_fs20.default.readFileSync(filePath, "utf8");
10138
10527
  } catch {
10139
10528
  return /* @__PURE__ */ new Map();
10140
10529
  }
@@ -10218,6 +10607,45 @@ function collectEntries(sinceMs) {
10218
10607
  }
10219
10608
  return [...combined.values()];
10220
10609
  }
10610
+ function chunk(arr, size) {
10611
+ if (size <= 0) return arr.length ? [arr] : [];
10612
+ const out = [];
10613
+ for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size));
10614
+ return out;
10615
+ }
10616
+ async function postCostBatches(apiUrl, apiKey, machineId, entries) {
10617
+ for (const batch of chunk(entries, COST_BATCH_SIZE)) {
10618
+ try {
10619
+ const res = await fetch(`${apiUrl}/cost-sync`, {
10620
+ method: "POST",
10621
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
10622
+ body: JSON.stringify({ machineId, entries: batch }),
10623
+ signal: AbortSignal.timeout(15e3)
10624
+ });
10625
+ if (!res.ok) {
10626
+ import_fs20.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] HTTP ${res.status}
10627
+ `);
10628
+ } else {
10629
+ let stored;
10630
+ try {
10631
+ const respBody = typeof res.json === "function" ? await res.json() : null;
10632
+ stored = respBody?.stored;
10633
+ } catch {
10634
+ }
10635
+ if (typeof stored === "number" && stored < batch.length) {
10636
+ import_fs20.default.appendFileSync(
10637
+ HOOK_DEBUG_LOG,
10638
+ `[cost-sync] dropped ${batch.length - stored} of ${batch.length} rows
10639
+ `
10640
+ );
10641
+ }
10642
+ }
10643
+ } catch (err2) {
10644
+ import_fs20.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] ${err2.message}
10645
+ `);
10646
+ }
10647
+ }
10648
+ }
10221
10649
  async function syncCost() {
10222
10650
  const creds = getCredentials();
10223
10651
  if (!creds?.apiKey || !creds?.apiUrl) return;
@@ -10226,25 +10654,11 @@ async function syncCost() {
10226
10654
  if (entries.length === 0) return;
10227
10655
  let username = "unknown";
10228
10656
  try {
10229
- username = import_os17.default.userInfo().username;
10657
+ username = import_os19.default.userInfo().username;
10230
10658
  } catch {
10231
10659
  }
10232
- const machineId = `${import_os17.default.hostname()}:${username}`;
10233
- try {
10234
- const res = await fetch(`${creds.apiUrl}/cost-sync`, {
10235
- method: "POST",
10236
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${creds.apiKey}` },
10237
- body: JSON.stringify({ machineId, entries }),
10238
- signal: AbortSignal.timeout(15e3)
10239
- });
10240
- if (!res.ok) {
10241
- import_fs18.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] HTTP ${res.status}
10242
- `);
10243
- }
10244
- } catch (err2) {
10245
- import_fs18.default.appendFileSync(HOOK_DEBUG_LOG, `[cost-sync] ${err2.message}
10246
- `);
10247
- }
10660
+ const machineId = `${import_os19.default.hostname()}:${username}`;
10661
+ await postCostBatches(creds.apiUrl, creds.apiKey, machineId, entries);
10248
10662
  }
10249
10663
  function startCostSync() {
10250
10664
  syncCost().catch(() => {
@@ -10255,52 +10669,54 @@ function startCostSync() {
10255
10669
  }, SYNC_INTERVAL_MS);
10256
10670
  timer.unref();
10257
10671
  }
10258
- var import_fs18, import_path20, import_os17, SYNC_INTERVAL_MS, claudeSource, COST_SOURCES;
10672
+ var import_fs20, import_path22, import_os19, SYNC_INTERVAL_MS, claudeSource, COST_SOURCES, COST_BATCH_SIZE;
10259
10673
  var init_costSync = __esm({
10260
10674
  "src/costSync.ts"() {
10261
10675
  "use strict";
10262
- import_fs18 = __toESM(require("fs"));
10263
- import_path20 = __toESM(require("path"));
10264
- import_os17 = __toESM(require("os"));
10676
+ import_fs20 = __toESM(require("fs"));
10677
+ import_path22 = __toESM(require("path"));
10678
+ import_os19 = __toESM(require("os"));
10265
10679
  init_config();
10266
10680
  init_audit();
10267
10681
  init_litellm();
10268
10682
  init_cost_codex();
10683
+ init_cost_gemini();
10684
+ init_cost_copilot();
10269
10685
  SYNC_INTERVAL_MS = 10 * 60 * 1e3;
10270
10686
  claudeSource = {
10271
10687
  id: "claude",
10272
10688
  available() {
10273
- return import_fs18.default.existsSync(import_path20.default.join(import_os17.default.homedir(), ".claude", "projects"));
10689
+ return import_fs20.default.existsSync(import_path22.default.join(import_os19.default.homedir(), ".claude", "projects"));
10274
10690
  },
10275
10691
  collect(sinceMs) {
10276
- const projectsDir = import_path20.default.join(import_os17.default.homedir(), ".claude", "projects");
10277
- if (!import_fs18.default.existsSync(projectsDir)) return [];
10692
+ const projectsDir = import_path22.default.join(import_os19.default.homedir(), ".claude", "projects");
10693
+ if (!import_fs20.default.existsSync(projectsDir)) return [];
10278
10694
  const combined = /* @__PURE__ */ new Map();
10279
10695
  let dirs;
10280
10696
  try {
10281
- dirs = import_fs18.default.readdirSync(projectsDir);
10697
+ dirs = import_fs20.default.readdirSync(projectsDir);
10282
10698
  } catch {
10283
10699
  return [];
10284
10700
  }
10285
10701
  for (const dir of dirs) {
10286
- const dirPath = import_path20.default.join(projectsDir, dir);
10702
+ const dirPath = import_path22.default.join(projectsDir, dir);
10287
10703
  try {
10288
- if (!import_fs18.default.statSync(dirPath).isDirectory()) continue;
10704
+ if (!import_fs20.default.statSync(dirPath).isDirectory()) continue;
10289
10705
  } catch {
10290
10706
  continue;
10291
10707
  }
10292
10708
  let files;
10293
10709
  try {
10294
- files = import_fs18.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
10710
+ files = import_fs20.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
10295
10711
  } catch {
10296
10712
  continue;
10297
10713
  }
10298
10714
  const fallbackWorkingDir = decodeProjectDirName(dir);
10299
10715
  for (const file of files) {
10300
- const filePath = import_path20.default.join(dirPath, file);
10716
+ const filePath = import_path22.default.join(dirPath, file);
10301
10717
  if (sinceMs !== void 0) {
10302
10718
  try {
10303
- if (import_fs18.default.statSync(filePath).mtimeMs < sinceMs) continue;
10719
+ if (import_fs20.default.statSync(filePath).mtimeMs < sinceMs) continue;
10304
10720
  } catch {
10305
10721
  continue;
10306
10722
  }
@@ -10323,7 +10739,8 @@ var init_costSync = __esm({
10323
10739
  return [...combined.values()];
10324
10740
  }
10325
10741
  };
10326
- COST_SOURCES = [claudeSource, codexSource];
10742
+ COST_SOURCES = [claudeSource, codexSource, geminiSource, copilotSource];
10743
+ COST_BATCH_SIZE = 200;
10327
10744
  }
10328
10745
  });
10329
10746
 
@@ -10350,7 +10767,7 @@ function freshWatermark() {
10350
10767
  function loadWatermark() {
10351
10768
  let raw;
10352
10769
  try {
10353
- raw = import_fs19.default.readFileSync(WATERMARK_FILE(), "utf-8");
10770
+ raw = import_fs21.default.readFileSync(WATERMARK_FILE(), "utf-8");
10354
10771
  } catch {
10355
10772
  return { status: "fresh", wm: freshWatermark() };
10356
10773
  }
@@ -10402,28 +10819,28 @@ function loadWatermark() {
10402
10819
  function saveWatermark(wm) {
10403
10820
  if (wm.schemaVersion > WATERMARK_SCHEMA_VERSION) return;
10404
10821
  const target = WATERMARK_FILE();
10405
- const dir = import_path21.default.dirname(target);
10406
- if (!import_fs19.default.existsSync(dir)) import_fs19.default.mkdirSync(dir, { recursive: true });
10822
+ const dir = import_path23.default.dirname(target);
10823
+ if (!import_fs21.default.existsSync(dir)) import_fs21.default.mkdirSync(dir, { recursive: true });
10407
10824
  const tmp = target + ".tmp";
10408
- import_fs19.default.writeFileSync(tmp, JSON.stringify(wm, null, 2) + "\n", "utf-8");
10409
- import_fs19.default.renameSync(tmp, target);
10825
+ import_fs21.default.writeFileSync(tmp, JSON.stringify(wm, null, 2) + "\n", "utf-8");
10826
+ import_fs21.default.renameSync(tmp, target);
10410
10827
  }
10411
10828
  function listJsonlFiles() {
10412
10829
  const root = PROJECTS_DIR();
10413
- if (!import_fs19.default.existsSync(root)) return [];
10830
+ if (!import_fs21.default.existsSync(root)) return [];
10414
10831
  const out = [];
10415
- for (const entry of import_fs19.default.readdirSync(root, { withFileTypes: true })) {
10832
+ for (const entry of import_fs21.default.readdirSync(root, { withFileTypes: true })) {
10416
10833
  if (!entry.isDirectory()) continue;
10417
- const projectDir = import_path21.default.join(root, entry.name);
10834
+ const projectDir = import_path23.default.join(root, entry.name);
10418
10835
  let inner;
10419
10836
  try {
10420
- inner = import_fs19.default.readdirSync(projectDir, { withFileTypes: true });
10837
+ inner = import_fs21.default.readdirSync(projectDir, { withFileTypes: true });
10421
10838
  } catch {
10422
10839
  continue;
10423
10840
  }
10424
10841
  for (const file of inner) {
10425
10842
  if (file.isFile() && file.name.endsWith(".jsonl")) {
10426
- out.push(import_path21.default.join(projectDir, file.name));
10843
+ out.push(import_path23.default.join(projectDir, file.name));
10427
10844
  }
10428
10845
  }
10429
10846
  }
@@ -10431,7 +10848,7 @@ function listJsonlFiles() {
10431
10848
  }
10432
10849
  function fileSize(p) {
10433
10850
  try {
10434
- return import_fs19.default.statSync(p).size;
10851
+ return import_fs21.default.statSync(p).size;
10435
10852
  } catch {
10436
10853
  return 0;
10437
10854
  }
@@ -10439,7 +10856,7 @@ function fileSize(p) {
10439
10856
  async function scanDelta(filePath, fromByte, onLine) {
10440
10857
  const size = fileSize(filePath);
10441
10858
  if (size <= fromByte) return fromByte;
10442
- const stream = import_fs19.default.createReadStream(filePath, {
10859
+ const stream = import_fs21.default.createReadStream(filePath, {
10443
10860
  start: fromByte,
10444
10861
  end: size - 1,
10445
10862
  highWaterMark: 64 * 1024
@@ -10551,7 +10968,7 @@ async function tickForensicBroadcast(offsets) {
10551
10968
  continue;
10552
10969
  }
10553
10970
  if (size <= offset) continue;
10554
- const sessionId = import_path21.default.basename(file, ".jsonl");
10971
+ const sessionId = import_path23.default.basename(file, ".jsonl");
10555
10972
  const newOffset = await scanDelta(file, offset, (obj, lineIndex) => {
10556
10973
  out.push(...extractFindingsFromLine(obj, sessionId, lineIndex));
10557
10974
  });
@@ -10610,7 +11027,7 @@ function emptyTick(uploadAs) {
10610
11027
  function readRawWatermarkPreservingOffsets() {
10611
11028
  let raw;
10612
11029
  try {
10613
- raw = import_fs19.default.readFileSync(WATERMARK_FILE(), "utf-8");
11030
+ raw = import_fs21.default.readFileSync(WATERMARK_FILE(), "utf-8");
10614
11031
  } catch {
10615
11032
  return null;
10616
11033
  }
@@ -10644,13 +11061,13 @@ async function runActualTick(wm) {
10644
11061
  if (!known) {
10645
11062
  let mtimeMs = 0;
10646
11063
  try {
10647
- mtimeMs = import_fs19.default.statSync(filePath).mtime.getTime();
11064
+ mtimeMs = import_fs21.default.statSync(filePath).mtime.getTime();
10648
11065
  } catch {
10649
11066
  continue;
10650
11067
  }
10651
11068
  if (mtimeMs >= watermarkCreatedAt) {
10652
11069
  filesNew++;
10653
- const sessionId2 = import_path21.default.basename(filePath, ".jsonl");
11070
+ const sessionId2 = import_path23.default.basename(filePath, ".jsonl");
10654
11071
  const newScannedTo2 = await scanDelta(filePath, 0, (obj, lineIndex) => {
10655
11072
  totalToolCalls++;
10656
11073
  toolCallsBySession[sessionId2] = (toolCallsBySession[sessionId2] ?? 0) + 1;
@@ -10668,7 +11085,7 @@ async function runActualTick(wm) {
10668
11085
  filesSkipped++;
10669
11086
  continue;
10670
11087
  }
10671
- const sessionId = import_path21.default.basename(filePath, ".jsonl");
11088
+ const sessionId = import_path23.default.basename(filePath, ".jsonl");
10672
11089
  const newScannedTo = await scanDelta(filePath, known.scannedTo, (obj, lineIndex) => {
10673
11090
  totalToolCalls++;
10674
11091
  toolCallsBySession[sessionId] = (toolCallsBySession[sessionId] ?? 0) + 1;
@@ -10690,18 +11107,18 @@ async function runActualTick(wm) {
10690
11107
  schemaFuture: false
10691
11108
  };
10692
11109
  }
10693
- var import_fs19, import_os18, import_path21, import_readline, PROJECTS_DIR, WATERMARK_FILE, MAX_LINE_BYTES, WATERMARK_SCHEMA_VERSION, LONG_OUTPUT_THRESHOLD_BYTES2;
11110
+ var import_fs21, import_os20, import_path23, import_readline, PROJECTS_DIR, WATERMARK_FILE, MAX_LINE_BYTES, WATERMARK_SCHEMA_VERSION, LONG_OUTPUT_THRESHOLD_BYTES2;
10694
11111
  var init_scan_watermark = __esm({
10695
11112
  "src/daemon/scan-watermark.ts"() {
10696
11113
  "use strict";
10697
- import_fs19 = __toESM(require("fs"));
10698
- import_os18 = __toESM(require("os"));
10699
- import_path21 = __toESM(require("path"));
11114
+ import_fs21 = __toESM(require("fs"));
11115
+ import_os20 = __toESM(require("os"));
11116
+ import_path23 = __toESM(require("path"));
10700
11117
  import_readline = __toESM(require("readline"));
10701
11118
  init_dlp();
10702
11119
  init_dist();
10703
- PROJECTS_DIR = () => import_path21.default.join(import_os18.default.homedir(), ".claude", "projects");
10704
- WATERMARK_FILE = () => import_path21.default.join(import_os18.default.homedir(), ".node9", "scan-watermark.json");
11120
+ PROJECTS_DIR = () => import_path23.default.join(import_os20.default.homedir(), ".claude", "projects");
11121
+ WATERMARK_FILE = () => import_path23.default.join(import_os20.default.homedir(), ".node9", "scan-watermark.json");
10705
11122
  MAX_LINE_BYTES = 2 * 1024 * 1024;
10706
11123
  WATERMARK_SCHEMA_VERSION = 2;
10707
11124
  LONG_OUTPUT_THRESHOLD_BYTES2 = LONG_OUTPUT_THRESHOLD_BYTES;
@@ -10750,40 +11167,40 @@ function parseSinceCutoff(raw, now = /* @__PURE__ */ new Date()) {
10750
11167
  return now.getTime() - 90 * 864e5;
10751
11168
  }
10752
11169
  function* iterateJsonlFiles(cutoffMs) {
10753
- const projectsDir = import_path22.default.join(import_os19.default.homedir(), ".claude", "projects");
11170
+ const projectsDir = import_path24.default.join(import_os21.default.homedir(), ".claude", "projects");
10754
11171
  let dirs;
10755
11172
  try {
10756
- dirs = import_fs20.default.readdirSync(projectsDir);
11173
+ dirs = import_fs22.default.readdirSync(projectsDir);
10757
11174
  } catch {
10758
11175
  return;
10759
11176
  }
10760
11177
  for (const dir of dirs) {
10761
- const dirPath = import_path22.default.join(projectsDir, dir);
11178
+ const dirPath = import_path24.default.join(projectsDir, dir);
10762
11179
  let stats;
10763
11180
  try {
10764
- stats = import_fs20.default.statSync(dirPath);
11181
+ stats = import_fs22.default.statSync(dirPath);
10765
11182
  } catch {
10766
11183
  continue;
10767
11184
  }
10768
11185
  if (!stats.isDirectory()) continue;
10769
11186
  let files;
10770
11187
  try {
10771
- files = import_fs20.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
11188
+ files = import_fs22.default.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl"));
10772
11189
  } catch {
10773
11190
  continue;
10774
11191
  }
10775
11192
  for (const file of files) {
10776
- const filePath = import_path22.default.join(dirPath, file);
11193
+ const filePath = import_path24.default.join(dirPath, file);
10777
11194
  let mtime = 0;
10778
11195
  try {
10779
- mtime = import_fs20.default.statSync(filePath).mtimeMs;
11196
+ mtime = import_fs22.default.statSync(filePath).mtimeMs;
10780
11197
  } catch {
10781
11198
  continue;
10782
11199
  }
10783
11200
  if (mtime < cutoffMs) continue;
10784
11201
  yield {
10785
11202
  filePath,
10786
- sessionId: import_path22.default.basename(file, ".jsonl"),
11203
+ sessionId: import_path24.default.basename(file, ".jsonl"),
10787
11204
  projectDir: dir
10788
11205
  };
10789
11206
  }
@@ -10837,7 +11254,9 @@ async function runUploadHistory(opts) {
10837
11254
  let filesScanned = 0;
10838
11255
  let linesParsed = 0;
10839
11256
  let linesSkipped = 0;
10840
- const dailyEntries = [];
11257
+ const dailyEntries = collectEntries(cutoffMs).filter(
11258
+ (e) => cutoffMs === 0 || Date.parse(e.date + "T00:00:00Z") >= cutoffMs
11259
+ );
10841
11260
  const liveLoopCfg = getConfig().policy.loopDetection;
10842
11261
  const loopCfg = {
10843
11262
  enabled: liveLoopCfg.enabled,
@@ -10849,7 +11268,7 @@ async function runUploadHistory(opts) {
10849
11268
  filesScanned++;
10850
11269
  let content;
10851
11270
  try {
10852
- content = import_fs20.default.readFileSync(filePath, "utf8");
11271
+ content = import_fs22.default.readFileSync(filePath, "utf8");
10853
11272
  } catch {
10854
11273
  continue;
10855
11274
  }
@@ -10899,14 +11318,6 @@ async function runUploadHistory(opts) {
10899
11318
  if (sf) findings.push(sf);
10900
11319
  }
10901
11320
  }
10902
- const fallbackWorkingDir = decodeProjectDirName(projectDir);
10903
- const dailyMap = parseJSONLFile(filePath, fallbackWorkingDir);
10904
- for (const entry of dailyMap.values()) {
10905
- if (cutoffMs > 0 && Date.parse(entry.date + "T00:00:00Z") < cutoffMs) {
10906
- continue;
10907
- }
10908
- dailyEntries.push(entry);
10909
- }
10910
11321
  }
10911
11322
  if (filesScanned === 0) {
10912
11323
  console.log(import_chalk4.default.yellow(" No JSONL files found in window. Nothing to upload."));
@@ -10931,10 +11342,10 @@ async function runUploadHistory(opts) {
10931
11342
  const costUrl = creds.apiUrl.endsWith("/policies/sync") ? creds.apiUrl.replace(/\/policies\/sync$/, "/cost-sync") : `${creds.apiUrl.replace(/\/$/, "")}/cost-sync`;
10932
11343
  let username = "unknown";
10933
11344
  try {
10934
- username = import_os19.default.userInfo().username;
11345
+ username = import_os21.default.userInfo().username;
10935
11346
  } catch {
10936
11347
  }
10937
- const machineId = `${import_os19.default.hostname()}:${username}`;
11348
+ const machineId = `${import_os21.default.hostname()}:${username}`;
10938
11349
  await postJson(costUrl, creds.apiKey, {
10939
11350
  machineId,
10940
11351
  entries: dailyEntries
@@ -10984,14 +11395,14 @@ async function postJson(url, apiKey, body) {
10984
11395
  req.end();
10985
11396
  });
10986
11397
  }
10987
- var import_fs20, import_https, import_os19, import_path22, import_chalk4, FINDING_TO_SIGNAL2;
11398
+ var import_fs22, import_https, import_os21, import_path24, import_chalk4, FINDING_TO_SIGNAL2;
10988
11399
  var init_scan_upload_history = __esm({
10989
11400
  "src/scan-upload-history.ts"() {
10990
11401
  "use strict";
10991
- import_fs20 = __toESM(require("fs"));
11402
+ import_fs22 = __toESM(require("fs"));
10992
11403
  import_https = __toESM(require("https"));
10993
- import_os19 = __toESM(require("os"));
10994
- import_path22 = __toESM(require("path"));
11404
+ import_os21 = __toESM(require("os"));
11405
+ import_path24 = __toESM(require("path"));
10995
11406
  import_chalk4 = __toESM(require("chalk"));
10996
11407
  init_dist();
10997
11408
  init_config();
@@ -11237,14 +11648,14 @@ function buildRuleSources() {
11237
11648
  }
11238
11649
  function countScanFiles() {
11239
11650
  let total = 0;
11240
- const claudeDir = import_path23.default.join(import_os20.default.homedir(), ".claude", "projects");
11241
- if (import_fs21.default.existsSync(claudeDir)) {
11651
+ const claudeDir = import_path25.default.join(import_os22.default.homedir(), ".claude", "projects");
11652
+ if (import_fs23.default.existsSync(claudeDir)) {
11242
11653
  try {
11243
- for (const proj of import_fs21.default.readdirSync(claudeDir)) {
11244
- const p = import_path23.default.join(claudeDir, proj);
11654
+ for (const proj of import_fs23.default.readdirSync(claudeDir)) {
11655
+ const p = import_path25.default.join(claudeDir, proj);
11245
11656
  try {
11246
- if (!import_fs21.default.statSync(p).isDirectory()) continue;
11247
- total += import_fs21.default.readdirSync(p).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-")).length;
11657
+ if (!import_fs23.default.statSync(p).isDirectory()) continue;
11658
+ total += import_fs23.default.readdirSync(p).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-")).length;
11248
11659
  } catch {
11249
11660
  continue;
11250
11661
  }
@@ -11252,17 +11663,17 @@ function countScanFiles() {
11252
11663
  } catch {
11253
11664
  }
11254
11665
  }
11255
- const geminiDir = import_path23.default.join(import_os20.default.homedir(), ".gemini", "tmp");
11256
- if (import_fs21.default.existsSync(geminiDir)) {
11666
+ const geminiDir = import_path25.default.join(import_os22.default.homedir(), ".gemini", "tmp");
11667
+ if (import_fs23.default.existsSync(geminiDir)) {
11257
11668
  try {
11258
- for (const slug of import_fs21.default.readdirSync(geminiDir)) {
11259
- const p = import_path23.default.join(geminiDir, slug);
11669
+ for (const slug of import_fs23.default.readdirSync(geminiDir)) {
11670
+ const p = import_path25.default.join(geminiDir, slug);
11260
11671
  try {
11261
- if (!import_fs21.default.statSync(p).isDirectory()) continue;
11262
- const chatsDir = import_path23.default.join(p, "chats");
11263
- if (import_fs21.default.existsSync(chatsDir)) {
11672
+ if (!import_fs23.default.statSync(p).isDirectory()) continue;
11673
+ const chatsDir = import_path25.default.join(p, "chats");
11674
+ if (import_fs23.default.existsSync(chatsDir)) {
11264
11675
  try {
11265
- total += import_fs21.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json")).length;
11676
+ total += import_fs23.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json")).length;
11266
11677
  } catch {
11267
11678
  }
11268
11679
  }
@@ -11274,15 +11685,15 @@ function countScanFiles() {
11274
11685
  }
11275
11686
  }
11276
11687
  for (const surface of ["antigravity-cli", "antigravity-ide"]) {
11277
- const brainDir = import_path23.default.join(import_os20.default.homedir(), ".gemini", surface, "brain");
11278
- if (!import_fs21.default.existsSync(brainDir)) continue;
11688
+ const brainDir = import_path25.default.join(import_os22.default.homedir(), ".gemini", surface, "brain");
11689
+ if (!import_fs23.default.existsSync(brainDir)) continue;
11279
11690
  try {
11280
- for (const conv of import_fs21.default.readdirSync(brainDir)) {
11281
- const convPath = import_path23.default.join(brainDir, conv);
11691
+ for (const conv of import_fs23.default.readdirSync(brainDir)) {
11692
+ const convPath = import_path25.default.join(brainDir, conv);
11282
11693
  try {
11283
- if (!import_fs21.default.statSync(convPath).isDirectory()) continue;
11284
- const logsDir = import_path23.default.join(convPath, ".system_generated", "logs");
11285
- if (import_fs21.default.existsSync(import_path23.default.join(logsDir, "transcript_full.jsonl")) || import_fs21.default.existsSync(import_path23.default.join(logsDir, "transcript.jsonl"))) {
11694
+ if (!import_fs23.default.statSync(convPath).isDirectory()) continue;
11695
+ const logsDir = import_path25.default.join(convPath, ".system_generated", "logs");
11696
+ if (import_fs23.default.existsSync(import_path25.default.join(logsDir, "transcript_full.jsonl")) || import_fs23.default.existsSync(import_path25.default.join(logsDir, "transcript.jsonl"))) {
11286
11697
  total += 1;
11287
11698
  }
11288
11699
  } catch {
@@ -11292,31 +11703,31 @@ function countScanFiles() {
11292
11703
  } catch {
11293
11704
  }
11294
11705
  }
11295
- const copilotDir = import_path23.default.join(import_os20.default.homedir(), ".copilot", "session-state");
11296
- if (import_fs21.default.existsSync(copilotDir)) {
11706
+ const copilotDir = import_path25.default.join(import_os22.default.homedir(), ".copilot", "session-state");
11707
+ if (import_fs23.default.existsSync(copilotDir)) {
11297
11708
  try {
11298
- for (const sid of import_fs21.default.readdirSync(copilotDir)) {
11299
- if (import_fs21.default.existsSync(import_path23.default.join(copilotDir, sid, "events.jsonl"))) total += 1;
11709
+ for (const sid of import_fs23.default.readdirSync(copilotDir)) {
11710
+ if (import_fs23.default.existsSync(import_path25.default.join(copilotDir, sid, "events.jsonl"))) total += 1;
11300
11711
  }
11301
11712
  } catch {
11302
11713
  }
11303
11714
  }
11304
- const codexDir = import_path23.default.join(import_os20.default.homedir(), ".codex", "sessions");
11305
- if (import_fs21.default.existsSync(codexDir)) {
11715
+ const codexDir = import_path25.default.join(import_os22.default.homedir(), ".codex", "sessions");
11716
+ if (import_fs23.default.existsSync(codexDir)) {
11306
11717
  try {
11307
- for (const year of import_fs21.default.readdirSync(codexDir)) {
11308
- const yp = import_path23.default.join(codexDir, year);
11718
+ for (const year of import_fs23.default.readdirSync(codexDir)) {
11719
+ const yp = import_path25.default.join(codexDir, year);
11309
11720
  try {
11310
- if (!import_fs21.default.statSync(yp).isDirectory()) continue;
11311
- for (const month of import_fs21.default.readdirSync(yp)) {
11312
- const mp = import_path23.default.join(yp, month);
11721
+ if (!import_fs23.default.statSync(yp).isDirectory()) continue;
11722
+ for (const month of import_fs23.default.readdirSync(yp)) {
11723
+ const mp = import_path25.default.join(yp, month);
11313
11724
  try {
11314
- if (!import_fs21.default.statSync(mp).isDirectory()) continue;
11315
- for (const day of import_fs21.default.readdirSync(mp)) {
11316
- const dp = import_path23.default.join(mp, day);
11725
+ if (!import_fs23.default.statSync(mp).isDirectory()) continue;
11726
+ for (const day of import_fs23.default.readdirSync(mp)) {
11727
+ const dp = import_path25.default.join(mp, day);
11317
11728
  try {
11318
- if (!import_fs21.default.statSync(dp).isDirectory()) continue;
11319
- total += import_fs21.default.readdirSync(dp).filter((f) => f.endsWith(".jsonl")).length;
11729
+ if (!import_fs23.default.statSync(dp).isDirectory()) continue;
11730
+ total += import_fs23.default.readdirSync(dp).filter((f) => f.endsWith(".jsonl")).length;
11320
11731
  } catch {
11321
11732
  continue;
11322
11733
  }
@@ -11352,7 +11763,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
11352
11763
  const sessionId = file.replace(/\.jsonl$/, "");
11353
11764
  let raw;
11354
11765
  try {
11355
- raw = import_fs21.default.readFileSync(import_path23.default.join(projPath, file), "utf-8");
11766
+ raw = import_fs23.default.readFileSync(import_path25.default.join(projPath, file), "utf-8");
11356
11767
  } catch {
11357
11768
  return;
11358
11769
  }
@@ -11404,7 +11815,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
11404
11815
  if (block.type !== "tool_result") continue;
11405
11816
  const filePath = block.tool_use_id ? toolUseFilePaths.get(block.tool_use_id) : void 0;
11406
11817
  if (filePath) {
11407
- const ext = import_path23.default.extname(filePath).toLowerCase();
11818
+ const ext = import_path25.default.extname(filePath).toLowerCase();
11408
11819
  if (CODE_EXTENSIONS.has(ext)) continue;
11409
11820
  }
11410
11821
  const resultText = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => c.text ?? "").join("\n") : null;
@@ -11461,7 +11872,7 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
11461
11872
  const rawCmd = String(input.command ?? "").trimStart();
11462
11873
  if (/^node9\s+(scan|explain|report|tail|dlp|status|sessions|audit)\b/.test(rawCmd)) continue;
11463
11874
  const inputFilePath = typeof input.file_path === "string" ? input.file_path : "";
11464
- const inputFileExt = inputFilePath ? import_path23.default.extname(inputFilePath).toLowerCase() : "";
11875
+ const inputFileExt = inputFilePath ? import_path25.default.extname(inputFilePath).toLowerCase() : "";
11465
11876
  if (CODE_EXTENSIONS.has(inputFileExt)) continue;
11466
11877
  const dlpMatch = scanArgs(input);
11467
11878
  if (dlpMatch) {
@@ -11558,19 +11969,19 @@ function processClaudeFile(file, projPath, projLabel, ruleSources, startDate, re
11558
11969
  }
11559
11970
  }
11560
11971
  function processClaudeProject(proj, projectsDir, ruleSources, startDate, result, dedup, onProgress, onLine) {
11561
- const projPath = import_path23.default.join(projectsDir, proj);
11972
+ const projPath = import_path25.default.join(projectsDir, proj);
11562
11973
  try {
11563
- if (!import_fs21.default.statSync(projPath).isDirectory()) return;
11974
+ if (!import_fs23.default.statSync(projPath).isDirectory()) return;
11564
11975
  } catch {
11565
11976
  return;
11566
11977
  }
11567
- const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(import_os20.default.homedir(), "~")).slice(
11978
+ const projLabel = stripTerminalEscapes(decodeURIComponent(proj).replace(import_os22.default.homedir(), "~")).slice(
11568
11979
  0,
11569
11980
  40
11570
11981
  );
11571
11982
  let files;
11572
11983
  try {
11573
- files = import_fs21.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
11984
+ files = import_fs23.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
11574
11985
  } catch {
11575
11986
  return;
11576
11987
  }
@@ -11604,12 +12015,12 @@ function emptyClaudeScan() {
11604
12015
  };
11605
12016
  }
11606
12017
  function scanClaudeHistory(startDate, onProgress, onLine) {
11607
- const projectsDir = import_path23.default.join(import_os20.default.homedir(), ".claude", "projects");
12018
+ const projectsDir = import_path25.default.join(import_os22.default.homedir(), ".claude", "projects");
11608
12019
  const result = emptyClaudeScan();
11609
- if (!import_fs21.default.existsSync(projectsDir)) return result;
12020
+ if (!import_fs23.default.existsSync(projectsDir)) return result;
11610
12021
  let projDirs;
11611
12022
  try {
11612
- projDirs = import_fs21.default.readdirSync(projectsDir);
12023
+ projDirs = import_fs23.default.readdirSync(projectsDir);
11613
12024
  } catch {
11614
12025
  return result;
11615
12026
  }
@@ -11630,7 +12041,7 @@ function scanClaudeHistory(startDate, onProgress, onLine) {
11630
12041
  return result;
11631
12042
  }
11632
12043
  function scanGeminiHistory(startDate, onProgress, onLine) {
11633
- const tmpDir = import_path23.default.join(import_os20.default.homedir(), ".gemini", "tmp");
12044
+ const tmpDir = import_path25.default.join(import_os22.default.homedir(), ".gemini", "tmp");
11634
12045
  const result = {
11635
12046
  filesScanned: 0,
11636
12047
  sessions: 0,
@@ -11645,33 +12056,33 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
11645
12056
  sessionsWithEarlySecrets: 0
11646
12057
  };
11647
12058
  const dedup = emptyScanDedup();
11648
- if (!import_fs21.default.existsSync(tmpDir)) return result;
12059
+ if (!import_fs23.default.existsSync(tmpDir)) return result;
11649
12060
  let slugDirs;
11650
12061
  try {
11651
- slugDirs = import_fs21.default.readdirSync(tmpDir);
12062
+ slugDirs = import_fs23.default.readdirSync(tmpDir);
11652
12063
  } catch {
11653
12064
  return result;
11654
12065
  }
11655
12066
  const ruleSources = buildRuleSources();
11656
12067
  for (const slug of slugDirs) {
11657
- const slugPath = import_path23.default.join(tmpDir, slug);
12068
+ const slugPath = import_path25.default.join(tmpDir, slug);
11658
12069
  try {
11659
- if (!import_fs21.default.statSync(slugPath).isDirectory()) continue;
12070
+ if (!import_fs23.default.statSync(slugPath).isDirectory()) continue;
11660
12071
  } catch {
11661
12072
  continue;
11662
12073
  }
11663
12074
  let projLabel = stripTerminalEscapes(slug).slice(0, 40);
11664
12075
  try {
11665
12076
  projLabel = stripTerminalEscapes(
11666
- import_fs21.default.readFileSync(import_path23.default.join(slugPath, ".project_root"), "utf-8").trim()
11667
- ).replace(import_os20.default.homedir(), "~").slice(0, 40);
12077
+ import_fs23.default.readFileSync(import_path25.default.join(slugPath, ".project_root"), "utf-8").trim()
12078
+ ).replace(import_os22.default.homedir(), "~").slice(0, 40);
11668
12079
  } catch {
11669
12080
  }
11670
- const chatsDir = import_path23.default.join(slugPath, "chats");
11671
- if (!import_fs21.default.existsSync(chatsDir)) continue;
12081
+ const chatsDir = import_path25.default.join(slugPath, "chats");
12082
+ if (!import_fs23.default.existsSync(chatsDir)) continue;
11672
12083
  let chatFiles;
11673
12084
  try {
11674
- chatFiles = import_fs21.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
12085
+ chatFiles = import_fs23.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
11675
12086
  } catch {
11676
12087
  continue;
11677
12088
  }
@@ -11681,7 +12092,7 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
11681
12092
  const sessionId = chatFile.replace(/\.json$/, "");
11682
12093
  let raw;
11683
12094
  try {
11684
- raw = import_fs21.default.readFileSync(import_path23.default.join(chatsDir, chatFile), "utf-8");
12095
+ raw = import_fs23.default.readFileSync(import_path25.default.join(chatsDir, chatFile), "utf-8");
11685
12096
  } catch {
11686
12097
  continue;
11687
12098
  }
@@ -11843,13 +12254,13 @@ function scanGeminiHistory(startDate, onProgress, onLine) {
11843
12254
  return result;
11844
12255
  }
11845
12256
  function antigravityBrainDirs() {
11846
- return ["antigravity-cli", "antigravity-ide"].map((surface) => import_path23.default.join(import_os20.default.homedir(), ".gemini", surface, "brain")).filter((p) => import_fs21.default.existsSync(p));
12257
+ return ["antigravity-cli", "antigravity-ide"].map((surface) => import_path25.default.join(import_os22.default.homedir(), ".gemini", surface, "brain")).filter((p) => import_fs23.default.existsSync(p));
11847
12258
  }
11848
12259
  function antigravityTranscriptPath(convPath) {
11849
- const logsDir = import_path23.default.join(convPath, ".system_generated", "logs");
12260
+ const logsDir = import_path25.default.join(convPath, ".system_generated", "logs");
11850
12261
  for (const name of ["transcript_full.jsonl", "transcript.jsonl"]) {
11851
- const p = import_path23.default.join(logsDir, name);
11852
- if (import_fs21.default.existsSync(p)) return p;
12262
+ const p = import_path25.default.join(logsDir, name);
12263
+ if (import_fs23.default.existsSync(p)) return p;
11853
12264
  }
11854
12265
  return null;
11855
12266
  }
@@ -11875,14 +12286,14 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
11875
12286
  for (const brainDir of brainDirs) {
11876
12287
  let convDirs;
11877
12288
  try {
11878
- convDirs = import_fs21.default.readdirSync(brainDir);
12289
+ convDirs = import_fs23.default.readdirSync(brainDir);
11879
12290
  } catch {
11880
12291
  continue;
11881
12292
  }
11882
12293
  for (const conv of convDirs) {
11883
- const convPath = import_path23.default.join(brainDir, conv);
12294
+ const convPath = import_path25.default.join(brainDir, conv);
11884
12295
  try {
11885
- if (!import_fs21.default.statSync(convPath).isDirectory()) continue;
12296
+ if (!import_fs23.default.statSync(convPath).isDirectory()) continue;
11886
12297
  } catch {
11887
12298
  continue;
11888
12299
  }
@@ -11892,7 +12303,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
11892
12303
  onProgress?.(result.filesScanned);
11893
12304
  let raw;
11894
12305
  try {
11895
- raw = import_fs21.default.readFileSync(transcriptFile, "utf-8");
12306
+ raw = import_fs23.default.readFileSync(transcriptFile, "utf-8");
11896
12307
  } catch {
11897
12308
  continue;
11898
12309
  }
@@ -11949,7 +12360,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
11949
12360
  result.bashCalls++;
11950
12361
  const cwd = String(input.cwd ?? "");
11951
12362
  if (cwd && projLabel === conv.slice(0, 8)) {
11952
- projLabel = stripTerminalEscapes(cwd).replace(import_os20.default.homedir(), "~").slice(0, 40);
12363
+ projLabel = stripTerminalEscapes(cwd).replace(import_os22.default.homedir(), "~").slice(0, 40);
11953
12364
  }
11954
12365
  }
11955
12366
  const rawCmd = String(input.command ?? "").trimStart();
@@ -12049,7 +12460,7 @@ function scanAntigravityHistory(startDate, onProgress, onLine) {
12049
12460
  return result;
12050
12461
  }
12051
12462
  function scanCopilotHistory(startDate, onProgress, onLine) {
12052
- const sessionDir = import_path23.default.join(import_os20.default.homedir(), ".copilot", "session-state");
12463
+ const sessionDir = import_path25.default.join(import_os22.default.homedir(), ".copilot", "session-state");
12053
12464
  const result = {
12054
12465
  filesScanned: 0,
12055
12466
  sessions: 0,
@@ -12065,22 +12476,22 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
12065
12476
  sessionsWithEarlySecrets: 0
12066
12477
  };
12067
12478
  const dedup = emptyScanDedup();
12068
- if (!import_fs21.default.existsSync(sessionDir)) return result;
12479
+ if (!import_fs23.default.existsSync(sessionDir)) return result;
12069
12480
  let sessionIds;
12070
12481
  try {
12071
- sessionIds = import_fs21.default.readdirSync(sessionDir);
12482
+ sessionIds = import_fs23.default.readdirSync(sessionDir);
12072
12483
  } catch {
12073
12484
  return result;
12074
12485
  }
12075
12486
  const ruleSources = buildRuleSources();
12076
12487
  for (const sessionId of sessionIds) {
12077
- const eventsPath = import_path23.default.join(sessionDir, sessionId, "events.jsonl");
12078
- if (!import_fs21.default.existsSync(eventsPath)) continue;
12488
+ const eventsPath = import_path25.default.join(sessionDir, sessionId, "events.jsonl");
12489
+ if (!import_fs23.default.existsSync(eventsPath)) continue;
12079
12490
  result.filesScanned++;
12080
12491
  onProgress?.(result.filesScanned);
12081
12492
  let raw;
12082
12493
  try {
12083
- raw = import_fs21.default.readFileSync(eventsPath, "utf-8");
12494
+ raw = import_fs23.default.readFileSync(eventsPath, "utf-8");
12084
12495
  } catch {
12085
12496
  continue;
12086
12497
  }
@@ -12100,7 +12511,7 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
12100
12511
  if (ev.type === "session.start") {
12101
12512
  const cwd = ev.data?.context?.cwd;
12102
12513
  if (typeof cwd === "string" && cwd) {
12103
- projLabel = stripTerminalEscapes(cwd).replace(import_os20.default.homedir(), "~").slice(0, 40);
12514
+ projLabel = stripTerminalEscapes(cwd).replace(import_os22.default.homedir(), "~").slice(0, 40);
12104
12515
  }
12105
12516
  continue;
12106
12517
  }
@@ -12232,7 +12643,7 @@ function scanCopilotHistory(startDate, onProgress, onLine) {
12232
12643
  return result;
12233
12644
  }
12234
12645
  function scanCodexHistory(startDate, onProgress, onLine) {
12235
- const sessionsBase = import_path23.default.join(import_os20.default.homedir(), ".codex", "sessions");
12646
+ const sessionsBase = import_path25.default.join(import_os22.default.homedir(), ".codex", "sessions");
12236
12647
  const result = {
12237
12648
  filesScanned: 0,
12238
12649
  sessions: 0,
@@ -12247,32 +12658,32 @@ function scanCodexHistory(startDate, onProgress, onLine) {
12247
12658
  sessionsWithEarlySecrets: 0
12248
12659
  };
12249
12660
  const dedup = emptyScanDedup();
12250
- if (!import_fs21.default.existsSync(sessionsBase)) return result;
12661
+ if (!import_fs23.default.existsSync(sessionsBase)) return result;
12251
12662
  const jsonlFiles = [];
12252
12663
  try {
12253
- for (const year of import_fs21.default.readdirSync(sessionsBase)) {
12254
- const yearPath = import_path23.default.join(sessionsBase, year);
12664
+ for (const year of import_fs23.default.readdirSync(sessionsBase)) {
12665
+ const yearPath = import_path25.default.join(sessionsBase, year);
12255
12666
  try {
12256
- if (!import_fs21.default.statSync(yearPath).isDirectory()) continue;
12667
+ if (!import_fs23.default.statSync(yearPath).isDirectory()) continue;
12257
12668
  } catch {
12258
12669
  continue;
12259
12670
  }
12260
- for (const month of import_fs21.default.readdirSync(yearPath)) {
12261
- const monthPath = import_path23.default.join(yearPath, month);
12671
+ for (const month of import_fs23.default.readdirSync(yearPath)) {
12672
+ const monthPath = import_path25.default.join(yearPath, month);
12262
12673
  try {
12263
- if (!import_fs21.default.statSync(monthPath).isDirectory()) continue;
12674
+ if (!import_fs23.default.statSync(monthPath).isDirectory()) continue;
12264
12675
  } catch {
12265
12676
  continue;
12266
12677
  }
12267
- for (const day of import_fs21.default.readdirSync(monthPath)) {
12268
- const dayPath = import_path23.default.join(monthPath, day);
12678
+ for (const day of import_fs23.default.readdirSync(monthPath)) {
12679
+ const dayPath = import_path25.default.join(monthPath, day);
12269
12680
  try {
12270
- if (!import_fs21.default.statSync(dayPath).isDirectory()) continue;
12681
+ if (!import_fs23.default.statSync(dayPath).isDirectory()) continue;
12271
12682
  } catch {
12272
12683
  continue;
12273
12684
  }
12274
- for (const file of import_fs21.default.readdirSync(dayPath)) {
12275
- if (file.endsWith(".jsonl")) jsonlFiles.push(import_path23.default.join(dayPath, file));
12685
+ for (const file of import_fs23.default.readdirSync(dayPath)) {
12686
+ if (file.endsWith(".jsonl")) jsonlFiles.push(import_path25.default.join(dayPath, file));
12276
12687
  }
12277
12688
  }
12278
12689
  }
@@ -12286,7 +12697,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
12286
12697
  onProgress?.(result.filesScanned);
12287
12698
  let lines;
12288
12699
  try {
12289
- lines = import_fs21.default.readFileSync(filePath, "utf-8").split("\n");
12700
+ lines = import_fs23.default.readFileSync(filePath, "utf-8").split("\n");
12290
12701
  } catch {
12291
12702
  continue;
12292
12703
  }
@@ -12312,7 +12723,7 @@ function scanCodexHistory(startDate, onProgress, onLine) {
12312
12723
  sessionId = String(payload["id"] ?? filePath);
12313
12724
  startTime = String(payload["timestamp"] ?? "");
12314
12725
  const cwd = String(payload["cwd"] ?? "");
12315
- projLabel = stripTerminalEscapes(cwd.replace(import_os20.default.homedir(), "~")).slice(0, 40);
12726
+ projLabel = stripTerminalEscapes(cwd.replace(import_os22.default.homedir(), "~")).slice(0, 40);
12316
12727
  continue;
12317
12728
  }
12318
12729
  if (entry.type === "event_msg" && payload["type"] === "token_count") {
@@ -12465,17 +12876,17 @@ function scanCodexHistory(startDate, onProgress, onLine) {
12465
12876
  return result;
12466
12877
  }
12467
12878
  function scanShellConfig() {
12468
- const home = import_os20.default.homedir();
12879
+ const home = import_os22.default.homedir();
12469
12880
  const configFiles = [".zshrc", ".bashrc", ".bash_profile", ".profile"].map(
12470
- (f) => import_path23.default.join(home, f)
12881
+ (f) => import_path25.default.join(home, f)
12471
12882
  );
12472
12883
  const findings = [];
12473
12884
  const seen = /* @__PURE__ */ new Set();
12474
12885
  for (const filePath of configFiles) {
12475
- if (!import_fs21.default.existsSync(filePath)) continue;
12886
+ if (!import_fs23.default.existsSync(filePath)) continue;
12476
12887
  let lines;
12477
12888
  try {
12478
- lines = import_fs21.default.readFileSync(filePath, "utf-8").split("\n");
12889
+ lines = import_fs23.default.readFileSync(filePath, "utf-8").split("\n");
12479
12890
  } catch {
12480
12891
  continue;
12481
12892
  }
@@ -13281,7 +13692,7 @@ function registerScanCommand(program2) {
13281
13692
  if (!drillDown) {
13282
13693
  const useInk2 = !options.classic;
13283
13694
  if (useInk2) {
13284
- const scanInkPath = import_path23.default.join(__dirname, "scan-ink.mjs");
13695
+ const scanInkPath = import_path25.default.join(__dirname, "scan-ink.mjs");
13285
13696
  const dynamicImport = new Function("id", "return import(id)");
13286
13697
  const mod = await dynamicImport(`file://${scanInkPath}`);
13287
13698
  const rangeLabel2 = options.all ? "all time" : `last ${options.days ?? 90} days`;
@@ -13506,14 +13917,14 @@ function registerScanCommand(program2) {
13506
13917
  }
13507
13918
  );
13508
13919
  }
13509
- var import_chalk5, import_fs21, import_path23, import_os20, import_string_width2, CLAUDE_PRICING, GEMINI_PRICING, 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;
13920
+ var import_chalk5, import_fs23, import_path25, import_os22, import_string_width2, CLAUDE_PRICING, GEMINI_PRICING, 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;
13510
13921
  var init_scan = __esm({
13511
13922
  "src/cli/commands/scan.ts"() {
13512
13923
  "use strict";
13513
13924
  import_chalk5 = __toESM(require("chalk"));
13514
- import_fs21 = __toESM(require("fs"));
13515
- import_path23 = __toESM(require("path"));
13516
- import_os20 = __toESM(require("os"));
13925
+ import_fs23 = __toESM(require("fs"));
13926
+ import_path25 = __toESM(require("path"));
13927
+ import_os22 = __toESM(require("os"));
13517
13928
  init_shields();
13518
13929
  init_config();
13519
13930
  init_policy();
@@ -13707,12 +14118,12 @@ var init_suggestion_tracker = __esm({
13707
14118
  });
13708
14119
 
13709
14120
  // src/daemon/taint-store.ts
13710
- var import_fs22, import_path24, DEFAULT_TTL_MS, TaintStore;
14121
+ var import_fs24, import_path26, DEFAULT_TTL_MS, TaintStore;
13711
14122
  var init_taint_store = __esm({
13712
14123
  "src/daemon/taint-store.ts"() {
13713
14124
  "use strict";
13714
- import_fs22 = __toESM(require("fs"));
13715
- import_path24 = __toESM(require("path"));
14125
+ import_fs24 = __toESM(require("fs"));
14126
+ import_path26 = __toESM(require("path"));
13716
14127
  DEFAULT_TTL_MS = 60 * 60 * 1e3;
13717
14128
  TaintStore = class {
13718
14129
  records = /* @__PURE__ */ new Map();
@@ -13777,9 +14188,9 @@ var init_taint_store = __esm({
13777
14188
  /** Resolve to absolute path, falling back to path.resolve if file doesn't exist yet. */
13778
14189
  _resolve(filePath) {
13779
14190
  try {
13780
- return import_fs22.default.realpathSync.native(import_path24.default.resolve(filePath));
14191
+ return import_fs24.default.realpathSync.native(import_path26.default.resolve(filePath));
13781
14192
  } catch {
13782
- return import_path24.default.resolve(filePath);
14193
+ return import_path26.default.resolve(filePath);
13783
14194
  }
13784
14195
  }
13785
14196
  };
@@ -13897,8 +14308,8 @@ var init_session_history = __esm({
13897
14308
  // src/daemon/state.ts
13898
14309
  function loadInsightCounts() {
13899
14310
  try {
13900
- if (!import_fs23.default.existsSync(INSIGHT_COUNTS_FILE)) return;
13901
- const data = JSON.parse(import_fs23.default.readFileSync(INSIGHT_COUNTS_FILE, "utf-8"));
14311
+ if (!import_fs25.default.existsSync(INSIGHT_COUNTS_FILE)) return;
14312
+ const data = JSON.parse(import_fs25.default.readFileSync(INSIGHT_COUNTS_FILE, "utf-8"));
13902
14313
  for (const [tool, count] of Object.entries(data)) {
13903
14314
  if (typeof count === "number" && count > 0) insightCounts.set(tool, count);
13904
14315
  }
@@ -13937,23 +14348,23 @@ function markRejectionHandlerRegistered() {
13937
14348
  daemonRejectionHandlerRegistered = true;
13938
14349
  }
13939
14350
  function atomicWriteSync2(filePath, data, options) {
13940
- const dir = import_path25.default.dirname(filePath);
13941
- if (!import_fs23.default.existsSync(dir)) import_fs23.default.mkdirSync(dir, { recursive: true });
14351
+ const dir = import_path27.default.dirname(filePath);
14352
+ if (!import_fs25.default.existsSync(dir)) import_fs25.default.mkdirSync(dir, { recursive: true });
13942
14353
  const tmpPath = `${filePath}.${(0, import_crypto8.randomUUID)()}.tmp`;
13943
14354
  try {
13944
- import_fs23.default.writeFileSync(tmpPath, data, options);
14355
+ import_fs25.default.writeFileSync(tmpPath, data, options);
13945
14356
  } catch (err2) {
13946
14357
  try {
13947
- import_fs23.default.unlinkSync(tmpPath);
14358
+ import_fs25.default.unlinkSync(tmpPath);
13948
14359
  } catch {
13949
14360
  }
13950
14361
  throw err2;
13951
14362
  }
13952
14363
  try {
13953
- import_fs23.default.renameSync(tmpPath, filePath);
14364
+ import_fs25.default.renameSync(tmpPath, filePath);
13954
14365
  } catch (err2) {
13955
14366
  try {
13956
- import_fs23.default.unlinkSync(tmpPath);
14367
+ import_fs25.default.unlinkSync(tmpPath);
13957
14368
  } catch {
13958
14369
  }
13959
14370
  throw err2;
@@ -13977,16 +14388,16 @@ function appendAuditLog(data) {
13977
14388
  decision: data.decision,
13978
14389
  source: "daemon"
13979
14390
  };
13980
- const dir = import_path25.default.dirname(AUDIT_LOG_FILE);
13981
- if (!import_fs23.default.existsSync(dir)) import_fs23.default.mkdirSync(dir, { recursive: true });
13982
- import_fs23.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
14391
+ const dir = import_path27.default.dirname(AUDIT_LOG_FILE);
14392
+ if (!import_fs25.default.existsSync(dir)) import_fs25.default.mkdirSync(dir, { recursive: true });
14393
+ import_fs25.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
13983
14394
  } catch {
13984
14395
  }
13985
14396
  }
13986
14397
  function getAuditHistory(limit = 20) {
13987
14398
  try {
13988
- if (!import_fs23.default.existsSync(AUDIT_LOG_FILE)) return [];
13989
- const lines = import_fs23.default.readFileSync(AUDIT_LOG_FILE, "utf-8").trim().split("\n");
14399
+ if (!import_fs25.default.existsSync(AUDIT_LOG_FILE)) return [];
14400
+ const lines = import_fs25.default.readFileSync(AUDIT_LOG_FILE, "utf-8").trim().split("\n");
13990
14401
  if (lines.length === 1 && lines[0] === "") return [];
13991
14402
  return lines.slice(-limit).map((l) => JSON.parse(l)).reverse();
13992
14403
  } catch {
@@ -13995,7 +14406,7 @@ function getAuditHistory(limit = 20) {
13995
14406
  }
13996
14407
  function getOrgName() {
13997
14408
  try {
13998
- if (import_fs23.default.existsSync(CREDENTIALS_FILE)) return "Node9 Cloud";
14409
+ if (import_fs25.default.existsSync(CREDENTIALS_FILE)) return "Node9 Cloud";
13999
14410
  } catch {
14000
14411
  }
14001
14412
  return null;
@@ -14003,8 +14414,8 @@ function getOrgName() {
14003
14414
  function writeGlobalSetting(key, value) {
14004
14415
  let config = {};
14005
14416
  try {
14006
- if (import_fs23.default.existsSync(GLOBAL_CONFIG_FILE)) {
14007
- config = JSON.parse(import_fs23.default.readFileSync(GLOBAL_CONFIG_FILE, "utf-8"));
14417
+ if (import_fs25.default.existsSync(GLOBAL_CONFIG_FILE)) {
14418
+ config = JSON.parse(import_fs25.default.readFileSync(GLOBAL_CONFIG_FILE, "utf-8"));
14008
14419
  }
14009
14420
  } catch {
14010
14421
  }
@@ -14016,8 +14427,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
14016
14427
  try {
14017
14428
  let trust = { entries: [] };
14018
14429
  try {
14019
- if (import_fs23.default.existsSync(TRUST_FILE2))
14020
- trust = JSON.parse(import_fs23.default.readFileSync(TRUST_FILE2, "utf-8"));
14430
+ if (import_fs25.default.existsSync(TRUST_FILE2))
14431
+ trust = JSON.parse(import_fs25.default.readFileSync(TRUST_FILE2, "utf-8"));
14021
14432
  } catch {
14022
14433
  }
14023
14434
  trust.entries = trust.entries.filter(
@@ -14034,8 +14445,8 @@ function writeTrustEntry(toolName, durationMs, commandPattern) {
14034
14445
  }
14035
14446
  function readPersistentDecisions() {
14036
14447
  try {
14037
- if (import_fs23.default.existsSync(DECISIONS_FILE)) {
14038
- return JSON.parse(import_fs23.default.readFileSync(DECISIONS_FILE, "utf-8"));
14448
+ if (import_fs25.default.existsSync(DECISIONS_FILE)) {
14449
+ return JSON.parse(import_fs25.default.readFileSync(DECISIONS_FILE, "utf-8"));
14039
14450
  }
14040
14451
  } catch {
14041
14452
  }
@@ -14052,7 +14463,7 @@ function writePersistentDecision(toolName, decision) {
14052
14463
  function readBody(req) {
14053
14464
  return new Promise((resolve) => {
14054
14465
  let body = "";
14055
- req.on("data", (chunk) => body += chunk);
14466
+ req.on("data", (chunk2) => body += chunk2);
14056
14467
  req.on("end", () => resolve(body));
14057
14468
  });
14058
14469
  }
@@ -14063,7 +14474,7 @@ function estimateToolCost(tool, args) {
14063
14474
  const filePath = a.file_path ?? a.path;
14064
14475
  if (filePath) {
14065
14476
  try {
14066
- const bytes = import_fs23.default.statSync(filePath).size;
14477
+ const bytes = import_fs25.default.statSync(filePath).size;
14067
14478
  return bytes / BYTES_PER_TOKEN / 1e6 * INPUT_PRICE_PER_1M;
14068
14479
  } catch {
14069
14480
  }
@@ -14134,7 +14545,7 @@ function abandonPending() {
14134
14545
  });
14135
14546
  if (autoStarted) {
14136
14547
  try {
14137
- import_fs23.default.unlinkSync(DAEMON_PID_FILE);
14548
+ import_fs25.default.unlinkSync(DAEMON_PID_FILE);
14138
14549
  } catch {
14139
14550
  }
14140
14551
  setTimeout(() => {
@@ -14145,8 +14556,8 @@ function abandonPending() {
14145
14556
  }
14146
14557
  function logActivitySocket(msg) {
14147
14558
  try {
14148
- import_fs23.default.appendFileSync(
14149
- import_path25.default.join(homeDir, ".node9", "hook-debug.log"),
14559
+ import_fs25.default.appendFileSync(
14560
+ import_path27.default.join(homeDir, ".node9", "hook-debug.log"),
14150
14561
  `[${(/* @__PURE__ */ new Date()).toISOString()}] [activity-socket] ${msg}
14151
14562
  `
14152
14563
  );
@@ -14168,13 +14579,13 @@ function shouldRebind(now = Date.now()) {
14168
14579
  function startActivitySocket() {
14169
14580
  bindActivitySocket();
14170
14581
  activityHealthInterval = setInterval(() => {
14171
- if (!import_fs23.default.existsSync(ACTIVITY_SOCKET_PATH2)) attemptRebind("health-probe");
14582
+ if (!import_fs25.default.existsSync(ACTIVITY_SOCKET_PATH2)) attemptRebind("health-probe");
14172
14583
  }, ACTIVITY_HEALTH_PROBE_MS);
14173
14584
  activityHealthInterval.unref();
14174
14585
  process.on("exit", () => {
14175
14586
  if (activityHealthInterval) clearInterval(activityHealthInterval);
14176
14587
  try {
14177
- import_fs23.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
14588
+ import_fs25.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
14178
14589
  } catch {
14179
14590
  }
14180
14591
  });
@@ -14202,20 +14613,20 @@ function attemptRebind(reason) {
14202
14613
  }
14203
14614
  function bindActivitySocket() {
14204
14615
  try {
14205
- import_fs23.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
14616
+ import_fs25.default.unlinkSync(ACTIVITY_SOCKET_PATH2);
14206
14617
  } catch {
14207
14618
  }
14208
14619
  const ACTIVITY_MAX_BYTES = 1024 * 1024;
14209
14620
  const unixServer = import_net2.default.createServer((socket) => {
14210
14621
  const chunks = [];
14211
14622
  let bytesReceived = 0;
14212
- socket.on("data", (chunk) => {
14213
- bytesReceived += chunk.length;
14623
+ socket.on("data", (chunk2) => {
14624
+ bytesReceived += chunk2.length;
14214
14625
  if (bytesReceived > ACTIVITY_MAX_BYTES) {
14215
14626
  socket.destroy();
14216
14627
  return;
14217
14628
  }
14218
- chunks.push(chunk);
14629
+ chunks.push(chunk2);
14219
14630
  });
14220
14631
  socket.on("end", () => {
14221
14632
  try {
@@ -14306,28 +14717,28 @@ function bindActivitySocket() {
14306
14717
  });
14307
14718
  activitySocketServer = unixServer;
14308
14719
  }
14309
- var import_net2, import_fs23, import_path25, import_os21, 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, 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;
14720
+ 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, 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;
14310
14721
  var init_state2 = __esm({
14311
14722
  "src/daemon/state.ts"() {
14312
14723
  "use strict";
14313
14724
  import_net2 = __toESM(require("net"));
14314
- import_fs23 = __toESM(require("fs"));
14315
- import_path25 = __toESM(require("path"));
14316
- import_os21 = __toESM(require("os"));
14725
+ import_fs25 = __toESM(require("fs"));
14726
+ import_path27 = __toESM(require("path"));
14727
+ import_os23 = __toESM(require("os"));
14317
14728
  import_crypto8 = require("crypto");
14318
14729
  init_daemon();
14319
14730
  init_suggestion_tracker();
14320
14731
  init_taint_store();
14321
14732
  init_session_counters();
14322
14733
  init_session_history();
14323
- homeDir = import_os21.default.homedir();
14324
- DAEMON_PID_FILE = import_path25.default.join(homeDir, ".node9", "daemon.pid");
14325
- DECISIONS_FILE = import_path25.default.join(homeDir, ".node9", "decisions.json");
14326
- AUDIT_LOG_FILE = import_path25.default.join(homeDir, ".node9", "audit.log");
14327
- TRUST_FILE2 = import_path25.default.join(homeDir, ".node9", "trust.json");
14328
- GLOBAL_CONFIG_FILE = import_path25.default.join(homeDir, ".node9", "config.json");
14329
- CREDENTIALS_FILE = import_path25.default.join(homeDir, ".node9", "credentials.json");
14330
- INSIGHT_COUNTS_FILE = import_path25.default.join(homeDir, ".node9", "insight-counts.json");
14734
+ homeDir = import_os23.default.homedir();
14735
+ DAEMON_PID_FILE = import_path27.default.join(homeDir, ".node9", "daemon.pid");
14736
+ DECISIONS_FILE = import_path27.default.join(homeDir, ".node9", "decisions.json");
14737
+ AUDIT_LOG_FILE = import_path27.default.join(homeDir, ".node9", "audit.log");
14738
+ TRUST_FILE2 = import_path27.default.join(homeDir, ".node9", "trust.json");
14739
+ GLOBAL_CONFIG_FILE = import_path27.default.join(homeDir, ".node9", "config.json");
14740
+ CREDENTIALS_FILE = import_path27.default.join(homeDir, ".node9", "credentials.json");
14741
+ INSIGHT_COUNTS_FILE = import_path27.default.join(homeDir, ".node9", "insight-counts.json");
14331
14742
  pending = /* @__PURE__ */ new Map();
14332
14743
  sseClients = /* @__PURE__ */ new Set();
14333
14744
  suggestionTracker = new SuggestionTracker(3);
@@ -14344,7 +14755,7 @@ var init_state2 = __esm({
14344
14755
  "2h": 2 * 60 * 6e4
14345
14756
  };
14346
14757
  autoStarted = process.env.NODE9_AUTO_STARTED === "1";
14347
- ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path25.default.join(import_os21.default.tmpdir(), "node9-activity.sock");
14758
+ ACTIVITY_SOCKET_PATH2 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path27.default.join(import_os23.default.tmpdir(), "node9-activity.sock");
14348
14759
  ACTIVITY_RING_SIZE = 100;
14349
14760
  activityRing = [];
14350
14761
  LARGE_RESPONSE_RING_SIZE = 20;
@@ -14422,8 +14833,8 @@ function readCredentials() {
14422
14833
  };
14423
14834
  }
14424
14835
  try {
14425
- const credPath = import_path26.default.join(import_os22.default.homedir(), ".node9", "credentials.json");
14426
- const creds = JSON.parse(import_fs24.default.readFileSync(credPath, "utf-8"));
14836
+ const credPath = import_path28.default.join(import_os24.default.homedir(), ".node9", "credentials.json");
14837
+ const creds = JSON.parse(import_fs26.default.readFileSync(credPath, "utf-8"));
14427
14838
  const profileName = process.env.NODE9_PROFILE ?? "default";
14428
14839
  const profile = creds[profileName];
14429
14840
  if (typeof profile?.apiKey === "string" && profile.apiKey.length > 0) {
@@ -14449,7 +14860,7 @@ function readCredentials() {
14449
14860
  }
14450
14861
  function readCachedEtag() {
14451
14862
  try {
14452
- const raw = JSON.parse(import_fs24.default.readFileSync(rulesCacheFile(), "utf-8"));
14863
+ const raw = JSON.parse(import_fs26.default.readFileSync(rulesCacheFile(), "utf-8"));
14453
14864
  return typeof raw.etag === "string" ? raw.etag : void 0;
14454
14865
  } catch {
14455
14866
  return void 0;
@@ -14479,7 +14890,7 @@ function fetchCloudPolicy(apiKey, apiUrl, ifNoneMatch) {
14479
14890
  return;
14480
14891
  }
14481
14892
  const chunks = [];
14482
- res.on("data", (chunk) => chunks.push(chunk));
14893
+ res.on("data", (chunk2) => chunks.push(chunk2));
14483
14894
  res.on("end", () => {
14484
14895
  if (res.statusCode !== 200) {
14485
14896
  reject(new Error(`API returned ${res.statusCode ?? "unknown"}`));
@@ -14510,9 +14921,9 @@ function extractRules(body) {
14510
14921
  return [];
14511
14922
  }
14512
14923
  function writeCache2(cache) {
14513
- const dir = import_path26.default.dirname(rulesCacheFile());
14514
- if (!import_fs24.default.existsSync(dir)) import_fs24.default.mkdirSync(dir, { recursive: true });
14515
- import_fs24.default.writeFileSync(rulesCacheFile(), JSON.stringify(cache, null, 2) + "\n", "utf-8");
14924
+ const dir = import_path28.default.dirname(rulesCacheFile());
14925
+ if (!import_fs26.default.existsSync(dir)) import_fs26.default.mkdirSync(dir, { recursive: true });
14926
+ import_fs26.default.writeFileSync(rulesCacheFile(), JSON.stringify(cache, null, 2) + "\n", "utf-8");
14516
14927
  }
14517
14928
  async function syncOnce() {
14518
14929
  const creds = readCredentials();
@@ -14669,7 +15080,7 @@ async function runCloudSync() {
14669
15080
  }
14670
15081
  function getCloudSyncStatus() {
14671
15082
  try {
14672
- const raw = JSON.parse(import_fs24.default.readFileSync(rulesCacheFile(), "utf-8"));
15083
+ const raw = JSON.parse(import_fs26.default.readFileSync(rulesCacheFile(), "utf-8"));
14673
15084
  if (!Array.isArray(raw.rules) || typeof raw.fetchedAt !== "string") return { cached: false };
14674
15085
  return {
14675
15086
  cached: true,
@@ -14686,7 +15097,7 @@ function getCloudSyncStatus() {
14686
15097
  }
14687
15098
  function getCloudRules() {
14688
15099
  try {
14689
- const raw = JSON.parse(import_fs24.default.readFileSync(rulesCacheFile(), "utf-8"));
15100
+ const raw = JSON.parse(import_fs26.default.readFileSync(rulesCacheFile(), "utf-8"));
14690
15101
  return Array.isArray(raw.rules) ? raw.rules : null;
14691
15102
  } catch {
14692
15103
  return null;
@@ -14720,14 +15131,14 @@ function startForensicBroadcast() {
14720
15131
  const recurring = setInterval(() => void tick(), FORENSIC_BROADCAST_INTERVAL_MS);
14721
15132
  recurring.unref();
14722
15133
  }
14723
- var import_fs24, import_https2, import_os22, import_path26, FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_HOURS, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
15134
+ var import_fs26, import_https2, import_os24, import_path28, FINDING_TO_SIGNAL3, rulesCacheFile, DEFAULT_API_URL, DEFAULT_INTERVAL_HOURS, MIN_INTERVAL_HOURS, FORENSIC_BROADCAST_INTERVAL_MS, FORENSIC_INITIAL_DELAY_MS, forensicBroadcastOffsets;
14724
15135
  var init_sync = __esm({
14725
15136
  "src/daemon/sync.ts"() {
14726
15137
  "use strict";
14727
- import_fs24 = __toESM(require("fs"));
15138
+ import_fs26 = __toESM(require("fs"));
14728
15139
  import_https2 = __toESM(require("https"));
14729
- import_os22 = __toESM(require("os"));
14730
- import_path26 = __toESM(require("path"));
15140
+ import_os24 = __toESM(require("os"));
15141
+ import_path28 = __toESM(require("path"));
14731
15142
  init_config();
14732
15143
  init_blast();
14733
15144
  init_dist();
@@ -14746,7 +15157,7 @@ var init_sync = __esm({
14746
15157
  loop: "loops",
14747
15158
  "long-output-redacted": "longOutputRedactions"
14748
15159
  };
14749
- rulesCacheFile = () => import_path26.default.join(import_os22.default.homedir(), ".node9", "rules-cache.json");
15160
+ rulesCacheFile = () => import_path28.default.join(import_os24.default.homedir(), ".node9", "rules-cache.json");
14750
15161
  DEFAULT_API_URL = "https://api.node9.ai/api/v1/intercept/policies/sync";
14751
15162
  DEFAULT_INTERVAL_HOURS = 5;
14752
15163
  MIN_INTERVAL_HOURS = 1;
@@ -14770,21 +15181,21 @@ __export(audit_shipper_exports, {
14770
15181
  writeWatermark: () => writeWatermark
14771
15182
  });
14772
15183
  function fileSignature(filePath) {
14773
- const fd = import_fs25.default.openSync(filePath, "r");
15184
+ const fd = import_fs27.default.openSync(filePath, "r");
14774
15185
  try {
14775
15186
  const buf = Buffer.alloc(512);
14776
- const read = import_fs25.default.readSync(fd, buf, 0, 512, 0);
15187
+ const read = import_fs27.default.readSync(fd, buf, 0, 512, 0);
14777
15188
  const slice = buf.subarray(0, read);
14778
15189
  const nl = slice.indexOf(10);
14779
15190
  const firstLine = nl === -1 ? slice : slice.subarray(0, nl);
14780
15191
  return import_crypto9.default.createHash("sha256").update(firstLine).digest("hex").slice(0, 16);
14781
15192
  } finally {
14782
- import_fs25.default.closeSync(fd);
15193
+ import_fs27.default.closeSync(fd);
14783
15194
  }
14784
15195
  }
14785
15196
  function readWatermark(watermarkPath) {
14786
15197
  try {
14787
- const raw = JSON.parse(import_fs25.default.readFileSync(watermarkPath, "utf-8"));
15198
+ const raw = JSON.parse(import_fs27.default.readFileSync(watermarkPath, "utf-8"));
14788
15199
  if (typeof raw.fileSig === "string" && typeof raw.offset === "number" && raw.offset >= 0)
14789
15200
  return raw;
14790
15201
  } catch {
@@ -14793,13 +15204,13 @@ function readWatermark(watermarkPath) {
14793
15204
  }
14794
15205
  function writeWatermark(watermarkPath, wm) {
14795
15206
  const tmp = `${watermarkPath}.tmp`;
14796
- import_fs25.default.writeFileSync(tmp, JSON.stringify(wm));
14797
- import_fs25.default.renameSync(tmp, watermarkPath);
15207
+ import_fs27.default.writeFileSync(tmp, JSON.stringify(wm));
15208
+ import_fs27.default.renameSync(tmp, watermarkPath);
14798
15209
  }
14799
- function buildWireRows(chunk) {
14800
- const lastNl = chunk.lastIndexOf(10);
15210
+ function buildWireRows(chunk2) {
15211
+ const lastNl = chunk2.lastIndexOf(10);
14801
15212
  if (lastNl === -1) return { rows: [], consumed: 0 };
14802
- const complete = chunk.subarray(0, lastNl + 1);
15213
+ const complete = chunk2.subarray(0, lastNl + 1);
14803
15214
  const rows = [];
14804
15215
  for (const line of complete.toString("utf-8").split("\n")) {
14805
15216
  if (!line.trim()) continue;
@@ -14833,7 +15244,10 @@ function buildWireRows(chunk) {
14833
15244
  ...typeof parsed.sessionId === "string" ? { sessionId: parsed.sessionId } : {},
14834
15245
  ...typeof parsed.dlpPattern === "string" ? { dlpPattern: parsed.dlpPattern } : {},
14835
15246
  ...typeof parsed.dlpSample === "string" ? { dlpSample: parsed.dlpSample } : {},
14836
- ...cloudRequestId ? { cloudRequestId } : {}
15247
+ ...cloudRequestId ? { cloudRequestId } : {},
15248
+ ...typeof parsed.workingDir === "string" ? { workingDir: parsed.workingDir } : {},
15249
+ ...typeof parsed.platform === "string" ? { platform: parsed.platform } : {},
15250
+ ...typeof parsed.shellType === "string" ? { shellType: parsed.shellType } : {}
14837
15251
  });
14838
15252
  }
14839
15253
  return { rows, consumed: lastNl + 1 };
@@ -14862,11 +15276,11 @@ async function shipOnce(deps = {}) {
14862
15276
  if (!creds?.apiKey) return { status: "no-creds", shipped: 0 };
14863
15277
  const endpoint = buildBatchEndpoint(creds.apiUrl);
14864
15278
  if (!endpoint) return { status: "no-creds", shipped: 0 };
14865
- if (!import_fs25.default.existsSync(auditLogPath)) return { status: "idle", shipped: 0 };
15279
+ if (!import_fs27.default.existsSync(auditLogPath)) return { status: "idle", shipped: 0 };
14866
15280
  let shipped = 0;
14867
15281
  try {
14868
15282
  for (let chunkN = 0; chunkN < MAX_CHUNKS_PER_TICK; chunkN++) {
14869
- const size = import_fs25.default.statSync(auditLogPath).size;
15283
+ const size = import_fs27.default.statSync(auditLogPath).size;
14870
15284
  if (size === 0) break;
14871
15285
  const sig = fileSignature(auditLogPath);
14872
15286
  const wm = readWatermark(watermarkPath);
@@ -14874,12 +15288,12 @@ async function shipOnce(deps = {}) {
14874
15288
  if (offset >= size) break;
14875
15289
  const toRead = Math.min(size - offset, MAX_CHUNK_BYTES);
14876
15290
  const buf = Buffer.alloc(toRead);
14877
- const fd = import_fs25.default.openSync(auditLogPath, "r");
15291
+ const fd = import_fs27.default.openSync(auditLogPath, "r");
14878
15292
  let read;
14879
15293
  try {
14880
- read = import_fs25.default.readSync(fd, buf, 0, toRead, offset);
15294
+ read = import_fs27.default.readSync(fd, buf, 0, toRead, offset);
14881
15295
  } finally {
14882
- import_fs25.default.closeSync(fd);
15296
+ import_fs27.default.closeSync(fd);
14883
15297
  }
14884
15298
  const { rows, consumed } = buildWireRows(buf.subarray(0, read));
14885
15299
  if (consumed === 0) break;
@@ -14926,8 +15340,8 @@ async function shipOnce(deps = {}) {
14926
15340
  }
14927
15341
  function shipLagBytes(auditLogPath = LOCAL_AUDIT_LOG, watermarkPath = AUDIT_SHIP_WATERMARK) {
14928
15342
  try {
14929
- if (!import_fs25.default.existsSync(auditLogPath)) return 0;
14930
- const size = import_fs25.default.statSync(auditLogPath).size;
15343
+ if (!import_fs27.default.existsSync(auditLogPath)) return 0;
15344
+ const size = import_fs27.default.statSync(auditLogPath).size;
14931
15345
  const wm = readWatermark(watermarkPath);
14932
15346
  if (!wm) return size;
14933
15347
  if (wm.fileSig !== fileSignature(auditLogPath)) return size;
@@ -14950,19 +15364,19 @@ function startAuditShipper() {
14950
15364
  setTimeout(() => void shipOnce(), 3e3);
14951
15365
  setInterval(() => void shipOnce(), intervalMs);
14952
15366
  }
14953
- var import_fs25, import_path27, import_os23, import_crypto9, AUDIT_SHIP_WATERMARK, DEFAULT_INTERVAL_MS, MAX_BATCH, MAX_CHUNK_BYTES, MAX_CHUNKS_PER_TICK, FETCH_TIMEOUT_MS, SKIP_CHECKED_BY, shipperStarted;
15367
+ var import_fs27, import_path29, import_os25, import_crypto9, AUDIT_SHIP_WATERMARK, DEFAULT_INTERVAL_MS, MAX_BATCH, MAX_CHUNK_BYTES, MAX_CHUNKS_PER_TICK, FETCH_TIMEOUT_MS, SKIP_CHECKED_BY, shipperStarted;
14954
15368
  var init_audit_shipper = __esm({
14955
15369
  "src/daemon/audit-shipper.ts"() {
14956
15370
  "use strict";
14957
- import_fs25 = __toESM(require("fs"));
14958
- import_path27 = __toESM(require("path"));
14959
- import_os23 = __toESM(require("os"));
15371
+ import_fs27 = __toESM(require("fs"));
15372
+ import_path29 = __toESM(require("path"));
15373
+ import_os25 = __toESM(require("os"));
14960
15374
  import_crypto9 = __toESM(require("crypto"));
14961
15375
  init_audit();
14962
15376
  init_config();
14963
15377
  init_sync();
14964
15378
  init_cloud();
14965
- AUDIT_SHIP_WATERMARK = import_path27.default.join(import_os23.default.homedir(), ".node9", "audit-ship.json");
15379
+ AUDIT_SHIP_WATERMARK = import_path29.default.join(import_os25.default.homedir(), ".node9", "audit-ship.json");
14966
15380
  DEFAULT_INTERVAL_MS = 2e4;
14967
15381
  MAX_BATCH = 500;
14968
15382
  MAX_CHUNK_BYTES = 4 * 1024 * 1024;
@@ -14976,70 +15390,70 @@ var init_audit_shipper = __esm({
14976
15390
  // src/daemon/dlp-scanner.ts
14977
15391
  function loadIndex() {
14978
15392
  try {
14979
- return JSON.parse(import_fs26.default.readFileSync(INDEX_FILE, "utf-8"));
15393
+ return JSON.parse(import_fs28.default.readFileSync(INDEX_FILE, "utf-8"));
14980
15394
  } catch {
14981
15395
  return {};
14982
15396
  }
14983
15397
  }
14984
15398
  function saveIndex(index) {
14985
15399
  try {
14986
- import_fs26.default.writeFileSync(INDEX_FILE, JSON.stringify(index), { encoding: "utf-8", mode: 384 });
15400
+ import_fs28.default.writeFileSync(INDEX_FILE, JSON.stringify(index), { encoding: "utf-8", mode: 384 });
14987
15401
  } catch {
14988
15402
  }
14989
15403
  }
14990
15404
  function appendAuditEntry(entry) {
14991
15405
  try {
14992
- import_fs26.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
15406
+ import_fs28.default.appendFileSync(AUDIT_LOG_FILE, JSON.stringify(entry) + "\n");
14993
15407
  } catch {
14994
15408
  }
14995
15409
  }
14996
15410
  function runDlpScan() {
14997
- if (!import_fs26.default.existsSync(PROJECTS_DIR2)) return;
15411
+ if (!import_fs28.default.existsSync(PROJECTS_DIR2)) return;
14998
15412
  const index = loadIndex();
14999
15413
  let updated = false;
15000
15414
  let projDirs;
15001
15415
  try {
15002
- projDirs = import_fs26.default.readdirSync(PROJECTS_DIR2);
15416
+ projDirs = import_fs28.default.readdirSync(PROJECTS_DIR2);
15003
15417
  } catch {
15004
15418
  return;
15005
15419
  }
15006
15420
  for (const proj of projDirs) {
15007
- const projPath = import_path28.default.join(PROJECTS_DIR2, proj);
15421
+ const projPath = import_path30.default.join(PROJECTS_DIR2, proj);
15008
15422
  try {
15009
- if (!import_fs26.default.lstatSync(projPath).isDirectory()) continue;
15010
- const real = import_fs26.default.realpathSync(projPath);
15011
- if (!real.startsWith(PROJECTS_DIR2 + import_path28.default.sep) && real !== PROJECTS_DIR2) continue;
15423
+ if (!import_fs28.default.lstatSync(projPath).isDirectory()) continue;
15424
+ const real = import_fs28.default.realpathSync(projPath);
15425
+ if (!real.startsWith(PROJECTS_DIR2 + import_path30.default.sep) && real !== PROJECTS_DIR2) continue;
15012
15426
  } catch {
15013
15427
  continue;
15014
15428
  }
15015
15429
  let files;
15016
15430
  try {
15017
- files = import_fs26.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
15431
+ files = import_fs28.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
15018
15432
  } catch {
15019
15433
  continue;
15020
15434
  }
15021
15435
  for (const file of files) {
15022
- const filePath = import_path28.default.join(projPath, file);
15436
+ const filePath = import_path30.default.join(projPath, file);
15023
15437
  const lastOffset = index[filePath] ?? 0;
15024
15438
  let size;
15025
15439
  try {
15026
- size = import_fs26.default.statSync(filePath).size;
15440
+ size = import_fs28.default.statSync(filePath).size;
15027
15441
  } catch {
15028
15442
  continue;
15029
15443
  }
15030
15444
  if (size <= lastOffset) continue;
15031
15445
  let fd;
15032
15446
  try {
15033
- fd = import_fs26.default.openSync(filePath, "r");
15447
+ fd = import_fs28.default.openSync(filePath, "r");
15034
15448
  } catch {
15035
15449
  continue;
15036
15450
  }
15037
15451
  try {
15038
15452
  const chunkSize = size - lastOffset;
15039
15453
  const buf = Buffer.alloc(chunkSize);
15040
- import_fs26.default.readSync(fd, buf, 0, chunkSize, lastOffset);
15041
- const chunk = buf.toString("utf-8");
15042
- for (const line of chunk.split("\n")) {
15454
+ import_fs28.default.readSync(fd, buf, 0, chunkSize, lastOffset);
15455
+ const chunk2 = buf.toString("utf-8");
15456
+ for (const line of chunk2.split("\n")) {
15043
15457
  if (!line.trim()) continue;
15044
15458
  let entry;
15045
15459
  try {
@@ -15057,7 +15471,7 @@ function runDlpScan() {
15057
15471
  if (typeof text !== "string") continue;
15058
15472
  const match = scanText(text);
15059
15473
  if (!match) continue;
15060
- const projLabel = decodeURIComponent(proj).replace(import_os24.default.homedir(), "~").slice(0, 40);
15474
+ const projLabel = decodeURIComponent(proj).replace(import_os26.default.homedir(), "~").slice(0, 40);
15061
15475
  const ts = entry.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
15062
15476
  appendAuditEntry({
15063
15477
  ts,
@@ -15082,7 +15496,7 @@ Run: node9 report --period 30d`
15082
15496
  updated = true;
15083
15497
  } finally {
15084
15498
  try {
15085
- import_fs26.default.closeSync(fd);
15499
+ import_fs28.default.closeSync(fd);
15086
15500
  } catch {
15087
15501
  }
15088
15502
  }
@@ -15108,30 +15522,30 @@ function startDlpScanner() {
15108
15522
  );
15109
15523
  timer.unref();
15110
15524
  }
15111
- var import_fs26, import_path28, import_os24, INDEX_FILE, PROJECTS_DIR2;
15525
+ var import_fs28, import_path30, import_os26, INDEX_FILE, PROJECTS_DIR2;
15112
15526
  var init_dlp_scanner = __esm({
15113
15527
  "src/daemon/dlp-scanner.ts"() {
15114
15528
  "use strict";
15115
- import_fs26 = __toESM(require("fs"));
15116
- import_path28 = __toESM(require("path"));
15117
- import_os24 = __toESM(require("os"));
15529
+ import_fs28 = __toESM(require("fs"));
15530
+ import_path30 = __toESM(require("path"));
15531
+ import_os26 = __toESM(require("os"));
15118
15532
  init_dlp();
15119
15533
  init_native();
15120
15534
  init_state2();
15121
- INDEX_FILE = import_path28.default.join(import_os24.default.homedir(), ".node9", "dlp-index.json");
15122
- PROJECTS_DIR2 = import_path28.default.join(import_os24.default.homedir(), ".claude", "projects");
15535
+ INDEX_FILE = import_path30.default.join(import_os26.default.homedir(), ".node9", "dlp-index.json");
15536
+ PROJECTS_DIR2 = import_path30.default.join(import_os26.default.homedir(), ".claude", "projects");
15123
15537
  }
15124
15538
  });
15125
15539
 
15126
15540
  // src/daemon/mcp-tools.ts
15127
15541
  function getMcpToolsFile() {
15128
- return import_path29.default.join(import_os25.default.homedir(), ".node9", "mcp-tools.json");
15542
+ return import_path31.default.join(import_os27.default.homedir(), ".node9", "mcp-tools.json");
15129
15543
  }
15130
15544
  function readMcpToolsConfig() {
15131
15545
  try {
15132
15546
  const file = getMcpToolsFile();
15133
- if (!import_fs27.default.existsSync(file)) return {};
15134
- const raw = import_fs27.default.readFileSync(file, "utf-8");
15547
+ if (!import_fs29.default.existsSync(file)) return {};
15548
+ const raw = import_fs29.default.readFileSync(file, "utf-8");
15135
15549
  return JSON.parse(raw);
15136
15550
  } catch {
15137
15551
  return {};
@@ -15140,11 +15554,11 @@ function readMcpToolsConfig() {
15140
15554
  function writeMcpToolsConfig(config) {
15141
15555
  try {
15142
15556
  const file = getMcpToolsFile();
15143
- const dir = import_path29.default.dirname(file);
15144
- if (!import_fs27.default.existsSync(dir)) import_fs27.default.mkdirSync(dir, { recursive: true });
15145
- const tmpPath = `${file}.${import_os25.default.hostname()}.${process.pid}.tmp`;
15146
- import_fs27.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2));
15147
- import_fs27.default.renameSync(tmpPath, file);
15557
+ const dir = import_path31.default.dirname(file);
15558
+ if (!import_fs29.default.existsSync(dir)) import_fs29.default.mkdirSync(dir, { recursive: true });
15559
+ const tmpPath = `${file}.${import_os27.default.hostname()}.${process.pid}.tmp`;
15560
+ import_fs29.default.writeFileSync(tmpPath, JSON.stringify(config, null, 2));
15561
+ import_fs29.default.renameSync(tmpPath, file);
15148
15562
  } catch (e) {
15149
15563
  console.error("Failed to write mcp-tools.json", e);
15150
15564
  }
@@ -15183,13 +15597,13 @@ function approveServer(serverKey, disabledTools) {
15183
15597
  writeMcpToolsConfig(config);
15184
15598
  }
15185
15599
  }
15186
- var import_fs27, import_path29, import_os25;
15600
+ var import_fs29, import_path31, import_os27;
15187
15601
  var init_mcp_tools = __esm({
15188
15602
  "src/daemon/mcp-tools.ts"() {
15189
15603
  "use strict";
15190
- import_fs27 = __toESM(require("fs"));
15191
- import_path29 = __toESM(require("path"));
15192
- import_os25 = __toESM(require("os"));
15604
+ import_fs29 = __toESM(require("fs"));
15605
+ import_path31 = __toESM(require("path"));
15606
+ import_os27 = __toESM(require("os"));
15193
15607
  }
15194
15608
  });
15195
15609
 
@@ -15212,7 +15626,7 @@ function startDaemon() {
15212
15626
  idleTimer = setTimeout(() => {
15213
15627
  if (autoStarted) {
15214
15628
  try {
15215
- import_fs28.default.unlinkSync(DAEMON_PID_FILE);
15629
+ import_fs30.default.unlinkSync(DAEMON_PID_FILE);
15216
15630
  } catch {
15217
15631
  }
15218
15632
  }
@@ -15357,7 +15771,7 @@ data: ${JSON.stringify(item.data)}
15357
15771
  mcpServer: entry.mcpServer
15358
15772
  });
15359
15773
  }
15360
- const projectCwd = typeof cwd === "string" && import_path30.default.isAbsolute(cwd) ? cwd : void 0;
15774
+ const projectCwd = typeof cwd === "string" && import_path32.default.isAbsolute(cwd) ? cwd : void 0;
15361
15775
  const projectConfig = getConfig(projectCwd);
15362
15776
  const browserEnabled = projectConfig.settings.approvers?.browser !== false;
15363
15777
  const terminalEnabled = projectConfig.settings.approvers?.terminal !== false;
@@ -15649,8 +16063,8 @@ data: ${JSON.stringify(item.data)}
15649
16063
  if (!validToken(req)) return res.writeHead(403).end();
15650
16064
  const periodParam = reqUrl.searchParams.get("period") || "7d";
15651
16065
  const period = ["today", "7d", "30d", "month"].includes(periodParam) ? periodParam : "7d";
15652
- const logPath = import_path30.default.join(import_os26.default.homedir(), ".node9", "audit.log");
15653
- if (!import_fs28.default.existsSync(logPath)) {
16066
+ const logPath = import_path32.default.join(import_os28.default.homedir(), ".node9", "audit.log");
16067
+ if (!import_fs30.default.existsSync(logPath)) {
15654
16068
  res.writeHead(200, { "Content-Type": "application/json" });
15655
16069
  return res.end(
15656
16070
  JSON.stringify({
@@ -15663,7 +16077,7 @@ data: ${JSON.stringify(item.data)}
15663
16077
  );
15664
16078
  }
15665
16079
  try {
15666
- const raw = import_fs28.default.readFileSync(logPath, "utf-8");
16080
+ const raw = import_fs30.default.readFileSync(logPath, "utf-8");
15667
16081
  const allEntries = raw.split("\n").flatMap((line) => {
15668
16082
  if (!line.trim()) return [];
15669
16083
  try {
@@ -15986,14 +16400,14 @@ data: ${JSON.stringify(item.data)}
15986
16400
  server.on("error", (e) => {
15987
16401
  if (e.code === "EADDRINUSE") {
15988
16402
  try {
15989
- if (import_fs28.default.existsSync(DAEMON_PID_FILE)) {
15990
- const { pid } = JSON.parse(import_fs28.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
16403
+ if (import_fs30.default.existsSync(DAEMON_PID_FILE)) {
16404
+ const { pid } = JSON.parse(import_fs30.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
15991
16405
  process.kill(pid, 0);
15992
16406
  return process.exit(0);
15993
16407
  }
15994
16408
  } catch {
15995
16409
  try {
15996
- import_fs28.default.unlinkSync(DAEMON_PID_FILE);
16410
+ import_fs30.default.unlinkSync(DAEMON_PID_FILE);
15997
16411
  } catch {
15998
16412
  }
15999
16413
  server.listen(DAEMON_PORT, DAEMON_HOST);
@@ -16065,14 +16479,14 @@ data: ${JSON.stringify(item.data)}
16065
16479
  }
16066
16480
  startActivitySocket();
16067
16481
  }
16068
- var import_http, import_fs28, import_path30, import_os26, import_crypto10, import_child_process2, import_chalk6;
16482
+ var import_http, import_fs30, import_path32, import_os28, import_crypto10, import_child_process2, import_chalk6;
16069
16483
  var init_server = __esm({
16070
16484
  "src/daemon/server.ts"() {
16071
16485
  "use strict";
16072
16486
  import_http = __toESM(require("http"));
16073
- import_fs28 = __toESM(require("fs"));
16074
- import_path30 = __toESM(require("path"));
16075
- import_os26 = __toESM(require("os"));
16487
+ import_fs30 = __toESM(require("fs"));
16488
+ import_path32 = __toESM(require("path"));
16489
+ import_os28 = __toESM(require("os"));
16076
16490
  import_crypto10 = require("crypto");
16077
16491
  import_child_process2 = require("child_process");
16078
16492
  import_chalk6 = __toESM(require("chalk"));
@@ -16093,8 +16507,8 @@ var init_server = __esm({
16093
16507
  function resolveNode9Binary() {
16094
16508
  try {
16095
16509
  const script = process.argv[1];
16096
- if (typeof script === "string" && import_path31.default.isAbsolute(script) && import_fs29.default.existsSync(script)) {
16097
- return import_fs29.default.realpathSync(script);
16510
+ if (typeof script === "string" && import_path33.default.isAbsolute(script) && import_fs31.default.existsSync(script)) {
16511
+ return import_fs31.default.realpathSync(script);
16098
16512
  }
16099
16513
  } catch {
16100
16514
  }
@@ -16112,11 +16526,11 @@ function xmlEscape(s) {
16112
16526
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
16113
16527
  }
16114
16528
  function launchdPlist(binaryPath) {
16115
- const logDir = import_path31.default.join(import_os27.default.homedir(), ".node9");
16529
+ const logDir = import_path33.default.join(import_os29.default.homedir(), ".node9");
16116
16530
  const nodePath = xmlEscape(process.execPath);
16117
16531
  const scriptPath = xmlEscape(binaryPath);
16118
- const outLog = xmlEscape(import_path31.default.join(logDir, "daemon.log"));
16119
- const errLog = xmlEscape(import_path31.default.join(logDir, "daemon-error.log"));
16532
+ const outLog = xmlEscape(import_path33.default.join(logDir, "daemon.log"));
16533
+ const errLog = xmlEscape(import_path33.default.join(logDir, "daemon-error.log"));
16120
16534
  return `<?xml version="1.0" encoding="UTF-8"?>
16121
16535
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
16122
16536
  <plist version="1.0">
@@ -16149,9 +16563,9 @@ function launchdPlist(binaryPath) {
16149
16563
  `;
16150
16564
  }
16151
16565
  function installLaunchd(binaryPath) {
16152
- const dir = import_path31.default.dirname(LAUNCHD_PLIST);
16153
- if (!import_fs29.default.existsSync(dir)) import_fs29.default.mkdirSync(dir, { recursive: true });
16154
- import_fs29.default.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
16566
+ const dir = import_path33.default.dirname(LAUNCHD_PLIST);
16567
+ if (!import_fs31.default.existsSync(dir)) import_fs31.default.mkdirSync(dir, { recursive: true });
16568
+ import_fs31.default.writeFileSync(LAUNCHD_PLIST, launchdPlist(binaryPath), "utf-8");
16155
16569
  (0, import_child_process3.spawnSync)("launchctl", ["unload", LAUNCHD_PLIST], { encoding: "utf8" });
16156
16570
  const r = (0, import_child_process3.spawnSync)("launchctl", ["load", "-w", LAUNCHD_PLIST], {
16157
16571
  encoding: "utf8",
@@ -16162,13 +16576,13 @@ function installLaunchd(binaryPath) {
16162
16576
  }
16163
16577
  }
16164
16578
  function uninstallLaunchd() {
16165
- if (import_fs29.default.existsSync(LAUNCHD_PLIST)) {
16579
+ if (import_fs31.default.existsSync(LAUNCHD_PLIST)) {
16166
16580
  (0, import_child_process3.spawnSync)("launchctl", ["unload", "-w", LAUNCHD_PLIST], { encoding: "utf8", timeout: 5e3 });
16167
- import_fs29.default.unlinkSync(LAUNCHD_PLIST);
16581
+ import_fs31.default.unlinkSync(LAUNCHD_PLIST);
16168
16582
  }
16169
16583
  }
16170
16584
  function isLaunchdInstalled() {
16171
- return import_fs29.default.existsSync(LAUNCHD_PLIST);
16585
+ return import_fs31.default.existsSync(LAUNCHD_PLIST);
16172
16586
  }
16173
16587
  function systemdUnit(binaryPath) {
16174
16588
  return `[Unit]
@@ -16187,12 +16601,12 @@ WantedBy=default.target
16187
16601
  `;
16188
16602
  }
16189
16603
  function installSystemd(binaryPath) {
16190
- if (!import_fs29.default.existsSync(SYSTEMD_UNIT_DIR)) {
16191
- import_fs29.default.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
16604
+ if (!import_fs31.default.existsSync(SYSTEMD_UNIT_DIR)) {
16605
+ import_fs31.default.mkdirSync(SYSTEMD_UNIT_DIR, { recursive: true });
16192
16606
  }
16193
- import_fs29.default.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
16607
+ import_fs31.default.writeFileSync(SYSTEMD_UNIT, systemdUnit(binaryPath), "utf-8");
16194
16608
  try {
16195
- (0, import_child_process3.execFileSync)("loginctl", ["enable-linger", import_os27.default.userInfo().username], { timeout: 3e3 });
16609
+ (0, import_child_process3.execFileSync)("loginctl", ["enable-linger", import_os29.default.userInfo().username], { timeout: 3e3 });
16196
16610
  } catch {
16197
16611
  }
16198
16612
  const reload = (0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], {
@@ -16212,23 +16626,23 @@ function installSystemd(binaryPath) {
16212
16626
  }
16213
16627
  }
16214
16628
  function uninstallSystemd() {
16215
- if (import_fs29.default.existsSync(SYSTEMD_UNIT)) {
16629
+ if (import_fs31.default.existsSync(SYSTEMD_UNIT)) {
16216
16630
  (0, import_child_process3.spawnSync)("systemctl", ["--user", "disable", "--now", "node9-daemon"], {
16217
16631
  encoding: "utf8",
16218
16632
  timeout: 5e3
16219
16633
  });
16220
16634
  (0, import_child_process3.spawnSync)("systemctl", ["--user", "daemon-reload"], { encoding: "utf8", timeout: 5e3 });
16221
- import_fs29.default.unlinkSync(SYSTEMD_UNIT);
16635
+ import_fs31.default.unlinkSync(SYSTEMD_UNIT);
16222
16636
  }
16223
16637
  }
16224
16638
  function isSystemdInstalled() {
16225
- return import_fs29.default.existsSync(SYSTEMD_UNIT);
16639
+ return import_fs31.default.existsSync(SYSTEMD_UNIT);
16226
16640
  }
16227
16641
  function stopRunningDaemon() {
16228
- const pidFile = import_path31.default.join(import_os27.default.homedir(), ".node9", "daemon.pid");
16229
- if (!import_fs29.default.existsSync(pidFile)) return;
16642
+ const pidFile = import_path33.default.join(import_os29.default.homedir(), ".node9", "daemon.pid");
16643
+ if (!import_fs31.default.existsSync(pidFile)) return;
16230
16644
  try {
16231
- const data = JSON.parse(import_fs29.default.readFileSync(pidFile, "utf-8"));
16645
+ const data = JSON.parse(import_fs31.default.readFileSync(pidFile, "utf-8"));
16232
16646
  const pid = data.pid;
16233
16647
  const MAX_PID2 = 4194304;
16234
16648
  if (typeof pid === "number" && Number.isInteger(pid) && pid > 0 && pid <= MAX_PID2) {
@@ -16248,7 +16662,7 @@ function stopRunningDaemon() {
16248
16662
  }
16249
16663
  }
16250
16664
  try {
16251
- import_fs29.default.unlinkSync(pidFile);
16665
+ import_fs31.default.unlinkSync(pidFile);
16252
16666
  } catch {
16253
16667
  }
16254
16668
  } catch {
@@ -16318,26 +16732,26 @@ function isDaemonServiceInstalled() {
16318
16732
  if (process.platform === "linux") return isSystemdInstalled();
16319
16733
  return false;
16320
16734
  }
16321
- var import_fs29, import_path31, import_os27, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
16735
+ var import_fs31, import_path33, import_os29, import_child_process3, LAUNCHD_LABEL, LAUNCHD_PLIST, SYSTEMD_UNIT_DIR, SYSTEMD_UNIT;
16322
16736
  var init_service = __esm({
16323
16737
  "src/daemon/service.ts"() {
16324
16738
  "use strict";
16325
- import_fs29 = __toESM(require("fs"));
16326
- import_path31 = __toESM(require("path"));
16327
- import_os27 = __toESM(require("os"));
16739
+ import_fs31 = __toESM(require("fs"));
16740
+ import_path33 = __toESM(require("path"));
16741
+ import_os29 = __toESM(require("os"));
16328
16742
  import_child_process3 = require("child_process");
16329
16743
  LAUNCHD_LABEL = "ai.node9.daemon";
16330
- LAUNCHD_PLIST = import_path31.default.join(import_os27.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
16331
- SYSTEMD_UNIT_DIR = import_path31.default.join(import_os27.default.homedir(), ".config", "systemd", "user");
16332
- SYSTEMD_UNIT = import_path31.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
16744
+ LAUNCHD_PLIST = import_path33.default.join(import_os29.default.homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
16745
+ SYSTEMD_UNIT_DIR = import_path33.default.join(import_os29.default.homedir(), ".config", "systemd", "user");
16746
+ SYSTEMD_UNIT = import_path33.default.join(SYSTEMD_UNIT_DIR, "node9-daemon.service");
16333
16747
  }
16334
16748
  });
16335
16749
 
16336
16750
  // src/daemon/index.ts
16337
16751
  function stopDaemon() {
16338
- if (!import_fs30.default.existsSync(DAEMON_PID_FILE)) return console.log(import_chalk7.default.yellow("Not running."));
16752
+ if (!import_fs32.default.existsSync(DAEMON_PID_FILE)) return console.log(import_chalk7.default.yellow("Not running."));
16339
16753
  try {
16340
- const data = JSON.parse(import_fs30.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
16754
+ const data = JSON.parse(import_fs32.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
16341
16755
  const pid = data.pid;
16342
16756
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
16343
16757
  console.log(import_chalk7.default.gray("Cleaned up invalid PID file."));
@@ -16349,7 +16763,7 @@ function stopDaemon() {
16349
16763
  console.log(import_chalk7.default.gray("Cleaned up stale PID file."));
16350
16764
  } finally {
16351
16765
  try {
16352
- import_fs30.default.unlinkSync(DAEMON_PID_FILE);
16766
+ import_fs32.default.unlinkSync(DAEMON_PID_FILE);
16353
16767
  } catch {
16354
16768
  }
16355
16769
  }
@@ -16358,9 +16772,9 @@ function daemonStatus() {
16358
16772
  const serviceInstalled = isDaemonServiceInstalled();
16359
16773
  const serviceLabel = serviceInstalled ? import_chalk7.default.green("installed (starts on login)") : import_chalk7.default.yellow("not installed \u2014 run: node9 daemon install");
16360
16774
  let processStatus;
16361
- if (import_fs30.default.existsSync(DAEMON_PID_FILE)) {
16775
+ if (import_fs32.default.existsSync(DAEMON_PID_FILE)) {
16362
16776
  try {
16363
- const data = JSON.parse(import_fs30.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
16777
+ const data = JSON.parse(import_fs32.default.readFileSync(DAEMON_PID_FILE, "utf-8"));
16364
16778
  const pid = data.pid;
16365
16779
  const port = data.port;
16366
16780
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0 || pid > MAX_PID) {
@@ -16382,11 +16796,11 @@ function daemonStatus() {
16382
16796
  console.log(` Service : ${serviceLabel}
16383
16797
  `);
16384
16798
  }
16385
- var import_fs30, import_chalk7, MAX_PID;
16799
+ var import_fs32, import_chalk7, MAX_PID;
16386
16800
  var init_daemon2 = __esm({
16387
16801
  "src/daemon/index.ts"() {
16388
16802
  "use strict";
16389
- import_fs30 = __toESM(require("fs"));
16803
+ import_fs32 = __toESM(require("fs"));
16390
16804
  import_chalk7 = __toESM(require("chalk"));
16391
16805
  init_server();
16392
16806
  init_state2();
@@ -16426,20 +16840,20 @@ function getModelContextLimit(model) {
16426
16840
  return 2e5;
16427
16841
  }
16428
16842
  function readSessionUsage() {
16429
- const projectsDir = import_path49.default.join(import_os43.default.homedir(), ".claude", "projects");
16430
- if (!import_fs48.default.existsSync(projectsDir)) return null;
16843
+ const projectsDir = import_path51.default.join(import_os45.default.homedir(), ".claude", "projects");
16844
+ if (!import_fs50.default.existsSync(projectsDir)) return null;
16431
16845
  let latestFile = null;
16432
16846
  let latestMtime = 0;
16433
16847
  try {
16434
- for (const dir of import_fs48.default.readdirSync(projectsDir)) {
16435
- const dirPath = import_path49.default.join(projectsDir, dir);
16848
+ for (const dir of import_fs50.default.readdirSync(projectsDir)) {
16849
+ const dirPath = import_path51.default.join(projectsDir, dir);
16436
16850
  try {
16437
- if (!import_fs48.default.statSync(dirPath).isDirectory()) continue;
16438
- for (const file of import_fs48.default.readdirSync(dirPath)) {
16851
+ if (!import_fs50.default.statSync(dirPath).isDirectory()) continue;
16852
+ for (const file of import_fs50.default.readdirSync(dirPath)) {
16439
16853
  if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
16440
- const filePath = import_path49.default.join(dirPath, file);
16854
+ const filePath = import_path51.default.join(dirPath, file);
16441
16855
  try {
16442
- const mtime = import_fs48.default.statSync(filePath).mtimeMs;
16856
+ const mtime = import_fs50.default.statSync(filePath).mtimeMs;
16443
16857
  if (mtime > latestMtime) {
16444
16858
  latestMtime = mtime;
16445
16859
  latestFile = filePath;
@@ -16454,7 +16868,7 @@ function readSessionUsage() {
16454
16868
  }
16455
16869
  if (!latestFile) return null;
16456
16870
  try {
16457
- const lines = import_fs48.default.readFileSync(latestFile, "utf-8").split("\n");
16871
+ const lines = import_fs50.default.readFileSync(latestFile, "utf-8").split("\n");
16458
16872
  let lastModel = "";
16459
16873
  let lastInput = 0;
16460
16874
  let lastOutput = 0;
@@ -16515,7 +16929,7 @@ function formatBase(activity) {
16515
16929
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
16516
16930
  const icon = getIcon(activity.tool);
16517
16931
  const toolName = activity.tool.slice(0, 16).padEnd(16);
16518
- const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os43.default.homedir(), "~");
16932
+ const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os45.default.homedir(), "~");
16519
16933
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
16520
16934
  return `${import_chalk29.default.gray(time)} ${icon} ${agentLabel(activity.agent, activity.mcpServer, activity.sessionId)}${import_chalk29.default.white.bold(toolName)} ${import_chalk29.default.dim(argsPreview)}`;
16521
16935
  }
@@ -16554,9 +16968,9 @@ function renderPending(activity) {
16554
16968
  }
16555
16969
  async function ensureDaemon() {
16556
16970
  let pidPort = null;
16557
- if (import_fs48.default.existsSync(PID_FILE)) {
16971
+ if (import_fs50.default.existsSync(PID_FILE)) {
16558
16972
  try {
16559
- const { port } = JSON.parse(import_fs48.default.readFileSync(PID_FILE, "utf-8"));
16973
+ const { port } = JSON.parse(import_fs50.default.readFileSync(PID_FILE, "utf-8"));
16560
16974
  pidPort = port;
16561
16975
  } catch {
16562
16976
  console.error(import_chalk29.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
@@ -16712,9 +17126,9 @@ function buildRecoveryCardLines(req) {
16712
17126
  ];
16713
17127
  }
16714
17128
  function readApproversFromDisk() {
16715
- const configPath = import_path49.default.join(import_os43.default.homedir(), ".node9", "config.json");
17129
+ const configPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "config.json");
16716
17130
  try {
16717
- const raw = JSON.parse(import_fs48.default.readFileSync(configPath, "utf-8"));
17131
+ const raw = JSON.parse(import_fs50.default.readFileSync(configPath, "utf-8"));
16718
17132
  const settings = raw.settings ?? {};
16719
17133
  return settings.approvers ?? {};
16720
17134
  } catch {
@@ -16730,15 +17144,15 @@ function approverStatusLine() {
16730
17144
  return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
16731
17145
  }
16732
17146
  function toggleApprover(channel) {
16733
- const configPath = import_path49.default.join(import_os43.default.homedir(), ".node9", "config.json");
17147
+ const configPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "config.json");
16734
17148
  try {
16735
- const raw = JSON.parse(import_fs48.default.readFileSync(configPath, "utf-8"));
17149
+ const raw = JSON.parse(import_fs50.default.readFileSync(configPath, "utf-8"));
16736
17150
  const settings = raw.settings ?? {};
16737
17151
  const approvers = settings.approvers ?? {};
16738
17152
  approvers[channel] = approvers[channel] === false;
16739
17153
  settings.approvers = approvers;
16740
17154
  raw.settings = settings;
16741
- import_fs48.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
17155
+ import_fs50.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
16742
17156
  } catch (err2) {
16743
17157
  process.stderr.write(`[node9] toggleApprover failed: ${String(err2)}
16744
17158
  `);
@@ -16910,8 +17324,8 @@ async function startTail(options = {}) {
16910
17324
  }
16911
17325
  postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
16912
17326
  try {
16913
- import_fs48.default.appendFileSync(
16914
- import_path49.default.join(import_os43.default.homedir(), ".node9", "hook-debug.log"),
17327
+ import_fs50.default.appendFileSync(
17328
+ import_path51.default.join(import_os45.default.homedir(), ".node9", "hook-debug.log"),
16915
17329
  `[tail] POST /decision failed: ${String(err2)}
16916
17330
  `
16917
17331
  );
@@ -16975,9 +17389,9 @@ async function startTail(options = {}) {
16975
17389
  };
16976
17390
  process.stdin.on("keypress", onKeypress);
16977
17391
  }
16978
- const auditLog = import_path49.default.join(import_os43.default.homedir(), ".node9", "audit.log");
17392
+ const auditLog = import_path51.default.join(import_os45.default.homedir(), ".node9", "audit.log");
16979
17393
  try {
16980
- const unackedDlp = import_fs48.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
17394
+ const unackedDlp = import_fs50.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
16981
17395
  if (unackedDlp > 0) {
16982
17396
  console.log("");
16983
17397
  console.log(
@@ -17017,7 +17431,7 @@ async function startTail(options = {}) {
17017
17431
  if (stallWarned) return;
17018
17432
  if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
17019
17433
  try {
17020
- const auditMtime = import_fs48.default.statSync(auditLog).mtimeMs;
17434
+ const auditMtime = import_fs50.default.statSync(auditLog).mtimeMs;
17021
17435
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
17022
17436
  console.log("");
17023
17437
  console.log(
@@ -17202,20 +17616,20 @@ async function startTail(options = {}) {
17202
17616
  process.exit(1);
17203
17617
  });
17204
17618
  }
17205
- var import_http2, import_chalk29, import_fs48, import_os43, import_path49, import_readline6, import_child_process12, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
17619
+ var import_http2, import_chalk29, import_fs50, import_os45, import_path51, import_readline6, import_child_process12, PID_FILE, ICONS, MODEL_CONTEXT_LIMITS, RESET2, BOLD2, RED, YELLOW, CYAN, GRAY, GREEN, HIDE_CURSOR, SHOW_CURSOR, ERASE_DOWN, pendingShownForId, pendingWrappedLines, DIVIDER;
17206
17620
  var init_tail = __esm({
17207
17621
  "src/tui/tail.ts"() {
17208
17622
  "use strict";
17209
17623
  import_http2 = __toESM(require("http"));
17210
17624
  import_chalk29 = __toESM(require("chalk"));
17211
- import_fs48 = __toESM(require("fs"));
17212
- import_os43 = __toESM(require("os"));
17213
- import_path49 = __toESM(require("path"));
17625
+ import_fs50 = __toESM(require("fs"));
17626
+ import_os45 = __toESM(require("os"));
17627
+ import_path51 = __toESM(require("path"));
17214
17628
  import_readline6 = __toESM(require("readline"));
17215
17629
  import_child_process12 = require("child_process");
17216
17630
  init_daemon2();
17217
17631
  init_daemon();
17218
- PID_FILE = import_path49.default.join(import_os43.default.homedir(), ".node9", "daemon.pid");
17632
+ PID_FILE = import_path51.default.join(import_os45.default.homedir(), ".node9", "daemon.pid");
17219
17633
  ICONS = {
17220
17634
  bash: "\u{1F4BB}",
17221
17635
  shell: "\u{1F4BB}",
@@ -17265,8 +17679,8 @@ __export(hud_exports, {
17265
17679
  });
17266
17680
  async function readStdin() {
17267
17681
  const chunks = [];
17268
- for await (const chunk of process.stdin) {
17269
- chunks.push(chunk);
17682
+ for await (const chunk2 of process.stdin) {
17683
+ chunks.push(chunk2);
17270
17684
  }
17271
17685
  const raw = Buffer.concat(chunks).toString("utf-8").trim();
17272
17686
  if (!raw) return {};
@@ -17337,9 +17751,9 @@ function formatTimeLeft(resetsAt) {
17337
17751
  return ` (${m}m left)`;
17338
17752
  }
17339
17753
  function safeReadJson(filePath) {
17340
- if (!import_fs49.default.existsSync(filePath)) return null;
17754
+ if (!import_fs51.default.existsSync(filePath)) return null;
17341
17755
  try {
17342
- return JSON.parse(import_fs49.default.readFileSync(filePath, "utf-8"));
17756
+ return JSON.parse(import_fs51.default.readFileSync(filePath, "utf-8"));
17343
17757
  } catch {
17344
17758
  return null;
17345
17759
  }
@@ -17360,12 +17774,12 @@ function countHooksInFile(filePath) {
17360
17774
  return Object.keys(cfg.hooks).length;
17361
17775
  }
17362
17776
  function countRulesInDir(rulesDir) {
17363
- if (!import_fs49.default.existsSync(rulesDir)) return 0;
17777
+ if (!import_fs51.default.existsSync(rulesDir)) return 0;
17364
17778
  let count = 0;
17365
17779
  try {
17366
- for (const entry of import_fs49.default.readdirSync(rulesDir, { withFileTypes: true })) {
17780
+ for (const entry of import_fs51.default.readdirSync(rulesDir, { withFileTypes: true })) {
17367
17781
  if (entry.isDirectory()) {
17368
- count += countRulesInDir(import_path50.default.join(rulesDir, entry.name));
17782
+ count += countRulesInDir(import_path52.default.join(rulesDir, entry.name));
17369
17783
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
17370
17784
  count++;
17371
17785
  }
@@ -17376,46 +17790,46 @@ function countRulesInDir(rulesDir) {
17376
17790
  }
17377
17791
  function isSamePath(a, b) {
17378
17792
  try {
17379
- return import_path50.default.resolve(a) === import_path50.default.resolve(b);
17793
+ return import_path52.default.resolve(a) === import_path52.default.resolve(b);
17380
17794
  } catch {
17381
17795
  return false;
17382
17796
  }
17383
17797
  }
17384
17798
  function countConfigs(cwd) {
17385
- const homeDir2 = import_os44.default.homedir();
17386
- const claudeDir = import_path50.default.join(homeDir2, ".claude");
17799
+ const homeDir2 = import_os46.default.homedir();
17800
+ const claudeDir = import_path52.default.join(homeDir2, ".claude");
17387
17801
  let claudeMdCount = 0;
17388
17802
  let rulesCount = 0;
17389
17803
  let hooksCount = 0;
17390
17804
  const userMcpServers = /* @__PURE__ */ new Set();
17391
17805
  const projectMcpServers = /* @__PURE__ */ new Set();
17392
- if (import_fs49.default.existsSync(import_path50.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
17393
- rulesCount += countRulesInDir(import_path50.default.join(claudeDir, "rules"));
17394
- const userSettings = import_path50.default.join(claudeDir, "settings.json");
17806
+ if (import_fs51.default.existsSync(import_path52.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
17807
+ rulesCount += countRulesInDir(import_path52.default.join(claudeDir, "rules"));
17808
+ const userSettings = import_path52.default.join(claudeDir, "settings.json");
17395
17809
  for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
17396
17810
  hooksCount += countHooksInFile(userSettings);
17397
- const userClaudeJson = import_path50.default.join(homeDir2, ".claude.json");
17811
+ const userClaudeJson = import_path52.default.join(homeDir2, ".claude.json");
17398
17812
  for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
17399
17813
  for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
17400
17814
  userMcpServers.delete(name);
17401
17815
  }
17402
17816
  if (cwd) {
17403
- if (import_fs49.default.existsSync(import_path50.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
17404
- if (import_fs49.default.existsSync(import_path50.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
17405
- const projectClaudeDir = import_path50.default.join(cwd, ".claude");
17817
+ if (import_fs51.default.existsSync(import_path52.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
17818
+ if (import_fs51.default.existsSync(import_path52.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
17819
+ const projectClaudeDir = import_path52.default.join(cwd, ".claude");
17406
17820
  const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
17407
17821
  if (!overlapsUserScope) {
17408
- if (import_fs49.default.existsSync(import_path50.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
17409
- rulesCount += countRulesInDir(import_path50.default.join(projectClaudeDir, "rules"));
17410
- const projSettings = import_path50.default.join(projectClaudeDir, "settings.json");
17822
+ if (import_fs51.default.existsSync(import_path52.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
17823
+ rulesCount += countRulesInDir(import_path52.default.join(projectClaudeDir, "rules"));
17824
+ const projSettings = import_path52.default.join(projectClaudeDir, "settings.json");
17411
17825
  for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
17412
17826
  hooksCount += countHooksInFile(projSettings);
17413
17827
  }
17414
- if (import_fs49.default.existsSync(import_path50.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
17415
- const localSettings = import_path50.default.join(projectClaudeDir, "settings.local.json");
17828
+ if (import_fs51.default.existsSync(import_path52.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
17829
+ const localSettings = import_path52.default.join(projectClaudeDir, "settings.local.json");
17416
17830
  for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
17417
17831
  hooksCount += countHooksInFile(localSettings);
17418
- const mcpJsonServers = getMcpServerNames(import_path50.default.join(cwd, ".mcp.json"));
17832
+ const mcpJsonServers = getMcpServerNames(import_path52.default.join(cwd, ".mcp.json"));
17419
17833
  const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
17420
17834
  for (const name of disabledMcpJson) mcpJsonServers.delete(name);
17421
17835
  for (const name of mcpJsonServers) projectMcpServers.add(name);
@@ -17448,12 +17862,12 @@ function readActiveShieldsHud() {
17448
17862
  return shieldsCache.value;
17449
17863
  }
17450
17864
  try {
17451
- const shieldsPath = import_path50.default.join(import_os44.default.homedir(), ".node9", "shields.json");
17452
- if (!import_fs49.default.existsSync(shieldsPath)) {
17865
+ const shieldsPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "shields.json");
17866
+ if (!import_fs51.default.existsSync(shieldsPath)) {
17453
17867
  shieldsCache = { value: [], ts: now };
17454
17868
  return [];
17455
17869
  }
17456
- const parsed = JSON.parse(import_fs49.default.readFileSync(shieldsPath, "utf-8"));
17870
+ const parsed = JSON.parse(import_fs51.default.readFileSync(shieldsPath, "utf-8"));
17457
17871
  if (!Array.isArray(parsed.active)) {
17458
17872
  shieldsCache = { value: [], ts: now };
17459
17873
  return [];
@@ -17555,17 +17969,17 @@ function renderContextLine(stdin) {
17555
17969
  async function main() {
17556
17970
  try {
17557
17971
  const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
17558
- if (import_fs49.default.existsSync(import_path50.default.join(import_os44.default.homedir(), ".node9", "hud-debug"))) {
17972
+ if (import_fs51.default.existsSync(import_path52.default.join(import_os46.default.homedir(), ".node9", "hud-debug"))) {
17559
17973
  try {
17560
- const logPath = import_path50.default.join(import_os44.default.homedir(), ".node9", "hud-debug.log");
17974
+ const logPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "hud-debug.log");
17561
17975
  const MAX_LOG_SIZE = 10 * 1024 * 1024;
17562
17976
  let size = 0;
17563
17977
  try {
17564
- size = import_fs49.default.statSync(logPath).size;
17978
+ size = import_fs51.default.statSync(logPath).size;
17565
17979
  } catch {
17566
17980
  }
17567
17981
  if (size < MAX_LOG_SIZE) {
17568
- import_fs49.default.appendFileSync(
17982
+ import_fs51.default.appendFileSync(
17569
17983
  logPath,
17570
17984
  JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
17571
17985
  );
@@ -17586,11 +18000,11 @@ async function main() {
17586
18000
  try {
17587
18001
  const cwd = stdin.cwd ?? process.cwd();
17588
18002
  for (const configPath of [
17589
- import_path50.default.join(cwd, "node9.config.json"),
17590
- import_path50.default.join(import_os44.default.homedir(), ".node9", "config.json")
18003
+ import_path52.default.join(cwd, "node9.config.json"),
18004
+ import_path52.default.join(import_os46.default.homedir(), ".node9", "config.json")
17591
18005
  ]) {
17592
- if (!import_fs49.default.existsSync(configPath)) continue;
17593
- const cfg = JSON.parse(import_fs49.default.readFileSync(configPath, "utf-8"));
18006
+ if (!import_fs51.default.existsSync(configPath)) continue;
18007
+ const cfg = JSON.parse(import_fs51.default.readFileSync(configPath, "utf-8"));
17594
18008
  const hud = cfg.settings?.hud;
17595
18009
  if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
17596
18010
  }
@@ -17608,13 +18022,13 @@ async function main() {
17608
18022
  renderOffline();
17609
18023
  }
17610
18024
  }
17611
- var import_fs49, import_path50, import_os44, import_http3, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
18025
+ var import_fs51, import_path52, import_os46, import_http3, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
17612
18026
  var init_hud = __esm({
17613
18027
  "src/cli/hud.ts"() {
17614
18028
  "use strict";
17615
- import_fs49 = __toESM(require("fs"));
17616
- import_path50 = __toESM(require("path"));
17617
- import_os44 = __toESM(require("os"));
18029
+ import_fs51 = __toESM(require("fs"));
18030
+ import_path52 = __toESM(require("path"));
18031
+ import_os46 = __toESM(require("os"));
17618
18032
  import_http3 = __toESM(require("http"));
17619
18033
  init_daemon();
17620
18034
  RESET3 = "\x1B[0m";
@@ -17641,9 +18055,9 @@ init_core();
17641
18055
  init_setup();
17642
18056
  init_daemon2();
17643
18057
  var import_chalk30 = __toESM(require("chalk"));
17644
- var import_fs50 = __toESM(require("fs"));
17645
- var import_path51 = __toESM(require("path"));
17646
- var import_os45 = __toESM(require("os"));
18058
+ var import_fs52 = __toESM(require("fs"));
18059
+ var import_path53 = __toESM(require("path"));
18060
+ var import_os47 = __toESM(require("os"));
17647
18061
  var import_prompts2 = require("@inquirer/prompts");
17648
18062
 
17649
18063
  // src/utils/duration.ts
@@ -17825,18 +18239,18 @@ async function runProxy(targetCommand) {
17825
18239
 
17826
18240
  // src/cli/daemon-starter.ts
17827
18241
  var import_child_process5 = require("child_process");
17828
- var import_path32 = __toESM(require("path"));
17829
- var import_fs31 = __toESM(require("fs"));
18242
+ var import_path34 = __toESM(require("path"));
18243
+ var import_fs33 = __toESM(require("fs"));
17830
18244
  init_daemon();
17831
18245
  function isTestingMode() {
17832
18246
  return /^(1|true|yes)$/i.test(process.env.NODE9_TESTING ?? "");
17833
18247
  }
17834
18248
  async function autoStartDaemonAndWait() {
17835
18249
  if (isTestingMode()) return false;
17836
- if (!import_path32.default.isAbsolute(process.argv[1])) return false;
18250
+ if (!import_path34.default.isAbsolute(process.argv[1])) return false;
17837
18251
  let resolvedArgv1;
17838
18252
  try {
17839
- resolvedArgv1 = import_fs31.default.realpathSync(process.argv[1]);
18253
+ resolvedArgv1 = import_fs33.default.realpathSync(process.argv[1]);
17840
18254
  } catch {
17841
18255
  return false;
17842
18256
  }
@@ -17863,10 +18277,10 @@ async function autoStartDaemonAndWait() {
17863
18277
 
17864
18278
  // src/cli/commands/check.ts
17865
18279
  var import_chalk9 = __toESM(require("chalk"));
17866
- var import_fs34 = __toESM(require("fs"));
18280
+ var import_fs36 = __toESM(require("fs"));
17867
18281
  var import_child_process7 = require("child_process");
17868
- var import_path35 = __toESM(require("path"));
17869
- var import_os30 = __toESM(require("os"));
18282
+ var import_path37 = __toESM(require("path"));
18283
+ var import_os32 = __toESM(require("os"));
17870
18284
  init_orchestrator();
17871
18285
  init_daemon();
17872
18286
  init_config();
@@ -17875,11 +18289,11 @@ init_policy();
17875
18289
  // src/undo.ts
17876
18290
  var import_child_process6 = require("child_process");
17877
18291
  var import_crypto11 = __toESM(require("crypto"));
17878
- var import_fs32 = __toESM(require("fs"));
18292
+ var import_fs34 = __toESM(require("fs"));
17879
18293
  var import_net3 = __toESM(require("net"));
17880
- var import_path33 = __toESM(require("path"));
17881
- var import_os28 = __toESM(require("os"));
17882
- var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path33.default.join(import_os28.default.tmpdir(), "node9-activity.sock");
18294
+ var import_path35 = __toESM(require("path"));
18295
+ var import_os30 = __toESM(require("os"));
18296
+ var ACTIVITY_SOCKET_PATH3 = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : import_path35.default.join(import_os30.default.tmpdir(), "node9-activity.sock");
17883
18297
  function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
17884
18298
  try {
17885
18299
  const payload = JSON.stringify({
@@ -17899,22 +18313,22 @@ function notifySnapshotTaken(hash, tool, argsSummary, fileCount) {
17899
18313
  } catch {
17900
18314
  }
17901
18315
  }
17902
- var SNAPSHOT_STACK_PATH = import_path33.default.join(import_os28.default.homedir(), ".node9", "snapshots.json");
17903
- var UNDO_LATEST_PATH = import_path33.default.join(import_os28.default.homedir(), ".node9", "undo_latest.txt");
18316
+ var SNAPSHOT_STACK_PATH = import_path35.default.join(import_os30.default.homedir(), ".node9", "snapshots.json");
18317
+ var UNDO_LATEST_PATH = import_path35.default.join(import_os30.default.homedir(), ".node9", "undo_latest.txt");
17904
18318
  var MAX_SNAPSHOTS = 10;
17905
18319
  var GIT_TIMEOUT = 15e3;
17906
18320
  function readStack() {
17907
18321
  try {
17908
- if (import_fs32.default.existsSync(SNAPSHOT_STACK_PATH))
17909
- return JSON.parse(import_fs32.default.readFileSync(SNAPSHOT_STACK_PATH, "utf-8"));
18322
+ if (import_fs34.default.existsSync(SNAPSHOT_STACK_PATH))
18323
+ return JSON.parse(import_fs34.default.readFileSync(SNAPSHOT_STACK_PATH, "utf-8"));
17910
18324
  } catch {
17911
18325
  }
17912
18326
  return [];
17913
18327
  }
17914
18328
  function writeStack(stack) {
17915
- const dir = import_path33.default.dirname(SNAPSHOT_STACK_PATH);
17916
- if (!import_fs32.default.existsSync(dir)) import_fs32.default.mkdirSync(dir, { recursive: true });
17917
- import_fs32.default.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
18329
+ const dir = import_path35.default.dirname(SNAPSHOT_STACK_PATH);
18330
+ if (!import_fs34.default.existsSync(dir)) import_fs34.default.mkdirSync(dir, { recursive: true });
18331
+ import_fs34.default.writeFileSync(SNAPSHOT_STACK_PATH, JSON.stringify(stack, null, 2));
17918
18332
  }
17919
18333
  function extractFilePath(args) {
17920
18334
  if (!args || typeof args !== "object") return null;
@@ -17934,12 +18348,12 @@ function buildArgsSummary(tool, args) {
17934
18348
  return "";
17935
18349
  }
17936
18350
  function findProjectRoot(filePath) {
17937
- let dir = import_path33.default.dirname(filePath);
18351
+ let dir = import_path35.default.dirname(filePath);
17938
18352
  while (true) {
17939
- if (import_fs32.default.existsSync(import_path33.default.join(dir, ".git")) || import_fs32.default.existsSync(import_path33.default.join(dir, "package.json"))) {
18353
+ if (import_fs34.default.existsSync(import_path35.default.join(dir, ".git")) || import_fs34.default.existsSync(import_path35.default.join(dir, "package.json"))) {
17940
18354
  return dir;
17941
18355
  }
17942
- const parent = import_path33.default.dirname(dir);
18356
+ const parent = import_path35.default.dirname(dir);
17943
18357
  if (parent === dir) return process.cwd();
17944
18358
  dir = parent;
17945
18359
  }
@@ -17947,7 +18361,7 @@ function findProjectRoot(filePath) {
17947
18361
  function normalizeCwdForHash(cwd) {
17948
18362
  let normalized;
17949
18363
  try {
17950
- normalized = import_fs32.default.realpathSync(cwd);
18364
+ normalized = import_fs34.default.realpathSync(cwd);
17951
18365
  } catch {
17952
18366
  normalized = cwd;
17953
18367
  }
@@ -17957,16 +18371,16 @@ function normalizeCwdForHash(cwd) {
17957
18371
  }
17958
18372
  function getShadowRepoDir(cwd) {
17959
18373
  const hash = import_crypto11.default.createHash("sha256").update(normalizeCwdForHash(cwd)).digest("hex").slice(0, 16);
17960
- return import_path33.default.join(import_os28.default.homedir(), ".node9", "snapshots", hash);
18374
+ return import_path35.default.join(import_os30.default.homedir(), ".node9", "snapshots", hash);
17961
18375
  }
17962
18376
  function cleanOrphanedIndexFiles(shadowDir) {
17963
18377
  try {
17964
18378
  const cutoff = Date.now() - 6e4;
17965
- for (const f of import_fs32.default.readdirSync(shadowDir)) {
18379
+ for (const f of import_fs34.default.readdirSync(shadowDir)) {
17966
18380
  if (f.startsWith("index_")) {
17967
- const fp = import_path33.default.join(shadowDir, f);
18381
+ const fp = import_path35.default.join(shadowDir, f);
17968
18382
  try {
17969
- if (import_fs32.default.statSync(fp).mtimeMs < cutoff) import_fs32.default.unlinkSync(fp);
18383
+ if (import_fs34.default.statSync(fp).mtimeMs < cutoff) import_fs34.default.unlinkSync(fp);
17970
18384
  } catch {
17971
18385
  }
17972
18386
  }
@@ -17978,7 +18392,7 @@ function writeShadowExcludes(shadowDir, ignorePaths) {
17978
18392
  const hardcoded = [".git", ".node9"];
17979
18393
  const lines = [...hardcoded, ...ignorePaths].join("\n");
17980
18394
  try {
17981
- import_fs32.default.writeFileSync(import_path33.default.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
18395
+ import_fs34.default.writeFileSync(import_path35.default.join(shadowDir, "info", "exclude"), lines + "\n", "utf8");
17982
18396
  } catch {
17983
18397
  }
17984
18398
  }
@@ -17991,25 +18405,25 @@ function ensureShadowRepo(shadowDir, cwd) {
17991
18405
  timeout: 3e3
17992
18406
  });
17993
18407
  if (check.status === 0) {
17994
- const ptPath = import_path33.default.join(shadowDir, "project-path.txt");
18408
+ const ptPath = import_path35.default.join(shadowDir, "project-path.txt");
17995
18409
  try {
17996
- const stored = import_fs32.default.readFileSync(ptPath, "utf8").trim();
18410
+ const stored = import_fs34.default.readFileSync(ptPath, "utf8").trim();
17997
18411
  if (stored === normalizedCwd) return true;
17998
18412
  if (process.env.NODE9_DEBUG === "1")
17999
18413
  console.error(
18000
18414
  `[Node9] Shadow repo path mismatch: stored="${stored}" expected="${normalizedCwd}" \u2014 reinitializing`
18001
18415
  );
18002
- import_fs32.default.rmSync(shadowDir, { recursive: true, force: true });
18416
+ import_fs34.default.rmSync(shadowDir, { recursive: true, force: true });
18003
18417
  } catch {
18004
18418
  try {
18005
- import_fs32.default.writeFileSync(ptPath, normalizedCwd, "utf8");
18419
+ import_fs34.default.writeFileSync(ptPath, normalizedCwd, "utf8");
18006
18420
  } catch {
18007
18421
  }
18008
18422
  return true;
18009
18423
  }
18010
18424
  }
18011
18425
  try {
18012
- import_fs32.default.mkdirSync(shadowDir, { recursive: true });
18426
+ import_fs34.default.mkdirSync(shadowDir, { recursive: true });
18013
18427
  } catch {
18014
18428
  }
18015
18429
  const init = (0, import_child_process6.spawnSync)("git", ["init", "--bare", shadowDir], { timeout: 5e3 });
@@ -18018,7 +18432,7 @@ function ensureShadowRepo(shadowDir, cwd) {
18018
18432
  if (process.env.NODE9_DEBUG === "1") console.error("[Node9] git init --bare failed:", reason);
18019
18433
  return false;
18020
18434
  }
18021
- const configFile = import_path33.default.join(shadowDir, "config");
18435
+ const configFile = import_path35.default.join(shadowDir, "config");
18022
18436
  (0, import_child_process6.spawnSync)("git", ["config", "--file", configFile, "core.untrackedCache", "true"], {
18023
18437
  timeout: 3e3
18024
18438
  });
@@ -18026,7 +18440,7 @@ function ensureShadowRepo(shadowDir, cwd) {
18026
18440
  timeout: 3e3
18027
18441
  });
18028
18442
  try {
18029
- import_fs32.default.writeFileSync(import_path33.default.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
18443
+ import_fs34.default.writeFileSync(import_path35.default.join(shadowDir, "project-path.txt"), normalizedCwd, "utf8");
18030
18444
  } catch {
18031
18445
  }
18032
18446
  return true;
@@ -18049,12 +18463,12 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
18049
18463
  let indexFile = null;
18050
18464
  try {
18051
18465
  const rawFilePath = extractFilePath(args);
18052
- const absFilePath = rawFilePath && import_path33.default.isAbsolute(rawFilePath) ? rawFilePath : null;
18466
+ const absFilePath = rawFilePath && import_path35.default.isAbsolute(rawFilePath) ? rawFilePath : null;
18053
18467
  const cwd = absFilePath ? findProjectRoot(absFilePath) : process.cwd();
18054
18468
  const shadowDir = getShadowRepoDir(cwd);
18055
18469
  if (!ensureShadowRepo(shadowDir, cwd)) return null;
18056
18470
  writeShadowExcludes(shadowDir, ignorePaths);
18057
- indexFile = import_path33.default.join(shadowDir, `index_${process.pid}_${Date.now()}`);
18471
+ indexFile = import_path35.default.join(shadowDir, `index_${process.pid}_${Date.now()}`);
18058
18472
  const shadowEnv = {
18059
18473
  ...process.env,
18060
18474
  GIT_DIR: shadowDir,
@@ -18126,7 +18540,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
18126
18540
  writeStack(stack);
18127
18541
  const entry = stack[stack.length - 1];
18128
18542
  notifySnapshotTaken(commitHash.slice(0, 7), tool, entry.argsSummary, capturedFiles.length);
18129
- import_fs32.default.writeFileSync(UNDO_LATEST_PATH, commitHash);
18543
+ import_fs34.default.writeFileSync(UNDO_LATEST_PATH, commitHash);
18130
18544
  if (shouldGc) {
18131
18545
  (0, import_child_process6.spawn)("git", ["gc", "--auto"], { env: shadowEnv, detached: true, stdio: "ignore" }).unref();
18132
18546
  }
@@ -18137,7 +18551,7 @@ async function createShadowSnapshot(tool = "unknown", args = {}, ignorePaths = [
18137
18551
  } finally {
18138
18552
  if (indexFile) {
18139
18553
  try {
18140
- import_fs32.default.unlinkSync(indexFile);
18554
+ import_fs34.default.unlinkSync(indexFile);
18141
18555
  } catch {
18142
18556
  }
18143
18557
  }
@@ -18213,9 +18627,9 @@ function applyUndo(hash, cwd) {
18213
18627
  timeout: GIT_TIMEOUT
18214
18628
  }).stdout?.toString().trim().split("\n").filter(Boolean) ?? [];
18215
18629
  for (const file of [...tracked, ...untracked]) {
18216
- const fullPath = import_path33.default.join(dir, file);
18217
- if (!snapshotFiles.has(file) && import_fs32.default.existsSync(fullPath)) {
18218
- import_fs32.default.unlinkSync(fullPath);
18630
+ const fullPath = import_path35.default.join(dir, file);
18631
+ if (!snapshotFiles.has(file) && import_fs34.default.existsSync(fullPath)) {
18632
+ import_fs34.default.unlinkSync(fullPath);
18219
18633
  }
18220
18634
  }
18221
18635
  return true;
@@ -18225,12 +18639,12 @@ function applyUndo(hash, cwd) {
18225
18639
  }
18226
18640
 
18227
18641
  // src/skill-pin.ts
18228
- var import_fs33 = __toESM(require("fs"));
18229
- var import_path34 = __toESM(require("path"));
18230
- var import_os29 = __toESM(require("os"));
18642
+ var import_fs35 = __toESM(require("fs"));
18643
+ var import_path36 = __toESM(require("path"));
18644
+ var import_os31 = __toESM(require("os"));
18231
18645
  var import_crypto12 = __toESM(require("crypto"));
18232
18646
  function getPinsFilePath2() {
18233
- return import_path34.default.join(import_os29.default.homedir(), ".node9", "skill-pins.json");
18647
+ return import_path36.default.join(import_os31.default.homedir(), ".node9", "skill-pins.json");
18234
18648
  }
18235
18649
  var MAX_FILES = 5e3;
18236
18650
  var MAX_TOTAL_BYTES = 50 * 1024 * 1024;
@@ -18244,18 +18658,18 @@ function walkDir(root) {
18244
18658
  if (out.length >= MAX_FILES) return;
18245
18659
  let entries;
18246
18660
  try {
18247
- entries = import_fs33.default.readdirSync(dir, { withFileTypes: true });
18661
+ entries = import_fs35.default.readdirSync(dir, { withFileTypes: true });
18248
18662
  } catch {
18249
18663
  return;
18250
18664
  }
18251
18665
  entries.sort((a, b) => a.name.localeCompare(b.name));
18252
18666
  for (const entry of entries) {
18253
18667
  if (out.length >= MAX_FILES) return;
18254
- const full = import_path34.default.join(dir, entry.name);
18255
- const rel = relDir ? import_path34.default.posix.join(relDir, entry.name) : entry.name;
18668
+ const full = import_path36.default.join(dir, entry.name);
18669
+ const rel = relDir ? import_path36.default.posix.join(relDir, entry.name) : entry.name;
18256
18670
  let lst;
18257
18671
  try {
18258
- lst = import_fs33.default.lstatSync(full);
18672
+ lst = import_fs35.default.lstatSync(full);
18259
18673
  } catch {
18260
18674
  continue;
18261
18675
  }
@@ -18267,7 +18681,7 @@ function walkDir(root) {
18267
18681
  if (!lst.isFile()) continue;
18268
18682
  if (totalBytes + lst.size > MAX_TOTAL_BYTES) continue;
18269
18683
  try {
18270
- const buf = import_fs33.default.readFileSync(full);
18684
+ const buf = import_fs35.default.readFileSync(full);
18271
18685
  totalBytes += buf.length;
18272
18686
  out.push({ rel, hash: sha256Bytes(buf) });
18273
18687
  } catch {
@@ -18281,14 +18695,14 @@ function walkDir(root) {
18281
18695
  function hashSkillRoot(absPath) {
18282
18696
  let lst;
18283
18697
  try {
18284
- lst = import_fs33.default.lstatSync(absPath);
18698
+ lst = import_fs35.default.lstatSync(absPath);
18285
18699
  } catch {
18286
18700
  return { exists: false, contentHash: "", fileCount: 0 };
18287
18701
  }
18288
18702
  if (lst.isSymbolicLink()) return { exists: false, contentHash: "", fileCount: 0 };
18289
18703
  if (lst.isFile()) {
18290
18704
  try {
18291
- return { exists: true, contentHash: sha256Bytes(import_fs33.default.readFileSync(absPath)), fileCount: 1 };
18705
+ return { exists: true, contentHash: sha256Bytes(import_fs35.default.readFileSync(absPath)), fileCount: 1 };
18292
18706
  } catch {
18293
18707
  return { exists: false, contentHash: "", fileCount: 0 };
18294
18708
  }
@@ -18306,7 +18720,7 @@ function getRootKey(absPath) {
18306
18720
  function readSkillPinsSafe() {
18307
18721
  const filePath = getPinsFilePath2();
18308
18722
  try {
18309
- const raw = import_fs33.default.readFileSync(filePath, "utf-8");
18723
+ const raw = import_fs35.default.readFileSync(filePath, "utf-8");
18310
18724
  if (!raw.trim()) return { ok: false, reason: "corrupt", detail: "empty file" };
18311
18725
  const parsed = JSON.parse(raw);
18312
18726
  if (!parsed.roots || typeof parsed.roots !== "object" || Array.isArray(parsed.roots)) {
@@ -18326,10 +18740,10 @@ function readSkillPins() {
18326
18740
  }
18327
18741
  function writeSkillPins(data) {
18328
18742
  const filePath = getPinsFilePath2();
18329
- import_fs33.default.mkdirSync(import_path34.default.dirname(filePath), { recursive: true });
18743
+ import_fs35.default.mkdirSync(import_path36.default.dirname(filePath), { recursive: true });
18330
18744
  const tmp = `${filePath}.${import_crypto12.default.randomBytes(6).toString("hex")}.tmp`;
18331
- import_fs33.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
18332
- import_fs33.default.renameSync(tmp, filePath);
18745
+ import_fs35.default.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 384 });
18746
+ import_fs35.default.renameSync(tmp, filePath);
18333
18747
  }
18334
18748
  function removePin2(rootKey) {
18335
18749
  const pins = readSkillPins();
@@ -18373,36 +18787,36 @@ function verifyAndPinRoots(roots) {
18373
18787
  return { kind: "verified" };
18374
18788
  }
18375
18789
  function defaultSkillRoots(_cwd) {
18376
- const marketplaces = import_path34.default.join(import_os29.default.homedir(), ".claude", "plugins", "marketplaces");
18790
+ const marketplaces = import_path36.default.join(import_os31.default.homedir(), ".claude", "plugins", "marketplaces");
18377
18791
  const roots = [];
18378
18792
  let registries;
18379
18793
  try {
18380
- registries = import_fs33.default.readdirSync(marketplaces, { withFileTypes: true });
18794
+ registries = import_fs35.default.readdirSync(marketplaces, { withFileTypes: true });
18381
18795
  } catch {
18382
18796
  return [];
18383
18797
  }
18384
18798
  for (const registry of registries) {
18385
18799
  if (!registry.isDirectory()) continue;
18386
- const pluginsDir = import_path34.default.join(marketplaces, registry.name, "plugins");
18800
+ const pluginsDir = import_path36.default.join(marketplaces, registry.name, "plugins");
18387
18801
  let plugins;
18388
18802
  try {
18389
- plugins = import_fs33.default.readdirSync(pluginsDir, { withFileTypes: true });
18803
+ plugins = import_fs35.default.readdirSync(pluginsDir, { withFileTypes: true });
18390
18804
  } catch {
18391
18805
  continue;
18392
18806
  }
18393
18807
  for (const plugin of plugins) {
18394
18808
  if (!plugin.isDirectory()) continue;
18395
- roots.push(import_path34.default.join(pluginsDir, plugin.name));
18809
+ roots.push(import_path36.default.join(pluginsDir, plugin.name));
18396
18810
  }
18397
18811
  }
18398
18812
  return roots;
18399
18813
  }
18400
18814
  function resolveUserSkillRoot(entry, cwd) {
18401
18815
  if (!entry) return null;
18402
- if (entry.startsWith("~/") || entry === "~") return import_path34.default.join(import_os29.default.homedir(), entry.slice(1));
18403
- if (import_path34.default.isAbsolute(entry)) return entry;
18404
- if (!cwd || !import_path34.default.isAbsolute(cwd)) return null;
18405
- return import_path34.default.join(cwd, entry);
18816
+ if (entry.startsWith("~/") || entry === "~") return import_path36.default.join(import_os31.default.homedir(), entry.slice(1));
18817
+ if (import_path36.default.isAbsolute(entry)) return entry;
18818
+ if (!cwd || !import_path36.default.isAbsolute(cwd)) return null;
18819
+ return import_path36.default.join(cwd, entry);
18406
18820
  }
18407
18821
 
18408
18822
  // src/cli/commands/check.ts
@@ -18471,9 +18885,9 @@ function registerCheckCommand(program2) {
18471
18885
  } catch (err2) {
18472
18886
  const tempConfig = getConfig();
18473
18887
  if (process.env.NODE9_DEBUG === "1" || tempConfig.settings.enableHookLogDebug) {
18474
- const logPath = import_path35.default.join(import_os30.default.homedir(), ".node9", "hook-debug.log");
18888
+ const logPath = import_path37.default.join(import_os32.default.homedir(), ".node9", "hook-debug.log");
18475
18889
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
18476
- import_fs34.default.appendFileSync(
18890
+ import_fs36.default.appendFileSync(
18477
18891
  logPath,
18478
18892
  `[${(/* @__PURE__ */ new Date()).toISOString()}] JSON_PARSE_ERROR: ${errMsg}
18479
18893
  RAW: ${raw}
@@ -18486,14 +18900,14 @@ RAW: ${raw}
18486
18900
  const prompt = typeof payload.prompt === "string" ? payload.prompt : "";
18487
18901
  if (process.env.NODE9_DEBUG === "1") {
18488
18902
  try {
18489
- const logPath = import_path35.default.join(import_os30.default.homedir(), ".node9", "hook-debug.log");
18490
- if (!import_fs34.default.existsSync(import_path35.default.dirname(logPath)))
18491
- import_fs34.default.mkdirSync(import_path35.default.dirname(logPath), { recursive: true });
18903
+ const logPath = import_path37.default.join(import_os32.default.homedir(), ".node9", "hook-debug.log");
18904
+ if (!import_fs36.default.existsSync(import_path37.default.dirname(logPath)))
18905
+ import_fs36.default.mkdirSync(import_path37.default.dirname(logPath), { recursive: true });
18492
18906
  const sanitized = JSON.stringify({
18493
18907
  ...payload,
18494
18908
  prompt: `<redacted, ${prompt.length} bytes>`
18495
18909
  });
18496
- import_fs34.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
18910
+ import_fs36.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${sanitized}
18497
18911
  `);
18498
18912
  } catch {
18499
18913
  }
@@ -18513,8 +18927,8 @@ RAW: ${raw}
18513
18927
  );
18514
18928
  const reason = `\u{1F6A8} Node9 DLP: ${dlpMatch.patternName} detected in prompt (${dlpMatch.redactedSample}). Prompt was not submitted \u2014 remove the credential and try again.`;
18515
18929
  try {
18516
- const ttyFd = import_fs34.default.openSync("/dev/tty", "w");
18517
- import_fs34.default.writeSync(
18930
+ const ttyFd = import_fs36.default.openSync("/dev/tty", "w");
18931
+ import_fs36.default.writeSync(
18518
18932
  ttyFd,
18519
18933
  import_chalk9.default.bgRed.white.bold(`
18520
18934
  \u{1F6A8} NODE9 DLP \u2014 PROMPT BLOCKED
@@ -18524,7 +18938,7 @@ RAW: ${raw}
18524
18938
 
18525
18939
  `)
18526
18940
  );
18527
- import_fs34.default.closeSync(ttyFd);
18941
+ import_fs36.default.closeSync(ttyFd);
18528
18942
  } catch {
18529
18943
  }
18530
18944
  const isCodex = agent2 === "Codex";
@@ -18543,16 +18957,16 @@ RAW: ${raw}
18543
18957
  process.exit(2);
18544
18958
  }
18545
18959
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
18546
- const safeCwdForConfig = typeof payloadCwd === "string" && import_path35.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
18960
+ const safeCwdForConfig = typeof payloadCwd === "string" && import_path37.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
18547
18961
  const config = getConfig(safeCwdForConfig);
18548
18962
  if (config.settings.autoStartDaemon && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON) {
18549
18963
  try {
18550
18964
  const scriptPath = process.argv[1];
18551
- if (typeof scriptPath !== "string" || !import_path35.default.isAbsolute(scriptPath))
18965
+ if (typeof scriptPath !== "string" || !import_path37.default.isAbsolute(scriptPath))
18552
18966
  throw new Error("node9: argv[1] is not an absolute path");
18553
- const resolvedScript = import_fs34.default.realpathSync(scriptPath);
18554
- const packageDist = import_fs34.default.realpathSync(import_path35.default.resolve(__dirname, "../.."));
18555
- if (!resolvedScript.startsWith(packageDist + import_path35.default.sep) && resolvedScript !== packageDist)
18967
+ const resolvedScript = import_fs36.default.realpathSync(scriptPath);
18968
+ const packageDist = import_fs36.default.realpathSync(import_path37.default.resolve(__dirname, "../.."));
18969
+ if (!resolvedScript.startsWith(packageDist + import_path37.default.sep) && resolvedScript !== packageDist)
18556
18970
  throw new Error(
18557
18971
  `node9: daemon spawn aborted \u2014 argv[1] (${resolvedScript}) is outside package dist (${packageDist})`
18558
18972
  );
@@ -18574,10 +18988,10 @@ RAW: ${raw}
18574
18988
  });
18575
18989
  d.unref();
18576
18990
  } catch (spawnErr) {
18577
- const logPath = import_path35.default.join(import_os30.default.homedir(), ".node9", "hook-debug.log");
18991
+ const logPath = import_path37.default.join(import_os32.default.homedir(), ".node9", "hook-debug.log");
18578
18992
  const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
18579
18993
  try {
18580
- import_fs34.default.appendFileSync(
18994
+ import_fs36.default.appendFileSync(
18581
18995
  logPath,
18582
18996
  `[${(/* @__PURE__ */ new Date()).toISOString()}] daemon-autostart-failed: ${msg}
18583
18997
  `
@@ -18587,10 +19001,10 @@ RAW: ${raw}
18587
19001
  }
18588
19002
  }
18589
19003
  if (process.env.NODE9_DEBUG === "1" || config.settings.enableHookLogDebug) {
18590
- const logPath = import_path35.default.join(import_os30.default.homedir(), ".node9", "hook-debug.log");
18591
- if (!import_fs34.default.existsSync(import_path35.default.dirname(logPath)))
18592
- import_fs34.default.mkdirSync(import_path35.default.dirname(logPath), { recursive: true });
18593
- import_fs34.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
19004
+ const logPath = import_path37.default.join(import_os32.default.homedir(), ".node9", "hook-debug.log");
19005
+ if (!import_fs36.default.existsSync(import_path37.default.dirname(logPath)))
19006
+ import_fs36.default.mkdirSync(import_path37.default.dirname(logPath), { recursive: true });
19007
+ import_fs36.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] STDIN: ${raw}
18594
19008
  `);
18595
19009
  }
18596
19010
  const rawToolName = sanitize2(extractToolName(payload));
@@ -18604,8 +19018,8 @@ RAW: ${raw}
18604
19018
  const isHumanDecision = blockedByContext.toLowerCase().includes("user") || blockedByContext.toLowerCase().includes("daemon") || blockedByContext.toLowerCase().includes("decision");
18605
19019
  let ttyFd = null;
18606
19020
  try {
18607
- ttyFd = import_fs34.default.openSync("/dev/tty", "w");
18608
- const writeTty = (line) => import_fs34.default.writeSync(ttyFd, line + "\n");
19021
+ ttyFd = import_fs36.default.openSync("/dev/tty", "w");
19022
+ const writeTty = (line) => import_fs36.default.writeSync(ttyFd, line + "\n");
18609
19023
  if (blockedByContext.includes("DLP") || blockedByContext.includes("Secret Detected") || blockedByContext.includes("Credential Review")) {
18610
19024
  writeTty(import_chalk9.default.bgRed.white.bold(`
18611
19025
  \u{1F6A8} NODE9 DLP ALERT \u2014 CREDENTIAL DETECTED `));
@@ -18624,7 +19038,7 @@ RAW: ${raw}
18624
19038
  } finally {
18625
19039
  if (ttyFd !== null)
18626
19040
  try {
18627
- import_fs34.default.closeSync(ttyFd);
19041
+ import_fs36.default.closeSync(ttyFd);
18628
19042
  } catch {
18629
19043
  }
18630
19044
  }
@@ -18675,17 +19089,17 @@ RAW: ${raw}
18675
19089
  const safeSessionId = /^[A-Za-z0-9_\-]{1,128}$/.test(rawSessionId) ? rawSessionId : "";
18676
19090
  if (skillPinCfg.enabled && safeSessionId) {
18677
19091
  try {
18678
- const sessionsDir = import_path35.default.join(import_os30.default.homedir(), ".node9", "skill-sessions");
18679
- const flagPath = import_path35.default.join(sessionsDir, `${safeSessionId}.json`);
19092
+ const sessionsDir = import_path37.default.join(import_os32.default.homedir(), ".node9", "skill-sessions");
19093
+ const flagPath = import_path37.default.join(sessionsDir, `${safeSessionId}.json`);
18680
19094
  let flag = null;
18681
19095
  try {
18682
- flag = JSON.parse(import_fs34.default.readFileSync(flagPath, "utf-8"));
19096
+ flag = JSON.parse(import_fs36.default.readFileSync(flagPath, "utf-8"));
18683
19097
  } catch {
18684
19098
  }
18685
19099
  const writeFlag = (data2) => {
18686
19100
  try {
18687
- import_fs34.default.mkdirSync(sessionsDir, { recursive: true });
18688
- import_fs34.default.writeFileSync(
19101
+ import_fs36.default.mkdirSync(sessionsDir, { recursive: true });
19102
+ import_fs36.default.writeFileSync(
18689
19103
  flagPath,
18690
19104
  JSON.stringify({ ...data2, timestamp: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
18691
19105
  { mode: 384 }
@@ -18696,8 +19110,8 @@ RAW: ${raw}
18696
19110
  const sendSkillWarn = (detail, recoveryCmd) => {
18697
19111
  let ttyFd = null;
18698
19112
  try {
18699
- ttyFd = import_fs34.default.openSync("/dev/tty", "w");
18700
- const w = (line) => import_fs34.default.writeSync(ttyFd, line + "\n");
19113
+ ttyFd = import_fs36.default.openSync("/dev/tty", "w");
19114
+ const w = (line) => import_fs36.default.writeSync(ttyFd, line + "\n");
18701
19115
  w(import_chalk9.default.yellow(`
18702
19116
  \u26A0\uFE0F Node9: installed skill drift detected`));
18703
19117
  w(import_chalk9.default.gray(` ${detail}`));
@@ -18712,7 +19126,7 @@ RAW: ${raw}
18712
19126
  } finally {
18713
19127
  if (ttyFd !== null)
18714
19128
  try {
18715
- import_fs34.default.closeSync(ttyFd);
19129
+ import_fs36.default.closeSync(ttyFd);
18716
19130
  } catch {
18717
19131
  }
18718
19132
  }
@@ -18728,7 +19142,7 @@ RAW: ${raw}
18728
19142
  return;
18729
19143
  }
18730
19144
  if (!flag || flag.state !== "verified" && flag.state !== "warned") {
18731
- const absoluteCwd = typeof payloadCwd === "string" && import_path35.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
19145
+ const absoluteCwd = typeof payloadCwd === "string" && import_path37.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
18732
19146
  const extraRoots = skillPinCfg.roots;
18733
19147
  const resolvedExtra = extraRoots.map((r) => resolveUserSkillRoot(r, absoluteCwd)).filter((r) => typeof r === "string");
18734
19148
  const roots = [...defaultSkillRoots(absoluteCwd), ...resolvedExtra];
@@ -18769,10 +19183,10 @@ RAW: ${raw}
18769
19183
  }
18770
19184
  try {
18771
19185
  const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
18772
- for (const name of import_fs34.default.readdirSync(sessionsDir)) {
18773
- const p = import_path35.default.join(sessionsDir, name);
19186
+ for (const name of import_fs36.default.readdirSync(sessionsDir)) {
19187
+ const p = import_path37.default.join(sessionsDir, name);
18774
19188
  try {
18775
- if (import_fs34.default.statSync(p).mtimeMs < cutoff) import_fs34.default.unlinkSync(p);
19189
+ if (import_fs36.default.statSync(p).mtimeMs < cutoff) import_fs36.default.unlinkSync(p);
18776
19190
  } catch {
18777
19191
  }
18778
19192
  }
@@ -18782,9 +19196,9 @@ RAW: ${raw}
18782
19196
  } catch (err2) {
18783
19197
  if (process.env.NODE9_DEBUG === "1") {
18784
19198
  try {
18785
- const dbg = import_path35.default.join(import_os30.default.homedir(), ".node9", "hook-debug.log");
19199
+ const dbg = import_path37.default.join(import_os32.default.homedir(), ".node9", "hook-debug.log");
18786
19200
  const msg = err2 instanceof Error ? err2.message : String(err2);
18787
- import_fs34.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
19201
+ import_fs36.default.appendFileSync(dbg, `[${(/* @__PURE__ */ new Date()).toISOString()}] SKILL_PIN_ERROR: ${msg}
18788
19202
  `);
18789
19203
  } catch {
18790
19204
  }
@@ -18794,7 +19208,7 @@ RAW: ${raw}
18794
19208
  if (shouldSnapshot(toolName, toolInput, config)) {
18795
19209
  await createShadowSnapshot(toolName, toolInput, config.policy.snapshot.ignorePaths);
18796
19210
  }
18797
- const safeCwdForAuth = typeof payloadCwd === "string" && import_path35.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
19211
+ const safeCwdForAuth = typeof payloadCwd === "string" && import_path37.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
18798
19212
  const result = await authorizeHeadless(toolName, toolInput, meta, {
18799
19213
  cwd: safeCwdForAuth
18800
19214
  });
@@ -18806,12 +19220,12 @@ RAW: ${raw}
18806
19220
  }
18807
19221
  if (result.noApprovalMechanism && !isDaemonRunning() && !process.env.NODE9_NO_AUTO_DAEMON && !process.stdout.isTTY && config.settings.autoStartDaemon) {
18808
19222
  try {
18809
- const tty = import_fs34.default.openSync("/dev/tty", "w");
18810
- import_fs34.default.writeSync(
19223
+ const tty = import_fs36.default.openSync("/dev/tty", "w");
19224
+ import_fs36.default.writeSync(
18811
19225
  tty,
18812
19226
  import_chalk9.default.cyan("\n\u{1F6E1}\uFE0F Node9: Starting approval daemon automatically...\n")
18813
19227
  );
18814
- import_fs34.default.closeSync(tty);
19228
+ import_fs36.default.closeSync(tty);
18815
19229
  } catch {
18816
19230
  }
18817
19231
  const daemonReady = await autoStartDaemonAndWait();
@@ -18838,9 +19252,9 @@ RAW: ${raw}
18838
19252
  });
18839
19253
  } catch (err2) {
18840
19254
  if (process.env.NODE9_DEBUG === "1") {
18841
- const logPath = import_path35.default.join(import_os30.default.homedir(), ".node9", "hook-debug.log");
19255
+ const logPath = import_path37.default.join(import_os32.default.homedir(), ".node9", "hook-debug.log");
18842
19256
  const errMsg = err2 instanceof Error ? err2.message : String(err2);
18843
- import_fs34.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
19257
+ import_fs36.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] ERROR: ${errMsg}
18844
19258
  `);
18845
19259
  }
18846
19260
  process.exit(0);
@@ -18860,8 +19274,8 @@ RAW: ${raw}
18860
19274
  await processPayload(raw);
18861
19275
  };
18862
19276
  process.stdin.setEncoding("utf-8");
18863
- process.stdin.on("data", (chunk) => {
18864
- raw += chunk;
19277
+ process.stdin.on("data", (chunk2) => {
19278
+ raw += chunk2;
18865
19279
  if (inactivityTimer) clearTimeout(inactivityTimer);
18866
19280
  inactivityTimer = setTimeout(() => void done(), 2e3);
18867
19281
  });
@@ -18874,9 +19288,9 @@ RAW: ${raw}
18874
19288
  }
18875
19289
 
18876
19290
  // src/cli/commands/log.ts
18877
- var import_fs35 = __toESM(require("fs"));
18878
- var import_path36 = __toESM(require("path"));
18879
- var import_os31 = __toESM(require("os"));
19291
+ var import_fs37 = __toESM(require("fs"));
19292
+ var import_path38 = __toESM(require("path"));
19293
+ var import_os33 = __toESM(require("os"));
18880
19294
  init_audit();
18881
19295
  init_config();
18882
19296
  init_daemon();
@@ -18971,10 +19385,10 @@ function registerLogCommand(program2) {
18971
19385
  if (rawToolName !== tool) entry.agentToolName = rawToolName;
18972
19386
  const payloadSessionId = payload.session_id ?? payload.conversationId;
18973
19387
  if (payloadSessionId) entry.sessionId = payloadSessionId;
18974
- const logPath = import_path36.default.join(import_os31.default.homedir(), ".node9", "audit.log");
18975
- if (!import_fs35.default.existsSync(import_path36.default.dirname(logPath)))
18976
- import_fs35.default.mkdirSync(import_path36.default.dirname(logPath), { recursive: true });
18977
- import_fs35.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
19388
+ const logPath = import_path38.default.join(import_os33.default.homedir(), ".node9", "audit.log");
19389
+ if (!import_fs37.default.existsSync(import_path38.default.dirname(logPath)))
19390
+ import_fs37.default.mkdirSync(import_path38.default.dirname(logPath), { recursive: true });
19391
+ import_fs37.default.appendFileSync(logPath, JSON.stringify(entry) + "\n");
18978
19392
  if ((tool === "Bash" || tool === "bash") && isDaemonRunning()) {
18979
19393
  const command = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
18980
19394
  if (command) {
@@ -19008,7 +19422,7 @@ function registerLogCommand(program2) {
19008
19422
  }
19009
19423
  }
19010
19424
  const payloadCwd = typeof payload.cwd === "string" ? payload.cwd : Array.isArray(payload.workspacePaths) && typeof payload.workspacePaths[0] === "string" ? payload.workspacePaths[0] : void 0;
19011
- const safeCwd = typeof payloadCwd === "string" && import_path36.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
19425
+ const safeCwd = typeof payloadCwd === "string" && import_path38.default.isAbsolute(payloadCwd) ? payloadCwd : void 0;
19012
19426
  const config = getConfig(safeCwd);
19013
19427
  if ((tool === "Bash" || tool === "bash") && config.settings.enableUndo !== false) {
19014
19428
  const bashCommand = typeof rawInput === "object" && rawInput !== null && "command" in rawInput && typeof rawInput.command === "string" ? rawInput.command : null;
@@ -19029,9 +19443,9 @@ function registerLogCommand(program2) {
19029
19443
  const msg = err2 instanceof Error ? err2.message : String(err2);
19030
19444
  process.stderr.write(`[Node9] audit log error: ${msg}
19031
19445
  `);
19032
- const debugPath = import_path36.default.join(import_os31.default.homedir(), ".node9", "hook-debug.log");
19446
+ const debugPath = import_path38.default.join(import_os33.default.homedir(), ".node9", "hook-debug.log");
19033
19447
  try {
19034
- import_fs35.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
19448
+ import_fs37.default.appendFileSync(debugPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] LOG_ERROR: ${msg}
19035
19449
  `);
19036
19450
  } catch {
19037
19451
  }
@@ -19043,7 +19457,7 @@ function registerLogCommand(program2) {
19043
19457
  } else {
19044
19458
  let raw = "";
19045
19459
  process.stdin.setEncoding("utf-8");
19046
- process.stdin.on("data", (chunk) => raw += chunk);
19460
+ process.stdin.on("data", (chunk2) => raw += chunk2);
19047
19461
  process.stdin.on("end", () => {
19048
19462
  void logPayload(raw);
19049
19463
  });
@@ -19071,7 +19485,7 @@ function httpsFetch(url) {
19071
19485
  return;
19072
19486
  }
19073
19487
  const chunks = [];
19074
- res.on("data", (chunk) => chunks.push(chunk));
19488
+ res.on("data", (chunk2) => chunks.push(chunk2));
19075
19489
  res.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
19076
19490
  res.on("error", reject);
19077
19491
  }).on("error", reject);
@@ -19431,15 +19845,15 @@ function registerConfigShowCommand(program2) {
19431
19845
 
19432
19846
  // src/cli/commands/doctor.ts
19433
19847
  var import_chalk11 = __toESM(require("chalk"));
19434
- var import_fs36 = __toESM(require("fs"));
19435
- var import_path37 = __toESM(require("path"));
19436
- var import_os32 = __toESM(require("os"));
19848
+ var import_fs38 = __toESM(require("fs"));
19849
+ var import_path39 = __toESM(require("path"));
19850
+ var import_os34 = __toESM(require("os"));
19437
19851
  var import_child_process8 = require("child_process");
19438
19852
  init_daemon();
19439
19853
  init_config();
19440
19854
  function registerDoctorCommand(program2, version2) {
19441
19855
  program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
19442
- const homeDir2 = import_os32.default.homedir();
19856
+ const homeDir2 = import_os34.default.homedir();
19443
19857
  let failures = 0;
19444
19858
  function pass(msg) {
19445
19859
  console.log(import_chalk11.default.green(" \u2705 ") + msg);
@@ -19488,10 +19902,10 @@ function registerDoctorCommand(program2, version2) {
19488
19902
  );
19489
19903
  }
19490
19904
  section("Configuration");
19491
- const globalConfigPath = import_path37.default.join(homeDir2, ".node9", "config.json");
19492
- if (import_fs36.default.existsSync(globalConfigPath)) {
19905
+ const globalConfigPath = import_path39.default.join(homeDir2, ".node9", "config.json");
19906
+ if (import_fs38.default.existsSync(globalConfigPath)) {
19493
19907
  try {
19494
- JSON.parse(import_fs36.default.readFileSync(globalConfigPath, "utf-8"));
19908
+ JSON.parse(import_fs38.default.readFileSync(globalConfigPath, "utf-8"));
19495
19909
  pass("~/.node9/config.json found and valid");
19496
19910
  } catch {
19497
19911
  fail("~/.node9/config.json is invalid JSON", "Run: node9 init --force");
@@ -19499,10 +19913,10 @@ function registerDoctorCommand(program2, version2) {
19499
19913
  } else {
19500
19914
  warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
19501
19915
  }
19502
- const projectConfigPath = import_path37.default.join(process.cwd(), "node9.config.json");
19503
- if (import_fs36.default.existsSync(projectConfigPath)) {
19916
+ const projectConfigPath = import_path39.default.join(process.cwd(), "node9.config.json");
19917
+ if (import_fs38.default.existsSync(projectConfigPath)) {
19504
19918
  try {
19505
- JSON.parse(import_fs36.default.readFileSync(projectConfigPath, "utf-8"));
19919
+ JSON.parse(import_fs38.default.readFileSync(projectConfigPath, "utf-8"));
19506
19920
  pass("node9.config.json found and valid (project)");
19507
19921
  } catch {
19508
19922
  fail(
@@ -19511,8 +19925,8 @@ function registerDoctorCommand(program2, version2) {
19511
19925
  );
19512
19926
  }
19513
19927
  }
19514
- const credsPath = import_path37.default.join(homeDir2, ".node9", "credentials.json");
19515
- if (import_fs36.default.existsSync(credsPath)) {
19928
+ const credsPath = import_path39.default.join(homeDir2, ".node9", "credentials.json");
19929
+ if (import_fs38.default.existsSync(credsPath)) {
19516
19930
  pass("Cloud credentials found (~/.node9/credentials.json)");
19517
19931
  } else {
19518
19932
  warn(
@@ -19521,10 +19935,10 @@ function registerDoctorCommand(program2, version2) {
19521
19935
  );
19522
19936
  }
19523
19937
  section("Agent Hooks");
19524
- const claudeSettingsPath = import_path37.default.join(homeDir2, ".claude", "settings.json");
19525
- if (import_fs36.default.existsSync(claudeSettingsPath)) {
19938
+ const claudeSettingsPath = import_path39.default.join(homeDir2, ".claude", "settings.json");
19939
+ if (import_fs38.default.existsSync(claudeSettingsPath)) {
19526
19940
  try {
19527
- const cs = JSON.parse(import_fs36.default.readFileSync(claudeSettingsPath, "utf-8"));
19941
+ const cs = JSON.parse(import_fs38.default.readFileSync(claudeSettingsPath, "utf-8"));
19528
19942
  const hasHook = cs.hooks?.PreToolUse?.some(
19529
19943
  (m) => m.hooks.some((h) => h.command?.includes("node9") || h.command?.includes("cli.js"))
19530
19944
  );
@@ -19540,10 +19954,10 @@ function registerDoctorCommand(program2, version2) {
19540
19954
  } else {
19541
19955
  warn("Claude Code \u2014 not configured", "Run: node9 setup claude");
19542
19956
  }
19543
- const geminiSettingsPath = import_path37.default.join(homeDir2, ".gemini", "settings.json");
19544
- if (import_fs36.default.existsSync(geminiSettingsPath)) {
19957
+ const geminiSettingsPath = import_path39.default.join(homeDir2, ".gemini", "settings.json");
19958
+ if (import_fs38.default.existsSync(geminiSettingsPath)) {
19545
19959
  try {
19546
- const gs = JSON.parse(import_fs36.default.readFileSync(geminiSettingsPath, "utf-8"));
19960
+ const gs = JSON.parse(import_fs38.default.readFileSync(geminiSettingsPath, "utf-8"));
19547
19961
  const hasHook = gs.hooks?.BeforeTool?.some(
19548
19962
  (m) => m.hooks.some((h) => h.command?.includes("node9") || h.command?.includes("cli.js"))
19549
19963
  );
@@ -19559,10 +19973,10 @@ function registerDoctorCommand(program2, version2) {
19559
19973
  } else {
19560
19974
  warn("Gemini CLI \u2014 not configured", "Run: node9 setup gemini (skip if not using Gemini)");
19561
19975
  }
19562
- const cursorHooksPath = import_path37.default.join(homeDir2, ".cursor", "hooks.json");
19563
- if (import_fs36.default.existsSync(cursorHooksPath)) {
19976
+ const cursorHooksPath = import_path39.default.join(homeDir2, ".cursor", "hooks.json");
19977
+ if (import_fs38.default.existsSync(cursorHooksPath)) {
19564
19978
  try {
19565
- const cur = JSON.parse(import_fs36.default.readFileSync(cursorHooksPath, "utf-8"));
19979
+ const cur = JSON.parse(import_fs38.default.readFileSync(cursorHooksPath, "utf-8"));
19566
19980
  const hasHook = cur.hooks?.preToolUse?.some(
19567
19981
  (h) => h.command?.includes("node9") || h.command?.includes("cli.js")
19568
19982
  );
@@ -19593,7 +20007,7 @@ function registerDoctorCommand(program2, version2) {
19593
20007
  try {
19594
20008
  const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
19595
20009
  const cfg = getConfig();
19596
- const creds = import_fs36.default.existsSync(import_path37.default.join(import_os32.default.homedir(), ".node9", "credentials.json"));
20010
+ const creds = import_fs38.default.existsSync(import_path39.default.join(import_os34.default.homedir(), ".node9", "credentials.json"));
19597
20011
  if (!creds) {
19598
20012
  warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
19599
20013
  } else if (!cfg.settings.approvers.cloud) {
@@ -19643,9 +20057,9 @@ function registerDoctorCommand(program2, version2) {
19643
20057
 
19644
20058
  // src/cli/commands/audit.ts
19645
20059
  var import_chalk12 = __toESM(require("chalk"));
19646
- var import_fs37 = __toESM(require("fs"));
19647
- var import_path38 = __toESM(require("path"));
19648
- var import_os33 = __toESM(require("os"));
20060
+ var import_fs39 = __toESM(require("fs"));
20061
+ var import_path40 = __toESM(require("path"));
20062
+ var import_os35 = __toESM(require("os"));
19649
20063
  function formatRelativeTime(timestamp) {
19650
20064
  const diff = Date.now() - new Date(timestamp).getTime();
19651
20065
  const sec = Math.floor(diff / 1e3);
@@ -19658,14 +20072,14 @@ function formatRelativeTime(timestamp) {
19658
20072
  }
19659
20073
  function registerAuditCommand(program2) {
19660
20074
  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) => {
19661
- const logPath = import_path38.default.join(import_os33.default.homedir(), ".node9", "audit.log");
19662
- if (!import_fs37.default.existsSync(logPath)) {
20075
+ const logPath = import_path40.default.join(import_os35.default.homedir(), ".node9", "audit.log");
20076
+ if (!import_fs39.default.existsSync(logPath)) {
19663
20077
  console.log(
19664
20078
  import_chalk12.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
19665
20079
  );
19666
20080
  return;
19667
20081
  }
19668
- const raw = import_fs37.default.readFileSync(logPath, "utf-8");
20082
+ const raw = import_fs39.default.readFileSync(logPath, "utf-8");
19669
20083
  const lines = raw.split("\n").filter((l) => l.trim() !== "");
19670
20084
  let entries = lines.flatMap((line) => {
19671
20085
  try {
@@ -19721,9 +20135,9 @@ function registerAuditCommand(program2) {
19721
20135
  var import_chalk13 = __toESM(require("chalk"));
19722
20136
 
19723
20137
  // src/cli/aggregate/report-audit.ts
19724
- var import_fs38 = __toESM(require("fs"));
19725
- var import_os34 = __toESM(require("os"));
19726
- var import_path39 = __toESM(require("path"));
20138
+ var import_fs40 = __toESM(require("fs"));
20139
+ var import_os36 = __toESM(require("os"));
20140
+ var import_path41 = __toESM(require("path"));
19727
20141
  init_costSync();
19728
20142
  init_litellm();
19729
20143
  var TEST_COMMAND_RE3 = /(?:^|\s)(npm\s+(?:run\s+)?test|npx\s+(?:vitest|jest|mocha)|yarn\s+(?:run\s+)?test|pnpm\s+(?:run\s+)?test|vitest|jest|mocha|pytest|py\.test|cargo\s+test|go\s+test|bundle\s+exec\s+rspec|rspec|phpunit|dotnet\s+test)\b/i;
@@ -19805,8 +20219,8 @@ function getDateRange(period, now) {
19805
20219
  }
19806
20220
  }
19807
20221
  function parseAuditLog(logPath) {
19808
- if (!import_fs38.default.existsSync(logPath)) return [];
19809
- const raw = import_fs38.default.readFileSync(logPath, "utf-8");
20222
+ if (!import_fs40.default.existsSync(logPath)) return [];
20223
+ const raw = import_fs40.default.readFileSync(logPath, "utf-8");
19810
20224
  return raw.split("\n").flatMap((line) => {
19811
20225
  if (!line.trim()) return [];
19812
20226
  try {
@@ -19866,25 +20280,25 @@ function freezeClaudeCost(acc) {
19866
20280
  };
19867
20281
  }
19868
20282
  function processClaudeCostProject(proj, projectsDir, start, end, acc) {
19869
- const projPath = import_path39.default.join(projectsDir, proj);
20283
+ const projPath = import_path41.default.join(projectsDir, proj);
19870
20284
  let files;
19871
20285
  try {
19872
- const stat = import_fs38.default.statSync(projPath);
20286
+ const stat = import_fs40.default.statSync(projPath);
19873
20287
  if (!stat.isDirectory()) return;
19874
- files = import_fs38.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
20288
+ files = import_fs40.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
19875
20289
  } catch {
19876
20290
  return;
19877
20291
  }
19878
20292
  const startMs = start.getTime();
19879
20293
  for (const file of files) {
19880
- const filePath = import_path39.default.join(projPath, file);
20294
+ const filePath = import_path41.default.join(projPath, file);
19881
20295
  try {
19882
- if (import_fs38.default.statSync(filePath).mtimeMs < startMs) continue;
20296
+ if (import_fs40.default.statSync(filePath).mtimeMs < startMs) continue;
19883
20297
  } catch {
19884
20298
  continue;
19885
20299
  }
19886
20300
  try {
19887
- const raw = import_fs38.default.readFileSync(filePath, "utf-8");
20301
+ const raw = import_fs40.default.readFileSync(filePath, "utf-8");
19888
20302
  for (const line of raw.split("\n")) {
19889
20303
  if (!line.trim()) continue;
19890
20304
  let entry;
@@ -19934,10 +20348,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
19934
20348
  }
19935
20349
  function loadClaudeCost(start, end, projectsDir) {
19936
20350
  const acc = emptyClaudeCostAccumulator();
19937
- if (!import_fs38.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
20351
+ if (!import_fs40.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
19938
20352
  let dirs;
19939
20353
  try {
19940
- dirs = import_fs38.default.readdirSync(projectsDir);
20354
+ dirs = import_fs40.default.readdirSync(projectsDir);
19941
20355
  } catch {
19942
20356
  return freezeClaudeCost(acc);
19943
20357
  }
@@ -19949,7 +20363,7 @@ function loadClaudeCost(start, end, projectsDir) {
19949
20363
  function processCodexCostFile(filePath, start, end, acc) {
19950
20364
  let lines;
19951
20365
  try {
19952
- lines = import_fs38.default.readFileSync(filePath, "utf-8").split("\n");
20366
+ lines = import_fs40.default.readFileSync(filePath, "utf-8").split("\n");
19953
20367
  } catch {
19954
20368
  return;
19955
20369
  }
@@ -19992,33 +20406,33 @@ function processCodexCostFile(filePath, start, end, acc) {
19992
20406
  const dateKey = sessionStart2.slice(0, 10);
19993
20407
  acc.byDay.set(dateKey, (acc.byDay.get(dateKey) ?? 0) + cost);
19994
20408
  }
19995
- function listCodexSessionFiles(sessionsBase) {
20409
+ function listCodexSessionFiles2(sessionsBase) {
19996
20410
  const jsonlFiles = [];
19997
- if (!import_fs38.default.existsSync(sessionsBase)) return jsonlFiles;
20411
+ if (!import_fs40.default.existsSync(sessionsBase)) return jsonlFiles;
19998
20412
  try {
19999
- for (const year of import_fs38.default.readdirSync(sessionsBase)) {
20000
- const yearPath = import_path39.default.join(sessionsBase, year);
20413
+ for (const year of import_fs40.default.readdirSync(sessionsBase)) {
20414
+ const yearPath = import_path41.default.join(sessionsBase, year);
20001
20415
  try {
20002
- if (!import_fs38.default.statSync(yearPath).isDirectory()) continue;
20416
+ if (!import_fs40.default.statSync(yearPath).isDirectory()) continue;
20003
20417
  } catch {
20004
20418
  continue;
20005
20419
  }
20006
- for (const month of import_fs38.default.readdirSync(yearPath)) {
20007
- const monthPath = import_path39.default.join(yearPath, month);
20420
+ for (const month of import_fs40.default.readdirSync(yearPath)) {
20421
+ const monthPath = import_path41.default.join(yearPath, month);
20008
20422
  try {
20009
- if (!import_fs38.default.statSync(monthPath).isDirectory()) continue;
20423
+ if (!import_fs40.default.statSync(monthPath).isDirectory()) continue;
20010
20424
  } catch {
20011
20425
  continue;
20012
20426
  }
20013
- for (const day of import_fs38.default.readdirSync(monthPath)) {
20014
- const dayPath = import_path39.default.join(monthPath, day);
20427
+ for (const day of import_fs40.default.readdirSync(monthPath)) {
20428
+ const dayPath = import_path41.default.join(monthPath, day);
20015
20429
  try {
20016
- if (!import_fs38.default.statSync(dayPath).isDirectory()) continue;
20430
+ if (!import_fs40.default.statSync(dayPath).isDirectory()) continue;
20017
20431
  } catch {
20018
20432
  continue;
20019
20433
  }
20020
- for (const file of import_fs38.default.readdirSync(dayPath)) {
20021
- if (file.endsWith(".jsonl")) jsonlFiles.push(import_path39.default.join(dayPath, file));
20434
+ for (const file of import_fs40.default.readdirSync(dayPath)) {
20435
+ if (file.endsWith(".jsonl")) jsonlFiles.push(import_path41.default.join(dayPath, file));
20022
20436
  }
20023
20437
  }
20024
20438
  }
@@ -20030,17 +20444,17 @@ function listCodexSessionFiles(sessionsBase) {
20030
20444
  }
20031
20445
  function loadCodexCost(start, end, sessionsBase) {
20032
20446
  const acc = { total: 0, toolCalls: 0, byDay: /* @__PURE__ */ new Map() };
20033
- const files = listCodexSessionFiles(sessionsBase);
20447
+ const files = listCodexSessionFiles2(sessionsBase);
20034
20448
  for (const filePath of files) {
20035
20449
  processCodexCostFile(filePath, start, end, acc);
20036
20450
  }
20037
20451
  return { total: acc.total, byDay: acc.byDay, toolCalls: acc.toolCalls };
20038
20452
  }
20039
- var GEMINI_FALLBACK_MODELS = ["gemini-2.5-flash", "gemini-2.0-flash"];
20040
- function geminiPriceFor(model) {
20453
+ var GEMINI_FALLBACK_MODELS2 = ["gemini-2.5-flash", "gemini-2.0-flash"];
20454
+ function geminiPriceFor2(model) {
20041
20455
  let tuple = pricingFor(model);
20042
20456
  if (!tuple && /^gemini-/i.test(model)) {
20043
- for (const proxy of GEMINI_FALLBACK_MODELS) {
20457
+ for (const proxy of GEMINI_FALLBACK_MODELS2) {
20044
20458
  tuple = pricingFor(proxy);
20045
20459
  if (tuple) break;
20046
20460
  }
@@ -20071,13 +20485,13 @@ function freezeGeminiCost(acc) {
20071
20485
  function processGeminiCostFile(filePath, projectKey, start, end, acc) {
20072
20486
  const startMs = start.getTime();
20073
20487
  try {
20074
- if (import_fs38.default.statSync(filePath).mtimeMs < startMs) return;
20488
+ if (import_fs40.default.statSync(filePath).mtimeMs < startMs) return;
20075
20489
  } catch {
20076
20490
  return;
20077
20491
  }
20078
20492
  let raw;
20079
20493
  try {
20080
- raw = import_fs38.default.readFileSync(filePath, "utf-8");
20494
+ raw = import_fs40.default.readFileSync(filePath, "utf-8");
20081
20495
  } catch {
20082
20496
  return;
20083
20497
  }
@@ -20098,7 +20512,7 @@ function processGeminiCostFile(filePath, projectKey, start, end, acc) {
20098
20512
  }
20099
20513
  const ts = new Date(entry.timestamp);
20100
20514
  if (ts < start || ts > end) continue;
20101
- const price = geminiPriceFor(entry.model);
20515
+ const price = geminiPriceFor2(entry.model);
20102
20516
  if (!price) continue;
20103
20517
  const inp = entry.tokens.input ?? 0;
20104
20518
  const out = entry.tokens.output ?? 0;
@@ -20122,46 +20536,46 @@ function processGeminiCostFile(filePath, projectKey, start, end, acc) {
20122
20536
  acc.byProject.set(projectKey, rollup);
20123
20537
  }
20124
20538
  }
20125
- function listGeminiSessionFiles(geminiTmpDir) {
20539
+ function listGeminiSessionFiles2(geminiTmpDir2) {
20126
20540
  const out = [];
20127
20541
  let dirs;
20128
20542
  try {
20129
- if (!import_fs38.default.statSync(geminiTmpDir).isDirectory()) return out;
20130
- dirs = import_fs38.default.readdirSync(geminiTmpDir);
20543
+ if (!import_fs40.default.statSync(geminiTmpDir2).isDirectory()) return out;
20544
+ dirs = import_fs40.default.readdirSync(geminiTmpDir2);
20131
20545
  } catch {
20132
20546
  return out;
20133
20547
  }
20134
20548
  for (const proj of dirs) {
20135
- const chatsDir = import_path39.default.join(geminiTmpDir, proj, "chats");
20549
+ const chatsDir = import_path41.default.join(geminiTmpDir2, proj, "chats");
20136
20550
  let files;
20137
20551
  try {
20138
- if (!import_fs38.default.statSync(chatsDir).isDirectory()) continue;
20139
- files = import_fs38.default.readdirSync(chatsDir);
20552
+ if (!import_fs40.default.statSync(chatsDir).isDirectory()) continue;
20553
+ files = import_fs40.default.readdirSync(chatsDir);
20140
20554
  } catch {
20141
20555
  continue;
20142
20556
  }
20143
20557
  for (const f of files) {
20144
20558
  if (!f.endsWith(".jsonl")) continue;
20145
- out.push({ projectKey: proj, file: import_path39.default.join(chatsDir, f) });
20559
+ out.push({ projectKey: proj, file: import_path41.default.join(chatsDir, f) });
20146
20560
  }
20147
20561
  }
20148
20562
  return out;
20149
20563
  }
20150
- function loadGeminiCost(start, end, geminiTmpDir) {
20564
+ function loadGeminiCost(start, end, geminiTmpDir2) {
20151
20565
  const acc = emptyGeminiAccumulator();
20152
- if (!import_fs38.default.existsSync(geminiTmpDir)) return freezeGeminiCost(acc);
20153
- for (const { projectKey, file } of listGeminiSessionFiles(geminiTmpDir)) {
20566
+ if (!import_fs40.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
20567
+ for (const { projectKey, file } of listGeminiSessionFiles2(geminiTmpDir2)) {
20154
20568
  processGeminiCostFile(file, projectKey, start, end, acc);
20155
20569
  }
20156
20570
  return freezeGeminiCost(acc);
20157
20571
  }
20158
20572
  function aggregateReportFromAudit(period, opts = {}) {
20159
20573
  const now = opts.now ?? /* @__PURE__ */ new Date();
20160
- const auditLogPath = opts.auditLogPath ?? import_path39.default.join(import_os34.default.homedir(), ".node9", "audit.log");
20161
- const claudeProjectsDir = opts.claudeProjectsDir ?? import_path39.default.join(import_os34.default.homedir(), ".claude", "projects");
20162
- const codexSessionsDir = opts.codexSessionsDir ?? import_path39.default.join(import_os34.default.homedir(), ".codex", "sessions");
20163
- const geminiTmpDir = opts.geminiTmpDir ?? import_path39.default.join(import_os34.default.homedir(), ".gemini", "tmp");
20164
- const hasAuditFile = import_fs38.default.existsSync(auditLogPath);
20574
+ const auditLogPath = opts.auditLogPath ?? import_path41.default.join(import_os36.default.homedir(), ".node9", "audit.log");
20575
+ const claudeProjectsDir = opts.claudeProjectsDir ?? import_path41.default.join(import_os36.default.homedir(), ".claude", "projects");
20576
+ const codexSessionsDir2 = opts.codexSessionsDir ?? import_path41.default.join(import_os36.default.homedir(), ".codex", "sessions");
20577
+ const geminiTmpDir2 = opts.geminiTmpDir ?? import_path41.default.join(import_os36.default.homedir(), ".gemini", "tmp");
20578
+ const hasAuditFile = import_fs40.default.existsSync(auditLogPath);
20165
20579
  const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
20166
20580
  const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
20167
20581
  const { start, end } = getDateRange(period, now);
@@ -20178,8 +20592,8 @@ function aggregateReportFromAudit(period, opts = {}) {
20178
20592
  };
20179
20593
  });
20180
20594
  const claudeCost = opts.preloadedClaudeCost ?? loadClaudeCost(start, end, claudeProjectsDir);
20181
- const codexCost = opts.preloadedCodexCost ?? loadCodexCost(start, end, codexSessionsDir);
20182
- const geminiCost = opts.preloadedGeminiCost ?? loadGeminiCost(start, end, geminiTmpDir);
20595
+ const codexCost = opts.preloadedCodexCost ?? loadCodexCost(start, end, codexSessionsDir2);
20596
+ const geminiCost = opts.preloadedGeminiCost ?? loadGeminiCost(start, end, geminiTmpDir2);
20183
20597
  for (const [day, c] of codexCost.byDay) {
20184
20598
  claudeCost.byDay.set(day, (claudeCost.byDay.get(day) ?? 0) + c);
20185
20599
  }
@@ -20857,21 +21271,48 @@ function registerDaemonCommand(program2) {
20857
21271
 
20858
21272
  // src/cli/commands/status.ts
20859
21273
  var import_chalk15 = __toESM(require("chalk"));
20860
- var import_fs39 = __toESM(require("fs"));
20861
- var import_path40 = __toESM(require("path"));
20862
- var import_os35 = __toESM(require("os"));
21274
+ var import_fs41 = __toESM(require("fs"));
21275
+ var import_path42 = __toESM(require("path"));
21276
+ var import_os37 = __toESM(require("os"));
21277
+ var yaml2 = __toESM(require("yaml"));
20863
21278
  init_core();
20864
21279
  init_daemon();
21280
+ init_setup();
21281
+ function readHermesHooks(configPath) {
21282
+ if (!import_fs41.default.existsSync(configPath)) return null;
21283
+ let raw;
21284
+ try {
21285
+ raw = import_fs41.default.readFileSync(configPath, "utf-8");
21286
+ } catch {
21287
+ return null;
21288
+ }
21289
+ try {
21290
+ const cfg = yaml2.parse(raw);
21291
+ const has = (event) => (cfg?.hooks?.[event] ?? []).some(
21292
+ (e) => typeof e?.command === "string" && isNode9Hook(e.command)
21293
+ );
21294
+ return { pre: has("pre_tool_call"), post: has("post_tool_call") };
21295
+ } catch {
21296
+ console.error(
21297
+ import_chalk15.default.yellow(
21298
+ ` \u26A0\uFE0F Hermes config.yaml at ${configPath} is not valid YAML \u2014 showing as unwired.`
21299
+ )
21300
+ );
21301
+ return { pre: false, post: false };
21302
+ }
21303
+ }
20865
21304
  function readJson2(filePath) {
20866
21305
  try {
20867
- if (import_fs39.default.existsSync(filePath)) return JSON.parse(import_fs39.default.readFileSync(filePath, "utf-8"));
21306
+ if (import_fs41.default.existsSync(filePath)) return JSON.parse(import_fs41.default.readFileSync(filePath, "utf-8"));
20868
21307
  } catch {
20869
21308
  }
20870
21309
  return null;
20871
21310
  }
20872
- function isNode9Hook2(cmd) {
20873
- if (!cmd) return false;
20874
- return /(?:^|[\s/\\])node9 (?:check|log)/.test(cmd) || /(?:^|[\s/\\])cli\.js (?:check|log)/.test(cmd);
21311
+ function matchersHaveNode9Hook(matchers) {
21312
+ return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
21313
+ }
21314
+ function flatHaveNode9Hook(entries) {
21315
+ return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
20875
21316
  }
20876
21317
  function wrappedMcpServers(servers) {
20877
21318
  if (!servers) return [];
@@ -20886,6 +21327,7 @@ function printAgentSection(label, hookPairs, wrapped) {
20886
21327
  console.log(import_chalk15.default.red(` \u2717 ${name}`) + import_chalk15.default.gray(" (not wired)"));
20887
21328
  }
20888
21329
  }
21330
+ if (wrapped === null) return;
20889
21331
  if (wrapped.length > 0) {
20890
21332
  console.log(import_chalk15.default.cyan(` MCP proxied:`));
20891
21333
  for (const entry of wrapped) {
@@ -20929,40 +21371,51 @@ function registerStatusCommand(program2) {
20929
21371
  console.log("");
20930
21372
  const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
20931
21373
  console.log(` Mode: ${modeLabel}`);
20932
- const projectConfig = import_path40.default.join(process.cwd(), "node9.config.json");
20933
- const globalConfig = import_path40.default.join(import_os35.default.homedir(), ".node9", "config.json");
21374
+ const projectConfig = import_path42.default.join(process.cwd(), "node9.config.json");
21375
+ const globalConfig = import_path42.default.join(import_os37.default.homedir(), ".node9", "config.json");
20934
21376
  console.log(
20935
- ` Local: ${import_fs39.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
21377
+ ` Local: ${import_fs41.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
20936
21378
  );
20937
21379
  console.log(
20938
- ` Global: ${import_fs39.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
21380
+ ` Global: ${import_fs41.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
20939
21381
  );
20940
21382
  if (mergedConfig.policy.sandboxPaths.length > 0) {
20941
21383
  console.log(
20942
21384
  ` Sandbox: ${import_chalk15.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
20943
21385
  );
20944
21386
  }
20945
- const homeDir2 = import_os35.default.homedir();
21387
+ const homeDir2 = import_os37.default.homedir();
20946
21388
  const claudeSettings = readJson2(
20947
- import_path40.default.join(homeDir2, ".claude", "settings.json")
21389
+ import_path42.default.join(homeDir2, ".claude", "settings.json")
20948
21390
  );
20949
- const claudeConfig = readJson2(import_path40.default.join(homeDir2, ".claude.json"));
21391
+ const claudeConfig = readJson2(import_path42.default.join(homeDir2, ".claude.json"));
20950
21392
  const geminiSettings = readJson2(
20951
- import_path40.default.join(homeDir2, ".gemini", "settings.json")
21393
+ import_path42.default.join(homeDir2, ".gemini", "settings.json")
21394
+ );
21395
+ const cursorConfig = readJson2(import_path42.default.join(homeDir2, ".cursor", "mcp.json"));
21396
+ const antigravityHooks = readJson2(
21397
+ import_path42.default.join(homeDir2, ".gemini", "config", "hooks.json")
21398
+ );
21399
+ const antigravityMcp = readJson2(
21400
+ import_path42.default.join(homeDir2, ".gemini", "config", "mcp_config.json")
21401
+ );
21402
+ const antigravityPresent = antigravityHooks !== null || import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".gemini", "antigravity-cli")) || import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".gemini", "antigravity-ide"));
21403
+ const copilotHooks = readJson2(
21404
+ import_path42.default.join(homeDir2, ".copilot", "hooks", "node9.json")
20952
21405
  );
20953
- const cursorConfig = readJson2(import_path40.default.join(homeDir2, ".cursor", "mcp.json"));
20954
- const agentFound = claudeSettings || claudeConfig || geminiSettings || cursorConfig;
21406
+ const copilotMcp = readJson2(
21407
+ import_path42.default.join(homeDir2, ".copilot", "mcp-config.json")
21408
+ );
21409
+ const copilotPresent = import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".copilot"));
21410
+ const hermesHooks = readHermesHooks(hermesConfigPath(homeDir2));
21411
+ const agentFound = claudeSettings || claudeConfig || geminiSettings || cursorConfig || antigravityPresent || copilotPresent || hermesHooks;
20955
21412
  if (agentFound) {
20956
21413
  console.log("");
20957
21414
  console.log(import_chalk15.default.bold(" Agent Wiring:"));
20958
21415
  console.log("");
20959
21416
  if (claudeSettings || claudeConfig) {
20960
- const preHook = claudeSettings?.hooks?.PreToolUse?.some(
20961
- (m) => m.hooks.some((h) => isNode9Hook2(h.command))
20962
- ) ?? false;
20963
- const postHook = claudeSettings?.hooks?.PostToolUse?.some(
20964
- (m) => m.hooks.some((h) => isNode9Hook2(h.command))
20965
- ) ?? false;
21417
+ const preHook = matchersHaveNode9Hook(claudeSettings?.hooks?.PreToolUse);
21418
+ const postHook = matchersHaveNode9Hook(claudeSettings?.hooks?.PostToolUse);
20966
21419
  printAgentSection(
20967
21420
  "Claude Code",
20968
21421
  [
@@ -20974,12 +21427,8 @@ function registerStatusCommand(program2) {
20974
21427
  console.log("");
20975
21428
  }
20976
21429
  if (geminiSettings) {
20977
- const beforeHook = geminiSettings.hooks?.BeforeTool?.some(
20978
- (m) => m.hooks.some((h) => isNode9Hook2(h.command))
20979
- ) ?? false;
20980
- const afterHook = geminiSettings.hooks?.AfterTool?.some(
20981
- (m) => m.hooks.some((h) => isNode9Hook2(h.command))
20982
- ) ?? false;
21430
+ const beforeHook = matchersHaveNode9Hook(geminiSettings.hooks?.BeforeTool);
21431
+ const afterHook = matchersHaveNode9Hook(geminiSettings.hooks?.AfterTool);
20983
21432
  printAgentSection(
20984
21433
  "Gemini CLI",
20985
21434
  [
@@ -20990,10 +21439,50 @@ function registerStatusCommand(program2) {
20990
21439
  );
20991
21440
  console.log("");
20992
21441
  }
21442
+ if (antigravityPresent) {
21443
+ const preHook = matchersHaveNode9Hook(antigravityHooks?.hooks?.PreToolUse);
21444
+ const postHook = matchersHaveNode9Hook(antigravityHooks?.hooks?.PostToolUse);
21445
+ printAgentSection(
21446
+ "Antigravity",
21447
+ [
21448
+ { name: "PreToolUse (node9 check)", present: preHook },
21449
+ { name: "PostToolUse (node9 log)", present: postHook }
21450
+ ],
21451
+ wrappedMcpServers(antigravityMcp?.mcpServers)
21452
+ );
21453
+ console.log("");
21454
+ }
21455
+ if (copilotPresent) {
21456
+ const preHook = flatHaveNode9Hook(copilotHooks?.hooks?.PreToolUse);
21457
+ const postHook = flatHaveNode9Hook(copilotHooks?.hooks?.PostToolUse);
21458
+ const promptHook = flatHaveNode9Hook(copilotHooks?.hooks?.UserPromptSubmit);
21459
+ printAgentSection(
21460
+ "GitHub Copilot",
21461
+ [
21462
+ { name: "PreToolUse (node9 check)", present: preHook },
21463
+ { name: "PostToolUse (node9 log)", present: postHook },
21464
+ { name: "UserPromptSubmit (node9 check)", present: promptHook }
21465
+ ],
21466
+ wrappedMcpServers(copilotMcp?.mcpServers)
21467
+ );
21468
+ console.log("");
21469
+ }
20993
21470
  if (cursorConfig) {
20994
21471
  printAgentSection("Cursor", [], wrappedMcpServers(cursorConfig.mcpServers));
20995
21472
  console.log("");
20996
21473
  }
21474
+ if (hermesHooks) {
21475
+ printAgentSection(
21476
+ "Hermes Agent",
21477
+ [
21478
+ { name: "pre_tool_call (node9 check)", present: hermesHooks.pre },
21479
+ { name: "post_tool_call (node9 log)", present: hermesHooks.post }
21480
+ ],
21481
+ null
21482
+ // Hermes has no MCP surface
21483
+ );
21484
+ console.log("");
21485
+ }
20997
21486
  }
20998
21487
  const pauseState = checkPause();
20999
21488
  if (pauseState.paused) {
@@ -21009,9 +21498,9 @@ function registerStatusCommand(program2) {
21009
21498
 
21010
21499
  // src/cli/commands/init.ts
21011
21500
  var import_chalk16 = __toESM(require("chalk"));
21012
- var import_fs40 = __toESM(require("fs"));
21013
- var import_path41 = __toESM(require("path"));
21014
- var import_os36 = __toESM(require("os"));
21501
+ var import_fs42 = __toESM(require("fs"));
21502
+ var import_path43 = __toESM(require("path"));
21503
+ var import_os38 = __toESM(require("os"));
21015
21504
  var import_https4 = __toESM(require("https"));
21016
21505
  init_core();
21017
21506
  init_setup();
@@ -21101,16 +21590,16 @@ function registerInitCommand(program2) {
21101
21590
  }
21102
21591
  console.log("");
21103
21592
  }
21104
- const configPath = import_path41.default.join(import_os36.default.homedir(), ".node9", "config.json");
21105
- const isFirstInstall = !import_fs40.default.existsSync(configPath);
21106
- if (import_fs40.default.existsSync(configPath) && !options.force) {
21593
+ const configPath = import_path43.default.join(import_os38.default.homedir(), ".node9", "config.json");
21594
+ const isFirstInstall = !import_fs42.default.existsSync(configPath);
21595
+ if (import_fs42.default.existsSync(configPath) && !options.force) {
21107
21596
  try {
21108
- const existing = JSON.parse(import_fs40.default.readFileSync(configPath, "utf-8"));
21597
+ const existing = JSON.parse(import_fs42.default.readFileSync(configPath, "utf-8"));
21109
21598
  const settings = existing.settings ?? {};
21110
21599
  if (settings.mode !== chosenMode) {
21111
21600
  settings.mode = chosenMode;
21112
21601
  existing.settings = settings;
21113
- import_fs40.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
21602
+ import_fs42.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
21114
21603
  console.log(import_chalk16.default.green(`\u2705 Mode updated: ${chosenMode}`));
21115
21604
  } else {
21116
21605
  console.log(import_chalk16.default.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
@@ -21123,9 +21612,9 @@ function registerInitCommand(program2) {
21123
21612
  ...DEFAULT_CONFIG,
21124
21613
  settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
21125
21614
  };
21126
- const dir = import_path41.default.dirname(configPath);
21127
- if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
21128
- import_fs40.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
21615
+ const dir = import_path43.default.dirname(configPath);
21616
+ if (!import_fs42.default.existsSync(dir)) import_fs42.default.mkdirSync(dir, { recursive: true });
21617
+ import_fs42.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
21129
21618
  console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
21130
21619
  console.log(import_chalk16.default.gray(` Mode: ${chosenMode}`));
21131
21620
  }
@@ -21230,7 +21719,7 @@ function registerInitCommand(program2) {
21230
21719
  }
21231
21720
 
21232
21721
  // src/cli/commands/undo.ts
21233
- var import_path42 = __toESM(require("path"));
21722
+ var import_path44 = __toESM(require("path"));
21234
21723
  var import_chalk18 = __toESM(require("chalk"));
21235
21724
 
21236
21725
  // src/tui/undo-navigator.ts
@@ -21389,7 +21878,7 @@ function findMatchingCwd(startDir, history) {
21389
21878
  let dir = startDir;
21390
21879
  while (true) {
21391
21880
  if (cwds.has(dir)) return dir;
21392
- const parent = import_path42.default.dirname(dir);
21881
+ const parent = import_path44.default.dirname(dir);
21393
21882
  if (parent === dir) return null;
21394
21883
  dir = parent;
21395
21884
  }
@@ -21965,9 +22454,9 @@ function registerMcpGatewayCommand(program2) {
21965
22454
 
21966
22455
  // src/mcp-server/index.ts
21967
22456
  var import_readline5 = __toESM(require("readline"));
21968
- var import_fs41 = __toESM(require("fs"));
21969
- var import_os37 = __toESM(require("os"));
21970
- var import_path43 = __toESM(require("path"));
22457
+ var import_fs43 = __toESM(require("fs"));
22458
+ var import_os39 = __toESM(require("os"));
22459
+ var import_path45 = __toESM(require("path"));
21971
22460
  var import_child_process11 = require("child_process");
21972
22461
  init_core();
21973
22462
  init_daemon();
@@ -22218,13 +22707,13 @@ function handleStatus() {
22218
22707
  lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
22219
22708
  lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
22220
22709
  lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
22221
- const projectConfig = import_path43.default.join(process.cwd(), "node9.config.json");
22222
- const globalConfig = import_path43.default.join(import_os37.default.homedir(), ".node9", "config.json");
22710
+ const projectConfig = import_path45.default.join(process.cwd(), "node9.config.json");
22711
+ const globalConfig = import_path45.default.join(import_os39.default.homedir(), ".node9", "config.json");
22223
22712
  lines.push(
22224
- `Project config (node9.config.json): ${import_fs41.default.existsSync(projectConfig) ? "present" : "not found"}`
22713
+ `Project config (node9.config.json): ${import_fs43.default.existsSync(projectConfig) ? "present" : "not found"}`
22225
22714
  );
22226
22715
  lines.push(
22227
- `Global config (~/.node9/config.json): ${import_fs41.default.existsSync(globalConfig) ? "present" : "not found"}`
22716
+ `Global config (~/.node9/config.json): ${import_fs43.default.existsSync(globalConfig) ? "present" : "not found"}`
22228
22717
  );
22229
22718
  return lines.join("\n");
22230
22719
  }
@@ -22298,21 +22787,21 @@ function handleShieldDisable(args) {
22298
22787
  writeActiveShields(active.filter((s) => s !== name));
22299
22788
  return `Shield "${name}" disabled.`;
22300
22789
  }
22301
- var GLOBAL_CONFIG_PATH = import_path43.default.join(import_os37.default.homedir(), ".node9", "config.json");
22790
+ var GLOBAL_CONFIG_PATH = import_path45.default.join(import_os39.default.homedir(), ".node9", "config.json");
22302
22791
  var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
22303
22792
  function readGlobalConfigRaw() {
22304
22793
  try {
22305
- if (import_fs41.default.existsSync(GLOBAL_CONFIG_PATH)) {
22306
- return JSON.parse(import_fs41.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
22794
+ if (import_fs43.default.existsSync(GLOBAL_CONFIG_PATH)) {
22795
+ return JSON.parse(import_fs43.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
22307
22796
  }
22308
22797
  } catch {
22309
22798
  }
22310
22799
  return {};
22311
22800
  }
22312
22801
  function writeGlobalConfigRaw(data) {
22313
- const dir = import_path43.default.dirname(GLOBAL_CONFIG_PATH);
22314
- if (!import_fs41.default.existsSync(dir)) import_fs41.default.mkdirSync(dir, { recursive: true });
22315
- import_fs41.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
22802
+ const dir = import_path45.default.dirname(GLOBAL_CONFIG_PATH);
22803
+ if (!import_fs43.default.existsSync(dir)) import_fs43.default.mkdirSync(dir, { recursive: true });
22804
+ import_fs43.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
22316
22805
  }
22317
22806
  function handleApproverList() {
22318
22807
  const config = getConfig();
@@ -22356,9 +22845,9 @@ function handleApproverSet(args) {
22356
22845
  function handleAuditGet(args) {
22357
22846
  const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
22358
22847
  const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
22359
- const auditPath = import_path43.default.join(import_os37.default.homedir(), ".node9", "audit.log");
22360
- if (!import_fs41.default.existsSync(auditPath)) return "No audit log found.";
22361
- const rawLines = import_fs41.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
22848
+ const auditPath = import_path45.default.join(import_os39.default.homedir(), ".node9", "audit.log");
22849
+ if (!import_fs43.default.existsSync(auditPath)) return "No audit log found.";
22850
+ const rawLines = import_fs43.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
22362
22851
  const parsed = [];
22363
22852
  for (const line of rawLines) {
22364
22853
  try {
@@ -22693,7 +23182,7 @@ function registerTrustCommand(program2) {
22693
23182
  // src/cli/commands/mcp-pin.ts
22694
23183
  var import_chalk21 = __toESM(require("chalk"));
22695
23184
  init_mcp_pin();
22696
- var import_fs42 = __toESM(require("fs"));
23185
+ var import_fs44 = __toESM(require("fs"));
22697
23186
  function registerMcpPinCommand(program2) {
22698
23187
  const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
22699
23188
  const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
@@ -22704,7 +23193,7 @@ function registerMcpPinCommand(program2) {
22704
23193
  let repoCorrupt = false;
22705
23194
  if (found.source === "repo") {
22706
23195
  try {
22707
- const raw = import_fs42.default.readFileSync(found.path, "utf-8");
23196
+ const raw = import_fs44.default.readFileSync(found.path, "utf-8");
22708
23197
  const parsed = JSON.parse(raw);
22709
23198
  repoEntries = parsed.servers ?? {};
22710
23199
  } catch {
@@ -23017,9 +23506,9 @@ init_scan();
23017
23506
 
23018
23507
  // src/cli/commands/sessions.ts
23019
23508
  var import_chalk24 = __toESM(require("chalk"));
23020
- var import_fs43 = __toESM(require("fs"));
23021
- var import_path44 = __toESM(require("path"));
23022
- var import_os38 = __toESM(require("os"));
23509
+ var import_fs45 = __toESM(require("fs"));
23510
+ var import_path46 = __toESM(require("path"));
23511
+ var import_os40 = __toESM(require("os"));
23023
23512
  init_scan_summary();
23024
23513
  var CLAUDE_PRICING3 = {
23025
23514
  "claude-opus-4-6": { i: 5e-6, o: 25e-6, cw: 625e-8, cr: 5e-7 },
@@ -23061,10 +23550,10 @@ function encodeProjectPath(projectPath) {
23061
23550
  }
23062
23551
  function sessionJsonlPath(projectPath, sessionId) {
23063
23552
  const encoded = encodeProjectPath(projectPath);
23064
- return import_path44.default.join(import_os38.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
23553
+ return import_path46.default.join(import_os40.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
23065
23554
  }
23066
23555
  function projectLabel(projectPath) {
23067
- return projectPath.replace(import_os38.default.homedir(), "~");
23556
+ return projectPath.replace(import_os40.default.homedir(), "~");
23068
23557
  }
23069
23558
  function parseHistoryLines(lines) {
23070
23559
  const entries = [];
@@ -23133,10 +23622,10 @@ function parseSessionLines(lines) {
23133
23622
  return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
23134
23623
  }
23135
23624
  function loadAuditEntries(auditPath) {
23136
- const aPath = auditPath ?? import_path44.default.join(import_os38.default.homedir(), ".node9", "audit.log");
23625
+ const aPath = auditPath ?? import_path46.default.join(import_os40.default.homedir(), ".node9", "audit.log");
23137
23626
  let raw;
23138
23627
  try {
23139
- raw = import_fs43.default.readFileSync(aPath, "utf-8");
23628
+ raw = import_fs45.default.readFileSync(aPath, "utf-8");
23140
23629
  } catch {
23141
23630
  return [];
23142
23631
  }
@@ -23172,8 +23661,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
23172
23661
  return result;
23173
23662
  }
23174
23663
  function buildGeminiSessions(days, allAuditEntries) {
23175
- const tmpDir = import_path44.default.join(import_os38.default.homedir(), ".gemini", "tmp");
23176
- if (!import_fs43.default.existsSync(tmpDir)) return [];
23664
+ const tmpDir = import_path46.default.join(import_os40.default.homedir(), ".gemini", "tmp");
23665
+ if (!import_fs45.default.existsSync(tmpDir)) return [];
23177
23666
  const cutoff = days !== null ? (() => {
23178
23667
  const d = /* @__PURE__ */ new Date();
23179
23668
  d.setDate(d.getDate() - days);
@@ -23182,35 +23671,35 @@ function buildGeminiSessions(days, allAuditEntries) {
23182
23671
  })() : null;
23183
23672
  let slugDirs;
23184
23673
  try {
23185
- slugDirs = import_fs43.default.readdirSync(tmpDir);
23674
+ slugDirs = import_fs45.default.readdirSync(tmpDir);
23186
23675
  } catch {
23187
23676
  return [];
23188
23677
  }
23189
23678
  const summaries = [];
23190
23679
  for (const slug of slugDirs) {
23191
- const slugPath = import_path44.default.join(tmpDir, slug);
23680
+ const slugPath = import_path46.default.join(tmpDir, slug);
23192
23681
  try {
23193
- if (!import_fs43.default.statSync(slugPath).isDirectory()) continue;
23682
+ if (!import_fs45.default.statSync(slugPath).isDirectory()) continue;
23194
23683
  } catch {
23195
23684
  continue;
23196
23685
  }
23197
- let projectRoot = import_path44.default.join(import_os38.default.homedir(), slug);
23686
+ let projectRoot = import_path46.default.join(import_os40.default.homedir(), slug);
23198
23687
  try {
23199
- projectRoot = import_fs43.default.readFileSync(import_path44.default.join(slugPath, ".project_root"), "utf-8").trim();
23688
+ projectRoot = import_fs45.default.readFileSync(import_path46.default.join(slugPath, ".project_root"), "utf-8").trim();
23200
23689
  } catch {
23201
23690
  }
23202
- const chatsDir = import_path44.default.join(slugPath, "chats");
23203
- if (!import_fs43.default.existsSync(chatsDir)) continue;
23691
+ const chatsDir = import_path46.default.join(slugPath, "chats");
23692
+ if (!import_fs45.default.existsSync(chatsDir)) continue;
23204
23693
  let chatFiles;
23205
23694
  try {
23206
- chatFiles = import_fs43.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
23695
+ chatFiles = import_fs45.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
23207
23696
  } catch {
23208
23697
  continue;
23209
23698
  }
23210
23699
  for (const chatFile of chatFiles) {
23211
23700
  let raw;
23212
23701
  try {
23213
- raw = import_fs43.default.readFileSync(import_path44.default.join(chatsDir, chatFile), "utf-8");
23702
+ raw = import_fs45.default.readFileSync(import_path46.default.join(chatsDir, chatFile), "utf-8");
23214
23703
  } catch {
23215
23704
  continue;
23216
23705
  }
@@ -23290,8 +23779,8 @@ function buildGeminiSessions(days, allAuditEntries) {
23290
23779
  return summaries;
23291
23780
  }
23292
23781
  function buildCodexSessions(days, allAuditEntries) {
23293
- const sessionsBase = import_path44.default.join(import_os38.default.homedir(), ".codex", "sessions");
23294
- if (!import_fs43.default.existsSync(sessionsBase)) return [];
23782
+ const sessionsBase = import_path46.default.join(import_os40.default.homedir(), ".codex", "sessions");
23783
+ if (!import_fs45.default.existsSync(sessionsBase)) return [];
23295
23784
  const cutoff = days !== null ? (() => {
23296
23785
  const d = /* @__PURE__ */ new Date();
23297
23786
  d.setDate(d.getDate() - days);
@@ -23300,29 +23789,29 @@ function buildCodexSessions(days, allAuditEntries) {
23300
23789
  })() : null;
23301
23790
  const jsonlFiles = [];
23302
23791
  try {
23303
- for (const year of import_fs43.default.readdirSync(sessionsBase)) {
23304
- const yearPath = import_path44.default.join(sessionsBase, year);
23792
+ for (const year of import_fs45.default.readdirSync(sessionsBase)) {
23793
+ const yearPath = import_path46.default.join(sessionsBase, year);
23305
23794
  try {
23306
- if (!import_fs43.default.statSync(yearPath).isDirectory()) continue;
23795
+ if (!import_fs45.default.statSync(yearPath).isDirectory()) continue;
23307
23796
  } catch {
23308
23797
  continue;
23309
23798
  }
23310
- for (const month of import_fs43.default.readdirSync(yearPath)) {
23311
- const monthPath = import_path44.default.join(yearPath, month);
23799
+ for (const month of import_fs45.default.readdirSync(yearPath)) {
23800
+ const monthPath = import_path46.default.join(yearPath, month);
23312
23801
  try {
23313
- if (!import_fs43.default.statSync(monthPath).isDirectory()) continue;
23802
+ if (!import_fs45.default.statSync(monthPath).isDirectory()) continue;
23314
23803
  } catch {
23315
23804
  continue;
23316
23805
  }
23317
- for (const day of import_fs43.default.readdirSync(monthPath)) {
23318
- const dayPath = import_path44.default.join(monthPath, day);
23806
+ for (const day of import_fs45.default.readdirSync(monthPath)) {
23807
+ const dayPath = import_path46.default.join(monthPath, day);
23319
23808
  try {
23320
- if (!import_fs43.default.statSync(dayPath).isDirectory()) continue;
23809
+ if (!import_fs45.default.statSync(dayPath).isDirectory()) continue;
23321
23810
  } catch {
23322
23811
  continue;
23323
23812
  }
23324
- for (const file of import_fs43.default.readdirSync(dayPath)) {
23325
- if (file.endsWith(".jsonl")) jsonlFiles.push(import_path44.default.join(dayPath, file));
23813
+ for (const file of import_fs45.default.readdirSync(dayPath)) {
23814
+ if (file.endsWith(".jsonl")) jsonlFiles.push(import_path46.default.join(dayPath, file));
23326
23815
  }
23327
23816
  }
23328
23817
  }
@@ -23334,7 +23823,7 @@ function buildCodexSessions(days, allAuditEntries) {
23334
23823
  for (const filePath of jsonlFiles) {
23335
23824
  let lines;
23336
23825
  try {
23337
- lines = import_fs43.default.readFileSync(filePath, "utf-8").split("\n");
23826
+ lines = import_fs45.default.readFileSync(filePath, "utf-8").split("\n");
23338
23827
  } catch {
23339
23828
  continue;
23340
23829
  }
@@ -23412,10 +23901,10 @@ function buildCodexSessions(days, allAuditEntries) {
23412
23901
  return summaries;
23413
23902
  }
23414
23903
  function buildSessions(days, historyPath) {
23415
- const hPath = historyPath ?? import_path44.default.join(import_os38.default.homedir(), ".claude", "history.jsonl");
23904
+ const hPath = historyPath ?? import_path46.default.join(import_os40.default.homedir(), ".claude", "history.jsonl");
23416
23905
  let historyRaw;
23417
23906
  try {
23418
- historyRaw = import_fs43.default.readFileSync(hPath, "utf-8");
23907
+ historyRaw = import_fs45.default.readFileSync(hPath, "utf-8");
23419
23908
  } catch {
23420
23909
  return [];
23421
23910
  }
@@ -23440,7 +23929,7 @@ function buildSessions(days, historyPath) {
23440
23929
  const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
23441
23930
  let sessionLines = [];
23442
23931
  try {
23443
- sessionLines = import_fs43.default.readFileSync(jsonlFile, "utf-8").split("\n");
23932
+ sessionLines = import_fs45.default.readFileSync(jsonlFile, "utf-8").split("\n");
23444
23933
  } catch {
23445
23934
  }
23446
23935
  const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
@@ -23708,8 +24197,8 @@ function registerSessionsCommand(program2) {
23708
24197
  console.log("");
23709
24198
  console.log(import_chalk24.default.cyan.bold("\u{1F4CB} node9 sessions") + import_chalk24.default.dim(" \u2014 what your AI agent did"));
23710
24199
  console.log("");
23711
- const historyPath = import_path44.default.join(import_os38.default.homedir(), ".claude", "history.jsonl");
23712
- if (!import_fs43.default.existsSync(historyPath)) {
24200
+ const historyPath = import_path46.default.join(import_os40.default.homedir(), ".claude", "history.jsonl");
24201
+ if (!import_fs45.default.existsSync(historyPath)) {
23713
24202
  console.log(import_chalk24.default.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
23714
24203
  console.log(import_chalk24.default.gray(" Install Claude Code, run a few sessions, then try again.\n"));
23715
24204
  return;
@@ -23746,12 +24235,12 @@ function registerSessionsCommand(program2) {
23746
24235
 
23747
24236
  // src/cli/commands/skill-pin.ts
23748
24237
  var import_chalk25 = __toESM(require("chalk"));
23749
- var import_fs44 = __toESM(require("fs"));
23750
- var import_os39 = __toESM(require("os"));
23751
- var import_path45 = __toESM(require("path"));
24238
+ var import_fs46 = __toESM(require("fs"));
24239
+ var import_os41 = __toESM(require("os"));
24240
+ var import_path47 = __toESM(require("path"));
23752
24241
  function wipeSkillSessions() {
23753
24242
  try {
23754
- import_fs44.default.rmSync(import_path45.default.join(import_os39.default.homedir(), ".node9", "skill-sessions"), {
24243
+ import_fs46.default.rmSync(import_path47.default.join(import_os41.default.homedir(), ".node9", "skill-sessions"), {
23755
24244
  recursive: true,
23756
24245
  force: true
23757
24246
  });
@@ -23833,15 +24322,15 @@ function registerSkillPinCommand(program2) {
23833
24322
  }
23834
24323
 
23835
24324
  // src/cli/commands/decisions.ts
23836
- var import_fs45 = __toESM(require("fs"));
23837
- var import_os40 = __toESM(require("os"));
23838
- var import_path46 = __toESM(require("path"));
24325
+ var import_fs47 = __toESM(require("fs"));
24326
+ var import_os42 = __toESM(require("os"));
24327
+ var import_path48 = __toESM(require("path"));
23839
24328
  var import_chalk26 = __toESM(require("chalk"));
23840
- var DECISIONS_FILE2 = import_path46.default.join(import_os40.default.homedir(), ".node9", "decisions.json");
24329
+ var DECISIONS_FILE2 = import_path48.default.join(import_os42.default.homedir(), ".node9", "decisions.json");
23841
24330
  function readDecisions() {
23842
24331
  try {
23843
- if (!import_fs45.default.existsSync(DECISIONS_FILE2)) return {};
23844
- const raw = import_fs45.default.readFileSync(DECISIONS_FILE2, "utf-8");
24332
+ if (!import_fs47.default.existsSync(DECISIONS_FILE2)) return {};
24333
+ const raw = import_fs47.default.readFileSync(DECISIONS_FILE2, "utf-8");
23845
24334
  const parsed = JSON.parse(raw);
23846
24335
  const out = {};
23847
24336
  for (const [k, v] of Object.entries(parsed)) {
@@ -23853,11 +24342,11 @@ function readDecisions() {
23853
24342
  }
23854
24343
  }
23855
24344
  function writeDecisions(d) {
23856
- const dir = import_path46.default.dirname(DECISIONS_FILE2);
23857
- if (!import_fs45.default.existsSync(dir)) import_fs45.default.mkdirSync(dir, { recursive: true });
24345
+ const dir = import_path48.default.dirname(DECISIONS_FILE2);
24346
+ if (!import_fs47.default.existsSync(dir)) import_fs47.default.mkdirSync(dir, { recursive: true });
23858
24347
  const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
23859
- import_fs45.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
23860
- import_fs45.default.renameSync(tmp, DECISIONS_FILE2);
24348
+ import_fs47.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
24349
+ import_fs47.default.renameSync(tmp, DECISIONS_FILE2);
23861
24350
  }
23862
24351
  function registerDecisionsCommand(program2) {
23863
24352
  const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
@@ -23914,18 +24403,18 @@ Persistent decisions (${entries.length})
23914
24403
 
23915
24404
  // src/cli/commands/dlp.ts
23916
24405
  var import_chalk27 = __toESM(require("chalk"));
23917
- var import_fs46 = __toESM(require("fs"));
23918
- var import_path47 = __toESM(require("path"));
23919
- var import_os41 = __toESM(require("os"));
23920
- var AUDIT_LOG = import_path47.default.join(import_os41.default.homedir(), ".node9", "audit.log");
23921
- var RESOLVED_FILE = import_path47.default.join(import_os41.default.homedir(), ".node9", "dlp-resolved.json");
24406
+ var import_fs48 = __toESM(require("fs"));
24407
+ var import_path49 = __toESM(require("path"));
24408
+ var import_os43 = __toESM(require("os"));
24409
+ var AUDIT_LOG = import_path49.default.join(import_os43.default.homedir(), ".node9", "audit.log");
24410
+ var RESOLVED_FILE = import_path49.default.join(import_os43.default.homedir(), ".node9", "dlp-resolved.json");
23922
24411
  var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
23923
24412
  function stripAnsi(s) {
23924
24413
  return s.replace(ANSI_RE, "");
23925
24414
  }
23926
24415
  function loadResolved() {
23927
24416
  try {
23928
- const raw = JSON.parse(import_fs46.default.readFileSync(RESOLVED_FILE, "utf-8"));
24417
+ const raw = JSON.parse(import_fs48.default.readFileSync(RESOLVED_FILE, "utf-8"));
23929
24418
  return new Set(raw);
23930
24419
  } catch {
23931
24420
  return /* @__PURE__ */ new Set();
@@ -23933,13 +24422,13 @@ function loadResolved() {
23933
24422
  }
23934
24423
  function saveResolved(resolved) {
23935
24424
  try {
23936
- import_fs46.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
24425
+ import_fs48.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
23937
24426
  } catch {
23938
24427
  }
23939
24428
  }
23940
24429
  function loadDlpFindings() {
23941
- if (!import_fs46.default.existsSync(AUDIT_LOG)) return [];
23942
- return import_fs46.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
24430
+ if (!import_fs48.default.existsSync(AUDIT_LOG)) return [];
24431
+ return import_fs48.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
23943
24432
  if (!line.trim()) return [];
23944
24433
  try {
23945
24434
  const e = JSON.parse(line);
@@ -24037,15 +24526,15 @@ function registerDlpCommand(program2) {
24037
24526
 
24038
24527
  // src/cli/commands/mask.ts
24039
24528
  var import_chalk28 = __toESM(require("chalk"));
24040
- var import_fs47 = __toESM(require("fs"));
24041
- var import_path48 = __toESM(require("path"));
24042
- var import_os42 = __toESM(require("os"));
24529
+ var import_fs49 = __toESM(require("fs"));
24530
+ var import_path50 = __toESM(require("path"));
24531
+ var import_os44 = __toESM(require("os"));
24043
24532
  init_dlp();
24044
24533
  function findJsonlFiles(dir) {
24045
24534
  const results = [];
24046
- if (!import_fs47.default.existsSync(dir)) return results;
24047
- for (const entry of import_fs47.default.readdirSync(dir, { withFileTypes: true })) {
24048
- const full = import_path48.default.join(dir, entry.name);
24535
+ if (!import_fs49.default.existsSync(dir)) return results;
24536
+ for (const entry of import_fs49.default.readdirSync(dir, { withFileTypes: true })) {
24537
+ const full = import_path50.default.join(dir, entry.name);
24049
24538
  if (entry.isDirectory()) results.push(...findJsonlFiles(full));
24050
24539
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
24051
24540
  }
@@ -24088,7 +24577,7 @@ function redactJson(obj) {
24088
24577
  function processFile(filePath, dryRun) {
24089
24578
  let raw;
24090
24579
  try {
24091
- raw = import_fs47.default.readFileSync(filePath, "utf-8");
24580
+ raw = import_fs49.default.readFileSync(filePath, "utf-8");
24092
24581
  } catch {
24093
24582
  return { redactedLines: 0, patterns: [] };
24094
24583
  }
@@ -24120,14 +24609,14 @@ function processFile(filePath, dryRun) {
24120
24609
  }
24121
24610
  }
24122
24611
  if (!dryRun && redactedLines > 0) {
24123
- import_fs47.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
24612
+ import_fs49.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
24124
24613
  }
24125
24614
  return { redactedLines, patterns };
24126
24615
  }
24127
24616
  function processJsonFile(filePath, dryRun) {
24128
24617
  let raw;
24129
24618
  try {
24130
- raw = import_fs47.default.readFileSync(filePath, "utf-8");
24619
+ raw = import_fs49.default.readFileSync(filePath, "utf-8");
24131
24620
  } catch {
24132
24621
  return { redactedLines: 0, patterns: [] };
24133
24622
  }
@@ -24140,15 +24629,15 @@ function processJsonFile(filePath, dryRun) {
24140
24629
  const { value, modified, found } = redactJson(parsed);
24141
24630
  if (!modified) return { redactedLines: 0, patterns: [] };
24142
24631
  if (!dryRun) {
24143
- import_fs47.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
24632
+ import_fs49.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
24144
24633
  }
24145
24634
  return { redactedLines: 1, patterns: found };
24146
24635
  }
24147
24636
  function findJsonFiles(dir) {
24148
24637
  const results = [];
24149
- if (!import_fs47.default.existsSync(dir)) return results;
24150
- for (const entry of import_fs47.default.readdirSync(dir, { withFileTypes: true })) {
24151
- const full = import_path48.default.join(dir, entry.name);
24638
+ if (!import_fs49.default.existsSync(dir)) return results;
24639
+ for (const entry of import_fs49.default.readdirSync(dir, { withFileTypes: true })) {
24640
+ const full = import_path50.default.join(dir, entry.name);
24152
24641
  if (entry.isDirectory()) results.push(...findJsonFiles(full));
24153
24642
  else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
24154
24643
  }
@@ -24157,9 +24646,9 @@ function findJsonFiles(dir) {
24157
24646
  function registerMaskCommand(program2) {
24158
24647
  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) => {
24159
24648
  const dryRun = !!options.dryRun;
24160
- const home = import_os42.default.homedir();
24161
- const claudeDir = import_path48.default.join(home, ".claude", "projects");
24162
- const geminiDir = import_path48.default.join(home, ".gemini", "tmp");
24649
+ const home = import_os44.default.homedir();
24650
+ const claudeDir = import_path50.default.join(home, ".claude", "projects");
24651
+ const geminiDir = import_path50.default.join(home, ".gemini", "tmp");
24163
24652
  const allFiles = [
24164
24653
  ...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
24165
24654
  ...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
@@ -24167,7 +24656,7 @@ function registerMaskCommand(program2) {
24167
24656
  const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
24168
24657
  const filtered = cutoff ? allFiles.filter((f) => {
24169
24658
  try {
24170
- return import_fs47.default.statSync(f.path).mtime >= cutoff;
24659
+ return import_fs49.default.statSync(f.path).mtime >= cutoff;
24171
24660
  } catch {
24172
24661
  return false;
24173
24662
  }
@@ -24223,20 +24712,20 @@ function registerMaskCommand(program2) {
24223
24712
  // src/cli.ts
24224
24713
  init_blast();
24225
24714
  var { version } = JSON.parse(
24226
- import_fs50.default.readFileSync(import_path51.default.join(__dirname, "../package.json"), "utf-8")
24715
+ import_fs52.default.readFileSync(import_path53.default.join(__dirname, "../package.json"), "utf-8")
24227
24716
  );
24228
24717
  var program = new import_commander.Command();
24229
24718
  program.name("node9").description("The Sudo Command for AI Agents").version(version);
24230
24719
  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) => {
24231
24720
  const DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept";
24232
- const credPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "credentials.json");
24233
- if (!import_fs50.default.existsSync(import_path51.default.dirname(credPath)))
24234
- import_fs50.default.mkdirSync(import_path51.default.dirname(credPath), { recursive: true });
24721
+ const credPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "credentials.json");
24722
+ if (!import_fs52.default.existsSync(import_path53.default.dirname(credPath)))
24723
+ import_fs52.default.mkdirSync(import_path53.default.dirname(credPath), { recursive: true });
24235
24724
  const profileName = options.profile || "default";
24236
24725
  let existingCreds = {};
24237
24726
  try {
24238
- if (import_fs50.default.existsSync(credPath)) {
24239
- const raw = JSON.parse(import_fs50.default.readFileSync(credPath, "utf-8"));
24727
+ if (import_fs52.default.existsSync(credPath)) {
24728
+ const raw = JSON.parse(import_fs52.default.readFileSync(credPath, "utf-8"));
24240
24729
  if (raw.apiKey) {
24241
24730
  existingCreds = {
24242
24731
  default: { apiKey: raw.apiKey, apiUrl: raw.apiUrl || DEFAULT_API_URL2 }
@@ -24248,14 +24737,14 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
24248
24737
  } catch {
24249
24738
  }
24250
24739
  existingCreds[profileName] = { apiKey, apiUrl: DEFAULT_API_URL2 };
24251
- import_fs50.default.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), { mode: 384 });
24740
+ import_fs52.default.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), { mode: 384 });
24252
24741
  let effectiveCloud = null;
24253
24742
  if (profileName === "default") {
24254
- const configPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "config.json");
24743
+ const configPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "config.json");
24255
24744
  let config = {};
24256
24745
  try {
24257
- if (import_fs50.default.existsSync(configPath))
24258
- config = JSON.parse(import_fs50.default.readFileSync(configPath, "utf-8"));
24746
+ if (import_fs52.default.existsSync(configPath))
24747
+ config = JSON.parse(import_fs52.default.readFileSync(configPath, "utf-8"));
24259
24748
  } catch {
24260
24749
  }
24261
24750
  if (!config.settings || typeof config.settings !== "object") config.settings = {};
@@ -24270,9 +24759,9 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
24270
24759
  approvers.cloud = false;
24271
24760
  }
24272
24761
  s.approvers = approvers;
24273
- if (!import_fs50.default.existsSync(import_path51.default.dirname(configPath)))
24274
- import_fs50.default.mkdirSync(import_path51.default.dirname(configPath), { recursive: true });
24275
- import_fs50.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
24762
+ if (!import_fs52.default.existsSync(import_path53.default.dirname(configPath)))
24763
+ import_fs52.default.mkdirSync(import_path53.default.dirname(configPath), { recursive: true });
24764
+ import_fs52.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
24276
24765
  effectiveCloud = approvers.cloud === true;
24277
24766
  }
24278
24767
  if (options.profile && profileName !== "default") {
@@ -24431,15 +24920,15 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
24431
24920
  }
24432
24921
  }
24433
24922
  if (options.purge) {
24434
- const node9Dir = import_path51.default.join(import_os45.default.homedir(), ".node9");
24435
- if (import_fs50.default.existsSync(node9Dir)) {
24923
+ const node9Dir = import_path53.default.join(import_os47.default.homedir(), ".node9");
24924
+ if (import_fs52.default.existsSync(node9Dir)) {
24436
24925
  const confirmed = await (0, import_prompts2.confirm)({
24437
24926
  message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
24438
24927
  default: false
24439
24928
  });
24440
24929
  if (confirmed) {
24441
- import_fs50.default.rmSync(node9Dir, { recursive: true });
24442
- if (import_fs50.default.existsSync(node9Dir)) {
24930
+ import_fs52.default.rmSync(node9Dir, { recursive: true });
24931
+ if (import_fs52.default.existsSync(node9Dir)) {
24443
24932
  console.error(
24444
24933
  import_chalk30.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
24445
24934
  );
@@ -24554,7 +25043,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
24554
25043
  });
24555
25044
  program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
24556
25045
  try {
24557
- const dashboardPath = import_path51.default.join(__dirname, "dashboard.mjs");
25046
+ const dashboardPath = import_path53.default.join(__dirname, "dashboard.mjs");
24558
25047
  const dynamicImport = new Function("id", "return import(id)");
24559
25048
  const mod = await dynamicImport(`file://${dashboardPath}`);
24560
25049
  await mod.startMonitor();
@@ -24592,14 +25081,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
24592
25081
  Run "node9 addto claude" to register it as the statusLine.`
24593
25082
  ).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
24594
25083
  if (subcommand === "debug") {
24595
- const flagFile = import_path51.default.join(import_os45.default.homedir(), ".node9", "hud-debug");
25084
+ const flagFile = import_path53.default.join(import_os47.default.homedir(), ".node9", "hud-debug");
24596
25085
  if (state === "on") {
24597
- import_fs50.default.mkdirSync(import_path51.default.dirname(flagFile), { recursive: true });
24598
- import_fs50.default.writeFileSync(flagFile, "");
25086
+ import_fs52.default.mkdirSync(import_path53.default.dirname(flagFile), { recursive: true });
25087
+ import_fs52.default.writeFileSync(flagFile, "");
24599
25088
  console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
24600
25089
  console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
24601
25090
  } else if (state === "off") {
24602
- if (import_fs50.default.existsSync(flagFile)) import_fs50.default.unlinkSync(flagFile);
25091
+ if (import_fs52.default.existsSync(flagFile)) import_fs52.default.unlinkSync(flagFile);
24603
25092
  console.log("HUD debug logging disabled.");
24604
25093
  } else {
24605
25094
  console.error("Usage: node9 hud debug on|off");
@@ -24716,9 +25205,9 @@ if (process.argv[2] !== "daemon") {
24716
25205
  const isCheckHook = process.argv[2] === "check";
24717
25206
  if (isCheckHook) {
24718
25207
  if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
24719
- const logPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "hook-debug.log");
25208
+ const logPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "hook-debug.log");
24720
25209
  const msg = reason instanceof Error ? reason.message : String(reason);
24721
- import_fs50.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
25210
+ import_fs52.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
24722
25211
  `);
24723
25212
  }
24724
25213
  process.exit(0);