Skip to content

feat(providers): OpenAI-compatible provider seam (+ Grok/xAI, OpenRouter) - #79

Merged
csmatar merged 1 commit into
mainfrom
feat/openai-compatible-provider-seam
Aug 3, 2026
Merged

feat(providers): OpenAI-compatible provider seam (+ Grok/xAI, OpenRouter)#79
csmatar merged 1 commit into
mainfrom
feat/openai-compatible-provider-seam

Conversation

@csmatar

@csmatar csmatar commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Turn the OpenAI adapter into a reusable OpenAI-compatible provider seam, so any provider
speaking the OpenAI Chat Completions wire format is a data row, not a new adapter. Ships Grok
(xAI)
as the reference and OpenRouter as the single-key live/recording path. Closes #71 and
unblocks #72/#73/#74/#75.

Scope

Changes

  • OpenAIGateway generalized in place — new name / base_url / stop_reason_key kwargs,
    all defaulting to today's plain-OpenAI behavior byte-for-byte. name moved from a class attr to
    an instance attr; the @runtime_checkable ModelGateway Protocol still matches. No new class, no
    inheritance.
  • from_wire gained stop_reason_key: str = "openai" — compat providers reuse OpenAI's
    finish-reason table, so stop_reason.py needs no per-provider row. Provider identity
    (name, which keys provider:model pricing) is decoupled from the wire family.
  • composition.OPENAI_COMPATIBLE registry (name → (base_url, env_var)) + one make_gateway
    branch that iterates it. Adding Kimi/GLM/DeepSeek is now a single row. Registered xai
    (https://api.x.ai/v1, XAI_API_KEY) and openrouter (https://openrouter.ai/api/v1,
    OPENROUTER_API_KEY).
  • application/loop.py unchanged (load-bearing rule) — the seam is entirely at/below the port.

Testing

make check          # lint + typecheck + arch + test — all green
# 586 passed, 3 skipped (live), coverage 93.30% (floor 92%)
  • New offline unit tests fake the SDK via sys.modules["openai"] and assert the captured
    base_url/api_key kwargs — no network, no key.
  • Live smoke (test_openrouter_live.py, @pytest.mark.live, skipped in CI) does a two-turn
    tool-calling exchange through OpenRouter; point it at any model with DRYFIRE_OPENROUTER_MODEL.

Quality gate

  • make check passes locally
  • New/changed tests run offline — no network, no API key
  • Architecture contracts kept (make arch) — no new import-linter exceptions
  • No unittest.mock outside tests/contracts/
  • Ubiquitous language respected (ARCHITECTURE §3)

Scope discipline

  • Nothing further-deferred (server/DB/account/streaming/export) was built
  • No ARCHITECTURE §11 tripwires introduced

Public contracts

  • Exit codes (0/1/2/3) unchanged
  • YAML suite format unchanged — provider: xai / provider: openrouter are new values of the
    existing free-form provider: field, not a schema change
  • Trace JSON shape unchanged

Docs

Risks

  • Compat providers ship unpriced by design. pricing.yaml carries only Anthropic rows today;
    the OpenAI adapter (v0.2) is already unpriced, so cost is advisory None. Fabricating xAI/OpenRouter
    prices offline would violate the "never a guess" rule and make _meta.source wrong. Pricing is a
    data-only follow-up (or user pricing_file).
  • Live tests exercise real endpoints only when keys are present; CI never runs them.

Follow-ups

…ter)

Generalize OpenAIGateway (name/base_url/stop_reason_key, defaults byte-identical
to the plain OpenAI path) and add an OPENAI_COMPATIBLE registry in composition so
providers speaking the OpenAI Chat Completions wire format are a data row, not a
new adapter. Register xai (reference) and openrouter (single-key live path).
application/loop.py unchanged; the openai.py translation is reused verbatim.

Closes #71.
@csmatar csmatar added this to the v0.4 Model Breadth milestone Aug 3, 2026
@csmatar csmatar added enhancement New feature or request provider Model provider / adapter support labels Aug 3, 2026
@csmatar
csmatar merged commit f52b894 into main Aug 3, 2026
5 checks passed
@csmatar
csmatar deleted the feat/openai-compatible-provider-seam branch August 3, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request provider Model provider / adapter support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provider: OpenAI-compatible provider seam (+ Grok/xAI reference)

1 participant