@garuda-agent/garuda 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -1
- package/README.md +62 -5
- package/dist/acpCommand-FZ2P5JFO.js +153 -0
- package/dist/chunk-23FXBNBB.js +46 -0
- package/dist/{chunk-QOW5TK4L.js → chunk-2S62ZNTC.js} +6 -6
- package/dist/{chunk-ZGZ2ZADL.js → chunk-2TAXSFWN.js} +2 -2
- package/dist/chunk-4JSUUDFQ.js +118 -0
- package/dist/{chunk-KWRJREUH.js → chunk-B25VL4RU.js} +1 -42
- package/dist/chunk-EPKWDCV4.js +9 -0
- package/dist/{chunk-W7BPYQMW.js → chunk-HRGX53VC.js} +2 -2
- package/dist/{chunk-U4OQVT2T.js → chunk-INRZR772.js} +2 -2
- package/dist/{chunk-YIZWYUBG.js → chunk-K3SIUOAG.js} +2 -2
- package/dist/{chunk-ITITLNAR.js → chunk-K7KK7U44.js} +36 -19
- package/dist/chunk-NXJ4XLB5.js +19 -0
- package/dist/{chunk-YM6T4J5V.js → chunk-PQNT34LY.js} +8 -111
- package/dist/{chunk-35GMLLJW.js → chunk-S77XDSD4.js} +2 -2
- package/dist/{chunk-D5O5CIWK.js → chunk-SI2QJYCR.js} +3 -1
- package/dist/{chunk-V7WPGQLB.js → chunk-YFQJXRIJ.js} +4 -18
- package/dist/cli/index.js +43 -31
- package/dist/{create-Y5SXJUXO.js → create-N4I7TIZE.js} +5 -5
- package/dist/{evalCommand-5TG2CKZY.js → evalCommand-3SSFMZQD.js} +13 -10
- package/dist/{inkChat-3J26R24L.js → inkChat-34BTFG2K.js} +12 -9
- package/dist/{install-XWLU22OH.js → install-VRPBZY5H.js} +3 -3
- package/dist/{jobCommand-IYWZWTSI.js → jobCommand-XJ5GULS5.js} +7 -7
- package/dist/{launchd-2FL5UN2U.js → launchd-QVHQ3VNN.js} +4 -4
- package/dist/{lspCommand-TJEZBV2E.js → lspCommand-XNTBHXLA.js} +3 -3
- package/dist/{manager-EBTYO2GR.js → manager-CSI76AWF.js} +3 -3
- package/dist/{nightCommand-DUNWJASI.js → nightCommand-CR6ZHYGP.js} +7 -7
- package/dist/{remove-AENULZZE.js → remove-LE7Q7K46.js} +3 -3
- package/dist/{run-66Y6R2KU.js → run-ML6GSPN4.js} +5 -3
- package/dist/server-R3GNIC33.js +676 -0
- package/package.json +2 -1
- package/dist/chunk-6TWBYMY7.js +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.15.0 (2026-10-06)
|
|
4
|
+
|
|
5
|
+
Garuda in your editor. Version 0.15.0 is not the old "0.15" branch label of the status table (code
|
|
6
|
+
intelligence), which shipped in 0.14.0.
|
|
7
|
+
|
|
8
|
+
### Editors
|
|
9
|
+
|
|
10
|
+
- `garuda acp`: Garuda as an agent for editors over the Agent Client Protocol (v1): VS Code (with
|
|
11
|
+
the "ACP Client" extension), Zed, JetBrains, Neovim, Emacs. One runtime per editor session, with
|
|
12
|
+
the same permission engine, OS sandbox, team policy, hooks and audit log as the terminal.
|
|
13
|
+
- Approval questions name their tool call (`callId`), and file writes carry the whole change, so an
|
|
14
|
+
editor shows each question next to the right call, with its own diff view.
|
|
15
|
+
- A stop in the editor names what it ended: each stopped tool call shows as failed, with a line
|
|
16
|
+
such as "Garuda: $ sleep 60 cancelled." (or "the turn was cancelled." when no call ran). A call
|
|
17
|
+
that has not reported within 3 s of the stop ends as failed, so none stays "running".
|
|
18
|
+
- Docs: the website's Editors page (VS Code with ACP Client, Zed, other ACP editors). Tested live
|
|
19
|
+
in VS Code and Zed on macOS.
|
|
20
|
+
|
|
3
21
|
## 0.14.1 (2026-10)
|
|
4
22
|
|
|
5
23
|
The first version on npm (`@garuda-agent/garuda`) and Homebrew (`madhu-sv/garuda/garuda`). It fixes
|
|
@@ -10,7 +28,8 @@ of the other areas are closed. Each fix has a test that fails without it.
|
|
|
10
28
|
|
|
11
29
|
- npm: `npm install -g @garuda-agent/garuda`. Published from the release workflow with npm trusted
|
|
12
30
|
publishing, with provenance.
|
|
13
|
-
- Homebrew: `brew
|
|
31
|
+
- Homebrew: `brew tap madhu-sv/garuda`, `brew trust --formula madhu-sv/garuda/garuda`, then
|
|
32
|
+
`brew install garuda`.
|
|
14
33
|
|
|
15
34
|
### Security
|
|
16
35
|
|
package/README.md
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
Website and docs: https://madhu-sv.github.io/garuda/
|
|
6
6
|
|
|
7
|
-
Garuda is a terminal coding agent. This is version 0.
|
|
8
|
-
|
|
7
|
+
Garuda is a terminal coding agent. This is version 0.15.0: Garuda in your editor over the Agent Client
|
|
8
|
+
Protocol (`garuda acp`), on top of 0.14.1 (the 0.14–0.17 branches after the merge gate and Garuda's own
|
|
9
|
+
review; see the notes under the status table). Release notes: [CHANGELOG.md](CHANGELOG.md).
|
|
9
10
|
Design documents: [docs/](docs/README.md) (architecture, high-level design, low-level design per component).
|
|
10
11
|
The requirements doc defines the scope. Code, tests and commits refer to its IDs (F1–F26, N1–N8).
|
|
11
12
|
|
|
@@ -34,6 +35,10 @@ The requirements doc defines the scope. Code, tests and commits refer to its IDs
|
|
|
34
35
|
| 0.15: multi-language AST code intelligence (Python, Java, TS/JS, call graph, blast radius, /callers, /defs, /impact, ast_query) | Done (0.14.0) |
|
|
35
36
|
| 0.16: language plugins (Go and Rust built in, user plugins in ~/.garuda/languages, /languages; project plugins not loaded) | Done (0.14.0) |
|
|
36
37
|
| 0.17: Mixture-of-Experts subagents (opt-in), team policy and audit log (W5) | Done (0.14.0) |
|
|
38
|
+
| Editors over the Agent Client Protocol (`garuda acp`: VS Code with an extension, Zed, JetBrains, Neovim, Emacs) | Done (0.15.0) |
|
|
39
|
+
|
|
40
|
+
The rows labelled 0.14–0.17 are branch labels, not versions: the "0.15" branch (code intelligence)
|
|
41
|
+
shipped in 0.14.0. The editors row is version 0.15.0.
|
|
37
42
|
|
|
38
43
|
The 0.14–0.17 rows were built on stacked branches that were never released. They ship together as
|
|
39
44
|
0.14.0 after the merge gate: the high findings of the branch review are fixed (policy source, audit
|
|
@@ -45,7 +50,7 @@ headings below keep the branch labels (0.14–0.17).
|
|
|
45
50
|
Before 0.14.0, Garuda reviewed its own code with Fable 5.1, one area at a time (knowledge,
|
|
46
51
|
permissions, tools, sandbox, audit, loop, agents), in plan mode. 0.14.1 adds the cli and extensions
|
|
47
52
|
areas and fixes the open findings of all nine areas (see [CHANGELOG.md](CHANGELOG.md)). Known limits
|
|
48
|
-
in 0.
|
|
53
|
+
in 0.15.0:
|
|
49
54
|
|
|
50
55
|
- G09: project language plugins are not loaded (no consent flow for their imports yet).
|
|
51
56
|
- Subagents: each child has its own step and token budget (capped by the team policy); it does not
|
|
@@ -57,14 +62,25 @@ in 0.14.1:
|
|
|
57
62
|
`~/.m2/wrapper`) hold programs that a build runs later outside the sandbox. They stay writable, because
|
|
58
63
|
`./gradlew` needs them in the sandbox; a sandboxed command could change them.
|
|
59
64
|
- The jdtls download is checked against the `.sha256` file of the same server, not a pinned hash.
|
|
65
|
+
- Editors (`garuda acp`): Garuda's session history is not in the editor (no `session/load`), the
|
|
66
|
+
editor's MCP servers are not started, Garuda reads saved files (not unsaved buffers), the terminal's
|
|
67
|
+
own commands (`/undo`, `/diff` …) are not available, and an edit is approved as a whole (no hunks).
|
|
60
68
|
|
|
61
69
|
## Use
|
|
62
70
|
|
|
63
71
|
Install (0.14.1 and later) with Homebrew or npm. You need Node 22 or later; Homebrew installs it.
|
|
64
72
|
|
|
65
73
|
```sh
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
npm install -g @garuda-agent/garuda
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Or with Homebrew (macOS and Linux). Homebrew loads a formula from a third-party tap only after you
|
|
78
|
+
trust it, so trust the Garuda formula first:
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
brew tap madhu-sv/garuda
|
|
82
|
+
brew trust --formula madhu-sv/garuda/garuda
|
|
83
|
+
brew install garuda
|
|
68
84
|
```
|
|
69
85
|
|
|
70
86
|
Or build from source. You need Node 22 or later, pnpm 10 and git. Node 25 and later do not include
|
|
@@ -236,6 +252,47 @@ Set the context window, price and output limit per model, and add providers, in
|
|
|
236
252
|
|
|
237
253
|
Model text goes to stdout; tool activity and notes go to stderr. So `garuda -p "…" > answer.md` keeps only the answer.
|
|
238
254
|
|
|
255
|
+
## Editors (ACP, 0.15)
|
|
256
|
+
|
|
257
|
+
`garuda acp` runs Garuda as an agent for editors that speak the Agent Client Protocol. The editor
|
|
258
|
+
starts it, shows the conversation, the tool calls and the questions, and Garuda does the work with
|
|
259
|
+
the same permission engine, OS sandbox, team policy, hooks and audit log as in the terminal.
|
|
260
|
+
|
|
261
|
+
VS Code, with the extension "ACP Client" (`formulahendry.acp-client`), in the user settings
|
|
262
|
+
(Cmd+Shift+P, **Preferences: Open User Settings (JSON)**). Use the full path from `which garuda`:
|
|
263
|
+
VS Code started from the Dock does not get your shell's `PATH`.
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"acp.agents": {
|
|
268
|
+
"Garuda": {
|
|
269
|
+
"command": "/opt/homebrew/bin/garuda",
|
|
270
|
+
"args": ["acp"],
|
|
271
|
+
"env": { "GARUDA_MODEL": "claude-sonnet-5", "ANTHROPIC_API_KEY": "..." }
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Zed: the same command, argument and environment under `agent_servers` (with `"type": "custom"`).
|
|
278
|
+
The website's [Editors](https://madhu-sv.github.io/garuda/docs/editors/) page has the steps, a way
|
|
279
|
+
to keep the API key out of `settings.json`, and what the editor shows.
|
|
280
|
+
|
|
281
|
+
- Each edit asks in the editor, with the editor's diff view; "Allow for this session" lasts for this
|
|
282
|
+
session only. Keep an extension's auto-approve off: it answers Garuda's questions for you.
|
|
283
|
+
- The editor's stop button ends the turn: a running command stops, and a waiting question is a deny.
|
|
284
|
+
Each call that the stop ended shows as failed, with a line such as "Garuda: $ sleep 60 cancelled."
|
|
285
|
+
A command that exits with an error shows as done (the model reads the error); a refused call shows
|
|
286
|
+
as failed.
|
|
287
|
+
- Build and plan modes are in the editor's mode menu; custom commands and skills are in its `/` menu.
|
|
288
|
+
Built-in chat commands (`/undo`, `/diff` ...) are only in the terminal in this version.
|
|
289
|
+
- Garuda reads and writes files and runs commands itself; it does not use the editor's file or
|
|
290
|
+
terminal access, so it reads the saved file, not an unsaved buffer. It does not start MCP servers
|
|
291
|
+
that the editor sends (its own `~/.garuda/mcp.json` and the project's work as usual).
|
|
292
|
+
- Project settings that loosen safety apply only after a yes in a terminal (`garuda` in that folder).
|
|
293
|
+
|
|
294
|
+
Design: [docs/lld/acp.md](docs/lld/acp.md).
|
|
295
|
+
|
|
239
296
|
## Init: set up a folder
|
|
240
297
|
|
|
241
298
|
`garuda init` (or `/init` in the chat) sets up the current folder:
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
keepProviderKey,
|
|
4
|
+
loadModelsConfig,
|
|
5
|
+
resolveModel
|
|
6
|
+
} from "./chunk-YFQJXRIJ.js";
|
|
7
|
+
import {
|
|
8
|
+
FileSessionStore,
|
|
9
|
+
Runtime,
|
|
10
|
+
auditDirFor
|
|
11
|
+
} from "./chunk-K7KK7U44.js";
|
|
12
|
+
import "./chunk-A2QAIRQL.js";
|
|
13
|
+
import "./chunk-HRGX53VC.js";
|
|
14
|
+
import "./chunk-G2AX7MGS.js";
|
|
15
|
+
import {
|
|
16
|
+
loadSearchConfig
|
|
17
|
+
} from "./chunk-B25VL4RU.js";
|
|
18
|
+
import "./chunk-23FXBNBB.js";
|
|
19
|
+
import {
|
|
20
|
+
VERSION
|
|
21
|
+
} from "./chunk-EPKWDCV4.js";
|
|
22
|
+
import "./chunk-5DEWP3YX.js";
|
|
23
|
+
import "./chunk-ZAE25JM2.js";
|
|
24
|
+
import "./chunk-ATW7BNIG.js";
|
|
25
|
+
import "./chunk-PZS3V6P3.js";
|
|
26
|
+
import "./chunk-OUCV3FCT.js";
|
|
27
|
+
import "./chunk-SI2QJYCR.js";
|
|
28
|
+
import "./chunk-WMOLXTBU.js";
|
|
29
|
+
import "./chunk-HUIK3WXO.js";
|
|
30
|
+
import "./chunk-3NJNVZTK.js";
|
|
31
|
+
|
|
32
|
+
// src/cli/acpCommand.ts
|
|
33
|
+
import { homedir } from "os";
|
|
34
|
+
import { Readable } from "stream";
|
|
35
|
+
async function acpCommand(options) {
|
|
36
|
+
const output = protocolOutput(process.stdout, process.stderr);
|
|
37
|
+
const input = Readable.toWeb(process.stdin);
|
|
38
|
+
const setup = await prepare(options);
|
|
39
|
+
const { acpServer } = await import("./server-R3GNIC33.js");
|
|
40
|
+
const server = acpServer({
|
|
41
|
+
version: VERSION,
|
|
42
|
+
createRuntime: async ({ root, approver, onEvent, onNotice }) => {
|
|
43
|
+
if (typeof setup === "string") throw new Error(setup);
|
|
44
|
+
return createRuntime(setup, { root, approver, onEvent, onNotice });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
process.on("exit", () => server.shutdown());
|
|
48
|
+
const stop = () => {
|
|
49
|
+
server.shutdown();
|
|
50
|
+
process.exit(143);
|
|
51
|
+
};
|
|
52
|
+
process.once("SIGTERM", stop);
|
|
53
|
+
await server.serve(output, input);
|
|
54
|
+
await server.close();
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
function protocolOutput(stdout, stderr) {
|
|
58
|
+
const write = stdout.write.bind(stdout);
|
|
59
|
+
const toStderr = stderr.write.bind(stderr);
|
|
60
|
+
stdout.write = ((...args) => toStderr(...args));
|
|
61
|
+
return new WritableStream({
|
|
62
|
+
write: (chunk) => new Promise((resolve, reject) => {
|
|
63
|
+
write(chunk, (error) => error ? reject(error) : resolve());
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async function prepare(options) {
|
|
68
|
+
const spec = options.model ?? process.env.GARUDA_MODEL;
|
|
69
|
+
if (!spec) return "Set a model with --model <id> or the GARUDA_MODEL variable.";
|
|
70
|
+
const models = await loadModelsConfig();
|
|
71
|
+
if (models.problem !== void 0) return models.problem;
|
|
72
|
+
let resolved;
|
|
73
|
+
let sub;
|
|
74
|
+
try {
|
|
75
|
+
resolved = resolveModel(spec, models.config);
|
|
76
|
+
const subSpec = process.env.GARUDA_SUBAGENT_MODEL;
|
|
77
|
+
if (subSpec) sub = resolveModel(subSpec, models.config);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return error.message;
|
|
80
|
+
}
|
|
81
|
+
const search = await loadSearchConfig();
|
|
82
|
+
for (const name of [resolved.def.apiKeyEnv, sub?.def.apiKeyEnv, "ANTHROPIC_API_KEY"]) {
|
|
83
|
+
if (name !== void 0) keepProviderKey(name);
|
|
84
|
+
}
|
|
85
|
+
const { loadTeamPolicy } = await import("./policy-EJPLEEXP.js");
|
|
86
|
+
let team;
|
|
87
|
+
try {
|
|
88
|
+
team = await loadTeamPolicy();
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return `Team policy: ${error.message}`;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
resolved,
|
|
94
|
+
...sub === void 0 ? {} : { sub },
|
|
95
|
+
models: models.config,
|
|
96
|
+
...team === void 0 ? {} : { team: { policy: team.policy, sources: team.sources } },
|
|
97
|
+
search
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function createRuntime(setup, input) {
|
|
101
|
+
const { resolved, sub, models, team, search } = setup;
|
|
102
|
+
return Runtime.create({
|
|
103
|
+
root: input.root,
|
|
104
|
+
modelId: resolved.spec,
|
|
105
|
+
...team === void 0 ? {} : { policy: team.policy, policySources: team.sources },
|
|
106
|
+
audit: { dir: auditDirFor(input.root) },
|
|
107
|
+
model: () => resolved.create(),
|
|
108
|
+
modelInfo: resolved.info,
|
|
109
|
+
...resolved.maxTokens === void 0 ? {} : { maxTokens: resolved.maxTokens },
|
|
110
|
+
...sub === void 0 ? {} : { subagentModel: { spec: sub.spec, model: () => sub.create(), info: sub.info } },
|
|
111
|
+
approver: input.approver,
|
|
112
|
+
store: new FileSessionStore(input.root),
|
|
113
|
+
undo: {},
|
|
114
|
+
skills: {},
|
|
115
|
+
languages: {},
|
|
116
|
+
// The editor cannot answer a question before session/new returns: only project settings that
|
|
117
|
+
// the user approved in a terminal apply; the rest is left out with a notice (docs/lld/acp.md).
|
|
118
|
+
projectSettings: { home: homedir(), ask: false },
|
|
119
|
+
...search.config === void 0 && search.claude === void 0 ? {} : {
|
|
120
|
+
search: {
|
|
121
|
+
...search.config === void 0 ? {} : { config: search.config },
|
|
122
|
+
...search.claude === void 0 ? {} : { claude: search.claude },
|
|
123
|
+
...search.use === void 0 ? {} : { use: search.use },
|
|
124
|
+
home: homedir()
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
agents: {
|
|
128
|
+
resolveModel: (spec) => {
|
|
129
|
+
const r = resolveModel(spec, models);
|
|
130
|
+
return { spec: r.spec, model: () => r.create(), info: r.info };
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
models: {
|
|
134
|
+
resolve: (spec) => {
|
|
135
|
+
const r = resolveModel(spec, models);
|
|
136
|
+
return {
|
|
137
|
+
spec: r.spec,
|
|
138
|
+
model: () => r.create(),
|
|
139
|
+
info: r.info,
|
|
140
|
+
...r.maxTokens === void 0 ? {} : { maxTokens: r.maxTokens }
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
configured: Object.keys(models.models)
|
|
144
|
+
},
|
|
145
|
+
...input.onEvent === void 0 ? {} : { onEvent: input.onEvent },
|
|
146
|
+
onNotice: input.onNotice
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
export {
|
|
150
|
+
acpCommand,
|
|
151
|
+
protocolOutput
|
|
152
|
+
};
|
|
153
|
+
//# sourceMappingURL=acpCommand-FZ2P5JFO.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/commands/builtins.ts
|
|
4
|
+
var BUILTIN_COMMANDS = [
|
|
5
|
+
"help",
|
|
6
|
+
"usage",
|
|
7
|
+
"session",
|
|
8
|
+
"sessions",
|
|
9
|
+
"models",
|
|
10
|
+
"export",
|
|
11
|
+
"compact",
|
|
12
|
+
"diff",
|
|
13
|
+
"schedule",
|
|
14
|
+
"jobs",
|
|
15
|
+
"where",
|
|
16
|
+
"defs",
|
|
17
|
+
"refs",
|
|
18
|
+
"callers",
|
|
19
|
+
"impact",
|
|
20
|
+
"map",
|
|
21
|
+
"mcp",
|
|
22
|
+
"hooks",
|
|
23
|
+
"lsp",
|
|
24
|
+
"languages",
|
|
25
|
+
"experts",
|
|
26
|
+
"audit",
|
|
27
|
+
"commands",
|
|
28
|
+
"agents",
|
|
29
|
+
"plan",
|
|
30
|
+
"build",
|
|
31
|
+
"new",
|
|
32
|
+
"init",
|
|
33
|
+
"editor",
|
|
34
|
+
"details",
|
|
35
|
+
"thinking",
|
|
36
|
+
"search",
|
|
37
|
+
"undo",
|
|
38
|
+
"redo",
|
|
39
|
+
"exit",
|
|
40
|
+
"quit"
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
BUILTIN_COMMANDS
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=chunk-23FXBNBB.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
gateProjectSettings,
|
|
8
8
|
totalTokens
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-HRGX53VC.js";
|
|
10
10
|
import {
|
|
11
11
|
TrustStore
|
|
12
12
|
} from "./chunk-5DEWP3YX.js";
|
|
@@ -15,11 +15,11 @@ import {
|
|
|
15
15
|
commitJob,
|
|
16
16
|
jobChanges,
|
|
17
17
|
prepareWorktree
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-K3SIUOAG.js";
|
|
19
19
|
import {
|
|
20
20
|
defaultAgentEnv,
|
|
21
21
|
removeAgent
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-S77XDSD4.js";
|
|
23
23
|
import {
|
|
24
24
|
jobReport
|
|
25
25
|
} from "./chunk-YQTGMCU6.js";
|
|
@@ -36,11 +36,11 @@ import {
|
|
|
36
36
|
JobGitError,
|
|
37
37
|
git,
|
|
38
38
|
hostCommand
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-2TAXSFWN.js";
|
|
40
40
|
import {
|
|
41
41
|
createExecutor,
|
|
42
42
|
loadSettings
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-SI2QJYCR.js";
|
|
44
44
|
import {
|
|
45
45
|
JOBS_DIR,
|
|
46
46
|
loadJob,
|
|
@@ -317,4 +317,4 @@ export {
|
|
|
317
317
|
msUntil,
|
|
318
318
|
finishJob
|
|
319
319
|
};
|
|
320
|
-
//# sourceMappingURL=chunk-
|
|
320
|
+
//# sourceMappingURL=chunk-2S62ZNTC.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DEFAULT_ENV_ALLOWLIST
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SI2QJYCR.js";
|
|
5
5
|
|
|
6
6
|
// src/jobs/git.ts
|
|
7
7
|
var GIT_TIMEOUT_MS = 12e4;
|
|
@@ -46,4 +46,4 @@ export {
|
|
|
46
46
|
git,
|
|
47
47
|
hostCommand
|
|
48
48
|
};
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
49
|
+
//# sourceMappingURL=chunk-2TAXSFWN.js.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/approver.ts
|
|
4
|
+
import { styleText } from "util";
|
|
5
|
+
var TerminalApprover = class {
|
|
6
|
+
/** Set by the CLI: it aborts the current turn. */
|
|
7
|
+
onInterrupt = () => {
|
|
8
|
+
};
|
|
9
|
+
/** One question at a time (0.14.1, review): two prompts at once mixed their keys. */
|
|
10
|
+
ask(request, signal) {
|
|
11
|
+
const next = this.asking === 0 ? this.askNow(request, signal) : this.queue.then(() => this.askNow(request, signal));
|
|
12
|
+
this.asking++;
|
|
13
|
+
this.queue = next.catch(() => {
|
|
14
|
+
}).finally(() => {
|
|
15
|
+
this.asking--;
|
|
16
|
+
});
|
|
17
|
+
return next;
|
|
18
|
+
}
|
|
19
|
+
asking = 0;
|
|
20
|
+
queue = Promise.resolve();
|
|
21
|
+
async askNow(request, signal) {
|
|
22
|
+
signal.throwIfAborted();
|
|
23
|
+
const out = process.stderr;
|
|
24
|
+
out.write(`
|
|
25
|
+
${header(request)}
|
|
26
|
+
${colorPreview(request)}
|
|
27
|
+
`);
|
|
28
|
+
if (!process.stdin.isTTY) {
|
|
29
|
+
out.write("No terminal to ask for approval, so Garuda denies this call.\n");
|
|
30
|
+
return "deny";
|
|
31
|
+
}
|
|
32
|
+
const sessionLabel = request.labels?.session ?? (request.target.kind === "command" ? "Yes, and allow this exact command for this session" : request.target.kind === "url" ? `Yes, and allow ${request.target.host} for this session` : `Yes, and allow all ${request.tool} calls for this session`);
|
|
33
|
+
const { select } = await import("@inquirer/prompts");
|
|
34
|
+
try {
|
|
35
|
+
return await select(
|
|
36
|
+
{
|
|
37
|
+
message: request.question ?? "Allow?",
|
|
38
|
+
choices: [
|
|
39
|
+
{ name: request.labels?.once ?? "Yes, once", value: "once" },
|
|
40
|
+
{ name: sessionLabel, value: "session" },
|
|
41
|
+
{ name: request.labels?.deny ?? "No, deny", value: "deny" }
|
|
42
|
+
].filter((c) => request.choices?.includes(c.value) ?? true)
|
|
43
|
+
},
|
|
44
|
+
{ signal, output: out }
|
|
45
|
+
);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (error.name === "ExitPromptError") this.onInterrupt();
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var SwitchApprover = class {
|
|
53
|
+
constructor(current) {
|
|
54
|
+
this.current = current;
|
|
55
|
+
}
|
|
56
|
+
current;
|
|
57
|
+
/** Called before each question: the chat's notifier (0.6). */
|
|
58
|
+
onAsk = () => {
|
|
59
|
+
};
|
|
60
|
+
ask(request, signal) {
|
|
61
|
+
this.onAsk(request);
|
|
62
|
+
return this.current.ask(request, signal);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
function visible(text) {
|
|
66
|
+
return text.replace(/[\u0000-\u0008\u000b-\u001f]/g, (c) => String.fromCodePoint(9216 + c.charCodeAt(0))).replace(/\u007f/g, "\u2421").replace(
|
|
67
|
+
/[\u0080-\u009f\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u2069\ufeff\u{e0000}-\u{e007f}]/gu,
|
|
68
|
+
(c) => `[U+${(c.codePointAt(0) ?? 0).toString(16).toUpperCase().padStart(4, "0")}]`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
function hasHidden(text) {
|
|
72
|
+
return visible(text) !== text;
|
|
73
|
+
}
|
|
74
|
+
var HIDDEN_WARNING = "! This holds hidden or control characters, shown as \u240D, \u241B or [U+\u2026]. Read it with care.";
|
|
75
|
+
function headerText(request) {
|
|
76
|
+
const { tool, target, isolation } = request;
|
|
77
|
+
if (request.title !== void 0) return visible(request.title);
|
|
78
|
+
if (target.kind === "command") {
|
|
79
|
+
const where = isolation === "none" ? "on your machine, no sandbox" : target.outsideSandbox ? "OUTSIDE the sandbox: network on, writes anywhere" : `sandbox: ${isolation}`;
|
|
80
|
+
return `${tool} wants to run a command (${where}):`;
|
|
81
|
+
}
|
|
82
|
+
if (target.kind === "input") return `${tool} wants to run with this input:`;
|
|
83
|
+
if (target.kind === "url") return `${tool} wants to fetch from ${visible(target.host)}:`;
|
|
84
|
+
return `${tool} wants to change ${visible(target.path)}:`;
|
|
85
|
+
}
|
|
86
|
+
function header(request) {
|
|
87
|
+
return styleText("bold", headerText(request));
|
|
88
|
+
}
|
|
89
|
+
function colorPreview({ target, preview }) {
|
|
90
|
+
const warning = hasHidden(preview) ? `
|
|
91
|
+
${styleText("yellow", ` ${HIDDEN_WARNING}`)}` : "";
|
|
92
|
+
if (target.kind === "command") return `${styleText("cyan", ` $ ${visible(preview)}`)}${warning}`;
|
|
93
|
+
if (target.kind === "url") return `${visible(preview)}${warning}`;
|
|
94
|
+
return `${colorDiff(visible(preview))}${warning}`;
|
|
95
|
+
}
|
|
96
|
+
function colorDiff(text) {
|
|
97
|
+
return text.split("\n").map((line) => {
|
|
98
|
+
if (line.startsWith("+++") || line.startsWith("---") || line.startsWith("diff --git"))
|
|
99
|
+
return styleText("bold", line);
|
|
100
|
+
if (line.startsWith("+")) return styleText("green", line);
|
|
101
|
+
if (line.startsWith("-")) return styleText("red", line);
|
|
102
|
+
if (line.startsWith("@@")) return styleText("cyan", line);
|
|
103
|
+
return line;
|
|
104
|
+
}).join("\n");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
TerminalApprover,
|
|
109
|
+
SwitchApprover,
|
|
110
|
+
visible,
|
|
111
|
+
hasHidden,
|
|
112
|
+
HIDDEN_WARNING,
|
|
113
|
+
headerText,
|
|
114
|
+
header,
|
|
115
|
+
colorPreview,
|
|
116
|
+
colorDiff
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=chunk-4JSUUDFQ.js.map
|
|
@@ -3,46 +3,6 @@ import {
|
|
|
3
3
|
isLoopbackHost
|
|
4
4
|
} from "./chunk-ATW7BNIG.js";
|
|
5
5
|
|
|
6
|
-
// src/commands/builtins.ts
|
|
7
|
-
var BUILTIN_COMMANDS = [
|
|
8
|
-
"help",
|
|
9
|
-
"usage",
|
|
10
|
-
"session",
|
|
11
|
-
"sessions",
|
|
12
|
-
"models",
|
|
13
|
-
"export",
|
|
14
|
-
"compact",
|
|
15
|
-
"diff",
|
|
16
|
-
"schedule",
|
|
17
|
-
"jobs",
|
|
18
|
-
"where",
|
|
19
|
-
"defs",
|
|
20
|
-
"refs",
|
|
21
|
-
"callers",
|
|
22
|
-
"impact",
|
|
23
|
-
"map",
|
|
24
|
-
"mcp",
|
|
25
|
-
"hooks",
|
|
26
|
-
"lsp",
|
|
27
|
-
"languages",
|
|
28
|
-
"experts",
|
|
29
|
-
"audit",
|
|
30
|
-
"commands",
|
|
31
|
-
"agents",
|
|
32
|
-
"plan",
|
|
33
|
-
"build",
|
|
34
|
-
"new",
|
|
35
|
-
"init",
|
|
36
|
-
"editor",
|
|
37
|
-
"details",
|
|
38
|
-
"thinking",
|
|
39
|
-
"search",
|
|
40
|
-
"undo",
|
|
41
|
-
"redo",
|
|
42
|
-
"exit",
|
|
43
|
-
"quit"
|
|
44
|
-
];
|
|
45
|
-
|
|
46
6
|
// src/web/search.ts
|
|
47
7
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
48
8
|
import { homedir } from "os";
|
|
@@ -273,11 +233,10 @@ async function readCapped(response, max) {
|
|
|
273
233
|
}
|
|
274
234
|
|
|
275
235
|
export {
|
|
276
|
-
BUILTIN_COMMANDS,
|
|
277
236
|
MAX_RESULTS,
|
|
278
237
|
providerLabel,
|
|
279
238
|
loadSearchConfig,
|
|
280
239
|
saveSearchUse,
|
|
281
240
|
search
|
|
282
241
|
};
|
|
283
|
-
//# sourceMappingURL=chunk-
|
|
242
|
+
//# sourceMappingURL=chunk-B25VL4RU.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-PZS3V6P3.js";
|
|
5
5
|
import {
|
|
6
6
|
EFFORTS
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SI2QJYCR.js";
|
|
8
8
|
import {
|
|
9
9
|
formatRule
|
|
10
10
|
} from "./chunk-3NJNVZTK.js";
|
|
@@ -170,4 +170,4 @@ export {
|
|
|
170
170
|
contextSize,
|
|
171
171
|
gateProjectSettings
|
|
172
172
|
};
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
173
|
+
//# sourceMappingURL=chunk-HRGX53VC.js.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-EU7PA45O.js";
|
|
7
7
|
import {
|
|
8
8
|
DEFAULT_ENV_ALLOWLIST
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-SI2QJYCR.js";
|
|
10
10
|
|
|
11
11
|
// src/lsp/install.ts
|
|
12
12
|
import { mkdir } from "fs/promises";
|
|
@@ -70,4 +70,4 @@ export {
|
|
|
70
70
|
installCommand,
|
|
71
71
|
installServer
|
|
72
72
|
};
|
|
73
|
-
//# sourceMappingURL=chunk-
|
|
73
|
+
//# sourceMappingURL=chunk-INRZR772.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
JobGitError,
|
|
4
4
|
git
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2TAXSFWN.js";
|
|
6
6
|
|
|
7
7
|
// src/jobs/worktree.ts
|
|
8
8
|
import { createHash } from "crypto";
|
|
@@ -135,4 +135,4 @@ export {
|
|
|
135
135
|
commitJob,
|
|
136
136
|
jobChanges
|
|
137
137
|
};
|
|
138
|
-
//# sourceMappingURL=chunk-
|
|
138
|
+
//# sourceMappingURL=chunk-K3SIUOAG.js.map
|