feat: add opencode provider support#1758
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 Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ 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 |
ApprovabilityVerdict: Needs human review This PR adds a complete new provider integration (OpenCode) with ~4000 lines of new code including adapters, runtime management, UI integration, and settings. New features of this scope require human review. Additionally, there are unresolved medium-severity review comments about server process management and text streaming logic that should be addressed. You can customize Macroscope's approvability policy. Learn more. |
- preserve OpenCode variant and agent selections - hide unsupported interaction mode controls - add provider snapshot and UI coverage
| }), | ||
| }), | ||
| (server) => Effect.sync(() => server.close()), | ||
| ); |
There was a problem hiding this comment.
Each text generation spawns and tears down server process
Medium Severity
Every call to runOpenCodeJson (commit messages, PR content, branch names, thread titles) spawns a brand new OpenCode server child process via startOpenCodeServerProcess, waits for it to become ready, creates a session, sends a single prompt, then immediately shuts down the server. This involves finding a free port, spawning a process, waiting up to 5 seconds for startup, and then killing it — all for a single text generation request. The adapter (OpenCodeAdapter) maintains a long-lived server per session, but the text generation layer does not reuse any server instance.
Reviewed by Cursor Bugbot for commit 5ebbf95. Configure here.
- Keep a warm OpenCode process alive across back-to-back requests - Close the shared server after the idle TTL and add coverage for reuse
- Reuse an existing OpenCode server for provider sessions and text generation - Add `serverUrl` to settings, UI, and runtime connection handling - Update tests for configured-server behavior
- Plumb OpenCode server passwords through settings and contracts - Send basic auth to external OpenCode servers when configured - Surface the password field in the web settings UI
|
is it going to be implemented? |
Co-authored-by: codex <codex@users.noreply.github.com> # Conflicts: # apps/web/src/components/ChatView.tsx # apps/web/src/components/chat/TraitsPicker.browser.tsx # apps/web/src/components/chat/composerProviderRegistry.test.tsx # apps/web/src/components/chat/composerProviderRegistry.tsx # apps/web/src/composerDraftStore.ts # packages/contracts/src/orchestration.ts # packages/contracts/src/settings.ts
- Reuse active shared servers safely under binary-path races - Emit assistant text updates from both message and part events - Make OpenCode permissions default to ask and disable password autofill - Fix settings panel test mounting and composer layout
| const makeRoutingTextGeneration = Effect.gen(function* () { | ||
| const codex = yield* CodexTextGen; | ||
| const claude = yield* ClaudeTextGen; | ||
| const openCode = yield* OpenCodeTextGen; |
There was a problem hiding this comment.
Inconsistent indentation suggests wrong scope level
Low Severity
The openCode variable declaration uses 2-space indentation while the adjacent codex and claude declarations use 4-space indentation. The same pattern appears in ProviderRegistry.ts line 42 (openCodeProvider), and in several lines of ProviderAdapterRegistry.test.ts. While JavaScript doesn't use indentation for scoping, this inconsistency is misleading and suggests the line may be at a different scope level than its siblings.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 8a3159c. Configure here.
- Fall back to default OpenCode settings when provider config is missing - Abort newly started remote SDK sessions when a concurrent winner already exists - Co-authored-by: codex <codex@users.noreply.github.com>
| sessions.delete(context.session.threadId); | ||
| context.server.close(); | ||
| const turnId = context.activeTurnId; | ||
| void emitPromise({ |
There was a problem hiding this comment.
🟢 Low Layers/OpenCodeAdapter.ts:349
At lines 349 and 357, void emitPromise(...) creates promises that are never awaited or caught. If Effect.runPromiseWith throws, the rejection becomes unhandled and Node.js will emit an unhandledRejection event. Consider awaiting these promises or adding .catch() handlers to ensure errors are handled explicitly.
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/provider/Layers/OpenCodeAdapter.ts around line 349:
At lines 349 and 357, `void emitPromise(...)` creates promises that are never awaited or caught. If `Effect.runPromiseWith` throws, the rejection becomes unhandled and Node.js will emit an `unhandledRejection` event. Consider awaiting these promises or adding `.catch()` handlers to ensure errors are handled explicitly.
Evidence trail:
apps/server/src/provider/Layers/OpenCodeAdapter.ts lines 336-339 (definition of emit and emitPromise), lines 349 and 357 (void emitPromise calls), lines 382, 407, 483, 544, 551, 573, 591, 615, 630, 649, 667, 691, 704 (awaited emitPromise calls showing the expected pattern)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c69f377. Configure here.
| context.emittedTextLengthByPartId.set( | ||
| event.properties.partID, | ||
| previousLength + delta.length, | ||
| ); |
There was a problem hiding this comment.
Inconsistent text length tracking between delta and update handlers
Medium Severity
The message.part.delta handler tracks emitted text length by adding delta.length to emittedTextLengthByPartId, while emitAssistantTextDelta (called from message.part.updated) sets it to text.length (absolute). If both event types fire for overlapping content on the same part, the tracked length becomes the sum of both, exceeding the actual text length. Subsequent emitAssistantTextDelta calls would then skip legitimate new text (because text.length > inflatedPreviousLength is false), causing lost streaming output.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c69f377. Configure here.
- VSCode launch.json and tasks.json - Windows-only release workflow (release-fork.yml) - Android Capacitor build setup - Standalone Linux server build with systemd service install - VCS mode setting (git/disabled) Deferred: OpenCode and Gemini-cli implementation (PR pingdotgg#1758, pingdotgg#1983)


summary
testing
Note
High Risk
Introduces a new end-to-end provider (server process spawning/connection, session streaming, and provider registry wiring) and updates model-selection handling across the web app, increasing risk of lifecycle/streaming bugs or subtle option serialization differences.
Overview
Adds first-class
opencodeprovider support across server and web, including provider discovery/health probing, provider registry wiring, settings persistence, and UI selection.Implements an OpenCode runtime + adapter using
@opencode-ai/sdkto start/connect to an OpenCode server, create/abort sessions, stream events, and map permissions/questions/tool lifecycle into the app’s runtime event model.Adds OpenCode-backed git text generation (
commit,PR,branch,thread title) with a shared server reuse mechanism (idle TTL) and structured JSON-schema decoding, plus updates the web composer/settings to support OpenCode-specific model traits (variant/agent) and hides the Build/Plan toggle where unsupported.Reviewed by Cursor Bugbot for commit c69f377. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add OpenCode as a supported AI provider across server, composer, and settings UI
opencodeas a validProviderKindin contracts, settings, and session logic; adds default modelopenai/gpt-5and display name 'OpenCode'.OpenCodeProviderthat probes either a local CLI binary or a configured server URL, returning human-readable status messages for missing CLI, auth failures, and connection errors.OpenCodeAdapterand wires it into the provider adapter registry and the routing text-generation layer.OpenCodeTextGenerationwhich reuses a single OpenCode server process across requests and shuts it down after 30s of inactivity.opencode.Macroscope summarized c69f377.