@garuda-agent/garuda 0.15.0 → 0.16.1
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/CHANGELOG.md +35 -0
- package/README.md +30 -17
- package/dist/{acpCommand-FZ2P5JFO.js → acpCommand-OTAYW7BS.js} +64 -26
- package/dist/chunk-3EQU2GUX.js +27 -0
- package/dist/{chunk-K3SIUOAG.js → chunk-44QN5SWZ.js} +2 -2
- package/dist/{chunk-INRZR772.js → chunk-B6FA4I7Q.js} +2 -2
- package/dist/{chunk-PQNT34LY.js → chunk-BQTUOO4G.js} +4 -4
- package/dist/chunk-EIXUSVFX.js +116 -0
- package/dist/{chunk-SI2QJYCR.js → chunk-GXZACJUI.js} +6 -25
- package/dist/{chunk-2S62ZNTC.js → chunk-HE2K657U.js} +9 -7
- package/dist/chunk-NP6RIC25.js +331 -0
- package/dist/chunk-R7I2NBPX.js +71 -0
- package/dist/{chunk-K7KK7U44.js → chunk-TILFPYWO.js} +125 -226
- package/dist/{chunk-2TAXSFWN.js → chunk-TUUEBHG2.js} +2 -2
- package/dist/{chunk-HRGX53VC.js → chunk-ULAJPMY7.js} +1 -67
- package/dist/{chunk-S77XDSD4.js → chunk-USCUXCAU.js} +2 -2
- package/dist/chunk-VBZCNMUD.js +9 -0
- package/dist/cli/index.js +50 -33
- package/dist/{create-N4I7TIZE.js → create-VXIH2GUZ.js} +6 -5
- package/dist/{evalCommand-3SSFMZQD.js → evalCommand-RGMZRYDR.js} +31 -17
- package/dist/{inkChat-34BTFG2K.js → inkChat-WEDGQMCY.js} +10 -7
- package/dist/{install-VRPBZY5H.js → install-EWDSPFFZ.js} +4 -3
- package/dist/{jobCommand-XJ5GULS5.js → jobCommand-ACSGSBQ4.js} +9 -7
- package/dist/{launchd-QVHQ3VNN.js → launchd-SSX362VG.js} +5 -4
- package/dist/{lspCommand-XNTBHXLA.js → lspCommand-JRXKRSL7.js} +4 -3
- package/dist/{manager-CSI76AWF.js → manager-773PUDFE.js} +4 -3
- package/dist/{nightCommand-CR6ZHYGP.js → nightCommand-65MUEV32.js} +9 -7
- package/dist/{remove-LE7Q7K46.js → remove-6GDSTAIO.js} +4 -3
- package/dist/{server-R3GNIC33.js → server-NGKVIQEV.js} +28 -6
- package/dist/setupCommand-VA7D5MZK.js +303 -0
- package/package.json +1 -1
- package/dist/chunk-EPKWDCV4.js +0 -9
- 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-
|
|
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-
|
|
38
|
+
} from "./chunk-VBZCNMUD.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-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2312
|
-
const real = await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2650
|
-
import { join as
|
|
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 =
|
|
2552
|
+
const file2 = join4(root, name);
|
|
2653
2553
|
let real;
|
|
2654
2554
|
try {
|
|
2655
|
-
real = await
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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:
|
|
3569
|
-
{ dir:
|
|
3570
|
-
{ dir:
|
|
3571
|
-
{ dir:
|
|
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 =
|
|
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
|
|
4172
|
-
import { join as
|
|
4173
|
-
var COMMANDS_DIR =
|
|
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(
|
|
4180
|
-
const project =
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
4219
|
+
const file2 = join7(root, "node_modules", ".bin", name);
|
|
4320
4220
|
return isFile(file2) ? file2 : void 0;
|
|
4321
4221
|
};
|
|
4322
|
-
const venv = (name) => [
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
4310
|
+
if (files.some((f) => isFile(join7(root, f)))) return true;
|
|
4411
4311
|
try {
|
|
4412
|
-
const pkg = JSON.parse(readText(
|
|
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 =
|
|
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
|
|
4344
|
+
import { join as join8 } from "path";
|
|
4445
4345
|
import { z as z17 } from "zod";
|
|
4446
|
-
var HOOKS_FILE =
|
|
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(
|
|
4493
|
-
const project = home === root ? { hooks: [], problems: [] } : await readHooks(
|
|
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
|
|
4507
|
-
import { rm as rm2, writeFile
|
|
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
|
|
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 =
|
|
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
|
|
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 :
|
|
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
|
|
4663
|
-
import { dirname as
|
|
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
|
|
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
|
|
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 :
|
|
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 &&
|
|
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 =
|
|
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 =
|
|
5846
|
-
const id =
|
|
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 =
|
|
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 =
|
|
5869
|
-
const id =
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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 =
|
|
6283
|
+
const path = join12(this.root, GRAPH_FILE);
|
|
6384
6284
|
try {
|
|
6385
|
-
await mkdir4(
|
|
6386
|
-
await
|
|
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
|
|
6624
|
-
import { join as
|
|
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:
|
|
6633
|
-
{ dir:
|
|
6634
|
-
{ dir:
|
|
6635
|
-
{ dir:
|
|
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 =
|
|
6575
|
+
const dir = join13(place.dir, entry);
|
|
6676
6576
|
const shown = `${place.shown}/${entry}`;
|
|
6677
|
-
const file2 =
|
|
6577
|
+
const file2 = join13(dir, SKILL_FILE);
|
|
6678
6578
|
try {
|
|
6679
|
-
if (!(await
|
|
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
|
|
6778
|
-
import { join as
|
|
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([
|
|
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
|
|
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 =
|
|
6890
|
-
const info = await
|
|
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
|
|
6880
|
+
import { mkdir as mkdir5, writeFile as writeFile3 } from "fs/promises";
|
|
6981
6881
|
import { homedir as homedir3 } from "os";
|
|
6982
|
-
import { join as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
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-
|
|
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-
|
|
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-
|
|
8725
|
-
const { jobLeftovers, removeJob } = await import("./remove-
|
|
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 =
|
|
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-
|
|
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-
|
|
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-
|
|
8996
|
+
const { McpManager } = await import("./manager-773PUDFE.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-
|
|
9257
|
+
//# sourceMappingURL=chunk-TILFPYWO.js.map
|