@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.
Files changed (54) hide show
  1. package/README.md +106 -4
  2. package/dist/cli/repl.d.ts +7 -2
  3. package/dist/cli/repl.d.ts.map +1 -1
  4. package/dist/cli/repl.js +390 -95
  5. package/dist/cli/repl.js.map +1 -1
  6. package/dist/cli.js +18 -8
  7. package/dist/cli.js.map +1 -1
  8. package/dist/core/__tests__/agent.test.js +42 -1
  9. package/dist/core/__tests__/agent.test.js.map +1 -1
  10. package/dist/core/__tests__/context.test.js +37 -0
  11. package/dist/core/__tests__/context.test.js.map +1 -1
  12. package/dist/core/__tests__/guardrails.test.d.ts +2 -0
  13. package/dist/core/__tests__/guardrails.test.d.ts.map +1 -0
  14. package/dist/core/__tests__/guardrails.test.js +400 -0
  15. package/dist/core/__tests__/guardrails.test.js.map +1 -0
  16. package/dist/core/__tests__/permission-manager.test.d.ts +2 -0
  17. package/dist/core/__tests__/permission-manager.test.d.ts.map +1 -0
  18. package/dist/core/__tests__/permission-manager.test.js +246 -0
  19. package/dist/core/__tests__/permission-manager.test.js.map +1 -0
  20. package/dist/core/__tests__/streaming.test.js +8 -1
  21. package/dist/core/__tests__/streaming.test.js.map +1 -1
  22. package/dist/core/agent.d.ts +20 -2
  23. package/dist/core/agent.d.ts.map +1 -1
  24. package/dist/core/agent.js +259 -82
  25. package/dist/core/agent.js.map +1 -1
  26. package/dist/core/context.d.ts.map +1 -1
  27. package/dist/core/context.js +17 -2
  28. package/dist/core/context.js.map +1 -1
  29. package/dist/core/guardrails.d.ts +32 -0
  30. package/dist/core/guardrails.d.ts.map +1 -0
  31. package/dist/core/guardrails.js +149 -0
  32. package/dist/core/guardrails.js.map +1 -0
  33. package/dist/core/loader.d.ts +6 -2
  34. package/dist/core/loader.d.ts.map +1 -1
  35. package/dist/core/loader.js +23 -9
  36. package/dist/core/loader.js.map +1 -1
  37. package/dist/core/permissions.d.ts +60 -0
  38. package/dist/core/permissions.d.ts.map +1 -0
  39. package/dist/core/permissions.js +252 -0
  40. package/dist/core/permissions.js.map +1 -0
  41. package/dist/core/registry.d.ts.map +1 -1
  42. package/dist/core/registry.js +16 -0
  43. package/dist/core/registry.js.map +1 -1
  44. package/dist/core/skills.d.ts.map +1 -1
  45. package/dist/core/skills.js +26 -3
  46. package/dist/core/skills.js.map +1 -1
  47. package/dist/core/types.d.ts +20 -2
  48. package/dist/core/types.d.ts.map +1 -1
  49. package/dist/memory/__tests__/memory.test.js +33 -3
  50. package/dist/memory/__tests__/memory.test.js.map +1 -1
  51. package/dist/memory/memory.d.ts.map +1 -1
  52. package/dist/memory/memory.js +25 -3
  53. package/dist/memory/memory.js.map +1 -1
  54. 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) y
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) y
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
 
@@ -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 confirmCb;
11
- constructor(agent: Agent, confirmCb?: ReturnType<typeof createConfirmCallback>);
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;
@@ -1 +1 @@
1
- {"version":3,"file":"repl.d.ts","sourceRoot":"","sources":["../../src/cli/repl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,KAAK,EAA0B,MAAM,kBAAkB,CAAC;AAKjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAoBxD,wBAAgB,qBAAqB,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,eAAe,GAAG;IAAE,YAAY,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;CAAE,CAuBnH;AAmBD,qBAAa,IAAI;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkD;gBAEhE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC;IAcxE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YA6Id,aAAa;IAmU3B,OAAO,CAAC,GAAG;CAGZ"}
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"}