Skip to content

Commit 99f2e72

Browse files
committed
feat(welcome): navigate to 3rd-party provider when auth completes without model selection
When a user signs up via Roo Code Cloud but doesn't select a provider model during the signup flow, they should be taken to the provider selection screen with '3rd-party Provider' pre-selected instead of automatically being configured with the Roo provider. Changes: - WebAuthService: Store roo-auth-skip-model flag when providerModel is not provided - ExtensionState: Add cloudAuthSkipModel field to pass flag to webview - ClineProvider: Read and pass the flag to webview state - WebviewMessage: Add clearCloudAuthSkipModel message type - webviewMessageHandler: Add handler to clear the flag - WelcomeViewProvider: Check flag on auth completion and navigate to custom provider selection - Tests: Add test for skip model flag behavior
1 parent e58d1b0 commit 99f2e72

File tree

7 files changed

+75
-16
lines changed

7 files changed

+75
-16
lines changed

packages/cloud/src/WebAuthService.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,15 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
331331

332332
await this.storeCredentials(credentials)
333333

334-
// Store the provider model if provided
334+
// Store the provider model if provided, or flag that no model was selected
335335
if (providerModel) {
336336
await this.context.globalState.update("roo-provider-model", providerModel)
337+
await this.context.globalState.update("roo-auth-skip-model", undefined)
337338
this.log(`[auth] Stored provider model: ${providerModel}`)
339+
} else {
340+
// No model was selected during signup - flag this for the webview
341+
await this.context.globalState.update("roo-auth-skip-model", true)
342+
this.log(`[auth] No provider model selected during signup`)
338343
}
339344

340345
const vscode = await importVscode()

packages/cloud/src/__tests__/WebAuthService.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,38 @@ describe("WebAuthService", () => {
395395
await authService.handleCallback("auth-code", storedState, null, "xai/grok-code-fast-1")
396396

397397
expect(mockContext.globalState.update).toHaveBeenCalledWith("roo-provider-model", "xai/grok-code-fast-1")
398+
expect(mockContext.globalState.update).toHaveBeenCalledWith("roo-auth-skip-model", undefined)
398399
expect(mockLog).toHaveBeenCalledWith("[auth] Stored provider model: xai/grok-code-fast-1")
399400
})
400401

