From 7675c01c5cf583f7c5b69c0eba468cde5131f5fa Mon Sep 17 00:00:00 2001 From: JinHyuk Sung <163989462+sjh9714@users.noreply.github.com> Date: Thu, 21 May 2026 19:49:29 +0900 Subject: [PATCH] fix(billing): hide budget-complete prompt for free zero-budget plans (#2300) --- app/src/hooks/useUsageState.test.ts | 4 ++-- app/src/hooks/useUsageState.ts | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/hooks/useUsageState.test.ts b/app/src/hooks/useUsageState.test.ts index cf16453f1..352b7c0a4 100644 --- a/app/src/hooks/useUsageState.test.ts +++ b/app/src/hooks/useUsageState.test.ts @@ -114,7 +114,7 @@ describe('useUsageState', () => { mockLoadAISettings.mockResolvedValue(ALL_OPENHUMAN_AI_SETTINGS); }); - it('does not treat free users with zero recurring budget as exhausted', async () => { + it('does not show the completed-budget message for free users with zero recurring budget', async () => { const { useUsageState } = await import('./useUsageState'); mockGetCurrentPlan.mockResolvedValue(freePlan()); mockGetTeamUsage.mockResolvedValue(buildUsage()); @@ -127,7 +127,7 @@ describe('useUsageState', () => { expect(result.current.isFreeTier).toBe(true); expect(result.current.isBudgetExhausted).toBe(false); - expect(result.current.shouldShowBudgetCompletedMessage).toBe(true); + expect(result.current.shouldShowBudgetCompletedMessage).toBe(false); expect(result.current.isAtLimit).toBe(false); expect(result.current.usagePct).toBe(0); }); diff --git a/app/src/hooks/useUsageState.ts b/app/src/hooks/useUsageState.ts index 3b4566bc2..79d460248 100644 --- a/app/src/hooks/useUsageState.ts +++ b/app/src/hooks/useUsageState.ts @@ -165,12 +165,10 @@ export function useUsageState(): UsageState { ? teamUsage.cycleBudgetUsd > 0.01 && teamUsage.remainingUsd <= 0.01 : false; - // Some users have no included recurring budget at all. They still need the - // completed-budget warning in chat even though they are not in an exhausted - // paid cycle — but only when their chat actually flows through OpenHuman. - const rawShouldShowBudgetCompletedMessage = teamUsage - ? rawBudgetExhausted || (teamUsage.cycleBudgetUsd <= 0.01 && teamUsage.remainingUsd <= 0.01) - : false; + // Only show the completed-budget warning for an actually exhausted + // recurring budget. Free plans with no recurring budget should not look like + // they have exhausted a paid/included cycle (#2129). + const rawShouldShowBudgetCompletedMessage = rawBudgetExhausted; const isBudgetExhausted = !isFullyRoutedAway && rawBudgetExhausted; const shouldShowBudgetCompletedMessage =