@getaegis/cli 0.8.0 → 0.9.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.
Files changed (242) hide show
  1. package/README.md +43 -14
  2. package/dist/agent/agent.d.ts +98 -0
  3. package/dist/agent/agent.d.ts.map +1 -0
  4. package/dist/agent/agent.js +212 -0
  5. package/dist/agent/agent.js.map +1 -0
  6. package/dist/agent/index.d.ts +3 -0
  7. package/dist/agent/index.d.ts.map +1 -0
  8. package/dist/agent/index.js +2 -0
  9. package/dist/agent/index.js.map +1 -0
  10. package/dist/cli/auth.d.ts +19 -0
  11. package/dist/cli/auth.d.ts.map +1 -0
  12. package/dist/cli/auth.js +44 -0
  13. package/dist/cli/auth.js.map +1 -0
  14. package/dist/cli/commands/agent.d.ts +6 -0
  15. package/dist/cli/commands/agent.d.ts.map +1 -0
  16. package/dist/cli/commands/agent.js +241 -0
  17. package/dist/cli/commands/agent.js.map +1 -0
  18. package/dist/cli/commands/config.d.ts +6 -0
  19. package/dist/cli/commands/config.d.ts.map +1 -0
  20. package/dist/cli/commands/config.js +125 -0
  21. package/dist/cli/commands/config.js.map +1 -0
  22. package/dist/cli/commands/dashboard.d.ts +6 -0
  23. package/dist/cli/commands/dashboard.d.ts.map +1 -0
  24. package/dist/cli/commands/dashboard.js +195 -0
  25. package/dist/cli/commands/dashboard.js.map +1 -0
  26. package/dist/cli/commands/db.d.ts +6 -0
  27. package/dist/cli/commands/db.d.ts.map +1 -0
  28. package/dist/cli/commands/db.js +139 -0
  29. package/dist/cli/commands/db.js.map +1 -0
  30. package/dist/cli/commands/doctor.d.ts +6 -0
  31. package/dist/cli/commands/doctor.d.ts.map +1 -0
  32. package/dist/cli/commands/doctor.js +39 -0
  33. package/dist/cli/commands/doctor.js.map +1 -0
  34. package/dist/cli/commands/gate.d.ts +6 -0
  35. package/dist/cli/commands/gate.d.ts.map +1 -0
  36. package/dist/cli/commands/gate.js +202 -0
  37. package/dist/cli/commands/gate.js.map +1 -0
  38. package/dist/cli/commands/init.d.ts +6 -0
  39. package/dist/cli/commands/init.d.ts.map +1 -0
  40. package/dist/cli/commands/init.js +175 -0
  41. package/dist/cli/commands/init.js.map +1 -0
  42. package/dist/cli/commands/key.d.ts +6 -0
  43. package/dist/cli/commands/key.d.ts.map +1 -0
  44. package/dist/cli/commands/key.js +49 -0
  45. package/dist/cli/commands/key.js.map +1 -0
  46. package/dist/cli/commands/ledger.d.ts +6 -0
  47. package/dist/cli/commands/ledger.d.ts.map +1 -0
  48. package/dist/cli/commands/ledger.js +140 -0
  49. package/dist/cli/commands/ledger.js.map +1 -0
  50. package/dist/cli/commands/mcp.d.ts +6 -0
  51. package/dist/cli/commands/mcp.d.ts.map +1 -0
  52. package/dist/cli/commands/mcp.js +224 -0
  53. package/dist/cli/commands/mcp.js.map +1 -0
  54. package/dist/cli/commands/policy.d.ts +6 -0
  55. package/dist/cli/commands/policy.d.ts.map +1 -0
  56. package/dist/cli/commands/policy.js +126 -0
  57. package/dist/cli/commands/policy.js.map +1 -0
  58. package/dist/cli/commands/user.d.ts +6 -0
  59. package/dist/cli/commands/user.d.ts.map +1 -0
  60. package/dist/cli/commands/user.js +150 -0
  61. package/dist/cli/commands/user.js.map +1 -0
  62. package/dist/cli/commands/vault-manager.d.ts +6 -0
  63. package/dist/cli/commands/vault-manager.d.ts.map +1 -0
  64. package/dist/cli/commands/vault-manager.js +240 -0
  65. package/dist/cli/commands/vault-manager.js.map +1 -0
  66. package/dist/cli/commands/vault.d.ts +6 -0
  67. package/dist/cli/commands/vault.d.ts.map +1 -0
  68. package/dist/cli/commands/vault.js +265 -0
  69. package/dist/cli/commands/vault.js.map +1 -0
  70. package/dist/cli/commands/webhook.d.ts +6 -0
  71. package/dist/cli/commands/webhook.d.ts.map +1 -0
  72. package/dist/cli/commands/webhook.js +151 -0
  73. package/dist/cli/commands/webhook.js.map +1 -0
  74. package/dist/cli/helpers.d.ts +12 -0
  75. package/dist/cli/helpers.d.ts.map +1 -0
  76. package/dist/cli/helpers.js +61 -0
  77. package/dist/cli/helpers.js.map +1 -0
  78. package/dist/cli/index.d.ts +19 -0
  79. package/dist/cli/index.d.ts.map +1 -0
  80. package/dist/cli/index.js +19 -0
  81. package/dist/cli/index.js.map +1 -0
  82. package/dist/cli/validation.d.ts +37 -0
  83. package/dist/cli/validation.d.ts.map +1 -0
  84. package/dist/cli/validation.js +104 -0
  85. package/dist/cli/validation.js.map +1 -0
  86. package/dist/cli.d.ts +3 -0
  87. package/dist/cli.d.ts.map +1 -0
  88. package/dist/cli.js +37 -0
  89. package/dist/cli.js.map +1 -0
  90. package/dist/config.d.ts +120 -0
  91. package/dist/config.d.ts.map +1 -0
  92. package/dist/config.js +401 -0
  93. package/dist/config.js.map +1 -0
  94. package/dist/dashboard/dashboard-server.d.ts +95 -0
  95. package/dist/dashboard/dashboard-server.d.ts.map +1 -0
  96. package/dist/dashboard/dashboard-server.js +329 -0
  97. package/dist/dashboard/dashboard-server.js.map +1 -0
  98. package/dist/dashboard/index.d.ts +3 -0
  99. package/dist/dashboard/index.d.ts.map +1 -0
  100. package/dist/dashboard/index.js +2 -0
  101. package/dist/dashboard/index.js.map +1 -0
  102. package/dist/dashboard/public/assets/index-Cah0_BKk.js +148 -0
  103. package/dist/dashboard/public/assets/index-CpMruPNh.css +1 -0
  104. package/dist/dashboard/public/favicon.svg +6 -0
  105. package/dist/dashboard/public/index.html +14 -0
  106. package/dist/db.d.ts +27 -0
  107. package/dist/db.d.ts.map +1 -0
  108. package/dist/db.js +209 -0
  109. package/dist/db.js.map +1 -0
  110. package/dist/doctor.d.ts +37 -0
  111. package/dist/doctor.d.ts.map +1 -0
  112. package/dist/doctor.js +216 -0
  113. package/dist/doctor.js.map +1 -0
  114. package/dist/gate/body-inspector.d.ts +31 -0
  115. package/dist/gate/body-inspector.d.ts.map +1 -0
  116. package/dist/gate/body-inspector.js +193 -0
  117. package/dist/gate/body-inspector.js.map +1 -0
  118. package/dist/gate/gate.d.ts +190 -0
  119. package/dist/gate/gate.d.ts.map +1 -0
  120. package/dist/gate/gate.js +1243 -0
  121. package/dist/gate/gate.js.map +1 -0
  122. package/dist/gate/index.d.ts +7 -0
  123. package/dist/gate/index.d.ts.map +1 -0
  124. package/dist/gate/index.js +4 -0
  125. package/dist/gate/index.js.map +1 -0
  126. package/dist/gate/rate-limiter.d.ts +59 -0
  127. package/dist/gate/rate-limiter.d.ts.map +1 -0
  128. package/dist/gate/rate-limiter.js +120 -0
  129. package/dist/gate/rate-limiter.js.map +1 -0
  130. package/dist/index.d.ts +28 -0
  131. package/dist/index.d.ts.map +1 -0
  132. package/dist/index.js +17 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/key-storage/credential-manager-windows.d.ts +19 -0
  135. package/dist/key-storage/credential-manager-windows.d.ts.map +1 -0
  136. package/dist/key-storage/credential-manager-windows.js +87 -0
  137. package/dist/key-storage/credential-manager-windows.js.map +1 -0
  138. package/dist/key-storage/file-fallback.d.ts +21 -0
  139. package/dist/key-storage/file-fallback.d.ts.map +1 -0
  140. package/dist/key-storage/file-fallback.js +62 -0
  141. package/dist/key-storage/file-fallback.js.map +1 -0
  142. package/dist/key-storage/index.d.ts +6 -0
  143. package/dist/key-storage/index.d.ts.map +1 -0
  144. package/dist/key-storage/index.js +6 -0
  145. package/dist/key-storage/index.js.map +1 -0
  146. package/dist/key-storage/key-storage.d.ts +41 -0
  147. package/dist/key-storage/key-storage.d.ts.map +1 -0
  148. package/dist/key-storage/key-storage.js +70 -0
  149. package/dist/key-storage/key-storage.js.map +1 -0
  150. package/dist/key-storage/keychain-macos.d.ts +19 -0
  151. package/dist/key-storage/keychain-macos.d.ts.map +1 -0
  152. package/dist/key-storage/keychain-macos.js +51 -0
  153. package/dist/key-storage/keychain-macos.js.map +1 -0
  154. package/dist/key-storage/secret-service-linux.d.ts +19 -0
  155. package/dist/key-storage/secret-service-linux.d.ts.map +1 -0
  156. package/dist/key-storage/secret-service-linux.js +55 -0
  157. package/dist/key-storage/secret-service-linux.js.map +1 -0
  158. package/dist/ledger/index.d.ts +3 -0
  159. package/dist/ledger/index.d.ts.map +1 -0
  160. package/dist/ledger/index.js +2 -0
  161. package/dist/ledger/index.js.map +1 -0
  162. package/dist/ledger/ledger.d.ts +98 -0
  163. package/dist/ledger/ledger.d.ts.map +1 -0
  164. package/dist/ledger/ledger.js +145 -0
  165. package/dist/ledger/ledger.js.map +1 -0
  166. package/dist/logger/index.d.ts +3 -0
  167. package/dist/logger/index.d.ts.map +1 -0
  168. package/dist/logger/index.js +2 -0
  169. package/dist/logger/index.js.map +1 -0
  170. package/dist/logger/logger.d.ts +58 -0
  171. package/dist/logger/logger.d.ts.map +1 -0
  172. package/dist/logger/logger.js +201 -0
  173. package/dist/logger/logger.js.map +1 -0
  174. package/dist/mcp/index.d.ts +3 -0
  175. package/dist/mcp/index.d.ts.map +1 -0
  176. package/dist/mcp/index.js +2 -0
  177. package/dist/mcp/index.js.map +1 -0
  178. package/dist/mcp/mcp-server.d.ts +130 -0
  179. package/dist/mcp/mcp-server.d.ts.map +1 -0
  180. package/dist/mcp/mcp-server.js +775 -0
  181. package/dist/mcp/mcp-server.js.map +1 -0
  182. package/dist/metrics/index.d.ts +3 -0
  183. package/dist/metrics/index.d.ts.map +1 -0
  184. package/dist/metrics/index.js +2 -0
  185. package/dist/metrics/index.js.map +1 -0
  186. package/dist/metrics/metrics.d.ts +88 -0
  187. package/dist/metrics/metrics.d.ts.map +1 -0
  188. package/dist/metrics/metrics.js +179 -0
  189. package/dist/metrics/metrics.js.map +1 -0
  190. package/dist/policy/index.d.ts +3 -0
  191. package/dist/policy/index.d.ts.map +1 -0
  192. package/dist/policy/index.js +2 -0
  193. package/dist/policy/index.js.map +1 -0
  194. package/dist/policy/policy.d.ts +119 -0
  195. package/dist/policy/policy.d.ts.map +1 -0
  196. package/dist/policy/policy.js +426 -0
  197. package/dist/policy/policy.js.map +1 -0
  198. package/dist/user/index.d.ts +3 -0
  199. package/dist/user/index.d.ts.map +1 -0
  200. package/dist/user/index.js +2 -0
  201. package/dist/user/index.js.map +1 -0
  202. package/dist/user/user.d.ts +102 -0
  203. package/dist/user/user.d.ts.map +1 -0
  204. package/dist/user/user.js +216 -0
  205. package/dist/user/user.js.map +1 -0
  206. package/dist/vault/crypto.d.ts +28 -0
  207. package/dist/vault/crypto.d.ts.map +1 -0
  208. package/dist/vault/crypto.js +44 -0
  209. package/dist/vault/crypto.js.map +1 -0
  210. package/dist/vault/index.d.ts +10 -0
  211. package/dist/vault/index.d.ts.map +1 -0
  212. package/dist/vault/index.js +6 -0
  213. package/dist/vault/index.js.map +1 -0
  214. package/dist/vault/seal.d.ts +68 -0
  215. package/dist/vault/seal.d.ts.map +1 -0
  216. package/dist/vault/seal.js +110 -0
  217. package/dist/vault/seal.js.map +1 -0
  218. package/dist/vault/shamir.d.ts +33 -0
  219. package/dist/vault/shamir.d.ts.map +1 -0
  220. package/dist/vault/shamir.js +174 -0
  221. package/dist/vault/shamir.js.map +1 -0
  222. package/dist/vault/vault-manager.d.ts +62 -0
  223. package/dist/vault/vault-manager.d.ts.map +1 -0
  224. package/dist/vault/vault-manager.js +151 -0
  225. package/dist/vault/vault-manager.js.map +1 -0
  226. package/dist/vault/vault.d.ts +104 -0
  227. package/dist/vault/vault.d.ts.map +1 -0
  228. package/dist/vault/vault.js +259 -0
  229. package/dist/vault/vault.js.map +1 -0
  230. package/dist/version.d.ts +3 -0
  231. package/dist/version.d.ts.map +1 -0
  232. package/dist/version.js +18 -0
  233. package/dist/version.js.map +1 -0
  234. package/dist/webhook/index.d.ts +3 -0
  235. package/dist/webhook/index.d.ts.map +1 -0
  236. package/dist/webhook/index.js +2 -0
  237. package/dist/webhook/index.js.map +1 -0
  238. package/dist/webhook/webhook.d.ts +114 -0
  239. package/dist/webhook/webhook.d.ts.map +1 -0
  240. package/dist/webhook/webhook.js +269 -0
  241. package/dist/webhook/webhook.js.map +1 -0
  242. package/package.json +12 -6
