Skip to content

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

Closed

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-conta2 → openai 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-20 — baseProviderLabel
  • src/codex/account-label.ts:6 — CODEX_ACCOUNT_LOG_LABEL_RE = /^p[a-f0-9]{6}$/
  • src/usage/cost.ts:176-212 — resolveMatchedPrice

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

  1. added
    enhancementNew feature or request
    catalogModel catalog, slugs, visibility, routed entries
    on Sep 6, 2026
  2. lidge-jun commented on Sep 6, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 46 / 80

    이슈 #3817은 Logs 화면의 ~$ 가격 칸이 계정용 로그 라벨에서 비어 보이는 문제를 다룹니다. 지금 dev HEAD(137d6a727, 2.46.0)의 실제 코드를 읽어 보면, 설명과 거의 그대로 맞습니다.

    가격을 찾을 때는 src/usage/cost.ts의 resolveMatchedPrice가 먼저 baseProviderLabel(provider)로 이름을 줄인 뒤, 그 이름으로 사용자 modelCosts 오버레이 → jawcode → expected-prices 순으로 찾습니다. 줄이지 못하면 resolveMatchedPriceExact가 openai-conta2 같은 문자열을 그대로 키로 쓰고, 설정에는 openai만 있으니 매칭이 실패합니다. 실패하면 UI는 의도적으로 em dash(—)를 보여 줍니다. 즉 “가격이 0원”이 아니라 “가격을 못 찾음”입니다.

    그런데 src/providers/label.ts의 baseProviderLabel은 하이픈 뒤 접미사가 리터럴 main이거나 CODEX_ACCOUNT_LOG_LABEL_RE(/^p[a-f0-9]{6}$/)일 때만 앞쪽 베이스로 접습니다. src/codex/account-label.ts에는 OAuth용 o[a-f0-9]{6}와 합친 ACCOUNT_LOG_LABEL_RE도 있지만, baseProviderLabel은 Codex용 p…만 봅니다. 그래서 openai-p104398은 openai로 잘 접히고, 제보하신 openai-conta2처럼 p+hex6가 아닌 접미사는 접히지 않습니다. 테스트(tests/usage/usage-provider-label.test.ts)도 openai-apikey, anthropic-claude는 접지 말라고 못 박아 두었습니다.

    올바른 수정은 “가격만 베이스 오버레이를 물려 주되, 하이픈이 있다고 아무 이름이나 접지 않기”입니다. resolveMatchedPrice 주석도 이미 “설정된 진짜 프로바이더(예: acme-pabcdef)는 자기 가격 네임스페이스를 유지하고, 생성된 계정 로그만 접는다”고 적혀 있습니다. 제보의 “설정에 없는 접미사는 전부 접기”는 Logs 고통은 줄이지만, baseProviderLabel이 summary·모델 신원·priority/long-context에도 쓰이므로 과접힘 위험이 큽니다. 더 안전한 방향은 (1) 가격 경로에서만 알려진 계정 로그 라벨/ACCOUNT_LOG_LABEL_RE 계열을 접거나, (2) 설정에 있는 베이스 프로바이더의 계정 라벨 목록과 대조해 접는 쪽입니다. 합성 프로바이더를 config.json에 복붙하는 우회는 Zod baseUrl 검증에 막혀 재시작마다 오버레이가 통째로 날아간다는 점도 HEAD 기준으로 설득력 있습니다.

    src/providers/label.ts:8-20 - baseProviderLabel이 main/p[hex6]만 접어서 openai-conta2 같은 계정 로그 키가 베이스 openai 오버레이에 못 닿음

    src/codex/account-label.ts:6,22-23 - CODEX_ACCOUNT_LOG_LABEL_RE만 접힘에 쓰이고, 같은 파일의 OAUTH_ACCOUNT_LOG_LABEL_RE/ACCOUNT_LOG_LABEL_RE는 가격 접힘에 연결되어 있지 않음

    src/usage/cost.ts:183-205,252-262 - resolveMatchedPrice→resolveMatchedPriceExact가 접히지 않은 키로 user overlay를 찾아, 실패 시 null → Logs ~$ em dash

    tests/usage/usage-provider-label.test.ts - openai-apikey/anthropic-claude 비접힘 계약이 있어, “하이픈 뒤면 무조건 접기” 수정은 이 테스트·실제 커스텀 프로바이더와 충돌함

    메인테이너의 판단이 필요한 지점

    • 접힘을 baseProviderLabel 전역에 넓힐지, resolveMatchedPrice(가격 전용)에만 둘지
    • 허용 접미사 범위: 공식 main/[po]hex6만인지, 운영자가 붙인 자유 형식(conta2)까지인지
    • 자유 형식까지 허용하면 “설정에 없는 하이픈 이름”과 “진짜 다른 프로바이더”를 무엇으로 구분할지 (activeConfiguredProviders만으로 충분한지)
    • OAuth o[hex6]가 provider 필드에 붙는 경로가 있는지도 같이 확인할지

    너의 추천
    이슈는 열고, 라벨은 그대로 둔다. 수정 PR은 baseProviderLabel을 마음대로 넓히지 말고, 가격 해석(resolveMatchedPrice 근처)에서 “설정된 베이스의 계정 로그 라벨”만 openai 오버레이로 물려 주게 한다. 회귀 테스트에 openai-conta2→베이스 가격 적중과 openai-apikey/anthropic-claude 비접힘을 함께 넣는다. 제보의 “미설정 접미사 전부 접기”는 거절에 가깝게 보고, 범위가 합의된 뒤에만 착수한다.

    이 댓글은 grok-bot이 작성했습니다

  3. added a commit that references this issue on Sep 7, 2026
  4. lidge-jun commented on Sep 7, 2026

    @lidge-jun
    Owner

    Fixed on dev by #3903 (merge cb1113f6d): account log labels now resolve pricing through the account→provider identity (base rate, Fast and long-context alike) instead of the raw label, so pool accounts inherit the base provider's price overlays. Ships in the next release.

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