@@ -141,7 +141,8 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
141141 if (
142142 this . credentials === null ||
143143 this . credentials . clientToken !== credentials . clientToken ||
144- this . credentials . sessionId !== credentials . sessionId
144+ this . credentials . sessionId !== credentials . sessionId ||
145+ this . credentials . organizationId !== credentials . organizationId
145146 ) {
146147 this . transitionToAttemptingSession ( credentials )
147148 }
@@ -174,6 +175,7 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
174175
175176 this . changeState ( "attempting-session" )
176177
178+ this . timer . stop ( )
177179 this . timer . start ( )
178180 }
179181
@@ -248,8 +250,10 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
248250 *
249251 * This method initiates the authentication flow by generating a state parameter
250252 * and opening the browser to the authorization URL.
253+ *
254+ * @param landingPageSlug Optional slug of a specific landing page (e.g., "supernova", "special-offer", etc.)
251255 */
252- public async login ( ) : Promise < void > {
256+ public async login ( landingPageSlug ?: string ) : Promise < void > {
253257 try {
254258 const vscode = await importVscode ( )
255259
@@ -267,11 +271,17 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
267271 state,
268272 auth_redirect : `${ vscode . env . uriScheme } ://${ publisher } .${ name } ` ,
269273 } )
270- const url = `${ getRooCodeApiUrl ( ) } /extension/sign-in?${ params . toString ( ) } `
274+
275+ // Use landing page URL if slug is provided, otherwise use default sign-in URL
276+ const url = landingPageSlug
277+ ? `${ getRooCodeApiUrl ( ) } /l/${ landingPageSlug } ?${ params . toString ( ) } `
278+ : `${ getRooCodeApiUrl ( ) } /extension/sign-in?${ params . toString ( ) } `
279+
271280 await vscode . env . openExternal ( vscode . Uri . parse ( url ) )
272281 } catch ( error ) {
273- this . log ( `[auth] Error initiating Roo Code Cloud auth: ${ error } ` )
274- throw new Error ( `Failed to initiate Roo Code Cloud authentication: ${ error } ` )
282+ const context = landingPageSlug ? ` (landing page: ${ landingPageSlug } )` : ""
283+ this . log ( `[auth] Error initiating Roo Code Cloud auth${ context } : ${ error } ` )
284+ throw new Error ( `Failed to initiate Roo Code Cloud authentication${ context } : ${ error } ` )
275285 }
276286 }
277287
@@ -461,6 +471,42 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
461471 return this . credentials ?. organizationId || null
462472 }
463473
474+ /**
475+ * Switch to a different organization context
476+ * @param organizationId The organization ID to switch to, or null for personal account
477+ */
478+ public async switchOrganization ( organizationId : string | null ) : Promise < void > {
479+ if ( ! this . credentials ) {
480+ throw new Error ( "Cannot switch organization: not authenticated" )
481+ }
482+
483+ // Update the stored credentials with the new organization ID
484+ const updatedCredentials : AuthCredentials = {
485+ ...this . credentials ,
486+ organizationId : organizationId ,
487+ }
488+
489+ // Store the updated credentials, handleCredentialsChange will handle the update
490+ await this . storeCredentials ( updatedCredentials )
491+ }
492+
493+ /**
494+ * Get all organization memberships for the current user
495+ * @returns Array of organization memberships
496+ */
497+ public async getOrganizationMemberships ( ) : Promise < CloudOrganizationMembership [ ] > {
498+ if ( ! this . credentials ) {
499+ return [ ]
500+ }
501+
502+ try {
503+ return await this . clerkGetOrganizationMemberships ( )
504+ } catch ( error ) {
505+ this . log ( `[auth] Failed to get organization memberships: ${ error } ` )
506+ return [ ]
507+ }
508+ }
509+
464510 private async clerkSignIn ( ticket : string ) : Promise < AuthCredentials > {
465511 const formData = new URLSearchParams ( )
466512 formData . append ( "strategy" , "ticket" )
@@ -645,9 +691,14 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
645691 }
646692
647693 private async clerkGetOrganizationMemberships ( ) : Promise < CloudOrganizationMembership [ ] > {
694+ if ( ! this . credentials ) {
695+ this . log ( "[auth] Cannot get organization memberships: missing credentials" )
696+ return [ ]
697+ }
698+
648699 const response = await fetch ( `${ getClerkBaseUrl ( ) } /v1/me/organization_memberships` , {
649700 headers : {
650- Authorization : `Bearer ${ this . credentials ! . clientToken } ` ,
701+ Authorization : `Bearer ${ this . credentials . clientToken } ` ,
651702 "User-Agent" : this . userAgent ( ) ,
652703 } ,
653704 signal : AbortSignal . timeout ( 10000 ) ,
0 commit comments