402+
it("should set skip model flag when provider model is NOT provided in callback", async () => {
403+
const storedState = "valid-state"
404+
mockContext.globalState.get.mockReturnValue(storedState)
405+
406+
// Mock successful Clerk sign-in response
407+
const mockResponse = {
408+
ok: true,
409+
json: () =>
410+
Promise.resolve({
411+
response: { created_session_id: "session-123" },
412+
}),
413+
headers: {
414+
get: (header: string) => (header === "authorization" ? "Bearer token-123" : null),
415+
},
416+
}
417+
mockFetch.mockResolvedValue(mockResponse)
418+
419+
const vscode = await import("vscode")
420+
const mockShowInfo = vi.fn()
421+
vi.mocked(vscode.window.showInformationMessage).mockImplementation(mockShowInfo)
422+
423+
// Call without provider model
424+
await authService.handleCallback("auth-code", storedState, null)
425+
426+
expect(mockContext.globalState.update).toHaveBeenCalledWith("roo-auth-skip-model", true)
427+
expect(mockLog).toHaveBeenCalledWith("[auth] No provider model selected during signup")
428+
})
429+
401430
it("should handle Clerk API errors", async () => {
402431
const storedState = "valid-state"
403432
mockContext.globalState.get.mockReturnValue(storedState)

src/core/webview/ClineProvider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2025,6 +2025,7 @@ export class ClineProvider
20252025
enterBehavior: enterBehavior ?? "send",
20262026
cloudUserInfo,
20272027
cloudIsAuthenticated: cloudIsAuthenticated ?? false,
2028+
cloudAuthSkipModel: this.context.globalState.get<boolean>("roo-auth-skip-model") ?? false,
20282029
cloudOrganizations,
20292030
sharingEnabled: sharingEnabled ?? false,
20302031
publicSharingEnabled: publicSharingEnabled ?? false,

src/core/webview/webviewMessageHandler.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,6 +2384,12 @@ export const webviewMessageHandler = async (
23842384

23852385
break
23862386
}
2387+
case "clearCloudAuthSkipModel": {
2388+
// Clear the flag that indicates auth completed without model selection
2389+
await provider.context.globalState.update("roo-auth-skip-model", undefined)
2390+
await provider.postStateToWebview()
2391+
break
2392+
}
23872393
case "switchOrganization": {
23882394
try {
23892395
const organizationId = message.organizationId ?? null

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ export type ExtensionState = Pick<
335335

336336
cloudUserInfo: CloudUserInfo | null
337337
cloudIsAuthenticated: boolean
338+
cloudAuthSkipModel?: boolean // Flag indicating auth completed without model selection (user should pick 3rd-party provider)
338339
cloudApiUrl?: string
339340
cloudOrganizations?: CloudOrganizationMembership[]
340341
sharingEnabled: boolean

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export interface WebviewMessage {
122122
| "searchFiles"
123123
| "toggleApiConfigPin"
124124
| "hasOpenedModeSelector"
125+
| "clearCloudAuthSkipModel"
125126
| "cloudButtonClicked"
126127
| "rooCloudSignIn"
127128
| "cloudLandingPageSignIn"

webview-ui/src/components/welcome/WelcomeViewProvider.tsx

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ type ProviderOption = "roo" | "custom"
2727
type AuthOrigin = "landing" | "providerSelection"
2828

2929
const WelcomeViewProvider = () => {
30-
const { apiConfiguration, currentApiConfigName, setApiConfiguration, uriScheme, cloudIsAuthenticated } =
31-
useExtensionState()
30+
const {
31+
apiConfiguration,
32+
currentApiConfigName,
33+
setApiConfiguration,
34+
uriScheme,
35+
cloudIsAuthenticated,
36+
cloudAuthSkipModel,
37+
} = useExtensionState()
3238
const { t } = useAppTranslation()
3339
const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined)
3440
const [selectedProvider, setSelectedProvider] = useState<ProviderOption | null>(null)
@@ -39,23 +45,33 @@ const WelcomeViewProvider = () => {
3945
const [manualErrorMessage, setManualErrorMessage] = useState<boolean | undefined>(undefined)
4046
const manualUrlInputRef = useRef<HTMLInputElement | null>(null)
4147

42-
// When auth completes during the provider signup flow, save the Roo config
43-
// This will cause showWelcome to become false and navigate to chat
48+
// When auth completes during the provider signup flow, either:
49+
// 1. If user skipped model selection (cloudAuthSkipModel=true), navigate to provider selection with "custom" selected
50+
// 2. Otherwise, save the Roo config and navigate to chat
4451
useEffect(() => {
4552
if (cloudIsAuthenticated && authInProgress) {
46-
// Auth completed from provider signup flow - save the config now
47-
const rooConfig: ProviderSettings = {
48-
apiProvider: "roo",
53+
if (cloudAuthSkipModel) {
54+
// User skipped model selection during signup - navigate to provider selection with 3rd-party selected
55+
setSelectedProvider("custom")
56+
setAuthInProgress(false)
57+
setShowManualEntry(false)
58+
// Clear the flag so it doesn't affect future flows
59+
vscode.postMessage({ type: "clearCloudAuthSkipModel" })
60+
} else {
61+
// Auth completed from provider signup flow - save the config now
62+
const rooConfig: ProviderSettings = {
63+
apiProvider: "roo",
64+
}
65+
vscode.postMessage({
66+
type: "upsertApiConfiguration",
67+
text: currentApiConfigName,
68+
apiConfiguration: rooConfig,
69+
})
70+
setAuthInProgress(false)
71+
setShowManualEntry(false)
4972
}
50-
vscode.postMessage({
51-
type: "upsertApiConfiguration",
52-
text: currentApiConfigName,
53-
apiConfiguration: rooConfig,
54-
})
55-
setAuthInProgress(false)
56-
setShowManualEntry(false)
5773
}
58-
}, [cloudIsAuthenticated, authInProgress, currentApiConfigName])
74+
}, [cloudIsAuthenticated, authInProgress, currentApiConfigName, cloudAuthSkipModel])
5975

6076
// Focus the manual URL input when it becomes visible
6177
useEffect(() => {

0 commit comments

Comments
 (0)