Repository navigation
feat(opencode): build opencode-terminal-headless so OpenCode Terminal agents report status and serve MCP reads #864
Description
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-stateis 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_agentsalways runs to its timeout.orchestration_read_agent,agent_management_read_agentand Reader/Copy Last Response come back empty, becauseruntime.entriesis 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 withtranscript_unavailablebecause 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
eventlog with a gapless per-sessionseq, written in the same transaction as themessage/partrows. It is tailed byseqcursor 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-spawnOPENCODE_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-headlessrepo 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 ownmessage/partprojection, not against the reader itself. - The live reader maps
session.statusand 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_agentandagent_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_fileandagent_transcript_inspect_fileaccept anopencode://session/<id>locator. - Unsupported OpenCode versions (no event log) or schemas fail closed with a diagnostic and today's behavior, not wrong data.
Related
- Fixes bug(opencode): OpenCode Terminal runtime sessions never report running #857 (the runtime never reports running).
- Refs bug(terminal): OpenCode terminal panes lose mouse tracking and cannot scroll or jump to latest #843: a known server URL enables
/tui/execute-command, the route that issue recommends for jump-to-latest. - Refs Add native-mode surface for Agent Code terminal/hybrid rendering opencode-headless#3: that issue asked for a native-mode surface. This package provides it without turning opencode-headless into a terminal wrapper.
- Refs feat(opencode): add separately spawnable terminal runtime #754, feat(opencode): add terminal runtime and transcript switching #755.
Activity
test(harness): run the replay harness from DOM-emulating host tests
docs(opencode): tick the verification and PR steps
test(runtime): split the end-to-end suite by behavioral owner
fix(opencode): stop hiding OpenCode read failures and harden the adap…
fix(mcp): report OpenCode answers, writes and patches as OpenCode mea…
merge: bring OpenCode export integrity up to date with main
fix(opencode): give transcript transforms a large-conversation CLI de…
fix(opencode): let the pane say its server came up after all