docs(opencode): fix the generated OpenCode provider config - #90
Conversation
The generator script produced model entries that OpenCode could not fully
use, and the setup steps referenced a script that was never linked.
Config generator:
- Emit `limit` (context/output). Without it OpenCode records context 0, so
the TUI cannot track context usage or trigger compaction, and reasoning
models get a negative thinking budget.
- Always emit both `cost.input` and `cost.output`; the config schema
requires both, and the old dict comprehension dropped either when the
price was 0 or absent.
- Emit `tool_call`, `modalities` and `attachment`. Modalities default to
false, which silently disabled image/file attachments on vision models.
Eden AI's `file` modality is mapped to OpenCode's `pdf`.
- Detect reasoning from `capabilities.reasoning.mandatory` as well as
`supports_reasoning`, which is absent on ~120 catalog entries.
- Merge into an existing `opencode.json` instead of overwriting the whole
global config.
Page:
- Give the script a filename before the run command and add the
`pip install requests` step.
- Add Prerequisites and Troubleshooting sections, matching the other
integration pages.
- Document choosing a model: `/models`, or the `model` key as
`edenai/<full-eden-model-id>` (OpenCode splits on the first slash only,
so multi-slash IDs work).
- Document the `{env:EDENAI_API_KEY}` alternative to `/connect`, and the
curl/brew install options.
Verified: generated config validates against https://opencode.ai/config.json
(681 models from the live catalog); the snippet runs clean under the docs
snippet extractor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
Warning Review limit reached
Next review available in: 25 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughThe OpenCode integration guide adds installation methods, expanded setup instructions, and updated configuration generation. The generator now preserves settings, applies model metadata and limits, filters unsupported models, and handles missing API data. The guide also adds model selection, refresh, and troubleshooting guidance. ChangesOpenCode integration
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@v3/integrations/opencode.mdx`:
- Around line 122-129: Update the provider configuration generation to preserve
existing provider.edenai.options, including options.apiKey, when rebuilding the
Eden AI entry. Merge the existing options into the generated options and then
explicitly set baseURL to BASE_URL, while leaving the other provider fields and
model_entries behavior unchanged.
- Around line 101-104: Update the cache price checks in the pricing
configuration logic to test whether each value is None rather than relying on
truthiness, so zero-valued cache_read_input_token_cost and
cache_creation_input_token_cost values are converted and emitted. Preserve the
existing per_million conversion and cost assignments.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3b6ed27c-0343-48fe-840b-d5210107b876
📒 Files selected for processing (1)
v3/integrations/opencode.mdx
| if pricing.get("cache_read_input_token_cost"): | ||
| cost["cache_read"] = per_million(pricing["cache_read_input_token_cost"]) | ||
| if pricing.get("cache_creation_input_token_cost"): | ||
| cost["cache_write"] = per_million(pricing["cache_creation_input_token_cost"]) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Emit zero-valued cache prices.
Lines 101 and 103 treat a cache price of 0 as unavailable. A zero price is an explicit value. The generated configuration then omits cache metadata despite the stated requirement to include cache costs when available.
Test for None instead of truthiness.
Proposed fix
- if pricing.get("cache_read_input_token_cost"):
+ if pricing.get("cache_read_input_token_cost") is not None:
cost["cache_read"] = per_million(pricing["cache_read_input_token_cost"])
- if pricing.get("cache_creation_input_token_cost"):
+ if pricing.get("cache_creation_input_token_cost") is not None:
cost["cache_write"] = per_million(pricing["cache_creation_input_token_cost"])📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if pricing.get("cache_read_input_token_cost"): | |
| cost["cache_read"] = per_million(pricing["cache_read_input_token_cost"]) | |
| if pricing.get("cache_creation_input_token_cost"): | |
| cost["cache_write"] = per_million(pricing["cache_creation_input_token_cost"]) | |
| if pricing.get("cache_read_input_token_cost") is not None: | |
| cost["cache_read"] = per_million(pricing["cache_read_input_token_cost"]) | |
| if pricing.get("cache_creation_input_token_cost") is not None: | |
| cost["cache_write"] = per_million(pricing["cache_creation_input_token_cost"]) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@v3/integrations/opencode.mdx` around lines 101 - 104, Update the cache price
checks in the pricing configuration logic to test whether each value is None
rather than relying on truthiness, so zero-valued cache_read_input_token_cost
and cache_creation_input_token_cost values are converted and emitted. Preserve
the existing per_million conversion and cost assignments.
| config = json.loads(output.read_text()) if output.exists() else {} | ||
| config["$schema"] = "https://opencode.ai/config.json" | ||
| config.setdefault("provider", {})["edenai"] = { | ||
| "npm": "@ai-sdk/openai-compatible", | ||
| "name": "Eden AI", | ||
| "options": {"baseURL": BASE_URL}, | ||
| "models": model_entries, | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Preserve existing Eden AI authentication options.
Line 124 replaces the complete provider.edenai object. A later refresh deletes the options.apiKey setting documented on Line 143. Requests then lose environment-variable authentication.
Merge existing edenai.options into the generated options. Set baseURL explicitly after the merge.
Proposed fix
config = json.loads(output.read_text()) if output.exists() else {}
config["$schema"] = "https://opencode.ai/config.json"
-config.setdefault("provider", {})["edenai"] = {
+provider = config.setdefault("provider", {})
+edenai_options = provider.get("edenai", {}).get("options", {})
+provider["edenai"] = {
"npm": "`@ai-sdk/openai-compatible`",
"name": "Eden AI",
- "options": {"baseURL": BASE_URL},
+ "options": {**edenai_options, "baseURL": BASE_URL},
"models": model_entries,
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| config = json.loads(output.read_text()) if output.exists() else {} | |
| config["$schema"] = "https://opencode.ai/config.json" | |
| config.setdefault("provider", {})["edenai"] = { | |
| "npm": "@ai-sdk/openai-compatible", | |
| "name": "Eden AI", | |
| "options": {"baseURL": BASE_URL}, | |
| "models": model_entries, | |
| } | |
| config = json.loads(output.read_text()) if output.exists() else {} | |
| config["$schema"] = "https://opencode.ai/config.json" | |
| provider = config.setdefault("provider", {}) | |
| edenai_options = provider.get("edenai", {}).get("options", {}) | |
| provider["edenai"] = { | |
| "npm": "`@ai-sdk/openai-compatible`", | |
| "name": "Eden AI", | |
| "options": {**edenai_options, "baseURL": BASE_URL}, | |
| "models": model_entries, | |
| } |
🧰 Tools
🪛 GitHub Check: Mintlify Validation (edenai) - vale-spellcheck
[warning] 128-128: v3/integrations/opencode.mdx#L128
Did you really mean 'model_entries'?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@v3/integrations/opencode.mdx` around lines 122 - 129, Update the provider
configuration generation to preserve existing provider.edenai.options, including
options.apiKey, when rebuilding the Eden AI entry. Merge the existing options
into the generated options and then explicitly set baseURL to BASE_URL, while
leaving the other provider fields and model_entries behavior unchanged.
Tested against opencode 1.18.16 with a real Eden AI key: a mistyped model reference surfaces as a generic UnknownError, not the "Model not found: edenai/..." string the section quoted. Describe the symptom users actually see and point at `opencode models` for the exact IDs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The OpenCode page's generator script wrote a config that OpenCode loads but can't fully use, and the setup steps pointed at a script that was never linked.
Everything below was tested end-to-end against opencode 1.18.16 with a real Eden AI key, in a sandboxed
HOME— not just read off the schema. Test method is at the bottom.Config generator
limitemitted/config/providersreportslimit: {context: 0, output: 0}for every model — it has no idea how big any context window is.limit.contextfromcontext_length,limit.outputcapped at OpenCode's 32kOUTPUT_TOKEN_MAX. Now reports the real values (e.g. gpt-5-mini400000, gemini-3.6-flash1048576).modalities/attachmentattachment: False,input: {text: true, image: false, pdf: false}on models that do support images.unsupportedParts()then replaces any attached image/PDF with the literal textERROR: Cannot read "x.png" (this model does not support image input).filemodality maps to OpenCode'spdf. Loaded state now matches the catalog exactly.supports_reasoningcapabilities.reasoning.mandatory: true).costbuilt by dropping falsy valuesinputandoutput(additionalProperties: false), so a model priced 0 on exactly one side would emit an invalid object. No model in today's catalog does that, so nothing is broken right now.cache_read/cache_writewhen present.opencode.jsontheme,autoupdate,model,mcpand a second custom provider came through untouched, withedenaiadded alongside.Two things I got wrong in my first pass and have corrected here:
limitgives reasoning models a negative thinking budget. It does not on this path —ProviderTransform.variants()for@ai-sdk/openai-compatiblereturnsreasoningEffortstrings and never toucheslimit.output. The budget math is on the Anthropic/Bedrock npm paths.limitis still worth emitting for context tracking, but not for that reason.tool_callwas never a bug: it defaults totrue. The config now states it explicitly, which is tidier, not a fix.per_millionwas already correct — OpenCode divides by 1e6 when computing spend.Page
python gen_opencode_config.py, and "Download the script" linked nowhere. Now: save asgen_opencode_config.py, with apip install requestsstep.codex-cli.mdxandopenclaw.mdx.modelkey form.UnknownError, not theModel not found:string I first wrote.{env:EDENAI_API_KEY}as an alternative to/connect, plus the curl/brew install options.Verification
Sandboxed
HOME,opencode-ai@1.18.16installed from npm, script run verbatim as extracted from the published page.https://opencode.ai/config.json(jsonschema) — 681 function-calling models, all 681 listed byopencode models.anthropic/claude-sonnet-latest,openai/gpt-5-mini,google/gemini-3.6-flash, andtogether_ai/meta-models/Muse-Glimmer-30B(a 3-segment ID — confirmsparseModelsplits on the first slash only)./connect) verified: "Eden AI" is present in the list the TUI connect dialog renders (GET /provider→all,source: config). Storing the key the way/connectdoes (PUT /auth/edenai→auth.json) and running with no env var and noapiKeyin config produced a working completion.{env:EDENAI_API_KEY}tip works — that's how most of the runs above were authenticated.modeldefault key works:opencode runwith no--modelusededenai/anthropic/claude-sonnet-latest.%USERPROFILE%\.config\opencode\opencode.json.['edenai'].Not tested: the
curlandbrewinstall lines (Windows host); both are quoted from OpenCode's own install docs.🤖 Generated with Claude Code