Skip to content
Open
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
41 changes: 40 additions & 1 deletion packages/shared/src/usageLimits.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ describe("/usage-limits", () => {
expect(report?.accounts[0]?.limits.resetCredits?.availableCount).toBe(3);
});

it("keeps accounts and custom instances separate, filtering by driver", () => {
it("keeps unidentified custom instances separate, filtering by driver", () => {
const report = collectProviderUsageLimits(
selected.instanceId,
[
Expand Down Expand Up @@ -991,6 +991,45 @@ describe("/usage-limits", () => {
expect(report?.notices).toEqual([]);
});

it("keeps the freshest usable duplicate and its latest native credits", () => {
const failed = provider({
auth: selected.auth,
usageLimits: { ...limits, unavailable: { reason: "probeFailed" } },
});
const credited = provider({
instanceId: ProviderInstanceId.make("codex-credit"),
auth: selected.auth,
usageLimits: {
checkedAt: "2026-09-03T11:20:00.000Z",
windows: [{ ...window, usedPercent: 50 }],
resetCredits: { availableCount: 2 },
},
});
const freshest = provider({
instanceId: ProviderInstanceId.make("codex-fresh"),
auth: selected.auth,
usageLimits: {
checkedAt: "2026-09-03T11:30:00.000Z",
windows: [{ ...window, usedPercent: 55 }],
},
});
const report = collectProviderUsageLimits(
failed.instanceId,
[failed, credited, freshest],
sources,
now,
);
expect(report?.accounts.map((account) => account.id)).toEqual(["codex-fresh", "hub:oss"]);
expect(report?.accounts[0]).toMatchObject({
limits: {
checkedAt: "2026-09-03T11:30:00.000Z",
windows: [{ usedPercent: 55 }],
resetCredits: { availableCount: 2 },
},
resetCreditInput: { instanceId: "codex-credit" },
});
});

it("supports a source-only provider and keeps duplicates when the native probe failed", () => {
expect(
collectProviderUsageLimits(selected.instanceId, [provider({})], sources, now)?.accounts.map(
Expand Down
56 changes: 44 additions & 12 deletions packages/shared/src/usageLimits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,11 +630,40 @@ export function collectProviderUsageLimits(
): UsageLimitsReport | null {
const selected = providers.find((provider) => provider.instanceId === instanceId);
if (!selected || !hasProviderUsageLimits(selected.driver, providers, sources)) return null;
const native = providersWithLimits(providers).filter(
(provider) => provider.driver === selected.driver,
);
const nativeAccounts = new Set(
native.flatMap((provider) => {
const nativeByAccount = new Map<
string,
{ provider: ServerProvider; creditProvider: ServerProvider | null }
>();
for (const provider of providersWithLimits(providers)) {
if (provider.driver !== selected.driver || !provider.usageLimits) continue;
const key =
accountKey(provider.driver, provider.auth.email, provider.usageLimits) ??
Comment thread
stephenjason89 marked this conversation as resolved.
`instance:${provider.instanceId}`;
const previous = nativeByAccount.get(key);
const previousUsable = previous ? limitsNotice(previous.provider.usageLimits!) === null : false;
const usable = limitsNotice(provider.usageLimits) === null;
const providerWins =
!previous ||
(usable && !previousUsable) ||
(usable === previousUsable &&
Date.parse(provider.usageLimits.checkedAt) >
Date.parse(previous.provider.usageLimits!.checkedAt));
const previousCredit = previous?.creditProvider;
const creditProvider =
provider.usageLimits.resetCredits &&
(!previousCredit ||
Date.parse(provider.usageLimits.checkedAt) >
Date.parse(previousCredit.usageLimits!.checkedAt))
? provider
: (previousCredit ?? null);
nativeByAccount.set(key, {
provider: providerWins ? provider : previous.provider,
creditProvider,
});
}
const native = [...nativeByAccount.values()];
const nativeAccountKeys = new Set(
native.flatMap(({ provider }) => {
const key = accountKey(provider.driver, provider.auth.email, provider.usageLimits);
return key && provider.usageLimits?.windows.length && !provider.usageLimits.unavailable
? [key]
Expand All @@ -643,7 +672,7 @@ export function collectProviderUsageLimits(
);
const accounts: Array<UsageLimitsReport["accounts"][number]> = [];
const notices: string[] = [];
for (const provider of native) {
for (const { provider, creditProvider } of native) {
if (!provider.usageLimits) continue;
const key = accountKey(provider.driver, provider.auth.email, provider.usageLimits);
const hubCredits = sources
Expand All @@ -670,9 +699,12 @@ export function collectProviderUsageLimits(
const hubCreditId = hubCredits?.account.usageLimits.resetCredits?.nextCreditId;
const showHubCredits =
hubCredits &&
(!provider.usageLimits.resetCredits ||
(!creditProvider ||
Date.parse(hubCredits.account.usageLimits.checkedAt) >
Date.parse(provider.usageLimits.checkedAt));
Date.parse(creditProvider.usageLimits!.checkedAt));
const shownCredits = showHubCredits
? hubCredits.account.usageLimits.resetCredits
: creditProvider?.usageLimits?.resetCredits;
accounts.push({
id: provider.instanceId,
driver: provider.driver,
Expand All @@ -686,20 +718,20 @@ export function collectProviderUsageLimits(
accountId: hubCredits.account.id,
creditId: hubCreditId,
}
: { instanceId: provider.instanceId },
: { instanceId: creditProvider?.instanceId ?? provider.instanceId },
...(provider.displayName ? { displayName: provider.displayName } : {}),
...(provider.accentColor ? { accentColor: provider.accentColor } : {}),
...(provider.auth.email ? { email: provider.auth.email } : {}),
limits: showHubCredits
? { ...provider.usageLimits, resetCredits: hubCredits.account.usageLimits.resetCredits }
limits: shownCredits
? { ...provider.usageLimits, resetCredits: shownCredits }
: provider.usageLimits,
});
}
for (const source of sources) {
const matching = source.accounts.filter((account) => account.driver === selected.driver);
for (const account of matching) {
const key = accountKey(account.driver, account.email, account.usageLimits);
if (key && nativeAccounts.has(key)) continue;
if (key && nativeAccountKeys.has(key)) continue;
accounts.push({
id: `${source.id}:${account.id}`,
driver: account.driver,
Expand Down
Loading