diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index e63ca7dd5b..c549442f3a 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -1,6 +1,6 @@ import React, { memo, useCallback, useEffect, useMemo, useState } from "react" import { convertHeadersToObject } from "./utils/headers" -import { useDebounce } from "react-use" +import { useDebounce, useEvent } from "react-use" import { VSCodeLink } from "@vscode/webview-ui-toolkit/react" import { @@ -55,6 +55,7 @@ import { TemperatureControl } from "./TemperatureControl" import { RateLimitSecondsControl } from "./RateLimitSecondsControl" import { BedrockCustomArn } from "./providers/BedrockCustomArn" import { buildDocLink } from "@src/utils/docLinks" +import { ExtensionMessage } from "@roo/shared/ExtensionMessage" export interface ApiOptionsProps { uriScheme: string | undefined @@ -152,27 +153,19 @@ const ApiOptions = ({ } }, [initialRouterModels, defaultRouterModels]) - // Listen for specific provider model updates - useEffect(() => { - const handler = (event: MessageEvent) => { - const message = event.data - if (message.type === "providerModelsResponse" && message.payload) { - const { provider, models, error } = message.payload as { - provider: keyof RouterModels - models?: ModelRecord - error?: string - } - if (provider && models && !error) { - setCurrentRouterModels((prevModels) => ({ - ...prevModels, // prevModels is now guaranteed to be RouterModels - [provider]: models, - })) - } + // Listen for specific provider model updates using useEvent + useEvent("message", (event: MessageEvent) => { + const message = event.data + if (message.type === "providerModelsResponse" && message.payload) { + const { provider, models, error } = message.payload + if (provider && models && !error) { + setCurrentRouterModels((prevModels) => ({ + ...prevModels, + [provider]: models, + })) } } - window.addEventListener("message", handler) - return () => window.removeEventListener("message", handler) - }, []) + }) // Update `apiModelId` whenever `selectedModelId` changes. useEffect(() => { diff --git a/webview-ui/src/components/settings/providers/LiteLLM.tsx b/webview-ui/src/components/settings/providers/LiteLLM.tsx index aae723b663..413db6c812 100644 --- a/webview-ui/src/components/settings/providers/LiteLLM.tsx +++ b/webview-ui/src/components/settings/providers/LiteLLM.tsx @@ -1,5 +1,6 @@ -import { useCallback, useState, useEffect } from "react" +import { useCallback, useState } from "react" import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react" +import { useEvent } from "react-use" import { ProviderSettings, RouterModels, litellmDefaultModelId } from "@roo/shared/api" import { vscode } from "@src/utils/vscode" @@ -9,7 +10,7 @@ import { useAppTranslation } from "@src/i18n/TranslationContext" import { inputEventTransform } from "../transforms" import { ModelPicker } from "../ModelPicker" import { WebviewMessage } from "@roo/shared/WebviewMessage" -import { ExtensionMessage, ProviderModelsResponsePayload } from "@roo/shared/ExtensionMessage" +import { ExtensionMessage } from "@roo/shared/ExtensionMessage" type LiteLLMProps = { apiConfiguration: ProviderSettings @@ -49,28 +50,19 @@ export const LiteLLM = ({ apiConfiguration, setApiConfigurationField, routerMode vscode.postMessage(message) } - // Effect to listen for model refresh responses - useEffect(() => { - const handler = (event: MessageEvent) => { - const message = event.data - if ( - message.type === "providerModelsResponse" && - message.payload && - message.payload.provider === "litellm" - ) { - const payload = message.payload as ProviderModelsResponsePayload - if (payload.error) { - setRefreshStatus("error") - setRefreshError(payload.error) - } else { - setRefreshStatus("success") - // Parent (ApiOptions.tsx) will handle updating the routerModels prop for ModelPicker - } + // Listen for model refresh responses using useEvent + useEvent("message", (event: MessageEvent) => { + const message = event.data + if (message.type === "providerModelsResponse" && message.payload && message.payload.provider === "litellm") { + if (message.payload.error) { + setRefreshStatus("error") + setRefreshError(message.payload.error) + } else { + setRefreshStatus("success") + // Parent (ApiOptions.tsx) will handle updating the routerModels prop for ModelPicker } } - window.addEventListener("message", handler) - return () => window.removeEventListener("message", handler) - }, []) + }) return ( <>