diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 7c68795040b5..6443ccad93d5 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -440,12 +440,13 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode // Watch for authentication state changes and refresh Roo models useEffect(() => { const currentAuth = state.cloudIsAuthenticated ?? false - if (!prevCloudIsAuthenticated && currentAuth) { - // User just authenticated - refresh Roo models with the new auth token + const currentProvider = state.apiConfiguration?.apiProvider + if (!prevCloudIsAuthenticated && currentAuth && currentProvider === "roo") { + // User just authenticated and Roo is the active provider - refresh Roo models vscode.postMessage({ type: "requestRooModels" }) } setPrevCloudIsAuthenticated(currentAuth) - }, [state.cloudIsAuthenticated, prevCloudIsAuthenticated]) + }, [state.cloudIsAuthenticated, prevCloudIsAuthenticated, state.apiConfiguration?.apiProvider]) const contextValue: ExtensionStateContextType = { ...state, diff --git a/webview-ui/src/context/__tests__/ExtensionStateContext.roo-auth-gate.spec.tsx b/webview-ui/src/context/__tests__/ExtensionStateContext.roo-auth-gate.spec.tsx new file mode 100644 index 000000000000..d62adf26e935 --- /dev/null +++ b/webview-ui/src/context/__tests__/ExtensionStateContext.roo-auth-gate.spec.tsx @@ -0,0 +1,75 @@ +import { render, waitFor } from "@/utils/test-utils" +import React from "react" + +vi.mock("@src/utils/vscode", () => ({ + vscode: { + postMessage: vi.fn(), + }, +})) + +import { ExtensionStateContextProvider } from "@src/context/ExtensionStateContext" +import { vscode } from "@src/utils/vscode" + +describe("ExtensionStateContext Roo auth gate", () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + function postStateMessage(state: any) { + window.dispatchEvent( + new MessageEvent("message", { + data: { + type: "state", + state, + }, + }), + ) + } + + it("does not post requestRooModels when auth flips and provider !== 'roo'", async () => { + render( + +
+ , + ) + + // Flip auth to true with a non-roo provider (anthropic) + postStateMessage({ + cloudIsAuthenticated: true, + apiConfiguration: { apiProvider: "anthropic" }, + }) + + // Should NOT fire auth-driven Roo refresh + await waitFor(() => { + const calls = (vscode.postMessage as any).mock.calls as any[][] + const hasRequest = calls.some((c) => c[0]?.type === "requestRooModels") + expect(hasRequest).toBe(false) + }) + }) + + it("posts requestRooModels when auth flips and provider === 'roo'", async () => { + render( + +
+ , + ) + + // Ensure prev false (explicit) + postStateMessage({ + cloudIsAuthenticated: false, + apiConfiguration: { apiProvider: "roo" }, + }) + + vi.clearAllMocks() + + // Flip to true with provider roo - should trigger + postStateMessage({ + cloudIsAuthenticated: true, + apiConfiguration: { apiProvider: "roo" }, + }) + + await waitFor(() => { + expect(vscode.postMessage).toHaveBeenCalledWith({ type: "requestRooModels" }) + }) + }) +})