feat(providers): add opencode community provider#1462
feat(providers): add opencode community provider#1462alexsiri7 wants to merge 1 commit intocoleam00:devfrom
Conversation
Adds OpencodeProvider that wraps the opencode SDK to give Archon workflows access to any model configured in ~/.config/opencode/opencode.json, including local Ollama models and any provider opencode supports. Key implementation details: - Lazy server startup (deferred dynamic import avoids binary lookup at boot) - Module-level singleton for the opencode server process (one process per parent) - AsyncQueue-based SSE pump (same pattern as Pi provider) to keep the stream alive and buffer events without dropping any - Subscribe without directory filter: opencode dispatches model events through the process-CWD instance, not the session's cwd instance; sessionID filtering in bridgeOpencodeEvents catches only the relevant session's events - JSON schema structured output via prompt engineering (no SDK-level JSON mode) - Session resume support via resumeSessionId Model format: '<providerID>/<modelID>' (e.g. 'ollama/qwen3:8b', 'requesty/google/gemini-3-flash-preview', 'anthropic/claude-sonnet-4-5'). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (14)
📝 WalkthroughWalkthroughThis PR introduces a new OpenCode community provider for Archon, including provider implementation with async generator-based query execution, event bridging from OpenCode SSE streams to MessageChunk sequences, configuration parsing, capability definitions, and registration logic. An E2E smoke-test workflow and comprehensive test coverage are also included. Changes
Sequence DiagramsequenceDiagram
participant Consumer as Consumer
participant Provider as OpencodeProvider
participant SDK as OpenCode SDK
participant Bridge as Event Bridge
Consumer->>Provider: sendQuery(prompt, cwd, options)
Provider->>SDK: Initialize SDK (lazy, once)
Note over Provider: Setup server, cache promise
Provider->>SDK: Create/Resume Session
alt Resume Requested
Provider->>SDK: Resume existing session
alt Resume Fails
Provider->>Consumer: Emit warning chunk
Provider->>SDK: Create new session
end
else New Session
Provider->>SDK: Create new session
end
Note over Provider: Optionally augment prompt with JSON schema
Provider->>SDK: Send prompt via session
Provider->>SDK: Subscribe to SSE event stream
loop Stream Events
SDK->>Provider: Emit SSE events (async)
Note over Provider: Buffer into queue
Provider->>Bridge: Bridge queued events
Bridge->>Consumer: Emit MessageChunk<br/>(text, thinking, tool, result)
end
Note over Bridge: On session.idle or session.error
Bridge->>Consumer: Emit final result chunk<br/>(tokens, cost, isError)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
This already has 2 open prs, please coordinate with other contributors |
Summary
OpencodeProvider— a community provider that wraps the opencode SDK to give Archon workflows access to any model configured in~/.config/opencode/opencode.json(local Ollama models, Requesty, Anthropic, OpenAI, etc.)<providerID>/<modelID>(e.g.ollama/qwen3:8b,requesty/google/gemini-3-flash-preview,anthropic/claude-sonnet-4-5)assistantTextfield toResultChunkintypes.tsso providers can surface the full accumulated text alongside theresulteventImplementation notes
SSE event delivery fix — the root cause of the most interesting bug: opencode dispatches model-response events (
message.part.delta,session.idle) through the process-CWD instance, not the session'scwdinstance. Subscribing withdirectory: cwdscoped the SSE connection to the wrong instance. The fix is to subscribe without a directory filter and rely on the bridge's existingsessionIDfilter.AsyncQueue pump — same pattern as the Pi provider: a background IIFE continuously reads from the SSE stream and pushes into a single-producer/single-consumer queue. This keeps the SSE response body alive (Bun closes idle bodies after ~99ms) and decouples the pump from the
bridgeOpencodeEventsconsumer.Lazy server startup —
createOpencode()is dynamically imported on firstsendQueryso the module can be loaded without spawning a child process when opencode is absent but unused.Test plan
bun test packages/providers/src/community/opencode/— 39 tests, all passingbun test packages/providers/src/registry.test.ts— 35 tests, all passingarchon workflow run e2e-opencode-smoke— completes in ~3s withPASS: got response: '4'tsc --noEmit)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests
Chores