@agent-guardrails/opencode-shell-warden-hook 0.2.0 → 0.2.1
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/package.json +1 -1
- package/src/apply.ts +9 -4
- package/src/index.ts +11 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-guardrails/opencode-shell-warden-hook",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "OpenCode V2 hook plugin: forwards shell permission decisions to the shell-warden engine over NDJSON JSON-RPC stdio",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/apply.ts
CHANGED
|
@@ -27,24 +27,29 @@ export function cacheKey(action: string, resources: readonly string[], cwd: stri
|
|
|
27
27
|
.digest("hex")
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/** Letter per 02-letter-verdict.md §2.2 — exactly the schema fields, no extras.
|
|
30
|
+
/** Letter per 02-letter-verdict.md §2.2 — exactly the schema fields, no extras.
|
|
31
|
+
* `projectDir` is required and non-empty: the engine invalidates every letter whose
|
|
32
|
+
* commands[].cwd is empty ("letter commands[0].cwd must be 1..4096 chars"), and the
|
|
33
|
+
* ask payload carries no per-command cwd — the permission request's directory is the
|
|
34
|
+
* only cwd the shim has. Callers without a directory must degrade before calling. */
|
|
31
35
|
export function buildLetter(args: {
|
|
32
36
|
data: AskData
|
|
33
37
|
invocationId: string
|
|
34
|
-
projectDir
|
|
38
|
+
projectDir: string
|
|
35
39
|
agent?: string
|
|
36
40
|
}): Letter {
|
|
37
41
|
const { data, invocationId, projectDir, agent } = args
|
|
42
|
+
if (!projectDir) throw new Error("buildLetter: projectDir is required — the engine rejects letters with an empty commands[].cwd")
|
|
38
43
|
return {
|
|
39
44
|
version: 1,
|
|
40
45
|
invocation: {
|
|
41
46
|
id: invocationId,
|
|
42
47
|
sessionID: data.sessionID ?? "",
|
|
43
48
|
...(agent !== undefined ? { agent } : {}),
|
|
44
|
-
|
|
49
|
+
projectDir,
|
|
45
50
|
},
|
|
46
51
|
action: data.action ?? "",
|
|
47
|
-
commands: (data.resources ?? []).map((raw, index) => ({ index, raw, cwd:
|
|
52
|
+
commands: (data.resources ?? []).map((raw, index) => ({ index, raw, cwd: projectDir })),
|
|
48
53
|
}
|
|
49
54
|
}
|
|
50
55
|
|
package/src/index.ts
CHANGED
|
@@ -80,8 +80,17 @@ export default Plugin.define({
|
|
|
80
80
|
try {
|
|
81
81
|
if (!(cfg.actionsAll || cfg.actions.includes(d.action))) continue
|
|
82
82
|
const invocationId = invocationIdOf(d.source, d.sessionID, d.action)
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
// The ask payload carries no per-command cwd; the permission event's
|
|
84
|
+
// location is the only directory the shim has. Letters with an empty
|
|
85
|
+
// commands[].cwd are rejected by the engine, so without one we degrade —
|
|
86
|
+
// never spawn a letter the engine would refuse.
|
|
87
|
+
const projectDir = loc || myLocation || ""
|
|
88
|
+
if (!projectDir) {
|
|
89
|
+
log("warn", `no project directory for ${invocationId} — degrade (${cfg.onCheckerError})`)
|
|
90
|
+
if (cfg.onCheckerError === "deny") await reply(d.sessionID, d.id, "reject", undefined).catch(() => {})
|
|
91
|
+
continue
|
|
92
|
+
}
|
|
93
|
+
const key = cacheKey(d.action, d.resources, projectDir)
|
|
85
94
|
|
|
86
95
|
if (cfg.cache.enabled) {
|
|
87
96
|
const cached = cache.get(key)
|