Skip to content

Feat/opencode zen provider#4467

Open
snail-vs wants to merge 13 commits into
Hmbown:mainfrom
snail-vs:feat/opencode-zen-provider
Open

Feat/opencode zen provider#4467
snail-vs wants to merge 13 commits into
Hmbown:mainfrom
snail-vs:feat/opencode-zen-provider

Conversation

@snail-vs

@snail-vs snail-vs commented Jul 17, 2026

Copy link
Copy Markdown

Summary

  • Added OpenCode Zen as a model-aware provider.
  • Routes Zen models across Responses, Anthropic Messages, and Chat Completions.
  • Added Zen-specific missing-API-key messaging.
  • Fixed Zen Claude authentication to use x-api-key.
  • Kept OpenCode Go out of this PR.

Testing

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features
  • cargo test --workspace --all-features
    Full workspace tests were run serially. One unrelated TUI test failed in the full suite but passed when rerun in isolation:
    non_recoverable_engine_error_enters_offline_mode

Checklist

  • Updated docs or comments as needed
  • Added or updated tests where relevant
  • Verified TUI behavior manually if UI changes
  • Harvested/co-authored credit uses a GitHub numeric noreply address

No-Issue: Implements only the OpenCode Zen half of #1481; OpenCode Go remains out of scope, so the umbrella issue must stay open.

@snail-vs
snail-vs requested a review from Hmbown as a code owner July 17, 2026 06:22
@github-actions

Copy link
Copy Markdown
Contributor

Thanks @snail-vs for taking the time to contribute.

This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant recurring PR access by commenting /lgtm on a pull request.

@Hmbown Hmbown added this to the v0.9.3 milestone Jul 17, 2026
@Hmbown

Hmbown commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Intake note: this covers the OpenCode Zen half of #1481, which is milestone-assigned to v0.9.3 (the OpenCode Go half shipped in #4420; Zen + the Messages-protocol route follow in the v0.9.3 window). Setting the milestone accordingly — no action needed from you; we'll do the full review pass when v0.9.3 opens. Thanks for taking this on!

Hmbown commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Thanks — this is what a complete provider addition looks like: WirePolicy::ModelAware with per-model wire selection across Responses, Anthropic Messages, and Chat Completions, fail-closed handling for unknown and Gemini models, the Zen x-api-key fix with request-shape tests, secrets env-alias tests, and the parity pieces (docs/PROVIDERS.md, config.example.toml, CHANGELOG, check-provider-registry.py) all in one branch.

Where it stands: per the intake note, this is the Zen half of #1481 (Go shipped in #4420) and sits on the v0.9.3 milestone; v0.9.1 is freezing and v0.9.2 is the active lane, so the full review pass comes when v0.9.3 opens. The full CI matrix has not run on this head yet — fork PRs only get the intake gate and GitGuardian until review.

