@garuda-agent/garuda 0.15.0 → 0.16.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +30 -17
  3. package/dist/{acpCommand-FZ2P5JFO.js → acpCommand-AJJBKAE5.js} +64 -26
  4. package/dist/chunk-3EQU2GUX.js +27 -0
  5. package/dist/{chunk-K3SIUOAG.js → chunk-44QN5SWZ.js} +2 -2
  6. package/dist/{chunk-INRZR772.js → chunk-B6FA4I7Q.js} +2 -2
  7. package/dist/chunk-EIXUSVFX.js +116 -0
  8. package/dist/{chunk-PQNT34LY.js → chunk-ENLDPN4S.js} +4 -4
  9. package/dist/{chunk-SI2QJYCR.js → chunk-GXZACJUI.js} +6 -25
  10. package/dist/{chunk-2S62ZNTC.js → chunk-HE2K657U.js} +9 -7
  11. package/dist/chunk-NP6RIC25.js +331 -0
  12. package/dist/chunk-R7I2NBPX.js +71 -0
  13. package/dist/{chunk-2TAXSFWN.js → chunk-TUUEBHG2.js} +2 -2
  14. package/dist/{chunk-HRGX53VC.js → chunk-ULAJPMY7.js} +1 -67
  15. package/dist/{chunk-S77XDSD4.js → chunk-USCUXCAU.js} +2 -2
  16. package/dist/{chunk-K7KK7U44.js → chunk-WIJL72ZE.js} +125 -226
  17. package/dist/chunk-XOK5OZOC.js +9 -0
  18. package/dist/cli/index.js +50 -33
  19. package/dist/{create-N4I7TIZE.js → create-VXIH2GUZ.js} +6 -5
  20. package/dist/{evalCommand-3SSFMZQD.js → evalCommand-OX2LQYEK.js} +31 -17
  21. package/dist/{inkChat-34BTFG2K.js → inkChat-YMMMGU7Y.js} +10 -7
  22. package/dist/{install-VRPBZY5H.js → install-EWDSPFFZ.js} +4 -3
  23. package/dist/{jobCommand-XJ5GULS5.js → jobCommand-ACSGSBQ4.js} +9 -7
  24. package/dist/{launchd-QVHQ3VNN.js → launchd-SSX362VG.js} +5 -4
  25. package/dist/{lspCommand-XNTBHXLA.js → lspCommand-JRXKRSL7.js} +4 -3
  26. package/dist/{manager-CSI76AWF.js → manager-AWU4NHHK.js} +4 -3
  27. package/dist/{nightCommand-CR6ZHYGP.js → nightCommand-65MUEV32.js} +9 -7
  28. package/dist/{remove-LE7Q7K46.js → remove-6GDSTAIO.js} +4 -3
  29. package/dist/{server-R3GNIC33.js → server-KHHNHUYV.js} +24 -6
  30. package/dist/setupCommand-VA7D5MZK.js +303 -0
  31. package/package.json +1 -1
  32. package/dist/chunk-EPKWDCV4.js +0 -9
  33. package/dist/chunk-YFQJXRIJ.js +0 -193
@@ -1,22 +1,29 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ loadLspConfig
4
+ } from "./chunk-G2AX7MGS.js";
2
5
  import {
3
6
  hasServerBlocks,
4
7
  serverCallText,
5
8
  serverPairText,
6
9
  withoutServerBlocks
7
10
  } from "./chunk-A2QAIRQL.js";
11
+ import {
12
+ gateProjectSettings
13
+ } from "./chunk-ULAJPMY7.js";
14
+ import {
15
+ REDACTED,
16
+ Redactor,
17
+ writeFileAtomic
18
+ } from "./chunk-EIXUSVFX.js";
8
19
  import {
9
20
  aliasModel,
10
21
  contextSize,
11
- gateProjectSettings,
12
22
  knownModels,
13
23
  lookupModel,
14
24
  responseCost,
15
25
  totalTokens
16
- } from "./chunk-HRGX53VC.js";
17
- import {
18
- loadLspConfig
19
- } from "./chunk-G2AX7MGS.js";
26
+ } from "./chunk-R7I2NBPX.js";
20
27
  import {
21
28
  MAX_RESULTS,
22
29
  providerLabel,
@@ -28,7 +35,7 @@ import {
28
35
  } from "./chunk-23FXBNBB.js";
29
36
  import {
30
37
  VERSION
31
- } from "./chunk-EPKWDCV4.js";
38
+ } from "./chunk-XOK5OZOC.js";
32
39
  import {
33
40
  TrustStore
34
41
  } from "./chunk-5DEWP3YX.js";
@@ -52,24 +59,26 @@ import {
52
59
  } from "./chunk-OUCV3FCT.js";
53
60
  import {
54
61
  DEFAULT_ENV_ALLOWLIST,
55
- EFFORTS,
56
62
  NETWORK_PORTS,
57
63
  PermissionEngine,
58
- ZERO_USAGE,
59
- addUsage,
60
64
  createExecutor,
61
65
  describeAllowlist,
62
66
  expandAllowlist,
63
67
  hostAllowed,
64
68
  isSensitive,
65
69
  loadSettings
66
- } from "./chunk-SI2QJYCR.js";
70
+ } from "./chunk-GXZACJUI.js";
67
71
  import {
68
72
  PathOutsideRootError,
69
73
  displayPath,
70
74
  isInside,
71
75
  resolveInRoot
72
76
  } from "./chunk-WMOLXTBU.js";
77
+ import {
78
+ EFFORTS,
79
+ ZERO_USAGE,
80
+ addUsage
81
+ } from "./chunk-3EQU2GUX.js";
73
82
  import {
74
83
  assertModelAllowedByPolicy,
75
84
  ignoredProjectPolicy,
@@ -86,71 +95,6 @@ import { randomBytes } from "crypto";
86
95
  import { appendFileSync, mkdirSync } from "fs";
87
96
  import { readdir, readFile, rm, stat, utimes } from "fs/promises";
88
97
  import { basename, join } from "path";
89
-
90
- // src/session/redact.ts
91
- var REDACTED = "[REDACTED]";
92
- var PATTERNS = [
93
- /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
94
- /sk-ant-[A-Za-z0-9_-]{16,}/g,
95
- /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}/g,
96
- /\bAKIA[0-9A-Z]{16}\b/g,
97
- /\bgh[pousr]_[A-Za-z0-9]{30,}\b/g,
98
- /\bgithub_pat_[A-Za-z0-9_]{30,}\b/g,
99
- /\bxox[abprs]-[A-Za-z0-9-]{10,}/g,
100
- /\bAIza[0-9A-Za-z_-]{35}\b/g,
101
- /\beyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g
102
- ];
103
- var ASSIGNMENT = /\b([A-Za-z0-9_]*(?:api[_-]?key|secret|token|password|passwd)[A-Za-z0-9_]*)(["']?\s*[:=]\s*["']?)([^\s"'`,;]{8,})/gi;
104
- var OPAQUE_KEYS = /* @__PURE__ */ new Set(["encrypted_content", "encrypted_index", "signature"]);
105
- function looksLikeCode(name, value, next) {
106
- if (/^[\d_.]+$/.test(value)) return !/pass|secret/i.test(name);
107
- if (value.includes("(") || next === "(") return true;
108
- return /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/.test(value) && !/\d{4,}/.test(value);
109
- }
110
- var SECRET_ENV_NAME = /(KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL)/i;
111
- var movedSecrets = /* @__PURE__ */ new Map();
112
- function keepSecretForRedaction(name, value) {
113
- movedSecrets.set(name, value);
114
- }
115
- var Redactor = class {
116
- literals;
117
- /**
118
- * `env`: variables whose names look secret have their values removed wherever they appear.
119
- * Default: this process's environment and the secrets moved out of it.
120
- */
121
- constructor(env = { ...process.env, ...Object.fromEntries(movedSecrets) }) {
122
- this.literals = Object.entries(env).filter(([name, value]) => SECRET_ENV_NAME.test(name) && (value?.length ?? 0) >= 8).map(([, value]) => value).sort((a, b) => b.length - a.length);
123
- }
124
- text(input12) {
125
- let out = input12;
126
- for (const literal of this.literals) out = out.split(literal).join(REDACTED);
127
- for (const pattern of PATTERNS) out = out.replace(pattern, REDACTED);
128
- return out.replace(
129
- ASSIGNMENT,
130
- (all, name, sep4, value, at) => looksLikeCode(name, value, out[at + all.length]) ? all : `${name}${sep4}${REDACTED}`
131
- );
132
- }
133
- /** A copy of `value` with every string redacted. */
134
- value(value) {
135
- return this.walk(value);
136
- }
137
- walk(value) {
138
- if (typeof value === "string") return this.text(value);
139
- if (Array.isArray(value)) return value.map((item) => this.walk(item));
140
- if (value !== null && typeof value === "object") {
141
- const redactedThinking = value.type === "redacted_thinking";
142
- return Object.fromEntries(
143
- Object.entries(value).map(([k, v]) => [
144
- k,
145
- (OPAQUE_KEYS.has(k) || redactedThinking && k === "data") && typeof v === "string" ? v : this.walk(v)
146
- ])
147
- );
148
- }
149
- return value;
150
- }
151
- };
152
-
153
- // src/session/store.ts
154
98
  var SESSIONS_DIR = join(".garuda", "sessions");
155
99
  var FileSessionStore = class {
156
100
  dir;
@@ -1936,50 +1880,6 @@ var repoMapTool = {
1936
1880
  // src/tools/editFile.ts
1937
1881
  import { readFile as readFile3 } from "fs/promises";
1938
1882
  import { z as z4 } from "zod";
1939
-
1940
- // src/tools/atomicWrite.ts
1941
- import { randomBytes as randomBytes3 } from "crypto";
1942
- import { chmod, link, realpath, rename, stat as stat2, unlink, writeFile } from "fs/promises";
1943
- import { basename as basename3, dirname, join as join4 } from "path";
1944
- async function writeFileAtomic(path, content, { createOnly }) {
1945
- const target = createOnly ? path : await realpath(path);
1946
- const temp = join4(
1947
- dirname(target),
1948
- `.${basename3(target)}.garuda-${randomBytes3(4).toString("hex")}.tmp`
1949
- );
1950
- const mode = createOnly ? void 0 : (await stat2(target)).mode & 4095;
1951
- await writeFile(temp, content, { flag: "wx", ...mode === void 0 ? {} : { mode } });
1952
- try {
1953
- if (createOnly) {
1954
- try {
1955
- await link(temp, target);
1956
- } catch (error) {
1957
- const code = error.code;
1958
- if (code !== "EPERM" && code !== "ENOTSUP" && code !== "EXDEV") throw error;
1959
- if (await exists(target)) throw Object.assign(new Error("EEXIST"), { code: "EEXIST" });
1960
- await rename(temp, target);
1961
- return;
1962
- }
1963
- } else {
1964
- await chmod(temp, mode ?? 420);
1965
- await rename(temp, target);
1966
- return;
1967
- }
1968
- } finally {
1969
- await unlink(temp).catch(() => {
1970
- });
1971
- }
1972
- }
1973
- async function exists(path) {
1974
- try {
1975
- await stat2(path);
1976
- return true;
1977
- } catch {
1978
- return false;
1979
- }
1980
- }
1981
-
1982
- // src/tools/editFile.ts
1983
1883
  var input2 = z4.object({
1984
1884
  path: z4.string().min(1).describe("File path, relative to the working root."),
1985
1885
  old_string: z4.string().min(1).describe("The exact text to replace. It must occur exactly once in the file."),
@@ -2085,11 +1985,11 @@ function countOccurrences(text, search3) {
2085
1985
  }
2086
1986
 
2087
1987
  // src/tools/glob.ts
2088
- import { stat as stat4 } from "fs/promises";
1988
+ import { stat as stat3 } from "fs/promises";
2089
1989
  import { z as z5 } from "zod";
2090
1990
 
2091
1991
  // src/tools/files.ts
2092
- import { stat as stat3 } from "fs/promises";
1992
+ import { stat as stat2 } from "fs/promises";
2093
1993
  import { globby } from "globby";
2094
1994
  async function listFiles(base, pattern, root) {
2095
1995
  assertSafePattern(pattern);
@@ -2114,7 +2014,7 @@ function assertSafePattern(pattern) {
2114
2014
  }
2115
2015
  async function isDirectory(path) {
2116
2016
  try {
2117
- return (await stat3(path)).isDirectory();
2017
+ return (await stat2(path)).isDirectory();
2118
2018
  } catch {
2119
2019
  return false;
2120
2020
  }
@@ -2140,7 +2040,7 @@ var globTool = {
2140
2040
  (p) => !permissions.deniedByPolicy(displayPath(root, p))
2141
2041
  );
2142
2042
  const withTimes = await Promise.all(
2143
- paths.map(async (p) => ({ p, mtime: (await stat4(p).catch(() => void 0))?.mtimeMs ?? 0 }))
2043
+ paths.map(async (p) => ({ p, mtime: (await stat3(p).catch(() => void 0))?.mtimeMs ?? 0 }))
2144
2044
  );
2145
2045
  withTimes.sort((a, b) => b.mtime - a.mtime || a.p.localeCompare(b.p));
2146
2046
  return {
@@ -2158,7 +2058,7 @@ var globTool = {
2158
2058
  };
2159
2059
 
2160
2060
  // src/tools/grep.ts
2161
- import { lstat, readFile as readFile4, realpath as realpath2, stat as stat5 } from "fs/promises";
2061
+ import { lstat, readFile as readFile4, realpath, stat as stat4 } from "fs/promises";
2162
2062
  import { z as z6 } from "zod";
2163
2063
 
2164
2064
  // src/tools/regexWorker.ts
@@ -2308,13 +2208,13 @@ async function search2(args, root, signal, permissions, matcher, mode, max, cont
2308
2208
  const shownPath = displayPath(root, file2);
2309
2209
  if (isSensitive(shownPath) || permissions.deniedByPolicy(shownPath)) continue;
2310
2210
  if ((await lstat(file2).catch(() => void 0))?.isSymbolicLink() === true) {
2311
- realRoot ??= await realpath2(root);
2312
- const real = await realpath2(file2).catch(() => void 0);
2211
+ realRoot ??= await realpath(root);
2212
+ const real = await realpath(file2).catch(() => void 0);
2313
2213
  if (real === void 0 || !isInside(realRoot, real)) continue;
2314
2214
  const realShown = displayPath(realRoot, real);
2315
2215
  if (isSensitive(realShown) || permissions.deniedByPolicy(realShown)) continue;
2316
2216
  }
2317
- const info = await stat5(file2).catch(() => void 0);
2217
+ const info = await stat4(file2).catch(() => void 0);
2318
2218
  if (info === void 0 || !info.isFile() || info.size > LIMITS.grepFileBytes) continue;
2319
2219
  const buffer = await readFile4(file2);
2320
2220
  if (looksBinary(buffer)) continue;
@@ -2587,7 +2487,7 @@ var processManagerTool = {
2587
2487
  };
2588
2488
 
2589
2489
  // src/tools/readFile.ts
2590
- import { readFile as readFile5, stat as stat6 } from "fs/promises";
2490
+ import { readFile as readFile5, stat as stat5 } from "fs/promises";
2591
2491
  import { z as z9 } from "zod";
2592
2492
  var input6 = z9.object({
2593
2493
  path: z9.string().min(1).describe("File path, relative to the working root."),
@@ -2609,7 +2509,7 @@ var readFileTool = {
2609
2509
  async run({ path, offset = 1, limit = LIMITS.readLines }, { root, files }) {
2610
2510
  const absolute = await resolveInRoot(root, path);
2611
2511
  const shown = displayPath(root, absolute);
2612
- const info = await stat6(absolute).catch(() => void 0);
2512
+ const info = await stat5(absolute).catch(() => void 0);
2613
2513
  if (info === void 0) throw new Error(`${shown} does not exist.`);
2614
2514
  if (info.isDirectory()) throw new Error(`${shown} is a folder. Use glob to list its files.`);
2615
2515
  if (info.size > LIMITS.readFileBytes) {
@@ -2642,23 +2542,23 @@ var readFileTool = {
2642
2542
 
2643
2543
  // src/tools/remember.ts
2644
2544
  import { mkdir as mkdir2, readFile as readFile7 } from "fs/promises";
2645
- import { dirname as dirname2 } from "path";
2545
+ import { dirname } from "path";
2646
2546
  import { z as z10 } from "zod";
2647
2547
 
2648
2548
  // src/context/instructions.ts
2649
- import { readFile as readFile6, realpath as realpath3 } from "fs/promises";
2650
- import { join as join5 } from "path";
2549
+ import { readFile as readFile6, realpath as realpath2 } from "fs/promises";
2550
+ import { join as join4 } from "path";
2651
2551
  async function readInRoot(root, name) {
2652
- const file2 = join5(root, name);
2552
+ const file2 = join4(root, name);
2653
2553
  let real;
2654
2554
  try {
2655
- real = await realpath3(file2);
2555
+ real = await realpath2(file2);
2656
2556
  } catch (error) {
2657
2557
  const code = error.code;
2658
2558
  if (code === "ENOENT" || code === "ENOTDIR") return void 0;
2659
2559
  throw error;
2660
2560
  }
2661
- if (!isInside(await realpath3(root), real)) return void 0;
2561
+ if (!isInside(await realpath2(root), real)) return void 0;
2662
2562
  try {
2663
2563
  return await readFile6(real, "utf8");
2664
2564
  } catch (error) {
@@ -2872,7 +2772,7 @@ var rememberTool = {
2872
2772
  `The project memory is full (${MEMORY_MAX_CHARS} characters). Ask the user to clean up ${MEMORY_FILE}.`
2873
2773
  );
2874
2774
  }
2875
- await mkdir2(dirname2(path), { recursive: true });
2775
+ await mkdir2(dirname(path), { recursive: true });
2876
2776
  await writeFileAtomic(path, next, { createOnly: current === "" });
2877
2777
  return `Saved to ${MEMORY_FILE}. It loads in the next session.`;
2878
2778
  }
@@ -3235,7 +3135,7 @@ function pageText(page, start, maxChars) {
3235
3135
 
3236
3136
  // src/tools/writeFile.ts
3237
3137
  import { mkdir as mkdir3 } from "fs/promises";
3238
- import { dirname as dirname3 } from "path";
3138
+ import { dirname as dirname2 } from "path";
3239
3139
  import { z as z13 } from "zod";
3240
3140
  var input9 = z13.object({
3241
3141
  path: z13.string().min(1).describe("Path of the new file, relative to the working root."),
@@ -3264,7 +3164,7 @@ var writeFileTool = {
3264
3164
  const { root, files } = context;
3265
3165
  const absolute = await resolveInRoot(root, path);
3266
3166
  const shown = displayPath(root, absolute);
3267
- await mkdir3(dirname3(absolute), { recursive: true });
3167
+ await mkdir3(dirname2(absolute), { recursive: true });
3268
3168
  try {
3269
3169
  await writeFileAtomic(absolute, content, { createOnly: true });
3270
3170
  } catch (error) {
@@ -3317,7 +3217,7 @@ function defaultTools({
3317
3217
  // src/app/runtime.ts
3318
3218
  import { readFile as readFile16 } from "fs/promises";
3319
3219
  import { homedir as homedir4 } from "os";
3320
- import { join as join18 } from "path";
3220
+ import { join as join17 } from "path";
3321
3221
 
3322
3222
  // src/agents/agentTool.ts
3323
3223
  import { z as z14 } from "zod";
@@ -3478,7 +3378,7 @@ function describeCall(call) {
3478
3378
  // src/agents/custom.ts
3479
3379
  import { createHash as createHash3 } from "crypto";
3480
3380
  import { lstat as lstat2, readdir as readdir3, readFile as readFile8 } from "fs/promises";
3481
- import { join as join6 } from "path";
3381
+ import { join as join5 } from "path";
3482
3382
 
3483
3383
  // src/skills/frontmatter.ts
3484
3384
  function parseFrontmatterBlock(text) {
@@ -3565,10 +3465,10 @@ var READ_ONLY_AGENT_TOOLS = [
3565
3465
  ];
3566
3466
  function agentDirs(home, root) {
3567
3467
  return [
3568
- { dir: join6(home, ".garuda", "agents"), shown: "~/.garuda/agents", source: "user" },
3569
- { dir: join6(home, ".claude", "agents"), shown: "~/.claude/agents", source: "user" },
3570
- { dir: join6(root, ".garuda", "agents"), shown: ".garuda/agents", source: "project" },
3571
- { dir: join6(root, ".claude", "agents"), shown: ".claude/agents", source: "project" }
3468
+ { dir: join5(home, ".garuda", "agents"), shown: "~/.garuda/agents", source: "user" },
3469
+ { dir: join5(home, ".claude", "agents"), shown: "~/.claude/agents", source: "user" },
3470
+ { dir: join5(root, ".garuda", "agents"), shown: ".garuda/agents", source: "project" },
3471
+ { dir: join5(root, ".claude", "agents"), shown: ".claude/agents", source: "project" }
3572
3472
  ];
3573
3473
  }
3574
3474
  async function loadAgents(options) {
@@ -3585,7 +3485,7 @@ async function loadAgents(options) {
3585
3485
  continue;
3586
3486
  }
3587
3487
  for (const entry of entries) {
3588
- const file2 = join6(place.dir, entry);
3488
+ const file2 = join5(place.dir, entry);
3589
3489
  const shown = `${place.shown}/${entry}`;
3590
3490
  try {
3591
3491
  const info = await lstat2(file2);
@@ -4168,16 +4068,16 @@ function createMoeDispatchTool(options) {
4168
4068
 
4169
4069
  // src/commands/custom.ts
4170
4070
  import { createHash as createHash4 } from "crypto";
4171
- import { lstat as lstat3, readdir as readdir4, readFile as readFile9, stat as stat7 } from "fs/promises";
4172
- import { join as join7, relative, sep } from "path";
4173
- var COMMANDS_DIR = join7(".garuda", "commands");
4071
+ import { lstat as lstat3, readdir as readdir4, readFile as readFile9, stat as stat6 } from "fs/promises";
4072
+ import { join as join6, relative, sep } from "path";
4073
+ var COMMANDS_DIR = join6(".garuda", "commands");
4174
4074
  var COMMAND_MAX_CHARS = 2e4;
4175
4075
  var MAX_FILES = 200;
4176
4076
  var NAME = /^[a-z0-9][a-z0-9_-]*(?::[a-z0-9][a-z0-9_-]*)*$/;
4177
4077
  async function loadCommands(options) {
4178
4078
  const problems = [];
4179
- const user = await loadDir(join7(options.home, COMMANDS_DIR), "user", problems);
4180
- const project = join7(options.home, COMMANDS_DIR) === join7(options.root, COMMANDS_DIR) ? [] : await loadDir(join7(options.root, COMMANDS_DIR), "project", problems);
4079
+ const user = await loadDir(join6(options.home, COMMANDS_DIR), "user", problems);
4080
+ const project = join6(options.home, COMMANDS_DIR) === join6(options.root, COMMANDS_DIR) ? [] : await loadDir(join6(options.root, COMMANDS_DIR), "project", problems);
4181
4081
  const byName = /* @__PURE__ */ new Map();
4182
4082
  for (const command of [...user, ...project]) {
4183
4083
  if (options.builtins.includes(command.name)) {
@@ -4207,7 +4107,7 @@ async function loadDir(dir, source, problems) {
4207
4107
  }
4208
4108
  const out = [];
4209
4109
  for (const rel of files) {
4210
- const file2 = join7(dir, rel);
4110
+ const file2 = join6(dir, rel);
4211
4111
  const name = relative(dir, file2).slice(0, -3).split(sep).join(":").toLowerCase();
4212
4112
  if (!NAME.test(name)) {
4213
4113
  problems.push(`${file2}: a command name may hold only a\u2013z, 0\u20139, "-" and "_".`);
@@ -4218,7 +4118,7 @@ async function loadDir(dir, source, problems) {
4218
4118
  problems.push(`${file2}: a project command may not be a symbolic link; ignored.`);
4219
4119
  continue;
4220
4120
  }
4221
- if (!(await stat7(file2)).isFile()) continue;
4121
+ if (!(await stat6(file2)).isFile()) continue;
4222
4122
  const text = await readFile9(file2, "utf8");
4223
4123
  if (text.length > COMMAND_MAX_CHARS) {
4224
4124
  problems.push(`${file2}: longer than ${COMMAND_MAX_CHARS} characters; ignored.`);
@@ -4310,18 +4210,18 @@ function commandConsent(command, changed, isolation) {
4310
4210
 
4311
4211
  // src/format/formatters.ts
4312
4212
  import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "fs";
4313
- import { delimiter, extname, join as join8 } from "path";
4213
+ import { delimiter, extname, join as join7 } from "path";
4314
4214
  var JS_EXTENSIONS = ["js", "jsx", "mjs", "cjs", "ts", "tsx", "mts", "cts"];
4315
4215
  function detectFormatters(root, path, settings = {}) {
4316
4216
  const found = [];
4317
4217
  const onPath = (name) => findOnPath(name, path);
4318
4218
  const local = (name) => {
4319
- const file2 = join8(root, "node_modules", ".bin", name);
4219
+ const file2 = join7(root, "node_modules", ".bin", name);
4320
4220
  return isFile(file2) ? file2 : void 0;
4321
4221
  };
4322
- const venv = (name) => [join8(root, ".venv", "bin", name), join8(root, "venv", "bin", name)].find(isFile);
4222
+ const venv = (name) => [join7(root, ".venv", "bin", name), join7(root, "venv", "bin", name)].find(isFile);
4323
4223
  const biome = local("biome");
4324
- if (biome !== void 0 && ["biome.json", "biome.jsonc"].some((f) => isFile(join8(root, f)))) {
4224
+ if (biome !== void 0 && ["biome.json", "biome.jsonc"].some((f) => isFile(join7(root, f)))) {
4325
4225
  found.push({
4326
4226
  name: "biome",
4327
4227
  extensions: [...JS_EXTENSIONS, "json", "jsonc", "css"],
@@ -4347,9 +4247,9 @@ function detectFormatters(root, path, settings = {}) {
4347
4247
  command: [prettier, "--write", "$FILE"]
4348
4248
  });
4349
4249
  }
4350
- const pyproject = readText(join8(root, "pyproject.toml"));
4250
+ const pyproject = readText(join7(root, "pyproject.toml"));
4351
4251
  const ruff = venv("ruff") ?? onPath("ruff");
4352
- if (ruff !== void 0 && (pyproject.includes("[tool.ruff") || ["ruff.toml", ".ruff.toml"].some((f) => isFile(join8(root, f))))) {
4252
+ if (ruff !== void 0 && (pyproject.includes("[tool.ruff") || ["ruff.toml", ".ruff.toml"].some((f) => isFile(join7(root, f))))) {
4353
4253
  found.push({ name: "ruff", extensions: ["py", "pyi"], command: [ruff, "format", "$FILE"] });
4354
4254
  }
4355
4255
  const black = venv("black") ?? onPath("black");
@@ -4357,11 +4257,11 @@ function detectFormatters(root, path, settings = {}) {
4357
4257
  found.push({ name: "black", extensions: ["py", "pyi"], command: [black, "-q", "$FILE"] });
4358
4258
  }
4359
4259
  const gofmt = onPath("gofmt");
4360
- if (gofmt !== void 0 && isFile(join8(root, "go.mod"))) {
4260
+ if (gofmt !== void 0 && isFile(join7(root, "go.mod"))) {
4361
4261
  found.push({ name: "gofmt", extensions: ["go"], command: [gofmt, "-w", "$FILE"] });
4362
4262
  }
4363
4263
  const rustfmt = onPath("rustfmt");
4364
- const cargo = readText(join8(root, "Cargo.toml"));
4264
+ const cargo = readText(join7(root, "Cargo.toml"));
4365
4265
  if (rustfmt !== void 0 && cargo !== "") {
4366
4266
  const edition = /^\s*edition\s*=\s*"(\d{4})"/m.exec(cargo)?.[1] ?? "2021";
4367
4267
  found.push({
@@ -4407,9 +4307,9 @@ function hasPrettierConfig(root) {
4407
4307
  "prettier.config.cjs",
4408
4308
  "prettier.config.mjs"
4409
4309
  ];
4410
- if (files.some((f) => isFile(join8(root, f)))) return true;
4310
+ if (files.some((f) => isFile(join7(root, f)))) return true;
4411
4311
  try {
4412
- const pkg = JSON.parse(readText(join8(root, "package.json")) || "{}");
4312
+ const pkg = JSON.parse(readText(join7(root, "package.json")) || "{}");
4413
4313
  return pkg.prettier !== void 0;
4414
4314
  } catch {
4415
4315
  return false;
@@ -4418,7 +4318,7 @@ function hasPrettierConfig(root) {
4418
4318
  function findOnPath(name, path) {
4419
4319
  for (const dir of (path ?? "").split(delimiter)) {
4420
4320
  if (dir === "") continue;
4421
- const file2 = join8(dir, name);
4321
+ const file2 = join7(dir, name);
4422
4322
  if (isFile(file2)) return file2;
4423
4323
  }
4424
4324
  return void 0;
@@ -4441,9 +4341,9 @@ function readText(file2) {
4441
4341
  // src/hooks/config.ts
4442
4342
  import { createHash as createHash5 } from "crypto";
4443
4343
  import { readFile as readFile10 } from "fs/promises";
4444
- import { join as join9 } from "path";
4344
+ import { join as join8 } from "path";
4445
4345
  import { z as z17 } from "zod";
4446
- var HOOKS_FILE = join9(".garuda", "hooks.json");
4346
+ var HOOKS_FILE = join8(".garuda", "hooks.json");
4447
4347
  var HOOK_EVENTS = ["preToolUse", "postToolUse"];
4448
4348
  var hookSchema = z17.strictObject({
4449
4349
  command: z17.string().min(1),
@@ -4489,8 +4389,8 @@ async function readHooks(file2, source) {
4489
4389
  return { hooks, problems };
4490
4390
  }
4491
4391
  async function loadHooks(home, root) {
4492
- const user = await readHooks(join9(home, HOOKS_FILE), "user");
4493
- const project = home === root ? { hooks: [], problems: [] } : await readHooks(join9(root, HOOKS_FILE), "project");
4392
+ const user = await readHooks(join8(home, HOOKS_FILE), "user");
4393
+ const project = home === root ? { hooks: [], problems: [] } : await readHooks(join8(root, HOOKS_FILE), "project");
4494
4394
  return {
4495
4395
  user: user.hooks,
4496
4396
  project: project.hooks,
@@ -4503,10 +4403,10 @@ function hooksHash(hooks) {
4503
4403
  }
4504
4404
 
4505
4405
  // src/hooks/runner.ts
4506
- import { randomBytes as randomBytes4 } from "crypto";
4507
- import { rm as rm2, writeFile as writeFile2 } from "fs/promises";
4406
+ import { randomBytes as randomBytes3 } from "crypto";
4407
+ import { rm as rm2, writeFile } from "fs/promises";
4508
4408
  import { tmpdir } from "os";
4509
- import { isAbsolute as isAbsolute2, join as join10 } from "path";
4409
+ import { isAbsolute as isAbsolute2, join as join9 } from "path";
4510
4410
  var OUTPUT_BYTES = 8e3;
4511
4411
  var FEEDBACK_CHARS = 4e3;
4512
4412
  var HookRunner = class {
@@ -4577,7 +4477,7 @@ ${clean2(r.stderr)}
4577
4477
  });
4578
4478
  return { exitCode: null, signal: "refused by the team policy", timedOut: false, stderr: "" };
4579
4479
  }
4580
- const file2 = join10(tmpdir(), `garuda-hook-${randomBytes4(6).toString("hex")}.json`);
4480
+ const file2 = join9(tmpdir(), `garuda-hook-${randomBytes3(6).toString("hex")}.json`);
4581
4481
  const data = {
4582
4482
  event: hook.event,
4583
4483
  tool: call.tool,
@@ -4586,14 +4486,14 @@ ${clean2(r.stderr)}
4586
4486
  ...outcome === void 0 ? {} : { result: outcome },
4587
4487
  root
4588
4488
  };
4589
- await writeFile2(file2, JSON.stringify(data), { mode: 384 });
4489
+ await writeFile(file2, JSON.stringify(data), { mode: 384 });
4590
4490
  const env = {
4591
4491
  GARUDA_HOOK_EVENT: hook.event,
4592
4492
  GARUDA_TOOL: call.tool,
4593
4493
  GARUDA_HOOK_INPUT: file2
4594
4494
  };
4595
4495
  if (target?.kind === "path") {
4596
- env.GARUDA_FILE = isAbsolute2(target.path) ? target.path : join10(root, target.path);
4496
+ env.GARUDA_FILE = isAbsolute2(target.path) ? target.path : join9(root, target.path);
4597
4497
  }
4598
4498
  if (target?.kind === "command") env.GARUDA_COMMAND = target.command;
4599
4499
  if (target?.kind === "url") env.GARUDA_URL = target.url;
@@ -4659,8 +4559,8 @@ function hooksConsent(hooks, file2, isolation, changed) {
4659
4559
 
4660
4560
  // src/knowledge/index.ts
4661
4561
  import { createHash as createHash7 } from "crypto";
4662
- import { mkdir as mkdir4, readFile as readFile12, stat as stat8, writeFile as writeFile3 } from "fs/promises";
4663
- import { dirname as dirname5, extname as extname3, join as join13 } from "path";
4562
+ import { mkdir as mkdir4, readFile as readFile12, stat as stat7, writeFile as writeFile2 } from "fs/promises";
4563
+ import { dirname as dirname4, extname as extname3, join as join12 } from "path";
4664
4564
 
4665
4565
  // src/knowledge/java.ts
4666
4566
  import { readFileSync as readFileSync3, statSync as statSync2 } from "fs";
@@ -5342,7 +5242,7 @@ function createRustExpert(root) {
5342
5242
  // src/knowledge/plugins.ts
5343
5243
  import { createHash as createHash6 } from "crypto";
5344
5244
  import { readdir as readdir5, readFile as readFile11 } from "fs/promises";
5345
- import { basename as basename4, extname as extname2, join as join12 } from "path";
5245
+ import { basename as basename3, extname as extname2, join as join11 } from "path";
5346
5246
  import { pathToFileURL } from "url";
5347
5247
 
5348
5248
  // src/knowledge/python.ts
@@ -5585,7 +5485,7 @@ function openTripleQuote(line) {
5585
5485
 
5586
5486
  // src/knowledge/typescript.ts
5587
5487
  import { readFileSync as readFileSync7, statSync as statSync6 } from "fs";
5588
- import { dirname as dirname4, isAbsolute as isAbsolute7, join as join11, relative as relative2, sep as sep2 } from "path";
5488
+ import { dirname as dirname3, isAbsolute as isAbsolute7, join as join10, relative as relative2, sep as sep2 } from "path";
5589
5489
  async function createTypeScriptExpert(root) {
5590
5490
  const ts = (await import("ts6")).default;
5591
5491
  return new TypeScriptExpert(ts, root);
@@ -5751,7 +5651,7 @@ var TypeScriptExpert = class {
5751
5651
  };
5752
5652
  }
5753
5653
  abs(path) {
5754
- return isAbsolute7(path) ? path : join11(this.root, path);
5654
+ return isAbsolute7(path) ? path : join10(this.root, path);
5755
5655
  }
5756
5656
  rel(file2) {
5757
5657
  return relative2(this.root, file2).split(sep2).join("/");
@@ -5775,7 +5675,7 @@ function declarationKind(ts, node) {
5775
5675
  function compilerOptions(ts, root) {
5776
5676
  let base = {};
5777
5677
  const configPath = ts.findConfigFile(root, (f) => ts.sys.fileExists(f));
5778
- if (configPath !== void 0 && dirname4(configPath) === root) {
5678
+ if (configPath !== void 0 && dirname3(configPath) === root) {
5779
5679
  const read = ts.readConfigFile(configPath, (f) => ts.sys.readFile(f));
5780
5680
  if (read.config !== void 0) {
5781
5681
  base = ts.parseJsonConfigFileContent(read.config, ts.sys, root).options;
@@ -5838,12 +5738,12 @@ async function discoverPlugins({
5838
5738
  }) {
5839
5739
  const plugins = includeBuiltins ? [...BUILTIN_PLUGINS] : [];
5840
5740
  const warnings = [];
5841
- const userDir = join12(home, ".garuda", "languages");
5741
+ const userDir = join11(home, ".garuda", "languages");
5842
5742
  const userFiles = await safeReaddir(userDir);
5843
5743
  for (const filename of userFiles) {
5844
5744
  if (!isPluginFile(filename)) continue;
5845
- const fullPath = join12(userDir, filename);
5846
- const id = basename4(filename, extname2(filename));
5745
+ const fullPath = join11(userDir, filename);
5746
+ const id = basename3(filename, extname2(filename));
5847
5747
  try {
5848
5748
  const plugin = await loadPluginModule(fullPath, id, "user", root);
5849
5749
  if (plugin) {
@@ -5853,7 +5753,7 @@ async function discoverPlugins({
5853
5753
  warnings.push(`Failed to load user language plugin "${id}": ${error.message}`);
5854
5754
  }
5855
5755
  }
5856
- const projDir = join12(root, ".garuda", "languages");
5756
+ const projDir = join11(root, ".garuda", "languages");
5857
5757
  const projFiles = (await safeReaddir(projDir)).filter(isPluginFile);
5858
5758
  if (!projectPlugins) {
5859
5759
  if (projFiles.length > 0) {
@@ -5865,8 +5765,8 @@ async function discoverPlugins({
5865
5765
  }
5866
5766
  for (const filename of projFiles) {
5867
5767
  if (!isPluginFile(filename)) continue;
5868
- const fullPath = join12(projDir, filename);
5869
- const id = basename4(filename, extname2(filename));
5768
+ const fullPath = join11(projDir, filename);
5769
+ const id = basename3(filename, extname2(filename));
5870
5770
  try {
5871
5771
  const content = await readFile11(fullPath, "utf8");
5872
5772
  const hash2 = createHash6("sha256").update(content).digest("hex");
@@ -6101,7 +6001,7 @@ var KnowledgeIndex = class {
6101
6001
  const callableSymbols = fileSymbols.filter(
6102
6002
  (s) => s.kind === "function" || s.kind === "method" || s.kind === "constructor" || s.kind === "class"
6103
6003
  );
6104
- const content = await readFile12(join13(this.root, filePath), "utf8").catch(() => "");
6004
+ const content = await readFile12(join12(this.root, filePath), "utf8").catch(() => "");
6105
6005
  const lines = content.split("\n");
6106
6006
  for (const site of sites) {
6107
6007
  const enclosing = enclosingSymbol(filePath, content, lines, site.line, callableSymbols);
@@ -6291,7 +6191,7 @@ var KnowledgeIndex = class {
6291
6191
  const prefix = dir.replace(/^\.?\/?/, "").replace(/\/?$/, dir === "" || dir === "." ? "" : "/");
6292
6192
  for (const { expert, files } of await this.byExpert()) {
6293
6193
  for (const path of files) {
6294
- const content = await readFile12(join13(this.root, path), "utf8").catch(() => void 0);
6194
+ const content = await readFile12(join12(this.root, path), "utf8").catch(() => void 0);
6295
6195
  if (content === void 0) continue;
6296
6196
  const hash2 = createHash7("sha256").update(content).digest("hex");
6297
6197
  const cached = cache.files[path];
@@ -6363,7 +6263,7 @@ var KnowledgeIndex = class {
6363
6263
  const ext = extname3(path);
6364
6264
  const group = groups.find((g) => g.expert.extensions.includes(ext));
6365
6265
  if (group === void 0) continue;
6366
- const info = await stat8(absolute).catch(() => void 0);
6266
+ const info = await stat7(absolute).catch(() => void 0);
6367
6267
  if (info === void 0 || info.size > MAX_FILE_BYTES) continue;
6368
6268
  group.files.push(path);
6369
6269
  if (++count >= MAX_FILES2) break;
@@ -6372,7 +6272,7 @@ var KnowledgeIndex = class {
6372
6272
  }
6373
6273
  async loadCache() {
6374
6274
  try {
6375
- const cache = JSON.parse(await readFile12(join13(this.root, GRAPH_FILE), "utf8"));
6275
+ const cache = JSON.parse(await readFile12(join12(this.root, GRAPH_FILE), "utf8"));
6376
6276
  if (cache.version === GRAPH_VERSION) return cache;
6377
6277
  } catch {
6378
6278
  }
@@ -6380,10 +6280,10 @@ var KnowledgeIndex = class {
6380
6280
  }
6381
6281
  /** Best effort (0.14, review): a read-only checkout gives the map without a cache, not an error. */
6382
6282
  async saveCache(cache) {
6383
- const path = join13(this.root, GRAPH_FILE);
6283
+ const path = join12(this.root, GRAPH_FILE);
6384
6284
  try {
6385
- await mkdir4(dirname5(path), { recursive: true });
6386
- await writeFile3(path, JSON.stringify(cache));
6285
+ await mkdir4(dirname4(path), { recursive: true });
6286
+ await writeFile2(path, JSON.stringify(cache));
6387
6287
  } catch {
6388
6288
  }
6389
6289
  }
@@ -6620,8 +6520,8 @@ function repairServerBlocks(message) {
6620
6520
 
6621
6521
  // src/skills/load.ts
6622
6522
  import { createHash as createHash8 } from "crypto";
6623
- import { lstat as lstat4, readdir as readdir6, readFile as readFile13, stat as stat9 } from "fs/promises";
6624
- import { join as join14 } from "path";
6523
+ import { lstat as lstat4, readdir as readdir6, readFile as readFile13, stat as stat8 } from "fs/promises";
6524
+ import { join as join13 } from "path";
6625
6525
  var SKILL_FILE = "SKILL.md";
6626
6526
  var SKILL_NAME = /^(?!-)(?!.*--)[a-z0-9-]{1,64}(?<!-)$/;
6627
6527
  var SKILL_MAX_CHARS = 5e4;
@@ -6629,10 +6529,10 @@ var DESCRIPTION_MAX_CHARS2 = 1536;
6629
6529
  var MAX_SKILLS = 100;
6630
6530
  function skillDirs(home, root) {
6631
6531
  return [
6632
- { dir: join14(home, ".garuda", "skills"), shown: "~/.garuda/skills", source: "user" },
6633
- { dir: join14(home, ".claude", "skills"), shown: "~/.claude/skills", source: "user" },
6634
- { dir: join14(root, ".garuda", "skills"), shown: ".garuda/skills", source: "project" },
6635
- { dir: join14(root, ".claude", "skills"), shown: ".claude/skills", source: "project" }
6532
+ { dir: join13(home, ".garuda", "skills"), shown: "~/.garuda/skills", source: "user" },
6533
+ { dir: join13(home, ".claude", "skills"), shown: "~/.claude/skills", source: "user" },
6534
+ { dir: join13(root, ".garuda", "skills"), shown: ".garuda/skills", source: "project" },
6535
+ { dir: join13(root, ".claude", "skills"), shown: ".claude/skills", source: "project" }
6636
6536
  ];
6637
6537
  }
6638
6538
  async function loadSkills(options) {
@@ -6672,11 +6572,11 @@ async function loadDir2(place, problems) {
6672
6572
  const out = [];
6673
6573
  for (const entry of entries) {
6674
6574
  if (entry.startsWith(".")) continue;
6675
- const dir = join14(place.dir, entry);
6575
+ const dir = join13(place.dir, entry);
6676
6576
  const shown = `${place.shown}/${entry}`;
6677
- const file2 = join14(dir, SKILL_FILE);
6577
+ const file2 = join13(dir, SKILL_FILE);
6678
6578
  try {
6679
- if (!(await stat9(dir)).isDirectory()) continue;
6579
+ if (!(await stat8(dir)).isDirectory()) continue;
6680
6580
  if (place.source === "project" && ((await lstat4(dir)).isSymbolicLink() || (await lstat4(file2)).isSymbolicLink())) {
6681
6581
  problems.push(`${shown}: a project skill may not be a symbolic link; ignored.`);
6682
6582
  continue;
@@ -6774,8 +6674,8 @@ function skillConsent(skill, changed, isolation) {
6774
6674
  }
6775
6675
 
6776
6676
  // src/skills/tool.ts
6777
- import { readdir as readdir7, readFile as readFile14, realpath as realpath4, stat as stat10 } from "fs/promises";
6778
- import { join as join15, relative as relative3, resolve, sep as sep3 } from "path";
6677
+ import { readdir as readdir7, readFile as readFile14, realpath as realpath3, stat as stat9 } from "fs/promises";
6678
+ import { join as join14, relative as relative3, resolve, sep as sep3 } from "path";
6779
6679
  import { z as z18 } from "zod";
6780
6680
  var input10 = z18.object({
6781
6681
  name: z18.string().min(1).describe("The skill name from the list."),
@@ -6845,11 +6745,11 @@ async function skillText(skill, args, place) {
6845
6745
  async function readSkillFile(skill, file2) {
6846
6746
  const target = resolve(skill.dir, file2);
6847
6747
  try {
6848
- const [realDir, realTarget] = await Promise.all([realpath4(skill.dir), realpath4(target)]);
6748
+ const [realDir, realTarget] = await Promise.all([realpath3(skill.dir), realpath3(target)]);
6849
6749
  if (!isInside(realDir, realTarget) || !isInside(skill.dir, target)) {
6850
6750
  return { error: true, text: `"${file2}" is outside the skill folder.` };
6851
6751
  }
6852
- if (!(await stat10(realTarget)).isFile()) {
6752
+ if (!(await stat9(realTarget)).isFile()) {
6853
6753
  return { error: true, text: `"${file2}" is not a file.` };
6854
6754
  }
6855
6755
  const buffer = await readFile14(realTarget);
@@ -6886,8 +6786,8 @@ async function listFiles2(dir) {
6886
6786
  for (const name of entries) {
6887
6787
  if (out.length >= MAX_FILES_LISTED) return;
6888
6788
  if (name.startsWith(".")) continue;
6889
- const full = join15(current, name);
6890
- const info = await stat10(full).catch(() => void 0);
6789
+ const full = join14(current, name);
6790
+ const info = await stat9(full).catch(() => void 0);
6891
6791
  if (info?.isDirectory()) {
6892
6792
  if (depth < 3) await walk(full, depth + 1);
6893
6793
  } else if (info?.isFile()) {
@@ -6977,9 +6877,9 @@ No results.
6977
6877
 
6978
6878
  // src/undo/snapshots.ts
6979
6879
  import { createHash as createHash9 } from "crypto";
6980
- import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
6880
+ import { mkdir as mkdir5, writeFile as writeFile3 } from "fs/promises";
6981
6881
  import { homedir as homedir3 } from "os";
6982
- import { join as join16 } from "path";
6882
+ import { join as join15 } from "path";
6983
6883
  var SNAPSHOT_EXCLUDES = [
6984
6884
  ".git",
6985
6885
  ".garuda/sessions/",
@@ -7076,7 +6976,7 @@ var SnapshotStore = class {
7076
6976
  this.ready ??= (async () => {
7077
6977
  await mkdir5(this.dir, { recursive: true, mode: 448 });
7078
6978
  await this.git("init -q", signal, true);
7079
- await writeFile4(join16(this.dir, "info", "exclude"), `${SNAPSHOT_EXCLUDES.join("\n")}
6979
+ await writeFile3(join15(this.dir, "info", "exclude"), `${SNAPSHOT_EXCLUDES.join("\n")}
7080
6980
  `);
7081
6981
  })().catch((error) => {
7082
6982
  this.ready = void 0;
@@ -7130,7 +7030,7 @@ var SnapshotStore = class {
7130
7030
  };
7131
7031
  function storeDir(root, home = homedir3()) {
7132
7032
  const id = createHash9("sha256").update(root).digest("hex").slice(0, 16);
7133
- return join16(home, ".garuda", "snapshots", id);
7033
+ return join15(home, ".garuda", "snapshots", id);
7134
7034
  }
7135
7035
  function shellQuote(text) {
7136
7036
  return `'${text.replace(/'/g, "'\\''")}'`;
@@ -7141,7 +7041,7 @@ function tree(id) {
7141
7041
  }
7142
7042
 
7143
7043
  // src/app/mentions.ts
7144
- import { readdir as readdir8, readFile as readFile15, stat as stat11 } from "fs/promises";
7044
+ import { readdir as readdir8, readFile as readFile15, stat as stat10 } from "fs/promises";
7145
7045
  var MAX_ATTACHMENTS = 10;
7146
7046
  var MAX_TOTAL_CHARS = 15e4;
7147
7047
  var MAX_FOLDER_ENTRIES = 200;
@@ -7167,7 +7067,7 @@ async function attachMentions(prompt, root, files, denial = async () => void 0)
7167
7067
  }
7168
7068
  continue;
7169
7069
  }
7170
- const info = await stat11(absolute).catch(() => void 0);
7070
+ const info = await stat10(absolute).catch(() => void 0);
7171
7071
  if (info === void 0) continue;
7172
7072
  const shown = displayPath(root, absolute);
7173
7073
  if (attachments.length >= MAX_ATTACHMENTS) {
@@ -7370,7 +7270,7 @@ var ModelState = class {
7370
7270
  // src/app/network.ts
7371
7271
  import { createHash as createHash10 } from "crypto";
7372
7272
  import { existsSync as existsSync3 } from "fs";
7373
- import { basename as basename5, delimiter as delimiter2, join as join17 } from "path";
7273
+ import { basename as basename4, delimiter as delimiter2, join as join16 } from "path";
7374
7274
  function networkHash(entries) {
7375
7275
  const canonical = [...new Set(entries.map((e) => e.trim().toLowerCase()))].sort();
7376
7276
  return createHash10("sha256").update(JSON.stringify(canonical)).digest("hex");
@@ -7405,10 +7305,10 @@ function networkConsent(entries, isolation, changed) {
7405
7305
  };
7406
7306
  }
7407
7307
  function nodeBinary(execPath = process.execPath, path = process.env.PATH ?? "") {
7408
- if (/^node(\.exe)?$/.test(basename5(execPath))) return execPath;
7308
+ if (/^node(\.exe)?$/.test(basename4(execPath))) return execPath;
7409
7309
  for (const dir of path.split(delimiter2)) {
7410
7310
  if (dir === "") continue;
7411
- const candidate = join17(dir, "node");
7311
+ const candidate = join16(dir, "node");
7412
7312
  if (existsSync3(candidate)) return candidate;
7413
7313
  }
7414
7314
  return void 0;
@@ -8622,7 +8522,7 @@ ${neutralizeTags(output)}`
8622
8522
  text: "There is no finished plan in this chat. Make one in plan mode (/plan), then type /schedule."
8623
8523
  };
8624
8524
  }
8625
- const { createJob } = await import("./create-N4I7TIZE.js");
8525
+ const { createJob } = await import("./create-VXIH2GUZ.js");
8626
8526
  const created = await createJob({
8627
8527
  root: this.root,
8628
8528
  executor: this.executor,
@@ -8689,7 +8589,7 @@ ${result.stderr.text}`)
8689
8589
  */
8690
8590
  async cancelJob(id, agent = {}) {
8691
8591
  const { loadJob, saveJob } = await import("./job-3NYDMP2M.js");
8692
- const { defaultAgentEnv, nightSpec, removeAgent, removeSpec } = await import("./launchd-QVHQ3VNN.js");
8592
+ const { defaultAgentEnv, nightSpec, removeAgent, removeSpec } = await import("./launchd-SSX362VG.js");
8693
8593
  if (id === "night") {
8694
8594
  const removed = await removeSpec(
8695
8595
  agent.executor ?? this.executor,
@@ -8721,8 +8621,8 @@ ${result.stderr.text}`)
8721
8621
  */
8722
8622
  async deleteJob(id, signal, agent = {}) {
8723
8623
  const { loadJob } = await import("./job-3NYDMP2M.js");
8724
- const { defaultAgentEnv, removeAgent } = await import("./launchd-QVHQ3VNN.js");
8725
- const { jobLeftovers, removeJob } = await import("./remove-LE7Q7K46.js");
8624
+ const { defaultAgentEnv, removeAgent } = await import("./launchd-SSX362VG.js");
8625
+ const { jobLeftovers, removeJob } = await import("./remove-6GDSTAIO.js");
8726
8626
  let job;
8727
8627
  try {
8728
8628
  job = await loadJob(this.root, id);
@@ -8857,7 +8757,7 @@ ${result.stderr.text}`)
8857
8757
  if (known === hash2) {
8858
8758
  active = [...active, ...project];
8859
8759
  } else {
8860
- const file2 = join18(this.root, HOOKS_FILE);
8760
+ const file2 = join17(this.root, HOOKS_FILE);
8861
8761
  const request = hooksConsent(project, file2, this.executor.isolation, known !== void 0);
8862
8762
  const choice = await this.approver.ask(request, signal);
8863
8763
  if (choice !== "deny") active = [...active, ...project];
@@ -9049,7 +8949,7 @@ ${result.stderr.text}`)
9049
8949
  }
9050
8950
  /** Install a language server into ~/.garuda/lsp (the user asked for it). */
9051
8951
  async installLsp(language, signal) {
9052
- const { installServer } = await import("./install-VRPBZY5H.js");
8952
+ const { installServer } = await import("./install-EWDSPFFZ.js");
9053
8953
  const result = await installServer(language, {
9054
8954
  executor: this.executor,
9055
8955
  home: this.lspHome,
@@ -9060,7 +8960,7 @@ ${result.stderr.text}`)
9060
8960
  }
9061
8961
  /** autoInstall (~/.garuda/lsp.json): ask before a managed install. */
9062
8962
  async askInstall(language, signal) {
9063
- const { installCommand } = await import("./install-VRPBZY5H.js");
8963
+ const { installCommand } = await import("./install-EWDSPFFZ.js");
9064
8964
  const { LANGUAGE_LABELS } = await import("./manager-4PMSXT47.js");
9065
8965
  const { managedLabel, managedDir } = await import("./servers-6YDGWOZ6.js");
9066
8966
  const dir = managedDir(language, this.lspHome);
@@ -9093,7 +8993,7 @@ ${result.stderr.text}`)
9093
8993
  async startMcp(signal) {
9094
8994
  if (this.mcpServers.length === 0) return;
9095
8995
  this.mcpStarted ??= (async () => {
9096
- const { McpManager } = await import("./manager-CSI76AWF.js");
8996
+ const { McpManager } = await import("./manager-AWU4NHHK.js");
9097
8997
  const { AuthStore } = await import("./oauth-W6OK6XXO.js");
9098
8998
  const manager = new McpManager({
9099
8999
  root: this.root,
@@ -9320,7 +9220,6 @@ async function gatedProjectSettings(options) {
9320
9220
  }
9321
9221
 
9322
9222
  export {
9323
- keepSecretForRedaction,
9324
9223
  FileSessionStore,
9325
9224
  parseRecords,
9326
9225
  newSessionId,
@@ -9355,4 +9254,4 @@ export {
9355
9254
  modelFacts,
9356
9255
  Runtime
9357
9256
  };
9358
- //# sourceMappingURL=chunk-K7KK7U44.js.map
9257
+ //# sourceMappingURL=chunk-WIJL72ZE.js.map