Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/providers/label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export function canonicalUsageProviderLabel(provider: string): string {
return provider === "chatgpt" || provider === "openai-multi" ? "openai" : provider;
}

const LEGACY_MAIN_ACCOUNT_PROVIDER_LABELS = new Set(["openai-main", "chatgpt-main", "openai-multi-main"]);

export function usesApiKeyAccount(provider: Pick<OcxProviderConfig, "authMode" | "_apiKeyAttempt">): boolean {
return provider.authMode === "key"
|| (provider.authMode === undefined && !!provider._apiKeyAttempt?.reference);
Expand All @@ -29,11 +31,14 @@ export function baseProviderLabel(provider: string): string {
const cut = provider.lastIndexOf("-");
if (cut <= 0) return canonicalUsageProviderLabel(provider);
const suffix = provider.slice(cut + 1);
// `-main` is the legacy log label for the main Codex account (MAIN_CODEX_ACCOUNT_ID). New entries
// log under the base provider name, but historical `<provider>-main` entries must still collapse.
// `-main` was the legacy log label for the main Codex account (MAIN_CODEX_ACCOUNT_ID). Restrict
// that compatibility mapping to the known Codex provider labels so configured providers whose
// names naturally end in `-main` remain distinct.
// ChatGPT auth-pool and OpenAI passthrough are the same Codex/OpenAI usage surface, so display
// summaries normalize them to one `openai` row after recognized main/pool suffixes are removed.
if (suffix === "main") return canonicalUsageProviderLabel(provider.slice(0, cut));
if (LEGACY_MAIN_ACCOUNT_PROVIDER_LABELS.has(provider)) {
return canonicalUsageProviderLabel(provider.slice(0, cut));
}
return CODEX_ACCOUNT_LOG_LABEL_RE.test(suffix) ? canonicalUsageProviderLabel(provider.slice(0, cut)) : provider;
}

Expand Down
6 changes: 3 additions & 3 deletions tests/usage/usage-cost.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1510,13 +1510,13 @@ describe("Codex account pricing identity", () => {
}
});

test("only recognized historical phex and main suffixes retain the existing fallback", () => {
test("only recognized historical phex suffixes retain the existing fallback", () => {
refreshUserCostOverlays(config([]));
const custom = { ...row, provider: "legacy" };
for (const provider of ["legacy-pabcdef", "legacy-main"]) {
for (const provider of ["legacy-pabcdef"]) {
expect(resolveMatchedPrice(provider, modelId, [custom], [])?.cost4).toEqual(RATE);
}
for (const provider of ["legacy-unknown", "legacy-pABCDEF", "legacy-pabcde", "legacy-oabcdef", "legacy-__main__"]) {
for (const provider of ["legacy-unknown", "legacy-pABCDEF", "legacy-pabcde", "legacy-oabcdef", "legacy-__main__", "legacy-main"]) {
expect(resolveMatchedPrice(provider, modelId, [custom], [])).toBeNull();
}
});
Expand Down
10 changes: 8 additions & 2 deletions tests/usage/usage-provider-label.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ describe("baseProviderLabel", () => {
expect(baseProviderLabel("anthropic-pabc123")).toBe("anthropic");
});

test("strips the legacy -main suffix so historical main-account rows aggregate", () => {
test("keeps configured provider names ending in -main distinct", () => {
expect(baseProviderLabel("openrouter-main")).toBe("openrouter-main");
expect(baseProviderLabel("azure-main")).toBe("azure-main");
});

test("strips the legacy -main suffix from the known Codex provider labels", () => {
expect(baseProviderLabel("openai-main")).toBe("openai");
expect(baseProviderLabel("codex-main")).toBe("codex");
expect(baseProviderLabel("chatgpt-main")).toBe("openai");
expect(baseProviderLabel("openai-multi-main")).toBe("openai");
});

test("keeps suffixes that do not match the pool log-label shape", () => {
Expand Down
10 changes: 10 additions & 0 deletions tests/usage/usage-summary.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,16 @@ describe("summarizeUsage", () => {
]);
});

test("keeps configured providers ending in -main in distinct usage rows", () => {
const entries: PersistedUsageEntry[] = [
entry({ ts: FIXED_NOW - 1, provider: "openrouter", model: "shared-model", usageStatus: "reported", usage: { inputTokens: 4, outputTokens: 1 }, totalTokens: 5 }),
entry({ ts: FIXED_NOW - 2, provider: "openrouter-main", model: "shared-model", usageStatus: "reported", usage: { inputTokens: 2, outputTokens: 1 }, totalTokens: 3 }),
];
const sum = summarizeUsage(entries, "30d", FIXED_NOW);
expect(sum.providers.map(provider => provider.provider).sort()).toEqual(["openrouter", "openrouter-main"]);
expect(sum.models.map(model => model.provider).sort()).toEqual(["openrouter", "openrouter-main"]);
});

test("keeps one logical combo request while attributing both physical attempts", () => {
const combo = entry({
ts: FIXED_NOW - 1,
Expand Down
Loading