Skip to content

feat: generic OpenAI-compatible gateway quota provider (Refs #109)#110

Open
rice-as681 wants to merge 4 commits into
slkiser:mainfrom
rice-as681:feat/openai-compatible-gateway-provider
Open

feat: generic OpenAI-compatible gateway quota provider (Refs #109)#110
rice-as681 wants to merge 4 commits into
slkiser:mainfrom
rice-as681:feat/openai-compatible-gateway-provider

Conversation

@rice-as681
Copy link
Copy Markdown

@rice-as681 rice-as681 commented May 30, 2026

Refs #109

Summary

Adds a generic, config-driven openai-compatible provider for any self-hosted /
OpenAI-compatible gateway (LiteLLM, in-house/university gateways,
OpenRouter-compatible endpoints) that exposes a remaining-quota endpoint. No
vendor URL is hardcoded — the base URL is configurable — and it is bound to no
product (there is no standard quota endpoint, so it consumes a small documented
shape with an OpenRouter preset).

What changed

  • src/lib/openai-compatible.tsqueryGatewayQuota (GET <baseURL><quotaPath>,
    Bearer) → normalized {tokens, cost}; default vendor-neutral shape
    ({key, tokens:{limit,used,remaining,resets_at}, cost:{currency,limit,used,remaining}})
    plus an openrouter preset ({data:{usage,limit,limit_remaining}}).
  • src/lib/openai-compatible-config.ts — per-gateway API key via the shared
    createProviderApiKeyResolver (env <ID>_API_KEY / trusted global config
    provider.<id>.options.apiKey / auth.json) + base URL (override or
    provider.<id>.options.baseURL).
  • src/providers/openai-compatible.ts — config-driven over
    experimental.quotaToast.openaiCompatibleGateways; one provider, N gateways.
  • Config schema (types.ts, config.ts, entries.ts), registry +
    provider-metadata registration (canonical id openai-compatible), README
    (Providers table row, provider-specific setting, setup-notes section).

Design decisions (open to feedback — see #109)

  1. Config under experimental.quotaToast.openaiCompatibleGateways.
  2. matchesCurrentModel uses a fetch-time cache of the configured provider ids,
    since its (model, context) signature can't see ctx.config.
  3. Canonical id openai-compatible in enabledProviders; per-gateway ids are
    config, not metadata.

Checklist

  • Started from contributing/provider-template/
  • pnpm run typecheck ✓ · pnpm test ✓ (1040 passed) · pnpm run build
  • Tests for each auth source (env / trusted global config / auth.json) +
    fetch mappings (neutral + openrouter) + provider wrapper
  • Updated docs (README.md)
  • /quota_status auth-source diagnostics for this provider

Tested against OpenCode 1.15.12 (config schema + plugin API).

Andrew Shaw Care and others added 4 commits May 30, 2026 16:20
Core fetch+map for a generic OpenAI-compatible gateway quota endpoint
(GET <baseURL><quotaPath>, Bearer): vendor-neutral {key,tokens,cost} default
shape + an openrouter preset ({data:{usage,limit,limit_remaining}}). Null-safe;
maps to a normalized {tokens, cost}. Decision-independent of the config/registry
wiring (Refs slkiser#108). 7 unit tests, all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolve a gateway's API key via the shared createProviderApiKeyResolver, keyed
on its OpenCode provider id (env <ID>_API_KEY / trusted global config
provider.<id>.options.apiKey / auth.json), and its base URL from an explicit
override or provider.<id>.options.baseURL. Decision-independent of where the
gateway list config ultimately lives (Refs slkiser#108). 7 tests; typecheck + build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire the generic OpenAI-compatible gateway provider end to end (Refs slkiser#108):

- Config: new experimental.quotaToast.openaiCompatibleGateways list
  (providerId + optional baseURL/quotaPath/label/mapping), validated and
  applied like other settings (types.ts, config.ts) and surfaced on the
  provider context (entries.ts).
- Provider (src/providers/openai-compatible.ts): one provider covering N
  gateways — resolves each gateway's key + baseURL, polls queryGatewayQuota,
  maps the token bucket to a percent entry and cost to a value entry.
  matchesCurrentModel uses a fetch-time cache of configured provider ids
  (it can't see ctx.config) — flagged as design Q2 in slkiser#108.
- Registry + provider-metadata: register canonical id "openai-compatible"
  (label, runtime ids, shape); golden metadata test updated.
- README: Providers table row, provider-specific setting, and setup-notes
  section (neutral + openrouter mappings).

Decisions made here (config location, matchesCurrentModel caching,
enabledProviders canonical id) are open to maintainer feedback on slkiser#108.
typecheck + 1040 tests + build all green; started from contributing/provider-template/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round out the provider (Refs slkiser#109): getGatewayKeyDiagnostics reports each
configured gateway's key source/checked-paths, and /quota_status renders one
section per gateway (provider_id, quota_path, api_key_configured/source/
checked_paths), threaded from runtimeConfig.openaiCompatibleGateways. Closes the
last PR-checklist follow-up. 1042 tests + typecheck + build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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