@node9/proxy 1.32.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"
2711
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"
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" };
@@ -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,18 +21271,18 @@ 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"));
20863
21277
  var yaml2 = __toESM(require("yaml"));
20864
21278
  init_core();
20865
21279
  init_daemon();
20866
21280
  init_setup();
20867
21281
  function readHermesHooks(configPath) {
20868
- if (!import_fs39.default.existsSync(configPath)) return null;
21282
+ if (!import_fs41.default.existsSync(configPath)) return null;
20869
21283
  let raw;
20870
21284
  try {
20871
- raw = import_fs39.default.readFileSync(configPath, "utf-8");
21285
+ raw = import_fs41.default.readFileSync(configPath, "utf-8");
20872
21286
  } catch {
20873
21287
  return null;
20874
21288
  }
@@ -20889,7 +21303,7 @@ function readHermesHooks(configPath) {
20889
21303
  }
20890
21304
  function readJson2(filePath) {
20891
21305
  try {
20892
- 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"));
20893
21307
  } catch {
20894
21308
  }
20895
21309
  return null;
@@ -20957,42 +21371,42 @@ function registerStatusCommand(program2) {
20957
21371
  console.log("");
20958
21372
  const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
20959
21373
  console.log(` Mode: ${modeLabel}`);
20960
- const projectConfig = import_path40.default.join(process.cwd(), "node9.config.json");
20961
- 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");
20962
21376
  console.log(
20963
- ` 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")}`
20964
21378
  );
20965
21379
  console.log(
20966
- ` 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")}`
20967
21381
  );
20968
21382
  if (mergedConfig.policy.sandboxPaths.length > 0) {
20969
21383
  console.log(
20970
21384
  ` Sandbox: ${import_chalk15.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
20971
21385
  );
20972
21386
  }
20973
- const homeDir2 = import_os35.default.homedir();
21387
+ const homeDir2 = import_os37.default.homedir();
20974
21388
  const claudeSettings = readJson2(
20975
- import_path40.default.join(homeDir2, ".claude", "settings.json")
21389
+ import_path42.default.join(homeDir2, ".claude", "settings.json")
20976
21390
  );
20977
- const claudeConfig = readJson2(import_path40.default.join(homeDir2, ".claude.json"));
21391
+ const claudeConfig = readJson2(import_path42.default.join(homeDir2, ".claude.json"));
20978
21392
  const geminiSettings = readJson2(
20979
- import_path40.default.join(homeDir2, ".gemini", "settings.json")
21393
+ import_path42.default.join(homeDir2, ".gemini", "settings.json")
20980
21394
  );
20981
- const cursorConfig = readJson2(import_path40.default.join(homeDir2, ".cursor", "mcp.json"));
21395
+ const cursorConfig = readJson2(import_path42.default.join(homeDir2, ".cursor", "mcp.json"));
20982
21396
  const antigravityHooks = readJson2(
20983
- import_path40.default.join(homeDir2, ".gemini", "config", "hooks.json")
21397
+ import_path42.default.join(homeDir2, ".gemini", "config", "hooks.json")
20984
21398
  );
20985
21399
  const antigravityMcp = readJson2(
20986
- import_path40.default.join(homeDir2, ".gemini", "config", "mcp_config.json")
21400
+ import_path42.default.join(homeDir2, ".gemini", "config", "mcp_config.json")
20987
21401
  );
20988
- const antigravityPresent = antigravityHooks !== null || import_fs39.default.existsSync(import_path40.default.join(homeDir2, ".gemini", "antigravity-cli")) || import_fs39.default.existsSync(import_path40.default.join(homeDir2, ".gemini", "antigravity-ide"));
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"));
20989
21403
  const copilotHooks = readJson2(
20990
- import_path40.default.join(homeDir2, ".copilot", "hooks", "node9.json")
21404
+ import_path42.default.join(homeDir2, ".copilot", "hooks", "node9.json")
20991
21405
  );
20992
21406
  const copilotMcp = readJson2(
20993
- import_path40.default.join(homeDir2, ".copilot", "mcp-config.json")
21407
+ import_path42.default.join(homeDir2, ".copilot", "mcp-config.json")
20994
21408
  );
20995
- const copilotPresent = import_fs39.default.existsSync(import_path40.default.join(homeDir2, ".copilot"));
21409
+ const copilotPresent = import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".copilot"));
20996
21410
  const hermesHooks = readHermesHooks(hermesConfigPath(homeDir2));
20997
21411
  const agentFound = claudeSettings || claudeConfig || geminiSettings || cursorConfig || antigravityPresent || copilotPresent || hermesHooks;
20998
21412
  if (agentFound) {
@@ -21084,9 +21498,9 @@ function registerStatusCommand(program2) {
21084
21498
 
21085
21499
  // src/cli/commands/init.ts
21086
21500
  var import_chalk16 = __toESM(require("chalk"));
21087
- var import_fs40 = __toESM(require("fs"));
21088
- var import_path41 = __toESM(require("path"));
21089
- 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"));
21090
21504
  var import_https4 = __toESM(require("https"));
21091
21505
  init_core();
21092
21506
  init_setup();
@@ -21176,16 +21590,16 @@ function registerInitCommand(program2) {
21176
21590
  }
21177
21591
  console.log("");
21178
21592
  }
21179
- const configPath = import_path41.default.join(import_os36.default.homedir(), ".node9", "config.json");
21180
- const isFirstInstall = !import_fs40.default.existsSync(configPath);
21181
- 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) {
21182
21596
  try {
21183
- const existing = JSON.parse(import_fs40.default.readFileSync(configPath, "utf-8"));
21597
+ const existing = JSON.parse(import_fs42.default.readFileSync(configPath, "utf-8"));
21184
21598
  const settings = existing.settings ?? {};
21185
21599
  if (settings.mode !== chosenMode) {
21186
21600
  settings.mode = chosenMode;
21187
21601
  existing.settings = settings;
21188
- import_fs40.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
21602
+ import_fs42.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
21189
21603
  console.log(import_chalk16.default.green(`\u2705 Mode updated: ${chosenMode}`));
21190
21604
  } else {
21191
21605
  console.log(import_chalk16.default.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
@@ -21198,9 +21612,9 @@ function registerInitCommand(program2) {
21198
21612
  ...DEFAULT_CONFIG,
21199
21613
  settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
21200
21614
  };
21201
- const dir = import_path41.default.dirname(configPath);
21202
- if (!import_fs40.default.existsSync(dir)) import_fs40.default.mkdirSync(dir, { recursive: true });
21203
- 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");
21204
21618
  console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
21205
21619
  console.log(import_chalk16.default.gray(` Mode: ${chosenMode}`));
21206
21620
  }
@@ -21305,7 +21719,7 @@ function registerInitCommand(program2) {
21305
21719
  }
21306
21720
 
21307
21721
  // src/cli/commands/undo.ts
21308
- var import_path42 = __toESM(require("path"));
21722
+ var import_path44 = __toESM(require("path"));
21309
21723
  var import_chalk18 = __toESM(require("chalk"));
21310
21724
 
21311
21725
  // src/tui/undo-navigator.ts
@@ -21464,7 +21878,7 @@ function findMatchingCwd(startDir, history) {
21464
21878
  let dir = startDir;
21465
21879
  while (true) {
21466
21880
  if (cwds.has(dir)) return dir;
21467
- const parent = import_path42.default.dirname(dir);
21881
+ const parent = import_path44.default.dirname(dir);
21468
21882
  if (parent === dir) return null;
21469
21883
  dir = parent;
21470
21884
  }
@@ -22040,9 +22454,9 @@ function registerMcpGatewayCommand(program2) {
22040
22454
 
22041
22455
  // src/mcp-server/index.ts
22042
22456
  var import_readline5 = __toESM(require("readline"));
22043
- var import_fs41 = __toESM(require("fs"));
22044
- var import_os37 = __toESM(require("os"));
22045
- 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"));
22046
22460
  var import_child_process11 = require("child_process");
22047
22461
  init_core();
22048
22462
  init_daemon();
@@ -22293,13 +22707,13 @@ function handleStatus() {
22293
22707
  lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
22294
22708
  lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
22295
22709
  lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
22296
- const projectConfig = import_path43.default.join(process.cwd(), "node9.config.json");
22297
- 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");
22298
22712
  lines.push(
22299
- `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"}`
22300
22714
  );
22301
22715
  lines.push(
22302
- `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"}`
22303
22717
  );
22304
22718
  return lines.join("\n");
22305
22719
  }
@@ -22373,21 +22787,21 @@ function handleShieldDisable(args) {
22373
22787
  writeActiveShields(active.filter((s) => s !== name));
22374
22788
  return `Shield "${name}" disabled.`;
22375
22789
  }
22376
- 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");
22377
22791
  var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
22378
22792
  function readGlobalConfigRaw() {
22379
22793
  try {
22380
- if (import_fs41.default.existsSync(GLOBAL_CONFIG_PATH)) {
22381
- 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"));
22382
22796
  }
22383
22797
  } catch {
22384
22798
  }
22385
22799
  return {};
22386
22800
  }
22387
22801
  function writeGlobalConfigRaw(data) {
22388
- const dir = import_path43.default.dirname(GLOBAL_CONFIG_PATH);
22389
- if (!import_fs41.default.existsSync(dir)) import_fs41.default.mkdirSync(dir, { recursive: true });
22390
- 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");
22391
22805
  }
22392
22806
  function handleApproverList() {
22393
22807
  const config = getConfig();
@@ -22431,9 +22845,9 @@ function handleApproverSet(args) {
22431
22845
  function handleAuditGet(args) {
22432
22846
  const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
22433
22847
  const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
22434
- const auditPath = import_path43.default.join(import_os37.default.homedir(), ".node9", "audit.log");
22435
- if (!import_fs41.default.existsSync(auditPath)) return "No audit log found.";
22436
- 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);
22437
22851
  const parsed = [];
22438
22852
  for (const line of rawLines) {
22439
22853
  try {
@@ -22768,7 +23182,7 @@ function registerTrustCommand(program2) {
22768
23182
  // src/cli/commands/mcp-pin.ts
22769
23183
  var import_chalk21 = __toESM(require("chalk"));
22770
23184
  init_mcp_pin();
22771
- var import_fs42 = __toESM(require("fs"));
23185
+ var import_fs44 = __toESM(require("fs"));
22772
23186
  function registerMcpPinCommand(program2) {
22773
23187
  const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
22774
23188
  const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
@@ -22779,7 +23193,7 @@ function registerMcpPinCommand(program2) {
22779
23193
  let repoCorrupt = false;
22780
23194
  if (found.source === "repo") {
22781
23195
  try {
22782
- const raw = import_fs42.default.readFileSync(found.path, "utf-8");
23196
+ const raw = import_fs44.default.readFileSync(found.path, "utf-8");
22783
23197
  const parsed = JSON.parse(raw);
22784
23198
  repoEntries = parsed.servers ?? {};
22785
23199
  } catch {
@@ -23092,9 +23506,9 @@ init_scan();
23092
23506
 
23093
23507
  // src/cli/commands/sessions.ts
23094
23508
  var import_chalk24 = __toESM(require("chalk"));
23095
- var import_fs43 = __toESM(require("fs"));
23096
- var import_path44 = __toESM(require("path"));
23097
- 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"));
23098
23512
  init_scan_summary();
23099
23513
  var CLAUDE_PRICING3 = {
23100
23514
  "claude-opus-4-6": { i: 5e-6, o: 25e-6, cw: 625e-8, cr: 5e-7 },
@@ -23136,10 +23550,10 @@ function encodeProjectPath(projectPath) {
23136
23550
  }
23137
23551
  function sessionJsonlPath(projectPath, sessionId) {
23138
23552
  const encoded = encodeProjectPath(projectPath);
23139
- 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`);
23140
23554
  }
23141
23555
  function projectLabel(projectPath) {
23142
- return projectPath.replace(import_os38.default.homedir(), "~");
23556
+ return projectPath.replace(import_os40.default.homedir(), "~");
23143
23557
  }
23144
23558
  function parseHistoryLines(lines) {
23145
23559
  const entries = [];
@@ -23208,10 +23622,10 @@ function parseSessionLines(lines) {
23208
23622
  return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
23209
23623
  }
23210
23624
  function loadAuditEntries(auditPath) {
23211
- 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");
23212
23626
  let raw;
23213
23627
  try {
23214
- raw = import_fs43.default.readFileSync(aPath, "utf-8");
23628
+ raw = import_fs45.default.readFileSync(aPath, "utf-8");
23215
23629
  } catch {
23216
23630
  return [];
23217
23631
  }
@@ -23247,8 +23661,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
23247
23661
  return result;
23248
23662
  }
23249
23663
  function buildGeminiSessions(days, allAuditEntries) {
23250
- const tmpDir = import_path44.default.join(import_os38.default.homedir(), ".gemini", "tmp");
23251
- 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 [];
23252
23666
  const cutoff = days !== null ? (() => {
23253
23667
  const d = /* @__PURE__ */ new Date();
23254
23668
  d.setDate(d.getDate() - days);
@@ -23257,35 +23671,35 @@ function buildGeminiSessions(days, allAuditEntries) {
23257
23671
  })() : null;
23258
23672
  let slugDirs;
23259
23673
  try {
23260
- slugDirs = import_fs43.default.readdirSync(tmpDir);
23674
+ slugDirs = import_fs45.default.readdirSync(tmpDir);
23261
23675
  } catch {
23262
23676
  return [];
23263
23677
  }
23264
23678
  const summaries = [];
23265
23679
  for (const slug of slugDirs) {
23266
- const slugPath = import_path44.default.join(tmpDir, slug);
23680
+ const slugPath = import_path46.default.join(tmpDir, slug);
23267
23681
  try {
23268
- if (!import_fs43.default.statSync(slugPath).isDirectory()) continue;
23682
+ if (!import_fs45.default.statSync(slugPath).isDirectory()) continue;
23269
23683
  } catch {
23270
23684
  continue;
23271
23685
  }
23272
- let projectRoot = import_path44.default.join(import_os38.default.homedir(), slug);
23686
+ let projectRoot = import_path46.default.join(import_os40.default.homedir(), slug);
23273
23687
  try {
23274
- 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();
23275
23689
  } catch {
23276
23690
  }
23277
- const chatsDir = import_path44.default.join(slugPath, "chats");
23278
- if (!import_fs43.default.existsSync(chatsDir)) continue;
23691
+ const chatsDir = import_path46.default.join(slugPath, "chats");
23692
+ if (!import_fs45.default.existsSync(chatsDir)) continue;
23279
23693
  let chatFiles;
23280
23694
  try {
23281
- chatFiles = import_fs43.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
23695
+ chatFiles = import_fs45.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
23282
23696
  } catch {
23283
23697
  continue;
23284
23698
  }
23285
23699
  for (const chatFile of chatFiles) {
23286
23700
  let raw;
23287
23701
  try {
23288
- 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");
23289
23703
  } catch {
23290
23704
  continue;
23291
23705
  }
@@ -23365,8 +23779,8 @@ function buildGeminiSessions(days, allAuditEntries) {
23365
23779
  return summaries;
23366
23780
  }
23367
23781
  function buildCodexSessions(days, allAuditEntries) {
23368
- const sessionsBase = import_path44.default.join(import_os38.default.homedir(), ".codex", "sessions");
23369
- 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 [];
23370
23784
  const cutoff = days !== null ? (() => {
23371
23785
  const d = /* @__PURE__ */ new Date();
23372
23786
  d.setDate(d.getDate() - days);
@@ -23375,29 +23789,29 @@ function buildCodexSessions(days, allAuditEntries) {
23375
23789
  })() : null;
23376
23790
  const jsonlFiles = [];
23377
23791
  try {
23378
- for (const year of import_fs43.default.readdirSync(sessionsBase)) {
23379
- 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);
23380
23794
  try {
23381
- if (!import_fs43.default.statSync(yearPath).isDirectory()) continue;
23795
+ if (!import_fs45.default.statSync(yearPath).isDirectory()) continue;
23382
23796
  } catch {
23383
23797
  continue;
23384
23798
  }
23385
- for (const month of import_fs43.default.readdirSync(yearPath)) {
23386
- 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);
23387
23801
  try {
23388
- if (!import_fs43.default.statSync(monthPath).isDirectory()) continue;
23802
+ if (!import_fs45.default.statSync(monthPath).isDirectory()) continue;
23389
23803
  } catch {
23390
23804
  continue;
23391
23805
  }
23392
- for (const day of import_fs43.default.readdirSync(monthPath)) {
23393
- 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);
23394
23808
  try {
23395
- if (!import_fs43.default.statSync(dayPath).isDirectory()) continue;
23809
+ if (!import_fs45.default.statSync(dayPath).isDirectory()) continue;
23396
23810
  } catch {
23397
23811
  continue;
23398
23812
  }
23399
- for (const file of import_fs43.default.readdirSync(dayPath)) {
23400
- 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));
23401
23815
  }
23402
23816
  }
23403
23817
  }
@@ -23409,7 +23823,7 @@ function buildCodexSessions(days, allAuditEntries) {
23409
23823
  for (const filePath of jsonlFiles) {
23410
23824
  let lines;
23411
23825
  try {
23412
- lines = import_fs43.default.readFileSync(filePath, "utf-8").split("\n");
23826
+ lines = import_fs45.default.readFileSync(filePath, "utf-8").split("\n");
23413
23827
  } catch {
23414
23828
  continue;
23415
23829
  }
@@ -23487,10 +23901,10 @@ function buildCodexSessions(days, allAuditEntries) {
23487
23901
  return summaries;
23488
23902
  }
23489
23903
  function buildSessions(days, historyPath) {
23490
- 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");
23491
23905
  let historyRaw;
23492
23906
  try {
23493
- historyRaw = import_fs43.default.readFileSync(hPath, "utf-8");
23907
+ historyRaw = import_fs45.default.readFileSync(hPath, "utf-8");
23494
23908
  } catch {
23495
23909
  return [];
23496
23910
  }
@@ -23515,7 +23929,7 @@ function buildSessions(days, historyPath) {
23515
23929
  const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
23516
23930
  let sessionLines = [];
23517
23931
  try {
23518
- sessionLines = import_fs43.default.readFileSync(jsonlFile, "utf-8").split("\n");
23932
+ sessionLines = import_fs45.default.readFileSync(jsonlFile, "utf-8").split("\n");
23519
23933
  } catch {
23520
23934
  }
23521
23935
  const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
@@ -23783,8 +24197,8 @@ function registerSessionsCommand(program2) {
23783
24197
  console.log("");
23784
24198
  console.log(import_chalk24.default.cyan.bold("\u{1F4CB} node9 sessions") + import_chalk24.default.dim(" \u2014 what your AI agent did"));
23785
24199
  console.log("");
23786
- const historyPath = import_path44.default.join(import_os38.default.homedir(), ".claude", "history.jsonl");
23787
- 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)) {
23788
24202
  console.log(import_chalk24.default.yellow(" No Claude session history found at ~/.claude/history.jsonl"));
23789
24203
  console.log(import_chalk24.default.gray(" Install Claude Code, run a few sessions, then try again.\n"));
23790
24204
  return;
@@ -23821,12 +24235,12 @@ function registerSessionsCommand(program2) {
23821
24235
 
23822
24236
  // src/cli/commands/skill-pin.ts
23823
24237
  var import_chalk25 = __toESM(require("chalk"));
23824
- var import_fs44 = __toESM(require("fs"));
23825
- var import_os39 = __toESM(require("os"));
23826
- 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"));
23827
24241
  function wipeSkillSessions() {
23828
24242
  try {
23829
- 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"), {
23830
24244
  recursive: true,
23831
24245
  force: true
23832
24246
  });
@@ -23908,15 +24322,15 @@ function registerSkillPinCommand(program2) {
23908
24322
  }
23909
24323
 
23910
24324
  // src/cli/commands/decisions.ts
23911
- var import_fs45 = __toESM(require("fs"));
23912
- var import_os40 = __toESM(require("os"));
23913
- 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"));
23914
24328
  var import_chalk26 = __toESM(require("chalk"));
23915
- 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");
23916
24330
  function readDecisions() {
23917
24331
  try {
23918
- if (!import_fs45.default.existsSync(DECISIONS_FILE2)) return {};
23919
- 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");
23920
24334
  const parsed = JSON.parse(raw);
23921
24335
  const out = {};
23922
24336
  for (const [k, v] of Object.entries(parsed)) {
@@ -23928,11 +24342,11 @@ function readDecisions() {
23928
24342
  }
23929
24343
  }
23930
24344
  function writeDecisions(d) {
23931
- const dir = import_path46.default.dirname(DECISIONS_FILE2);
23932
- 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 });
23933
24347
  const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
23934
- import_fs45.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
23935
- 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);
23936
24350
  }
23937
24351
  function registerDecisionsCommand(program2) {
23938
24352
  const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
@@ -23989,18 +24403,18 @@ Persistent decisions (${entries.length})
23989
24403
 
23990
24404
  // src/cli/commands/dlp.ts
23991
24405
  var import_chalk27 = __toESM(require("chalk"));
23992
- var import_fs46 = __toESM(require("fs"));
23993
- var import_path47 = __toESM(require("path"));
23994
- var import_os41 = __toESM(require("os"));
23995
- var AUDIT_LOG = import_path47.default.join(import_os41.default.homedir(), ".node9", "audit.log");
23996
- 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");
23997
24411
  var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
23998
24412
  function stripAnsi(s) {
23999
24413
  return s.replace(ANSI_RE, "");
24000
24414
  }
24001
24415
  function loadResolved() {
24002
24416
  try {
24003
- 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"));
24004
24418
  return new Set(raw);
24005
24419
  } catch {
24006
24420
  return /* @__PURE__ */ new Set();
@@ -24008,13 +24422,13 @@ function loadResolved() {
24008
24422
  }
24009
24423
  function saveResolved(resolved) {
24010
24424
  try {
24011
- 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 });
24012
24426
  } catch {
24013
24427
  }
24014
24428
  }
24015
24429
  function loadDlpFindings() {
24016
- if (!import_fs46.default.existsSync(AUDIT_LOG)) return [];
24017
- 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) => {
24018
24432
  if (!line.trim()) return [];
24019
24433
  try {
24020
24434
  const e = JSON.parse(line);
@@ -24112,15 +24526,15 @@ function registerDlpCommand(program2) {
24112
24526
 
24113
24527
  // src/cli/commands/mask.ts
24114
24528
  var import_chalk28 = __toESM(require("chalk"));
24115
- var import_fs47 = __toESM(require("fs"));
24116
- var import_path48 = __toESM(require("path"));
24117
- 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"));
24118
24532
  init_dlp();
24119
24533
  function findJsonlFiles(dir) {
24120
24534
  const results = [];
24121
- if (!import_fs47.default.existsSync(dir)) return results;
24122
- for (const entry of import_fs47.default.readdirSync(dir, { withFileTypes: true })) {
24123
- 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);
24124
24538
  if (entry.isDirectory()) results.push(...findJsonlFiles(full));
24125
24539
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
24126
24540
  }
@@ -24163,7 +24577,7 @@ function redactJson(obj) {
24163
24577
  function processFile(filePath, dryRun) {
24164
24578
  let raw;
24165
24579
  try {
24166
- raw = import_fs47.default.readFileSync(filePath, "utf-8");
24580
+ raw = import_fs49.default.readFileSync(filePath, "utf-8");
24167
24581
  } catch {
24168
24582
  return { redactedLines: 0, patterns: [] };
24169
24583
  }
@@ -24195,14 +24609,14 @@ function processFile(filePath, dryRun) {
24195
24609
  }
24196
24610
  }
24197
24611
  if (!dryRun && redactedLines > 0) {
24198
- import_fs47.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
24612
+ import_fs49.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
24199
24613
  }
24200
24614
  return { redactedLines, patterns };
24201
24615
  }
24202
24616
  function processJsonFile(filePath, dryRun) {
24203
24617
  let raw;
24204
24618
  try {
24205
- raw = import_fs47.default.readFileSync(filePath, "utf-8");
24619
+ raw = import_fs49.default.readFileSync(filePath, "utf-8");
24206
24620
  } catch {
24207
24621
  return { redactedLines: 0, patterns: [] };
24208
24622
  }
@@ -24215,15 +24629,15 @@ function processJsonFile(filePath, dryRun) {
24215
24629
  const { value, modified, found } = redactJson(parsed);
24216
24630
  if (!modified) return { redactedLines: 0, patterns: [] };
24217
24631
  if (!dryRun) {
24218
- 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");
24219
24633
  }
24220
24634
  return { redactedLines: 1, patterns: found };
24221
24635
  }
24222
24636
  function findJsonFiles(dir) {
24223
24637
  const results = [];
24224
- if (!import_fs47.default.existsSync(dir)) return results;
24225
- for (const entry of import_fs47.default.readdirSync(dir, { withFileTypes: true })) {
24226
- 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);
24227
24641
  if (entry.isDirectory()) results.push(...findJsonFiles(full));
24228
24642
  else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
24229
24643
  }
@@ -24232,9 +24646,9 @@ function findJsonFiles(dir) {
24232
24646
  function registerMaskCommand(program2) {
24233
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) => {
24234
24648
  const dryRun = !!options.dryRun;
24235
- const home = import_os42.default.homedir();
24236
- const claudeDir = import_path48.default.join(home, ".claude", "projects");
24237
- 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");
24238
24652
  const allFiles = [
24239
24653
  ...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
24240
24654
  ...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
@@ -24242,7 +24656,7 @@ function registerMaskCommand(program2) {
24242
24656
  const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
24243
24657
  const filtered = cutoff ? allFiles.filter((f) => {
24244
24658
  try {
24245
- return import_fs47.default.statSync(f.path).mtime >= cutoff;
24659
+ return import_fs49.default.statSync(f.path).mtime >= cutoff;
24246
24660
  } catch {
24247
24661
  return false;
24248
24662
  }
@@ -24298,20 +24712,20 @@ function registerMaskCommand(program2) {
24298
24712
  // src/cli.ts
24299
24713
  init_blast();
24300
24714
  var { version } = JSON.parse(
24301
- 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")
24302
24716
  );
24303
24717
  var program = new import_commander.Command();
24304
24718
  program.name("node9").description("The Sudo Command for AI Agents").version(version);
24305
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) => {
24306
24720
  const DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept";
24307
- const credPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "credentials.json");
24308
- if (!import_fs50.default.existsSync(import_path51.default.dirname(credPath)))
24309
- 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 });
24310
24724
  const profileName = options.profile || "default";
24311
24725
  let existingCreds = {};
24312
24726
  try {
24313
- if (import_fs50.default.existsSync(credPath)) {
24314
- 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"));
24315
24729
  if (raw.apiKey) {
24316
24730
  existingCreds = {
24317
24731
  default: { apiKey: raw.apiKey, apiUrl: raw.apiUrl || DEFAULT_API_URL2 }
@@ -24323,14 +24737,14 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
24323
24737
  } catch {
24324
24738
  }
24325
24739
  existingCreds[profileName] = { apiKey, apiUrl: DEFAULT_API_URL2 };
24326
- 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 });
24327
24741
  let effectiveCloud = null;
24328
24742
  if (profileName === "default") {
24329
- 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");
24330
24744
  let config = {};
24331
24745
  try {
24332
- if (import_fs50.default.existsSync(configPath))
24333
- 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"));
24334
24748
  } catch {
24335
24749
  }
24336
24750
  if (!config.settings || typeof config.settings !== "object") config.settings = {};
@@ -24345,9 +24759,9 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
24345
24759
  approvers.cloud = false;
24346
24760
  }
24347
24761
  s.approvers = approvers;
24348
- if (!import_fs50.default.existsSync(import_path51.default.dirname(configPath)))
24349
- import_fs50.default.mkdirSync(import_path51.default.dirname(configPath), { recursive: true });
24350
- 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 });
24351
24765
  effectiveCloud = approvers.cloud === true;
24352
24766
  }
24353
24767
  if (options.profile && profileName !== "default") {
@@ -24506,15 +24920,15 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
24506
24920
  }
24507
24921
  }
24508
24922
  if (options.purge) {
24509
- const node9Dir = import_path51.default.join(import_os45.default.homedir(), ".node9");
24510
- 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)) {
24511
24925
  const confirmed = await (0, import_prompts2.confirm)({
24512
24926
  message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
24513
24927
  default: false
24514
24928
  });
24515
24929
  if (confirmed) {
24516
- import_fs50.default.rmSync(node9Dir, { recursive: true });
24517
- if (import_fs50.default.existsSync(node9Dir)) {
24930
+ import_fs52.default.rmSync(node9Dir, { recursive: true });
24931
+ if (import_fs52.default.existsSync(node9Dir)) {
24518
24932
  console.error(
24519
24933
  import_chalk30.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
24520
24934
  );
@@ -24629,7 +25043,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
24629
25043
  });
24630
25044
  program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
24631
25045
  try {
24632
- const dashboardPath = import_path51.default.join(__dirname, "dashboard.mjs");
25046
+ const dashboardPath = import_path53.default.join(__dirname, "dashboard.mjs");
24633
25047
  const dynamicImport = new Function("id", "return import(id)");
24634
25048
  const mod = await dynamicImport(`file://${dashboardPath}`);
24635
25049
  await mod.startMonitor();
@@ -24667,14 +25081,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
24667
25081
  Run "node9 addto claude" to register it as the statusLine.`
24668
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) => {
24669
25083
  if (subcommand === "debug") {
24670
- 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");
24671
25085
  if (state === "on") {
24672
- import_fs50.default.mkdirSync(import_path51.default.dirname(flagFile), { recursive: true });
24673
- import_fs50.default.writeFileSync(flagFile, "");
25086
+ import_fs52.default.mkdirSync(import_path53.default.dirname(flagFile), { recursive: true });
25087
+ import_fs52.default.writeFileSync(flagFile, "");
24674
25088
  console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
24675
25089
  console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
24676
25090
  } else if (state === "off") {
24677
- if (import_fs50.default.existsSync(flagFile)) import_fs50.default.unlinkSync(flagFile);
25091
+ if (import_fs52.default.existsSync(flagFile)) import_fs52.default.unlinkSync(flagFile);
24678
25092
  console.log("HUD debug logging disabled.");
24679
25093
  } else {
24680
25094
  console.error("Usage: node9 hud debug on|off");
@@ -24791,9 +25205,9 @@ if (process.argv[2] !== "daemon") {
24791
25205
  const isCheckHook = process.argv[2] === "check";
24792
25206
  if (isCheckHook) {
24793
25207
  if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
24794
- 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");
24795
25209
  const msg = reason instanceof Error ? reason.message : String(reason);
24796
- import_fs50.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
25210
+ import_fs52.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
24797
25211
  `);
24798
25212
  }
24799
25213
  process.exit(0);