@node9/proxy 2.43.0 → 2.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -799,12 +799,12 @@ function judgeInlineCode(language, code, isProtected) {
799
799
  category
800
800
  };
801
801
  }
802
- const path30 = protectedLiteral(text, isProtected);
803
- if (path30) {
802
+ const path31 = protectedLiteral(text, isProtected);
803
+ if (path31) {
804
804
  return {
805
805
  outcome: "dangerous",
806
806
  what: WHAT["reads-protected"],
807
- evidence: path30.slice(0, 60),
807
+ evidence: path31.slice(0, 60),
808
808
  category: "reads-protected"
809
809
  };
810
810
  }
@@ -2967,9 +2967,9 @@ function ruleServerMatches(rule, serverLabel) {
2967
2967
  if (rule.notServer && label2 && matchesPattern(label2, rule.notServer)) return false;
2968
2968
  return true;
2969
2969
  }
2970
- function getNestedValue(obj, path30) {
2970
+ function getNestedValue(obj, path31) {
2971
2971
  if (!obj || typeof obj !== "object") return null;
2972
- const segments2 = path30.split(".");
2972
+ const segments2 = path31.split(".");
2973
2973
  for (const seg of segments2) {
2974
2974
  if (FORBIDDEN_PATH_SEGMENTS.has(seg)) return null;
2975
2975
  }
@@ -3949,8 +3949,8 @@ function collectFileAccesses(tool, args, context = {}, inspection = {}) {
3949
3949
  }
3950
3950
  return out;
3951
3951
  }
3952
- function within(path30, root) {
3953
- return path30 === root || path30.startsWith(root === "/" ? "/" : root + "/");
3952
+ function within(path31, root) {
3953
+ return path31 === root || path31.startsWith(root === "/" ? "/" : root + "/");
3954
3954
  }
3955
3955
  function hits(access, paths, directories, context) {
3956
3956
  const home = context.homeDirs?.[0] ?? "~";
@@ -5338,7 +5338,10 @@ function classify(inv) {
5338
5338
  out.push({ ...f, shown: inv.shown, reason: `${f.reason}: ${inv.shown}` });
5339
5339
  };
5340
5340
  if (hooksBypass(inv)) found(HOOKS_BYPASS);
5341
- if (stagesEverything(inv)) found(STAGE_ALL);
5341
+ const staged = stagesEverything(inv);
5342
+ if (staged) {
5343
+ found(staged.ifWorkTreeTop === void 0 ? STAGE_ALL : { ...STAGE_ALL, ...staged });
5344
+ }
5342
5345
  if (inv.sub === null) {
5343
5346
  found(UNREADABLE);
5344
5347
  return out;
@@ -5399,12 +5402,35 @@ function appliedValue(env, name) {
5399
5402
  const word = f?.Stmts?.[0]?.Cmd?.Args?.[1];
5400
5403
  return word ? resolveWordLiteral(word) : null;
5401
5404
  }
5405
+ function lexicalPath(p) {
5406
+ if (/^[\\/~$]/.test(p) || /^[A-Za-z]:/.test(p)) return null;
5407
+ const parts = [];
5408
+ let climbed = false;
5409
+ for (const part of p.split(/[\\/]+/)) {
5410
+ if (part === "" || part === ".") continue;
5411
+ if (part === "..") {
5412
+ if (parts.length === 0) climbed = true;
5413
+ else parts.pop();
5414
+ } else parts.push(part);
5415
+ }
5416
+ return { parts, climbed };
5417
+ }
5418
+ function hooksPathBypasses(value) {
5419
+ if (value === null || value === void 0) return true;
5420
+ const v = value.trim();
5421
+ if (v === "" || v === "true") return true;
5422
+ const lp = lexicalPath(v);
5423
+ if (lp === null || lp.climbed || lp.parts.length === 0) return true;
5424
+ return lp.parts[0] === ".git" && lp.parts[1] !== "hooks";
5425
+ }
5402
5426
  function hooksBypass(inv) {
5403
- if (inv.config.has("core.hookspath")) return true;
5427
+ if (inv.config.has("core.hookspath") && hooksPathBypasses(inv.config.get("core.hookspath")))
5428
+ return true;
5404
5429
  for (const [name, value] of inv.env) {
5405
5430
  if (name === "GIT_CONFIG_PARAMETERS" && value !== null && /core\.hookspath/i.test(value))
5406
5431
  return true;
5407
- if (/^GIT_CONFIG_KEY_\d+$/.test(name) && value !== null && value.toLowerCase() === "core.hookspath")
5432
+ const key = /^GIT_CONFIG_KEY_(\d+)$/.exec(name);
5433
+ if (key && value !== null && value.toLowerCase() === "core.hookspath" && hooksPathBypasses(inv.env.get(`GIT_CONFIG_VALUE_${key[1]}`)))
5408
5434
  return true;
5409
5435
  }
5410
5436
  for (const name of HOOK_KILL_SWITCHES) {
@@ -5446,7 +5472,10 @@ function configWritesHooksPath(args) {
5446
5472
  }
5447
5473
  const key = args[i];
5448
5474
  if (key === null || key === void 0 || key.toLowerCase() !== "core.hookspath") return false;
5449
- return write || i + 1 < args.length;
5475
+ const unset = args.slice(0, i).some((w) => w === "--unset" || w === "--unset-all") || args[0] === "unset";
5476
+ if (unset) return true;
5477
+ if (i + 1 < args.length) return hooksPathBypasses(args[i + 1]);
5478
+ return write;
5450
5479
  }
5451
5480
  function isHookPath(word) {
5452
5481
  return /(^|[\\/])(\.git[\\/]hooks|\.husky)([\\/]|$)/.test(word);
@@ -5481,31 +5510,49 @@ function chmodDisarmsHook(args, shown) {
5481
5510
  function wholeTree(operand) {
5482
5511
  if (/^:\(top\)\.?$/.test(operand) || operand === ":/" || operand === "*") return true;
5483
5512
  if (operand.startsWith(":")) return false;
5513
+ const lp = lexicalPath(operand);
5514
+ return lp !== null && lp.parts.length === 0;
5515
+ }
5516
+ function chdirPrefix(inv) {
5517
+ const dirs = inv.chdir ?? [];
5518
+ if (dirs.length === 0) return null;
5484
5519
  const parts = [];
5485
- for (const part of operand.split("/")) {
5486
- if (!part || part === ".") continue;
5487
- if (part === "..") parts.pop();
5488
- else parts.push(part);
5520
+ for (const d of dirs) {
5521
+ if (d === null || d === "") return null;
5522
+ const lp = lexicalPath(d);
5523
+ if (lp === null || lp.climbed) return null;
5524
+ parts.push(...lp.parts);
5489
5525
  }
5490
- return parts.length === 0 && !operand.startsWith("/");
5526
+ return parts.length === 0 ? null : parts.join("/");
5491
5527
  }
5492
5528
  function stagesEverything(inv) {
5493
5529
  const sub = inv.sub?.toLowerCase();
5530
+ const prefix = chdirPrefix(inv);
5531
+ const judge = (operands2) => {
5532
+ let conditional = false;
5533
+ for (const operand of operands2) {
5534
+ if (!wholeTree(operand)) continue;
5535
+ if (prefix === null || operand.startsWith(":") || operand.startsWith("/")) return {};
5536
+ if (wholeTree(`${prefix}/${operand === "*" ? "." : operand}`)) return {};
5537
+ conditional = true;
5538
+ }
5539
+ return conditional && prefix !== null ? { ifWorkTreeTop: prefix } : null;
5540
+ };
5494
5541
  if (sub === "add") {
5495
5542
  const o = parseOptions(inv.args, "", ADD_LONG_VALUE);
5496
5543
  if (o.flags.has("-n") || o.flags.has("--dry-run") || o.flags.has("-i") || o.flags.has("--interactive") || o.flags.has("-p") || o.flags.has("--patch") || o.flags.has("-e") || o.flags.has("--edit"))
5497
- return false;
5544
+ return null;
5498
5545
  const all = o.flags.has("-A") || o.flags.has("--all") || o.flags.has("--no-ignore-removal") || o.flags.has("-u") || o.flags.has("--update");
5499
- if (all && o.operands.length === 0) return true;
5500
- return o.operands.some(wholeTree);
5546
+ if (all && o.operands.length === 0) return {};
5547
+ return judge(o.operands);
5501
5548
  }
5502
5549
  if (sub === "commit") {
5503
5550
  const o = parseOptions(inv.args, "mFCcut", COMMIT_LONG_VALUE);
5504
- if (o.flags.has("--dry-run")) return false;
5505
- if (o.flags.has("-a") || o.flags.has("--all")) return true;
5506
- return o.operands.some(wholeTree);
5551
+ if (o.flags.has("--dry-run")) return null;
5552
+ if (o.flags.has("-a") || o.flags.has("--all")) return {};
5553
+ return judge(o.operands);
5507
5554
  }
5508
- return false;
5555
+ return null;
5509
5556
  }
5510
5557
  function hookTextRunsNothing(text) {
5511
5558
  return text.split(/\r?\n/).every((line) => INERT_LINE_RE.test(line.trim()));
@@ -7161,9 +7208,9 @@ function bareToolName(toolName) {
7161
7208
  const parts = toolName.split("__");
7162
7209
  return (parts.length >= 3 ? parts.slice(2).join("__") : toolName).toLowerCase();
7163
7210
  }
7164
- function valuesAt(args, path30) {
7211
+ function valuesAt(args, path31) {
7165
7212
  let cursors = [args];
7166
- for (const rawSegment of path30.split(".")) {
7213
+ for (const rawSegment of path31.split(".")) {
7167
7214
  const isArray = rawSegment.endsWith("[]");
7168
7215
  const key = isArray ? rawSegment.slice(0, -2) : rawSegment;
7169
7216
  const next = [];
@@ -7194,8 +7241,8 @@ function extractToolDestinations(toolName, args) {
7194
7241
  try {
7195
7242
  const out = [];
7196
7243
  const paths = DESTINATION_ARGS.get(bareToolName(toolName)) ?? [];
7197
- for (const path30 of paths) {
7198
- for (const value of valuesAt(args, path30)) {
7244
+ for (const path31 of paths) {
7245
+ for (const value of valuesAt(args, path31)) {
7199
7246
  const host2 = hostOf(value);
7200
7247
  if (host2) out.push({ host: host2, binary: toolName, raw: value });
7201
7248
  }
@@ -7221,8 +7268,8 @@ function ssrfDestinationFloor(toolName, args, opts = {}) {
7221
7268
  try {
7222
7269
  const paths = DESTINATION_ARGS.get(bareToolName(toolName));
7223
7270
  if (!paths) return null;
7224
- for (const path30 of paths) {
7225
- for (const value of valuesAt(args, path30)) {
7271
+ for (const path31 of paths) {
7272
+ for (const value of valuesAt(args, path31)) {
7226
7273
  const host2 = hostOf(value);
7227
7274
  if (!host2) continue;
7228
7275
  const m = classifySsrf(host2);
@@ -7231,7 +7278,7 @@ function ssrfDestinationFloor(toolName, args, opts = {}) {
7231
7278
  const decision = ssrfFloorDecision(m, written, opts);
7232
7279
  if (decision === null) continue;
7233
7280
  const reason = decision === "review" ? ssrfDisguisedReason(m, written) : ssrfReason(m, host2);
7234
- return { ...m, argPath: path30, host: host2, reason, decision };
7281
+ return { ...m, argPath: path31, host: host2, reason, decision };
7235
7282
  }
7236
7283
  }
7237
7284
  return null;
@@ -7513,7 +7560,7 @@ async function evaluatePolicy(config, toolName, args, context = {}, hostHooks =
7513
7560
  }
7514
7561
  async function evaluatePolicyCore(config, toolName, args, context = {}, hooks = {}) {
7515
7562
  const { agent, cwd, activeEnvironment } = context;
7516
- const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry } = hooks;
7563
+ const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry, isGitWorkTreeTop: isGitWorkTreeTop2 } = hooks;
7517
7564
  const settingsView = catalogSettings(config);
7518
7565
  const layers = inspectionLayers(config.policy);
7519
7566
  const cv = (id) => checkValue(settingsView, id);
@@ -7667,6 +7714,8 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
7667
7714
  const action = cv(id);
7668
7715
  const finding = action === "off" ? void 0 : git.findings.find((f) => f.checkId === id);
7669
7716
  if (!finding) continue;
7717
+ if (finding.ifWorkTreeTop !== void 0 && isGitWorkTreeTop2 && cwd && !isGitWorkTreeTop2(finding.ifWorkTreeTop, cwd))
7718
+ continue;
7670
7719
  const v = applyCheckValue(action, {
7671
7720
  decision: "review",
7672
7721
  blockedByLabel: `Node9 (AST): ${finding.ruleName}`,
@@ -16278,6 +16327,7 @@ zoo`.split("\n");
16278
16327
  /** The words after `git`: global options, then the subcommand. */
16279
16328
  visitGit(rest, env, depth, viaXargs, fromAlias, shown) {
16280
16329
  const config = /* @__PURE__ */ new Map();
16330
+ const chdir = [];
16281
16331
  let i = 0;
16282
16332
  while (i < rest.length) {
16283
16333
  const w = rest[i];
@@ -16292,6 +16342,7 @@ zoo`.split("\n");
16292
16342
  i++;
16293
16343
  value = i < rest.length ? rest[i] : null;
16294
16344
  }
16345
+ if (name === "-C") chdir.push(viaXargs || (value ?? "").includes("{}") ? null : value);
16295
16346
  if (name === "-c" && value !== null) {
16296
16347
  const ceq = value.indexOf("=");
16297
16348
  const key = (ceq > 0 ? value.slice(0, ceq) : value).toLowerCase();
@@ -16308,7 +16359,7 @@ zoo`.split("\n");
16308
16359
  }
16309
16360
  const subWord = i < rest.length ? rest[i] : void 0;
16310
16361
  const args = rest.slice(i + 1);
16311
- const inv = { sub: null, args, config, env, shown };
16362
+ const inv = { sub: null, args, config, env, shown, chdir };
16312
16363
  if (subWord === void 0) {
16313
16364
  if (!viaXargs) return;
16314
16365
  this.emit(inv);
@@ -16322,16 +16373,23 @@ zoo`.split("\n");
16322
16373
  const fromConfig = config.get(`alias.${subWord.toLowerCase()}`);
16323
16374
  const alias = fromConfig !== void 0 ? fromConfig : this.aliases.get(subWord);
16324
16375
  if (alias !== void 0 && !fromAlias) {
16325
- this.expandAlias(subWord, alias, args, env, depth, 0, shown);
16376
+ this.expandAlias(subWord, alias, args, env, depth, 0, shown, chdir);
16326
16377
  return;
16327
16378
  }
16328
16379
  inv.sub = subWord;
16329
16380
  this.emit(inv);
16330
16381
  this.recordAliasDefinition(inv, env, depth);
16331
16382
  }
16332
- expandAlias(name, value, args, env, depth, level, shown) {
16383
+ expandAlias(name, value, args, env, depth, level, shown, chdir) {
16333
16384
  if (value === null) {
16334
- this.emit({ sub: null, args, config: /* @__PURE__ */ new Map(), env, shown: `${shown} (alias ${name})` });
16385
+ this.emit({
16386
+ sub: null,
16387
+ args,
16388
+ config: /* @__PURE__ */ new Map(),
16389
+ env,
16390
+ shown: `${shown} (alias ${name})`,
16391
+ chdir
16392
+ });
16335
16393
  return;
16336
16394
  }
16337
16395
  if (value.startsWith("!")) {
@@ -16345,7 +16403,16 @@ zoo`.split("\n");
16345
16403
  const nested = this.aliases.get(sub);
16346
16404
  const expandedShown = `${shown} (alias ${name} = ${value})`;
16347
16405
  if (nested !== void 0 && level < MAX_ALIAS_DEPTH) {
16348
- this.expandAlias(sub, nested, [...words.slice(1), ...args], env, depth, level + 1, shown);
16406
+ this.expandAlias(
16407
+ sub,
16408
+ nested,
16409
+ [...words.slice(1), ...args],
16410
+ env,
16411
+ depth,
16412
+ level + 1,
16413
+ shown,
16414
+ chdir
16415
+ );
16349
16416
  return;
16350
16417
  }
16351
16418
  this.emit({
@@ -16353,7 +16420,8 @@ zoo`.split("\n");
16353
16420
  args: [...words.slice(1), ...args],
16354
16421
  config: /* @__PURE__ */ new Map(),
16355
16422
  env,
16356
- shown: expandedShown
16423
+ shown: expandedShown,
16424
+ chdir
16357
16425
  });
16358
16426
  }
16359
16427
  /**
@@ -16387,7 +16455,7 @@ zoo`.split("\n");
16387
16455
  if (i + 1 >= args.length) return;
16388
16456
  const value = args[i + 1];
16389
16457
  this.aliases.set(m[1], value);
16390
- this.expandAlias(m[1], value, [], env, depth, 0, `${inv.shown}`);
16458
+ this.expandAlias(m[1], value, [], env, depth, 0, `${inv.shown}`, []);
16391
16459
  }
16392
16460
  };
16393
16461
  POSITIONAL2 = "\0positional";
@@ -18303,8 +18371,8 @@ var ConfigFileSchema = z.object({
18303
18371
  }).strict();
18304
18372
  function formatIssues(issues) {
18305
18373
  const lines = issues.map((issue) => {
18306
- const path30 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
18307
- return ` \u2022 ${path30}: ${issue.message}`;
18374
+ const path31 = issue.path.length > 0 ? issue.path.map(String).join(".") : "root";
18375
+ return ` \u2022 ${path31}: ${issue.message}`;
18308
18376
  });
18309
18377
  return `Invalid config:
18310
18378
  ${lines.join("\n")}`;
@@ -18317,9 +18385,9 @@ function prunePaths(root, paths) {
18317
18385
  const yi = y[y.length - 1];
18318
18386
  return typeof xi === "number" && typeof yi === "number" ? yi - xi : 0;
18319
18387
  });
18320
- for (const path30 of ordered) {
18388
+ for (const path31 of ordered) {
18321
18389
  let cur = root;
18322
- for (const key of path30.slice(0, -1)) {
18390
+ for (const key of path31.slice(0, -1)) {
18323
18391
  if (cur === null || typeof cur !== "object") {
18324
18392
  cur = void 0;
18325
18393
  break;
@@ -18327,7 +18395,7 @@ function prunePaths(root, paths) {
18327
18395
  cur = cur[key];
18328
18396
  }
18329
18397
  if (cur === null || typeof cur !== "object") continue;
18330
- const last = path30[path30.length - 1];
18398
+ const last = path31[path31.length - 1];
18331
18399
  if (Array.isArray(cur)) {
18332
18400
  const i = Number(last);
18333
18401
  if (Number.isInteger(i) && i >= 0 && i < cur.length) {
@@ -18363,7 +18431,7 @@ function sanitizeConfig(raw) {
18363
18431
  return issue.keys.map((k) => [...at, k]);
18364
18432
  }
18365
18433
  return [at.slice(0, -level || void 0)];
18366
- }).filter((path30) => path30.length > 0);
18434
+ }).filter((path31) => path31.length > 0);
18367
18435
  if (paths.length === 0 || !prunePaths(working, paths)) break;
18368
18436
  }
18369
18437
  if (ConfigFileSchema.safeParse(working).success) break;
@@ -19801,13 +19869,13 @@ function getConfig(cwd) {
19801
19869
  }
19802
19870
  if (Array.isArray(mc.jailPaths)) {
19803
19871
  for (const jp of mc.jailPaths) {
19804
- const path30 = typeof jp?.path === "string" ? jp.path.trim() : "";
19805
- if (!path30) continue;
19872
+ const path31 = typeof jp?.path === "string" ? jp.path.trim() : "";
19873
+ if (!path31) continue;
19806
19874
  const verdict = jp?.verdict === "review" ? "review" : "block";
19807
- for (const r of pathRules(path30, verdict, "org-managed jail")) {
19875
+ for (const r of pathRules(path31, verdict, "org-managed jail")) {
19808
19876
  mergedPolicy.smartRules.push({ ...r, name: `org:${r.name}` });
19809
19877
  }
19810
- mergedPolicy.managedJailPaths.push({ path: path30, verdict });
19878
+ mergedPolicy.managedJailPaths.push({ path: path31, verdict });
19811
19879
  }
19812
19880
  }
19813
19881
  if (Array.isArray(mc.trustedHosts)) {
@@ -20188,6 +20256,9 @@ function readCappedText(file2, maxBytes, openFlags = "r") {
20188
20256
  return r ? { text: r.bytes.toString("utf8"), truncated: r.truncated } : null;
20189
20257
  }
20190
20258
 
20259
+ // src/policy/index.ts
20260
+ import path13 from "path";
20261
+
20191
20262
  // src/dlp.ts
20192
20263
  init_dist();
20193
20264
  init_dist();
@@ -21508,10 +21579,19 @@ async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
21508
21579
  // reaches a long-lived in-process authorizer (the gateway) within seconds.
21509
21580
  isTrustedHost: config.policy.trustedHostsManaged ? (host2) => matchesTrustedHost(host2, config.policy.trustedHosts) : isTrustedHost,
21510
21581
  readAgentSettings,
21511
- isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2)
21582
+ isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2),
21583
+ isGitWorkTreeTop
21512
21584
  }
21513
21585
  );
21514
21586
  }
21587
+ function isGitWorkTreeTop(dir2, cwd) {
21588
+ if (!path13.isAbsolute(cwd)) return true;
21589
+ try {
21590
+ return fs13.existsSync(path13.join(path13.resolve(cwd, dir2), ".git"));
21591
+ } catch {
21592
+ return true;
21593
+ }
21594
+ }
21515
21595
  var MAX_AGENT_SETTINGS_BYTES = 256 * 1024;
21516
21596
  function readAgentSettings(absPath) {
21517
21597
  const r = readCappedText(
@@ -21527,11 +21607,11 @@ function isIgnoredTool2(toolName) {
21527
21607
 
21528
21608
  // src/auth/state.ts
21529
21609
  import fs14 from "fs";
21530
- import path13 from "path";
21610
+ import path14 from "path";
21531
21611
  import os9 from "os";
21532
21612
  init_forecast_context();
21533
- var PAUSED_FILE = path13.join(os9.homedir(), ".node9", "PAUSED");
21534
- var TRUST_FILE = path13.join(os9.homedir(), ".node9", "trust.json");
21613
+ var PAUSED_FILE = path14.join(os9.homedir(), ".node9", "PAUSED");
21614
+ var TRUST_FILE = path14.join(os9.homedir(), ".node9", "trust.json");
21535
21615
  function extractCommandPattern(toolName, args) {
21536
21616
  const lower2 = toolName.toLowerCase();
21537
21617
  if (lower2 !== "bash" && lower2 !== "execute_bash" && lower2 !== "shell") return void 0;
@@ -21608,7 +21688,7 @@ function writeTrustSession(toolName, durationMs, args) {
21608
21688
  }
21609
21689
  function getPersistentDecision(toolName) {
21610
21690
  try {
21611
- const file2 = path13.join(os9.homedir(), ".node9", "decisions.json");
21691
+ const file2 = path14.join(os9.homedir(), ".node9", "decisions.json");
21612
21692
  if (!fs14.existsSync(file2)) return null;
21613
21693
  const decisions = JSON.parse(fs14.readFileSync(file2, "utf-8"));
21614
21694
  const d = decisions[toolName];
@@ -21623,7 +21703,7 @@ init_forecast_context();
21623
21703
  import fs15 from "fs";
21624
21704
  import http from "http";
21625
21705
  import net from "net";
21626
- import path14 from "path";
21706
+ import path15 from "path";
21627
21707
  import os10 from "os";
21628
21708
 
21629
21709
  // src/auth/decision-record.ts
@@ -21774,7 +21854,7 @@ function recordFromLegacyWait(body, now = Date.now()) {
21774
21854
  }
21775
21855
 
21776
21856
  // src/auth/daemon.ts
21777
- var ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : path14.join(os10.tmpdir(), "node9-activity.sock");
21857
+ var ACTIVITY_SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\node9-activity" : path15.join(os10.tmpdir(), "node9-activity.sock");
21778
21858
  function notifyActivitySocket(data) {
21779
21859
  if (forecastRun()) return Promise.resolve(false);
21780
21860
  return new Promise((resolve) => {
@@ -21819,7 +21899,7 @@ var DAEMON_HOST = "127.0.0.1";
21819
21899
  function getInternalToken() {
21820
21900
  if (forecastRun()) return null;
21821
21901
  try {
21822
- const pidFile = path14.join(os10.homedir(), ".node9", "daemon.pid");
21902
+ const pidFile = path15.join(os10.homedir(), ".node9", "daemon.pid");
21823
21903
  if (!fs15.existsSync(pidFile)) return null;
21824
21904
  const data = JSON.parse(fs15.readFileSync(pidFile, "utf-8"));
21825
21905
  process.kill(data.pid, 0);
@@ -21830,7 +21910,7 @@ function getInternalToken() {
21830
21910
  }
21831
21911
  function isDaemonRunning() {
21832
21912
  if (forecastRun()) return false;
21833
- const pidFile = path14.join(os10.homedir(), ".node9", "daemon.pid");
21913
+ const pidFile = path15.join(os10.homedir(), ".node9", "daemon.pid");
21834
21914
  if (fs15.existsSync(pidFile)) {
21835
21915
  let pid;
21836
21916
  let port;
@@ -22193,7 +22273,7 @@ import { randomUUID as randomUUID2 } from "crypto";
22193
22273
  // src/apps/state.ts
22194
22274
  import fs17 from "fs";
22195
22275
  import os12 from "os";
22196
- import path16 from "path";
22276
+ import path17 from "path";
22197
22277
 
22198
22278
  // src/apps/catalog.ts
22199
22279
  var APP_CATALOG = [
@@ -22326,10 +22406,10 @@ init_audit();
22326
22406
 
22327
22407
  // src/daemon/mcp-tools.ts
22328
22408
  import fs16 from "fs";
22329
- import path15 from "path";
22409
+ import path16 from "path";
22330
22410
  import os11 from "os";
22331
22411
  function getMcpToolsFile() {
22332
- return path15.join(os11.homedir(), ".node9", "mcp-tools.json");
22412
+ return path16.join(os11.homedir(), ".node9", "mcp-tools.json");
22333
22413
  }
22334
22414
  function readMcpToolsConfig() {
22335
22415
  try {
@@ -22344,7 +22424,7 @@ function readMcpToolsConfig() {
22344
22424
 
22345
22425
  // src/apps/state.ts
22346
22426
  function appsFilePath(home = os12.homedir()) {
22347
- return path16.join(home, ".node9", "apps.json");
22427
+ return path17.join(home, ".node9", "apps.json");
22348
22428
  }
22349
22429
  var SIGNAL_KINDS = /* @__PURE__ */ new Set(["mcp-server", "command", "package", "env-name"]);
22350
22430
  function emptyFile() {
@@ -22448,14 +22528,14 @@ function resolveLinkedServer(label2, opts = {}) {
22448
22528
 
22449
22529
  // src/auth/orchestrator.ts
22450
22530
  import os21 from "os";
22451
- import path29 from "path";
22531
+ import path30 from "path";
22452
22532
 
22453
22533
  // src/ui/native.ts
22454
22534
  import { spawn } from "child_process";
22455
- import path18 from "path";
22535
+ import path19 from "path";
22456
22536
 
22457
22537
  // src/context-sniper.ts
22458
- import path17 from "path";
22538
+ import path18 from "path";
22459
22539
  function smartTruncate(str, maxLen = 500) {
22460
22540
  if (str.length <= maxLen) return str;
22461
22541
  const edge = Math.floor(maxLen / 2) - 3;
@@ -22523,7 +22603,7 @@ function computeRiskMetadata(args, tier, blockedByLabel, matchedField, matchedWo
22523
22603
  intent = "EDIT";
22524
22604
  if (obj.file_path) {
22525
22605
  editFilePath = String(obj.file_path);
22526
- editFileName = path17.basename(editFilePath);
22606
+ editFileName = path18.basename(editFilePath);
22527
22607
  }
22528
22608
  const result = extractContext(String(obj.new_string), matchedWord);
22529
22609
  contextSnippet = result.snippet;
@@ -22591,7 +22671,7 @@ function formatArgs(args, matchedField, matchedWord) {
22591
22671
  if (typeof parsed === "object" && !Array.isArray(parsed)) {
22592
22672
  const obj = parsed;
22593
22673
  if (obj.old_string !== void 0 && obj.new_string !== void 0) {
22594
- const file2 = obj.file_path ? path18.basename(String(obj.file_path)) : "file";
22674
+ const file2 = obj.file_path ? path19.basename(String(obj.file_path)) : "file";
22595
22675
  const oldPreview = smartTruncate(String(obj.old_string), 120);
22596
22676
  const newPreview = extractContext(String(obj.new_string), matchedWord).snippet;
22597
22677
  return {
@@ -22796,17 +22876,17 @@ end run`;
22796
22876
  // src/canary/registry.ts
22797
22877
  import fs19 from "fs";
22798
22878
  import os14 from "os";
22799
- import path20 from "path";
22879
+ import path21 from "path";
22800
22880
  init_dist();
22801
22881
 
22802
22882
  // src/shields/jail.ts
22803
22883
  import fs18 from "fs";
22804
22884
  import os13 from "os";
22805
- import path19 from "path";
22885
+ import path20 from "path";
22806
22886
  init_dist();
22807
22887
  var USER_JAIL_SHIELD = "user-jail";
22808
22888
  function jailStorePath() {
22809
- return path19.join(os13.homedir(), ".node9", "jail-paths.json");
22889
+ return path20.join(os13.homedir(), ".node9", "jail-paths.json");
22810
22890
  }
22811
22891
  function readJailPaths() {
22812
22892
  let text;
@@ -22840,7 +22920,7 @@ function findJailedPathIn(candidate, paths) {
22840
22920
 
22841
22921
  // src/canary/registry.ts
22842
22922
  function canaryStorePath() {
22843
- return path20.join(os14.homedir(), ".node9", "canaries.json");
22923
+ return path21.join(os14.homedir(), ".node9", "canaries.json");
22844
22924
  }
22845
22925
  function isRecord(x) {
22846
22926
  if (!x || typeof x !== "object") return false;
@@ -22880,7 +22960,7 @@ init_dist();
22880
22960
  init_dist();
22881
22961
  import fs20 from "fs";
22882
22962
  import os15 from "os";
22883
- import path21 from "path";
22963
+ import path22 from "path";
22884
22964
  var MAX_SCRIPT_BYTES = 64 * 1024;
22885
22965
  var MAX_RECORDED_WRITES = 32;
22886
22966
  function readScriptFile(resolved) {
@@ -22911,7 +22991,7 @@ function readScriptFile(resolved) {
22911
22991
  }
22912
22992
  function absolute(p, cwd, home) {
22913
22993
  const spelled = p === "~" || p.startsWith("~/") ? home + p.slice(1) : p;
22914
- return path21.resolve(cwd, spelled);
22994
+ return path22.resolve(cwd, spelled);
22915
22995
  }
22916
22996
  async function resolveSessionScript(toolName, args, cwd, layers, deps, home = os15.homedir()) {
22917
22997
  try {
@@ -22973,12 +23053,12 @@ init_dist();
22973
23053
 
22974
23054
  // src/exposure/known-hosts.ts
22975
23055
  import fs22 from "fs";
22976
- import path23 from "path";
23056
+ import path24 from "path";
22977
23057
 
22978
23058
  // src/utils/git-remotes.ts
22979
23059
  init_dist();
22980
23060
  import fs21 from "fs";
22981
- import path22 from "path";
23061
+ import path23 from "path";
22982
23062
  function readSmallFile(p, max) {
22983
23063
  let fd;
22984
23064
  try {
@@ -23010,20 +23090,20 @@ function gitRemoteHost(url) {
23010
23090
  return null;
23011
23091
  }
23012
23092
  function findGitConfig(dir2, walkUp = true) {
23013
- let cur = path22.resolve(dir2);
23093
+ let cur = path23.resolve(dir2);
23014
23094
  for (let i = 0; i < (walkUp ? 64 : 1); i++) {
23015
- const dotGit = path22.join(cur, ".git");
23016
- const direct = readSmallFile(path22.join(dotGit, "config"), 1e6);
23095
+ const dotGit = path23.join(cur, ".git");
23096
+ const direct = readSmallFile(path23.join(dotGit, "config"), 1e6);
23017
23097
  if (direct !== null) return direct;
23018
23098
  const pointer = readSmallFile(dotGit, 4096);
23019
23099
  const m = pointer && /^gitdir:\s*(.+?)\s*$/m.exec(pointer);
23020
23100
  if (m) {
23021
- let gitDir = path22.resolve(cur, m[1]);
23022
- const common = readSmallFile(path22.join(gitDir, "commondir"), 4096);
23023
- if (common !== null) gitDir = path22.resolve(gitDir, common.trim());
23024
- return readSmallFile(path22.join(gitDir, "config"), 1e6);
23101
+ let gitDir = path23.resolve(cur, m[1]);
23102
+ const common = readSmallFile(path23.join(gitDir, "commondir"), 4096);
23103
+ if (common !== null) gitDir = path23.resolve(gitDir, common.trim());
23104
+ return readSmallFile(path23.join(gitDir, "config"), 1e6);
23025
23105
  }
23026
- const parent = path22.dirname(cur);
23106
+ const parent = path23.dirname(cur);
23027
23107
  if (parent === cur) return null;
23028
23108
  cur = parent;
23029
23109
  }
@@ -23033,12 +23113,12 @@ var cache4 = /* @__PURE__ */ new Map();
23033
23113
  function readGitRemotes(dir2, opts = {}) {
23034
23114
  if (!dir2) return [];
23035
23115
  const walkUp = opts.walkUp !== false;
23036
- const key = `${walkUp ? "up" : "at"}:${path22.resolve(dir2)}`;
23116
+ const key = `${walkUp ? "up" : "at"}:${path23.resolve(dir2)}`;
23037
23117
  const hit = cache4.get(key);
23038
23118
  if (hit) return hit;
23039
23119
  const out = [];
23040
23120
  try {
23041
- const cfg = findGitConfig(path22.resolve(dir2), walkUp);
23121
+ const cfg = findGitConfig(path23.resolve(dir2), walkUp);
23042
23122
  if (cfg !== null) {
23043
23123
  let current = null;
23044
23124
  for (const line of cfg.split(/\r?\n/)) {
@@ -23074,15 +23154,15 @@ var ECOSYSTEMS = [
23074
23154
  ];
23075
23155
  var cache5 = /* @__PURE__ */ new Map();
23076
23156
  function manifestRoot(dir2) {
23077
- let cur = path23.resolve(dir2);
23157
+ let cur = path24.resolve(dir2);
23078
23158
  for (let i = 0; i < 64; i++) {
23079
23159
  for (const [m] of ECOSYSTEMS) {
23080
23160
  try {
23081
- if (fs22.existsSync(path23.join(cur, m))) return cur;
23161
+ if (fs22.existsSync(path24.join(cur, m))) return cur;
23082
23162
  } catch {
23083
23163
  }
23084
23164
  }
23085
- const parent = path23.dirname(cur);
23165
+ const parent = path24.dirname(cur);
23086
23166
  if (parent === cur) return null;
23087
23167
  cur = parent;
23088
23168
  }
@@ -23091,7 +23171,7 @@ function manifestRoot(dir2) {
23091
23171
  function knownProjectHosts(dir2) {
23092
23172
  const empty = { hosts: /* @__PURE__ */ new Set(), repos: /* @__PURE__ */ new Set(), remotes: /* @__PURE__ */ new Map() };
23093
23173
  if (!dir2) return empty;
23094
- const key = path23.resolve(dir2);
23174
+ const key = path24.resolve(dir2);
23095
23175
  const hit = cache5.get(key);
23096
23176
  if (hit) return hit;
23097
23177
  const out = { hosts: /* @__PURE__ */ new Set(), repos: /* @__PURE__ */ new Set(), remotes: /* @__PURE__ */ new Map() };
@@ -23104,7 +23184,7 @@ function knownProjectHosts(dir2) {
23104
23184
  const root = manifestRoot(key);
23105
23185
  if (root !== null) {
23106
23186
  for (const [m, registry] of ECOSYSTEMS) {
23107
- if (fs22.existsSync(path23.join(root, m))) out.hosts.add(registry);
23187
+ if (fs22.existsSync(path24.join(root, m))) out.hosts.add(registry);
23108
23188
  }
23109
23189
  try {
23110
23190
  if (fs22.readdirSync(root).some((f) => f.endsWith(".gemspec")))
@@ -23122,7 +23202,7 @@ function knownProjectHosts(dir2) {
23122
23202
  init_dist();
23123
23203
  import fs23 from "fs";
23124
23204
  import os16 from "os";
23125
- import path24 from "path";
23205
+ import path25 from "path";
23126
23206
  var WRITE_OPS = /* @__PURE__ */ new Set(["write", "create", "remove"]);
23127
23207
  var LIFECYCLE_RE = /"(scripts|preinstall|install|postinstall|prepare|prepublish|prepublishOnly|prepack|postpack|publish|postpublish)"\s*:/;
23128
23208
  function writtenContent(args) {
@@ -23172,7 +23252,7 @@ function judgeWritesAfterExposure(opts) {
23172
23252
  seen.add(p);
23173
23253
  if (p === "/dev" || p.startsWith("/dev/")) continue;
23174
23254
  if (root !== null && isInside(root, p)) {
23175
- if (isAgentInstructionPath(p, root) && (path24.basename(p) !== "package.json" || packageScriptsTouched(opts.args, p, opts.shellCommand)))
23255
+ if (isAgentInstructionPath(p, root) && (path25.basename(p) !== "package.json" || packageScriptsTouched(opts.args, p, opts.shellCommand)))
23176
23256
  holds.push({ path: p, why: "agent-instruction" });
23177
23257
  continue;
23178
23258
  }
@@ -23196,7 +23276,7 @@ function judgeWritesAfterExposure(opts) {
23196
23276
  import crypto3 from "crypto";
23197
23277
  import fs24 from "fs";
23198
23278
  import os17 from "os";
23199
- import path25 from "path";
23279
+ import path26 from "path";
23200
23280
 
23201
23281
  // src/daemon/exposure-store.ts
23202
23282
  var SESSION_EXPOSURE_TTL_MS = 4 * 60 * 60 * 1e3;
@@ -23204,11 +23284,11 @@ var SESSION_EXPOSURE_TTL_MS = 4 * 60 * 60 * 1e3;
23204
23284
  // src/exposure/marker.ts
23205
23285
  init_forecast_context();
23206
23286
  function dir() {
23207
- return path25.join(os17.homedir(), ".node9", "exposure-sessions");
23287
+ return path26.join(os17.homedir(), ".node9", "exposure-sessions");
23208
23288
  }
23209
23289
  function file(sessionId) {
23210
23290
  const id = crypto3.createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
23211
- return path25.join(dir(), id);
23291
+ return path26.join(dir(), id);
23212
23292
  }
23213
23293
  function maybeSessionExposed(sessionId) {
23214
23294
  if (!sessionId) return false;
@@ -23319,10 +23399,10 @@ function sourceWord(toolName) {
23319
23399
  // src/auth/trusted-recipients.ts
23320
23400
  init_dist();
23321
23401
  import fs26 from "fs";
23322
- import path26 from "path";
23402
+ import path27 from "path";
23323
23403
  import os18 from "os";
23324
23404
  function getTrustedRecipientsPath() {
23325
- return path26.join(os18.homedir(), ".node9", "trusted-recipients.json");
23405
+ return path27.join(os18.homedir(), ".node9", "trusted-recipients.json");
23326
23406
  }
23327
23407
  function readTrustedRecipients() {
23328
23408
  try {
@@ -23335,7 +23415,7 @@ function readTrustedRecipients() {
23335
23415
  }
23336
23416
  function writeTrustedRecipients(entries) {
23337
23417
  const filePath = getTrustedRecipientsPath();
23338
- fs26.mkdirSync(path26.dirname(filePath), { recursive: true });
23418
+ fs26.mkdirSync(path27.dirname(filePath), { recursive: true });
23339
23419
  const tmp = filePath + ".node9-tmp";
23340
23420
  fs26.writeFileSync(tmp, JSON.stringify({ entries }, null, 2), { mode: 384 });
23341
23421
  fs26.renameSync(tmp, filePath);
@@ -23373,7 +23453,7 @@ init_forecast_context();
23373
23453
  init_audit();
23374
23454
  import fs27 from "fs";
23375
23455
  import os19 from "os";
23376
- import path27 from "path";
23456
+ import path28 from "path";
23377
23457
  init_dist();
23378
23458
  var CLOUD_ARRAY_KEYS = /* @__PURE__ */ new Set(["exposureDestinations", "exposureDestinationHashes"]);
23379
23459
  function maskArgsForCloud(args) {
@@ -23408,7 +23488,7 @@ async function initNode9SaaS(toolName, args, creds, meta, riskMetadata, agentPol
23408
23488
  let ciContext;
23409
23489
  if (process.env.CI) {
23410
23490
  try {
23411
- const ciContextPath = path27.join(os19.homedir(), ".node9", "ci-context.json");
23491
+ const ciContextPath = path28.join(os19.homedir(), ".node9", "ci-context.json");
23412
23492
  const ci = readCappedText(ciContextPath, 1e4);
23413
23493
  if (!ci) throw new Error("ci-context.json unreadable");
23414
23494
  if (ci.truncated) throw new Error("ci-context.json exceeds 10 KB");
@@ -23546,10 +23626,10 @@ init_dist();
23546
23626
  init_forecast_context();
23547
23627
  init_dist();
23548
23628
  import fs28 from "fs";
23549
- import path28 from "path";
23629
+ import path29 from "path";
23550
23630
  import os20 from "os";
23551
23631
  function loopStateFile() {
23552
- return path28.join(os20.homedir(), ".node9", "loop-state.json");
23632
+ return path29.join(os20.homedir(), ".node9", "loop-state.json");
23553
23633
  }
23554
23634
  function readState() {
23555
23635
  try {
@@ -23563,7 +23643,7 @@ function readState() {
23563
23643
  }
23564
23644
  }
23565
23645
  function writeState(records) {
23566
- const dir2 = path28.dirname(loopStateFile());
23646
+ const dir2 = path29.dirname(loopStateFile());
23567
23647
  if (!fs28.existsSync(dir2)) fs28.mkdirSync(dir2, { recursive: true });
23568
23648
  const tmpPath = `${loopStateFile()}.${os20.hostname()}.${process.pid}.tmp`;
23569
23649
  fs28.writeFileSync(tmpPath, JSON.stringify(records));
@@ -23763,9 +23843,9 @@ function isMcpToolName(toolName) {
23763
23843
  return /^mcp__[^_](?:[^_]|_(?!_))*?__/i.test(toolName);
23764
23844
  }
23765
23845
  function absoluteUploadPath(spelled, cwd) {
23766
- const expanded = spelled === "~" || spelled.startsWith("~/") ? path29.join(os21.homedir(), spelled.slice(1)) : spelled;
23767
- if (path29.isAbsolute(expanded)) return expanded;
23768
- return cwd && path29.isAbsolute(cwd) ? path29.resolve(cwd, expanded) : expanded;
23846
+ const expanded = spelled === "~" || spelled.startsWith("~/") ? path30.join(os21.homedir(), spelled.slice(1)) : spelled;
23847
+ if (path30.isAbsolute(expanded)) return expanded;
23848
+ return cwd && path30.isAbsolute(cwd) ? path30.resolve(cwd, expanded) : expanded;
23769
23849
  }
23770
23850
  function extractFilePaths(toolName, args, shellCommand) {
23771
23851
  const paths = [];