fix(opencode): let subagents use their own permissions (#31696)

This commit is contained in:
Aiden Cline
2026-06-10 09:26:08 -05:00
committed by GitHub
parent e4300e9b74
commit 3ad6923c61
5 changed files with 50 additions and 84 deletions
+3
View File
@@ -160,6 +160,9 @@ export const layer = Layer.effect(
Permission.fromConfig({
question: "allow",
plan_exit: "allow",
task: {
general: "deny",
},
external_directory: {
[path.join(Global.Path.data, "plans", "*")]: "allow",
},
@@ -1,31 +1,23 @@
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
import type { Permission } from "../permission"
import type { Agent } from "./agent"
/**
* Build the `permission` ruleset for a subagent's session when it's spawned
* via the task tool. Combines:
*
* 1. The parent **agent's** edit-class deny rules — Plan Mode's file-edit
* restriction lives on the agent ruleset, not on the session, so a
* subagent that only inherited the parent SESSION's permission would
* silently bypass it. (#26514)
* 2. The parent **session's** deny rules and external_directory rules —
* same forwarding the original code already did.
* 3. Default `todowrite` and `task` denies if the subagent's own ruleset
* 1. The parent session's deny rules and external_directory rules.
* Parent agent restrictions only govern that agent; the subagent's own
* permissions determine its capabilities.
* 2. Default `todowrite` and `task` denies if the subagent's own ruleset
* doesn't already permit them.
*/
export function deriveSubagentSessionPermission(input: {
parentSessionPermission: PermissionV1.Ruleset
parentAgent: Agent.Info | undefined
subagent: Agent.Info
}): PermissionV1.Ruleset {
const canTask = input.subagent.permission.some((rule) => rule.permission === "task")
const canTodo = input.subagent.permission.some((rule) => rule.permission === "todowrite")
const parentAgentDenies =
input.parentAgent?.permission.filter((rule) => rule.action === "deny" && rule.permission === "edit") ?? []
return [
...parentAgentDenies,
...input.parentSessionPermission.filter(
(rule) => rule.permission === "external_directory" || rule.action === "deny",
),