package/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Aegis
2
2
 
3
+ [![CI](https://github.com/getaegis/aegis/actions/workflows/ci.yml/badge.svg)](https://github.com/getaegis/aegis/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@getaegis/cli)](https://www.npmjs.com/package/@getaegis/cli)
5
+ [![Docker](https://img.shields.io/badge/ghcr.io-getaegis%2Faegis-blue?logo=docker)](https://ghcr.io/getaegis/aegis)
6
+ [![License](https://img.shields.io/github/license/getaegis/aegis)](LICENSE)
7
+
3
8
  **Credential isolation for AI agents.**
4
9
 
5
10
  Aegis sits between your AI agent and the APIs it calls. The agent never sees, stores, or transmits real credentials — Aegis injects them at the network boundary.
@@ -41,17 +46,30 @@ Aegis solves all four. Your agent makes HTTP calls through a local proxy. Aegis
41
46
  npm install -g @getaegis/cli
42
47
 
43
48
  # Initialize — generates master key, config file, and encrypted vault
49
+ aegis init
50
+ ```
51
+
52
+ By default, `aegis init` stores the master key in your OS keychain (macOS Keychain, Windows Credential Manager, or Linux Secret Service). If no keychain is available, it falls back to a file at `.aegis/.master-key` (mode 0600).
53
+
54
+ Alternative storage modes:
55
+
56
+ ```bash
57
+ # Store in .env file (for CI/headless environments)
58
+ aegis init --env-file
59
+
60
+ # Store in aegis.config.yaml (convenient for local dev, not recommended for production)
44
61
  aegis init --write-secrets
62
+
63
+ # Check where your master key is stored
64
+ aegis key where
45
65
  ```
46
66
 
47
- `aegis init` prints a master key. Without `--write-secrets`, you must export it yourself:
67
+ If you use `--env-file` or need to set the key manually:
48
68
 
49
69
  ```bash
50
70
  export AEGIS_MASTER_KEY=<key from init>
51
71
  ```
52
72
 
53
- With `--write-secrets`, the key is saved to `aegis.config.yaml` automatically (convenient for local dev, not recommended for production).
54
-
55
73
  ```bash
56
74
  # Add a credential
57
75
  aegis vault add \
@@ -90,6 +108,7 @@ curl http://localhost:3100/slack/api/auth.test \
90
108
  | **RBAC** | Admin, operator, viewer roles with 16 granular permissions |
91
109
  | **Multi-Vault** | Separate vaults for dev/staging/prod with isolated encryption keys |
92
110
  | **Shamir's Secret Sharing** | M-of-N key splitting for team master key management |
111
+ | **Cross-Platform Key Storage** | OS keychain by default (macOS Keychain, Windows Credential Manager, Linux Secret Service) with file fallback |
93
112
  | **TLS Support** | Optional HTTPS on Gate with cert/key configuration |
94
113
  | **Configuration File** | `aegis.config.yaml` with env var overrides and CLI flag overrides |
95
114
 
@@ -116,7 +135,7 @@ The MCP server replicates the full Gate security pipeline: domain guard, agent a
116
135
 
117
136
  ## Agent Identity & Scoping
118
137
 
119
- Without agent auth, any process on localhost can use any credential. Enable agent auth to restrict access:
138
+ Agent authentication is **on by default**. Every request through Gate must include a valid `X-Aegis-Agent` header. Requests without a token get a helpful 401 error with instructions to create an agent.
120
139
 
121
140
  ```bash
122
141
  # Register an agent — token is printed once, save it
@@ -128,13 +147,16 @@ aegis agent grant --agent "research-bot" --credential "slack-bot"
128
147
  # Set per-agent rate limits
129
148
  aegis agent set-rate-limit --agent "research-bot" --limit 50/min
130
149
 
131
- # Start Gate with agent auth required
132
- aegis gate --require-agent-auth
150
+ # Start Gate (agent auth is on by default)
151
+ aegis gate
133
152
 
134
153
  # Agent must include its token in every request
135
154
  curl http://localhost:3100/slack/api/auth.test \
136
155
  -H "X-Target-Host: api.slack.com" \
137
156
  -H "X-Aegis-Agent: aegis_a1b2c3d4..."
157
+
158
+ # To disable agent auth (not recommended):
159
+ aegis gate --no-agent-auth
138
160
  ```
139
161
 
140
162
  Tokens are SHA-256 hashed for storage — they cannot be recovered, only regenerated:
@@ -204,7 +226,8 @@ aegis vault add \
204
226
  | `--ttl <days>` | *(none)* | Credential expires after this many days |
205
227
  | `--rate-limit` | *(none)* | Rate limit: `100/min`, `1000/hour`, `10/sec` |
206
228
  | `--body-inspection` | `block` | Scan outbound bodies for credential patterns: `off`, `warn`, `block` |
207
- | `--header-name` | — | Custom header name (only for `--auth-type header`) |
229
+ | `--header-name` | — | Custom header name (for `--auth-type header`) |
230
+ | `--query-param` | `key` | Query parameter name (for `--auth-type query`) |
208
231
 
209
232
  Update any field later:
210
233
 
@@ -221,7 +244,7 @@ Aegis supports four credential injection methods:
221
244
  | `bearer` | `--auth-type bearer` (default) | `Authorization: Bearer <secret>` |
222
245
  | `header` | `--auth-type header --header-name X-API-Key` | `X-API-Key: <secret>` |
223
246
  | `basic` | `--auth-type basic` | `Authorization: Basic <base64(secret)>` |
224
- | `query` | `--auth-type query` | Appends `?key=<secret>` to the URL |
247
+ | `query` | `--auth-type query --query-param api_key` | Appends `?api_key=<secret>` to the URL |
225
248
 
226
249
  ## Configuration
227
250
 
@@ -463,13 +486,15 @@ Runs diagnostics on your Aegis installation:
463
486
  - Config file validation
464
487
  - Database accessibility and schema
465
488
  - Master key correctness (test decrypt)
489
+ - Key storage backend (keychain type and status)
466
490
  - Expired or expiring-soon credentials
467
491
 
468
492
  Returns pass/warn/fail for each check.
469
493
 
470
494
  ## Security Model
471
495
 
472
- - **Encryption at rest** — AES-256-GCM with PBKDF2 key derivation (100k iterations, SHA-512, random per-deployment salt)
496
+ - **Encryption at rest** — AES-256-GCM with PBKDF2 key derivation (210,000 iterations, SHA-512, random per-deployment salt)
497
+ - **Cross-platform key storage** — master key stored in OS keychain by default (macOS Keychain, Windows Credential Manager, Linux Secret Service). File fallback for CI/headless
473
498
  - **Domain guard** — enforced on every outbound request. No bypass, no override. Wildcards supported (`*.slack.com`)
474
499
  - **Credential scopes** — `read` (GET/HEAD/OPTIONS), `write` (POST/PUT/PATCH/DELETE), `*` (all). Enforced at the Gate before any request is forwarded
475
500
  - **Header stripping** — agent-supplied `Authorization`, `X-API-Key`, `Proxy-Authorization` headers are removed before injection
@@ -479,13 +504,13 @@ Returns pass/warn/fail for each check.
479
504
  - **TLS support** — optional HTTPS on Gate (`aegis gate --tls --cert <path> --key <path>`)
480
505
  - **Graceful shutdown** — drains in-flight requests on SIGINT/SIGTERM
481
506
 
482
- See [SECURITY_ARCHITECTURE.md](docs/SECURITY_ARCHITECTURE.md) for the full security design, threat model, and trust boundaries.
507
+ See [SECURITY_ARCHITECTURE.md](docs/SECURITY_ARCHITECTURE.md) for the full security design and trust boundaries, and [THREAT_MODEL.md](docs/THREAT_MODEL.md) for the STRIDE threat analysis.
483
508
 
484
509
  ## CLI Reference
485
510
 
486
511
  ```
487
512
  aegis init [--write-secrets] Initialize Aegis (master key + config)
488
- aegis gate [--port] [--tls] [--require-agent-auth] [--policies-dir] [--policy-mode]
513
+ aegis gate [--port] [--tls] [--no-agent-auth] [--policies-dir] [--policy-mode]
489
514
  Start the HTTP proxy
490
515
  aegis dashboard [--port] [--gate-port] Start the web dashboard + Gate
491
516
 
@@ -547,8 +572,12 @@ aegis user regenerate-token --name <name> Regenerate user token
547
572
  aegis mcp serve [--transport] [--port] Start the MCP server
548
573
  aegis mcp config <claude|cursor|vscode> Generate MCP host config
549
574
 
575
+ aegis db backup [--output <path>] Backup the vault database
576
+ aegis db restore --input <path> [--force] Restore from a backup
577
+
550
578
  aegis config validate Validate config file
551
579
  aegis config show Show resolved configuration
580
+ aegis key where Show where the master key is stored
552
581
  aegis doctor Health check diagnostics
553
582
  ```
554
583
 
@@ -556,7 +585,7 @@ aegis doctor Health check diagnostics
556
585
 
557
586
  | Error | Cause | Fix |
558
587
  |-------|-------|-----|
559
- | `AEGIS_MASTER_KEY is not set` | No master key in config or env | `export AEGIS_MASTER_KEY=<key>` or use `aegis init --write-secrets` |
588
+ | `AEGIS_MASTER_KEY is not set` | No master key in config, env, or keychain | Run `aegis key where` to check storage, or `export AEGIS_MASTER_KEY=<key>` |
560
589
  | `Invalid master key` | Wrong key for this vault | Check `AEGIS_MASTER_KEY` matches the key from `aegis init` |
561
590
  | `Port 3100 is already in use` | Another process on that port | Use `aegis gate --port 3200` or stop the other process |
562
591
  | `Database file is corrupted` | SQLite file damaged | Back up `.aegis/` and re-run `aegis init` |
@@ -585,8 +614,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for code style, PR process, and architect
585
614
  |-------|------------|
586
615
  | Language | TypeScript (ES2022, native ESM) |
587
616
  | Runtime | Node.js ≥ 20 |
588
- | Database | SQLite via better-sqlite3 (WAL mode) |
589
- | Encryption | AES-256-GCM, PBKDF2 |
617
+ | Database | SQLite via better-sqlite3-multiple-ciphers (WAL mode, ChaCha20-Poly1305 encryption at rest) |
618
+ | Encryption | AES-256-GCM (field-level), ChaCha20-Poly1305 (full-database), PBKDF2 |
590
619
  | Logging | pino (structured JSON, field-level redaction) |
591
620
  | Metrics | prom-client (Prometheus) |
592
621
  | CLI | Commander.js |
@@ -0,0 +1,98 @@
1
+ import type Database from 'better-sqlite3-multiple-ciphers';
2
+ export interface Agent {
3
+ id: string;
4
+ name: string;
5
+ tokenPrefix: string;
6
+ rateLimit?: string;
7
+ createdAt: string;
8
+ updatedAt: string;
9
+ }
10
+ export interface AgentWithToken extends Agent {
11
+ token: string;
12
+ }
13
+ /**
14
+ * Agent Registry — manages agent identities and their credential access grants.
15
+ *
16
+ * Agents are identified by tokens (UUID v4 + HMAC suffix). Tokens are:
17
+ * - Hashed (SHA-256) for fast lookup during request validation — hash-only, no recovery
18
+ * - Prefixed (first 12 chars) for safe display in logs and audit entries
19
+ *
20
+ * Security: Tokens are never stored in recoverable form. If a token is lost,
21
+ * use regenerateToken() to issue a new one (same pattern as GitHub/Stripe key rotation).
22
+ */
23
+ export declare class AgentRegistry {
24
+ private db;
25
+ private derivedKey;
26
+ constructor(db: Database.Database, derivedKey: Buffer);
27
+ /**
28
+ * Register a new agent. Returns the agent with its token (shown once).
29
+ *
30
+ * Token format: aegis_{uuid}_{hmac_prefix}
31
+ * The HMAC is derived from the UUID using the master key, making tokens
32
+ * verifiable as Aegis-generated.
33
+ */
34
+ add(params: {
35
+ name: string;
36
+ rateLimit?: string;
37
+ }): AgentWithToken;
38
+ /**
39
+ * List all registered agents (without tokens).
40
+ */
41
+ list(): Agent[];
42
+ /**
43
+ * Get an agent by name (without token).
44
+ */
45
+ getByName(name: string): Agent | null;
46
+ /**
47
+ * Validate an agent token. Returns the agent if the token is valid, null otherwise.
48
+ *
49
+ * Uses SHA-256 hash comparison for constant-time-safe lookup.
50
+ */
51
+ validateToken(token: string): Agent | null;
52
+ /**
53
+ * Remove an agent by name. Also removes all credential grants.
54
+ */
55
+ remove(name: string): boolean;
56
+ /**
57
+ * Regenerate an agent's token. Issues a new token, invalidates the old one.
58
+ *
59
+ * The agent keeps its identity (id, name), credential grants, and rate limits.
60
+ * Only the token changes. This follows the same pattern as GitHub personal
61
+ * access token rotation or Stripe API key rolling.
62
+ *
63
+ * Returns the agent with the new token (shown once), or null if not found.
64
+ */
65
+ regenerateToken(name: string): AgentWithToken | null;
66
+ /**
67
+ * Grant an agent access to a credential.
68
+ */
69
+ grant(params: {
70
+ agentName: string;
71
+ credentialId: string;
72
+ }): void;
73
+ /**
74
+ * Revoke an agent's access to a credential.
75
+ */
76
+ revoke(params: {
77
+ agentName: string;
78
+ credentialId: string;
79
+ }): boolean;
80
+ /**
81
+ * Check if an agent has access to a specific credential.
82
+ */
83
+ hasAccess(agentId: string, credentialId: string): boolean;
84
+ /**
85
+ * List all credential IDs an agent has access to.
86
+ */
87
+ listGrants(agentName: string): string[];
88
+ /**
89
+ * Set or update an agent's rate limit for a specific service.
90
+ * This is stored as a general rate limit on the agent record.
91
+ */
92
+ setRateLimit(params: {
93
+ agentName: string;
94
+ rateLimit: string | null;
95
+ }): Agent;
96
+ private rowToAgent;
97
+ }
98
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,iCAAiC,CAAC;AAI5D,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,KAAK;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAcD;;;;;;;;;GASG;AACH,qBAAa,aAAa;IAItB,OAAO,CAAC,EAAE;IAHZ,OAAO,CAAC,UAAU,CAAS;gBAGjB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAC7B,UAAU,EAAE,MAAM;IAKpB;;;;;;OAMG;IACH,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,cAAc;IAkCjE;;OAEG;IACH,IAAI,IAAI,KAAK,EAAE;IAQf;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAOrC;;;;OAIG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IAS1C;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAS7B;;;;;;;;OAQG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAkCpD;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAoBhE;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;IAapE;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAQzD;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAevC;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,KAAK;IAmB5E,OAAO,CAAC,UAAU;CAUnB"}
@@ -0,0 +1,212 @@
1
+ import * as crypto from 'node:crypto';
2
+ // ─── Agent Registry ──────────────────────────────────────────────
3
+ /**
4
+ * Agent Registry — manages agent identities and their credential access grants.
5
+ *
6
+ * Agents are identified by tokens (UUID v4 + HMAC suffix). Tokens are:
7
+ * - Hashed (SHA-256) for fast lookup during request validation — hash-only, no recovery
8
+ * - Prefixed (first 12 chars) for safe display in logs and audit entries
9
+ *
10
+ * Security: Tokens are never stored in recoverable form. If a token is lost,
11
+ * use regenerateToken() to issue a new one (same pattern as GitHub/Stripe key rotation).
12
+ */
13
+ export class AgentRegistry {
14
+ db;
15
+ derivedKey;
16
+ constructor(db, derivedKey) {
17
+ this.db = db;
18
+ this.derivedKey = derivedKey;
19
+ }
20
+ /**
21
+ * Register a new agent. Returns the agent with its token (shown once).
22
+ *
23
+ * Token format: aegis_{uuid}_{hmac_prefix}
24
+ * The HMAC is derived from the UUID using the master key, making tokens
25
+ * verifiable as Aegis-generated.
26
+ */
27
+ add(params) {
28
+ const id = crypto.randomUUID();
29
+ const uuid = crypto.randomUUID();
30
+ // Create HMAC of the UUID using the derived key for token integrity
31
+ const hmac = crypto
32
+ .createHmac('sha256', this.derivedKey)
33
+ .update(uuid)
34
+ .digest('hex')
35
+ .slice(0, 16);
36
+ const token = `aegis_${uuid}_${hmac}`;
37
+ // Hash the full token for fast lookup (hash-only — no recovery, only regeneration)
38
+ const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
39
+ const tokenPrefix = token.slice(0, 12);
40
+ this.db
41
+ .prepare(`INSERT INTO agents (id, name, token_hash, token_prefix, rate_limit)
42
+ VALUES (?, ?, ?, ?, ?)`)
43
+ .run(id, params.name, tokenHash, tokenPrefix, params.rateLimit ?? null);
44
+ return {
45
+ id,
46
+ name: params.name,
47
+ tokenPrefix,
48
+ token,
49
+ rateLimit: params.rateLimit,
50
+ createdAt: new Date().toISOString(),
51
+ updatedAt: new Date().toISOString(),
52
+ };
53
+ }
54
+ /**
55
+ * List all registered agents (without tokens).
56
+ */
57
+ list() {
58
+ const rows = this.db
59
+ .prepare('SELECT * FROM agents ORDER BY created_at DESC')
60
+ .all();
61
+ return rows.map((row) => this.rowToAgent(row));
62
+ }
63
+ /**
64
+ * Get an agent by name (without token).
65
+ */
66
+ getByName(name) {
67
+ const row = this.db.prepare('SELECT * FROM agents WHERE name = ?').get(name);
68
+ return row ? this.rowToAgent(row) : null;
69
+ }
70
+ /**
71
+ * Validate an agent token. Returns the agent if the token is valid, null otherwise.
72
+ *
73
+ * Uses SHA-256 hash comparison for constant-time-safe lookup.
74
+ */
75
+ validateToken(token) {
76
+ const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
77
+ const row = this.db.prepare('SELECT * FROM agents WHERE token_hash = ?').get(tokenHash);
78
+ return row ? this.rowToAgent(row) : null;
79
+ }
80
+ /**
81
+ * Remove an agent by name. Also removes all credential grants.
82
+ */
83
+ remove(name) {
84
+ const agent = this.getByName(name);
85
+ if (!agent)
86
+ return false;
87
+ // Foreign key CASCADE handles agent_credentials cleanup
88
+ const result = this.db.prepare('DELETE FROM agents WHERE name = ?').run(name);
89
+ return result.changes > 0;
90
+ }
91
+ /**
92
+ * Regenerate an agent's token. Issues a new token, invalidates the old one.
93
+ *
94
+ * The agent keeps its identity (id, name), credential grants, and rate limits.
95
+ * Only the token changes. This follows the same pattern as GitHub personal
96
+ * access token rotation or Stripe API key rolling.
97
+ *
98
+ * Returns the agent with the new token (shown once), or null if not found.
99
+ */
100
+ regenerateToken(name) {
101
+ const agent = this.getByName(name);
102
+ if (!agent)
103
+ return null;
104
+ // Generate a new token with the same UUID+HMAC format
105
+ const uuid = crypto.randomUUID();
106
+ const hmac = crypto
107
+ .createHmac('sha256', this.derivedKey)
108
+ .update(uuid)
109
+ .digest('hex')
110
+ .slice(0, 16);
111
+ const token = `aegis_${uuid}_${hmac}`;
112
+ // Compute new hash and prefix
113
+ const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
114
+ const tokenPrefix = token.slice(0, 12);
115
+ // Update only the token fields — identity, grants, and rate limits are preserved
116
+ this.db
117
+ .prepare(`UPDATE agents SET token_hash = ?, token_prefix = ?, updated_at = datetime('now') WHERE id = ?`)
118
+ .run(tokenHash, tokenPrefix, agent.id);
119
+ return {
120
+ ...agent,
121
+ tokenPrefix,
122
+ token,
123
+ updatedAt: new Date().toISOString(),
124
+ };
125
+ }
126
+ // ─── Credential Grants ──────────────────────────────────────────
127
+ /**
128
+ * Grant an agent access to a credential.
129
+ */
130
+ grant(params) {
131
+ const agent = this.getByName(params.agentName);
132
+ if (!agent) {
133
+ throw new Error(`No agent found with name "${params.agentName}"`);
134
+ }
135
+ // Check if already granted
136
+ const existing = this.db
137
+ .prepare('SELECT 1 FROM agent_credentials WHERE agent_id = ? AND credential_id = ?')
138
+ .get(agent.id, params.credentialId);
139
+ if (existing) {
140
+ return; // Already granted — idempotent
141
+ }
142
+ this.db
143
+ .prepare('INSERT INTO agent_credentials (agent_id, credential_id) VALUES (?, ?)')
144
+ .run(agent.id, params.credentialId);
145
+ }
146
+ /**
147
+ * Revoke an agent's access to a credential.
148
+ */
149
+ revoke(params) {
150
+ const agent = this.getByName(params.agentName);
151
+ if (!agent) {
152
+ throw new Error(`No agent found with name "${params.agentName}"`);
153
+ }
154
+ const result = this.db
155
+ .prepare('DELETE FROM agent_credentials WHERE agent_id = ? AND credential_id = ?')
156
+ .run(agent.id, params.credentialId);
157
+ return result.changes > 0;
158
+ }
159
+ /**
160
+ * Check if an agent has access to a specific credential.
161
+ */
162
+ hasAccess(agentId, credentialId) {
163
+ const row = this.db
164
+ .prepare('SELECT 1 FROM agent_credentials WHERE agent_id = ? AND credential_id = ?')
165
+ .get(agentId, credentialId);
166
+ return row !== undefined;
167
+ }
168
+ /**
169
+ * List all credential IDs an agent has access to.
170
+ */
171
+ listGrants(agentName) {
172
+ const agent = this.getByName(agentName);
173
+ if (!agent) {
174
+ throw new Error(`No agent found with name "${agentName}"`);
175
+ }
176
+ const rows = this.db
177
+ .prepare('SELECT credential_id FROM agent_credentials WHERE agent_id = ?')
178
+ .all(agent.id);
179
+ return rows.map((r) => r.credential_id);
180
+ }
181
+ // ─── Per-Agent Rate Limits ──────────────────────────────────────
182
+ /**
183
+ * Set or update an agent's rate limit for a specific service.
184
+ * This is stored as a general rate limit on the agent record.
185
+ */
186
+ setRateLimit(params) {
187
+ const agent = this.getByName(params.agentName);
188
+ if (!agent) {
189
+ throw new Error(`No agent found with name "${params.agentName}"`);
190
+ }
191
+ this.db
192
+ .prepare("UPDATE agents SET rate_limit = ?, updated_at = datetime('now') WHERE id = ?")
193
+ .run(params.rateLimit, agent.id);
194
+ return {
195
+ ...agent,
196
+ rateLimit: params.rateLimit ?? undefined,
197
+ updatedAt: new Date().toISOString(),
198
+ };
199
+ }
200
+ // ─── Internal ───────────────────────────────────────────────────
201
+ rowToAgent(row) {
202
+ return {
203
+ id: row.id,
204
+ name: row.name,
205
+ tokenPrefix: row.token_prefix,
206
+ rateLimit: row.rate_limit ?? undefined,
207
+ createdAt: row.created_at,
208
+ updatedAt: row.updated_at,
209
+ };
210
+ }
211
+ }
212
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type { Agent, AgentWithToken } from './agent.js';
2
+ export { AgentRegistry } from './agent.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { AgentRegistry } from './agent.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * RBAC enforcement helper for CLI commands.
3
+ *
4
+ * Authenticates the current user via AEGIS_USER_TOKEN and checks
5
+ * whether they have the required permission.
6
+ */
7
+ import type { getDb } from '../db.js';
8
+ import type { Permission } from '../user/index.js';
9
+ /**
10
+ * Authenticate the current user via AEGIS_USER_TOKEN and check permission.
11
+ *
12
+ * Always enforced once users exist. If no users have been created yet
13
+ * (bootstrap mode), all commands are allowed — `aegis init` creates the
14
+ * first admin user.
15
+ *
16
+ * Returns true if allowed. Calls process.exit(1) if denied.
17
+ */
18
+ export declare function requireUserAuth(db: ReturnType<typeof getDb>, derivedKey: Buffer, permission: Permission): boolean;
19
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/cli/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,UAAU,GACrB,OAAO,CA+BT"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * RBAC enforcement helper for CLI commands.
3
+ *
4
+ * Authenticates the current user via AEGIS_USER_TOKEN and checks
5
+ * whether they have the required permission.
6
+ */
7
+ import { hasPermission, UserRegistry } from '../user/index.js';
8
+ /**
9
+ * Authenticate the current user via AEGIS_USER_TOKEN and check permission.
10
+ *
11
+ * Always enforced once users exist. If no users have been created yet
12
+ * (bootstrap mode), all commands are allowed — `aegis init` creates the
13
+ * first admin user.
14
+ *
15
+ * Returns true if allowed. Calls process.exit(1) if denied.
16
+ */
17
+ export function requireUserAuth(db, derivedKey, permission) {
18
+ const registry = new UserRegistry(db, derivedKey);
19
+ // Bootstrap mode: no users exist yet — allow everything so init can create the first admin
20
+ if (registry.count() === 0)
21
+ return true;
22
+ const token = process.env.AEGIS_USER_TOKEN;
23
+ if (!token) {
24
+ console.error('\n✗ Authentication required. Set AEGIS_USER_TOKEN=<your-api-key>\n');
25
+ console.error(' Get an API key from your admin, or regenerate with:');
26
+ console.error(' aegis user regenerate-token --name <name>\n');
27
+ process.exit(1);
28
+ }
29
+ const user = registry.validateToken(token);
30
+ if (!user) {
31
+ console.error('\n✗ Invalid API key. Token not recognized.\n');
32
+ console.error(' Regenerate with: aegis user regenerate-token --name <name>\n');
33
+ process.exit(1);
34
+ }
35
+ if (!hasPermission(user.role, permission)) {
36
+ console.error(`\n✗ Permission denied. Role "${user.role}" does not have "${permission}".\n`);
37
+ console.error(` Required permission: ${permission}`);
38
+ console.error(` Your role: ${user.role}`);
39
+ console.error(` Contact an admin to upgrade your role.\n`);
40
+ process.exit(1);
41
+ }
42
+ return true;
43
+ }
44
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/cli/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE/D;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,EAA4B,EAC5B,UAAkB,EAClB,UAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAElD,2FAA2F;IAC3F,IAAI,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACpF,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAE3C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC9D,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC;QAC1C,OAAO,CAAC,KAAK,CAAC,gCAAgC,IAAI,CAAC,IAAI,oBAAoB,UAAU,MAAM,CAAC,CAAC;QAC7F,OAAO,CAAC,KAAK,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,gBAAgB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Agent commands: add, list, remove, regenerate, grant, revoke, set-rate-limit.
3
+ */
4
+ import type { Command } from 'commander';
5
+ export declare function register(program: Command): void;
6
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqP/C"}