anomalyco / anomalyco/opencode

Depth-2 subagent questions are dropped by the same non-root bail-out as permissions (questions() in routes/session/index.tsx)

Open
#49,342 0 comments 0 reactions 1 assignee View on GitHub

@kommander is already working on this.

Since Sep 16, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

questions() in the TUI session route carries the identical defect reported for permissions in #39112: it returns [] for any non-root view, and it only ever reads the direct children of the viewed session. A question raised by a subagent at depth >= 2 is therefore never rendered in any view, and — as in the permission case — there is no timeout, so the turn hangs until the session is killed.

Filing this separately from #39112 so that a fix for permissions does not ship without it. #30635 was closed having fixed a single level of nesting, which is why #39112, #43996 and #44747 are all still open; questions() looks like the next half-fix waiting to happen.

Honesty about how this was found: by reading the source while investigating #39112, which I did reproduce. I have not executed the questions() path at runtime. The two memos are three lines apart and structurally identical, so I am reporting it rather than sitting on it, but please treat the repro steps below as derived, not executed.

Reachability: this needs explicit configuration. The global default is question: "deny" (packages/opencode/src/agent/agent.ts), and only the build and plan primaries get question: "allow". You need a subagent granted question, plus subagent_depth >= 2. That is the same shape of prerequisite as #39112 itself.

Source (v1.18.31)

packages/tui/src/routes/session/index.tsx:

const children = createMemo(() => {
  const parentID = session()?.parentID ?? session()?.id
  return sync.data.session
    .filter((x) => x.parentID === parentID || x.id === parentID)   // direct children only
    .toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
})
const permissions = createMemo(() => {
  if (session()?.parentID) return []                                // <- #39112
  return children().flatMap((x) => sync.data.permission[x.id] ?? [])
})
const questions = createMemo(() => {
  if (session()?.parentID) return []                                // <- this issue
  return children().flatMap((x) => sync.data.question[x.id] ?? [])
})

Two defects compound in both memos:

  1. children() collects direct children only — one level, not a recursive descendant walk. Viewed from the root it holds level-1 sessions, so a level-2 session id is never in the list.
  2. Each memo bails out entirely whenever session()?.parentID is truthy, i.e. from any non-root view — so navigating into the subagent view does not help either.

The data itself arrives and is stored correctly: packages/tui/src/context/sync.tsx keys it by the asking session's own id, and question.asked is published without a session filter (packages/opencode/src/question/index.ts). Nothing upstream of the render layer drops it.

Steps to reproduce

(Derived from source, not executed — see the note above.)

  1. Set subagent_depth: 2 or higher in opencode.json.
  2. Grant a subagent both task (so it can spawn) and question.
  3. Have it spawn a second-level subagent that is also granted question.
  4. Have the level-2 agent ask a question.

Expected: the question surfaces to the user. Actual (predicted from the code above): no dialog renders in any view and the turn does not complete.

OpenCode version

1.18.31

Suggested fix

The same patch that fixes #39112 should cover this: make children() walk descendants recursively instead of one level, and drop the if (session()?.parentID) return [] bail-out from both permissions() and questions().

Routing a nested request up to an ancestor the UI already knows about would work too, but note that PermissionV1.Request (packages/schema/src/v1/permission.ts) carries only sessionID — no parentID or rootID — so the view currently has nothing to walk up with.

Operating System

Linux

Terminal

zellij

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.