mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 14:19:56 +00:00
fix(accounts): prefer live codex plan over stale free tags
This commit is contained in:
@@ -104,6 +104,35 @@ function getCodexPlanAudience(quota: unknown): AccountAudience {
|
|||||||
return 'unknown';
|
return 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveCodexAudience(
|
||||||
|
identityAudience: AccountAudience,
|
||||||
|
planAudience: AccountAudience
|
||||||
|
): AccountAudience {
|
||||||
|
if (planAudience === 'unknown') {
|
||||||
|
return identityAudience;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (planAudience === 'business') {
|
||||||
|
return 'business';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identityAudience === 'business') {
|
||||||
|
return 'business';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (planAudience === 'personal') {
|
||||||
|
return 'personal';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (planAudience === 'free') {
|
||||||
|
return identityAudience === 'unknown' || identityAudience === 'free'
|
||||||
|
? 'free'
|
||||||
|
: identityAudience;
|
||||||
|
}
|
||||||
|
|
||||||
|
return identityAudience;
|
||||||
|
}
|
||||||
|
|
||||||
function getCodexPlanDetailLabel(quota: unknown): string | null {
|
function getCodexPlanDetailLabel(quota: unknown): string | null {
|
||||||
if (!quota || typeof quota !== 'object' || !('planType' in quota)) {
|
if (!quota || typeof quota !== 'object' || !('planType' in quota)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -162,7 +191,7 @@ function getVariantAudience(
|
|||||||
},
|
},
|
||||||
quota?: unknown
|
quota?: unknown
|
||||||
) {
|
) {
|
||||||
return variant.audience !== 'unknown' ? variant.audience : getCodexPlanAudience(quota);
|
return resolveCodexAudience(variant.audience, getCodexPlanAudience(quota));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVariantInlineLabel(
|
function getVariantInlineLabel(
|
||||||
@@ -176,8 +205,11 @@ function getVariantInlineLabel(
|
|||||||
quota?: unknown
|
quota?: unknown
|
||||||
) {
|
) {
|
||||||
const detailLabel = getVariantDetailLabel(variant, quota);
|
const detailLabel = getVariantDetailLabel(variant, quota);
|
||||||
|
const audience = getVariantAudience(variant, quota);
|
||||||
const audienceLabel =
|
const audienceLabel =
|
||||||
variant.audienceLabel ?? getDetailedAudienceLabel(getVariantAudience(variant, quota));
|
variant.audience === audience
|
||||||
|
? (variant.audienceLabel ?? getDetailedAudienceLabel(audience))
|
||||||
|
: getDetailedAudienceLabel(audience);
|
||||||
const composedLabel = [audienceLabel, detailLabel].filter(Boolean).join(' · ');
|
const composedLabel = [audienceLabel, detailLabel].filter(Boolean).join(' · ');
|
||||||
return composedLabel || variant.inlineLabel || null;
|
return composedLabel || variant.inlineLabel || null;
|
||||||
}
|
}
|
||||||
@@ -207,8 +239,8 @@ function getVariantMarkerLabel(
|
|||||||
|
|
||||||
const normalizedFallback =
|
const normalizedFallback =
|
||||||
compactDetailLabel?.trim() ||
|
compactDetailLabel?.trim() ||
|
||||||
variant.audienceLabel?.trim() ||
|
|
||||||
getDetailedAudienceLabel(audience) ||
|
getDetailedAudienceLabel(audience) ||
|
||||||
|
variant.audienceLabel?.trim() ||
|
||||||
variant.detailLabel?.trim();
|
variant.detailLabel?.trim();
|
||||||
return normalizedFallback?.[0]?.toUpperCase() ?? '?';
|
return normalizedFallback?.[0]?.toUpperCase() ?? '?';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,35 @@ function getCodexPlanAudience(quota: UnifiedQuotaResult | undefined): AccountAud
|
|||||||
return 'unknown';
|
return 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveCodexAudience(
|
||||||
|
identityAudience: AccountAudience,
|
||||||
|
planAudience: AccountAudience
|
||||||
|
): AccountAudience {
|
||||||
|
if (planAudience === 'unknown') {
|
||||||
|
return identityAudience;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (planAudience === 'business') {
|
||||||
|
return 'business';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identityAudience === 'business') {
|
||||||
|
return 'business';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (planAudience === 'personal') {
|
||||||
|
return 'personal';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (planAudience === 'free') {
|
||||||
|
return identityAudience === 'unknown' || identityAudience === 'free'
|
||||||
|
? 'free'
|
||||||
|
: identityAudience;
|
||||||
|
}
|
||||||
|
|
||||||
|
return identityAudience;
|
||||||
|
}
|
||||||
|
|
||||||
function getCodexPlanDetailLabel(quota: UnifiedQuotaResult | undefined): string | null {
|
function getCodexPlanDetailLabel(quota: UnifiedQuotaResult | undefined): string | null {
|
||||||
if (!quota || !('planType' in quota) || !quota.planType) {
|
if (!quota || !('planType' in quota) || !quota.planType) {
|
||||||
return null;
|
return null;
|
||||||
@@ -157,9 +186,16 @@ export function AccountSurfaceCard({
|
|||||||
normalizedProvider === 'codex' ? getCodexPlanAudience(quota) : 'unknown';
|
normalizedProvider === 'codex' ? getCodexPlanAudience(quota) : 'unknown';
|
||||||
const codexPlanDetailLabel =
|
const codexPlanDetailLabel =
|
||||||
normalizedProvider === 'codex' ? getCodexPlanDetailLabel(quota) : null;
|
normalizedProvider === 'codex' ? getCodexPlanDetailLabel(quota) : null;
|
||||||
const effectiveAudience = identity.audience !== 'unknown' ? identity.audience : codexPlanAudience;
|
const effectiveAudience =
|
||||||
|
normalizedProvider === 'codex'
|
||||||
|
? resolveCodexAudience(identity.audience, codexPlanAudience)
|
||||||
|
: identity.audience !== 'unknown'
|
||||||
|
? identity.audience
|
||||||
|
: codexPlanAudience;
|
||||||
const effectiveAudienceLabel =
|
const effectiveAudienceLabel =
|
||||||
identity.audienceLabel ?? getDetailedAudienceLabel(effectiveAudience);
|
identity.audience === effectiveAudience
|
||||||
|
? (identity.audienceLabel ?? getDetailedAudienceLabel(effectiveAudience))
|
||||||
|
: getDetailedAudienceLabel(effectiveAudience);
|
||||||
const resolvedDetailLabel = identity.detailLabel ?? codexPlanDetailLabel;
|
const resolvedDetailLabel = identity.detailLabel ?? codexPlanDetailLabel;
|
||||||
const resolvedCompactDetailLabel = identity.compactDetailLabel ?? codexPlanDetailLabel;
|
const resolvedCompactDetailLabel = identity.compactDetailLabel ?? codexPlanDetailLabel;
|
||||||
const showTierBadge =
|
const showTierBadge =
|
||||||
|
|||||||
@@ -127,4 +127,23 @@ describe('AccountSurfaceCard', () => {
|
|||||||
expect(screen.getByText('Pers')).toBeInTheDocument();
|
expect(screen.getByText('Pers')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Pro')).toBeInTheDocument();
|
expect(screen.getByText('Pro')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('lets live paid Codex plans override stale free identity badges', () => {
|
||||||
|
render(
|
||||||
|
<AccountSurfaceCard
|
||||||
|
mode="compact"
|
||||||
|
provider="codex"
|
||||||
|
accountId="user@example.com#free"
|
||||||
|
email="user@example.com"
|
||||||
|
displayEmail="user@example.com"
|
||||||
|
tokenFile="codex-user@example.com-free.json"
|
||||||
|
quota={createCodexQuotaResult({ planType: 'plus' })}
|
||||||
|
showQuota={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText('Pers')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Plus')).toBeInTheDocument();
|
||||||
|
expect(screen.queryByTitle('Free')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user