Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions webview-ui/src/context/ExtensionStateContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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(
<ExtensionStateContextProvider>
<div />
</ExtensionStateContextProvider>,
)

// 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(
<ExtensionStateContextProvider>
<div />
</ExtensionStateContextProvider>,
)

// 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" })
})
})
})