fix(run): prevent subagent question tool hang in non-interactive mode#13974
Open
PatrickRuddiman wants to merge 4 commits intoanomalyco:devfrom
Open
fix(run): prevent subagent question tool hang in non-interactive mode#13974PatrickRuddiman wants to merge 4 commits intoanomalyco:devfrom
PatrickRuddiman wants to merge 4 commits intoanomalyco:devfrom
Conversation
Subagent sessions created by TaskTool did not inherit the parent session's deny rules (question, plan_enter, plan_exit), causing opencode run to hang indefinitely when a subagent invoked the question tool. Three changes fix this: 1. task.ts: Propagate parent session deny rules to subagent sessions so question/plan permissions are inherited. 2. prompt.ts: Merge tool-derived permissions with existing session permissions instead of replacing them, which was silently discarding the inherited deny rules. 3. run.ts: Remove sessionID filter from permission.asked handler so subagent permission requests are also auto-rejected as a safety net.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes
opencode runhanging indefinitely when a subagent (e.g.@explore) invokes thequestiontool in non-interactive mode.Fixes #11899, #10012
Related: #9554, #8852, #10746, #11932
Problem
When
opencode runcreates a session, it correctly setsquestion: deny,plan_enter: deny, andplan_exit: denypermission rules on the main session. However, subagent sessions created byTaskTooldid not inherit these deny rules, so:PermissionNext.ask()published apermission.askedevent and blocked waiting for a replyrun.tsevent handler filteredpermission.askedevents bysessionID, silently ignoring events from subagent sessions (which have different session IDs)Additionally,
SessionPrompt.prompt()overwrote the session's permission array with tool-derived permissions instead of merging, which discarded any inherited deny rules even if they were correctly propagated.Changes
Three minimal changes fix this:
packages/opencode/src/tool/task.ts— Propagate the parent session's deny rules to subagent sessions. Before creating a child session, fetch the parent session and include its deny rules in the subagent's permission array.packages/opencode/src/session/prompt.ts— Merge tool-derived permissions with existing session permissions instead of replacing them. The backwards-compattoolsfield handling was overwritingsession.permissionwith only the tool deny/allow rules, silently discarding inherited deny rules from the parent session.packages/opencode/src/cli/cmd/run.ts— Remove thesessionIDfilter from thepermission.askedevent handler so that permission requests from subagent sessions are also auto-rejected. This serves as a safety net. Thesession.errorandsession.statushandlers retain their session ID filters since those should only apply to the main session.How I verified this works
bun dev runwith a prompt that triggers the@exploresubagentquestion:deny,plan_enter:deny,plan_exit:deny) alongside the hardcoded ones (todowrite:deny,todoread:deny,task:deny)Root cause analysis
The permission system uses
findLast(last-match-wins) across a merged ruleset.run.tssets deny rules on the main session, butTaskToolcreated subagent sessions with a hardcoded permission array that only includedtodowrite,todoread, and conditionallytaskdeny rules — never propagating the parent'squestion/plan_enter/plan_exitdeny rules. Even if the rules had been propagated to the session creation,SessionPrompt.prompt()would overwrite them when converting thetoolsparameter to permission rules.Related PRs
LLM.resolveToolsto check session permissions (complementary; prevents the tool from being sent to the LLM, but doesn't help if the subagent session lacks the deny rule)run.ts)prompt.tsmerge fix (complementary; larger scope, includes tool registry filtering)