1- import { memo , useCallback , useMemo , useState } from "react"
1+ import React , { memo , useCallback , useEffect , useMemo , useState } from "react"
22import { useDebounce , useEvent } from "react-use"
33import { Checkbox , Dropdown , Pane , type DropdownOption } from "vscrui"
44import { VSCodeLink , VSCodeRadio , VSCodeRadioGroup , VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
@@ -42,23 +42,25 @@ import { ModelInfoView } from "./ModelInfoView"
4242import { DROPDOWN_Z_INDEX } from "./styles"
4343import { ModelPicker } from "./ModelPicker"
4444import { TemperatureControl } from "./TemperatureControl"
45+ import { validateApiConfiguration , validateModelId } from "@/utils/validate"
46+ import ApiErrorMessage from "./ApiErrorMessage"
4547
4648interface ApiOptionsProps {
4749 uriScheme : string | undefined
4850 apiConfiguration : ApiConfiguration
4951 setApiConfigurationField : < K extends keyof ApiConfiguration > ( field : K , value : ApiConfiguration [ K ] ) => void
50- apiErrorMessage ?: string
51- modelIdErrorMessage ?: string
5252 fromWelcomeView ?: boolean
53+ errorMessage : string | undefined
54+ setErrorMessage : React . Dispatch < React . SetStateAction < string | undefined > >
5355}
5456
5557const ApiOptions = ( {
5658 uriScheme,
5759 apiConfiguration,
5860 setApiConfigurationField,
59- apiErrorMessage,
60- modelIdErrorMessage,
6161 fromWelcomeView,
62+ errorMessage,
63+ setErrorMessage,
6264} : ApiOptionsProps ) => {
6365 const [ ollamaModels , setOllamaModels ] = useState < string [ ] > ( [ ] )
6466 const [ lmStudioModels , setLmStudioModels ] = useState < string [ ] > ( [ ] )
@@ -146,6 +148,13 @@ const ApiOptions = ({
146148 ] ,
147149 )
148150
151+ useEffect ( ( ) => {
152+ const apiValidationResult =
153+ validateApiConfiguration ( apiConfiguration ) ||
154+ validateModelId ( apiConfiguration , glamaModels , openRouterModels , unboundModels )
155+ setErrorMessage ( apiValidationResult )
156+ } , [ apiConfiguration , glamaModels , openRouterModels , setErrorMessage , unboundModels ] )
157+
149158 const handleMessage = useCallback ( ( event : MessageEvent ) => {
150159 const message : ExtensionMessage = event . data
151160 switch ( message . type ) {
@@ -626,6 +635,7 @@ const ApiOptions = ({
626635 ] }
627636 />
628637 </ div >
638+ { errorMessage && < ApiErrorMessage errorMessage = { errorMessage } /> }
629639 < p
630640 style = { {
631641 fontSize : "12px" ,
@@ -705,6 +715,7 @@ const ApiOptions = ({
705715 models = { openAiModels }
706716 setApiConfigurationField = { setApiConfigurationField }
707717 defaultModelInfo = { openAiModelInfoSaneDefaults }
718+ errorMessage = { errorMessage }
708719 />
709720 < div style = { { display : "flex" , alignItems : "center" } } >
710721 < Checkbox
@@ -1068,18 +1079,6 @@ const ApiOptions = ({
10681079 />
10691080
10701081 { /* end Model Info Configuration */ }
1071-
1072- < p
1073- style = { {
1074- fontSize : "12px" ,
1075- marginTop : 3 ,
1076- color : "var(--vscode-descriptionForeground)" ,
1077- } } >
1078- < span style = { { color : "var(--vscode-errorForeground)" } } >
1079- (< span style = { { fontWeight : 500 } } > Note:</ span > Roo Code uses complex prompts and works best
1080- with Claude models. Less capable models may not work as expected.)
1081- </ span >
1082- </ p >
10831082 </ div >
10841083 ) }
10851084
@@ -1100,6 +1099,7 @@ const ApiOptions = ({
11001099 placeholder = { "e.g. meta-llama-3.1-8b-instruct" } >
11011100 < span style = { { fontWeight : 500 } } > Model ID</ span >
11021101 </ VSCodeTextField >
1102+ { errorMessage && < ApiErrorMessage errorMessage = { errorMessage } /> }
11031103
11041104 { lmStudioModels . length > 0 && (
11051105 < VSCodeRadioGroup
@@ -1245,6 +1245,12 @@ const ApiOptions = ({
12451245 placeholder = { "e.g. llama3.1" } >
12461246 < span style = { { fontWeight : 500 } } > Model ID</ span >
12471247 </ VSCodeTextField >
1248+ { errorMessage && (
1249+ < div className = "text-vscode-errorForeground text-sm" >
1250+ < span style = { { fontSize : "2em" } } className = { `codicon codicon-close align-middle mr-1` } />
1251+ { errorMessage }
1252+ </ div >
1253+ ) }
12481254 { ollamaModels . length > 0 && (
12491255 < VSCodeRadioGroup
12501256 value = {
@@ -1321,22 +1327,11 @@ const ApiOptions = ({
13211327 serviceUrl = "https://api.getunbound.ai/models"
13221328 recommendedModel = { unboundDefaultModelId }
13231329 setApiConfigurationField = { setApiConfigurationField }
1330+ errorMessage = { errorMessage }
13241331 />
13251332 </ div >
13261333 ) }
13271334
1328- { apiErrorMessage && (
1329- < p
1330- style = { {
1331- margin : "-10px 0 4px 0" ,
1332- fontSize : 12 ,
1333- color : "var(--vscode-errorForeground)" ,
1334- } } >
1335- < span style = { { fontSize : "2em" } } className = { `codicon codicon-close align-middle mr-1` } />
1336- { apiErrorMessage }
1337- </ p >
1338- ) }
1339-
13401335 { selectedProvider === "glama" && (
13411336 < ModelPicker
13421337 apiConfiguration = { apiConfiguration ?? { } }
@@ -1349,6 +1344,7 @@ const ApiOptions = ({
13491344 serviceUrl = "https://glama.ai/models"
13501345 recommendedModel = "anthropic/claude-3-7-sonnet"
13511346 setApiConfigurationField = { setApiConfigurationField }
1347+ errorMessage = { errorMessage }
13521348 />
13531349 ) }
13541350
@@ -1364,6 +1360,7 @@ const ApiOptions = ({
13641360 serviceName = "OpenRouter"
13651361 serviceUrl = "https://openrouter.ai/models"
13661362 recommendedModel = "anthropic/claude-3.7-sonnet"
1363+ errorMessage = { errorMessage }
13671364 />
13681365 ) }
13691366 { selectedProvider === "requesty" && (
@@ -1378,6 +1375,7 @@ const ApiOptions = ({
13781375 serviceName = "Requesty"
13791376 serviceUrl = "https://requesty.ai"
13801377 recommendedModel = "anthropic/claude-3-7-sonnet-latest"
1378+ errorMessage = { errorMessage }
13811379 />
13821380 ) }
13831381
@@ -1401,6 +1399,7 @@ const ApiOptions = ({
14011399 { selectedProvider === "deepseek" && createDropdown ( deepSeekModels ) }
14021400 { selectedProvider === "mistral" && createDropdown ( mistralModels ) }
14031401 </ div >
1402+ { errorMessage && < ApiErrorMessage errorMessage = { errorMessage } /> }
14041403 < ModelInfoView
14051404 selectedModelId = { selectedModelId }
14061405 modelInfo = { selectedModelInfo }
@@ -1448,18 +1447,6 @@ const ApiOptions = ({
14481447 />
14491448 </ div >
14501449 ) }
1451-
1452- { modelIdErrorMessage && (
1453- < p
1454- style = { {
1455- margin : "-10px 0 4px 0" ,
1456- fontSize : 12 ,
1457- color : "var(--vscode-errorForeground)" ,
1458- } } >
1459- < span style = { { fontSize : "2em" } } className = { `codicon codicon-close align-middle mr-1` } />
1460- { modelIdErrorMessage }
1461- </ p >
1462- ) }
14631450 </ div >
14641451 )
14651452}
0 commit comments