opencode-varlock 0.0.7 → 0.0.9
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 +29 -326
- package/assets/varlock.config.json +1 -1
- package/dist/config.d.ts +6 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -3
- package/dist/config.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +25 -4
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,86 +1,39 @@
|
|
|
1
1
|
# opencode-varlock
|
|
2
2
|
|
|
3
|
-
OpenCode plugin that gives agents access to environment variables
|
|
3
|
+
OpenCode plugin that gives agents access to environment variables without revealing secret values.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> Warning
|
|
6
|
+
> This plugin is still early in development, and there is active work underway to improve its security model and edge-case protections. PRs, issue reports, and security feedback are very welcome.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
## What it does
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
┌──────────────────────────────────────────────────┐
|
|
15
|
-
│ Agent context window │
|
|
16
|
-
│ │
|
|
17
|
-
│ "Loaded 3 vars: DB_URL, API_KEY, REDIS_HOST" │
|
|
18
|
-
│ ↑ names only, never values │
|
|
19
|
-
│ │
|
|
20
|
-
├──────────────────────────────────────────────────┤
|
|
21
|
-
│ Layer 1 — Custom tools (load_env / load_secrets)│
|
|
22
|
-
│ Reads files or calls Varlock CLI, injects into │
|
|
23
|
-
│ process.env, returns only key names. │
|
|
24
|
-
├──────────────────────────────────────────────────┤
|
|
25
|
-
│ Layer 2 — Permission rules │
|
|
26
|
-
│ Glob-based deny rules block `cat .env`, │
|
|
27
|
-
│ `printenv`, `echo $SECRET`, etc. │
|
|
28
|
-
├──────────────────────────────────────────────────┤
|
|
29
|
-
│ Layer 3 — EnvGuard hook │
|
|
30
|
-
│ tool.execute.before intercept catches anything │
|
|
31
|
-
│ the glob rules miss (python -c, scripting │
|
|
32
|
-
│ escapes, indirect reads). │
|
|
33
|
-
└──────────────────────────────────────────────────┘
|
|
34
|
-
```
|
|
10
|
+
- provides `load_env` so agents can use `.env` values without seeing them directly
|
|
11
|
+
- provides `load_secrets` and `secret_status` when the Varlock CLI is available
|
|
12
|
+
- blocks direct secret reads with permission presets plus a `tool.execute.before` guard
|
|
13
|
+
- tries to catch common workarounds like interpreter-based env reads
|
|
35
14
|
|
|
36
15
|
## Install
|
|
37
16
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install opencode-varlock
|
|
42
|
-
```
|
|
17
|
+
Add the package to your `opencode.json` file:
|
|
43
18
|
|
|
44
19
|
```json
|
|
45
|
-
// opencode.json
|
|
46
20
|
{
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
The published package ships compiled ESM in `dist/`, and the root entry exports only the plugin itself so OpenCode can load it cleanly through the normal npm plugin resolution flow.
|
|
52
|
-
|
|
53
|
-
### As a local plugin
|
|
54
|
-
|
|
55
|
-
Reference the package directory locally after building it:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"plugin": ["./path/to/opencode-varlock"]
|
|
21
|
+
"$schema": "https://opencode.ai/config.json",
|
|
22
|
+
"plugin": ["opencode-varlock@latest"]
|
|
60
23
|
}
|
|
61
24
|
```
|
|
62
25
|
|
|
63
26
|
## Configuration
|
|
64
27
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
1. `./varlock.config.json` (project root)
|
|
68
|
-
2. `.opencode/varlock.config.json`
|
|
28
|
+
`varlock.config.json` is optional.
|
|
69
29
|
|
|
70
|
-
|
|
30
|
+
If you do not provide one, the plugin uses its built-in defaults from [assets/varlock.config.json](assets/varlock.config.json). Create a local config only when you want to override those defaults.
|
|
71
31
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
Copy the default config into your project:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
cp node_modules/opencode-varlock/assets/varlock.config.json ./varlock.config.json
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Or create a minimal one — only the fields you want to change:
|
|
32
|
+
Quick example:
|
|
81
33
|
|
|
82
34
|
```json
|
|
83
35
|
{
|
|
36
|
+
"$schema": "https://raw.githubusercontent.com/itlackey/opencode-varlock/main/assets/varlock.schema.json",
|
|
84
37
|
"varlock": {
|
|
85
38
|
"enabled": true,
|
|
86
39
|
"namespace": "myapp"
|
|
@@ -88,276 +41,26 @@ Or create a minimal one — only the fields you want to change:
|
|
|
88
41
|
}
|
|
89
42
|
```
|
|
90
43
|
|
|
91
|
-
|
|
44
|
+
Useful files:
|
|
45
|
+
- default config: `assets/varlock.config.json`
|
|
46
|
+
- JSON schema: `assets/varlock.schema.json`
|
|
47
|
+
- recommended permission configurations: `assets/permissions.json`
|
|
92
48
|
|
|
93
|
-
|
|
49
|
+
## Docs
|
|
94
50
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
The copied config template points its `$schema` at `./node_modules/opencode-varlock/assets/varlock.schema.json`, so editors can validate and autocomplete it after install.
|
|
51
|
+
- setup and overrides: `docs/configuration.md`
|
|
52
|
+
- security model and limitations: `docs/security.md`
|
|
53
|
+
- tests and validation: `docs/testing.md`
|
|
54
|
+
- exported APIs and tools: `docs/api.md`
|
|
55
|
+
- Docker + pass guide: `docs/docker-pass-guide.md`
|
|
102
56
|
|
|
103
57
|
## Repo layout
|
|
104
58
|
|
|
105
59
|
```text
|
|
106
|
-
src/
|
|
107
|
-
assets/ JSON assets
|
|
108
|
-
docs/
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
## Testing
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
npm run test:unit
|
|
115
|
-
npm run test:integration
|
|
116
|
-
npm run test:coverage
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
- `test:unit` covers config, guard, tools, and plugin registration
|
|
120
|
-
- `test:integration` starts a real OpenCode server through `@opencode-ai/sdk` and verifies the plugin inside real sessions
|
|
121
|
-
- `test:coverage` emits text, HTML, and LCOV coverage reports under `coverage/`
|
|
122
|
-
|
|
123
|
-
### Full config reference
|
|
124
|
-
|
|
125
|
-
```json
|
|
126
|
-
{
|
|
127
|
-
"guard": {
|
|
128
|
-
"enabled": true,
|
|
129
|
-
|
|
130
|
-
"sensitivePatterns": [
|
|
131
|
-
".env", ".secret", ".pem", ".key", "credentials", ".pgpass"
|
|
132
|
-
],
|
|
133
|
-
|
|
134
|
-
"sensitiveGlobs": [
|
|
135
|
-
"**/.env",
|
|
136
|
-
"**/.env.*",
|
|
137
|
-
"**/.env.local",
|
|
138
|
-
"**/.env.production",
|
|
139
|
-
"**/*.pem",
|
|
140
|
-
"**/*.key",
|
|
141
|
-
"**/credentials",
|
|
142
|
-
"**/credentials.*",
|
|
143
|
-
"**/.pgpass",
|
|
144
|
-
"secrets/**"
|
|
145
|
-
],
|
|
146
|
-
|
|
147
|
-
"bashDenyPatterns": [],
|
|
148
|
-
|
|
149
|
-
"blockedReadTools": ["read", "grep", "glob", "view"],
|
|
150
|
-
"blockedWriteTools": ["write", "edit"]
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
"env": {
|
|
154
|
-
"enabled": true,
|
|
155
|
-
"allowedRoot": "."
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
"varlock": {
|
|
159
|
-
"enabled": false,
|
|
160
|
-
"autoDetect": true,
|
|
161
|
-
"command": "varlock",
|
|
162
|
-
"namespace": "app"
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Config sections
|
|
168
|
-
|
|
169
|
-
#### `guard` — EnvGuard hook
|
|
170
|
-
|
|
171
|
-
| Field | Type | Default | Description |
|
|
172
|
-
|---|---|---|---|
|
|
173
|
-
| `enabled` | `boolean` | `true` | Master switch for the `tool.execute.before` hook |
|
|
174
|
-
| `sensitivePatterns` | `string[]` | see above | Substring patterns — a path containing any of these is blocked |
|
|
175
|
-
| `sensitiveGlobs` | `string[]` | see above | Glob patterns — matched against full paths using `*`, `**`, `?` |
|
|
176
|
-
| `bashDenyPatterns` | `string[]` | `[]` | Extra bash substrings to deny (merged with ~30 built-ins) |
|
|
177
|
-
| `blockedReadTools` | `string[]` | `["read","grep","glob","view"]` | Tool names that trigger the file-read check |
|
|
178
|
-
| `blockedWriteTools` | `string[]` | `["write","edit"]` | Tool names that trigger the file-write check |
|
|
179
|
-
|
|
180
|
-
#### `env` — .env file loader
|
|
181
|
-
|
|
182
|
-
| Field | Type | Default | Description |
|
|
183
|
-
|---|---|---|---|
|
|
184
|
-
| `enabled` | `boolean` | `true` | Register the `load_env` tool |
|
|
185
|
-
| `allowedRoot` | `string` | `"."` | Path containment boundary (resolved relative to cwd) |
|
|
186
|
-
|
|
187
|
-
#### `varlock` — Varlock integration
|
|
188
|
-
|
|
189
|
-
| Field | Type | Default | Description |
|
|
190
|
-
|---|---|---|---|
|
|
191
|
-
| `enabled` | `boolean` | `false` | Explicitly enable Varlock tools |
|
|
192
|
-
| `autoDetect` | `boolean` | `true` | Probe for the CLI at startup and enable if found |
|
|
193
|
-
| `command` | `string` | `"varlock"` | Path or name of the Varlock binary |
|
|
194
|
-
| `namespace` | `string` | `"app"` | Default namespace for `load_secrets` / `secret_status` |
|
|
195
|
-
|
|
196
|
-
**Varlock resolution logic:**
|
|
197
|
-
|
|
198
|
-
- `enabled: true` → tools are registered (fails at runtime if CLI is missing)
|
|
199
|
-
- `enabled: false, autoDetect: true` → probes `which <command>`, enables if found
|
|
200
|
-
- `enabled: false, autoDetect: false` → Varlock is fully disabled
|
|
201
|
-
|
|
202
|
-
### Config merge behavior
|
|
203
|
-
|
|
204
|
-
Arrays are **replaced**, not concatenated. This means you can fully override the default glob list in your config file without inheriting the defaults:
|
|
205
|
-
|
|
206
|
-
```json
|
|
207
|
-
{
|
|
208
|
-
"guard": {
|
|
209
|
-
"sensitiveGlobs": ["secrets/**", "config/.env.*"]
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
Object sections are deep-merged. Scalar values overwrite.
|
|
215
|
-
|
|
216
|
-
### Programmatic overrides
|
|
217
|
-
|
|
218
|
-
For project-specific customization beyond what JSON can express:
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
// .opencode/plugin/secrets.ts
|
|
222
|
-
import { createVarlockPlugin } from "opencode-varlock/plugin"
|
|
223
|
-
|
|
224
|
-
export default createVarlockPlugin({
|
|
225
|
-
guard: {
|
|
226
|
-
sensitiveGlobs: [
|
|
227
|
-
"**/.env",
|
|
228
|
-
"**/.env.*",
|
|
229
|
-
"infra/secrets/**",
|
|
230
|
-
"deploy/*.key",
|
|
231
|
-
],
|
|
232
|
-
bashDenyPatterns: ["vault read", "aws secretsmanager"],
|
|
233
|
-
},
|
|
234
|
-
varlock: {
|
|
235
|
-
enabled: true,
|
|
236
|
-
command: "/usr/local/bin/varlock",
|
|
237
|
-
namespace: "prod",
|
|
238
|
-
},
|
|
239
|
-
})
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## Glob patterns
|
|
243
|
-
|
|
244
|
-
The guard supports glob patterns alongside the existing substring patterns. Both are checked — a match on either blocks the access.
|
|
245
|
-
|
|
246
|
-
### Supported syntax
|
|
247
|
-
|
|
248
|
-
| Pattern | Matches | Example |
|
|
249
|
-
|---|---|---|
|
|
250
|
-
| `*` | Any characters except `/` | `*.pem` matches `server.pem` |
|
|
251
|
-
| `**` | Any characters including `/` | `secrets/**` matches `secrets/prod/db.key` |
|
|
252
|
-
| `**/` | Zero or more directory levels | `**/.env` matches `.env` and `config/.env` |
|
|
253
|
-
| `?` | Single character except `/` | `?.key` matches `a.key` |
|
|
254
|
-
|
|
255
|
-
### When to use which
|
|
256
|
-
|
|
257
|
-
**Substring patterns** are fast and filename-oriented. Use them for extensions and file names that should be blocked everywhere regardless of path:
|
|
258
|
-
|
|
259
|
-
```json
|
|
260
|
-
"sensitivePatterns": [".env", ".pem", "credentials"]
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
**Glob patterns** are structural and path-aware. Use them for directory-scoped rules and more precise matching:
|
|
264
|
-
|
|
265
|
-
```json
|
|
266
|
-
"sensitiveGlobs": [
|
|
267
|
-
"secrets/**",
|
|
268
|
-
"config/.env.*",
|
|
269
|
-
"deploy/**/*.key",
|
|
270
|
-
"**/node_modules/**/.env"
|
|
271
|
-
]
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### How globs are checked
|
|
275
|
-
|
|
276
|
-
For file tool calls (`read`, `write`, `edit`, etc.), the glob is matched against the path argument directly.
|
|
277
|
-
|
|
278
|
-
For bash commands, the guard extracts file-path-like tokens from the command string and checks each one against the compiled globs. This catches things like `jq . secrets/config.json` even when the substring patterns wouldn't flag it.
|
|
279
|
-
|
|
280
|
-
## Tools
|
|
281
|
-
|
|
282
|
-
### `load_env`
|
|
283
|
-
|
|
284
|
-
Parses a `.env` file and sets `process.env`. Returns only variable **names**.
|
|
285
|
-
|
|
286
|
-
```
|
|
287
|
-
Agent → load_env(path: ".env")
|
|
288
|
-
← { loaded: ["DATABASE_URL", "REDIS_HOST"], skipped: ["NODE_ENV"] }
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
### `load_secrets` (Varlock)
|
|
292
|
-
|
|
293
|
-
Pulls secrets from Varlock and injects into `process.env`.
|
|
294
|
-
|
|
295
|
-
```
|
|
296
|
-
Agent → load_secrets(namespace: "prod", keys: ["db_url", "api_key"])
|
|
297
|
-
← { loaded: ["DB_URL", "API_KEY"], source: "varlock/prod" }
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### `secret_status` (Varlock)
|
|
301
|
-
|
|
302
|
-
Read-only check of which secrets exist and which are loaded.
|
|
303
|
-
|
|
304
|
-
```
|
|
305
|
-
Agent → secret_status(namespace: "app")
|
|
306
|
-
← { total: 5, loaded: 3, unloaded: 2, keys: [...] }
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
## Permission sets
|
|
310
|
-
|
|
311
|
-
The `assets/permissions.json` file contains three tiers (standard, strict, lockdown) plus an example agent definition. Copy the tier that fits your threat model into `opencode.json`.
|
|
312
|
-
|
|
313
|
-
These permission rules complement the EnvGuard hook — the rules handle fast-path blocking while the hook catches edge cases the glob-based rules miss.
|
|
314
|
-
|
|
315
|
-
## Architecture
|
|
316
|
-
|
|
317
|
-
### Why three layers?
|
|
318
|
-
|
|
319
|
-
**Permissions alone aren't enough.** An agent can try `python3 -c "print(open('.env').read())"` or `python -c "import os; print(os.getenv('API_KEY'))"` - the obvious glob rules won't catch every runtime exfiltration path.
|
|
320
|
-
|
|
321
|
-
**Prompt instructions alone aren't enough.** Telling an agent "never read .env" is a soft boundary the model can reason past.
|
|
322
|
-
|
|
323
|
-
**The plugin hook is the hard boundary.** `tool.execute.before` runs before every built-in tool call, inspects actual arguments, and throws an error the agent cannot suppress. The error message redirects it to the approved tools.
|
|
324
|
-
|
|
325
|
-
### What the agent sees
|
|
326
|
-
|
|
327
|
-
```
|
|
328
|
-
✓ "Loaded 5 variables: DATABASE_URL, API_KEY, REDIS_HOST, JWT_SECRET, SMTP_PASS"
|
|
329
|
-
✓ Writes code: const db = new Client(process.env.DATABASE_URL)
|
|
330
|
-
✗ cat .env → Blocked: deny pattern
|
|
331
|
-
✗ echo $API_KEY → Blocked: deny pattern
|
|
332
|
-
✗ python -c "os.getenv" → Blocked: runtime env read
|
|
333
|
-
✗ python -c "open..." → Blocked: sensitive file
|
|
334
|
-
✗ jq . secrets/app.json → Blocked: matches glob "secrets/**"
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
## Advanced: composing individual pieces
|
|
338
|
-
|
|
339
|
-
Every component is exported for use in custom plugins:
|
|
340
|
-
|
|
341
|
-
```typescript
|
|
342
|
-
import { loadConfig, DEFAULT_CONFIG } from "opencode-varlock/config"
|
|
343
|
-
import { createVarlockPlugin } from "opencode-varlock/plugin"
|
|
344
|
-
import { createEnvGuard, globToRegex } from "opencode-varlock/guard"
|
|
345
|
-
import { createLoadEnvTool } from "opencode-varlock/tools"
|
|
346
|
-
|
|
347
|
-
// Load config with custom overrides
|
|
348
|
-
const config = loadConfig(process.cwd(), {
|
|
349
|
-
guard: { sensitiveGlobs: ["my-secrets/**"] },
|
|
350
|
-
})
|
|
351
|
-
|
|
352
|
-
// Use just the guard
|
|
353
|
-
const guard = createEnvGuard(config.guard)
|
|
354
|
-
|
|
355
|
-
// Use just the tool
|
|
356
|
-
const loadEnv = createLoadEnvTool(config.env)
|
|
357
|
-
|
|
358
|
-
// Test a glob pattern
|
|
359
|
-
const regex = globToRegex("**/.env.*")
|
|
360
|
-
regex.test("config/.env.production") // true
|
|
60
|
+
src/ TypeScript source
|
|
61
|
+
assets/ Packaged JSON assets
|
|
62
|
+
docs/ Guides and reference docs
|
|
63
|
+
tests/ Unit and integration tests
|
|
361
64
|
```
|
|
362
65
|
|
|
363
66
|
## License
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/itlackey/opencode-varlock/main/assets/varlock.schema.json",
|
|
3
3
|
"$comment": "opencode-varlock configuration. Place in project root or .opencode/",
|
|
4
4
|
|
|
5
5
|
"guard": {
|
package/dist/config.d.ts
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
* 3. .opencode/varlock.config.json
|
|
8
8
|
* 4. Programmatic options passed to createVarlockPlugin()
|
|
9
9
|
*/
|
|
10
|
+
export type ConfigLogger = (input: {
|
|
11
|
+
level: "debug" | "info" | "warn" | "error";
|
|
12
|
+
message: string;
|
|
13
|
+
extra?: Record<string, unknown>;
|
|
14
|
+
}) => void | Promise<void>;
|
|
10
15
|
export type GuardConfig = {
|
|
11
16
|
enabled: boolean;
|
|
12
17
|
sensitivePatterns: string[];
|
|
@@ -31,7 +36,7 @@ export type PluginConfig = {
|
|
|
31
36
|
varlock: VarlockConfig;
|
|
32
37
|
};
|
|
33
38
|
export declare const DEFAULT_CONFIG: PluginConfig;
|
|
34
|
-
export declare function loadConfig(cwd: string, overrides?: DeepPartial<PluginConfig
|
|
39
|
+
export declare function loadConfig(cwd: string, overrides?: DeepPartial<PluginConfig>, logger?: ConfigLogger): PluginConfig;
|
|
35
40
|
type DeepPartial<T> = {
|
|
36
41
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
37
42
|
};
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,WAAW,CAAA;IAClB,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,YAqC5B,CAAA;AAOD,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,WAAW,CAAC,YAAY,CAAM,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE;IACjC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE1B,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,WAAW,CAAA;IAClB,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,YAqC5B,CAAA;AAOD,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,WAAW,CAAC,YAAY,CAAM,EACzC,MAAM,CAAC,EAAE,YAAY,GACpB,YAAY,CAyCd;AAED,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAA;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACrD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,CAAC,CAyBH;AAED,YAAY,EAAE,WAAW,EAAE,CAAA"}
|
package/dist/config.js
CHANGED
|
@@ -51,7 +51,7 @@ const CONFIG_FILENAMES = [
|
|
|
51
51
|
"varlock.config.json",
|
|
52
52
|
".opencode/varlock.config.json",
|
|
53
53
|
];
|
|
54
|
-
export function loadConfig(cwd, overrides = {}) {
|
|
54
|
+
export function loadConfig(cwd, overrides = {}, logger) {
|
|
55
55
|
let merged = structuredClone(DEFAULT_CONFIG);
|
|
56
56
|
for (const filename of CONFIG_FILENAMES) {
|
|
57
57
|
const filepath = resolve(cwd, filename);
|
|
@@ -62,10 +62,21 @@ export function loadConfig(cwd, overrides = {}) {
|
|
|
62
62
|
delete parsed.$schema;
|
|
63
63
|
delete parsed.$comment;
|
|
64
64
|
merged = deepMerge(merged, parsed);
|
|
65
|
-
|
|
65
|
+
logger?.({
|
|
66
|
+
level: "info",
|
|
67
|
+
message: "loaded config",
|
|
68
|
+
extra: { filepath },
|
|
69
|
+
});
|
|
66
70
|
}
|
|
67
71
|
catch (err) {
|
|
68
|
-
|
|
72
|
+
logger?.({
|
|
73
|
+
level: "warn",
|
|
74
|
+
message: "failed to parse config",
|
|
75
|
+
extra: {
|
|
76
|
+
filepath,
|
|
77
|
+
error: err instanceof Error ? err.message : String(err),
|
|
78
|
+
},
|
|
79
|
+
});
|
|
69
80
|
}
|
|
70
81
|
}
|
|
71
82
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAc,KAAK,YAAY,EAAE,KAAK,WAAW,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAc,KAAK,YAAY,EAAE,KAAK,WAAW,EAAqB,MAAM,aAAa,CAAA;AAQhG,eAAO,MAAM,aAAa,EAAE,MAE3B,CAAA;AAED,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,WAAW,CAAC,YAAY,CAAM,GACxC,MAAM,CA4ER;AAED,eAAe,aAAa,CAAA"}
|
package/dist/plugin.js
CHANGED
|
@@ -6,16 +6,30 @@ export const VarlockPlugin = async (ctx) => {
|
|
|
6
6
|
return createVarlockPlugin()(ctx);
|
|
7
7
|
};
|
|
8
8
|
export function createVarlockPlugin(overrides = {}) {
|
|
9
|
-
return async ({ $, project, directory }) => {
|
|
9
|
+
return async ({ $, client, project, directory }) => {
|
|
10
10
|
const cwd = directory ?? process.cwd();
|
|
11
|
-
const
|
|
11
|
+
const log = async ({ level, message, extra }) => {
|
|
12
|
+
await client.app.log({
|
|
13
|
+
body: {
|
|
14
|
+
service: "opencode-varlock",
|
|
15
|
+
level,
|
|
16
|
+
message,
|
|
17
|
+
extra,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
const config = loadConfig(cwd, overrides, log);
|
|
12
22
|
let varlockAvailable = config.varlock.enabled;
|
|
13
23
|
if (!varlockAvailable && config.varlock.autoDetect) {
|
|
14
24
|
try {
|
|
15
25
|
const result = await $ `which ${config.varlock.command}`.quiet();
|
|
16
26
|
varlockAvailable = result.exitCode === 0;
|
|
17
27
|
if (varlockAvailable) {
|
|
18
|
-
|
|
28
|
+
await log({
|
|
29
|
+
level: "info",
|
|
30
|
+
message: "auto-detected varlock cli",
|
|
31
|
+
extra: { command: config.varlock.command },
|
|
32
|
+
});
|
|
19
33
|
}
|
|
20
34
|
}
|
|
21
35
|
catch {
|
|
@@ -42,7 +56,14 @@ export function createVarlockPlugin(overrides = {}) {
|
|
|
42
56
|
const guardStatus = config.guard.enabled
|
|
43
57
|
? `${config.guard.sensitivePatterns.length} patterns, ${config.guard.sensitiveGlobs.length} globs`
|
|
44
58
|
: "disabled";
|
|
45
|
-
|
|
59
|
+
await log({
|
|
60
|
+
level: "info",
|
|
61
|
+
message: "session created",
|
|
62
|
+
extra: {
|
|
63
|
+
sources: sources.join(", ") || "none",
|
|
64
|
+
guard: guardStatus,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
46
67
|
}
|
|
47
68
|
},
|
|
48
69
|
};
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,UAAU,EAA0D,MAAM,aAAa,CAAA;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,YAAY,CAAA;AAEnB,MAAM,CAAC,MAAM,aAAa,GAAW,KAAK,EAAE,GAAG,EAAE,EAAE;IACjD,OAAO,mBAAmB,EAAE,CAAC,GAAG,CAAC,CAAA;AACnC,CAAC,CAAA;AAED,MAAM,UAAU,mBAAmB,CACjC,YAAuC,EAAE;IAEzC,OAAO,KAAK,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE;QACjD,MAAM,GAAG,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAA;QAEtC,MAAM,GAAG,GAAiB,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YAC5D,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBACnB,IAAI,EAAE;oBACJ,OAAO,EAAE,kBAAkB;oBAC3B,KAAK;oBACL,OAAO;oBACP,KAAK;iBACN;aACF,CAAC,CAAA;QACJ,CAAC,CAAA;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;QAE9C,IAAI,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAA;QAC7C,IAAI,CAAC,gBAAgB,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,CAAC,CAAA,SAAS,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAA;gBAC/D,gBAAgB,GAAG,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAA;gBACxC,IAAI,gBAAgB,EAAE,CAAC;oBACrB,MAAM,GAAG,CAAC;wBACR,KAAK,EAAE,MAAM;wBACb,OAAO,EAAE,2BAA2B;wBACpC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE;qBAC3C,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,gBAAgB,GAAG,KAAK,CAAA;YAC1B,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAA4C,EAAE,CAAA;QAEzD,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;YACvB,KAAK,CAAC,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAChD,CAAC;QAED,IAAI,gBAAgB,EAAE,CAAC;YACrB,KAAK,CAAC,YAAY,GAAG,qBAAqB,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;YAC7D,KAAK,CAAC,aAAa,GAAG,sBAAsB,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QACjE,CAAC;QAED,MAAM,UAAU,GAAwB;YACtC,IAAI,EAAE,KAAK;YAEX,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAA+B,EAAE,EAAE;gBACtD,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBACrC,MAAM,OAAO,GAAa,EAAE,CAAA;oBAC5B,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO;wBAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;oBAC5C,IAAI,gBAAgB;wBAAE,OAAO,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,OAAO,CAAC,OAAO,GAAG,CAAC,CAAA;oBAEzE,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO;wBACtC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,cAAc,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,QAAQ;wBAClG,CAAC,CAAC,UAAU,CAAA;oBAEd,MAAM,GAAG,CAAC;wBACR,KAAK,EAAE,MAAM;wBACb,OAAO,EAAE,iBAAiB;wBAC1B,KAAK,EAAE;4BACL,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM;4BACrC,KAAK,EAAE,WAAW;yBACnB;qBACF,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;SACF,CAAA;QAED,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACzB,UAAU,CAAC,qBAAqB,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAClE,CAAC;QAED,OAAO,UAAU,CAAA;IACnB,CAAC,CAAA;AACH,CAAC;AAED,eAAe,aAAa,CAAA"}
|