fix(shell): keep shell config consistent
Treat shell access as one logical toggle during agent creation and apply bash compatibility rules before explicit per-shell overrides. This avoids disabling the active Windows shell unexpectedly and keeps pwsh and powershell overrides deterministic.
This commit is contained in:
parent
2eb9ae4d34
commit
32ec3666b7
3 changed files with 46 additions and 50 deletions
|
|
@ -9,24 +9,12 @@ import fs from "fs/promises"
|
|||
import { Filesystem } from "../../util/filesystem"
|
||||
import matter from "gray-matter"
|
||||
import { Instance } from "../../project/instance"
|
||||
import { ShellTool } from "../../tool/shell/id"
|
||||
import { EOL } from "os"
|
||||
import type { Argv } from "yargs"
|
||||
|
||||
type AgentMode = "all" | "primary" | "subagent"
|
||||
|
||||
const AVAILABLE_TOOLS = [
|
||||
...ShellTool.ids,
|
||||
"read",
|
||||
"write",
|
||||
"edit",
|
||||
"list",
|
||||
"glob",
|
||||
"grep",
|
||||
"webfetch",
|
||||
"task",
|
||||
"todowrite",
|
||||
]
|
||||
const AVAILABLE_TOOLS = ["bash", "read", "write", "edit", "list", "glob", "grep", "webfetch", "task", "todowrite"]
|
||||
|
||||
const AgentCreateCommand = cmd({
|
||||
command: "create",
|
||||
|
|
|
|||
|
|
@ -276,46 +276,30 @@ export namespace Permission {
|
|||
return pattern
|
||||
}
|
||||
|
||||
function pushRules(ruleset: Ruleset, permission: string, value: Config.PermissionRule) {
|
||||
if (typeof value === "string") {
|
||||
ruleset.push({ permission, action: value, pattern: "*" })
|
||||
return
|
||||
}
|
||||
|
||||
ruleset.push(
|
||||
...Object.entries(value).map(([pattern, action]) => ({ permission, pattern: expand(pattern), action })),
|
||||
)
|
||||
}
|
||||
|
||||
export function fromConfig(permission: Config.Permission) {
|
||||
const ruleset: Ruleset = []
|
||||
|
||||
const bash = permission["bash"]
|
||||
if (bash !== undefined) {
|
||||
pushRules(ruleset, "bash", bash)
|
||||
pushRules(ruleset, "pwsh", bash)
|
||||
pushRules(ruleset, "powershell", bash)
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(permission)) {
|
||||
if (key === "bash") {
|
||||
if (typeof value === "string") {
|
||||
ruleset.push({ permission: "bash", action: value, pattern: "*" })
|
||||
ruleset.push({ permission: "pwsh", action: value, pattern: "*" })
|
||||
ruleset.push({ permission: "powershell", action: value, pattern: "*" })
|
||||
} else {
|
||||
ruleset.push(
|
||||
...Object.entries(value).map(([pattern, action]) => ({
|
||||
permission: "bash",
|
||||
pattern: expand(pattern),
|
||||
action,
|
||||
})),
|
||||
)
|
||||
ruleset.push(
|
||||
...Object.entries(value).map(([pattern, action]) => ({
|
||||
permission: "pwsh",
|
||||
pattern: expand(pattern),
|
||||
action,
|
||||
})),
|
||||
)
|
||||
ruleset.push(
|
||||
...Object.entries(value).map(([pattern, action]) => ({
|
||||
permission: "powershell",
|
||||
pattern: expand(pattern),
|
||||
action,
|
||||
})),
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
ruleset.push({ permission: key, action: value, pattern: "*" })
|
||||
continue
|
||||
}
|
||||
ruleset.push(
|
||||
...Object.entries(value).map(([pattern, action]) => ({ permission: key, pattern: expand(pattern), action })),
|
||||
)
|
||||
if (key === "bash") continue
|
||||
pushRules(ruleset, key, value)
|
||||
}
|
||||
return ruleset
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,30 @@ test("fromConfig - mixed string and object values", () => {
|
|||
])
|
||||
})
|
||||
|
||||
test("fromConfig - explicit pwsh overrides bash regardless of key order", () => {
|
||||
const result = Permission.fromConfig({
|
||||
pwsh: "deny",
|
||||
bash: "allow",
|
||||
})
|
||||
expect(result).toEqual([
|
||||
{ permission: "bash", pattern: "*", action: "allow" },
|
||||
{ permission: "pwsh", pattern: "*", action: "allow" },
|
||||
{ permission: "powershell", pattern: "*", action: "allow" },
|
||||
{ permission: "pwsh", pattern: "*", action: "deny" },
|
||||
])
|
||||
expect(Permission.evaluate("pwsh", "ls", result).action).toBe("deny")
|
||||
expect(Permission.evaluate("bash", "ls", result).action).toBe("allow")
|
||||
})
|
||||
|
||||
test("fromConfig - explicit powershell pattern overrides bash pattern regardless of key order", () => {
|
||||
const result = Permission.fromConfig({
|
||||
powershell: { "rm *": "deny" },
|
||||
bash: { "*": "allow", "rm *": "ask" },
|
||||
})
|
||||
expect(Permission.evaluate("powershell", "rm foo", result).action).toBe("deny")
|
||||
expect(Permission.evaluate("pwsh", "rm foo", result).action).toBe("ask")
|
||||
})
|
||||
|
||||
test("fromConfig - empty object", () => {
|
||||
const result = Permission.fromConfig({})
|
||||
expect(result).toEqual([])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue