Repository navigation
Complete OpenCode command integration — phase 4b sweep of remaining two-provider guards - #413
Merged
Merged
Conversation
Phase 7 (#408) registered OpenCode as the third agent provider, but a sweep across the command + modal surface left ~15 hardcoded "kind !== 'claude' && kind !== 'codex'" guards behind. The visible consequence: clicking "OpenCode" in the New Agent overlay silently did nothing in Dispatch mode, and every OpenCode pane went through 9 command surfaces that behaved as if the pane were terminal-kind. Primary bug (silent OpenCode spawn): * NewAgentPlacementOverlay.tsx:118, 139 — commitKind()'s Linked and Dispatch branches both dropped `kind === 'opencode'` without a toast. Replaced with isAgentProviderKind() so any registered agent provider spawns cleanly. Stale "Claude or Codex" prose in the surrounding comment rewritten to reflect the registry. Every remaining two-provider negative guard in the renderer replaced with the same registry predicate: * sessionCommands.ts:294, 340, 386, 432, 551, 587 — six commands (four enable-*-mcp toggles, Copy Resume Command, Duplicate Agent). Every one had `when: isAgentProviderKind(kind)` already allowing OpenCode through, followed by a stale `run:` re-narrow that filtered it back out. All downstream fns (buildProviderResumeCommand, duplicateSession, replaceSession) already accept AgentProviderKind — no downstream change needed. * orchestrationMcp.ts:157 — matchingOrchestrationSessionIds was silently excluding OpenCode orchestration children from the parent's visible list; list_agents and close_run would return the wrong scope. * hook/actions/reader.ts:40 — toggleReaderMode refused to enter Reader Mode on OpenCode panes even though every registered provider ships a transcript view under src/providers/<kind>/. * hook/actions/session.ts:971 — softReloadAgentView refused to refresh OpenCode panes. It's provider-neutral (renderer-only), so the pair guard was pure dead weight. * CloseOldAgentsModal.tsx:138 — bulk-close preview silently omitted OpenCode agents from the list and count. * loadWorktreeDump.ts:119 — per-worktree activity view hid OpenCode sessions from their worktree even when they were on-disk. * prompt-templates/templates.ts:89 — templates that reference "the other agents in this tab" silently narrowed the LLM's context window by dropping OpenCode. Data-integrity fixes (silent branch-fallthrough → fail loudly): * providerSwitch/duplicateSession.ts:66 — `if (provider === 'claude') … else duplicateCodex(...)` treated OpenCode as Codex silently, reading its server session id as a Codex rollout uuid and writing malformed output. Replaced with explicit dispatch that throws for unimplemented providers; the Duplicate Agent command's catch now surfaces the thrown message as a pane toast. * providerSwitch/rewindSession.ts:83 — same silent fallthrough. Same fail-loud dispatch; the rewind path's UI-level anchor union already keeps OpenCode from reaching this on the happy path, but MCP / test callers now get a clear error instead of corruption. Stale toast copy: * hook/actions/provider.ts:110, 177 — "Only Claude and Codex panes can reload/support rewind" replaced with registry-neutral wording ("Only agent panes can reload/support rewind") so the messages stay correct for any current or future provider set. Explicitly out of scope (each is a separate PR): * BulkProviderSwitchModal N-way rewrite and switchProvider engine dispatch — blocked on agent-transcript-parser#5 (opencode codec). switchProvider already fails loudly for unsupported pairs, and the modal only offers the pairs the engine translates, so both are honest today. * useIpcSubscriptions ingestion shape-sniff fallback and sessionIndex opencode discovery — OpenCode's on-disk model is server-based, not JSONL, so this needs its own architectural slice. * Command descriptions/keywords that still say "Claude and Codex agents" — cosmetic; the runtime is correct. Verification: `npx tsc --noEmit` clean on both tsconfig.node and tsconfig.web with a cleared incremental cache. No new tests per the repo's "don't add tests in feature/fix PRs" convention. Fixes the OpenCode spawn silent-fail. Closes the last two-provider literal in every renderer command surface. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #408 (Phase 7: wire OpenCode as the third plug-and-play provider) and the earlier #395/#397/…/#404/#405/#409 phases. Closes the OpenCode spawn silent-fail and the 8 command surfaces around it.
Why
Registering OpenCode as an
AgentProviderKind(#395) and wiring it through the registry (#408, #411, #412) was necessary but not sufficient: about 15 hand-writtenif (kind !== 'claude' && kind !== 'codex') returnguards survived across the renderer command / modal surface, and two more inproviderSwitch/silently mistreated OpenCode as Codex. Symptom the user hit: clicking OpenCode in the New Agent overlay in Dispatch mode did nothing — no spawn, no toast, no log entry.What changed (11 files, +164/-30)
Primary bug (silent OpenCode spawn)
NewAgentPlacementOverlay.tsx:118, 139—commitKind()'s Linked and Dispatch branches both droppedkind === 'opencode'silently. Replaced withisAgentProviderKind()so any registered provider spawns cleanly. Stale "Claude or Codex" prose in the surrounding comment updated.Registry-driven guard sweep (14 sites)
Every remaining
kind !== 'claude' && kind !== 'codex'in the renderer replaced withisAgentProviderKind(kind):sessionCommands.ts:294, 340, 386, 432, 551, 587— six commands (fourenable-*-mcptoggles, Copy Resume Command, Duplicate Agent). Every one hadwhen: isAgentProviderKind(kind)allowing OpenCode through, followed by a stalerun:re-narrow that filtered it back out.orchestrationMcp.ts:157—matchingOrchestrationSessionIdswas excluding OpenCode orchestration children from the parent's visible list;list_agents/close_runreturned the wrong scope.hook/actions/reader.ts:40— Reader Mode refused OpenCode panes even though every registered provider ships a transcript view.hook/actions/session.ts:971—softReloadAgentViewrefused OpenCode panes. It's provider-neutral (renderer-only), so the guard was dead weight.CloseOldAgentsModal.tsx:138— bulk-close preview silently omitted OpenCode agents.loadWorktreeDump.ts:119— per-worktree activity view hid OpenCode sessions from their worktree.prompt-templates/templates.ts:89— templates that reference "the other agents in this tab" silently narrowed the LLM's context window by dropping OpenCode.All downstream fns (
buildProviderResumeCommand,duplicateSession,replaceSession) already acceptAgentProviderKind— no downstream change needed.Data-integrity fixes (silent branch-fallthrough → fail loudly)
providerSwitch/duplicateSession.ts:66—if (provider === 'claude') … else duplicateCodex(...)treated OpenCode as Codex silently, reading its server session id as a Codex rollout uuid and writing malformed output. Replaced with explicit dispatch that throws for unimplemented providers; the Duplicate Agent command's catch now surfaces the message as a pane toast.providerSwitch/rewindSession.ts:83— same silent fallthrough. Same fail-loud dispatch.Stale toast copy
hook/actions/provider.ts:110, 177— "Only Claude and Codex panes can reload/support rewind" → "Only agent panes can reload/support rewind" so the messages stay correct for any current or future provider set.Explicitly out of scope (deferred to follow-up PRs)
BulkProviderSwitchModalN-way rewrite andswitchProviderengine dispatch — blocked onagent-transcript-parser#5(opencode codec).switchProvideralready fails loudly for unsupported pairs (see the throw at line 75), and the modal only offers translatable pairs, so both are honest today.useIpcSubscriptionsingestion shape-sniff andsessionIndexopencode discovery — OpenCode's on-disk model is server-based, not JSONL. Needs its own architectural slice.Verification
npx tsc --noEmit -p tsconfig.node.json— 0 errorsnpx tsc --noEmit -p tsconfig.web.json— 0 errors (with cleared.tsc-out/)Zero remaining
kind !== 'claude' && kind !== 'codex'in the tree.Per repo convention, no new tests added.
Test plan
npm run devopencode --session <id>; Soft Reload works#411)🤖 Generated with Claude Code