Skip to content

feat(pricing): apply base-provider price overlays to all account log labels #3817

Description

@rrmlima

Area

Catalog / models

What are you trying to accomplish?

I need user-configured price overlays (providers.<name>.modelCosts and expected-prices.ts overlays) to apply uniformly to every account under a base provider — including the dynamically generated account log labels that appear in usage.jsonl.

Today, an overlay keyed on openai does not resolve for requests whose provider field is openai-conta2, main, or conta2, even though those are just account-qualified log labels for the same underlying openai surface. The result is an em dash in the Logs ~$ column for those requests and no cost estimate at all.

What prevents this today?

baseProviderLabel() in src/providers/label.ts collapses a provider name to its base only when the suffix after the last - matches CODEX_ACCOUNT_LOG_LABEL_RE (/^p[a-f0-9]{6}$/) or is the literal main. Account labels like conta2 (a short alphanumeric handle, not a Codex-style p-prefix label) do not match, so resolveMatchedPrice never collapses openai-conta2openai and the overlay lookup misses.

resolveMatchedPriceExact is then called with provider="openai-conta2", finds no overlay row with that exact key, and returns null.

Relevant code:

  • src/providers/label.ts:8-20baseProviderLabel
  • src/codex/account-label.ts:6CODEX_ACCOUNT_LOG_LABEL_RE = /^p[a-f0-9]{6}$/
  • src/usage/cost.ts:176-212resolveMatchedPrice

The workaround today is to manually register a provider entry in config.json for every account suffix (e.g. openai-conta2, main, conta2), each carrying a full copy of every price overlay. That breaks on every proxy restart because those synthetic entries fail schema validation (baseUrl: Invalid input: expected string, received undefined), the proxy falls back to default config, and the whole catalog plus all overlays are lost.

What should OpenCodex do?

Cost resolution should apply a base provider's price overlays to every account-qualified log label derived from it, regardless of the suffix format.

Observable requirements:

  1. resolveMatchedPrice("openai-conta2", "gpt-6-astra") resolves to the same cost4 as resolveMatchedPrice("openai", "gpt-6-astra").
  2. The collapse happens for any suffix that does not itself correspond to a configured provider.
  3. No operator action is required beyond the single base-provider overlay.

Example usage or interface

// config.json — a single overlay on the base provider
{
  "providers": {
    "openai": {
      "modelCosts": {
        "gpt-6-astra": { "input": 10, "output": 50, "cacheRead": 1, "cacheWrite": 12.5 }
      }
    }
  }
}

Expected behaviour in usage.jsonl:

provider model resolved cost
openai gpt-6-astra $10 / $50
openai-conta2 gpt-6-astra $10 / $50
main gpt-6-astra $10 / $50
conta2 gpt-6-astra $10 / $50

Alternatives or workarounds

  • Register synthetic providers in config.json: creates openai-conta2, main, etc. as full provider entries. Breaks on restart because they fail Zod schema validation without baseUrl, dropping all overlays. Fragile and unscalable.
  • Duplicate every overlay for every account suffix: same validation problem, and the suffix set is dynamic — impossible to maintain.
  • Current proposed fix: widen baseProviderLabel so any unconfigured suffix collapses to the base, then resolve overlays on the collapsed name.

Additional context

  • This matters because OAuth multi-account routing generates these labels automatically; operators cannot predict or enumerate them.
  • A synthetic-provider workaround silently zeros cost estimates after every proxy restart, which is worse than no estimate at all because it looks intentional.

Checks

  • I searched existing issues and documentation.
  • This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
  • I removed secrets and personal data.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    catalogModel catalog, slugs, visibility, routed entriesenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions