Skip to content

Adopt session.step.streamed, ./tui-only exports, and beta-19381 - #2

Merged
P-Theo merged 2 commits into
mainfrom
step-streamed-boundary
Sep 9, 2026
Merged

P-Theo merged 2 commits into
mainfrom
step-streamed-boundary

Conversation

@P-Theo

@P-Theo P-Theo commented Sep 9, 2026

Copy link
Copy Markdown
Owner

What

Five changes in two commits (code and packaging first, then docs):

  • Settled spans end at session.step.streamed. The host publishes this after the provider stream exits and before local tools join, making it the authoritative span end. It replaces the last observable content boundary, which remains the fallback for hosts that don't publish the event — so the earliest compatible beta stays 0.0.0-beta-17595. This also fixes steps with exact usage but zero observable output (Gemini signature-only thinking) settling tokens with no duration.
  • ./tui-only exports. Dropping the . export fixes opencode2 plugin add opencode2-tps misrouting the package into the server config (opencode.json) instead of the TUI config (cli.json).
  • Beta 0.0.0-beta-176390.0.0-beta-19381, new @opencode scope. The type import moves to @opencode/plugin/tui; the compat script, CI, and Renovate follow the scope. The new SDK floors the @opentui/{core,solid} dev dependencies at 0.5.10 — the runtime peer range stays >=0.5.4 because the SDK import is type-only and hosts supply their own copies.
  • tui.tsx source entry. Current betas resolve a path entry as <directory>/tui.tsx and skip entries that point at a file, so the repository root gains a re-export shim that lets a path entry load the source. The tarball ships only dist, so it never reaches the package.
  • Docs. Installation now leads with opencode2 plugin add, which works with the ./tui-only export map introduced in this PR. The docs also describe the streamed boundary, correct the current tool-input event behavior, explain why this plugin's settled t/s can differ from OpenCode's built-in figure, and document the current host cache layout (~/.cache/opencode/npm/<name>@<spec>/<generation>/, newest generation winning) for installs, upgrades, and the release runbook.

Why the streamed boundary

The last content boundary is an approximation of the stream end: it is the final text/reasoning/tool.input block-ended event, which can fire well before the stream exits, and it is missing entirely when a step produces no observable content. session.step.streamed is exact by construction.

It also aligns the denominator with OpenCode's own assistant-footer t/s, which divides visible output tokens by time.streamed - time.created. This plugin keeps its inclusive numerator (tokens.output + tokens.reasoning), so the two figures differ in what they count, not in how time is measured. On a nine-step gpt-5.6-luna turn with 523 visible and 985 hidden reasoning tokens over 28.84s of streamed spans, the built-in figure reads 18.1 t/s while this plugin settles at ~52 t/s.

Compatibility

  • Older betas degrade gracefully: subscribing to session.step.streamed on a host that never publishes it is a no-op, and settlement falls back to the content boundary. The earliest compatible beta stays 0.0.0-beta-17595.
  • The retry edge is unchanged: a retried step reusing an assistantMessageID keeps the first attempt's startedAt; markStreamed is last-wins, so the boundary follows the latest attempt.

Verification

  • Local: lint, typecheck against @opencode/plugin@0.0.0-beta-19381, all 57 tests, build, and the compatibility check all pass.
  • New tests cover the streamed boundary and its fallback, zero-output steps, tool-execution gaps, failed and interrupted steps, retry last-wins, mismatched steps, provider-shaped traces (OpenAI Responses, Anthropic, Gemini), the subscription wiring, and replay dedup.
  • CI's packed-artifact check imports dist/tui.js by path, so it does not exercise the exports map. That contract is covered by a local Node resolution test and by release runbook step 5, which installs the packed tarball from the registry before publishing.

Version bump and publish follow the release runbook after merge.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The streamed-boundary change is integrated end-to-end (tracker logic + event wiring) with strong, targeted test coverage and the packaging/scope updates are consistently applied across CI, tooling, and documentation.

Pull request overview

This PR updates the plugin’s settled-span timing to use the host-published session.step.streamed boundary (with a fallback for older hosts), adjusts packaging to export only the ./tui entrypoint, and bumps OpenCode-related dependencies to the new @opencode/* scope and 0.0.0-beta-19381, with corresponding documentation/runbook updates.

Changes:

  • Track and prefer session.step.streamed as the authoritative end-of-stream timestamp when settling step durations, falling back to the last observable content boundary when absent.
  • Update packaging/export surface to ./tui only and add a repo-root tui.tsx source entrypoint for directory-based path loading.
  • Bump OpenCode SDK deps to @opencode/* 0.0.0-beta-19381 and refresh CI, Renovate, and docs to match (including updated install guidance).
File summaries
File Description
tui.tsx Adds a repo-root source entrypoint that re-exports the plugin definition for directory-based path loading.
tsconfig.json Includes tui.tsx in the TypeScript project inputs.
tps.tsx Implements streamed-boundary tracking (markStreamed) and uses it for settled duration computation; wires up the new event subscription.
tps.test.ts Adds comprehensive tests for streamed-boundary behavior, fallback behavior, retries, gaps, and subscription wiring/dedup.
renovate.jsonc Updates Renovate rules to track the new @opencode/* package names.
README.md Updates install instructions (lead with opencode2 plugin add), tested beta version, cache location details, and streamed-boundary explanation.
package.json Drops "." export and keeps only "./tui" export; bumps devDependencies to @opencode/* and updates @opentui/* floors.
docs/release.md Updates the release runbook to reflect host cache generations and ./tui export-based loading.
docs/development.md Updates source-run instructions to use a directory path entry and documents streamed-boundary semantics and tool-input event behavior.
check-compatibility.mjs Updates compatibility package list to @opencode/*.
.github/workflows/ci.yml Updates CI paths and version extraction for the new @opencode/cli package location/name.
Review details
  • Files reviewed: 10/12 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@P-Theo
P-Theo force-pushed the step-streamed-boundary branch from 0bd75fd to 3290760 Compare September 9, 2026 19:20
@P-Theo
P-Theo requested a balanced review from Copilot September 9, 2026 19:42

This comment was marked as low quality.

@P-Theo
P-Theo merged commit 8e49c85 into main Sep 9, 2026
1 check passed
@P-Theo
P-Theo deleted the step-streamed-boundary branch September 9, 2026 19:47
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.

2 participants