From e0e9f63b0be10f2e286a0eaf4587c013e0662d79 Mon Sep 17 00:00:00 2001 From: Dallin Romney Date: Tue, 14 Oct 2025 00:07:34 -0700 Subject: [PATCH] fix: check key type for onboarding modal --- core/config/usesFreeTrialApiKey.ts | 35 ++++++++++++++++++++++++++++++ core/llm/streamChat.ts | 4 ++-- core/llm/utils/starterCredits.ts | 4 ++-- gui/src/hooks/useCredits.ts | 8 +++++-- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/core/config/usesFreeTrialApiKey.ts b/core/config/usesFreeTrialApiKey.ts index 0ffbf2db5b2..2d4bc04bd45 100644 --- a/core/config/usesFreeTrialApiKey.ts +++ b/core/config/usesFreeTrialApiKey.ts @@ -29,6 +29,31 @@ export function usesCreditsBasedApiKey( return false; } +/** + * Helper function to determine if the config uses specifically a free trial API key (not models add-on) + * @param config The serialized config object + * @returns true if the config is using any free trial models + */ +export function usesFreeTrialApiKey( + config: BrowserSerializedContinueConfig | null, +): boolean { + if (!config) { + return false; + } + + const modelsByRole = config.modelsByRole; + const allModels = [...Object.values(modelsByRole)].flat(); + + try { + const hasFreeTrial = allModels?.some(modelUsesFreeTrialApiKey); + return hasFreeTrial; + } catch (e) { + console.error("Error checking for free trial API key:", e); + } + + return false; +} + const modelUsesCreditsBasedApiKey = (model: ModelDescription) => { if (!model.apiKeyLocation) { return false; @@ -40,3 +65,13 @@ const modelUsesCreditsBasedApiKey = (model: ModelDescription) => { secretType === SecretType.FreeTrial || secretType === SecretType.ModelsAddOn ); }; + +const modelUsesFreeTrialApiKey = (model: ModelDescription) => { + if (!model.apiKeyLocation) { + return false; + } + + const secretType = decodeSecretLocation(model.apiKeyLocation).secretType; + + return secretType === SecretType.FreeTrial; +}; diff --git a/core/llm/streamChat.ts b/core/llm/streamChat.ts index 4fba3b22661..cf5f3d2c53d 100644 --- a/core/llm/streamChat.ts +++ b/core/llm/streamChat.ts @@ -1,7 +1,7 @@ import { fetchwithRequestOptions } from "@continuedev/fetch"; import { ChatMessage, IDE, PromptLog } from ".."; import { ConfigHandler } from "../config/ConfigHandler"; -import { usesCreditsBasedApiKey } from "../config/usesFreeTrialApiKey"; +import { usesFreeTrialApiKey } from "../config/usesFreeTrialApiKey"; import { FromCoreProtocol, ToCoreProtocol } from "../protocol"; import { IMessenger, Message } from "../protocol/messenger"; import { Telemetry } from "../util/posthog"; @@ -178,7 +178,7 @@ async function checkForOutOfStarterCredits( if ( config && creditStatus && - isOutOfStarterCredits(usesCreditsBasedApiKey(config), creditStatus) + isOutOfStarterCredits(usesFreeTrialApiKey(config), creditStatus) ) { void messenger.request("freeTrialExceeded", undefined); } diff --git a/core/llm/utils/starterCredits.ts b/core/llm/utils/starterCredits.ts index 9f0d021d74b..4bd8105d3e4 100644 --- a/core/llm/utils/starterCredits.ts +++ b/core/llm/utils/starterCredits.ts @@ -1,11 +1,11 @@ import { CreditStatus } from "../../control-plane/client"; export function isOutOfStarterCredits( - usingModelsAddOnApiKey: boolean, + usingFreeTrialApiKey: boolean, creditStatus: CreditStatus, ): boolean { return ( - usingModelsAddOnApiKey && + usingFreeTrialApiKey && !creditStatus.hasCredits && !creditStatus.hasPurchasedCredits ); diff --git a/gui/src/hooks/useCredits.ts b/gui/src/hooks/useCredits.ts index 8f2a4bb45b7..3e4ee9fcca0 100644 --- a/gui/src/hooks/useCredits.ts +++ b/gui/src/hooks/useCredits.ts @@ -1,4 +1,7 @@ -import { usesCreditsBasedApiKey } from "core/config/usesFreeTrialApiKey"; +import { + usesCreditsBasedApiKey, + usesFreeTrialApiKey, +} from "core/config/usesFreeTrialApiKey"; import { CreditStatus } from "core/control-plane/client"; import { isOutOfStarterCredits } from "core/llm/utils/starterCredits"; import { useCallback, useContext, useEffect, useState } from "react"; @@ -13,9 +16,10 @@ export function useCreditStatus() { const hasExitedFreeTrial = getLocalStorage("hasExitedFreeTrial"); const usingCreditsBasedApiKey = usesCreditsBasedApiKey(config); + const usingFreeTrialApiKey = usesFreeTrialApiKey(config); const isUsingFreeTrial = usingCreditsBasedApiKey && !hasExitedFreeTrial; const outOfStarterCredits = creditStatus - ? isOutOfStarterCredits(usingCreditsBasedApiKey, creditStatus) + ? isOutOfStarterCredits(usingFreeTrialApiKey, creditStatus) : false; const refreshCreditStatus = useCallback(async () => {