fix: improve onboarding flow for non-free tier accounts

- Use raw API tier IDs (e.g., 'free-tier', 'g1-pro-tier') consistently
- Pass DEFAULT_PROJECT_ID for non-free tiers during onboarding
- Fix free tier detection to use .includes('free') instead of exact match
- Upgrade onboarding error logs from debug to warn for visibility
- Add debug logging for onboarding request parameters

Fixes onboarding failures for Pro/Ultra accounts that were previously
failing because the API requires a project ID for paid tier onboarding.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Badri Narayanan S
2026-01-15 20:25:10 +05:30
parent 9809337190
commit 9ffb83ab74
2 changed files with 23 additions and 8 deletions

View File

@@ -186,10 +186,19 @@ export async function discoverProject(token) {
tierSource = 'allowedTiers';
}
tierId = tierId || 'FREE';
tierId = tierId || 'free-tier';
logger.info(`[AccountManager] Onboarding user with tier: ${tierId} (source: ${tierSource})`);
const onboardedProject = await onboardUser(token, tierId);
// Check if this is a free tier (raw API values contain 'free')
const isFree = tierId.toLowerCase().includes('free');
// For non-free tiers, pass DEFAULT_PROJECT_ID as the GCP project
// The API requires a project for paid tier onboarding
const onboardedProject = await onboardUser(
token,
tierId,
isFree ? null : DEFAULT_PROJECT_ID
);
if (onboardedProject) {
logger.success(`[AccountManager] Successfully onboarded, project: ${onboardedProject}`);
return onboardedProject;

View File

@@ -37,8 +37,8 @@ export function getDefaultTierId(allowedTiers) {
* Onboard a user to get a managed project
*
* @param {string} token - OAuth access token
* @param {string} tierId - Tier ID (e.g., 'FREE', 'PRO', 'ULTRA')
* @param {string} [projectId] - Optional GCP project ID (required for non-FREE tiers)
* @param {string} tierId - Tier ID (raw API value, e.g., 'free-tier', 'standard-tier', 'g1-pro-tier')
* @param {string} [projectId] - Optional GCP project ID (required for non-free tiers)
* @param {number} [maxAttempts=10] - Maximum polling attempts
* @param {number} [delayMs=5000] - Delay between polling attempts
* @returns {Promise<string|null>} Managed project ID or null if failed
@@ -59,11 +59,16 @@ export async function onboardUser(token, tierId, projectId = null, maxAttempts =
metadata
};
// Non-FREE tiers require a cloudaicompanionProject
if (tierId !== 'FREE' && projectId) {
// Check if this is a free tier (handles raw API values like 'free-tier')
const isFree = tierId.toLowerCase().includes('free');
// Non-free tiers require a cloudaicompanionProject
if (!isFree && projectId) {
requestBody.cloudaicompanionProject = projectId;
}
logger.debug(`[Onboarding] Starting onboard with tierId: ${tierId}, projectId: ${projectId}, isFree: ${isFree}`);
for (const endpoint of ONBOARD_USER_ENDPOINTS) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
@@ -79,7 +84,7 @@ export async function onboardUser(token, tierId, projectId = null, maxAttempts =
if (!response.ok) {
const errorText = await response.text();
logger.debug(`[Onboarding] onboardUser failed at ${endpoint}: ${response.status} - ${errorText}`);
logger.warn(`[Onboarding] onboardUser failed at ${endpoint}: ${response.status} - ${errorText}`);
break; // Try next endpoint
}
@@ -101,11 +106,12 @@ export async function onboardUser(token, tierId, projectId = null, maxAttempts =
await sleep(delayMs);
}
} catch (error) {
logger.debug(`[Onboarding] onboardUser error at ${endpoint}:`, error.message);
logger.warn(`[Onboarding] onboardUser error at ${endpoint}:`, error.message);
break; // Try next endpoint
}
}
}
logger.warn(`[Onboarding] All onboarding attempts failed for tierId: ${tierId}`);
return null;
}