To keep the branch landable in the meantime:

  1. Rebase onto current main. The July 17-18 credential-help centralization (eb20e81, ca026e3, f6a882c) moved provider credential-page logic out of crates/tui/src/config.rs into CredentialHelp in crates/config/src/provider.rs; your hunk pointing Zen/Go at https://opencode.ai/zen/ needs to land on that new surface.
  2. Expect one more mechanical registry shift when the TelecomJS preset (feat: add TelecomJS provider support with configuration and catalog i… #4370 / Custom provider live catalog is never refreshed in production (scoped catalog state rewrite) #4462) lands in the v0.9.2 window ahead of this — re-derive the array counts rather than merging blindly.
  3. The full-suite flake you hit (non_recoverable_engine_error_enters_offline_mode) is not on the known-papercuts list; if you still have the output, filing it as an issue would be independently useful.

Related demand your work serves: #1481 and #4526.


Generated by Claude Code

@Hmbown

Hmbown commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Status update from the v0.9.2 maintainer pass, @snail-vs — this is a deferral to v0.9.3, not a rejection, and I'd rather say so than leave it sitting silently.

The review verdict is that this is a complete provider addition — enum variant, defaults, credential help, registry, and docs — which is exactly the shape we want and is rarer than it sounds. Most provider PRs arrive as partial plumbing that cannot build.

Why it isn't landing in v0.9.2: the conflict against current main is cosmetic (credential-help centralization moved, and the registry count changed underneath the branch), so this needs a rebase rather than rework. It sits behind #1481's Zen half, and v0.9.2 is closing on release-blocking work.

Nothing here needs redoing. If you want to rebase onto current main it will land faster; if you'd rather not, we'll harvest it with credit and your authorship preserved.

@Hmbown

Hmbown commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Thanks for the OpenCode Zen provider work, @snail-vs. This has fallen behind main and is now conflicting (29 files, mergeState DIRTY), so CI can't validate it. Could you rebase onto current main (the provider/catalog surface has moved quite a bit since July 17, including #4093 provider-scoped model handling)? Once it rebases cleanly and CI is green we can review it for merge. Happy to help triage any conflicts.

@snail-vs
snail-vs force-pushed the feat/opencode-zen-provider branch 2 times, most recently from 052e4f2 to 6ea82f2 Compare July 26, 2026 11:29
snailoniu added 10 commits July 26, 2026 21:33
Represent provider wire selection as either fixed or model-aware. Resolve model-aware protocols from catalog endpoint keys and fail closed when an endpoint does not prove a supported request shape.\n\nExisting providers remain fixed-policy routes, so this creates the Zen routing seam without changing current provider behavior.

Signed-off-by: snailoniu <snailoniu@gmail.com>
Register OpenCode Zen across config, CLI, secrets, and TUI surfaces with provider-scoped API key guidance. Keep its wire policy model-aware and fail closed until a catalog offering proves the selected model protocol.

Signed-off-by: snailoniu <snailoniu@gmail.com>
Route the documented Zen catalog across Responses, Anthropic Messages, and Chat Completions by model. Normalize the official opencode/model selector and reject Gemini or unknown models until their request protocol is supported and proven.

Signed-off-by: snailoniu <snailoniu@gmail.com>
Bind clients to the resolver-proven request protocol and send Zen models through Responses, Anthropic Messages, or Chat Completions as appropriate. Keep Zen on bearer authentication, exclude Codex OAuth headers, and fail closed when a request changes protocol or uses an unproven FIM route.

Signed-off-by: snailoniu <snailoniu@gmail.com>
Document Zen as a separate API-key provider with model-scoped Responses, Messages, and Chat Completions groups. Record the unsupported Gemini boundary and teach the provider registry drift check about the manual model-aware provider implementation.

Signed-off-by: snailoniu <snailoniu@gmail.com>
OpenCode Zen routes Anthropic models through the Messages API, which expects the native x-api-key header. Sending Zen keys as Authorization bearer tokens produced upstream 401 Missing API key errors for Claude models. Refresh the request-shape test to lock the Zen Messages auth dialect while keeping bearer auth for Zen Responses and Chat Completions routes.

Signed-off-by: snailoniu <snailoniu@gmail.com>
The model-aware route guard now reports that the Anthropic-compatible route has no proven FIM wire contract. Keep the local-failure test aligned with that fail-closed behavior and continue asserting that no HTTP request is made.

Signed-off-by: snailoniu <snailoniu@gmail.com>
Align the rebased provider with current route candidate accessors, offering capabilities, registry counts, and Responses URL construction. Rename custom-provider test fixtures now that opencode_zen is a built-in identity, and remove the superseded protocol helper.

Signed-off-by: snailoniu <snailoniu@gmail.com>
Route the opt-in resource-admission test skip notice through tracing so the all-targets Clippy gate respects the TUI module's print_stderr deny policy.

Signed-off-by: snailoniu <snailoniu@gmail.com>
State explicitly that Zen Responses and Chat Completions use Bearer authorization while Anthropic Messages uses x-api-key, matching the request-shape implementation and detailed protocol section.

Signed-off-by: snailoniu <snailoniu@gmail.com>
@snail-vs
snail-vs force-pushed the feat/opencode-zen-provider branch from 82337e6 to 19e47a6 Compare July 26, 2026 13:42
@snail-vs

Copy link
Copy Markdown
Author

Thanks for the OpenCode Zen provider work, @snail-vs. This has fallen behind main and is now conflicting (29 files, mergeState DIRTY), so CI can't validate it. Could you rebase onto current main (the provider/catalog surface has moved quite a bit since July 17, including #4093 provider-scoped model handling)? Once it rebases cleanly and CI is green we can review it for merge. Happy to help triage any conflicts.

Thanks @Hmbown — I’ve rebased this PR onto the current main (607129c) and force-pushed the updated branch. GitHub now reports the PR as mergeable.

I also resolved the provider-scoped model handling drift, completed the OpenCode Zen protocol/auth updates, clarified the provider documentation,
and ensured all commits carry DCO sign-offs.

Local checks passed:

  • cargo fmt --all -- --check
  • provider registry drift check
  • git diff --check
  • cargo clippy --workspace --all-targets --all-features
  • codewhale-config tests: 434 passed
  • OpenCode Zen targeted TUI and app-server tests: all passed

The GitHub Actions runs currently show action_required, so they appear to need maintainer approval for the fork workflows. Could you approve them
when convenient? I’ll address any actual CI failures once they run.

@Hmbown

Hmbown commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Maintainer review — I merged this branch with current origin/main locally and ran the real gates. The merge is clean (no conflicts), and everything passes except one test in your own PR, which is a test-isolation flake with a six-line fix.

The one failure, and why it is not a routing bug

---- tests::opencode_zen_configures_model_aware_provider_with_catalog_proof ----
assertion `left == right` failed
  left: NvidiaNim
 right: OpencodeZen

It passes in isolation and fails in the full run — which matches the note in your PR description about a test that passed on rerun. The cause: resolve_runtime_options consults CODEWHALE_PROVIDER / DEEPSEEK_PROVIDER from the process environment, and this test does not take the crate's env lock. Under parallel execution a sibling test's provider override leaks in, so the config's provider = "opencode-zen" is overridden by whatever that other test set. Nothing is wrong with the Zen provider wiring, the alias table, or the offering catalog — those all resolve correctly.

Every other resolution test in crates/config/src/tests.rs already guards this (see root_deepseek_fields_are_runtime_fallbacks). Adding the same two lines fixes it:

 #[test]
 fn opencode_zen_configures_model_aware_provider_with_catalog_proof() {
+    let _lock = env_lock();
+    let _env = EnvGuard::without_deepseek_runtime_overrides();
     for alias in [
         "opencode-zen",

With that applied, cargo test -p codewhale-config --lib --locked is 434 passed / 0 failed, stable across three consecutive full-suite runs.

Full local results on your branch merged with current main

  • cargo clippy --workspace --all-features --locked with CI's exact allow set — clean.
  • cargo fmt --all -- --check — clean.
  • codewhale-config — 434 passed / 0 failed (with the fix above).
  • codewhale-tui — 8336 passed / 0 failed.
  • scripts/check-provider-registry.py — drift check passed.

Please push that two-line change and CI should go green. I deliberately have not harvested this into a maintainer branch — the work is yours and it is close to landing. Thanks for the careful transport split across Responses / Anthropic Messages / Chat Completions, and for keeping OpenCode Go out of scope.

Serialize the model-aware provider test with other environment-mutating config tests and clear runtime provider overrides so parallel runs cannot leak a sibling test's provider selection.

Signed-off-by: snailoniu <snailoniu@gmail.com>
@snail-vs

Copy link
Copy Markdown
Author

Thanks @Hmbown — I’ve applied the requested test-isolation fix and pushed it in fbbedbe.

The test now takes env_lock() and clears the DeepSeek runtime provider overrides before resolving the OpenCode Zen configuration. The full
codewhale-config suite passes consistently.

The new workflow runs are currently waiting for fork-workflow approval (action_required). Could you approve them when convenient? Thanks again for
identifying the isolation issue.

@Hmbown Hmbown left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer approval: the contributor applied the requested environment-isolation fix in fbbedbe. The branch is mergeable; approving the fork workflows so the full hosted gates can run. Thank you for the careful OpenCode Zen implementation.

Hmbown added 2 commits July 26, 2026 16:48
Keep the public provider facts and source-candidate count aligned with the new ApiProvider variant so the hosted web gate remains truthful.

Verified: npm run check:facts; npm run check:docs; npm test (137/137); npm run lint; npm run build.
# Conflicts:
#	docs/public-surface-facts.json
#	web/lib/facts.generated.ts
@Hmbown

Hmbown commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Maintainer follow-up: I added the missing OpenCode Zen web facts mapping in c3647fe, regenerated the source-candidate facts, and merged current main in e701645 to restore mergeability without rewriting the contributor history. Local web receipts: check:facts PASS, check:docs PASS, 137/137 tests, lint PASS, production build PASS. The new fork workflow runs are approved. The explicit No-Issue: keeps umbrella issue #1481 open because this PR intentionally does not implement OpenCode Go.

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.

2 participants