@garuda-agent/garuda 0.0.1 → 0.14.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 +58 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +1040 -0
- package/SECURITY.md +32 -0
- package/dist/anthropic-NQDBCHJU.js +327 -0
- package/dist/chunk-35GMLLJW.js +157 -0
- package/dist/chunk-36GQIVGT.js +526 -0
- package/dist/chunk-3CEPHS4C.js +231 -0
- package/dist/chunk-3NJNVZTK.js +123 -0
- package/dist/chunk-42DSA4EA.js +116 -0
- package/dist/chunk-4P26OKTP.js +100 -0
- package/dist/chunk-5DEWP3YX.js +139 -0
- package/dist/chunk-6TWBYMY7.js +9 -0
- package/dist/chunk-A2QAIRQL.js +45 -0
- package/dist/chunk-ATW7BNIG.js +31 -0
- package/dist/chunk-D5O5CIWK.js +1339 -0
- package/dist/chunk-EU7PA45O.js +324 -0
- package/dist/chunk-FARS4R67.js +206 -0
- package/dist/chunk-G2AX7MGS.js +36 -0
- package/dist/chunk-HUIK3WXO.js +234 -0
- package/dist/chunk-ITITLNAR.js +9341 -0
- package/dist/chunk-KKB5W47S.js +231 -0
- package/dist/chunk-KWRJREUH.js +283 -0
- package/dist/chunk-N4I6YS3E.js +73 -0
- package/dist/chunk-OUCV3FCT.js +205 -0
- package/dist/chunk-PZS3V6P3.js +46 -0
- package/dist/chunk-QOW5TK4L.js +320 -0
- package/dist/chunk-U4OQVT2T.js +73 -0
- package/dist/chunk-V7WPGQLB.js +207 -0
- package/dist/chunk-W7BPYQMW.js +173 -0
- package/dist/chunk-WMOLXTBU.js +61 -0
- package/dist/chunk-YIZWYUBG.js +138 -0
- package/dist/chunk-YM6T4J5V.js +1350 -0
- package/dist/chunk-YQTGMCU6.js +111 -0
- package/dist/chunk-ZAE25JM2.js +158 -0
- package/dist/chunk-ZGZ2ZADL.js +49 -0
- package/dist/cli/index.js +1191 -0
- package/dist/create-Y5SXJUXO.js +223 -0
- package/dist/deadline-F5RJJ2QW.js +86 -0
- package/dist/detect-LARDSLLZ.js +10 -0
- package/dist/evalCommand-5TG2CKZY.js +2795 -0
- package/dist/export-HN3CT7AV.js +158 -0
- package/dist/inkChat-3J26R24L.js +1190 -0
- package/dist/install-XWLU22OH.js +17 -0
- package/dist/job-3NYDMP2M.js +31 -0
- package/dist/jobCommand-IYWZWTSI.js +30 -0
- package/dist/launchd-2FL5UN2U.js +40 -0
- package/dist/lspCommand-TJEZBV2E.js +99 -0
- package/dist/manager-4PMSXT47.js +14 -0
- package/dist/manager-EBTYO2GR.js +847 -0
- package/dist/nightCommand-DUNWJASI.js +247 -0
- package/dist/oauth-W6OK6XXO.js +23 -0
- package/dist/openaiCompatible-CJWVJP5M.js +501 -0
- package/dist/policy-EJPLEEXP.js +31 -0
- package/dist/proxy-XJAHCZB2.js +192 -0
- package/dist/remove-AENULZZE.js +59 -0
- package/dist/run-66Y6R2KU.js +886 -0
- package/dist/servers-6YDGWOZ6.js +24 -0
- package/dist/text-J2GD647J.js +11 -0
- package/package.json +83 -3
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lsp/servers.ts
|
|
4
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, realpathSync as realpathSync2, statSync } from "fs";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { delimiter as delimiter2, dirname as dirname2, extname, isAbsolute as isAbsolute2, join as join2, sep } from "path";
|
|
7
|
+
|
|
8
|
+
// src/lsp/jdtls.ts
|
|
9
|
+
import { createHash } from "crypto";
|
|
10
|
+
import { existsSync, readdirSync, readFileSync, realpathSync } from "fs";
|
|
11
|
+
import { delimiter, dirname, isAbsolute, join } from "path";
|
|
12
|
+
var JDTLS_VERSION = "1.61.0";
|
|
13
|
+
var JDTLS_BASE_URL = `https://download.eclipse.org/jdtls/milestones/${JDTLS_VERSION}`;
|
|
14
|
+
var JDTLS_MIN_JAVA = 21;
|
|
15
|
+
var JDTLS_READY = {
|
|
16
|
+
method: "language/status",
|
|
17
|
+
test: (params) => {
|
|
18
|
+
const type = params?.type;
|
|
19
|
+
return type === "Started" || type === "Error";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var JDTLS_INIT_OPTIONS = {
|
|
23
|
+
settings: {
|
|
24
|
+
java: {
|
|
25
|
+
import: {
|
|
26
|
+
generatesMetadataFilesAtProjectRoot: false,
|
|
27
|
+
maven: { offline: { enabled: true } },
|
|
28
|
+
gradle: { offline: { enabled: true } }
|
|
29
|
+
},
|
|
30
|
+
autobuild: { enabled: true }
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
function releaseMajor(text) {
|
|
35
|
+
const match = /^JAVA_VERSION="([^"]+)"/m.exec(text);
|
|
36
|
+
if (match?.[1] === void 0) return void 0;
|
|
37
|
+
const parts = match[1].split(".").map((p) => Number.parseInt(p, 10));
|
|
38
|
+
const major = parts[0] === 1 ? parts[1] : parts[0];
|
|
39
|
+
return major !== void 0 && Number.isFinite(major) ? major : void 0;
|
|
40
|
+
}
|
|
41
|
+
function runtimeAt(home) {
|
|
42
|
+
const java = join(home, "bin", "java");
|
|
43
|
+
const release = join(home, "release");
|
|
44
|
+
if (!existsSync(java) || !existsSync(release)) return void 0;
|
|
45
|
+
const major = releaseMajor(readFileSync(release, "utf8"));
|
|
46
|
+
return major === void 0 ? void 0 : { java, major };
|
|
47
|
+
}
|
|
48
|
+
var JDK_FOLDERS = [
|
|
49
|
+
"/Library/Java/JavaVirtualMachines",
|
|
50
|
+
"/opt/homebrew/opt",
|
|
51
|
+
"/usr/local/opt",
|
|
52
|
+
"/usr/lib/jvm"
|
|
53
|
+
];
|
|
54
|
+
function findJava(search = {}) {
|
|
55
|
+
const env = search.env ?? process.env;
|
|
56
|
+
const homes = [];
|
|
57
|
+
if (env.JAVA_HOME) homes.push(env.JAVA_HOME);
|
|
58
|
+
homes.push(...search.hints ?? []);
|
|
59
|
+
for (const dir of (env.PATH ?? "").split(delimiter)) {
|
|
60
|
+
if (!isAbsolute(dir)) continue;
|
|
61
|
+
const java = join(dir, "java");
|
|
62
|
+
if (!existsSync(java)) continue;
|
|
63
|
+
try {
|
|
64
|
+
homes.push(dirname(dirname(realpathSync(java))));
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const folder of search.jdkFolders ?? JDK_FOLDERS) {
|
|
69
|
+
let names = [];
|
|
70
|
+
try {
|
|
71
|
+
names = readdirSync(folder).sort().reverse();
|
|
72
|
+
} catch {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
for (const name of names) {
|
|
76
|
+
homes.push(
|
|
77
|
+
join(folder, name),
|
|
78
|
+
join(folder, name, "Contents", "Home"),
|
|
79
|
+
join(folder, name, "libexec", "openjdk.jdk", "Contents", "Home")
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const home of homes) {
|
|
84
|
+
const runtime = runtimeAt(home);
|
|
85
|
+
if (runtime !== void 0 && runtime.major >= JDTLS_MIN_JAVA) return runtime;
|
|
86
|
+
}
|
|
87
|
+
return void 0;
|
|
88
|
+
}
|
|
89
|
+
function jdtlsHome(script) {
|
|
90
|
+
let real = script;
|
|
91
|
+
try {
|
|
92
|
+
real = realpathSync(script);
|
|
93
|
+
} catch {
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
let text = "";
|
|
97
|
+
try {
|
|
98
|
+
text = readFileSync(real, "utf8").slice(0, 2e4);
|
|
99
|
+
} catch {
|
|
100
|
+
}
|
|
101
|
+
const quoted = [...text.matchAll(/["'](\/[^"'\s]+)["']/g)].map((m) => m[1]);
|
|
102
|
+
const hints = [...text.matchAll(/JAVA_HOME[=:]\s*["']?(\/[^"'\s]+)/g)].map((m) => m[1]);
|
|
103
|
+
const up = dirname(dirname(real));
|
|
104
|
+
const candidates = [
|
|
105
|
+
up,
|
|
106
|
+
join(up, "libexec"),
|
|
107
|
+
...quoted.flatMap((p) => [p, dirname(p), dirname(dirname(p))])
|
|
108
|
+
];
|
|
109
|
+
for (const dir of candidates) {
|
|
110
|
+
if (existsSync(join(dir, "plugins")) && launcherJar(dir) !== void 0) {
|
|
111
|
+
return { home: dir, hints };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
function launcherJar(home) {
|
|
117
|
+
try {
|
|
118
|
+
const jar = readdirSync(join(home, "plugins")).find(
|
|
119
|
+
(n) => n.startsWith("org.eclipse.equinox.launcher_") && n.endsWith(".jar")
|
|
120
|
+
);
|
|
121
|
+
return jar === void 0 ? void 0 : join(home, "plugins", jar);
|
|
122
|
+
} catch {
|
|
123
|
+
return void 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function configDir(home, platform = process.platform, arch = process.arch) {
|
|
127
|
+
const os = platform === "darwin" ? "mac" : platform === "win32" ? "win" : "linux";
|
|
128
|
+
const names = arch === "arm64" ? [`config_${os}_arm`, `config_${os}`] : [`config_${os}`];
|
|
129
|
+
return names.map((n) => join(home, n)).find((p) => existsSync(p));
|
|
130
|
+
}
|
|
131
|
+
function jdtlsLaunch(script, context) {
|
|
132
|
+
const install = jdtlsHome(script);
|
|
133
|
+
if (install === void 0) return { problem: `no jdtls install folder (plugins/) for ${script}` };
|
|
134
|
+
const jar = launcherJar(install.home);
|
|
135
|
+
const config = configDir(install.home, context.platform, context.arch);
|
|
136
|
+
if (config === void 0) return { problem: `no config_* folder in ${install.home}` };
|
|
137
|
+
const java = findJava({
|
|
138
|
+
...context.env === void 0 ? {} : { env: context.env },
|
|
139
|
+
hints: install.hints,
|
|
140
|
+
...context.jdkFolders === void 0 ? {} : { jdkFolders: context.jdkFolders }
|
|
141
|
+
});
|
|
142
|
+
if (java === void 0) {
|
|
143
|
+
return { problem: `jdtls needs Java ${JDTLS_MIN_JAVA} or later; set JAVA_HOME to such a JDK` };
|
|
144
|
+
}
|
|
145
|
+
const cache = join(context.home, ".cache", "garuda", "jdtls");
|
|
146
|
+
const id = (text) => createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
147
|
+
return {
|
|
148
|
+
argv: [
|
|
149
|
+
java.java,
|
|
150
|
+
"-Declipse.application=org.eclipse.jdt.ls.core.id1",
|
|
151
|
+
"-Dosgi.bundles.defaultStartLevel=4",
|
|
152
|
+
"-Declipse.product=org.eclipse.jdt.ls.core.product",
|
|
153
|
+
// The install is read-only in the sandbox: its configuration is shared, ours is in the cache.
|
|
154
|
+
`-Dosgi.sharedConfiguration.area=${config}`,
|
|
155
|
+
"-Dosgi.sharedConfiguration.area.readOnly=true",
|
|
156
|
+
"-Dosgi.checkConfiguration=true",
|
|
157
|
+
"-Dosgi.configuration.cascaded=true",
|
|
158
|
+
"-Dlog.level=WARNING",
|
|
159
|
+
"-Xmx1G",
|
|
160
|
+
"--add-modules=ALL-SYSTEM",
|
|
161
|
+
"--add-opens",
|
|
162
|
+
"java.base/java.util=ALL-UNNAMED",
|
|
163
|
+
"--add-opens",
|
|
164
|
+
"java.base/java.lang=ALL-UNNAMED",
|
|
165
|
+
"-jar",
|
|
166
|
+
jar,
|
|
167
|
+
"-configuration",
|
|
168
|
+
join(cache, `config-${id(install.home)}`),
|
|
169
|
+
"-data",
|
|
170
|
+
join(cache, "workspace", id(context.root))
|
|
171
|
+
]
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function jdtlsInstallCommand(dir, quote) {
|
|
175
|
+
const d = quote(dir);
|
|
176
|
+
return [
|
|
177
|
+
`cd ${d}`,
|
|
178
|
+
`B=${JDTLS_BASE_URL}`,
|
|
179
|
+
`f=$(curl -fsSL "$B/latest.txt" 2>/dev/null || curl -fsSL "$B/" | grep -o 'jdt-language-server-[0-9.]*-[0-9]*\\.tar\\.gz' | head -1)`,
|
|
180
|
+
`test -n "$f" || { echo "No jdtls ${JDTLS_VERSION} file at $B" >&2; exit 1; }`,
|
|
181
|
+
`curl -fsSL -o jdtls.tar.gz "$B/$f"`,
|
|
182
|
+
`want=$(curl -fsSL "$B/$f.sha256") || { echo "No checksum file for $f, so Garuda does not install it" >&2; rm -f jdtls.tar.gz; exit 1; }`,
|
|
183
|
+
`got=$( (sha256sum jdtls.tar.gz 2>/dev/null || shasum -a 256 jdtls.tar.gz) | cut -d' ' -f1)`,
|
|
184
|
+
`test -n "$got" && test "$(echo "$want" | cut -d' ' -f1)" = "$got" || { echo "Checksum mismatch for $f" >&2; rm -f jdtls.tar.gz; exit 1; }`,
|
|
185
|
+
"rm -rf jdtls && mkdir jdtls && tar -xzf jdtls.tar.gz -C jdtls && rm jdtls.tar.gz"
|
|
186
|
+
].join(" && ");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/lsp/servers.ts
|
|
190
|
+
var LSP_LANGUAGES = ["typescript", "python", "java"];
|
|
191
|
+
var EXTENSIONS = {
|
|
192
|
+
".ts": { language: "typescript", id: "typescript" },
|
|
193
|
+
".mts": { language: "typescript", id: "typescript" },
|
|
194
|
+
".cts": { language: "typescript", id: "typescript" },
|
|
195
|
+
".tsx": { language: "typescript", id: "typescriptreact" },
|
|
196
|
+
".js": { language: "typescript", id: "javascript" },
|
|
197
|
+
".mjs": { language: "typescript", id: "javascript" },
|
|
198
|
+
".cjs": { language: "typescript", id: "javascript" },
|
|
199
|
+
".jsx": { language: "typescript", id: "javascriptreact" },
|
|
200
|
+
".py": { language: "python", id: "python" },
|
|
201
|
+
".pyi": { language: "python", id: "python" },
|
|
202
|
+
".java": { language: "java", id: "java" }
|
|
203
|
+
};
|
|
204
|
+
function languageOf(path) {
|
|
205
|
+
return EXTENSIONS[extname(path).toLowerCase()];
|
|
206
|
+
}
|
|
207
|
+
var SERVERS = {
|
|
208
|
+
typescript: [
|
|
209
|
+
// TypeScript 7 (native) has a built-in language server.
|
|
210
|
+
{ name: "tsc", bin: "tsc", args: ["--lsp", "--stdio"], accept: isTypeScript7 },
|
|
211
|
+
{ name: "tsgo", bin: "tsgo", args: ["--lsp", "--stdio"] },
|
|
212
|
+
{ name: "typescript-language-server", bin: "typescript-language-server", args: ["--stdio"] }
|
|
213
|
+
],
|
|
214
|
+
python: [
|
|
215
|
+
{ name: "basedpyright", bin: "basedpyright-langserver", args: ["--stdio"] },
|
|
216
|
+
{ name: "pyright", bin: "pyright-langserver", args: ["--stdio"] }
|
|
217
|
+
],
|
|
218
|
+
java: [
|
|
219
|
+
{
|
|
220
|
+
name: "jdtls",
|
|
221
|
+
bin: "jdtls",
|
|
222
|
+
args: [],
|
|
223
|
+
managed: join2("jdtls", "bin", "jdtls"),
|
|
224
|
+
launch: jdtlsLaunch,
|
|
225
|
+
initializationOptions: JDTLS_INIT_OPTIONS,
|
|
226
|
+
ready: JDTLS_READY,
|
|
227
|
+
// The first import of a Maven or Gradle project takes a while.
|
|
228
|
+
firstTimeoutMs: 12e4
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
};
|
|
232
|
+
var MANAGED = {
|
|
233
|
+
typescript: { kind: "npm", packages: ["typescript@7.0.2"] },
|
|
234
|
+
python: { kind: "npm", packages: ["pyright@1.1.414"] },
|
|
235
|
+
java: { kind: "eclipse" }
|
|
236
|
+
};
|
|
237
|
+
function managedLabel(language) {
|
|
238
|
+
const m = MANAGED[language];
|
|
239
|
+
return m.kind === "npm" ? m.packages.join(", ") : `jdtls ${JDTLS_VERSION} (from download.eclipse.org)`;
|
|
240
|
+
}
|
|
241
|
+
function managedDir(language, home = homedir()) {
|
|
242
|
+
return join2(home, ".garuda", "lsp", language);
|
|
243
|
+
}
|
|
244
|
+
function discoverServer(language, options) {
|
|
245
|
+
return findServer(language, options).server;
|
|
246
|
+
}
|
|
247
|
+
function findServer(language, options) {
|
|
248
|
+
const home = options.home ?? homedir();
|
|
249
|
+
const managed = managedDir(language, home);
|
|
250
|
+
const dirs = (options.path ?? process.env.PATH ?? "").split(delimiter2).filter((dir) => isAbsolute2(dir) && !inside(options.root, dir));
|
|
251
|
+
const problems = [];
|
|
252
|
+
const context = {
|
|
253
|
+
root: options.root,
|
|
254
|
+
home,
|
|
255
|
+
...options.env === void 0 ? {} : { env: options.env },
|
|
256
|
+
...options.jdkFolders === void 0 ? {} : { jdkFolders: options.jdkFolders }
|
|
257
|
+
};
|
|
258
|
+
for (const source of ["managed", "path"]) {
|
|
259
|
+
for (const spec of SERVERS[language]) {
|
|
260
|
+
const paths = source === "managed" ? [join2(managed, spec.managed ?? join2("node_modules", ".bin", spec.bin))] : dirs.map((dir) => join2(dir, spec.bin));
|
|
261
|
+
for (const path of paths) {
|
|
262
|
+
if (!isProgram(path)) continue;
|
|
263
|
+
if (spec.accept !== void 0 && !spec.accept(path)) continue;
|
|
264
|
+
const launch = spec.launch?.(path, context) ?? { argv: [path, ...spec.args] };
|
|
265
|
+
if ("problem" in launch) {
|
|
266
|
+
problems.push(launch.problem);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
return { server: { spec, path, source, argv: launch.argv }, problems };
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return { problems };
|
|
274
|
+
}
|
|
275
|
+
function inside(root, dir) {
|
|
276
|
+
let real = dir;
|
|
277
|
+
try {
|
|
278
|
+
real = realpathSync2(dir);
|
|
279
|
+
} catch {
|
|
280
|
+
}
|
|
281
|
+
return real === root || real.startsWith(`${root}${sep}`);
|
|
282
|
+
}
|
|
283
|
+
function isProgram(path) {
|
|
284
|
+
try {
|
|
285
|
+
const stat = statSync(path);
|
|
286
|
+
return stat.isFile() && (stat.mode & 73) !== 0;
|
|
287
|
+
} catch {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function isTypeScript7(path) {
|
|
292
|
+
let dir;
|
|
293
|
+
try {
|
|
294
|
+
dir = dirname2(realpathSync2(path));
|
|
295
|
+
} catch {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
const candidates = [join2(dir, "..", "typescript", "package.json")];
|
|
299
|
+
for (let i = 0; i < 4; i++, dir = dirname2(dir)) candidates.push(join2(dir, "package.json"));
|
|
300
|
+
for (const file of candidates) {
|
|
301
|
+
if (!existsSync2(file)) continue;
|
|
302
|
+
try {
|
|
303
|
+
const pkg = JSON.parse(readFileSync2(file, "utf8"));
|
|
304
|
+
if (pkg.name === "typescript") return Number.parseInt(pkg.version ?? "0", 10) >= 7;
|
|
305
|
+
} catch {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export {
|
|
313
|
+
jdtlsInstallCommand,
|
|
314
|
+
LSP_LANGUAGES,
|
|
315
|
+
languageOf,
|
|
316
|
+
SERVERS,
|
|
317
|
+
MANAGED,
|
|
318
|
+
managedLabel,
|
|
319
|
+
managedDir,
|
|
320
|
+
discoverServer,
|
|
321
|
+
findServer,
|
|
322
|
+
isTypeScript7
|
|
323
|
+
};
|
|
324
|
+
//# sourceMappingURL=chunk-EU7PA45O.js.map
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
serverCallText,
|
|
4
|
+
serverResultSummary
|
|
5
|
+
} from "./chunk-A2QAIRQL.js";
|
|
6
|
+
|
|
7
|
+
// src/cli/renderer.ts
|
|
8
|
+
import { styleText } from "util";
|
|
9
|
+
var PlainRenderer = class {
|
|
10
|
+
out;
|
|
11
|
+
err;
|
|
12
|
+
color;
|
|
13
|
+
/** True when the last text did not end with a new line. */
|
|
14
|
+
openLine = false;
|
|
15
|
+
/** /details (0.9): show the result line of each tool call. */
|
|
16
|
+
details = true;
|
|
17
|
+
/** Thinking text is streaming (0.9). */
|
|
18
|
+
thinking = false;
|
|
19
|
+
endThinking() {
|
|
20
|
+
if (!this.thinking) return;
|
|
21
|
+
this.thinking = false;
|
|
22
|
+
this.err.write("\n");
|
|
23
|
+
}
|
|
24
|
+
constructor(streams = { out: process.stdout, err: process.stderr }, color = process.stderr.isTTY === true && !process.env.NO_COLOR) {
|
|
25
|
+
this.out = streams.out;
|
|
26
|
+
this.err = streams.err;
|
|
27
|
+
this.color = color;
|
|
28
|
+
}
|
|
29
|
+
event(event) {
|
|
30
|
+
switch (event.type) {
|
|
31
|
+
case "thinking_delta":
|
|
32
|
+
if (!this.thinking) this.line(this.paint("dim", "\u273B thinking"));
|
|
33
|
+
this.thinking = true;
|
|
34
|
+
this.err.write(this.paint("dim", event.text));
|
|
35
|
+
return;
|
|
36
|
+
case "text_delta":
|
|
37
|
+
this.endThinking();
|
|
38
|
+
this.out.write(event.text);
|
|
39
|
+
this.openLine = !event.text.endsWith("\n");
|
|
40
|
+
return;
|
|
41
|
+
case "tool_call":
|
|
42
|
+
this.endThinking();
|
|
43
|
+
this.line(
|
|
44
|
+
`${this.paint("cyan", "\u25CF")} ${this.paint("bold", event.call.name)} ${summariseCall(event.call)}`
|
|
45
|
+
);
|
|
46
|
+
return;
|
|
47
|
+
case "tool_result": {
|
|
48
|
+
const text = summariseResult(event.call, event.outcome);
|
|
49
|
+
if (this.details || event.outcome.isError) {
|
|
50
|
+
this.line(
|
|
51
|
+
` ${this.paint("dim", "\u23BF")} ${event.outcome.isError ? this.paint("red", text) : this.paint("dim", text)}`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
for (const line of todoLines(event.call, event.outcome)) this.line(` ${line}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
case "compaction": {
|
|
58
|
+
const { stage, beforeTokens, afterTokens } = event.result;
|
|
59
|
+
this.info(`Context compacted (${stage}): ${beforeTokens} \u2192 about ${afterTokens} tokens.`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
case "model_retry":
|
|
63
|
+
this.warn(retryText(event));
|
|
64
|
+
return;
|
|
65
|
+
case "notice":
|
|
66
|
+
this.info(event.text);
|
|
67
|
+
return;
|
|
68
|
+
case "server_tool": {
|
|
69
|
+
const { call, result } = serverToolText(event);
|
|
70
|
+
const failed = event.result?.error !== void 0;
|
|
71
|
+
this.line(`${this.paint("cyan", "\u25CF")} ${this.paint("bold", call)}`);
|
|
72
|
+
if (this.details || failed) {
|
|
73
|
+
this.line(` ${this.paint("dim", "\u23BF")} ${this.paint(failed ? "red" : "dim", result)}`);
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
case "step_end":
|
|
78
|
+
this.endThinking();
|
|
79
|
+
return;
|
|
80
|
+
// Live status lines need a live view; plain output stays one line per call.
|
|
81
|
+
case "tool_progress":
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
info(text) {
|
|
86
|
+
this.line(this.paint("dim", text));
|
|
87
|
+
}
|
|
88
|
+
warn(text) {
|
|
89
|
+
this.line(this.paint("yellow", text));
|
|
90
|
+
}
|
|
91
|
+
error(text) {
|
|
92
|
+
this.line(this.paint("red", text));
|
|
93
|
+
}
|
|
94
|
+
/** A line on stderr. It starts on a new line if model text is still open. */
|
|
95
|
+
line(text) {
|
|
96
|
+
if (this.openLine) {
|
|
97
|
+
this.out.write("\n");
|
|
98
|
+
this.openLine = false;
|
|
99
|
+
}
|
|
100
|
+
this.err.write(`${text}
|
|
101
|
+
`);
|
|
102
|
+
}
|
|
103
|
+
paint(style, text) {
|
|
104
|
+
return this.color ? styleText(style, text) : text;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
function todoLines(call, outcome) {
|
|
108
|
+
if (call.name !== "todo_write" || outcome.isError) return [];
|
|
109
|
+
const marks = { "[x]": "\u2714", "[>]": "\u25B6", "[ ]": "\u25CB" };
|
|
110
|
+
return outcome.content.split("\n").map((line) => /^(\[[x> ]\]) (.*)$/.exec(line)).filter((m) => m !== null).map((m) => `${marks[m[1] ?? ""] ?? "\u25CB"} ${m[2] ?? ""}`);
|
|
111
|
+
}
|
|
112
|
+
function serverToolText(event) {
|
|
113
|
+
return {
|
|
114
|
+
call: `${event.call.name} (Claude) ${cut(serverCallText(event.call), 100)}`,
|
|
115
|
+
result: serverResultSummary(event.result)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function serverToolOutput(event) {
|
|
119
|
+
const result = event.result;
|
|
120
|
+
if (result === void 0 || result.results.length === 0) return serverResultSummary(result);
|
|
121
|
+
return result.results.map((r, i) => `${i + 1}. ${r.title}
|
|
122
|
+
${r.url}${r.age === void 0 ? "" : ` (${r.age})`}`).join("\n");
|
|
123
|
+
}
|
|
124
|
+
function retryText(event) {
|
|
125
|
+
return `The connection to the model broke (${event.reason}). Retrying (${event.attempt}/${event.maxRetries})\u2026`;
|
|
126
|
+
}
|
|
127
|
+
var cut = (text, max) => text.length <= max ? text : `${text.slice(0, max - 1)}\u2026`;
|
|
128
|
+
function summariseCall(call) {
|
|
129
|
+
const input = call.input ?? {};
|
|
130
|
+
const str = (key) => typeof input[key] === "string" ? input[key] : "";
|
|
131
|
+
switch (call.name) {
|
|
132
|
+
case "read_file":
|
|
133
|
+
case "write_file":
|
|
134
|
+
case "edit_file":
|
|
135
|
+
return str("path");
|
|
136
|
+
case "glob":
|
|
137
|
+
return str("pattern");
|
|
138
|
+
case "grep":
|
|
139
|
+
return `/${str("pattern")}/${str("path") ? ` in ${str("path")}` : ""}`;
|
|
140
|
+
case "bash":
|
|
141
|
+
return cut(str("command").split("\n")[0] ?? "", 100);
|
|
142
|
+
case "explore":
|
|
143
|
+
return cut(str("question").split("\n")[0] ?? "", 100);
|
|
144
|
+
case "todo_write": {
|
|
145
|
+
const todos = Array.isArray(input.todos) ? input.todos : [];
|
|
146
|
+
return `${todos.length} step(s)`;
|
|
147
|
+
}
|
|
148
|
+
default:
|
|
149
|
+
return cut(JSON.stringify(call.input), 100);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function summariseResult(call, outcome) {
|
|
153
|
+
const all = outcome.content.split("\n");
|
|
154
|
+
const first = ((all[0]?.startsWith("<mcp_result ") ? all[1] : all[0]) ?? "").trim();
|
|
155
|
+
if (outcome.isError) return cut(first.replace(/^Error: /, ""), 160);
|
|
156
|
+
const lines = outcome.content === "" ? 0 : outcome.content.split("\n").length;
|
|
157
|
+
switch (call.name) {
|
|
158
|
+
case "read_file":
|
|
159
|
+
return `${lines} line(s)`;
|
|
160
|
+
case "glob":
|
|
161
|
+
case "grep":
|
|
162
|
+
return first.startsWith("No ") ? first : `${lines} result line(s)`;
|
|
163
|
+
case "bash":
|
|
164
|
+
return first;
|
|
165
|
+
case "todo_write":
|
|
166
|
+
return /\((\d+ of \d+ done)\)/.exec(first)?.[1] ?? first;
|
|
167
|
+
case "web_search": {
|
|
168
|
+
const count = outcome.content.split("\n").filter((l) => /^\d+\. /.test(l)).length;
|
|
169
|
+
return count === 0 ? "no results" : `${count} result${count === 1 ? "" : "s"}`;
|
|
170
|
+
}
|
|
171
|
+
case "web_fetch": {
|
|
172
|
+
const title = / title="([^"]*)"/.exec(first)?.[1];
|
|
173
|
+
const range = /^\[characters (\d+)–(\d+) of (\d+)\]$/m.exec(outcome.content);
|
|
174
|
+
const size = range === null ? `${lines} line(s)` : range[1] === "0" && range[2] === range[3] ? `${Number(range[3]).toLocaleString("en")} characters` : `characters ${range[1]}\u2013${range[2]} of ${Number(range[3]).toLocaleString("en")}`;
|
|
175
|
+
return title === void 0 ? size : `${cut(title, 80)} \xB7 ${size}`;
|
|
176
|
+
}
|
|
177
|
+
case "skill": {
|
|
178
|
+
const file = / path="([^"]*)"/.exec(first)?.[1];
|
|
179
|
+
const name = / name="([^"]*)"/.exec(first)?.[1] ?? / skill="([^"]*)"/.exec(first)?.[1];
|
|
180
|
+
return file === void 0 ? `loaded ${name ?? "the skill"}` : `read ${file}`;
|
|
181
|
+
}
|
|
182
|
+
case "agent": {
|
|
183
|
+
const trailer = /^\[agent (.*)\]$/m.exec(outcome.content)?.[1];
|
|
184
|
+
const answerLines = outcome.content.split("\n[agent ")[0]?.trim().split("\n").length ?? 0;
|
|
185
|
+
return `answer (${answerLines} line(s))${trailer === void 0 ? "" : ` \xB7 ${trailer}`}`;
|
|
186
|
+
}
|
|
187
|
+
case "explore": {
|
|
188
|
+
const trailer = /^\[explore: (.*)\]$/m.exec(outcome.content)?.[1];
|
|
189
|
+
const answerLines = outcome.content.split("\n[explore: ")[0]?.trim().split("\n").length ?? 0;
|
|
190
|
+
return `answer (${answerLines} line(s))${trailer === void 0 ? "" : ` \xB7 ${trailer}`}`;
|
|
191
|
+
}
|
|
192
|
+
default:
|
|
193
|
+
return cut(first, 160);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export {
|
|
198
|
+
PlainRenderer,
|
|
199
|
+
todoLines,
|
|
200
|
+
serverToolText,
|
|
201
|
+
serverToolOutput,
|
|
202
|
+
retryText,
|
|
203
|
+
summariseCall,
|
|
204
|
+
summariseResult
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=chunk-FARS4R67.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lsp/config.ts
|
|
4
|
+
import { readFile } from "fs/promises";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
var LSP_CONFIG_FILE = join(".garuda", "lsp.json");
|
|
9
|
+
var schema = z.strictObject({ autoInstall: z.boolean().optional() });
|
|
10
|
+
async function loadLspConfig(home = homedir()) {
|
|
11
|
+
const file = join(home, LSP_CONFIG_FILE);
|
|
12
|
+
let text;
|
|
13
|
+
try {
|
|
14
|
+
text = await readFile(file, "utf8");
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (error.code === "ENOENT") return { autoInstall: false };
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
let json;
|
|
20
|
+
try {
|
|
21
|
+
json = JSON.parse(text);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
throw new Error(`${file} is not valid JSON: ${error.message}`);
|
|
24
|
+
}
|
|
25
|
+
const parsed = schema.safeParse(json);
|
|
26
|
+
if (!parsed.success) {
|
|
27
|
+
throw new Error(`${file}: ${parsed.error.issues.map((i) => i.message).join("; ")}`);
|
|
28
|
+
}
|
|
29
|
+
return { autoInstall: parsed.data.autoInstall === true };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
LSP_CONFIG_FILE,
|
|
34
|
+
loadLspConfig
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=chunk-G2AX7MGS.js.map
|