From 1780d810280d68cac7f694830e51164e8ef86b62 Mon Sep 17 00:00:00 2001 From: Continue Agent Date: Tue, 14 Oct 2025 07:15:46 +0000 Subject: [PATCH] Fix onboarding modal showing for paid users The isOutOfStarterCredits function now checks optedInToFreeTrial to ensure that only free trial users who have run out of credits see the onboarding dialog. Paid users who have purchased credits (even if exhausted) will not see the onboarding modal. Fixes CON-4405 Generated with [Continue](https://continue.dev) Co-Authored-By: Continue Co-authored-by: Username --- core/llm/utils/starterCredits.test.ts | 82 +++++++++++++++++++++++++++ core/llm/utils/starterCredits.ts | 13 +++++ 2 files changed, 95 insertions(+) create mode 100644 core/llm/utils/starterCredits.test.ts diff --git a/core/llm/utils/starterCredits.test.ts b/core/llm/utils/starterCredits.test.ts new file mode 100644 index 00000000000..401ef5de424 --- /dev/null +++ b/core/llm/utils/starterCredits.test.ts @@ -0,0 +1,82 @@ +import { describe, expect, it } from "vitest"; +import { CreditStatus } from "../../control-plane/client"; +import { isOutOfStarterCredits } from "./starterCredits"; + +describe("isOutOfStarterCredits", () => { + it("should return true for free trial users who have run out of credits", () => { + const creditStatus: CreditStatus = { + optedInToFreeTrial: true, + hasCredits: false, + creditBalance: 0, + hasPurchasedCredits: false, + }; + + expect(isOutOfStarterCredits(true, creditStatus)).toBe(true); + }); + + it("should return false for paid users who have run out of credits", () => { + const creditStatus: CreditStatus = { + optedInToFreeTrial: true, + hasCredits: false, + creditBalance: 0, + hasPurchasedCredits: true, + }; + + expect(isOutOfStarterCredits(true, creditStatus)).toBe(false); + }); + + it("should return false for free trial users who still have credits", () => { + const creditStatus: CreditStatus = { + optedInToFreeTrial: true, + hasCredits: true, + creditBalance: 1000, + hasPurchasedCredits: false, + }; + + expect(isOutOfStarterCredits(true, creditStatus)).toBe(false); + }); + + it("should return false for paid users who still have credits", () => { + const creditStatus: CreditStatus = { + optedInToFreeTrial: true, + hasCredits: true, + creditBalance: 5000, + hasPurchasedCredits: true, + }; + + expect(isOutOfStarterCredits(true, creditStatus)).toBe(false); + }); + + it("should return false when not using credits-based API key", () => { + const creditStatus: CreditStatus = { + optedInToFreeTrial: true, + hasCredits: false, + creditBalance: 0, + hasPurchasedCredits: false, + }; + + expect(isOutOfStarterCredits(false, creditStatus)).toBe(false); + }); + + it("should return false for users who did not opt into free trial", () => { + const creditStatus: CreditStatus = { + optedInToFreeTrial: false, + hasCredits: false, + creditBalance: 0, + hasPurchasedCredits: false, + }; + + expect(isOutOfStarterCredits(true, creditStatus)).toBe(false); + }); + + it("should return false for paid users who never opted into free trial", () => { + const creditStatus: CreditStatus = { + optedInToFreeTrial: false, + hasCredits: false, + creditBalance: 0, + hasPurchasedCredits: true, + }; + + expect(isOutOfStarterCredits(true, creditStatus)).toBe(false); + }); +}); diff --git a/core/llm/utils/starterCredits.ts b/core/llm/utils/starterCredits.ts index 9f0d021d74b..f9aaec0c378 100644 --- a/core/llm/utils/starterCredits.ts +++ b/core/llm/utils/starterCredits.ts @@ -1,11 +1,24 @@ import { CreditStatus } from "../../control-plane/client"; +/** + * Determines if a user has exhausted their free trial starter credits. + * This should ONLY return true for users who: + * 1. Are using credits-based API keys (free trial or models add-on) + * 2. Have no credits remaining + * 3. Have NOT purchased credits (i.e., are still on free trial) + * 4. Have opted into the free trial + * + * Paid users who have exhausted their purchased credits should NOT trigger this. + */ export function isOutOfStarterCredits( usingModelsAddOnApiKey: boolean, creditStatus: CreditStatus, ): boolean { + // Only show onboarding for free trial users who have run out of credits + // Do NOT show for paid users who have purchased credits, even if they've run out return ( usingModelsAddOnApiKey && + creditStatus.optedInToFreeTrial && !creditStatus.hasCredits && !creditStatus.hasPurchasedCredits );