feat(orchestrator): Add OpenCode 2 provider support - #5251
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
d6420ac to
6c8f5a0
Compare
There was a problem hiding this comment.
Effect service conventions review of the new OpenCode 2 service modules. Two findings; everything else (namespace effect/* imports, TextGeneration["Service"] usage, Context.Reference + layer in ProviderInteractionModeReflections.ts, scoped layer wiring) looks consistent with the conventions.
Posted via Macroscope — Effect Service Conventions
There was a problem hiding this comment.
Effect service conventions review of the new OpenCode 2 service modules. Six findings, all in newly added service code (runtime service module, reaper service, text-generation implementation). The adapter/driver wiring, ProviderInteractionModeReflections, and the client-runtime/mobile changes look consistent with the conventions.
Posted via Macroscope — Effect Service Conventions
6c8f5a0 to
4b51274
Compare
There was a problem hiding this comment.
One convention finding on the new OpenCode 2 service module. Everything flagged in earlier runs (inline Context.Service interfaces, structured OpenCode2RuntimeError/SpawnedProcessReaperError attributes, no raw server output or credential text in detail, retry classification on a structural category) is addressed in this head.
Posted via Macroscope — Effect Service Conventions
d21ef22 to
187dc69
Compare
There was a problem hiding this comment.
One finding on the new OpenCode 2 provider probe: the probe wrapper copies its cause's message into a detail field and builds the caller-visible status message from it.
Posted via Macroscope — Effect Service Conventions
There was a problem hiding this comment.
One finding on the new OpenCode 2 provider probe: the probe wrapper copies its cause's message into a detail field and builds the caller-visible status message from it.
Posted via Macroscope — Effect Service Conventions
187dc69 to
4e3e6e7
Compare
4e3e6e7 to
946af28
Compare
946af28 to
be938c2
Compare
a543fd4 to
378615b
Compare
be938c2 to
3a0b167
Compare
There was a problem hiding this comment.
Reviewed the new Effect service modules (opencode2Runtime.ts, SpawnedProcessReaper.ts, ProviderInteractionModeReflections.ts) and the OpenCode 2 provider/adapter/text-generation call sites against the service conventions. The earlier findings are resolved: both new service modules now declare their interface inline in Context.Service and export make/layer, OpenCode2RuntimeError carries a structured operation + category with a message derived from them (plus export const isOpenCode2RuntimeError = Schema.is(...)), and OpenCode2TextGeneration uses static detail strings with the real cause preserved and retries on the structural category instead of message text.
One small residual item on error construction is noted inline.
Posted via Macroscope — Effect Service Conventions
3a0b167 to
83f7b4c
Compare
There was a problem hiding this comment.
One finding: a newly added single-tag recovery uses Effect.catch with a hand-rolled schema predicate instead of Effect.catchTags. Everything previously flagged in this check (canonical make/layer in opencode2Runtime.ts, inline Context.Service interfaces, structured OpenCode2RuntimeError/SpawnedProcessReaperError attributes, static wrapper details with preserved cause, structural retry classification) now looks resolved.
Posted via Macroscope — Effect Service Conventions
83f7b4c to
e7c9b05
Compare
190c610 to
eb9ae77
Compare
There was a problem hiding this comment.
One convention issue found: the new opencode2Runtime service module is imported with an aliased layer in several wiring/test files, which erases the module namespace that the rest of the PR uses.
Posted via Macroscope — Effect Service Conventions
eb9ae77 to
7ca4193
Compare
There was a problem hiding this comment.
One finding: a warning log in the new OpenCode 2 adapter copies arbitrary provider error text into a detail log field, while every other log site in the same file uses the sanitized errorTag/structural fields. Everything else in the new Effect service surface (provider/opencode2Runtime.ts, provider/SpawnedProcessReaper.ts, orchestration-v2/ProviderInteractionModeReflections.ts and its worker) follows the canonical module order, inline Context.Service interfaces, make + layer exports, environment-based dependency acquisition, Schema.TaggedErrorClass failures with structural attributes and preserved causes, and Effect.catchTags for known tags.
Posted via Macroscope — Effect Service Conventions
7ca4193 to
655c107
Compare
There was a problem hiding this comment.
Reviewed the new Effect service modules (provider/opencode2Runtime.ts, provider/SpawnedProcessReaper.ts, orchestration-v2/ProviderInteractionModeReflections.ts), the OpenCode 2 driver/provider/adapter/text-generation code, and the mechanically updated layer wiring and call sites. The canonical make/layer exports, inline Context.Service interfaces, Foo["Service"] references, structured Schema.TaggedErrorClass failures with bounded category/operation attributes, Schema.is predicates, and Effect.catchTags usage all match the conventions now. One remaining wrapper still builds its detail from the cause's message.
Posted via Macroscope — Effect Service Conventions
655c107 to
6188c82
Compare
e24b59c to
4213ac5
Compare
6188c82 to
c92c468
Compare
OpenCode 2 documents /api/event as volatile under a slow consumer. Protocol logging blocked the pull path, so long turns filled the TCP buffer and the UI never projected tools, text, or forms. Stop also hung because interrupt waited forever for session.execution.interrupted on that dead stream. Keep protocol logs off the SSE path, resubscribe on failure or stall with a bounded budget, adopt missing execution.started when the turn already has parts, and force-finalize interrupted turns after a settle timeout so Stop always returns the run to a terminal state. Live: opencode2-settlement and opencode2-interrupt-direct-stop pass against private serve on this tree (manual guide: OpenCode 2 · baseline 1-2, OpenCode 2 · interrupt 1-3).
Track @opencode-ai/sdk@0.0.0-beta-202608061351 while remaining compatible with next-16909 session.* events via openCode2Wire. Update text generation for admit/wait/context, prefer /global/health for version, and adapt Session3 API gaps (messages, stubs).
Accept only session.next.* and still-current permission/question events. Remove form API mapping and rewrite replay fixtures to the beta event names and prompt payload shape.
Beta servers mint auth into XDG state (not always the banner), skip missing MCP routes, and must isolate XDG data so session.prompt does not 500 against a shared desktop opencode.db. Also fix TestClock-safe password grace and replay/testkit subscribe ordering for the beta wire surface.
Managed spawns isolate the opencode DB so they do not fight the desktop
service, but next-line stores provider credentials in that DB. Seed those
credentials (and auth JSON) from the host on spawn so glm-5.2 and other
paid models still appear after progressive model refresh. Also post
session.prompt as a flat { text } body: next-16916 rejects the nested
prompt field the beta SDK still maps, and no co-published SDK pin exists
for 0.0.0-next-16916 yet.
Accept short session.step/text/tool event names alongside session.next.*, read tool call keys from data.id when callID is absent, and settle on session.execution.interrupted so Stop matches the pinned next-16916 wire. Also type host credential seed binds as SQLInputValue for Check green. Live: opencode2-settlement and opencode2-interrupt-direct-stop pass on private serve with T3_MODEL=opencode/glm-5.2 against opencode2 v0.0.0-next-16916 (run 20260806-142805).
Make openCode2EventEndsExecution respect tool-calls finish so intermediate step.ended events do not clear activeExecution or settle wakes. Insert a newline when stdout/stderr chunks interleave without one so startup banner regex anchors still match. Seed managed OpenCode data with VACUUM INTO, refresh credentials in a transaction, and revoke managed auth files and credential rows when the host removes them.
Bring the current feat/opencode2-provider tip (e98b4fe) onto trial: sdk-next beta pin, dual wire normalize, SSE/Stop recovery, host auth seed hardening, step-finish wake gating, and scenario subagent deadline.
pnpm 11 defaults minimumReleaseAge to 1440 minutes. Same-day pins of @opencode-ai/sdk@0.0.0-beta-202608061351 fail real-pnpm installs until they mature unless listed in minimumReleaseAgeExclude, matching Clerk and Effect hygiene.
Summary
provider, using a separate
opencode2driver/runtime/adapter and@opencode-ai/sdk-next/v2(this branch is the sole consumer of the pinnpm:@opencode-ai/sdk@0.0.0-beta-202608061351).provider settings, model selection, reasoning variants, Build/Plan mode,
permissions, questions, Queue, Stop, background work, subagents, lineage,
replay, web, desktop, and mobile.
observed a complete, stable inventory.
(
session.step.*,session.text.*, tools,session.execution.interrupted)plus earlier beta
session.next.*aliases, including tool call keys fromdata.idwhencallIDis absent.opencode2 v0.0.0-next-16916(@opencode-ai/cli@0.0.0-next-16916), not afloating
@nextinstall. Channel advisories for@opencode-ai/cli@nextremainavailable for recognized package managers, but operators should pin the binary
they validate against.
This draft targets
t3code/codex-turn-mapping.Problem and Fix
opencode2driver, runtime, adapter, provider layer, and text-generation backend using@opencode-ai/sdk-next/v2. OpenCode 1.x remains unchanged and both providers can be configured together.question/question.v2wire (not the removed form API).latestchannel, while OpenCode 2 ships onnextand the wire moves between next builds; blindly floating@nextcan break the adapter, and an npm update may not own the configured executable.nextdist-tag with a channel-isolated cache key. Offer one-click updates only for recognized npm, Bun, pnpm, and Vite Plus paths; keep custom paths and external servers manual-only. Document and prefer an exact CLI pin (currently0.0.0-next-16916) for environments that need a known contract.Defensive Fixes
opencode2.exeas a placeholder that requires postinstall replacement, and Bun blocks dependency lifecycle scripts unless the package is trusted.--trustand pnpm's package-scoped build approval, and preserve the default script-running behavior for npm and Vite Plus.__proto__,constructor, andtoString.Object.prototype.false.nextbuild and bypass the adapter's verified protocol floor.yield*orEffect.flatMapat every adapter and test boundary.OpenCode2Runtimenamespace across all seven PR-owned live-test consumers and qualify its layer, service tag, helper, and tagged error exports.categoryandoperationfields directly, preserving useful diagnostics without coupling the log to an error message or nested provider cause.UI Changes
Before this change, T3 Code had no OpenCode 2 provider entry. After the change,
OpenCode 2 appears as a distinct Preview provider in Settings and the model
picker, with its own icon, provider instances, reasoning selector, Build/Plan
mapping, Queue controls, Stop states, provider-native child lineage, and the
shared one-click update action when its executable belongs to a recognized
package manager. Its icons use OpenCode's blue
devtreatment because OpenCode2 is distributed on OpenCode's development release track.
Baseline settlement:
Queue:
Subagents and background work:
Direct Stop and recovery:
The linked guide contains copyable prompts and expected UI outcomes for desktop,
web, and mobile. Packaged desktop verification covered provider setup, the
settled authenticated catalog, Queue to Steer, and multi-item Queue editing and
reordering. The Stop and nested-child rows are backed by the automated and
headless coverage below; their packaged UI prompts remain in the guide for the
draft review pass.
Startup Performance
Historical cold-start numbers measured with
opencode2 v0.0.0-next-16694(earlier than the current verified pin
0.0.0-next-16916) using isolated,test-owned process groups, ephemeral ports, and empty temporary working
directories:
630ms maximum.
maximum after banner readiness.
connected integrations. Every inventory accepted by the production 500ms floor
and matching-snapshot rule matched the inventory observed at 5.5 seconds; the
latest acceptance was 649ms after banner readiness.
1.779s median. Every check reported ready with all 108 models.
These measurements did not read T3 userdata or interact with a running desktop
application.
Validation
vp check: pass, with pre-existing warnings onlyvp run typecheck: reaches all 15 tasks; the only error is in unchanged baseapps/server/src/httpCompression/HttpResponseCompression.ts:33vp run build:desktop: passvp run test: pass across all 14 test packages; server result was 2,157passed with 16 environment-gated skips
node scripts/release-smoke.ts: passFocused orchestration Stop coverage: 242 tests pass
Changed-surface regression run: 505 tests pass with 10 environment-gated skips
Focused provider-maintenance, OpenCode 2 driver/provider, and shared semver
coverage: 52 tests pass across four files
Review-repair regression coverage: 150 focused tests pass across eight files
with three real-binary adapter cases gated; seven selected replay fixtures
also pass
Round B review-repair coverage: 143 focused tests pass across 13 files,
including multiselect forms on web and mobile, replay concurrency, Stop
targeting, stale refresh rejection, and reaper failure handling
Round C review-repair coverage: 254 focused tests pass across 12 server, web,
and mobile files, including direct tagged-error status formatting, the
generic unparseable-health diagnostic, all 98 replay integration scenarios,
and the replay transcript contract
Round D review-repair coverage: 109 focused tests pass across five directly
affected files, all 98 replay integration scenarios pass, and eight replay
transcript contract and NDJSON tests pass
Round E review-repair coverage: 52 focused tests pass across the OpenCode 2
runtime, text-generation, and provider files, including concurrent dead-server
replacement and inventory deadline stability
Round F review-repair coverage: all seven form helper tests pass, including
hostile field keys, inherited-name custom answers, and JSON serialization
Round G review-repair coverage: 25 OpenCode 2 runtime and form tests pass;
32 focused form, model-picker, and composer tests pass on the rebased base
Round H review-repair coverage: all 16 OpenCode 2 agent-selection and provider
cache tests pass for complete, Build-only, and Plan-only inventories
Rounds I and J review-repair coverage: 101 focused Grok adapter, xAI
extractor/encoder, and OpenCode 2 provider-status tests pass
Round K review-repair coverage: the focused OpenCode 2 thread-deletion replay
passes with an explicit stopped-before-detach assertion
Round L review-repair coverage: all 152 OpenCode 2 adapter and replay tests
pass, including typed missing-payload failures and the queued-subagent
launch-acknowledgement invariant
Round M review-repair coverage: all seven affected live-test modules import
successfully; three tests pass and ten real-runtime tests remain gated by
their existing environment flags
Round N review-repair coverage: both automatic permission-reply failure
replays pass with bounded structural warning annotations
Rounds O and P review-repair coverage: 118 focused OpenCode 2 driver,
provider, runtime, reaper, and registry tests pass, including inventory
instability, dead-after-banner startup, bounded snapshot diagnostics, and
same-workload recovery after the reaper cooldown
Current-head Macroscope Effect Service Conventions reports
All clear, andCorrectness reports no issues after reviewing 445 code objects
PR-wide TypeScript AST ternary audit: all 170 changed JavaScript and
TypeScript files parsed; zero PR-added nested conditional expressions remain
at depth 2 or greater, including zero at depth 3 or greater
Full typecheck was run on the rebased tree and reaches all 15 tasks; the only
error is in unchanged updated-base
apps/server/src/httpCompression/HttpResponseCompression.ts:33CI Release Smoke and Mobile Native Static Analysis pass
CI Test reports 1,820 passing web tests and two locally reproduced failures
in unchanged updated-base
ProjectScriptsControl.test.tsxCurrent-head CI Check passes; an earlier head reached only the known Vite+
warning-output panic with
Resource temporarily unavailable (os error 11)Isolated Bun-managed spawned-server runtime: pass with fresh HOME and XDG
directories under the parent workspace
tmp/Real Bun 1.3.14 isolated-global update:
opencode2advanced from next-16691to next-16694 with
bun add -g --trust @opencode-ai/cli@next; the resultingpackage bin is the platform ELF executable, not the shell placeholder
Real OpenCode 2 Queue packs pass for multi-item controls and Queue promotion
to Steer; packaged command logs confirm durable edit and reorder receipts
Real OpenCode 2 Stop coverage passes for direct Stop, queued recovery,
foreground-child Stop, settled-parent child Stop, direct-child Stop, sibling
exclusion, background shell Stop, recovery ordering, and nested depth-2 Stop
Nested depth-2 verification uses only inline
OPENCODE_CONFIG_CONTENT={"experimental":{"subagent_depth":2}}on a privatetest server; it does not change global OpenCode configuration
Published manual UI guide and live scenario matrix
2026-08-06 currency (
04eefae87throughe98b4febf; tip also has empty CIretrigger
8763ab36a):opencode2 v0.0.0-next-16916andT3_MODEL=opencode/glm-5.2:opencode2-settlementandopencode2-interrupt-direct-stoppass (tool ids real, nottool:undefined)boundaries, and managed auth seed: 86 tests pass
e98b4febfvp checkpass; server typecheck clean. Monorepo typecheck stillhits known base
apps/mobile/vite.config.tsexcessive stack depth on sometrees
during a platform outage window; last Actions run on
37ff24db9cancelledwithout runners (not a source failure on the current tip)
Known Limitations
between next builds. This driver intentionally has no default instance.
Pin an exact CLI version rather than floating
@opencode-ai/cli@next.Current verified pin:
opencode2 v0.0.0-next-16916(
@opencode-ai/cli@0.0.0-next-16916), withautoupdate: falserecommended for local installs that must match thisadapter. Authenticate with
opencode2 auth connect, then add an OpenCode 2provider instance explicitly. One-click channel updates remain available for
recognized package-managed paths when you intentionally advance the pin;
custom paths stay manual.
@opencode-ai/sdk-nexttonpm:@opencode-ai/sdk@0.0.0-beta-202608061351as its sole consumer. Theadapter dual-normalizes next-16916 short events and earlier beta
session.next.*names; a newer unpinned binary can still diverge.experimental background subagents themselves. T3-owned servers receive the
required environment flag from provider settings and seed host credentials
into an isolated managed data home (sessions are not shared with a desktop
opencode2 serve --service).Stop topology is therefore harness-only unless a server opts into depth 2.
Model: GPT-5 Codex, with Grok 4.5, GPT-5.6 Sol, and Terra review passes
Harness: T3 Code
Note
Add OpenCode 2 as a built-in provider with full orchestration and UI support
opencode2provider driver with its own settings schema (OpenCode2Settings), runtime (OpenCode2RuntimeLive), orchestration adapter (OpenCode2AdapterV2), and text generation implementation (makeOpenCode2TextGeneration).SpawnedProcessReaperservice with a sidecar process that ensures managed OpenCode 2 server subprocesses are cleaned up on parent exit, on both POSIX and Windows.hasInterruptibleProviderNativeBackgroundWork, Stop commands can target provider-native threads without a run ID, and the composer surfaces a secondary Stop button when background work is active.next) and per-channel version caching;parseSemveris fixed to preserve full prerelease identifiers containing hyphens (e.g.0.0.0-next-16339).OpenCode2Iconto the icon registry and surfaces OpenCode 2 in the model picker, settings UI, and mobile composer with distinct blue-themed visuals.OpenCode2RuntimeLiveandSpawnedProcessReaper; any misconfiguration in the sidecar respawn logic could affect process cleanup for all managed providers.📊 Macroscope summarized 6c8f5a0. 121 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
(Automatic summaries will resume when PR exits draft mode or review begins).🗂️ Filtered Issues
No issues evaluated.