@element47/ag 4.4.5 → 4.5.2
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/README.md +106 -4
- package/dist/cli/repl.d.ts +7 -2
- package/dist/cli/repl.d.ts.map +1 -1
- package/dist/cli/repl.js +390 -95
- package/dist/cli/repl.js.map +1 -1
- package/dist/cli.js +18 -8
- package/dist/cli.js.map +1 -1
- package/dist/core/__tests__/agent.test.js +42 -1
- package/dist/core/__tests__/agent.test.js.map +1 -1
- package/dist/core/__tests__/context.test.js +37 -0
- package/dist/core/__tests__/context.test.js.map +1 -1
- package/dist/core/__tests__/guardrails.test.d.ts +2 -0
- package/dist/core/__tests__/guardrails.test.d.ts.map +1 -0
- package/dist/core/__tests__/guardrails.test.js +400 -0
- package/dist/core/__tests__/guardrails.test.js.map +1 -0
- package/dist/core/__tests__/permission-manager.test.d.ts +2 -0
- package/dist/core/__tests__/permission-manager.test.d.ts.map +1 -0
- package/dist/core/__tests__/permission-manager.test.js +246 -0
- package/dist/core/__tests__/permission-manager.test.js.map +1 -0
- package/dist/core/__tests__/streaming.test.js +8 -1
- package/dist/core/__tests__/streaming.test.js.map +1 -1
- package/dist/core/agent.d.ts +20 -2
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +259 -82
- package/dist/core/agent.js.map +1 -1
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +17 -2
- package/dist/core/context.js.map +1 -1
- package/dist/core/guardrails.d.ts +32 -0
- package/dist/core/guardrails.d.ts.map +1 -0
- package/dist/core/guardrails.js +149 -0
- package/dist/core/guardrails.js.map +1 -0
- package/dist/core/loader.d.ts +6 -2
- package/dist/core/loader.d.ts.map +1 -1
- package/dist/core/loader.js +23 -9
- package/dist/core/loader.js.map +1 -1
- package/dist/core/permissions.d.ts +60 -0
- package/dist/core/permissions.d.ts.map +1 -0
- package/dist/core/permissions.js +252 -0
- package/dist/core/permissions.js.map +1 -0
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +16 -0
- package/dist/core/registry.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +26 -3
- package/dist/core/skills.js.map +1 -1
- package/dist/core/types.d.ts +20 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/memory/__tests__/memory.test.js +33 -3
- package/dist/memory/__tests__/memory.test.js.map +1 -1
- package/dist/memory/memory.d.ts.map +1 -1
- package/dist/memory/memory.js +25 -3
- package/dist/memory/memory.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -127,6 +127,46 @@ export default {
|
|
|
127
127
|
|
|
128
128
|
That's it. No config, no registry. Use `/tools` in the REPL to see what's loaded.
|
|
129
129
|
|
|
130
|
+
### Permission Keys
|
|
131
|
+
|
|
132
|
+
By default, custom tools require approval for every call (or you allow all calls with `toolname(*)`). To enable fine-grained permission patterns, add a `permissionKey` to your tool:
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
// .ag/tools/deploy.mjs
|
|
136
|
+
export default {
|
|
137
|
+
type: "function",
|
|
138
|
+
function: {
|
|
139
|
+
name: "deploy",
|
|
140
|
+
description: "Deploy to an environment",
|
|
141
|
+
parameters: {
|
|
142
|
+
type: "object",
|
|
143
|
+
properties: {
|
|
144
|
+
target: { type: "string", enum: ["staging", "production"] },
|
|
145
|
+
branch: { type: "string" }
|
|
146
|
+
},
|
|
147
|
+
required: ["target"]
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
permissionKey: { qualifier: "target" },
|
|
151
|
+
execute: async ({ target, branch }) => { /* ... */ }
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Now permission patterns can target specific argument values:
|
|
156
|
+
|
|
157
|
+
| Pattern | Effect |
|
|
158
|
+
|---------|--------|
|
|
159
|
+
| `deploy(staging)` | Allow staging deploys |
|
|
160
|
+
| `deploy(production)` | Allow production deploys |
|
|
161
|
+
| `deploy(*)` | Allow all deploys |
|
|
162
|
+
|
|
163
|
+
**`permissionKey` fields:**
|
|
164
|
+
|
|
165
|
+
- `qualifier` (required) — arg name whose value becomes the pattern qualifier. E.g., `{ qualifier: "target" }` + `target: "staging"` produces `deploy(staging)`.
|
|
166
|
+
- `value` (optional) — arg name whose value is matched by the glob portion. E.g., `{ qualifier: "action", value: "path" }` produces `mytool(read:configs/**)`.
|
|
167
|
+
|
|
168
|
+
Without `permissionKey`, the only available pattern is `toolname(*)`.
|
|
169
|
+
|
|
130
170
|
## Skills
|
|
131
171
|
|
|
132
172
|
Skills are reusable prompt instructions (with optional tools) that the agent activates on-demand. Browse and install from [skills.sh](https://skills.sh):
|
|
@@ -234,22 +274,84 @@ Or set it permanently:
|
|
|
234
274
|
|
|
235
275
|
## Permissions
|
|
236
276
|
|
|
237
|
-
In REPL mode, ag prompts before executing mutating operations:
|
|
277
|
+
In REPL mode, ag prompts before executing mutating operations. You can allow once, remember for the session, or save to the project:
|
|
238
278
|
|
|
239
279
|
```
|
|
240
|
-
? bash: npm test (y/n)
|
|
280
|
+
? bash: npm test (y)es / (a)lways / (p)roject / (n)o a
|
|
281
|
+
+ Session rule: bash(npm:*)
|
|
241
282
|
✓ [bash] All tests passed
|
|
242
|
-
? file(write): src/utils.ts (y/n)
|
|
283
|
+
? file(write): src/utils.ts (y)es / (a)lways / (p)roject / (n)o p
|
|
284
|
+
+ Saved to .ag/permissions.json: file(write:src/**)
|
|
243
285
|
✓ [file] Wrote src/utils.ts (24 lines, 680B)
|
|
244
286
|
```
|
|
245
287
|
|
|
288
|
+
**Prompt options:**
|
|
289
|
+
- **y** — allow this one time
|
|
290
|
+
- **a** — allow and remember the pattern for this session
|
|
291
|
+
- **p** — allow and save the pattern to project (`.ag/permissions.json`)
|
|
292
|
+
- **n** — deny this one time
|
|
293
|
+
|
|
294
|
+
### Pattern Syntax
|
|
295
|
+
|
|
296
|
+
Patterns use `Tool(qualifier:glob)` format:
|
|
297
|
+
|
|
298
|
+
| Pattern | Matches |
|
|
299
|
+
|---------|---------|
|
|
300
|
+
| `bash(npm:*)` | Any bash command starting with `npm` |
|
|
301
|
+
| `bash(git:*)` | Any bash command starting with `git` |
|
|
302
|
+
| `file(write:src/**)` | File writes anywhere under `src/` |
|
|
303
|
+
| `file(edit:*)` | All file edits |
|
|
304
|
+
| `git(commit)` | Git commit |
|
|
305
|
+
| `web(fetch:*github.com*)` | Fetch from GitHub domains |
|
|
306
|
+
| `bash(*)` | All bash commands |
|
|
307
|
+
| `*` | Everything |
|
|
308
|
+
|
|
309
|
+
### Rule Scopes
|
|
310
|
+
|
|
311
|
+
| Scope | Storage | Lifetime |
|
|
312
|
+
|-------|---------|----------|
|
|
313
|
+
| Session | In-memory | Until REPL exits |
|
|
314
|
+
| Project | `.ag/permissions.json` | Persists across sessions |
|
|
315
|
+
| Global | `~/.ag/permissions.json` | Persists everywhere |
|
|
316
|
+
|
|
317
|
+
Deny rules always override allow rules. Use `/permissions` to manage rules interactively.
|
|
318
|
+
|
|
319
|
+
### Built-in Classifications
|
|
320
|
+
|
|
246
321
|
**Always allowed (no prompt):** `file(read)`, `file(list)`, `grep(*)`, `memory(*)`, `plan(*)`, `skill(*)`, `git(status)`, `web(search)`
|
|
247
322
|
|
|
248
323
|
**Prompted:** `bash`, `file(write)`, `file(edit)`, `git(commit/push/branch)`, `web(fetch)`
|
|
249
324
|
|
|
250
325
|
**Always blocked:** `rm -rf /`, fork bombs, `sudo rm`, pipe-to-shell (enforced in code regardless of approval)
|
|
251
326
|
|
|
252
|
-
Skip prompts with `ag -y` or `--yes`. One-shot mode (`ag "query"`) auto-approves.
|
|
327
|
+
Skip all prompts with `ag -y` or `--yes`. One-shot mode (`ag "query"`) auto-approves.
|
|
328
|
+
|
|
329
|
+
## Guardrails
|
|
330
|
+
|
|
331
|
+
All externally-loaded tools and skills are scanned at load time for prompt injection and other security issues. This applies to:
|
|
332
|
+
|
|
333
|
+
- Custom tools (`.mjs` files in `~/.ag/tools/` and `.ag/tools/`)
|
|
334
|
+
- Skills (`SKILL.md` files in `~/.ag/skills/` and `.ag/skills/`)
|
|
335
|
+
- Skills installed from the registry via `/skill add`
|
|
336
|
+
|
|
337
|
+
**What gets checked:**
|
|
338
|
+
|
|
339
|
+
| Category | Severity | Examples |
|
|
340
|
+
|----------|----------|---------|
|
|
341
|
+
| Direct injection | Block | "ignore previous instructions", "system override", "reveal prompt" |
|
|
342
|
+
| Encoded payloads | Block | Base64-encoded injection attempts, HTML entity obfuscation |
|
|
343
|
+
| Hidden content | Block | HTML comments with instructions, zero-width characters, control chars |
|
|
344
|
+
| Exfiltration | Block/Warn | `fetch()` calls in descriptions (block), URLs/emails (warn) |
|
|
345
|
+
| Suspicious overrides | Warn | "bypass security", "auto-approve", "run without permission" |
|
|
346
|
+
|
|
347
|
+
**Blocked** items are skipped entirely with a warning. **Warned** items still load but emit a warning to stderr:
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
Warning: evil-tool.mjs blocked by guardrails: tool "evil" description: prompt injection: "ignore previous instructions"
|
|
351
|
+
Warning: shady-tool.mjs: tool "shady" description: description contains URL
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
When installing a skill from the registry, files are scanned before being written to disk. If the core `SKILL.md` is blocked, the entire installation is aborted.
|
|
253
355
|
|
|
254
356
|
## Streaming
|
|
255
357
|
|
package/dist/cli/repl.d.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { Interface } from 'node:readline';
|
|
2
2
|
import { Agent } from '../core/agent.js';
|
|
3
|
+
import { PermissionManager } from '../core/permissions.js';
|
|
3
4
|
import type { ConfirmToolCall } from '../core/types.js';
|
|
4
5
|
export declare function createConfirmCallback(sharedRl?: Interface): ConfirmToolCall & {
|
|
5
6
|
pauseSpinner: (() => void) | null;
|
|
6
7
|
};
|
|
8
|
+
export declare function createPermissionCallback(pm: PermissionManager, sharedRl?: Interface): ConfirmToolCall & {
|
|
9
|
+
pauseSpinner: (() => void) | null;
|
|
10
|
+
};
|
|
7
11
|
export declare class REPL {
|
|
8
12
|
private readonly agent;
|
|
9
13
|
private readonly rl;
|
|
10
|
-
private readonly
|
|
11
|
-
|
|
14
|
+
private readonly pm;
|
|
15
|
+
private confirmCb;
|
|
16
|
+
constructor(agent: Agent, pm?: PermissionManager, confirmCb?: ReturnType<typeof createPermissionCallback>);
|
|
12
17
|
start(): Promise<void>;
|
|
13
18
|
private handleCommand;
|
|
14
19
|
private ask;
|
package/dist/cli/repl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../src/cli/repl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,
|
|
1
|
+
{"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../src/cli/repl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,EAAsB,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAC;AAKjE,OAAO,EAAE,iBAAiB,EAAgB,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,kBAAkB,CAAC;AAqCvE,wBAAgB,qBAAqB,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,eAAe,GAAG;IAAE,YAAY,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;CAAE,CAgBnH;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,eAAe,GAAG;IAAE,YAAY,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;CAAE,CAiD7I;AA8GD,qBAAa,IAAI;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA2B;IAC9C,OAAO,CAAC,SAAS,CAAqD;gBAE1D,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC;IAqBnG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAwMd,aAAa;IA8Y3B,OAAO,CAAC,GAAG;CAGZ"}
|