From eff72eea3fc7e6ddc6096b67d37a4f31a4d7f775 Mon Sep 17 00:00:00 2001 From: sam hoang Date: Mon, 20 Jan 2025 23:07:40 +0700 Subject: [PATCH] fix: config-manager --- .../src/components/settings/ApiOptions.tsx | 46 ++++++++----------- .../components/settings/GlamaModelPicker.tsx | 11 ++++- .../components/settings/OpenAiModelPicker.tsx | 13 ++++-- .../settings/OpenRouterModelPicker.tsx | 11 ++++- .../src/context/ExtensionStateContext.tsx | 22 ++++++++- 5 files changed, 71 insertions(+), 32 deletions(-) diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index cad94a8..677086d 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -45,7 +45,7 @@ interface ApiOptionsProps { } const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) => { - const { apiConfiguration, setApiConfiguration, uriScheme, onUpdateApiConfig } = useExtensionState() + const { apiConfiguration, setApiConfiguration, uriScheme, handleInputChange } = useExtensionState() const [ollamaModels, setOllamaModels] = useState([]) const [lmStudioModels, setLmStudioModels] = useState([]) const [vsCodeLmModels, setVsCodeLmModels] = useState([]) @@ -53,12 +53,6 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = const [azureApiVersionSelected, setAzureApiVersionSelected] = useState(!!apiConfiguration?.azureApiVersion) const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false) - const handleInputChange = (field: keyof ApiConfiguration) => (event: any) => { - const apiConfig = { ...apiConfiguration, [field]: event.target.value } - onUpdateApiConfig(apiConfig) - // setApiConfiguration(apiConfig) - } - const { selectedProvider, selectedModelId, selectedModelInfo } = useMemo(() => { return normalizeApiConfiguration(apiConfiguration) }, [apiConfiguration]) @@ -162,7 +156,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.apiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("apiKey")} + onChange={handleInputChange("apiKey")} placeholder="Enter API Key..."> Anthropic API Key @@ -183,7 +177,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.anthropicBaseUrl || ""} style={{ width: "100%", marginTop: 3 }} type="url" - onInput={handleInputChange("anthropicBaseUrl")} + onChange={handleInputChange("anthropicBaseUrl")} placeholder="Default: https://api.anthropic.com" /> )} @@ -212,7 +206,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.glamaApiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("glamaApiKey")} + onChange={handleInputChange("glamaApiKey")} placeholder="Enter API Key..."> Glama API Key @@ -241,7 +235,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.openAiNativeApiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("openAiNativeApiKey")} + onChange={handleInputChange("openAiNativeApiKey")} placeholder="Enter API Key..."> OpenAI API Key @@ -269,7 +263,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.mistralApiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("mistralApiKey")} + onChange={handleInputChange("mistralApiKey")} placeholder="Enter API Key..."> Mistral API Key @@ -300,7 +294,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.openRouterApiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("openRouterApiKey")} + onChange={handleInputChange("openRouterApiKey")} placeholder="Enter API Key..."> OpenRouter API Key @@ -346,7 +340,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.awsAccessKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("awsAccessKey")} + onChange={handleInputChange("awsAccessKey")} placeholder="Enter Access Key..."> AWS Access Key @@ -354,7 +348,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.awsSecretKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("awsSecretKey")} + onChange={handleInputChange("awsSecretKey")} placeholder="Enter Secret Key..."> AWS Secret Key @@ -362,7 +356,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.awsSessionToken || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("awsSessionToken")} + onChange={handleInputChange("awsSessionToken")} placeholder="Enter Session Token..."> AWS Session Token @@ -428,7 +422,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = Google Cloud Project ID @@ -486,7 +480,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.geminiApiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("geminiApiKey")} + onChange={handleInputChange("geminiApiKey")} placeholder="Enter API Key..."> Gemini API Key @@ -514,7 +508,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.openAiBaseUrl || ""} style={{ width: "100%" }} type="url" - onInput={handleInputChange("openAiBaseUrl")} + onChange={handleInputChange("openAiBaseUrl")} placeholder={"Enter base URL..."}> Base URL @@ -522,7 +516,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.openAiApiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("openAiApiKey")} + onChange={handleInputChange("openAiApiKey")} placeholder="Enter API Key..."> API Key @@ -552,7 +546,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = )} @@ -576,14 +570,14 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.lmStudioBaseUrl || ""} style={{ width: "100%" }} type="url" - onInput={handleInputChange("lmStudioBaseUrl")} + onChange={handleInputChange("lmStudioBaseUrl")} placeholder={"Default: http://localhost:1234"}> Base URL (optional) Model ID @@ -645,7 +639,7 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.deepSeekApiKey || ""} style={{ width: "100%" }} type="password" - onInput={handleInputChange("deepSeekApiKey")} + onChange={handleInputChange("deepSeekApiKey")} placeholder="Enter API Key..."> DeepSeek API Key @@ -735,14 +729,14 @@ const ApiOptions = ({ apiErrorMessage, modelIdErrorMessage }: ApiOptionsProps) = value={apiConfiguration?.ollamaBaseUrl || ""} style={{ width: "100%" }} type="url" - onInput={handleInputChange("ollamaBaseUrl")} + onChange={handleInputChange("ollamaBaseUrl")} placeholder={"Default: http://localhost:11434"}> Base URL (optional) Model ID diff --git a/webview-ui/src/components/settings/GlamaModelPicker.tsx b/webview-ui/src/components/settings/GlamaModelPicker.tsx index 6d1dee1..c4767eb 100644 --- a/webview-ui/src/components/settings/GlamaModelPicker.tsx +++ b/webview-ui/src/components/settings/GlamaModelPicker.tsx @@ -167,9 +167,18 @@ const GlamaModelPicker: React.FC = () => { placeholder="Search and select a model..." value={searchTerm} onInput={(e) => { - handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase()) + const newModelId = (e.target as HTMLInputElement)?.value?.toLowerCase() + const apiConfig = { + ...apiConfiguration, + openAiModelId: newModelId, + } + setApiConfiguration(apiConfig) + setSearchTerm(newModelId) setIsDropdownVisible(true) }} + onChange={(e) => { + handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase()) + }} onFocus={() => setIsDropdownVisible(true)} onKeyDown={handleKeyDown} style={{ width: "100%", zIndex: GLAMA_MODEL_PICKER_Z_INDEX, position: "relative" }}> diff --git a/webview-ui/src/components/settings/OpenAiModelPicker.tsx b/webview-ui/src/components/settings/OpenAiModelPicker.tsx index 71957e7..9455f2a 100644 --- a/webview-ui/src/components/settings/OpenAiModelPicker.tsx +++ b/webview-ui/src/components/settings/OpenAiModelPicker.tsx @@ -25,8 +25,6 @@ const OpenAiModelPicker: React.FC = () => { } setApiConfiguration(apiConfig) onUpdateApiConfig(apiConfig) - - setSearchTerm(newModelId) } useEffect(() => { @@ -161,9 +159,18 @@ const OpenAiModelPicker: React.FC = () => { placeholder="Search and select a model..." value={searchTerm} onInput={(e) => { - handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase()) + const newModelId = (e.target as HTMLInputElement)?.value?.toLowerCase() + const apiConfig = { + ...apiConfiguration, + openAiModelId: newModelId, + } + setApiConfiguration(apiConfig) + setSearchTerm(newModelId) setIsDropdownVisible(true) }} + onChange={(e) => { + handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase()) + }} onFocus={() => setIsDropdownVisible(true)} onKeyDown={handleKeyDown} style={{ width: "100%", zIndex: OPENAI_MODEL_PICKER_Z_INDEX, position: "relative" }}> diff --git a/webview-ui/src/components/settings/OpenRouterModelPicker.tsx b/webview-ui/src/components/settings/OpenRouterModelPicker.tsx index a9508b8..a19246d 100644 --- a/webview-ui/src/components/settings/OpenRouterModelPicker.tsx +++ b/webview-ui/src/components/settings/OpenRouterModelPicker.tsx @@ -167,9 +167,18 @@ const OpenRouterModelPicker: React.FC = () => { placeholder="Search and select a model..." value={searchTerm} onInput={(e) => { - handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase()) + const newModelId = (e.target as HTMLInputElement)?.value?.toLowerCase() + const apiConfig = { + ...apiConfiguration, + openAiModelId: newModelId, + } + setApiConfiguration(apiConfig) + setSearchTerm(newModelId) setIsDropdownVisible(true) }} + onChange={(e) => { + handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase()) + }} onFocus={() => setIsDropdownVisible(true)} onKeyDown={handleKeyDown} style={{ width: "100%", zIndex: OPENROUTER_MODEL_PICKER_Z_INDEX, position: "relative" }}> diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 868bc97..3963aaf 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -65,6 +65,7 @@ export interface ExtensionStateContextType extends ExtensionState { setExperimentalDiffStrategy: (value: boolean) => void autoApprovalEnabled?: boolean setAutoApprovalEnabled: (value: boolean) => void + handleInputChange: (field: keyof ApiConfiguration) => (event: any) => void } export const ExtensionStateContext = createContext(undefined) @@ -117,15 +118,33 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode const onUpdateApiConfig = useCallback((apiConfig: ApiConfiguration) => { setState((currentState) => { + console.log("onUpdateApiConfig", currentState, apiConfig) + vscode.postMessage({ type: "upsertApiConfiguration", - text: currentState.currentApiConfigName, // Access latest state + text: currentState.currentApiConfigName, apiConfiguration: apiConfig, }) return currentState // No state update needed }) }, []) + const handleInputChange = useCallback( + (field: keyof ApiConfiguration) => (event: any) => { + setState((currentState) => { + console.log("handleInputChange", currentState, event) + + vscode.postMessage({ + type: "upsertApiConfiguration", + text: currentState.currentApiConfigName, + apiConfiguration: { ...currentState.apiConfiguration, [field]: event.target.value }, + }) + return currentState // No state update needed + }) + }, + [], + ) + const handleMessage = useCallback( (event: MessageEvent) => { const message: ExtensionMessage = event.data @@ -258,6 +277,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setExperimentalDiffStrategy: (value) => setState((prevState) => ({ ...prevState, experimentalDiffStrategy: value })), setAutoApprovalEnabled: (value) => setState((prevState) => ({ ...prevState, autoApprovalEnabled: value })), + handleInputChange, } return {children}