diff --git a/packages/cli/src/commands/install.ts b/packages/cli/src/commands/install.ts index a842e9a..c05ce4a 100644 --- a/packages/cli/src/commands/install.ts +++ b/packages/cli/src/commands/install.ts @@ -82,7 +82,11 @@ export function printPlanRequired(req: PlanRequirement): void { const current = req.currentPlan ? ` (you're on ${req.currentPlan})` : '' console.log() console.log(chalk.yellow(` RoBrain cloud isn't included in your plan${current}.`)) - console.log(chalk.dim(` It needs ${req.requiredPlan} or higher.`)) + console.log(chalk.dim( + req.requiredPlan + ? ` It needs ${req.requiredPlan} or higher.` + : ' It comes with every paid plan.', + )) console.log() if (req.trialAvailable) { console.log(' ' + chalk.bold('Try it free for 14 days') + chalk.dim(' — no charge until the trial ends:')) diff --git a/packages/cli/src/lib/auth.test.ts b/packages/cli/src/lib/auth.test.ts index 6cda865..31cf992 100644 --- a/packages/cli/src/lib/auth.test.ts +++ b/packages/cli/src/lib/auth.test.ts @@ -17,7 +17,9 @@ describe('detectPlanRequirement — entitlement vs. everything else', () => { it('reads a 403 carrying a plan error code', () => { const req = detectPlanRequirement(403, { code: 'upgrade_required' }) assert.ok(req) - assert.equal(req.requiredPlan, 'Pro') // default when the API does not name one + // Unset when the API names no tier — the CLI must not invent one, since + // cloud is included with every paid plan rather than a single named tier. + assert.equal(req.requiredPlan, undefined) }) it('reads a 403 whose message names the plan, without a code', () => { diff --git a/packages/cli/src/lib/auth.ts b/packages/cli/src/lib/auth.ts index b7da3d9..d9721b2 100644 --- a/packages/cli/src/lib/auth.ts +++ b/packages/cli/src/lib/auth.ts @@ -21,8 +21,12 @@ export interface AuthResult { export interface PlanRequirement { /** Plan the account is on today, when the API reports it (e.g. "free"). */ currentPlan?: string - /** Minimum plan that includes RoBrain cloud. */ - requiredPlan: string + /** + * Minimum plan that includes RoBrain cloud, when the API names one. Left + * unset otherwise — cloud ships with every paid plan, so there is no single + * tier name the CLI can safely assume on the API's behalf. + */ + requiredPlan?: string /** Only false when the API says the trial is used up or unavailable. */ trialAvailable: boolean } @@ -55,7 +59,7 @@ export function detectPlanRequirement(status: number, body: unknown): PlanRequir if (!looksLikePlan) return null return { currentPlan: typeof b.plan === 'string' ? b.plan : undefined, - requiredPlan: typeof b.required_plan === 'string' ? b.required_plan : 'Pro', + ...(typeof b.required_plan === 'string' ? { requiredPlan: b.required_plan } : {}), trialAvailable: b.trial_available !== false, } }