diff --git a/src/account-manager/credentials.js b/src/account-manager/credentials.js index c37db23..6e366fa 100644 --- a/src/account-manager/credentials.js +++ b/src/account-manager/credentials.js @@ -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; diff --git a/src/account-manager/onboarding.js b/src/account-manager/onboarding.js index c4d8d70..fc2033e 100644 --- a/src/account-manager/onboarding.js +++ b/src/account-manager/onboarding.js @@ -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} 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; }