Skip to content

Allow Fireworks and Baseten through OpenCode, with a key per provider - #1942

Merged
JacobStephens2 merged 3 commits into
issue-1872from
issue-1883
Nov 10, 2026
Merged

JacobStephens2 merged 3 commits into
issue-1872from
issue-1883

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

OpenCode sessions can now use fireworks-ai/... and baseten/... Models inside the sandbox. This applies to Grader panel Graders and to Arms. Each session takes the key for the provider its Model names.

 proxy allowed_hosts(OpenCode, model)
   opencode.ai, models.opencode.ai
   provider_hosts(provider)
     fireworks-ai -> api.fireworks.ai
+    baseten      -> inference.baseten.co
 sandbox opencode_into(request)
+  provider = trial_provider(model)            # <provider>/<model>
-  key = credentials opencode.api_key
+  key = [opencode.keys].<provider>, else opencode.api_key
   env THIRDSHIFT_OPENCODE_API_KEY = key
   OPENCODE_CONFIG_CONTENT: provider.<provider>.apiKey = {env:…}
# ~/.thirdshift/credentials.toml
[opencode]
api_key = "…"          # still works: the fallback for any provider without its own key
[opencode.keys]
fireworks-ai = "…"
baseten = "…"

Docs: docs/guide.md (which regenerates site/docs/index.html), docs/trial.md, and the Credentials entry in GLOSSARY.md. The hand-written site pages say nothing about OpenCode keys or provider hosts, so none of them needed changing.

Evidence

Execution evidence

  • Before: cargo test --bin thirdshift proxy::tests::an_opencode_fireworks
    called `Result::unwrap()` on an `Err` value: OpenCode Trial login failed: unknown provider baseten; the Trial's Model must name a provider this proxy allows
    test result: FAILED. 0 passed; 1 failed
    
    After: the same command passes.
    test result: ok. 14 passed; 0 failed   (proxy::tests)
    
  • Per-provider keys: cargo test --bin thirdshift -- sandbox::tests::opencode sandbox::tests::an_opencode --nocapture ran under bwrap, with no skip.
    test sandbox::tests::opencode_seats_with_different_providers_each_get_their_own_key ... ok
    test sandbox::tests::an_opencode_trial_without_its_providers_key_fails_before_its_session_starts ... ok
    test sandbox::tests::an_opencode_trial_gets_its_key_only_from_the_credentials ... ok   (single key, unchanged)
    
    The two-providers test checks that a Fireworks Model gets the Fireworks key, a Baseten Model the Baseten key, and an anthropic/... Model the single api_key. These tests were written together with OpenCodeKeys, so there is no failing run of them before the change.
  • Final validation: scripts/affected-tests origin/issue-1872
    PASS npm test --prefix site (29.29s)
    PASS cargo test (813.50s)
    
    npm run docs:check --prefix site also exited 0.

Visual evidence

No visual evidence is needed: there is no rendered-layout change. The only site change is one regenerated prose paragraph in the user manual.

Merge Danger

Door: two-way

The change only adds to the Credentials format. An existing single opencode.api_key keeps working, and nothing is rewritten.

Blast Radius: narrow

It affects OpenCode Trials and Graders only. The proxy allows one more host, and only for baseten/... Models. When a key is missing, the error now names the provider and both places a key can go.

Review coverage

Both review axes read every changed file. The one exception is site/docs/index.html, generated output that both reviewers confirmed as excluded: it comes from docs/guide.md through site/generate-docs.mjs, and npm run docs:check --prefix site exited 0.

Unaddressed findings

Standards

  • Primitive Obsession (mild): the OpenCode provider name is a bare &str. Declined. The diff extends the existing proxy::opencode_provider → provider_hosts pattern (src/proxy.rs:61) without changing its shape. A newtype across the proxy, Credentials and sandbox would be a refactor beyond Allow Fireworks and Baseten through opencode, with a key per provider #1883, and the reviewer rated it low priority.
  • Credentials::read_from widened to pub(crate) for tests. Declined. The reviewer noted it without objecting, citing codebase-design's "the interface is the test surface". The seam lets the sandbox tests build keys through the real parser (src/resend_key.rs, read_from), not through private fields.

Spec

  • Supporting changes flagged as possible scope creep: the read_from seam, opencode_keys(), the clearer missing-key error, and the docs. No change was needed: the reviewer judged each one to be in support of "opencode takes an API key per provider instead of one".

Security

  • None. The review covered key selection, the proxy allowlist and Credentials parsing. The key and the proxy hosts both come from the same proxy::opencode_provider, so a session receives only the key for the provider whose hosts the proxy allows. An unknown provider fails before its session starts. No other provider's key enters the sandbox.

Closes #1883

Built with claude 2.1.314 · opus · default effort

Security review outcome

No unaddressed introduced findings.

…#1883)

The proxy's OpenCode provider hosts gain Baseten's inference.baseten.co
beside Fireworks' api.fireworks.ai. The Credentials take an
[opencode.keys] table of keys by OpenCode provider name, with
opencode.api_key kept for any provider without its own, so two OpenCode
seats on different providers each get their own key.
Work out the OpenCode Trial's provider once, keep vocabulary to the
glossary's, list the OpenCode keys in the Credentials entry and module
doc, and rewrap long lines.
@JacobStephens2
JacobStephens2 merged commit 8fcbb37 into issue-1872 Nov 10, 2026
16 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-1883 branch November 10, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant