feat(models): add OpenCode Go provider with live model roster sync - #879
Gadgitmatic wants to merge 2 commits into
Conversation
🦋 Changeset detectedLatest commit: 8518b1b The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Wire OpenCode Zen Go as a well-known OpenAI-compatible provider: catalog presets, an adapter for its chat-completions models, and the per-session x-opencode-session header its gateway expects.
OpenCode Go publishes its live roster at GET {base_url}/models. Refresh it whenever the provider is saved so model pickers track the provider instead of the shipped presets: discovered ids are unioned with the configured models and discovery is best-effort (failures keep the stored manifest).
| added.push({ model_id: id, name: name.data, properties: {} }); | ||
| } | ||
| return added.length === 0 ? manifest : { ...manifest, models: [...manifest.models, ...added] }; | ||
| } |
There was a problem hiding this comment.
Roster sync allows duplicate names
Medium Severity
expandOpenCodeGoModels only skips duplicate model_ids and never checks that a slugified name is unused. slugifyModelId folds punctuation, case, and letter-digit boundaries, so distinct upstream ids can share one NameSchema name. The saved manifest then violates unique-name rules, GET /models emits duplicate FQNs, and a later settings PUT fails validation on that stored list.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c34e5a1. Configure here.
c34e5a1 to
8518b1b
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8518b1b. Configure here.
| ...(apiKey === undefined ? {} : { authorization: `Bearer ${apiKey}` }), | ||
| }, | ||
| signal: AbortSignal.timeout(MODEL_DISCOVERY_TIMEOUT_MS), | ||
| }); |
There was a problem hiding this comment.
Discovery fetch bypasses SSRF guard
High Severity
Roster sync calls native fetch after only assertSafeOutboundUrl. That check does not cover redirects or DNS rebinding, which ssrfFetch exists to stop. Because well-known providers allow a base_url override, a settings save can make the server follow a public URL to an internal hop, including with the Authorization bearer.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 8518b1b. Configure here.


Adds OpenCode Zen Go as a well-known OpenAI-compatible model provider, and keeps its model roster in sync with the provider instead of a static preset list.
What
opencode-goprovider type: catalog presets, an adapter for its chat-completions models, and the per-sessionx-opencode-session/user-agentheaders its gateway expects on model calls.GET {base_url}/modelsand unions the discovered ids with the configured models, so model pickers show the provider's full current roster. Discovery is best-effort: a 5s timeout, and any failure keeps the saved manifest unchanged.Notes
@truefoundry/trueforgeand@truefoundry/trueforge-corechangesets.Testing
pnpm --filter @truefoundry/trueforge typecheckpnpm --filter @truefoundry/trueforge test(581 passed)Note
Medium Risk
Introduces outbound model discovery on admin saves (after existing SSRF URL checks) and new runtime LLM headers for a provider type; failures are best-effort but mis-synced rosters could confuse model pickers.
Overview
Adds OpenCode Zen Go (
opencode-go) as a well-known model provider: catalog seed presets, schema/default base URL, and routing through the shared OpenAI-compatible LLM adapter (chat-completions models only).On every model-provider create/update,
opencode-gomanifests are refreshed fromGET {base_url}/models(5s timeout, Bearer auth). Discovered model ids are unioned with existing entries so presets and already-configured models are kept; failures are logged and the save still succeeds with the incoming roster. PUT with a redacted API key uses the stored key for discovery.During turns, OpenCode Go calls get
x-opencode-session(TrueForge session id) anduser-agent: TrueForge/{version}in addition to existing turn headers.Unit tests cover roster expansion, redacted-key discovery, and HTTP/network failure fallbacks; preset PUT tests stub fetch so other catalog types stay offline.
Reviewed by Cursor Bugbot for commit 8518b1b. Bugbot is set up for automated code reviews on this repo. Configure here.