Skip to content

feat(opencode): build opencode-terminal-headless so OpenCode Terminal agents report status and serve MCP reads #864

Closed

Description

@Juliusolsson05

Motivation

The OpenCode Terminal runtime (providerRuntime: 'terminal', #754/#755) runs the native OpenCode TUI in a bare PTY and gives Agent Code none of the signals the rest of the app runs on:

  • process-state is only ever { active: false }, and no semantic events or committed transcript entries are sent. Every status surface therefore shows the agent as idle from spawn to exit: pane header, tab bar, Dispatch, Agent Status, the close-confirmation and provider-switch guards (bug(opencode): OpenCode Terminal runtime sessions never report running #857).
  • orchestration_wait_agents always runs to its timeout. orchestration_read_agent, agent_management_read_agent and Reader/Copy Last Response come back empty, because runtime.entries is never filled.
  • Pending permission and question prompts never raise the Dispatch ACTION/QUESTION badge.
  • The agent_transcript_* tools cannot read any OpenCode session, and parked OpenCode agents fail with transcript_unavailable because the OpenCode registry has no history source.

Claude Code and Codex solve this with PTY headless packages (claude-code-headless, codex-headless) that read durable transcript and live channels and publish one event stream. OpenCode Terminal needs the same thing.

Intended behavior

A new package, opencode-terminal-headless (its own repository, added as a submodule under packages/), copies the structure of the other PTY headless packages. The caller passes in the PTY, and the package reads OpenCode's channels:

  • Durable channel: OpenCode's own SQLite event log, opened read-only. Since 1.18.x every session keeps an append-only event log with a gapless per-session seq, written in the same transaction as the message/part rows. It is tailed by seq cursor and becomes committed { info, parts } messages. This is the same record shape the structured runtime, opencode export, the renderer mapper and agent-transcript-parser already use.
  • Live channel: the TUI's own HTTP/SSE server, reachable when the TUI is launched with --hostname 127.0.0.1 --port <free> and a per-spawn OPENCODE_SERVER_PASSWORD. It carries the state OpenCode never writes to disk: session.status (busy/idle/retry) and permission/question requests, which can be answered over HTTP.
  • No screen mirror. Parsing the OpenTUI screen would be the most expensive and least reliable part.

Each signal has exactly one owner: the durable log owns committed history, and the live channel owns activity, turn boundaries and conditions. The live channel also tells the durable reader when to read, so a connected pane never polls.

The PR #755 rule "never read OpenCode's private database" applied to the structured runtime's write/transform boundary. This package only reads, and gates on schema and event versions. Writes (switch, duplicate, rewind, session creation) keep going through opencode import/export.

Acceptance criteria

  • The new opencode-terminal-headless repo copies the claude/codex package layout (launch/, terminal/, transcript/, live/, channels/, conditions/) and the shared testing contract. Its README states that it exists to match Agent Code's provider shape, not as a general OpenCode SDK.
  • The durable reader rebuilds committed { info, parts } messages from recorded real event logs. The expected output is checked against OpenCode's own message/part projection, not against the reader itself.
  • The live reader maps session.status and permission/question events into activity, turn and condition state, using recorded server event sequences.
  • While a turn runs, OpenCode Terminal panes report running (process-state, stream_phase, turn_started/turn_completed) and idle when it ends. The committed assistant message lands before the final idle.
  • orchestration_wait_agents, orchestration_read_agent and agent_management_read_agent (live and parked) return real output for OpenCode Terminal agents.
  • Pending permission and question prompts raise the Dispatch attention badge and can be answered through the existing condition-resolution path.
  • agent_transcript_read_file, agent_transcript_search_file and agent_transcript_inspect_file accept an opencode://session/<id> locator.
  • Unsupported OpenCode versions (no event log) or schemas fail closed with a diagnostic and today's behavior, not wrong data.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions