1- import { Fragment , memo , useCallback , useEffect , useMemo , useState } from "react"
1+ import { Fragment , memo , useCallback , useEffect , useMemo , useState , useRef } from "react"
22import { useEvent , useDebounce , useInterval } from "react-use"
33import { Checkbox , Dropdown , Pane , type DropdownOption } from "vscrui"
44import {
@@ -40,6 +40,8 @@ import {
4040 requestyDefaultModelInfo ,
4141 pearAiModels ,
4242 pearAiDefaultModelId ,
43+ pearAiDefaultModelInfo ,
44+ PEARAI_URL ,
4345} from "../../../../src/shared/api"
4446import { ExtensionMessage } from "../../../../src/shared/ExtensionMessage"
4547
@@ -52,17 +54,6 @@ import { validateApiConfiguration, validateModelId } from "@/utils/validate"
5254import { ApiErrorMessage } from "./ApiErrorMessage"
5355import { ThinkingBudget } from "./ThinkingBudget"
5456
55- const modelsByProvider : Record < string , Record < string , ModelInfo > > = {
56- anthropic : anthropicModels ,
57- bedrock : bedrockModels ,
58- vertex : vertexModels ,
59- gemini : geminiModels ,
60- "openai-native" : openAiNativeModels ,
61- deepseek : deepSeekModels ,
62- mistral : mistralModels ,
63- pearai : pearAiModels ,
64- }
65-
6657interface ApiOptionsProps {
6758 uriScheme : string | undefined
6859 apiConfiguration : ApiConfiguration
@@ -101,6 +92,9 @@ const ApiOptions = ({
10192 } )
10293
10394 const [ openAiModels , setOpenAiModels ] = useState < Record < string , ModelInfo > | null > ( null )
95+ const [ pearAiModels , setPearAiModels ] = useState < Record < string , ModelInfo > > ( {
96+ [ pearAiDefaultModelId ] : pearAiDefaultModelInfo ,
97+ } )
10498
10599 const [ anthropicBaseUrlSelected , setAnthropicBaseUrlSelected ] = useState ( ! ! apiConfiguration ?. anthropicBaseUrl )
106100 const [ azureApiVersionSelected , setAzureApiVersionSelected ] = useState ( ! ! apiConfiguration ?. azureApiVersion )
@@ -123,10 +117,16 @@ const ApiOptions = ({
123117 [ setApiConfigurationField ] ,
124118 )
125119
126- const { selectedProvider, selectedModelId, selectedModelInfo } = useMemo (
127- ( ) => normalizeApiConfiguration ( apiConfiguration ) ,
128- [ apiConfiguration ] ,
129- )
120+ const { selectedProvider, selectedModelId, selectedModelInfo } = useMemo ( ( ) => {
121+ const result = normalizeApiConfiguration ( apiConfiguration )
122+ if ( result . selectedProvider === "pearai" ) {
123+ return {
124+ ...result ,
125+ selectedModelInfo : pearAiModels [ result . selectedModelId ] || pearAiModels [ pearAiDefaultModelId ] ,
126+ }
127+ }
128+ return result
129+ } , [ apiConfiguration , pearAiModels ] )
130130
131131 // Debounced refresh model updates, only executed 250ms after the user
132132 // stops typing.
@@ -167,6 +167,28 @@ const ApiOptions = ({
167167 ] ,
168168 )
169169
170+ // Fetch PearAI models when provider is selected
171+ useEffect ( ( ) => {
172+ if ( selectedProvider === "pearai" ) {
173+ const fetchPearAiModels = async ( ) => {
174+ try {
175+ const res = await fetch ( `${ PEARAI_URL } /getPearAIAgentModels` )
176+ if ( ! res . ok ) throw new Error ( "Failed to fetch models" )
177+ const config = await res . json ( )
178+
179+ if ( config . models && Object . keys ( config . models ) . length > 0 ) {
180+ console . log ( "Models successfully loaded from server" )
181+ setPearAiModels ( config . models )
182+ }
183+ } catch ( error ) {
184+ console . error ( "Error fetching PearAI models:" , error )
185+ }
186+ }
187+
188+ fetchPearAiModels ( )
189+ }
190+ } , [ selectedProvider , setPearAiModels ] )
191+
170192 useEffect ( ( ) => {
171193 const apiValidationResult =
172194 validateApiConfiguration ( apiConfiguration ) ||
@@ -227,6 +249,28 @@ const ApiOptions = ({
227249
228250 useEvent ( "message" , onMessage )
229251
252+ const modelsByProvider = useMemo (
253+ ( ) => ( {
254+ anthropic : anthropicModels ,
255+ bedrock : bedrockModels ,
256+ vertex : vertexModels ,
257+ gemini : geminiModels ,
258+ "openai-native" : openAiNativeModels ,
259+ deepseek : deepSeekModels ,
260+ mistral : mistralModels ,
261+ pearai : pearAiModels ,
262+ glama : glamaModels ,
263+ openrouter : openRouterModels ,
264+ unbound : unboundModels ,
265+ requesty : requestyModels ,
266+ openai : openAiModels || { } ,
267+ ollama : { } ,
268+ lmstudio : { } ,
269+ "vscode-lm" : { } ,
270+ } ) ,
271+ [ pearAiModels , glamaModels , openRouterModels , unboundModels , requestyModels , openAiModels ] ,
272+ )
273+
230274 const selectedProviderModelOptions : DropdownOption [ ] = useMemo (
231275 ( ) =>
232276 modelsByProvider [ selectedProvider ]
@@ -238,7 +282,7 @@ const ApiOptions = ({
238282 } ) ) ,
239283 ]
240284 : [ ] ,
241- [ selectedProvider ] ,
285+ [ selectedProvider , modelsByProvider ] ,
242286 )
243287
244288 return (
0 commit comments