@node9/proxy 1.35.0 → 1.35.2

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.
Files changed (3) hide show
  1. package/dist/cli.js +478 -467
  2. package/dist/cli.mjs +474 -463
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -206,8 +206,8 @@ function sanitizeConfig(raw) {
206
206
  }
207
207
  }
208
208
  const lines = result.error.issues.map((issue) => {
209
- const path54 = issue.path.length > 0 ? issue.path.join(".") : "root";
210
- return ` \u2022 ${path54}: ${issue.message}`;
209
+ const path55 = issue.path.length > 0 ? issue.path.join(".") : "root";
210
+ return ` \u2022 ${path55}: ${issue.message}`;
211
211
  });
212
212
  return {
213
213
  sanitized,
@@ -1256,9 +1256,9 @@ function matchesPattern(text, patterns) {
1256
1256
  const withoutDotSlash = text.replace(/^\.\//, "");
1257
1257
  return isMatch(withoutDotSlash) || isMatch(`./${withoutDotSlash}`);
1258
1258
  }
1259
- function getNestedValue(obj, path54) {
1259
+ function getNestedValue(obj, path55) {
1260
1260
  if (!obj || typeof obj !== "object") return null;
1261
- const segments = path54.split(".");
1261
+ const segments = path55.split(".");
1262
1262
  for (const seg of segments) {
1263
1263
  if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
1264
1264
  }
@@ -8154,7 +8154,7 @@ function binaryInPath(binary) {
8154
8154
  return false;
8155
8155
  }
8156
8156
  function detectAgents(homeDir2 = import_os12.default.homedir()) {
8157
- const exists = (p) => {
8157
+ const exists2 = (p) => {
8158
8158
  try {
8159
8159
  return import_fs13.default.existsSync(p);
8160
8160
  } catch (err2) {
@@ -8168,7 +8168,7 @@ function detectAgents(homeDir2 = import_os12.default.homedir()) {
8168
8168
  };
8169
8169
  const desktopPath = claudeDesktopConfigPath(homeDir2);
8170
8170
  return {
8171
- claude: exists(import_path15.default.join(homeDir2, ".claude")) || exists(import_path15.default.join(homeDir2, ".claude.json")),
8171
+ claude: exists2(import_path15.default.join(homeDir2, ".claude")) || exists2(import_path15.default.join(homeDir2, ".claude.json")),
8172
8172
  // Antigravity (agy) shares the ~/.gemini root, so a bare
8173
8173
  // `exists(~/.gemini)` would report the (EOL'd) Gemini CLI as
8174
8174
  // installed on every agy machine — and `node9 init` would then
@@ -8178,35 +8178,35 @@ function detectAgents(homeDir2 = import_os12.default.homedir()) {
8178
8178
  // creates ~/.gemini/settings.json on first run; agy does not touch
8179
8179
  // it (it uses antigravity-cli/settings.json) — that file is the
8180
8180
  // legacy-CLI discriminator.
8181
- gemini: exists(import_path15.default.join(homeDir2, ".gemini", "settings.json")) || binaryInPath("gemini"),
8181
+ gemini: exists2(import_path15.default.join(homeDir2, ".gemini", "settings.json")) || binaryInPath("gemini"),
8182
8182
  // agy creates ~/.gemini/antigravity-cli/ on first launch; the IDE
8183
8183
  // creates antigravity-ide/. PATH fallback covers installed-but-
8184
8184
  // never-launched (same class as opencode #186).
8185
- antigravity: exists(import_path15.default.join(homeDir2, ".gemini", "antigravity-cli")) || exists(import_path15.default.join(homeDir2, ".gemini", "antigravity-ide")) || binaryInPath("agy"),
8185
+ antigravity: exists2(import_path15.default.join(homeDir2, ".gemini", "antigravity-cli")) || exists2(import_path15.default.join(homeDir2, ".gemini", "antigravity-ide")) || binaryInPath("agy"),
8186
8186
  // GitHub Copilot CLI creates ~/.copilot on first launch; PATH
8187
8187
  // fallback covers installed-but-never-launched (same as opencode #186).
8188
- copilot: exists(import_path15.default.join(homeDir2, ".copilot")) || binaryInPath("copilot"),
8189
- cursor: exists(import_path15.default.join(homeDir2, ".cursor")),
8190
- codex: exists(import_path15.default.join(homeDir2, ".codex")),
8191
- windsurf: exists(import_path15.default.join(homeDir2, ".codeium", "windsurf")),
8192
- vscode: exists(import_path15.default.join(homeDir2, ".vscode")),
8193
- claudeDesktop: desktopPath !== null && exists(import_path15.default.dirname(desktopPath)),
8188
+ copilot: exists2(import_path15.default.join(homeDir2, ".copilot")) || binaryInPath("copilot"),
8189
+ cursor: exists2(import_path15.default.join(homeDir2, ".cursor")),
8190
+ codex: exists2(import_path15.default.join(homeDir2, ".codex")),
8191
+ windsurf: exists2(import_path15.default.join(homeDir2, ".codeium", "windsurf")),
8192
+ vscode: exists2(import_path15.default.join(homeDir2, ".vscode")),
8193
+ claudeDesktop: desktopPath !== null && exists2(import_path15.default.dirname(desktopPath)),
8194
8194
  // Opencode creates ~/.config/opencode lazily on first launch — fall back
8195
8195
  // to a PATH lookup so installed-but-never-launched CLIs are still wired.
8196
- opencode: exists(import_path15.default.join(homeDir2, ".config", "opencode")) || binaryInPath("opencode"),
8196
+ opencode: exists2(import_path15.default.join(homeDir2, ".config", "opencode")) || binaryInPath("opencode"),
8197
8197
  // Pi (https://pi.dev): config dir is ~/.pi/agent (CONFIG_DIR_NAME=".pi"
8198
8198
  // + agentDir, verified against opensources/pi-main/packages/coding-agent/
8199
8199
  // src/config.ts:449,475). The Bun-compiled binary path may create this
8200
8200
  // dir lazily on first launch — same class of bug as opencode's #186
8201
8201
  // (design R6) — so fall back to PATH lookup for installed-but-never-
8202
8202
  // launched pi.
8203
- pi: exists(import_path15.default.join(homeDir2, ".pi", "agent")) || binaryInPath("pi"),
8203
+ pi: exists2(import_path15.default.join(homeDir2, ".pi", "agent")) || binaryInPath("pi"),
8204
8204
  // Hermes Agent (https://github.com/NousResearch/hermes-agent): home dir
8205
8205
  // is $HERMES_HOME (default ~/.hermes) per hermes_constants.py:30. config.yaml
8206
8206
  // appears after `hermes setup` has run; the directory alone exists from
8207
8207
  // install time. PATH fallback covers the rare case where the user blew
8208
8208
  // away ~/.hermes but kept the binary.
8209
- hermes: exists(hermesHomeDir(homeDir2)) || binaryInPath("hermes")
8209
+ hermes: exists2(hermesHomeDir(homeDir2)) || binaryInPath("hermes")
8210
8210
  };
8211
8211
  }
8212
8212
  async function setupCursor() {
@@ -16951,20 +16951,20 @@ function getModelContextLimit(model) {
16951
16951
  return 2e5;
16952
16952
  }
16953
16953
  function readSessionUsage() {
16954
- const projectsDir = import_path51.default.join(import_os45.default.homedir(), ".claude", "projects");
16955
- if (!import_fs50.default.existsSync(projectsDir)) return null;
16954
+ const projectsDir = import_path52.default.join(import_os46.default.homedir(), ".claude", "projects");
16955
+ if (!import_fs51.default.existsSync(projectsDir)) return null;
16956
16956
  let latestFile = null;
16957
16957
  let latestMtime = 0;
16958
16958
  try {
16959
- for (const dir of import_fs50.default.readdirSync(projectsDir)) {
16960
- const dirPath = import_path51.default.join(projectsDir, dir);
16959
+ for (const dir of import_fs51.default.readdirSync(projectsDir)) {
16960
+ const dirPath = import_path52.default.join(projectsDir, dir);
16961
16961
  try {
16962
- if (!import_fs50.default.statSync(dirPath).isDirectory()) continue;
16963
- for (const file of import_fs50.default.readdirSync(dirPath)) {
16962
+ if (!import_fs51.default.statSync(dirPath).isDirectory()) continue;
16963
+ for (const file of import_fs51.default.readdirSync(dirPath)) {
16964
16964
  if (!file.endsWith(".jsonl") || file.startsWith("agent-")) continue;
16965
- const filePath = import_path51.default.join(dirPath, file);
16965
+ const filePath = import_path52.default.join(dirPath, file);
16966
16966
  try {
16967
- const mtime = import_fs50.default.statSync(filePath).mtimeMs;
16967
+ const mtime = import_fs51.default.statSync(filePath).mtimeMs;
16968
16968
  if (mtime > latestMtime) {
16969
16969
  latestMtime = mtime;
16970
16970
  latestFile = filePath;
@@ -16979,7 +16979,7 @@ function readSessionUsage() {
16979
16979
  }
16980
16980
  if (!latestFile) return null;
16981
16981
  try {
16982
- const lines = import_fs50.default.readFileSync(latestFile, "utf-8").split("\n");
16982
+ const lines = import_fs51.default.readFileSync(latestFile, "utf-8").split("\n");
16983
16983
  let lastModel = "";
16984
16984
  let lastInput = 0;
16985
16985
  let lastOutput = 0;
@@ -17040,7 +17040,7 @@ function formatBase(activity) {
17040
17040
  const time = new Date(activity.ts).toLocaleTimeString([], { hour12: false });
17041
17041
  const icon = getIcon(activity.tool);
17042
17042
  const toolName = activity.tool.slice(0, 16).padEnd(16);
17043
- const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os45.default.homedir(), "~");
17043
+ const argsStr = JSON.stringify(activity.args ?? {}).replace(/\s+/g, " ").replaceAll(import_os46.default.homedir(), "~");
17044
17044
  const argsPreview = argsStr.length > 70 ? argsStr.slice(0, 70) + "\u2026" : argsStr;
17045
17045
  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)}`;
17046
17046
  }
@@ -17079,9 +17079,9 @@ function renderPending(activity) {
17079
17079
  }
17080
17080
  async function ensureDaemon() {
17081
17081
  let pidPort = null;
17082
- if (import_fs50.default.existsSync(PID_FILE)) {
17082
+ if (import_fs51.default.existsSync(PID_FILE)) {
17083
17083
  try {
17084
- const { port } = JSON.parse(import_fs50.default.readFileSync(PID_FILE, "utf-8"));
17084
+ const { port } = JSON.parse(import_fs51.default.readFileSync(PID_FILE, "utf-8"));
17085
17085
  pidPort = port;
17086
17086
  } catch {
17087
17087
  console.error(import_chalk29.default.dim("\u26A0\uFE0F Could not read PID file; falling back to default port."));
@@ -17237,9 +17237,9 @@ function buildRecoveryCardLines(req) {
17237
17237
  ];
17238
17238
  }
17239
17239
  function readApproversFromDisk() {
17240
- const configPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "config.json");
17240
+ const configPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "config.json");
17241
17241
  try {
17242
- const raw = JSON.parse(import_fs50.default.readFileSync(configPath, "utf-8"));
17242
+ const raw = JSON.parse(import_fs51.default.readFileSync(configPath, "utf-8"));
17243
17243
  const settings = raw.settings ?? {};
17244
17244
  return settings.approvers ?? {};
17245
17245
  } catch {
@@ -17255,15 +17255,15 @@ function approverStatusLine() {
17255
17255
  return `${fmt("native", "native")} ${fmt("cloud", "cloud")} ${fmt("terminal", "terminal")}`;
17256
17256
  }
17257
17257
  function toggleApprover(channel) {
17258
- const configPath = import_path51.default.join(import_os45.default.homedir(), ".node9", "config.json");
17258
+ const configPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "config.json");
17259
17259
  try {
17260
- const raw = JSON.parse(import_fs50.default.readFileSync(configPath, "utf-8"));
17260
+ const raw = JSON.parse(import_fs51.default.readFileSync(configPath, "utf-8"));
17261
17261
  const settings = raw.settings ?? {};
17262
17262
  const approvers = settings.approvers ?? {};
17263
17263
  approvers[channel] = approvers[channel] === false;
17264
17264
  settings.approvers = approvers;
17265
17265
  raw.settings = settings;
17266
- import_fs50.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
17266
+ import_fs51.default.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n");
17267
17267
  } catch (err2) {
17268
17268
  process.stderr.write(`[node9] toggleApprover failed: ${String(err2)}
17269
17269
  `);
@@ -17435,8 +17435,8 @@ async function startTail(options = {}) {
17435
17435
  }
17436
17436
  postDecisionHttp(req2.id, httpDecision, authToken, port, httpOpts).catch((err2) => {
17437
17437
  try {
17438
- import_fs50.default.appendFileSync(
17439
- import_path51.default.join(import_os45.default.homedir(), ".node9", "hook-debug.log"),
17438
+ import_fs51.default.appendFileSync(
17439
+ import_path52.default.join(import_os46.default.homedir(), ".node9", "hook-debug.log"),
17440
17440
  `[tail] POST /decision failed: ${String(err2)}
17441
17441
  `
17442
17442
  );
@@ -17500,9 +17500,9 @@ async function startTail(options = {}) {
17500
17500
  };
17501
17501
  process.stdin.on("keypress", onKeypress);
17502
17502
  }
17503
- const auditLog = import_path51.default.join(import_os45.default.homedir(), ".node9", "audit.log");
17503
+ const auditLog = import_path52.default.join(import_os46.default.homedir(), ".node9", "audit.log");
17504
17504
  try {
17505
- const unackedDlp = import_fs50.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
17505
+ const unackedDlp = import_fs51.default.readFileSync(auditLog, "utf-8").split("\n").filter((l) => l.includes('"response-dlp"')).length;
17506
17506
  if (unackedDlp > 0) {
17507
17507
  console.log("");
17508
17508
  console.log(
@@ -17542,7 +17542,7 @@ async function startTail(options = {}) {
17542
17542
  if (stallWarned) return;
17543
17543
  if (Date.now() - lastActivityFromDaemon < STALL_THRESHOLD_MS) return;
17544
17544
  try {
17545
- const auditMtime = import_fs50.default.statSync(auditLog).mtimeMs;
17545
+ const auditMtime = import_fs51.default.statSync(auditLog).mtimeMs;
17546
17546
  if (Date.now() - auditMtime >= STALL_THRESHOLD_MS) return;
17547
17547
  console.log("");
17548
17548
  console.log(
@@ -17727,20 +17727,20 @@ async function startTail(options = {}) {
17727
17727
  process.exit(1);
17728
17728
  });
17729
17729
  }
17730
- 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;
17730
+ var import_http2, import_chalk29, import_fs51, import_os46, import_path52, 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;
17731
17731
  var init_tail = __esm({
17732
17732
  "src/tui/tail.ts"() {
17733
17733
  "use strict";
17734
17734
  import_http2 = __toESM(require("http"));
17735
17735
  import_chalk29 = __toESM(require("chalk"));
17736
- import_fs50 = __toESM(require("fs"));
17737
- import_os45 = __toESM(require("os"));
17738
- import_path51 = __toESM(require("path"));
17736
+ import_fs51 = __toESM(require("fs"));
17737
+ import_os46 = __toESM(require("os"));
17738
+ import_path52 = __toESM(require("path"));
17739
17739
  import_readline6 = __toESM(require("readline"));
17740
17740
  import_child_process12 = require("child_process");
17741
17741
  init_daemon2();
17742
17742
  init_daemon();
17743
- PID_FILE = import_path51.default.join(import_os45.default.homedir(), ".node9", "daemon.pid");
17743
+ PID_FILE = import_path52.default.join(import_os46.default.homedir(), ".node9", "daemon.pid");
17744
17744
  ICONS = {
17745
17745
  bash: "\u{1F4BB}",
17746
17746
  shell: "\u{1F4BB}",
@@ -17862,9 +17862,9 @@ function formatTimeLeft(resetsAt) {
17862
17862
  return ` (${m}m left)`;
17863
17863
  }
17864
17864
  function safeReadJson(filePath) {
17865
- if (!import_fs51.default.existsSync(filePath)) return null;
17865
+ if (!import_fs52.default.existsSync(filePath)) return null;
17866
17866
  try {
17867
- return JSON.parse(import_fs51.default.readFileSync(filePath, "utf-8"));
17867
+ return JSON.parse(import_fs52.default.readFileSync(filePath, "utf-8"));
17868
17868
  } catch {
17869
17869
  return null;
17870
17870
  }
@@ -17885,12 +17885,12 @@ function countHooksInFile(filePath) {
17885
17885
  return Object.keys(cfg.hooks).length;
17886
17886
  }
17887
17887
  function countRulesInDir(rulesDir) {
17888
- if (!import_fs51.default.existsSync(rulesDir)) return 0;
17888
+ if (!import_fs52.default.existsSync(rulesDir)) return 0;
17889
17889
  let count = 0;
17890
17890
  try {
17891
- for (const entry of import_fs51.default.readdirSync(rulesDir, { withFileTypes: true })) {
17891
+ for (const entry of import_fs52.default.readdirSync(rulesDir, { withFileTypes: true })) {
17892
17892
  if (entry.isDirectory()) {
17893
- count += countRulesInDir(import_path52.default.join(rulesDir, entry.name));
17893
+ count += countRulesInDir(import_path53.default.join(rulesDir, entry.name));
17894
17894
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
17895
17895
  count++;
17896
17896
  }
@@ -17901,46 +17901,46 @@ function countRulesInDir(rulesDir) {
17901
17901
  }
17902
17902
  function isSamePath(a, b) {
17903
17903
  try {
17904
- return import_path52.default.resolve(a) === import_path52.default.resolve(b);
17904
+ return import_path53.default.resolve(a) === import_path53.default.resolve(b);
17905
17905
  } catch {
17906
17906
  return false;
17907
17907
  }
17908
17908
  }
17909
17909
  function countConfigs(cwd) {
17910
- const homeDir2 = import_os46.default.homedir();
17911
- const claudeDir = import_path52.default.join(homeDir2, ".claude");
17910
+ const homeDir2 = import_os47.default.homedir();
17911
+ const claudeDir = import_path53.default.join(homeDir2, ".claude");
17912
17912
  let claudeMdCount = 0;
17913
17913
  let rulesCount = 0;
17914
17914
  let hooksCount = 0;
17915
17915
  const userMcpServers = /* @__PURE__ */ new Set();
17916
17916
  const projectMcpServers = /* @__PURE__ */ new Set();
17917
- if (import_fs51.default.existsSync(import_path52.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
17918
- rulesCount += countRulesInDir(import_path52.default.join(claudeDir, "rules"));
17919
- const userSettings = import_path52.default.join(claudeDir, "settings.json");
17917
+ if (import_fs52.default.existsSync(import_path53.default.join(claudeDir, "CLAUDE.md"))) claudeMdCount++;
17918
+ rulesCount += countRulesInDir(import_path53.default.join(claudeDir, "rules"));
17919
+ const userSettings = import_path53.default.join(claudeDir, "settings.json");
17920
17920
  for (const name of getMcpServerNames(userSettings)) userMcpServers.add(name);
17921
17921
  hooksCount += countHooksInFile(userSettings);
17922
- const userClaudeJson = import_path52.default.join(homeDir2, ".claude.json");
17922
+ const userClaudeJson = import_path53.default.join(homeDir2, ".claude.json");
17923
17923
  for (const name of getMcpServerNames(userClaudeJson)) userMcpServers.add(name);
17924
17924
  for (const name of getDisabledMcpServers(userClaudeJson, "disabledMcpServers")) {
17925
17925
  userMcpServers.delete(name);
17926
17926
  }
17927
17927
  if (cwd) {
17928
- if (import_fs51.default.existsSync(import_path52.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
17929
- if (import_fs51.default.existsSync(import_path52.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
17930
- const projectClaudeDir = import_path52.default.join(cwd, ".claude");
17928
+ if (import_fs52.default.existsSync(import_path53.default.join(cwd, "CLAUDE.md"))) claudeMdCount++;
17929
+ if (import_fs52.default.existsSync(import_path53.default.join(cwd, "CLAUDE.local.md"))) claudeMdCount++;
17930
+ const projectClaudeDir = import_path53.default.join(cwd, ".claude");
17931
17931
  const overlapsUserScope = isSamePath(projectClaudeDir, claudeDir);
17932
17932
  if (!overlapsUserScope) {
17933
- if (import_fs51.default.existsSync(import_path52.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
17934
- rulesCount += countRulesInDir(import_path52.default.join(projectClaudeDir, "rules"));
17935
- const projSettings = import_path52.default.join(projectClaudeDir, "settings.json");
17933
+ if (import_fs52.default.existsSync(import_path53.default.join(projectClaudeDir, "CLAUDE.md"))) claudeMdCount++;
17934
+ rulesCount += countRulesInDir(import_path53.default.join(projectClaudeDir, "rules"));
17935
+ const projSettings = import_path53.default.join(projectClaudeDir, "settings.json");
17936
17936
  for (const name of getMcpServerNames(projSettings)) projectMcpServers.add(name);
17937
17937
  hooksCount += countHooksInFile(projSettings);
17938
17938
  }
17939
- if (import_fs51.default.existsSync(import_path52.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
17940
- const localSettings = import_path52.default.join(projectClaudeDir, "settings.local.json");
17939
+ if (import_fs52.default.existsSync(import_path53.default.join(projectClaudeDir, "CLAUDE.local.md"))) claudeMdCount++;
17940
+ const localSettings = import_path53.default.join(projectClaudeDir, "settings.local.json");
17941
17941
  for (const name of getMcpServerNames(localSettings)) projectMcpServers.add(name);
17942
17942
  hooksCount += countHooksInFile(localSettings);
17943
- const mcpJsonServers = getMcpServerNames(import_path52.default.join(cwd, ".mcp.json"));
17943
+ const mcpJsonServers = getMcpServerNames(import_path53.default.join(cwd, ".mcp.json"));
17944
17944
  const disabledMcpJson = getDisabledMcpServers(localSettings, "disabledMcpjsonServers");
17945
17945
  for (const name of disabledMcpJson) mcpJsonServers.delete(name);
17946
17946
  for (const name of mcpJsonServers) projectMcpServers.add(name);
@@ -17973,12 +17973,12 @@ function readActiveShieldsHud() {
17973
17973
  return shieldsCache.value;
17974
17974
  }
17975
17975
  try {
17976
- const shieldsPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "shields.json");
17977
- if (!import_fs51.default.existsSync(shieldsPath)) {
17976
+ const shieldsPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "shields.json");
17977
+ if (!import_fs52.default.existsSync(shieldsPath)) {
17978
17978
  shieldsCache = { value: [], ts: now };
17979
17979
  return [];
17980
17980
  }
17981
- const parsed = JSON.parse(import_fs51.default.readFileSync(shieldsPath, "utf-8"));
17981
+ const parsed = JSON.parse(import_fs52.default.readFileSync(shieldsPath, "utf-8"));
17982
17982
  if (!Array.isArray(parsed.active)) {
17983
17983
  shieldsCache = { value: [], ts: now };
17984
17984
  return [];
@@ -18080,17 +18080,17 @@ function renderContextLine(stdin) {
18080
18080
  async function main() {
18081
18081
  try {
18082
18082
  const [stdin, daemonStatus2] = await Promise.all([readStdin(), queryDaemon()]);
18083
- if (import_fs51.default.existsSync(import_path52.default.join(import_os46.default.homedir(), ".node9", "hud-debug"))) {
18083
+ if (import_fs52.default.existsSync(import_path53.default.join(import_os47.default.homedir(), ".node9", "hud-debug"))) {
18084
18084
  try {
18085
- const logPath = import_path52.default.join(import_os46.default.homedir(), ".node9", "hud-debug.log");
18085
+ const logPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "hud-debug.log");
18086
18086
  const MAX_LOG_SIZE = 10 * 1024 * 1024;
18087
18087
  let size = 0;
18088
18088
  try {
18089
- size = import_fs51.default.statSync(logPath).size;
18089
+ size = import_fs52.default.statSync(logPath).size;
18090
18090
  } catch {
18091
18091
  }
18092
18092
  if (size < MAX_LOG_SIZE) {
18093
- import_fs51.default.appendFileSync(
18093
+ import_fs52.default.appendFileSync(
18094
18094
  logPath,
18095
18095
  JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), stdin }) + "\n"
18096
18096
  );
@@ -18111,11 +18111,11 @@ async function main() {
18111
18111
  try {
18112
18112
  const cwd = stdin.cwd ?? process.cwd();
18113
18113
  for (const configPath of [
18114
- import_path52.default.join(cwd, "node9.config.json"),
18115
- import_path52.default.join(import_os46.default.homedir(), ".node9", "config.json")
18114
+ import_path53.default.join(cwd, "node9.config.json"),
18115
+ import_path53.default.join(import_os47.default.homedir(), ".node9", "config.json")
18116
18116
  ]) {
18117
- if (!import_fs51.default.existsSync(configPath)) continue;
18118
- const cfg = JSON.parse(import_fs51.default.readFileSync(configPath, "utf-8"));
18117
+ if (!import_fs52.default.existsSync(configPath)) continue;
18118
+ const cfg = JSON.parse(import_fs52.default.readFileSync(configPath, "utf-8"));
18119
18119
  const hud = cfg.settings?.hud;
18120
18120
  if (hud && "showEnvironmentCounts" in hud) return hud.showEnvironmentCounts !== false;
18121
18121
  }
@@ -18133,13 +18133,13 @@ async function main() {
18133
18133
  renderOffline();
18134
18134
  }
18135
18135
  }
18136
- 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;
18136
+ var import_fs52, import_path53, import_os47, import_http3, RESET3, BOLD3, DIM, RED2, GREEN2, YELLOW2, BLUE, MAGENTA, CYAN2, WHITE, BAR_FILLED, BAR_EMPTY, BAR_WIDTH, shieldsCache, SHIELDS_CACHE_TTL_MS;
18137
18137
  var init_hud = __esm({
18138
18138
  "src/cli/hud.ts"() {
18139
18139
  "use strict";
18140
- import_fs51 = __toESM(require("fs"));
18141
- import_path52 = __toESM(require("path"));
18142
- import_os46 = __toESM(require("os"));
18140
+ import_fs52 = __toESM(require("fs"));
18141
+ import_path53 = __toESM(require("path"));
18142
+ import_os47 = __toESM(require("os"));
18143
18143
  import_http3 = __toESM(require("http"));
18144
18144
  init_daemon();
18145
18145
  RESET3 = "\x1B[0m";
@@ -18166,9 +18166,9 @@ init_core();
18166
18166
  init_setup();
18167
18167
  init_daemon2();
18168
18168
  var import_chalk30 = __toESM(require("chalk"));
18169
- var import_fs52 = __toESM(require("fs"));
18170
- var import_path53 = __toESM(require("path"));
18171
- var import_os47 = __toESM(require("os"));
18169
+ var import_fs53 = __toESM(require("fs"));
18170
+ var import_path54 = __toESM(require("path"));
18171
+ var import_os48 = __toESM(require("os"));
18172
18172
  var import_prompts2 = require("@inquirer/prompts");
18173
18173
 
18174
18174
  // src/utils/duration.ts
@@ -19956,15 +19956,184 @@ function registerConfigShowCommand(program2) {
19956
19956
 
19957
19957
  // src/cli/commands/doctor.ts
19958
19958
  var import_chalk11 = __toESM(require("chalk"));
19959
- var import_fs38 = __toESM(require("fs"));
19960
- var import_path39 = __toESM(require("path"));
19961
- var import_os34 = __toESM(require("os"));
19959
+ var import_fs39 = __toESM(require("fs"));
19960
+ var import_path40 = __toESM(require("path"));
19961
+ var import_os35 = __toESM(require("os"));
19962
19962
  var import_child_process8 = require("child_process");
19963
19963
  init_daemon();
19964
19964
  init_config();
19965
+
19966
+ // src/agent-wiring.ts
19967
+ var import_fs38 = __toESM(require("fs"));
19968
+ var import_path39 = __toESM(require("path"));
19969
+ var import_os34 = __toESM(require("os"));
19970
+ var yaml2 = __toESM(require("yaml"));
19971
+ init_setup();
19972
+ function readJson2(filePath) {
19973
+ if (!import_fs38.default.existsSync(filePath)) return null;
19974
+ try {
19975
+ return JSON.parse(import_fs38.default.readFileSync(filePath, "utf-8"));
19976
+ } catch {
19977
+ return "invalid";
19978
+ }
19979
+ }
19980
+ function matchersHaveNode9Hook(matchers) {
19981
+ return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
19982
+ }
19983
+ function flatHaveNode9Hook(entries) {
19984
+ return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
19985
+ }
19986
+ function readHookRoot(filePath, format) {
19987
+ if (!import_fs38.default.existsSync(filePath)) return "absent";
19988
+ let raw;
19989
+ try {
19990
+ raw = import_fs38.default.readFileSync(filePath, "utf-8");
19991
+ } catch {
19992
+ return "absent";
19993
+ }
19994
+ try {
19995
+ const parsed = format === "yaml" ? yaml2.parse(raw) : JSON.parse(raw);
19996
+ return parsed?.hooks ?? {};
19997
+ } catch {
19998
+ return "invalid";
19999
+ }
20000
+ }
20001
+ function eventWired(root, ev, format) {
20002
+ const arr = root[ev.key];
20003
+ if (format === "matcher") return matchersHaveNode9Hook(arr);
20004
+ return flatHaveNode9Hook(arr);
20005
+ }
20006
+ function readMcp(filePath) {
20007
+ const parsed = readJson2(filePath);
20008
+ if (parsed === null || parsed === "invalid") return { wrapped: [], present: false };
20009
+ const servers = parsed.mcpServers ?? {};
20010
+ const entries = Object.entries(servers);
20011
+ const present = entries.some(([, s]) => s?.command === "node9");
20012
+ const wrapped = entries.filter(([, s]) => s?.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
20013
+ return { wrapped, present };
20014
+ }
20015
+ var exists = (p) => {
20016
+ try {
20017
+ return import_fs38.default.existsSync(p);
20018
+ } catch {
20019
+ return false;
20020
+ }
20021
+ };
20022
+ var ck = (key) => ({ key, kind: "check" });
20023
+ var lg = (key) => ({ key, kind: "log" });
20024
+ var DEFAULT_LABEL_PAD = 11;
20025
+ var hookLabelOf = (ev, pad) => `${ev.key.padEnd(pad)} (node9 ${ev.kind})`;
20026
+ var AGENT_SPECS = [
20027
+ {
20028
+ id: "claude",
20029
+ label: "Claude Code",
20030
+ setupCommand: "node9 setup claude",
20031
+ hookFile: (h) => import_path39.default.join(h, ".claude", "settings.json"),
20032
+ hookFormat: "matcher",
20033
+ hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
20034
+ mcpFile: (h) => import_path39.default.join(h, ".claude.json"),
20035
+ present: (h) => exists(import_path39.default.join(h, ".claude", "settings.json")) || exists(import_path39.default.join(h, ".claude.json"))
20036
+ },
20037
+ {
20038
+ id: "gemini",
20039
+ label: "Gemini CLI",
20040
+ setupCommand: "node9 setup gemini",
20041
+ hookFile: (h) => import_path39.default.join(h, ".gemini", "settings.json"),
20042
+ hookFormat: "matcher",
20043
+ hookEvents: [ck("BeforeTool"), lg("AfterTool")],
20044
+ mcpFile: (h) => import_path39.default.join(h, ".gemini", "settings.json"),
20045
+ present: (h) => exists(import_path39.default.join(h, ".gemini", "settings.json"))
20046
+ },
20047
+ {
20048
+ id: "codex",
20049
+ label: "Codex",
20050
+ setupCommand: "node9 setup codex",
20051
+ hookFile: (h) => import_path39.default.join(h, ".codex", "hooks.json"),
20052
+ hookFormat: "matcher",
20053
+ hookEvents: [ck("PreToolUse"), ck("UserPromptSubmit")],
20054
+ present: (h) => exists(import_path39.default.join(h, ".codex"))
20055
+ },
20056
+ {
20057
+ id: "antigravity",
20058
+ label: "Antigravity",
20059
+ setupCommand: "node9 setup antigravity",
20060
+ hookFile: (h) => import_path39.default.join(h, ".gemini", "config", "hooks.json"),
20061
+ hookFormat: "matcher",
20062
+ hookEvents: [ck("PreToolUse"), lg("PostToolUse")],
20063
+ mcpFile: (h) => import_path39.default.join(h, ".gemini", "config", "mcp_config.json"),
20064
+ present: (h) => exists(import_path39.default.join(h, ".gemini", "config", "hooks.json")) || exists(import_path39.default.join(h, ".gemini", "antigravity-cli")) || exists(import_path39.default.join(h, ".gemini", "antigravity-ide"))
20065
+ },
20066
+ {
20067
+ id: "copilot",
20068
+ label: "GitHub Copilot",
20069
+ setupCommand: "node9 setup copilot",
20070
+ hookFile: (h) => import_path39.default.join(h, ".copilot", "hooks", "node9.json"),
20071
+ hookFormat: "flat",
20072
+ hookEvents: [ck("PreToolUse"), lg("PostToolUse"), ck("UserPromptSubmit")],
20073
+ mcpFile: (h) => import_path39.default.join(h, ".copilot", "mcp-config.json"),
20074
+ present: (h) => exists(import_path39.default.join(h, ".copilot"))
20075
+ },
20076
+ {
20077
+ id: "cursor",
20078
+ label: "Cursor",
20079
+ setupCommand: "node9 setup cursor",
20080
+ // MCP-only — no hook file (see note above).
20081
+ hookFormat: "flat",
20082
+ hookEvents: [],
20083
+ mcpFile: (h) => import_path39.default.join(h, ".cursor", "mcp.json"),
20084
+ present: (h) => exists(import_path39.default.join(h, ".cursor", "mcp.json"))
20085
+ },
20086
+ {
20087
+ id: "hermes",
20088
+ label: "Hermes Agent",
20089
+ setupCommand: "node9 setup hermes",
20090
+ hookFile: (h) => hermesConfigPath(h),
20091
+ hookFormat: "yaml",
20092
+ hookEvents: [ck("pre_tool_call"), lg("post_tool_call")],
20093
+ labelPad: 14,
20094
+ // 'post_tool_call' is wider than the default
20095
+ present: (h) => exists(hermesConfigPath(h))
20096
+ }
20097
+ ];
20098
+ function getAgentWiring(home = import_os34.default.homedir()) {
20099
+ const detected = detectAgents(home);
20100
+ return AGENT_SPECS.map((spec) => {
20101
+ const root = spec.hookFile ? readHookRoot(spec.hookFile(home), spec.hookFormat) : "absent";
20102
+ const primary = spec.hookEvents[0];
20103
+ const rootPresent = root !== "absent" && root !== "invalid";
20104
+ const pad = spec.labelPad ?? DEFAULT_LABEL_PAD;
20105
+ const hooks = spec.hookEvents.map((ev) => ({
20106
+ label: hookLabelOf(ev, pad),
20107
+ wired: rootPresent && eventWired(root, ev, spec.hookFormat)
20108
+ }));
20109
+ let wireState;
20110
+ if (root === "absent") wireState = "absent";
20111
+ else if (root === "invalid") wireState = "invalid";
20112
+ else wireState = primary && eventWired(root, primary, spec.hookFormat) ? "wired" : "unwired";
20113
+ const mcp = spec.mcpFile ? readMcp(spec.mcpFile(home)) : null;
20114
+ const anyHookWired = hooks.some((h) => h.wired);
20115
+ return {
20116
+ id: spec.id,
20117
+ label: spec.label,
20118
+ setupCommand: spec.setupCommand,
20119
+ installed: detected[spec.id],
20120
+ present: spec.present(home),
20121
+ hooks,
20122
+ wireState,
20123
+ hookLabel: primary ? `${primary.key} hook` : "MCP proxy",
20124
+ settingsPath: spec.hookFile ? spec.hookFile(home) : spec.mcpFile ? spec.mcpFile(home) : "",
20125
+ configFormat: spec.hookFormat === "yaml" ? "YAML" : "JSON",
20126
+ mcpServers: mcp ? mcp.wrapped : null,
20127
+ mcpProtected: mcp ? mcp.present : false,
20128
+ isProtected: anyHookWired || (mcp?.present ?? false)
20129
+ };
20130
+ });
20131
+ }
20132
+
20133
+ // src/cli/commands/doctor.ts
19965
20134
  function registerDoctorCommand(program2, version2) {
19966
20135
  program2.command("doctor").description("Check that Node9 is installed and configured correctly").action(async () => {
19967
- const homeDir2 = import_os34.default.homedir();
20136
+ const homeDir2 = import_os35.default.homedir();
19968
20137
  let failures = 0;
19969
20138
  function pass(msg) {
19970
20139
  console.log(import_chalk11.default.green(" \u2705 ") + msg);
@@ -20013,10 +20182,10 @@ function registerDoctorCommand(program2, version2) {
20013
20182
  );
20014
20183
  }
20015
20184
  section("Configuration");
20016
- const globalConfigPath = import_path39.default.join(homeDir2, ".node9", "config.json");
20017
- if (import_fs38.default.existsSync(globalConfigPath)) {
20185
+ const globalConfigPath = import_path40.default.join(homeDir2, ".node9", "config.json");
20186
+ if (import_fs39.default.existsSync(globalConfigPath)) {
20018
20187
  try {
20019
- JSON.parse(import_fs38.default.readFileSync(globalConfigPath, "utf-8"));
20188
+ JSON.parse(import_fs39.default.readFileSync(globalConfigPath, "utf-8"));
20020
20189
  pass("~/.node9/config.json found and valid");
20021
20190
  } catch {
20022
20191
  fail("~/.node9/config.json is invalid JSON", "Run: node9 init --force");
@@ -20024,10 +20193,10 @@ function registerDoctorCommand(program2, version2) {
20024
20193
  } else {
20025
20194
  warn("~/.node9/config.json not found (using defaults)", "Run: node9 init");
20026
20195
  }
20027
- const projectConfigPath = import_path39.default.join(process.cwd(), "node9.config.json");
20028
- if (import_fs38.default.existsSync(projectConfigPath)) {
20196
+ const projectConfigPath = import_path40.default.join(process.cwd(), "node9.config.json");
20197
+ if (import_fs39.default.existsSync(projectConfigPath)) {
20029
20198
  try {
20030
- JSON.parse(import_fs38.default.readFileSync(projectConfigPath, "utf-8"));
20199
+ JSON.parse(import_fs39.default.readFileSync(projectConfigPath, "utf-8"));
20031
20200
  pass("node9.config.json found and valid (project)");
20032
20201
  } catch {
20033
20202
  fail(
@@ -20036,8 +20205,8 @@ function registerDoctorCommand(program2, version2) {
20036
20205
  );
20037
20206
  }
20038
20207
  }
20039
- const credsPath = import_path39.default.join(homeDir2, ".node9", "credentials.json");
20040
- if (import_fs38.default.existsSync(credsPath)) {
20208
+ const credsPath = import_path40.default.join(homeDir2, ".node9", "credentials.json");
20209
+ if (import_fs39.default.existsSync(credsPath)) {
20041
20210
  pass("Cloud credentials found (~/.node9/credentials.json)");
20042
20211
  } else {
20043
20212
  warn(
@@ -20046,62 +20215,25 @@ function registerDoctorCommand(program2, version2) {
20046
20215
  );
20047
20216
  }
20048
20217
  section("Agent Hooks");
20049
- const claudeSettingsPath = import_path39.default.join(homeDir2, ".claude", "settings.json");
20050
- if (import_fs38.default.existsSync(claudeSettingsPath)) {
20051
- try {
20052
- const cs = JSON.parse(import_fs38.default.readFileSync(claudeSettingsPath, "utf-8"));
20053
- const hasHook = cs.hooks?.PreToolUse?.some(
20054
- (m) => m.hooks.some((h) => h.command?.includes("node9") || h.command?.includes("cli.js"))
20055
- );
20056
- if (hasHook) pass("Claude Code \u2014 PreToolUse hook active");
20057
- else
20058
- fail(
20059
- "Claude Code \u2014 hooks file found but node9 hook missing",
20060
- "Run: node9 setup claude"
20061
- );
20062
- } catch {
20063
- fail("Claude Code \u2014 ~/.claude/settings.json is invalid JSON");
20064
- }
20065
- } else {
20066
- warn("Claude Code \u2014 not configured", "Run: node9 setup claude");
20067
- }
20068
- const geminiSettingsPath = import_path39.default.join(homeDir2, ".gemini", "settings.json");
20069
- if (import_fs38.default.existsSync(geminiSettingsPath)) {
20070
- try {
20071
- const gs = JSON.parse(import_fs38.default.readFileSync(geminiSettingsPath, "utf-8"));
20072
- const hasHook = gs.hooks?.BeforeTool?.some(
20073
- (m) => m.hooks.some((h) => h.command?.includes("node9") || h.command?.includes("cli.js"))
20074
- );
20075
- if (hasHook) pass("Gemini CLI \u2014 BeforeTool hook active");
20076
- else
20077
- fail(
20078
- "Gemini CLI \u2014 hooks file found but node9 hook missing",
20079
- "Run: node9 setup gemini"
20080
- );
20081
- } catch {
20082
- fail("Gemini CLI \u2014 ~/.gemini/settings.json is invalid JSON");
20218
+ const notConfigured = [];
20219
+ for (const a of getAgentWiring(homeDir2)) {
20220
+ const anyHookWired = a.hooks.some((h) => h.wired);
20221
+ if (a.isProtected) {
20222
+ pass(`${a.label} \u2014 ${anyHookWired ? `${a.hookLabel} active` : "MCP proxy active"}`);
20223
+ } else if (a.wireState === "invalid") {
20224
+ fail(`${a.label} \u2014 settings file is invalid JSON`, a.settingsPath);
20225
+ } else if (a.wireState === "unwired") {
20226
+ fail(`${a.label} \u2014 settings found but node9 hook missing`, `Run: ${a.setupCommand}`);
20227
+ } else {
20228
+ notConfigured.push(a.label);
20083
20229
  }
20084
- } else {
20085
- warn("Gemini CLI \u2014 not configured", "Run: node9 setup gemini (skip if not using Gemini)");
20086
20230
  }
20087
- const cursorHooksPath = import_path39.default.join(homeDir2, ".cursor", "hooks.json");
20088
- if (import_fs38.default.existsSync(cursorHooksPath)) {
20089
- try {
20090
- const cur = JSON.parse(import_fs38.default.readFileSync(cursorHooksPath, "utf-8"));
20091
- const hasHook = cur.hooks?.preToolUse?.some(
20092
- (h) => h.command?.includes("node9") || h.command?.includes("cli.js")
20093
- );
20094
- if (hasHook) pass("Cursor \u2014 preToolUse hook active");
20095
- else
20096
- fail(
20097
- "Cursor \u2014 hooks file found but node9 hook missing",
20098
- "Run: node9 setup cursor"
20099
- );
20100
- } catch {
20101
- fail("Cursor \u2014 ~/.cursor/hooks.json is invalid JSON");
20102
- }
20103
- } else {
20104
- warn("Cursor \u2014 not configured", "Run: node9 setup cursor (skip if not using Cursor)");
20231
+ if (notConfigured.length > 0) {
20232
+ console.log(
20233
+ import_chalk11.default.gray(
20234
+ ` \xB7 Not configured: ${notConfigured.join(", ")} \u2014 run \`node9 setup <agent>\` if you use one`
20235
+ )
20236
+ );
20105
20237
  }
20106
20238
  section("Daemon (optional)");
20107
20239
  if (isDaemonRunning()) {
@@ -20118,7 +20250,7 @@ function registerDoctorCommand(program2, version2) {
20118
20250
  try {
20119
20251
  const { shipLagBytes: shipLagBytes2, readWatermark: readWatermark2, AUDIT_SHIP_WATERMARK: AUDIT_SHIP_WATERMARK2 } = await Promise.resolve().then(() => (init_audit_shipper(), audit_shipper_exports));
20120
20252
  const cfg = getConfig();
20121
- const creds = import_fs38.default.existsSync(import_path39.default.join(import_os34.default.homedir(), ".node9", "credentials.json"));
20253
+ const creds = import_fs39.default.existsSync(import_path40.default.join(import_os35.default.homedir(), ".node9", "credentials.json"));
20122
20254
  if (!creds) {
20123
20255
  warn("Not logged in \u2014 audit rows stay local", "Run: node9 login <api-key>");
20124
20256
  } else if (!cfg.settings.approvers.cloud) {
@@ -20168,9 +20300,9 @@ function registerDoctorCommand(program2, version2) {
20168
20300
 
20169
20301
  // src/cli/commands/audit.ts
20170
20302
  var import_chalk12 = __toESM(require("chalk"));
20171
- var import_fs39 = __toESM(require("fs"));
20172
- var import_path40 = __toESM(require("path"));
20173
- var import_os35 = __toESM(require("os"));
20303
+ var import_fs40 = __toESM(require("fs"));
20304
+ var import_path41 = __toESM(require("path"));
20305
+ var import_os36 = __toESM(require("os"));
20174
20306
  function formatRelativeTime(timestamp) {
20175
20307
  const diff = Date.now() - new Date(timestamp).getTime();
20176
20308
  const sec = Math.floor(diff / 1e3);
@@ -20183,14 +20315,14 @@ function formatRelativeTime(timestamp) {
20183
20315
  }
20184
20316
  function registerAuditCommand(program2) {
20185
20317
  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) => {
20186
- const logPath = import_path40.default.join(import_os35.default.homedir(), ".node9", "audit.log");
20187
- if (!import_fs39.default.existsSync(logPath)) {
20318
+ const logPath = import_path41.default.join(import_os36.default.homedir(), ".node9", "audit.log");
20319
+ if (!import_fs40.default.existsSync(logPath)) {
20188
20320
  console.log(
20189
20321
  import_chalk12.default.yellow("No audit logs found. Run node9 with an agent to generate entries.")
20190
20322
  );
20191
20323
  return;
20192
20324
  }
20193
- const raw = import_fs39.default.readFileSync(logPath, "utf-8");
20325
+ const raw = import_fs40.default.readFileSync(logPath, "utf-8");
20194
20326
  const lines = raw.split("\n").filter((l) => l.trim() !== "");
20195
20327
  let entries = lines.flatMap((line) => {
20196
20328
  try {
@@ -20246,9 +20378,9 @@ function registerAuditCommand(program2) {
20246
20378
  var import_chalk13 = __toESM(require("chalk"));
20247
20379
 
20248
20380
  // src/cli/aggregate/report-audit.ts
20249
- var import_fs40 = __toESM(require("fs"));
20250
- var import_os36 = __toESM(require("os"));
20251
- var import_path41 = __toESM(require("path"));
20381
+ var import_fs41 = __toESM(require("fs"));
20382
+ var import_os37 = __toESM(require("os"));
20383
+ var import_path42 = __toESM(require("path"));
20252
20384
  init_costSync();
20253
20385
  init_litellm();
20254
20386
  init_cost_codex();
@@ -20331,8 +20463,8 @@ function getDateRange(period, now) {
20331
20463
  }
20332
20464
  }
20333
20465
  function parseAuditLog(logPath) {
20334
- if (!import_fs40.default.existsSync(logPath)) return [];
20335
- const raw = import_fs40.default.readFileSync(logPath, "utf-8");
20466
+ if (!import_fs41.default.existsSync(logPath)) return [];
20467
+ const raw = import_fs41.default.readFileSync(logPath, "utf-8");
20336
20468
  return raw.split("\n").flatMap((line) => {
20337
20469
  if (!line.trim()) return [];
20338
20470
  try {
@@ -20379,25 +20511,25 @@ function freezeClaudeCost(acc) {
20379
20511
  };
20380
20512
  }
20381
20513
  function processClaudeCostProject(proj, projectsDir, start, end, acc) {
20382
- const projPath = import_path41.default.join(projectsDir, proj);
20514
+ const projPath = import_path42.default.join(projectsDir, proj);
20383
20515
  let files;
20384
20516
  try {
20385
- const stat = import_fs40.default.statSync(projPath);
20517
+ const stat = import_fs41.default.statSync(projPath);
20386
20518
  if (!stat.isDirectory()) return;
20387
- files = import_fs40.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
20519
+ files = import_fs41.default.readdirSync(projPath).filter((f) => f.endsWith(".jsonl") && !f.startsWith("agent-"));
20388
20520
  } catch {
20389
20521
  return;
20390
20522
  }
20391
20523
  const startMs = start.getTime();
20392
20524
  for (const file of files) {
20393
- const filePath = import_path41.default.join(projPath, file);
20525
+ const filePath = import_path42.default.join(projPath, file);
20394
20526
  try {
20395
- if (import_fs40.default.statSync(filePath).mtimeMs < startMs) continue;
20527
+ if (import_fs41.default.statSync(filePath).mtimeMs < startMs) continue;
20396
20528
  } catch {
20397
20529
  continue;
20398
20530
  }
20399
20531
  try {
20400
- const raw = import_fs40.default.readFileSync(filePath, "utf-8");
20532
+ const raw = import_fs41.default.readFileSync(filePath, "utf-8");
20401
20533
  for (const line of raw.split("\n")) {
20402
20534
  if (!line.trim()) continue;
20403
20535
  let entry;
@@ -20447,10 +20579,10 @@ function processClaudeCostProject(proj, projectsDir, start, end, acc) {
20447
20579
  }
20448
20580
  function loadClaudeCost(start, end, projectsDir) {
20449
20581
  const acc = emptyClaudeCostAccumulator();
20450
- if (!import_fs40.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
20582
+ if (!import_fs41.default.existsSync(projectsDir)) return freezeClaudeCost(acc);
20451
20583
  let dirs;
20452
20584
  try {
20453
- dirs = import_fs40.default.readdirSync(projectsDir);
20585
+ dirs = import_fs41.default.readdirSync(projectsDir);
20454
20586
  } catch {
20455
20587
  return freezeClaudeCost(acc);
20456
20588
  }
@@ -20462,7 +20594,7 @@ function loadClaudeCost(start, end, projectsDir) {
20462
20594
  function processCodexCostFile(filePath, start, end, acc) {
20463
20595
  let lines;
20464
20596
  try {
20465
- lines = import_fs40.default.readFileSync(filePath, "utf-8").split("\n");
20597
+ lines = import_fs41.default.readFileSync(filePath, "utf-8").split("\n");
20466
20598
  } catch {
20467
20599
  return;
20468
20600
  }
@@ -20517,31 +20649,31 @@ function processCodexCostFile(filePath, start, end, acc) {
20517
20649
  }
20518
20650
  function listCodexSessionFiles2(sessionsBase) {
20519
20651
  const jsonlFiles = [];
20520
- if (!import_fs40.default.existsSync(sessionsBase)) return jsonlFiles;
20652
+ if (!import_fs41.default.existsSync(sessionsBase)) return jsonlFiles;
20521
20653
  try {
20522
- for (const year of import_fs40.default.readdirSync(sessionsBase)) {
20523
- const yearPath = import_path41.default.join(sessionsBase, year);
20654
+ for (const year of import_fs41.default.readdirSync(sessionsBase)) {
20655
+ const yearPath = import_path42.default.join(sessionsBase, year);
20524
20656
  try {
20525
- if (!import_fs40.default.statSync(yearPath).isDirectory()) continue;
20657
+ if (!import_fs41.default.statSync(yearPath).isDirectory()) continue;
20526
20658
  } catch {
20527
20659
  continue;
20528
20660
  }
20529
- for (const month of import_fs40.default.readdirSync(yearPath)) {
20530
- const monthPath = import_path41.default.join(yearPath, month);
20661
+ for (const month of import_fs41.default.readdirSync(yearPath)) {
20662
+ const monthPath = import_path42.default.join(yearPath, month);
20531
20663
  try {
20532
- if (!import_fs40.default.statSync(monthPath).isDirectory()) continue;
20664
+ if (!import_fs41.default.statSync(monthPath).isDirectory()) continue;
20533
20665
  } catch {
20534
20666
  continue;
20535
20667
  }
20536
- for (const day of import_fs40.default.readdirSync(monthPath)) {
20537
- const dayPath = import_path41.default.join(monthPath, day);
20668
+ for (const day of import_fs41.default.readdirSync(monthPath)) {
20669
+ const dayPath = import_path42.default.join(monthPath, day);
20538
20670
  try {
20539
- if (!import_fs40.default.statSync(dayPath).isDirectory()) continue;
20671
+ if (!import_fs41.default.statSync(dayPath).isDirectory()) continue;
20540
20672
  } catch {
20541
20673
  continue;
20542
20674
  }
20543
- for (const file of import_fs40.default.readdirSync(dayPath)) {
20544
- if (file.endsWith(".jsonl")) jsonlFiles.push(import_path41.default.join(dayPath, file));
20675
+ for (const file of import_fs41.default.readdirSync(dayPath)) {
20676
+ if (file.endsWith(".jsonl")) jsonlFiles.push(import_path42.default.join(dayPath, file));
20545
20677
  }
20546
20678
  }
20547
20679
  }
@@ -20606,13 +20738,13 @@ function freezeGeminiCost(acc) {
20606
20738
  function processGeminiCostFile(filePath, projectKey, start, end, acc) {
20607
20739
  const startMs = start.getTime();
20608
20740
  try {
20609
- if (import_fs40.default.statSync(filePath).mtimeMs < startMs) return;
20741
+ if (import_fs41.default.statSync(filePath).mtimeMs < startMs) return;
20610
20742
  } catch {
20611
20743
  return;
20612
20744
  }
20613
20745
  let raw;
20614
20746
  try {
20615
- raw = import_fs40.default.readFileSync(filePath, "utf-8");
20747
+ raw = import_fs41.default.readFileSync(filePath, "utf-8");
20616
20748
  } catch {
20617
20749
  return;
20618
20750
  }
@@ -20661,30 +20793,30 @@ function listGeminiSessionFiles2(geminiTmpDir2) {
20661
20793
  const out = [];
20662
20794
  let dirs;
20663
20795
  try {
20664
- if (!import_fs40.default.statSync(geminiTmpDir2).isDirectory()) return out;
20665
- dirs = import_fs40.default.readdirSync(geminiTmpDir2);
20796
+ if (!import_fs41.default.statSync(geminiTmpDir2).isDirectory()) return out;
20797
+ dirs = import_fs41.default.readdirSync(geminiTmpDir2);
20666
20798
  } catch {
20667
20799
  return out;
20668
20800
  }
20669
20801
  for (const proj of dirs) {
20670
- const chatsDir = import_path41.default.join(geminiTmpDir2, proj, "chats");
20802
+ const chatsDir = import_path42.default.join(geminiTmpDir2, proj, "chats");
20671
20803
  let files;
20672
20804
  try {
20673
- if (!import_fs40.default.statSync(chatsDir).isDirectory()) continue;
20674
- files = import_fs40.default.readdirSync(chatsDir);
20805
+ if (!import_fs41.default.statSync(chatsDir).isDirectory()) continue;
20806
+ files = import_fs41.default.readdirSync(chatsDir);
20675
20807
  } catch {
20676
20808
  continue;
20677
20809
  }
20678
20810
  for (const f of files) {
20679
20811
  if (!f.endsWith(".jsonl")) continue;
20680
- out.push({ projectKey: proj, file: import_path41.default.join(chatsDir, f) });
20812
+ out.push({ projectKey: proj, file: import_path42.default.join(chatsDir, f) });
20681
20813
  }
20682
20814
  }
20683
20815
  return out;
20684
20816
  }
20685
20817
  function loadGeminiCost(start, end, geminiTmpDir2) {
20686
20818
  const acc = emptyGeminiAccumulator();
20687
- if (!import_fs40.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
20819
+ if (!import_fs41.default.existsSync(geminiTmpDir2)) return freezeGeminiCost(acc);
20688
20820
  for (const { projectKey, file } of listGeminiSessionFiles2(geminiTmpDir2)) {
20689
20821
  processGeminiCostFile(file, projectKey, start, end, acc);
20690
20822
  }
@@ -20692,11 +20824,11 @@ function loadGeminiCost(start, end, geminiTmpDir2) {
20692
20824
  }
20693
20825
  function aggregateReportFromAudit(period, opts = {}) {
20694
20826
  const now = opts.now ?? /* @__PURE__ */ new Date();
20695
- const auditLogPath = opts.auditLogPath ?? import_path41.default.join(import_os36.default.homedir(), ".node9", "audit.log");
20696
- const claudeProjectsDir = opts.claudeProjectsDir ?? import_path41.default.join(import_os36.default.homedir(), ".claude", "projects");
20697
- const codexSessionsDir2 = opts.codexSessionsDir ?? import_path41.default.join(import_os36.default.homedir(), ".codex", "sessions");
20698
- const geminiTmpDir2 = opts.geminiTmpDir ?? import_path41.default.join(import_os36.default.homedir(), ".gemini", "tmp");
20699
- const hasAuditFile = import_fs40.default.existsSync(auditLogPath);
20827
+ const auditLogPath = opts.auditLogPath ?? import_path42.default.join(import_os37.default.homedir(), ".node9", "audit.log");
20828
+ const claudeProjectsDir = opts.claudeProjectsDir ?? import_path42.default.join(import_os37.default.homedir(), ".claude", "projects");
20829
+ const codexSessionsDir2 = opts.codexSessionsDir ?? import_path42.default.join(import_os37.default.homedir(), ".codex", "sessions");
20830
+ const geminiTmpDir2 = opts.geminiTmpDir ?? import_path42.default.join(import_os37.default.homedir(), ".gemini", "tmp");
20831
+ const hasAuditFile = import_fs41.default.existsSync(auditLogPath);
20700
20832
  const allEntries = opts.preloadedAuditEntries ?? parseAuditLog(auditLogPath);
20701
20833
  const unackedDlp = allEntries.filter((e) => e.source === "response-dlp");
20702
20834
  const { start, end } = getDateRange(period, now);
@@ -21392,53 +21524,11 @@ function registerDaemonCommand(program2) {
21392
21524
 
21393
21525
  // src/cli/commands/status.ts
21394
21526
  var import_chalk15 = __toESM(require("chalk"));
21395
- var import_fs41 = __toESM(require("fs"));
21396
- var import_path42 = __toESM(require("path"));
21397
- var import_os37 = __toESM(require("os"));
21398
- var yaml2 = __toESM(require("yaml"));
21527
+ var import_fs42 = __toESM(require("fs"));
21528
+ var import_path43 = __toESM(require("path"));
21529
+ var import_os38 = __toESM(require("os"));
21399
21530
  init_core();
21400
21531
  init_daemon();
21401
- init_setup();
21402
- function readHermesHooks(configPath) {
21403
- if (!import_fs41.default.existsSync(configPath)) return null;
21404
- let raw;
21405
- try {
21406
- raw = import_fs41.default.readFileSync(configPath, "utf-8");
21407
- } catch {
21408
- return null;
21409
- }
21410
- try {
21411
- const cfg = yaml2.parse(raw);
21412
- const has = (event) => (cfg?.hooks?.[event] ?? []).some(
21413
- (e) => typeof e?.command === "string" && isNode9Hook(e.command)
21414
- );
21415
- return { pre: has("pre_tool_call"), post: has("post_tool_call") };
21416
- } catch {
21417
- console.error(
21418
- import_chalk15.default.yellow(
21419
- ` \u26A0\uFE0F Hermes config.yaml at ${configPath} is not valid YAML \u2014 showing as unwired.`
21420
- )
21421
- );
21422
- return { pre: false, post: false };
21423
- }
21424
- }
21425
- function readJson2(filePath) {
21426
- try {
21427
- if (import_fs41.default.existsSync(filePath)) return JSON.parse(import_fs41.default.readFileSync(filePath, "utf-8"));
21428
- } catch {
21429
- }
21430
- return null;
21431
- }
21432
- function matchersHaveNode9Hook(matchers) {
21433
- return (matchers ?? []).some((m) => (m.hooks ?? []).some((h) => isNode9Hook(h.command)));
21434
- }
21435
- function flatHaveNode9Hook(entries) {
21436
- return (Array.isArray(entries) ? entries : []).some((h) => isNode9Hook(h.command));
21437
- }
21438
- function wrappedMcpServers(servers) {
21439
- if (!servers) return [];
21440
- return Object.entries(servers).filter(([, s]) => s.command === "node9" && Array.isArray(s.args) && s.args.length > 0).map(([name, s]) => `${name} \u2192 ${s.args.join(" ")}`);
21441
- }
21442
21532
  function printAgentSection(label, hookPairs, wrapped) {
21443
21533
  console.log(import_chalk15.default.bold(` ${label}`));
21444
21534
  for (const { name, present } of hookPairs) {
@@ -21492,115 +21582,36 @@ function registerStatusCommand(program2) {
21492
21582
  console.log("");
21493
21583
  const modeLabel = settings.mode === "audit" ? import_chalk15.default.blue("audit") : settings.mode === "strict" ? import_chalk15.default.red("strict") : import_chalk15.default.white("standard");
21494
21584
  console.log(` Mode: ${modeLabel}`);
21495
- const projectConfig = import_path42.default.join(process.cwd(), "node9.config.json");
21496
- const globalConfig = import_path42.default.join(import_os37.default.homedir(), ".node9", "config.json");
21585
+ const projectConfig = import_path43.default.join(process.cwd(), "node9.config.json");
21586
+ const globalConfig = import_path43.default.join(import_os38.default.homedir(), ".node9", "config.json");
21497
21587
  console.log(
21498
- ` Local: ${import_fs41.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
21588
+ ` Local: ${import_fs42.default.existsSync(projectConfig) ? import_chalk15.default.green("Active (node9.config.json)") : import_chalk15.default.gray("Not present")}`
21499
21589
  );
21500
21590
  console.log(
21501
- ` Global: ${import_fs41.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
21591
+ ` Global: ${import_fs42.default.existsSync(globalConfig) ? import_chalk15.default.green("Active (~/.node9/config.json)") : import_chalk15.default.gray("Not present")}`
21502
21592
  );
21503
21593
  if (mergedConfig.policy.sandboxPaths.length > 0) {
21504
21594
  console.log(
21505
21595
  ` Sandbox: ${import_chalk15.default.green(`${mergedConfig.policy.sandboxPaths.length} safe zones active`)}`
21506
21596
  );
21507
21597
  }
21508
- const homeDir2 = import_os37.default.homedir();
21509
- const claudeSettings = readJson2(
21510
- import_path42.default.join(homeDir2, ".claude", "settings.json")
21511
- );
21512
- const claudeConfig = readJson2(import_path42.default.join(homeDir2, ".claude.json"));
21513
- const geminiSettings = readJson2(
21514
- import_path42.default.join(homeDir2, ".gemini", "settings.json")
21515
- );
21516
- const cursorConfig = readJson2(import_path42.default.join(homeDir2, ".cursor", "mcp.json"));
21517
- const antigravityHooks = readJson2(
21518
- import_path42.default.join(homeDir2, ".gemini", "config", "hooks.json")
21519
- );
21520
- const antigravityMcp = readJson2(
21521
- import_path42.default.join(homeDir2, ".gemini", "config", "mcp_config.json")
21522
- );
21523
- 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"));
21524
- const copilotHooks = readJson2(
21525
- import_path42.default.join(homeDir2, ".copilot", "hooks", "node9.json")
21526
- );
21527
- const copilotMcp = readJson2(
21528
- import_path42.default.join(homeDir2, ".copilot", "mcp-config.json")
21529
- );
21530
- const copilotPresent = import_fs41.default.existsSync(import_path42.default.join(homeDir2, ".copilot"));
21531
- const hermesHooks = readHermesHooks(hermesConfigPath(homeDir2));
21532
- const agentFound = claudeSettings || claudeConfig || geminiSettings || cursorConfig || antigravityPresent || copilotPresent || hermesHooks;
21533
- if (agentFound) {
21598
+ const wiring = getAgentWiring(import_os38.default.homedir()).filter((a) => a.present);
21599
+ if (wiring.length > 0) {
21534
21600
  console.log("");
21535
21601
  console.log(import_chalk15.default.bold(" Agent Wiring:"));
21536
21602
  console.log("");
21537
- if (claudeSettings || claudeConfig) {
21538
- const preHook = matchersHaveNode9Hook(claudeSettings?.hooks?.PreToolUse);
21539
- const postHook = matchersHaveNode9Hook(claudeSettings?.hooks?.PostToolUse);
21540
- printAgentSection(
21541
- "Claude Code",
21542
- [
21543
- { name: "PreToolUse (node9 check)", present: preHook },
21544
- { name: "PostToolUse (node9 log)", present: postHook }
21545
- ],
21546
- wrappedMcpServers(claudeConfig?.mcpServers)
21547
- );
21548
- console.log("");
21549
- }
21550
- if (geminiSettings) {
21551
- const beforeHook = matchersHaveNode9Hook(geminiSettings.hooks?.BeforeTool);
21552
- const afterHook = matchersHaveNode9Hook(geminiSettings.hooks?.AfterTool);
21553
- printAgentSection(
21554
- "Gemini CLI",
21555
- [
21556
- { name: "BeforeTool (node9 check)", present: beforeHook },
21557
- { name: "AfterTool (node9 log)", present: afterHook }
21558
- ],
21559
- wrappedMcpServers(geminiSettings.mcpServers)
21560
- );
21561
- console.log("");
21562
- }
21563
- if (antigravityPresent) {
21564
- const preHook = matchersHaveNode9Hook(antigravityHooks?.hooks?.PreToolUse);
21565
- const postHook = matchersHaveNode9Hook(antigravityHooks?.hooks?.PostToolUse);
21566
- printAgentSection(
21567
- "Antigravity",
21568
- [
21569
- { name: "PreToolUse (node9 check)", present: preHook },
21570
- { name: "PostToolUse (node9 log)", present: postHook }
21571
- ],
21572
- wrappedMcpServers(antigravityMcp?.mcpServers)
21573
- );
21574
- console.log("");
21575
- }
21576
- if (copilotPresent) {
21577
- const preHook = flatHaveNode9Hook(copilotHooks?.hooks?.PreToolUse);
21578
- const postHook = flatHaveNode9Hook(copilotHooks?.hooks?.PostToolUse);
21579
- const promptHook = flatHaveNode9Hook(copilotHooks?.hooks?.UserPromptSubmit);
21580
- printAgentSection(
21581
- "GitHub Copilot",
21582
- [
21583
- { name: "PreToolUse (node9 check)", present: preHook },
21584
- { name: "PostToolUse (node9 log)", present: postHook },
21585
- { name: "UserPromptSubmit (node9 check)", present: promptHook }
21586
- ],
21587
- wrappedMcpServers(copilotMcp?.mcpServers)
21588
- );
21589
- console.log("");
21590
- }
21591
- if (cursorConfig) {
21592
- printAgentSection("Cursor", [], wrappedMcpServers(cursorConfig.mcpServers));
21593
- console.log("");
21594
- }
21595
- if (hermesHooks) {
21603
+ for (const a of wiring) {
21604
+ if (a.wireState === "invalid") {
21605
+ console.error(
21606
+ import_chalk15.default.yellow(
21607
+ ` \u26A0\uFE0F ${a.label} config at ${a.settingsPath} is not valid ${a.configFormat} \u2014 showing as unwired.`
21608
+ )
21609
+ );
21610
+ }
21596
21611
  printAgentSection(
21597
- "Hermes Agent",
21598
- [
21599
- { name: "pre_tool_call (node9 check)", present: hermesHooks.pre },
21600
- { name: "post_tool_call (node9 log)", present: hermesHooks.post }
21601
- ],
21602
- null
21603
- // Hermes has no MCP surface
21612
+ a.label,
21613
+ a.hooks.map((h) => ({ name: h.label, present: h.wired })),
21614
+ a.mcpServers
21604
21615
  );
21605
21616
  console.log("");
21606
21617
  }
@@ -21619,9 +21630,9 @@ function registerStatusCommand(program2) {
21619
21630
 
21620
21631
  // src/cli/commands/init.ts
21621
21632
  var import_chalk16 = __toESM(require("chalk"));
21622
- var import_fs42 = __toESM(require("fs"));
21623
- var import_path43 = __toESM(require("path"));
21624
- var import_os38 = __toESM(require("os"));
21633
+ var import_fs43 = __toESM(require("fs"));
21634
+ var import_path44 = __toESM(require("path"));
21635
+ var import_os39 = __toESM(require("os"));
21625
21636
  var import_https4 = __toESM(require("https"));
21626
21637
  init_core();
21627
21638
  init_setup();
@@ -21711,16 +21722,16 @@ function registerInitCommand(program2) {
21711
21722
  }
21712
21723
  console.log("");
21713
21724
  }
21714
- const configPath = import_path43.default.join(import_os38.default.homedir(), ".node9", "config.json");
21715
- const isFirstInstall = !import_fs42.default.existsSync(configPath);
21716
- if (import_fs42.default.existsSync(configPath) && !options.force) {
21725
+ const configPath = import_path44.default.join(import_os39.default.homedir(), ".node9", "config.json");
21726
+ const isFirstInstall = !import_fs43.default.existsSync(configPath);
21727
+ if (import_fs43.default.existsSync(configPath) && !options.force) {
21717
21728
  try {
21718
- const existing = JSON.parse(import_fs42.default.readFileSync(configPath, "utf-8"));
21729
+ const existing = JSON.parse(import_fs43.default.readFileSync(configPath, "utf-8"));
21719
21730
  const settings = existing.settings ?? {};
21720
21731
  if (settings.mode !== chosenMode) {
21721
21732
  settings.mode = chosenMode;
21722
21733
  existing.settings = settings;
21723
- import_fs42.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
21734
+ import_fs43.default.writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n");
21724
21735
  console.log(import_chalk16.default.green(`\u2705 Mode updated: ${chosenMode}`));
21725
21736
  } else {
21726
21737
  console.log(import_chalk16.default.blue(`\u2139\uFE0F Config already exists: ${configPath}`));
@@ -21733,9 +21744,9 @@ function registerInitCommand(program2) {
21733
21744
  ...DEFAULT_CONFIG,
21734
21745
  settings: { ...DEFAULT_CONFIG.settings, mode: chosenMode }
21735
21746
  };
21736
- const dir = import_path43.default.dirname(configPath);
21737
- if (!import_fs42.default.existsSync(dir)) import_fs42.default.mkdirSync(dir, { recursive: true });
21738
- import_fs42.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
21747
+ const dir = import_path44.default.dirname(configPath);
21748
+ if (!import_fs43.default.existsSync(dir)) import_fs43.default.mkdirSync(dir, { recursive: true });
21749
+ import_fs43.default.writeFileSync(configPath, JSON.stringify(configToSave, null, 2) + "\n");
21739
21750
  console.log(import_chalk16.default.green(`\u2705 Config created: ${configPath}`));
21740
21751
  console.log(import_chalk16.default.gray(` Mode: ${chosenMode}`));
21741
21752
  }
@@ -21840,7 +21851,7 @@ function registerInitCommand(program2) {
21840
21851
  }
21841
21852
 
21842
21853
  // src/cli/commands/undo.ts
21843
- var import_path44 = __toESM(require("path"));
21854
+ var import_path45 = __toESM(require("path"));
21844
21855
  var import_chalk18 = __toESM(require("chalk"));
21845
21856
 
21846
21857
  // src/tui/undo-navigator.ts
@@ -21999,7 +22010,7 @@ function findMatchingCwd(startDir, history) {
21999
22010
  let dir = startDir;
22000
22011
  while (true) {
22001
22012
  if (cwds.has(dir)) return dir;
22002
- const parent = import_path44.default.dirname(dir);
22013
+ const parent = import_path45.default.dirname(dir);
22003
22014
  if (parent === dir) return null;
22004
22015
  dir = parent;
22005
22016
  }
@@ -22634,9 +22645,9 @@ function registerMcpGatewayCommand(program2) {
22634
22645
 
22635
22646
  // src/mcp-server/index.ts
22636
22647
  var import_readline5 = __toESM(require("readline"));
22637
- var import_fs43 = __toESM(require("fs"));
22638
- var import_os39 = __toESM(require("os"));
22639
- var import_path45 = __toESM(require("path"));
22648
+ var import_fs44 = __toESM(require("fs"));
22649
+ var import_os40 = __toESM(require("os"));
22650
+ var import_path46 = __toESM(require("path"));
22640
22651
  var import_child_process11 = require("child_process");
22641
22652
  init_core();
22642
22653
  init_daemon();
@@ -22887,13 +22898,13 @@ function handleStatus() {
22887
22898
  lines.push(`Active shields: ${activeShields.length > 0 ? activeShields.join(", ") : "none"}`);
22888
22899
  lines.push(`Smart rules: ${config.policy.smartRules.length} loaded`);
22889
22900
  lines.push(`DLP: ${config.policy.dlp?.enabled !== false ? "enabled" : "disabled"}`);
22890
- const projectConfig = import_path45.default.join(process.cwd(), "node9.config.json");
22891
- const globalConfig = import_path45.default.join(import_os39.default.homedir(), ".node9", "config.json");
22901
+ const projectConfig = import_path46.default.join(process.cwd(), "node9.config.json");
22902
+ const globalConfig = import_path46.default.join(import_os40.default.homedir(), ".node9", "config.json");
22892
22903
  lines.push(
22893
- `Project config (node9.config.json): ${import_fs43.default.existsSync(projectConfig) ? "present" : "not found"}`
22904
+ `Project config (node9.config.json): ${import_fs44.default.existsSync(projectConfig) ? "present" : "not found"}`
22894
22905
  );
22895
22906
  lines.push(
22896
- `Global config (~/.node9/config.json): ${import_fs43.default.existsSync(globalConfig) ? "present" : "not found"}`
22907
+ `Global config (~/.node9/config.json): ${import_fs44.default.existsSync(globalConfig) ? "present" : "not found"}`
22897
22908
  );
22898
22909
  return lines.join("\n");
22899
22910
  }
@@ -22967,21 +22978,21 @@ function handleShieldDisable(args) {
22967
22978
  writeActiveShields(active.filter((s) => s !== name));
22968
22979
  return `Shield "${name}" disabled.`;
22969
22980
  }
22970
- var GLOBAL_CONFIG_PATH = import_path45.default.join(import_os39.default.homedir(), ".node9", "config.json");
22981
+ var GLOBAL_CONFIG_PATH = import_path46.default.join(import_os40.default.homedir(), ".node9", "config.json");
22971
22982
  var APPROVER_CHANNELS = ["native", "browser", "cloud", "terminal"];
22972
22983
  function readGlobalConfigRaw() {
22973
22984
  try {
22974
- if (import_fs43.default.existsSync(GLOBAL_CONFIG_PATH)) {
22975
- return JSON.parse(import_fs43.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
22985
+ if (import_fs44.default.existsSync(GLOBAL_CONFIG_PATH)) {
22986
+ return JSON.parse(import_fs44.default.readFileSync(GLOBAL_CONFIG_PATH, "utf-8"));
22976
22987
  }
22977
22988
  } catch {
22978
22989
  }
22979
22990
  return {};
22980
22991
  }
22981
22992
  function writeGlobalConfigRaw(data) {
22982
- const dir = import_path45.default.dirname(GLOBAL_CONFIG_PATH);
22983
- if (!import_fs43.default.existsSync(dir)) import_fs43.default.mkdirSync(dir, { recursive: true });
22984
- import_fs43.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
22993
+ const dir = import_path46.default.dirname(GLOBAL_CONFIG_PATH);
22994
+ if (!import_fs44.default.existsSync(dir)) import_fs44.default.mkdirSync(dir, { recursive: true });
22995
+ import_fs44.default.writeFileSync(GLOBAL_CONFIG_PATH, JSON.stringify(data, null, 2) + "\n");
22985
22996
  }
22986
22997
  function handleApproverList() {
22987
22998
  const config = getConfig();
@@ -23025,9 +23036,9 @@ function handleApproverSet(args) {
23025
23036
  function handleAuditGet(args) {
23026
23037
  const limit = Math.min(typeof args.limit === "number" ? args.limit : 20, 100);
23027
23038
  const filter = typeof args.filter === "string" && args.filter !== "all" ? args.filter : null;
23028
- const auditPath = import_path45.default.join(import_os39.default.homedir(), ".node9", "audit.log");
23029
- if (!import_fs43.default.existsSync(auditPath)) return "No audit log found.";
23030
- const rawLines = import_fs43.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
23039
+ const auditPath = import_path46.default.join(import_os40.default.homedir(), ".node9", "audit.log");
23040
+ if (!import_fs44.default.existsSync(auditPath)) return "No audit log found.";
23041
+ const rawLines = import_fs44.default.readFileSync(auditPath, "utf-8").trim().split("\n").filter(Boolean);
23031
23042
  const parsed = [];
23032
23043
  for (const line of rawLines) {
23033
23044
  try {
@@ -23362,7 +23373,7 @@ function registerTrustCommand(program2) {
23362
23373
  // src/cli/commands/mcp-pin.ts
23363
23374
  var import_chalk21 = __toESM(require("chalk"));
23364
23375
  init_mcp_pin();
23365
- var import_fs44 = __toESM(require("fs"));
23376
+ var import_fs45 = __toESM(require("fs"));
23366
23377
  function registerMcpPinCommand(program2) {
23367
23378
  const pinCmd = program2.command("mcp").description("Manage MCP server tool definition pinning (rug pull defense)");
23368
23379
  const pinSubCmd = pinCmd.command("pin").description("Manage pinned MCP server tool definitions");
@@ -23373,7 +23384,7 @@ function registerMcpPinCommand(program2) {
23373
23384
  let repoCorrupt = false;
23374
23385
  if (found.source === "repo") {
23375
23386
  try {
23376
- const raw = import_fs44.default.readFileSync(found.path, "utf-8");
23387
+ const raw = import_fs45.default.readFileSync(found.path, "utf-8");
23377
23388
  const parsed = JSON.parse(raw);
23378
23389
  repoEntries = parsed.servers ?? {};
23379
23390
  } catch {
@@ -23686,9 +23697,9 @@ init_scan();
23686
23697
 
23687
23698
  // src/cli/commands/sessions.ts
23688
23699
  var import_chalk24 = __toESM(require("chalk"));
23689
- var import_fs45 = __toESM(require("fs"));
23690
- var import_path46 = __toESM(require("path"));
23691
- var import_os40 = __toESM(require("os"));
23700
+ var import_fs46 = __toESM(require("fs"));
23701
+ var import_path47 = __toESM(require("path"));
23702
+ var import_os41 = __toESM(require("os"));
23692
23703
  init_scan_summary();
23693
23704
  init_litellm();
23694
23705
  init_cost_gemini();
@@ -23709,10 +23720,10 @@ function encodeProjectPath(projectPath) {
23709
23720
  }
23710
23721
  function sessionJsonlPath(projectPath, sessionId) {
23711
23722
  const encoded = encodeProjectPath(projectPath);
23712
- return import_path46.default.join(import_os40.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
23723
+ return import_path47.default.join(import_os41.default.homedir(), ".claude", "projects", encoded, `${sessionId}.jsonl`);
23713
23724
  }
23714
23725
  function projectLabel(projectPath) {
23715
- return projectPath.replace(import_os40.default.homedir(), "~");
23726
+ return projectPath.replace(import_os41.default.homedir(), "~");
23716
23727
  }
23717
23728
  function parseHistoryLines(lines) {
23718
23729
  const entries = [];
@@ -23781,10 +23792,10 @@ function parseSessionLines(lines) {
23781
23792
  return { toolCalls, costUSD, hasSnapshot, modifiedFiles };
23782
23793
  }
23783
23794
  function loadAuditEntries(auditPath) {
23784
- const aPath = auditPath ?? import_path46.default.join(import_os40.default.homedir(), ".node9", "audit.log");
23795
+ const aPath = auditPath ?? import_path47.default.join(import_os41.default.homedir(), ".node9", "audit.log");
23785
23796
  let raw;
23786
23797
  try {
23787
- raw = import_fs45.default.readFileSync(aPath, "utf-8");
23798
+ raw = import_fs46.default.readFileSync(aPath, "utf-8");
23788
23799
  } catch {
23789
23800
  return [];
23790
23801
  }
@@ -23820,8 +23831,8 @@ function auditEntriesInWindow(entries, windowStart, windowEnd) {
23820
23831
  return result;
23821
23832
  }
23822
23833
  function buildGeminiSessions(days, allAuditEntries) {
23823
- const tmpDir = import_path46.default.join(import_os40.default.homedir(), ".gemini", "tmp");
23824
- if (!import_fs45.default.existsSync(tmpDir)) return [];
23834
+ const tmpDir = import_path47.default.join(import_os41.default.homedir(), ".gemini", "tmp");
23835
+ if (!import_fs46.default.existsSync(tmpDir)) return [];
23825
23836
  const cutoff = days !== null ? (() => {
23826
23837
  const d = /* @__PURE__ */ new Date();
23827
23838
  d.setDate(d.getDate() - days);
@@ -23830,35 +23841,35 @@ function buildGeminiSessions(days, allAuditEntries) {
23830
23841
  })() : null;
23831
23842
  let slugDirs;
23832
23843
  try {
23833
- slugDirs = import_fs45.default.readdirSync(tmpDir);
23844
+ slugDirs = import_fs46.default.readdirSync(tmpDir);
23834
23845
  } catch {
23835
23846
  return [];
23836
23847
  }
23837
23848
  const summaries = [];
23838
23849
  for (const slug of slugDirs) {
23839
- const slugPath = import_path46.default.join(tmpDir, slug);
23850
+ const slugPath = import_path47.default.join(tmpDir, slug);
23840
23851
  try {
23841
- if (!import_fs45.default.statSync(slugPath).isDirectory()) continue;
23852
+ if (!import_fs46.default.statSync(slugPath).isDirectory()) continue;
23842
23853
  } catch {
23843
23854
  continue;
23844
23855
  }
23845
- let projectRoot = import_path46.default.join(import_os40.default.homedir(), slug);
23856
+ let projectRoot = import_path47.default.join(import_os41.default.homedir(), slug);
23846
23857
  try {
23847
- projectRoot = import_fs45.default.readFileSync(import_path46.default.join(slugPath, ".project_root"), "utf-8").trim();
23858
+ projectRoot = import_fs46.default.readFileSync(import_path47.default.join(slugPath, ".project_root"), "utf-8").trim();
23848
23859
  } catch {
23849
23860
  }
23850
- const chatsDir = import_path46.default.join(slugPath, "chats");
23851
- if (!import_fs45.default.existsSync(chatsDir)) continue;
23861
+ const chatsDir = import_path47.default.join(slugPath, "chats");
23862
+ if (!import_fs46.default.existsSync(chatsDir)) continue;
23852
23863
  let chatFiles;
23853
23864
  try {
23854
- chatFiles = import_fs45.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
23865
+ chatFiles = import_fs46.default.readdirSync(chatsDir).filter((f) => f.endsWith(".json"));
23855
23866
  } catch {
23856
23867
  continue;
23857
23868
  }
23858
23869
  for (const chatFile of chatFiles) {
23859
23870
  let raw;
23860
23871
  try {
23861
- raw = import_fs45.default.readFileSync(import_path46.default.join(chatsDir, chatFile), "utf-8");
23872
+ raw = import_fs46.default.readFileSync(import_path47.default.join(chatsDir, chatFile), "utf-8");
23862
23873
  } catch {
23863
23874
  continue;
23864
23875
  }
@@ -23938,8 +23949,8 @@ function buildGeminiSessions(days, allAuditEntries) {
23938
23949
  return summaries;
23939
23950
  }
23940
23951
  function buildCodexSessions(days, allAuditEntries) {
23941
- const sessionsBase = import_path46.default.join(import_os40.default.homedir(), ".codex", "sessions");
23942
- if (!import_fs45.default.existsSync(sessionsBase)) return [];
23952
+ const sessionsBase = import_path47.default.join(import_os41.default.homedir(), ".codex", "sessions");
23953
+ if (!import_fs46.default.existsSync(sessionsBase)) return [];
23943
23954
  const cutoff = days !== null ? (() => {
23944
23955
  const d = /* @__PURE__ */ new Date();
23945
23956
  d.setDate(d.getDate() - days);
@@ -23948,29 +23959,29 @@ function buildCodexSessions(days, allAuditEntries) {
23948
23959
  })() : null;
23949
23960
  const jsonlFiles = [];
23950
23961
  try {
23951
- for (const year of import_fs45.default.readdirSync(sessionsBase)) {
23952
- const yearPath = import_path46.default.join(sessionsBase, year);
23962
+ for (const year of import_fs46.default.readdirSync(sessionsBase)) {
23963
+ const yearPath = import_path47.default.join(sessionsBase, year);
23953
23964
  try {
23954
- if (!import_fs45.default.statSync(yearPath).isDirectory()) continue;
23965
+ if (!import_fs46.default.statSync(yearPath).isDirectory()) continue;
23955
23966
  } catch {
23956
23967
  continue;
23957
23968
  }
23958
- for (const month of import_fs45.default.readdirSync(yearPath)) {
23959
- const monthPath = import_path46.default.join(yearPath, month);
23969
+ for (const month of import_fs46.default.readdirSync(yearPath)) {
23970
+ const monthPath = import_path47.default.join(yearPath, month);
23960
23971
  try {
23961
- if (!import_fs45.default.statSync(monthPath).isDirectory()) continue;
23972
+ if (!import_fs46.default.statSync(monthPath).isDirectory()) continue;
23962
23973
  } catch {
23963
23974
  continue;
23964
23975
  }
23965
- for (const day of import_fs45.default.readdirSync(monthPath)) {
23966
- const dayPath = import_path46.default.join(monthPath, day);
23976
+ for (const day of import_fs46.default.readdirSync(monthPath)) {
23977
+ const dayPath = import_path47.default.join(monthPath, day);
23967
23978
  try {
23968
- if (!import_fs45.default.statSync(dayPath).isDirectory()) continue;
23979
+ if (!import_fs46.default.statSync(dayPath).isDirectory()) continue;
23969
23980
  } catch {
23970
23981
  continue;
23971
23982
  }
23972
- for (const file of import_fs45.default.readdirSync(dayPath)) {
23973
- if (file.endsWith(".jsonl")) jsonlFiles.push(import_path46.default.join(dayPath, file));
23983
+ for (const file of import_fs46.default.readdirSync(dayPath)) {
23984
+ if (file.endsWith(".jsonl")) jsonlFiles.push(import_path47.default.join(dayPath, file));
23974
23985
  }
23975
23986
  }
23976
23987
  }
@@ -23982,7 +23993,7 @@ function buildCodexSessions(days, allAuditEntries) {
23982
23993
  for (const filePath of jsonlFiles) {
23983
23994
  let lines;
23984
23995
  try {
23985
- lines = import_fs45.default.readFileSync(filePath, "utf-8").split("\n");
23996
+ lines = import_fs46.default.readFileSync(filePath, "utf-8").split("\n");
23986
23997
  } catch {
23987
23998
  continue;
23988
23999
  }
@@ -24068,10 +24079,10 @@ function buildCodexSessions(days, allAuditEntries) {
24068
24079
  return summaries;
24069
24080
  }
24070
24081
  function buildSessions(days, historyPath) {
24071
- const hPath = historyPath ?? import_path46.default.join(import_os40.default.homedir(), ".claude", "history.jsonl");
24082
+ const hPath = historyPath ?? import_path47.default.join(import_os41.default.homedir(), ".claude", "history.jsonl");
24072
24083
  let historyRaw = "";
24073
24084
  try {
24074
- historyRaw = import_fs45.default.readFileSync(hPath, "utf-8");
24085
+ historyRaw = import_fs46.default.readFileSync(hPath, "utf-8");
24075
24086
  } catch {
24076
24087
  }
24077
24088
  const cutoff = days !== null ? (() => {
@@ -24095,7 +24106,7 @@ function buildSessions(days, historyPath) {
24095
24106
  const jsonlFile = sessionJsonlPath(entry.project, entry.sessionId);
24096
24107
  let sessionLines = [];
24097
24108
  try {
24098
- sessionLines = import_fs45.default.readFileSync(jsonlFile, "utf-8").split("\n");
24109
+ sessionLines = import_fs46.default.readFileSync(jsonlFile, "utf-8").split("\n");
24099
24110
  } catch {
24100
24111
  }
24101
24112
  const { toolCalls, costUSD, hasSnapshot, modifiedFiles } = parseSessionLines(sessionLines);
@@ -24395,12 +24406,12 @@ function registerSessionsCommand(program2) {
24395
24406
 
24396
24407
  // src/cli/commands/skill-pin.ts
24397
24408
  var import_chalk25 = __toESM(require("chalk"));
24398
- var import_fs46 = __toESM(require("fs"));
24399
- var import_os41 = __toESM(require("os"));
24400
- var import_path47 = __toESM(require("path"));
24409
+ var import_fs47 = __toESM(require("fs"));
24410
+ var import_os42 = __toESM(require("os"));
24411
+ var import_path48 = __toESM(require("path"));
24401
24412
  function wipeSkillSessions() {
24402
24413
  try {
24403
- import_fs46.default.rmSync(import_path47.default.join(import_os41.default.homedir(), ".node9", "skill-sessions"), {
24414
+ import_fs47.default.rmSync(import_path48.default.join(import_os42.default.homedir(), ".node9", "skill-sessions"), {
24404
24415
  recursive: true,
24405
24416
  force: true
24406
24417
  });
@@ -24482,15 +24493,15 @@ function registerSkillPinCommand(program2) {
24482
24493
  }
24483
24494
 
24484
24495
  // src/cli/commands/decisions.ts
24485
- var import_fs47 = __toESM(require("fs"));
24486
- var import_os42 = __toESM(require("os"));
24487
- var import_path48 = __toESM(require("path"));
24496
+ var import_fs48 = __toESM(require("fs"));
24497
+ var import_os43 = __toESM(require("os"));
24498
+ var import_path49 = __toESM(require("path"));
24488
24499
  var import_chalk26 = __toESM(require("chalk"));
24489
- var DECISIONS_FILE2 = import_path48.default.join(import_os42.default.homedir(), ".node9", "decisions.json");
24500
+ var DECISIONS_FILE2 = import_path49.default.join(import_os43.default.homedir(), ".node9", "decisions.json");
24490
24501
  function readDecisions() {
24491
24502
  try {
24492
- if (!import_fs47.default.existsSync(DECISIONS_FILE2)) return {};
24493
- const raw = import_fs47.default.readFileSync(DECISIONS_FILE2, "utf-8");
24503
+ if (!import_fs48.default.existsSync(DECISIONS_FILE2)) return {};
24504
+ const raw = import_fs48.default.readFileSync(DECISIONS_FILE2, "utf-8");
24494
24505
  const parsed = JSON.parse(raw);
24495
24506
  const out = {};
24496
24507
  for (const [k, v] of Object.entries(parsed)) {
@@ -24502,11 +24513,11 @@ function readDecisions() {
24502
24513
  }
24503
24514
  }
24504
24515
  function writeDecisions(d) {
24505
- const dir = import_path48.default.dirname(DECISIONS_FILE2);
24506
- if (!import_fs47.default.existsSync(dir)) import_fs47.default.mkdirSync(dir, { recursive: true });
24516
+ const dir = import_path49.default.dirname(DECISIONS_FILE2);
24517
+ if (!import_fs48.default.existsSync(dir)) import_fs48.default.mkdirSync(dir, { recursive: true });
24507
24518
  const tmp = `${DECISIONS_FILE2}.${process.pid}.tmp`;
24508
- import_fs47.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
24509
- import_fs47.default.renameSync(tmp, DECISIONS_FILE2);
24519
+ import_fs48.default.writeFileSync(tmp, JSON.stringify(d, null, 2));
24520
+ import_fs48.default.renameSync(tmp, DECISIONS_FILE2);
24510
24521
  }
24511
24522
  function registerDecisionsCommand(program2) {
24512
24523
  const cmd = program2.command("decisions").description('Manage persistent "Always Allow" / "Always Deny" tool decisions');
@@ -24563,18 +24574,18 @@ Persistent decisions (${entries.length})
24563
24574
 
24564
24575
  // src/cli/commands/dlp.ts
24565
24576
  var import_chalk27 = __toESM(require("chalk"));
24566
- var import_fs48 = __toESM(require("fs"));
24567
- var import_path49 = __toESM(require("path"));
24568
- var import_os43 = __toESM(require("os"));
24569
- var AUDIT_LOG = import_path49.default.join(import_os43.default.homedir(), ".node9", "audit.log");
24570
- var RESOLVED_FILE = import_path49.default.join(import_os43.default.homedir(), ".node9", "dlp-resolved.json");
24577
+ var import_fs49 = __toESM(require("fs"));
24578
+ var import_path50 = __toESM(require("path"));
24579
+ var import_os44 = __toESM(require("os"));
24580
+ var AUDIT_LOG = import_path50.default.join(import_os44.default.homedir(), ".node9", "audit.log");
24581
+ var RESOLVED_FILE = import_path50.default.join(import_os44.default.homedir(), ".node9", "dlp-resolved.json");
24571
24582
  var ANSI_RE = /\x1b(?:\[[0-9;?]*[a-zA-Z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|[@-_])/g;
24572
24583
  function stripAnsi(s) {
24573
24584
  return s.replace(ANSI_RE, "");
24574
24585
  }
24575
24586
  function loadResolved() {
24576
24587
  try {
24577
- const raw = JSON.parse(import_fs48.default.readFileSync(RESOLVED_FILE, "utf-8"));
24588
+ const raw = JSON.parse(import_fs49.default.readFileSync(RESOLVED_FILE, "utf-8"));
24578
24589
  return new Set(raw);
24579
24590
  } catch {
24580
24591
  return /* @__PURE__ */ new Set();
@@ -24582,13 +24593,13 @@ function loadResolved() {
24582
24593
  }
24583
24594
  function saveResolved(resolved) {
24584
24595
  try {
24585
- import_fs48.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
24596
+ import_fs49.default.writeFileSync(RESOLVED_FILE, JSON.stringify([...resolved], null, 2), { mode: 384 });
24586
24597
  } catch {
24587
24598
  }
24588
24599
  }
24589
24600
  function loadDlpFindings() {
24590
- if (!import_fs48.default.existsSync(AUDIT_LOG)) return [];
24591
- return import_fs48.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
24601
+ if (!import_fs49.default.existsSync(AUDIT_LOG)) return [];
24602
+ return import_fs49.default.readFileSync(AUDIT_LOG, "utf-8").split("\n").flatMap((line) => {
24592
24603
  if (!line.trim()) return [];
24593
24604
  try {
24594
24605
  const e = JSON.parse(line);
@@ -24686,15 +24697,15 @@ function registerDlpCommand(program2) {
24686
24697
 
24687
24698
  // src/cli/commands/mask.ts
24688
24699
  var import_chalk28 = __toESM(require("chalk"));
24689
- var import_fs49 = __toESM(require("fs"));
24690
- var import_path50 = __toESM(require("path"));
24691
- var import_os44 = __toESM(require("os"));
24700
+ var import_fs50 = __toESM(require("fs"));
24701
+ var import_path51 = __toESM(require("path"));
24702
+ var import_os45 = __toESM(require("os"));
24692
24703
  init_dlp();
24693
24704
  function findJsonlFiles(dir) {
24694
24705
  const results = [];
24695
- if (!import_fs49.default.existsSync(dir)) return results;
24696
- for (const entry of import_fs49.default.readdirSync(dir, { withFileTypes: true })) {
24697
- const full = import_path50.default.join(dir, entry.name);
24706
+ if (!import_fs50.default.existsSync(dir)) return results;
24707
+ for (const entry of import_fs50.default.readdirSync(dir, { withFileTypes: true })) {
24708
+ const full = import_path51.default.join(dir, entry.name);
24698
24709
  if (entry.isDirectory()) results.push(...findJsonlFiles(full));
24699
24710
  else if (entry.isFile() && entry.name.endsWith(".jsonl")) results.push(full);
24700
24711
  }
@@ -24737,7 +24748,7 @@ function redactJson(obj) {
24737
24748
  function processFile(filePath, dryRun) {
24738
24749
  let raw;
24739
24750
  try {
24740
- raw = import_fs49.default.readFileSync(filePath, "utf-8");
24751
+ raw = import_fs50.default.readFileSync(filePath, "utf-8");
24741
24752
  } catch {
24742
24753
  return { redactedLines: 0, patterns: [] };
24743
24754
  }
@@ -24769,14 +24780,14 @@ function processFile(filePath, dryRun) {
24769
24780
  }
24770
24781
  }
24771
24782
  if (!dryRun && redactedLines > 0) {
24772
- import_fs49.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
24783
+ import_fs50.default.writeFileSync(filePath, newLines.join("\n"), "utf-8");
24773
24784
  }
24774
24785
  return { redactedLines, patterns };
24775
24786
  }
24776
24787
  function processJsonFile(filePath, dryRun) {
24777
24788
  let raw;
24778
24789
  try {
24779
- raw = import_fs49.default.readFileSync(filePath, "utf-8");
24790
+ raw = import_fs50.default.readFileSync(filePath, "utf-8");
24780
24791
  } catch {
24781
24792
  return { redactedLines: 0, patterns: [] };
24782
24793
  }
@@ -24789,15 +24800,15 @@ function processJsonFile(filePath, dryRun) {
24789
24800
  const { value, modified, found } = redactJson(parsed);
24790
24801
  if (!modified) return { redactedLines: 0, patterns: [] };
24791
24802
  if (!dryRun) {
24792
- import_fs49.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
24803
+ import_fs50.default.writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
24793
24804
  }
24794
24805
  return { redactedLines: 1, patterns: found };
24795
24806
  }
24796
24807
  function findJsonFiles(dir) {
24797
24808
  const results = [];
24798
- if (!import_fs49.default.existsSync(dir)) return results;
24799
- for (const entry of import_fs49.default.readdirSync(dir, { withFileTypes: true })) {
24800
- const full = import_path50.default.join(dir, entry.name);
24809
+ if (!import_fs50.default.existsSync(dir)) return results;
24810
+ for (const entry of import_fs50.default.readdirSync(dir, { withFileTypes: true })) {
24811
+ const full = import_path51.default.join(dir, entry.name);
24801
24812
  if (entry.isDirectory()) results.push(...findJsonFiles(full));
24802
24813
  else if (entry.isFile() && entry.name.endsWith(".json")) results.push(full);
24803
24814
  }
@@ -24806,9 +24817,9 @@ function findJsonFiles(dir) {
24806
24817
  function registerMaskCommand(program2) {
24807
24818
  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) => {
24808
24819
  const dryRun = !!options.dryRun;
24809
- const home = import_os44.default.homedir();
24810
- const claudeDir = import_path50.default.join(home, ".claude", "projects");
24811
- const geminiDir = import_path50.default.join(home, ".gemini", "tmp");
24820
+ const home = import_os45.default.homedir();
24821
+ const claudeDir = import_path51.default.join(home, ".claude", "projects");
24822
+ const geminiDir = import_path51.default.join(home, ".gemini", "tmp");
24812
24823
  const allFiles = [
24813
24824
  ...findJsonlFiles(claudeDir).map((p) => ({ path: p, type: "jsonl" })),
24814
24825
  ...findJsonFiles(geminiDir).map((p) => ({ path: p, type: "json" }))
@@ -24816,7 +24827,7 @@ function registerMaskCommand(program2) {
24816
24827
  const cutoff = options.all ? null : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
24817
24828
  const filtered = cutoff ? allFiles.filter((f) => {
24818
24829
  try {
24819
- return import_fs49.default.statSync(f.path).mtime >= cutoff;
24830
+ return import_fs50.default.statSync(f.path).mtime >= cutoff;
24820
24831
  } catch {
24821
24832
  return false;
24822
24833
  }
@@ -24872,20 +24883,20 @@ function registerMaskCommand(program2) {
24872
24883
  // src/cli.ts
24873
24884
  init_blast();
24874
24885
  var { version } = JSON.parse(
24875
- import_fs52.default.readFileSync(import_path53.default.join(__dirname, "../package.json"), "utf-8")
24886
+ import_fs53.default.readFileSync(import_path54.default.join(__dirname, "../package.json"), "utf-8")
24876
24887
  );
24877
24888
  var program = new import_commander.Command();
24878
24889
  program.name("node9").description("The Sudo Command for AI Agents").version(version);
24879
24890
  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) => {
24880
24891
  const DEFAULT_API_URL2 = "https://api.node9.ai/api/v1/intercept";
24881
- const credPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "credentials.json");
24882
- if (!import_fs52.default.existsSync(import_path53.default.dirname(credPath)))
24883
- import_fs52.default.mkdirSync(import_path53.default.dirname(credPath), { recursive: true });
24892
+ const credPath = import_path54.default.join(import_os48.default.homedir(), ".node9", "credentials.json");
24893
+ if (!import_fs53.default.existsSync(import_path54.default.dirname(credPath)))
24894
+ import_fs53.default.mkdirSync(import_path54.default.dirname(credPath), { recursive: true });
24884
24895
  const profileName = options.profile || "default";
24885
24896
  let existingCreds = {};
24886
24897
  try {
24887
- if (import_fs52.default.existsSync(credPath)) {
24888
- const raw = JSON.parse(import_fs52.default.readFileSync(credPath, "utf-8"));
24898
+ if (import_fs53.default.existsSync(credPath)) {
24899
+ const raw = JSON.parse(import_fs53.default.readFileSync(credPath, "utf-8"));
24889
24900
  if (raw.apiKey) {
24890
24901
  existingCreds = {
24891
24902
  default: { apiKey: raw.apiKey, apiUrl: raw.apiUrl || DEFAULT_API_URL2 }
@@ -24897,14 +24908,14 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
24897
24908
  } catch {
24898
24909
  }
24899
24910
  existingCreds[profileName] = { apiKey, apiUrl: DEFAULT_API_URL2 };
24900
- import_fs52.default.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), { mode: 384 });
24911
+ import_fs53.default.writeFileSync(credPath, JSON.stringify(existingCreds, null, 2), { mode: 384 });
24901
24912
  let effectiveCloud = null;
24902
24913
  if (profileName === "default") {
24903
- const configPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "config.json");
24914
+ const configPath = import_path54.default.join(import_os48.default.homedir(), ".node9", "config.json");
24904
24915
  let config = {};
24905
24916
  try {
24906
- if (import_fs52.default.existsSync(configPath))
24907
- config = JSON.parse(import_fs52.default.readFileSync(configPath, "utf-8"));
24917
+ if (import_fs53.default.existsSync(configPath))
24918
+ config = JSON.parse(import_fs53.default.readFileSync(configPath, "utf-8"));
24908
24919
  } catch {
24909
24920
  }
24910
24921
  if (!config.settings || typeof config.settings !== "object") config.settings = {};
@@ -24919,9 +24930,9 @@ program.command("login").argument("<apiKey>").option("--local", "Save key for au
24919
24930
  approvers.cloud = false;
24920
24931
  }
24921
24932
  s.approvers = approvers;
24922
- if (!import_fs52.default.existsSync(import_path53.default.dirname(configPath)))
24923
- import_fs52.default.mkdirSync(import_path53.default.dirname(configPath), { recursive: true });
24924
- import_fs52.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
24933
+ if (!import_fs53.default.existsSync(import_path54.default.dirname(configPath)))
24934
+ import_fs53.default.mkdirSync(import_path54.default.dirname(configPath), { recursive: true });
24935
+ import_fs53.default.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 384 });
24925
24936
  effectiveCloud = approvers.cloud === true;
24926
24937
  }
24927
24938
  if (options.profile && profileName !== "default") {
@@ -25080,15 +25091,15 @@ program.command("uninstall").description("Remove all Node9 hooks and optionally
25080
25091
  }
25081
25092
  }
25082
25093
  if (options.purge) {
25083
- const node9Dir = import_path53.default.join(import_os47.default.homedir(), ".node9");
25084
- if (import_fs52.default.existsSync(node9Dir)) {
25094
+ const node9Dir = import_path54.default.join(import_os48.default.homedir(), ".node9");
25095
+ if (import_fs53.default.existsSync(node9Dir)) {
25085
25096
  const confirmed = await (0, import_prompts2.confirm)({
25086
25097
  message: `Permanently delete ${node9Dir} (config, audit log, credentials)?`,
25087
25098
  default: false
25088
25099
  });
25089
25100
  if (confirmed) {
25090
- import_fs52.default.rmSync(node9Dir, { recursive: true });
25091
- if (import_fs52.default.existsSync(node9Dir)) {
25101
+ import_fs53.default.rmSync(node9Dir, { recursive: true });
25102
+ if (import_fs53.default.existsSync(node9Dir)) {
25092
25103
  console.error(
25093
25104
  import_chalk30.default.red("\n \u26A0\uFE0F ~/.node9/ could not be fully deleted \u2014 remove it manually.")
25094
25105
  );
@@ -25203,7 +25214,7 @@ program.command("tail").description("Stream live agent activity to the terminal"
25203
25214
  });
25204
25215
  program.command("monitor").description("Live interactive dashboard \u2014 activity feed, approvals, security signals").action(async () => {
25205
25216
  try {
25206
- const dashboardPath = import_path53.default.join(__dirname, "dashboard.mjs");
25217
+ const dashboardPath = import_path54.default.join(__dirname, "dashboard.mjs");
25207
25218
  const dynamicImport = new Function("id", "return import(id)");
25208
25219
  const mod = await dynamicImport(`file://${dashboardPath}`);
25209
25220
  await mod.startMonitor();
@@ -25241,14 +25252,14 @@ Claude Code spawns this command every ~300ms and writes a JSON payload to stdin.
25241
25252
  Run "node9 addto claude" to register it as the statusLine.`
25242
25253
  ).argument("[subcommand]", 'Optional: "debug on" / "debug off" to toggle stdin logging').argument("[state]", 'on|off \u2014 used with "debug" subcommand').action(async (subcommand, state) => {
25243
25254
  if (subcommand === "debug") {
25244
- const flagFile = import_path53.default.join(import_os47.default.homedir(), ".node9", "hud-debug");
25255
+ const flagFile = import_path54.default.join(import_os48.default.homedir(), ".node9", "hud-debug");
25245
25256
  if (state === "on") {
25246
- import_fs52.default.mkdirSync(import_path53.default.dirname(flagFile), { recursive: true });
25247
- import_fs52.default.writeFileSync(flagFile, "");
25257
+ import_fs53.default.mkdirSync(import_path54.default.dirname(flagFile), { recursive: true });
25258
+ import_fs53.default.writeFileSync(flagFile, "");
25248
25259
  console.log("HUD debug logging enabled \u2192 ~/.node9/hud-debug.log");
25249
25260
  console.log("Tail it with: tail -f ~/.node9/hud-debug.log");
25250
25261
  } else if (state === "off") {
25251
- if (import_fs52.default.existsSync(flagFile)) import_fs52.default.unlinkSync(flagFile);
25262
+ if (import_fs53.default.existsSync(flagFile)) import_fs53.default.unlinkSync(flagFile);
25252
25263
  console.log("HUD debug logging disabled.");
25253
25264
  } else {
25254
25265
  console.error("Usage: node9 hud debug on|off");
@@ -25365,9 +25376,9 @@ if (process.argv[2] !== "daemon") {
25365
25376
  const isCheckHook = process.argv[2] === "check";
25366
25377
  if (isCheckHook) {
25367
25378
  if (process.env.NODE9_DEBUG === "1" || getConfig().settings.enableHookLogDebug) {
25368
- const logPath = import_path53.default.join(import_os47.default.homedir(), ".node9", "hook-debug.log");
25379
+ const logPath = import_path54.default.join(import_os48.default.homedir(), ".node9", "hook-debug.log");
25369
25380
  const msg = reason instanceof Error ? reason.message : String(reason);
25370
- import_fs52.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
25381
+ import_fs53.default.appendFileSync(logPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] UNHANDLED: ${msg}
25371
25382
  `);
25372
25383
  }
25373
25384
  process.exit(0);