-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[Feature] Declarative "Custom Provider": bring-your-own endpoint + JSONPath field mapping #1735
Copy link
Copy link
Open
Labels
P3Low-risk cleanup, docs, polish, ergonomics, or speculative feature.Low-risk cleanup, docs, polish, ergonomics, or speculative feature.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.ClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:auth-providerThis issue is about auth, provider routing, model choice, or SecretRef resolution.This issue is about auth, provider routing, model choice, or SecretRef resolution.issue-rating: 🌊 off-meta tidepoolIssue quality rating does not apply to this item.Issue quality rating does not apply to this item.
Description
Metadata
Metadata
Assignees
Labels
P3Low-risk cleanup, docs, polish, ergonomics, or speculative feature.Low-risk cleanup, docs, polish, ergonomics, or speculative feature.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.ClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.ClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:auth-providerThis issue is about auth, provider routing, model choice, or SecretRef resolution.This issue is about auth, provider routing, model choice, or SecretRef resolution.issue-rating: 🌊 off-meta tidepoolIssue quality rating does not apply to this item.Issue quality rating does not apply to this item.
TL;DR
Let users define their own provider in
config.json: a custom endpoint (URL + auth) plus a small JSONPath-style mapping that translates that provider's usage response into CodexBar'sRateWindow/ProviderCostSnapshot/ProviderIdentitySnapshotfields — no Swift code, no fork, no release wait.Why I'm filing this
I self-host an LLM gateway. CodexBar can't see it. And I'm far from alone — the issue tracker tells the story. Every few weeks someone files "please add my provider":
Each is real demand, and each — today — needs a whole Swift module:
ProviderDescriptor+SettingsReader+UsageFetcher+ProviderImplementation+ an SVG icon + localization. That's right for first-class providers. For the long tail of self-hosted / in-house / boutique gateways it's a bottleneck for everyone: the user can't see their quota, and the maintainer drowns in one-off integrations nobody can really maintain.There's already a beautiful template: #264 → LLM Proxy (
LLMProxyUsageFetcher) and LiteLLM. Both already take base URL + API key and hit a known schema. The only thing keeping them from being generic is that the endpoint path and field extraction are hardcoded in Swift (DecodableCodingKeys+ a hand-writtentoUsageSnapshot()). Even the twoquota_groupsshapes (array vs keyed) are special-cased in code.That hand-coded mapping is exactly the seam a declarative provider would fill.
What I'd love
A
type: "custom"provider where a user supplies:Sketch
{ "providers": { "acme-gateway": { "type": "custom", "label": "Acme Gateway", "icon": "proxy", // built-in fallback, or path to a user svg "baseURL": "https://gw.acme.io", "auth": { "header": "Authorization", "prefix": "Bearer ", "env": "ACME_GATEWAY_API_KEY" }, "usage": { "method": "GET", "path": "/v1/quota" }, "mapping": { "usedPercent": "$.quota.used_pct", "remainingPercent": "$.quota.remaining_pct", "resetsAt": "$.quota.reset_at", // ISO-8601 "windowMinutes": "$.quota.window_min", "costUsed": "$.spend.usd", "costCurrency": "USD", "costPeriod": "Approx. spend", "organization": "$.plan.name", "loginMethod": "$.credits.balance_str" } } } }Field binding (reuses types CodexBar already has)
RateWindow.usedPercent$.quota.used_pctRateWindow.remainingPercent$.quota.remaining_pctRateWindow.resetsAt$.quota.reset_atRateWindow.windowMinutes$.quota.window_minProviderCostSnapshot.used$.spend.usdProviderIdentitySnapshot.accountOrganization$.plan.nameProviderIdentitySnapshot.loginMethod$.credits.balance_strFill in only the fields the endpoint exposes; the rest stay empty, same as any provider with sparse data.
Why this is low-risk
type: "custom"entry exists. All 53 existing providers keep working unchanged.UsageSnapshotthe menu already renders — no new UI primitives.Alternatives considered
Open questions (happy to defer)
POST/force-refresh like LLM Proxy, or keep custom providers poll-only?extraRateWindows).Happy to prototype or draft the docs. 🙌