Repository navigation
feat(pricing): apply base-provider price overlays to all account log labels #3817
Description
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—baseProviderLabelsrc/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:
resolveMatchedPrice("openai-conta2", "gpt-6-astra")resolves to the samecost4asresolveMatchedPrice("openai", "gpt-6-astra").- The collapse happens for any suffix that does not itself correspond to a configured provider.
- 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: createsopenai-conta2,main, etc. as full provider entries. Breaks on restart because they fail Zod schema validation withoutbaseUrl, 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
baseProviderLabelso 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
lidge-jun commentedon Sep 6, 2026
리뷰 · 우선순위 46 / 80
이슈 #3817은 Logs 화면의
~$가격 칸이 계정용 로그 라벨에서 비어 보이는 문제를 다룹니다. 지금devHEAD(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에 복붙하는 우회는 ZodbaseUrl검증에 막혀 재시작마다 오버레이가 통째로 날아간다는 점도 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 dashtests/usage/usage-provider-label.test.ts -
openai-apikey/anthropic-claude비접힘 계약이 있어, “하이픈 뒤면 무조건 접기” 수정은 이 테스트·실제 커스텀 프로바이더와 충돌함메인테이너의 판단이 필요한 지점
baseProviderLabel전역에 넓힐지,resolveMatchedPrice(가격 전용)에만 둘지main/[po]hex6만인지, 운영자가 붙인 자유 형식(conta2)까지인지activeConfiguredProviders만으로 충분한지)o[hex6]가 provider 필드에 붙는 경로가 있는지도 같이 확인할지너의 추천
이슈는 열고, 라벨은 그대로 둔다. 수정 PR은
baseProviderLabel을 마음대로 넓히지 말고, 가격 해석(resolveMatchedPrice근처)에서 “설정된 베이스의 계정 로그 라벨”만openai오버레이로 물려 주게 한다. 회귀 테스트에openai-conta2→베이스 가격 적중과openai-apikey/anthropic-claude비접힘을 함께 넣는다. 제보의 “미설정 접미사 전부 접기”는 거절에 가깝게 보고, 범위가 합의된 뒤에만 착수한다.이 댓글은 grok-bot이 작성했습니다
Merge pull request #3903: resolve account labels through pricing iden…
lidge-jun commentedon Sep 7, 2026
Fixed on
devby #3903 (mergecb1113f6d): 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.fix(usage): resolve account prices through provider identity [skip ci]
fix(usage): resolve account prices through provider identity [skip ci]
Merge pull request lidge-jun#3903: resolve account labels through pri…