From c7f8be5d7e262491192eb6bb3c09030e04987c3d Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Wed, 28 Jan 2026 21:35:38 -0800 Subject: [PATCH] Fix billing tier detection - use correct endpoint and pass API key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use /v1/metadata/balance endpoint (same as letta-code) - Pass API key explicitly since it may not be in process.env yet - Add debug logging for billing tier detection 🤖 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta --- src/onboard.ts | 4 +++- src/utils/model-selection.ts | 23 +++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/onboard.ts b/src/onboard.ts index 793d269..04c0a7e 100644 --- a/src/onboard.ts +++ b/src/onboard.ts @@ -372,7 +372,9 @@ async function stepModel(config: OnboardConfig, env: Record): Pr let billingTier: string | null = null; if (!isSelfHosted) { spinner.start('Checking account...'); - billingTier = await getBillingTier(); + // Pass the API key explicitly since it may not be in process.env yet + const apiKey = config.apiKey || env.LETTA_API_KEY || process.env.LETTA_API_KEY; + billingTier = await getBillingTier(apiKey); config.billingTier = billingTier ?? undefined; spinner.stop(billingTier === 'free' ? 'Free plan' : `Plan: ${billingTier || 'unknown'}`); } diff --git a/src/utils/model-selection.ts b/src/utils/model-selection.ts index e808714..dd6f0e5 100644 --- a/src/utils/model-selection.ts +++ b/src/utils/model-selection.ts @@ -23,28 +23,35 @@ export interface ModelInfo { /** * Get billing tier from Letta API + * Uses /v1/metadata/balance endpoint (same as letta-code) */ -export async function getBillingTier(): Promise { +export async function getBillingTier(apiKey?: string): Promise { try { const baseUrl = process.env.LETTA_BASE_URL || 'https://api.letta.com'; - const apiKey = process.env.LETTA_API_KEY; + const key = apiKey || process.env.LETTA_API_KEY; // Self-hosted servers don't have billing tiers if (baseUrl !== 'https://api.letta.com') { return null; } - if (!apiKey) return 'free'; + if (!key) return 'free'; - const response = await fetch(`${baseUrl}/v1/users/me/balance`, { - headers: { 'Authorization': `Bearer ${apiKey}` }, + const response = await fetch(`${baseUrl}/v1/metadata/balance`, { + headers: { 'Authorization': `Bearer ${key}` }, }); - if (!response.ok) return 'free'; + if (!response.ok) { + console.error(`[BillingTier] API returned ${response.status}`); + return 'free'; + } const data = await response.json() as { billing_tier?: string }; - return data.billing_tier?.toLowerCase() ?? 'free'; - } catch { + const tier = data.billing_tier?.toLowerCase() ?? 'free'; + console.log(`[BillingTier] Got tier: ${tier}`); + return tier; + } catch (err) { + console.error(`[BillingTier] Error:`, err); return 'free'; } }