Skip to content

fix(permissions): read permission and question subjects from the 1.18.30 payload - #14

Merged
Juliusolsson05 merged 4 commits into
mainfrom
fix/permission-question-subject
Sep 19, 2026
Merged

Juliusolsson05 merged 4 commits into
mainfrom
fix/permission-question-subject

Conversation

@Juliusolsson05

@Juliusolsson05 Juliusolsson05 commented Sep 19, 2026 •

Copy link
Copy Markdown
Owner

Problem

Juliusolsson05/agent-code#878. The structured runtime's permission modal showed no subject, so users approved bash: ls -1 blind, and the question modal showed no question. OpenCode is bundled in Agent Code now, so this is on the default path and a release blocker.

The payload shape (permission, patterns, metadata.command, an object tool, and questions[].question) is present since at least 1.14 and is recorded on 1.18.30. Neither parser matched it:

  • the dispatcher's first-non-null walk stopped at the object tool;
  • the pending-request builder had no key that exists in this shape.

Implemented

src/permissions/subject.ts is one parser, shared by the dispatcher (the modal) and OpencodeHeadless (the pending request).

  • bash shows the whole metadata.command, the same as OpenCode's own UI ($ <command>). patterns skips cd/pushd/export, so building the subject from it can hide part of what runs.
  • Other kinds show permission: patterns, for example edit: src/a.ts or webfetch: <url>.
  • A wildcard-only ["*"] (MCP, todowrite, lsp) shows the tool name alone.
  • Questions read questions[].question, one line per question.
  • Legacy keys stay as string-only fallbacks for 0.x servers, so an object can never shadow a later key again.

Verification

  • Replays of recorded OpenCode 1.18.30 SSE streams (testing/fixtures/live-1.18.30, provenance in its README) run through the real EventDispatcher and channels. On the unfixed code, the modal title and the question text were undefined.
  • Correction to the first version of this body: the test-only commit fails with Cannot find module './subject.js'. The subject failures quoted there came from running the new test against a stub.
  • Two more cases are derived from the recorded event by a visible transformation: a compound cd … && npm test command, and an MCP ["*"] ask. Both failed first.
  • Package suite 19/19; tsc --noEmit and test:contract are clean.
  • Not tested, stated honestly: the legacy 0.x fallbacks. No recording of a 0.x server exists, and a hand-typed payload would only test my own guess. Also untested: that OpencodeHeadless.handleSseMessage calls the shared function. It is a direct import, but no test drives the SSE handler.

Review (independent, round 1) → resolved

  1. Fixed: the bash subject could hide part of the command. It is the full command now.
  2. Fixed: the wildcard-only subject.
  3. Fixed: the inaccurate WHY comment and PR claims.

Three app-side follow-ups ship in Agent Code's submodule-bump PR:

  • a long command must scroll inside the modal, not push its buttons off-screen;
  • "Allow always" must show its real scope;
  • questions are now visible but still cannot be answered. That one becomes its own issue.

🤖 Generated with Claude Code

Juliusolsson05 and others added 4 commits September 18, 2026 23:27
Refs Juliusolsson05/agent-code#878

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… question subjects

Real OpenCode 1.18.30 SSE recordings are copied unchanged from
opencode-terminal-headless's Stage 0 live probe. They are replayed through
the real EventDispatcher and channels. Before the fix, the permission
title, the question text and the pending request's subject were all
undefined.

Refs Juliusolsson05/agent-code#878

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
….30 payload

OpenCode 1.18.30 sends permission.asked as { permission, patterns, tool:
{...} } and nests question text in questions[].question. Both readers
walked keys first-non-null, so the now-object tool field stopped the walk
and blanked the subject. The modal asked for permission without saying
what for.

One shared parser (permissions/subject.ts) now serves the dispatcher and
the pending-request path. It builds 'bash: ls -1' from permission and
patterns, reads questions[].question, and keeps the older keys as
string-only fallbacks, so an object can never shadow a later key again.

Refs Juliusolsson05/agent-code#878

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… subjects

Review of #14: the bash subject was built from patterns. Those hold only
the command nodes OpenCode collects, skipping cd/pushd and declarations
like export, so 'export NODE_OPTIONS=... && git status' still showed as
'bash: git status'. That is the blind approval this fix exists to
prevent. bash now shows metadata.command, as OpenCode's own UI does.

MCP, todowrite and lsp asks send patterns ['*'], which rendered as
'tool: *' and read like a request for everything; the tool name alone is
the subject now.

The WHY comment is also corrected: the payload shape predates 1.18.30,
and the pending-request builder never matched rather than being stopped
by the tool object.

Refs Juliusolsson05/agent-code#878

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Juliusolsson05
Juliusolsson05 merged commit 62440ad into main Sep 19, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant