Repository navigation
feat(llm): add Opencode provider (OpenCode Go and Zen) - #299
Open
Notaloop763 wants to merge 2 commits into
Open
Notaloop763 wants to merge 2 commits into
Notaloop763 wants to merge 2 commits into
Conversation
Notaloop763
force-pushed
the
feat/opencode
branch
from
October 10, 2026 16:46
4c70ef3 to
f20dc51
Compare
Contributor
Author
|
@hydropix, friendly ping: this is ready for review, and CI is green. It builds on frank-lar's #278, which has been inactive since mid-September. Their commits are credited as co-author. On top of that, it adds routing for every OpenCode API family (Responses, Anthropic Messages, Google), the Zen catalog, and live tests against all 38 Go models. If it's merged, #278 can be closed. |
Notaloop763
force-pushed
the
feat/opencode
branch
2 times, most recently
from
October 15, 2026 04:47
adfd23d to
32628a6
Compare
Owner
|
Thanks for the ping and for the work on top of #278, and sorry for the wait. I haven't been able to review this one properly yet, and I'd rather not merge a new provider of this size without going through it, so it won't be in the release going out today. It's next on my list, and I'll get back to you here with feedback. |
Add OpencodeProvider, an OpenAI-compatible provider for the OpenCode gateway. One API key reaches both catalogs, and the model id picks one using opencode's own "<catalog>/<model>" convention: opencode-go/<model> goes to Go (subscription) and opencode/<model> goes to Zen (pay-as-you-go). A bare id goes to Go so a missing prefix never spends balance. The API only ever receives the bare id; the model setter normalizes ids assigned later (e.g. by refinement passes) as well. - Send a random x-opencode-session header, stable for the provider's lifetime (one job), on chat, model-listing and context-detection requests. Go rejects requests without it. Supported by a new optional extra_headers on OpenAICompatibleProvider and ContextDetector. - Route each model to the API family the gateway serves it through, by model-id prefix, as opencode and hermes-agent do: gpt-/grok-/ muse-spark to OpenAI Responses, claude-/qwen/union-alpha (and minimax- on Go) to Anthropic Messages, gemini- on Zen to Google generateContent, and everything else to chat/completions. Only System One (jev- on Zen) is rejected and hidden from the model list. OpenAICompatibleProvider gains request-URL, auth-header, payload and response-parsing hooks for this. - The model list fetches both catalogs concurrently and groups them as "OpenCode Go" / "OpenCode Zen"; when both fail, the real cause is reported. - Gateway refusals (ModelProtocolUnsupported, FreeTierError, CreditsError / insufficient funds, "model access is disabled") get actionable messages via a new _describe_http_error hook. - Wire the provider through config (OPENCODE_API_KEY, OPENCODE_MODEL, OPENCODE_API_BASE), the factory, API routes and settings allow-list, translate/refine/PDF pipelines, CLI, web UI and all 7 locales. Also forward the NIM API key to the PDF pipeline, and cap in-place rate-limit sleeps at MAX_RATE_LIMIT_SLEEP (one hour): longer Retry-After waits, such as Go's weekly quota, raise RateLimitError so the pipeline auto-pauses instead of stalling. Verified live on Go: all 38 listed models translate, across chat, Responses (gpt, grok, muse-spark) and Messages (claude, minimax, qwen). Zen Messages and Google requests reach the gateway and get the expected billing refusal; paid Zen calls are covered by mocked tests only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: frank-lar <2317872+frank-lar@users.noreply.github.com>
Add an Opencode section to docs/PROVIDERS.md covering the Go and Zen catalogs, the "<catalog>/<model>" model ids (a bare id routes to Go), the per-job session header and which model families are supported. List the provider in the README, CLI, Docker, troubleshooting and API-key rotation docs, the translator skill, and the .env.example and docker-compose.yml option lists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: frank-lar <2317872+frank-lar@users.noreply.github.com>
Notaloop763
force-pushed
the
feat/opencode
branch
from
October 25, 2026 18:23
32628a6 to
2a9ab2a
Compare
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.
Summary
Adds an Opencode provider for the OpenCode gateway. One OpenCode API key reaches both catalogs:
/zen/go/v1), the subscription plan/zen/v1), pay-as-you-go from the workspace balanceModel ids follow opencode's own
<catalog>/<model>convention, as printed byopencode models.opencode-go/<model>routes to Go andopencode/<model>routes to Zen. A bare id routes to Go, so a missing prefix never spends balance. The API only ever receives the bare id.API families
The gateway serves each model through one API family. The provider picks the family from the model id, following the Go endpoint table and the routing in opencode's own client and hermes-agent:
gpt-*,grok-*,muse-spark*/v1/responsesclaude-*,qwen*,union-alpha*, and on Gominimax-*/v1/messagesgemini-*(Zen only)/v1/models/<model>:generateContent/v1/chat/completionsEach family gets its native request body, response parsing (text, finish reason, token usage, output-truncation detection) and auth header (
Authorization: Bearer,x-api-keyorx-goog-api-key). New models that rotate into the catalogs go to chat/completions unless their id matches a prefix above. Onlyjev-*on Zen (OpenCode's System One API) is not supported; those models are hidden from the model list and rejected with a clear error.OpenAICompatibleProvidergains small request-URL, auth-header, payload and response-parsing hooks for this. Its own behavior is unchanged.Details
x-opencode-sessionid, stable for one translation job, which keeps the gateway's prompt cache warm. Go rejects requests without it. The id is never derived from the machine or the install.ModelProtocolUnsupported,FreeTierError, insufficient balance, "model access is disabled") get actionable messages.OPENCODE_API_KEY,OPENCODE_MODEL,OPENCODE_API_BASE), factory, API routes and settings allow-list, translate/refine/PDF pipelines, CLI, web UI and all 7 locales.docs/PROVIDERS.md; the provider is also listed in the README, other docs,.env.exampleanddocker-compose.yml.Shared changes outside the provider
MAX_RATE_LIMIT_SLEEP(one hour). A longerRetry-After, such as OpenCode Go's weekly quota, raisesRateLimitError, so the pipeline auto-pauses with a checkpoint instead of stalling silently. Shorter throttles still wait in place, as before. This applies to every provider.Testing
tests/unit/test_opencode_provider.py(routing table, per-family request/response round trips, session header, model list, error hints) andtests/unit/test_opencode_integration.py, plus a rate-limit cap test.🤖 Generated with Claude Code