Skip to content

feat(provider): recognise OpenCode Go and Zen as first-class variants#6

Merged
bravo1goingdark merged 1 commit into
mainfrom
feat/opencode-provider-enum
May 5, 2026
Merged

feat(provider): recognise OpenCode Go and Zen as first-class variants#6
bravo1goingdark merged 1 commit into
mainfrom
feat/opencode-provider-enum

Conversation

@bravo1goingdark
Copy link
Copy Markdown
Owner

Summary

Previously, ingest events tagged `provider="opencode"` or `"opencode_zen"` fell through to `Provider::OpenAICompatible` — keeping the data correct but tagging it as `"openai_compatible"` on every downstream surface (`id_key`, dashboards, metrics labels).

This PR adds two dedicated variants so consumers (Obol's `/monitor`, dashboards, etc.) see the right label without inspecting the `base_url`:

  • `Provider::OpenCode` ← `opencode.ai/zen/go` (subscription, flat-rate)
  • `Provider::OpenCodeZen` ← `opencode.ai/zen` (pay-as-you-go)

Both share the same `canonical_host` (`opencode.ai`) and use bearer auth; `from_host_path` disambiguates by URL prefix (`/zen/go` for Go, `/zen` for Zen). `from_id_key` adds snake_case keys, with `from_id_key_ignore_case` also accepting the `"opencode-zen"` hyphenated form for HTTP query params.

`usage::total_billable_input_tokens` treats both as input-only (no cache-creation/cache-read summing) — same rule as the other OpenAI-compatible providers.

No schema change. No wire-format change. Existing events with `provider="opencode"` stored as `OpenAICompatible{base_url:"opencode"}` remain valid; new ingest will deserialise to the dedicated variant.

Test plan

  • `cargo build --workspace` clean
  • `cargo test --workspace` — all suites pass (host-matching battery + id-key uniqueness extended for new variants)
  • `cargo clippy --workspace --all-targets -- -D warnings` — clean
  • After deploy: fire an Obol→OpenCode call, query `/v1/events`, confirm response shape has `provider: "opencode"` (not `"openai_compatible"`)

Previously, ingest events tagged provider="opencode" or
"opencode_zen" fell through to Provider::OpenAICompatible — keeping
the data correct but tagging it as "openai_compatible" on every
downstream surface (id_key, dashboards, metrics labels). Adds two
dedicated variants so consumers see the right label without
inspecting the base_url.

- Provider::OpenCode      ← opencode.ai/zen/go (subscription)
- Provider::OpenCodeZen   ← opencode.ai/zen   (PAYG)

Both share the same canonical_host (opencode.ai) and use bearer
auth; from_host_path disambiguates by URL prefix (/zen/go for Go,
/zen for Zen). from_id_key adds the snake_case keys, with
from_id_key_ignore_case also accepting the "opencode-zen" hyphenated
form for HTTP query params. usage::total_billable_input_tokens
treats both as input-only (no cache-creation/cache-read summing) —
same rule as the other OpenAI-compatible providers.

No schema change. No wire-format change. Existing events with
provider="opencode" stored as OpenAICompatible{base_url:"opencode"}
remain valid; new ingest will deserialise to the dedicated variant.
@bravo1goingdark bravo1goingdark merged commit aa156ca into main May 5, 2026
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