1- import { useState , useCallback , useMemo , useEffect } from "react"
2- import { useEvent } from "react-use"
1+ import { useState , useCallback , useMemo , useEffect , useRef } from "react"
32import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
43import { Checkbox } from "vscrui"
54
65import { type ProviderSettings , type ExtensionMessage , type ModelRecord , ollamaDefaultModelInfo } from "@roo-code/types"
76
87import { useAppTranslation } from "@src/i18n/TranslationContext"
98import { useRouterModels } from "@src/components/ui/hooks/useRouterModels"
9+ import { Button } from "@src/components/ui"
1010import { vscode } from "@src/utils/vscode"
1111
1212import { inputEventTransform } from "../transforms"
@@ -22,6 +22,9 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro
2222 const { t } = useAppTranslation ( )
2323
2424 const [ ollamaModels , setOllamaModels ] = useState < ModelRecord > ( { } )
25+ const [ refreshStatus , setRefreshStatus ] = useState < "idle" | "loading" | "success" | "error" > ( "idle" )
26+ const [ refreshError , setRefreshError ] = useState < string | undefined > ( )
27+ const refreshStatusRef = useRef ( refreshStatus )
2528 const routerModels = useRouterModels ( )
2629
2730 const handleInputChange = useCallback (
@@ -35,20 +38,42 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro
3538 [ setApiConfigurationField ] ,
3639 )
3740
38- const onMessage = useCallback ( ( event : MessageEvent ) => {
39- const message : ExtensionMessage = event . data
41+ useEffect ( ( ) => {
42+ const handleMessage = ( event : MessageEvent ) => {
43+ const message : ExtensionMessage = event . data
44+
45+ if ( message . type === "ollamaModels" ) {
46+ if ( ! message . error ) {
47+ setOllamaModels ( message . ollamaModels ?? { } )
48+ }
4049
41- switch ( message . type ) {
42- case "ollamaModels" :
43- {
44- const newModels = message . ollamaModels ?? { }
45- setOllamaModels ( newModels )
50+ if ( refreshStatusRef . current === "loading" ) {
51+ const nextStatus = message . error ? "error" : "success"
52+ refreshStatusRef . current = nextStatus
53+ setRefreshStatus ( nextStatus )
54+ setRefreshError ( message . error )
4655 }
47- break
56+ }
57+ }
58+
59+ window . addEventListener ( "message" , handleMessage )
60+ return ( ) => {
61+ window . removeEventListener ( "message" , handleMessage )
4862 }
4963 } , [ ] )
5064
51- useEvent ( "message" , onMessage )
65+ const handleRefreshModels = useCallback ( ( ) => {
66+ refreshStatusRef . current = "loading"
67+ setRefreshStatus ( "loading" )
68+ setRefreshError ( undefined )
69+ vscode . postMessage ( {
70+ type : "requestOllamaModels" ,
71+ values : {
72+ baseUrl : apiConfiguration ?. ollamaBaseUrl ,
73+ apiKey : apiConfiguration ?. ollamaApiKey ,
74+ } ,
75+ } )
76+ } , [ apiConfiguration ?. ollamaBaseUrl , apiConfiguration ?. ollamaApiKey ] )
5277
5378 // Refresh models on mount
5479 useEffect ( ( ) => {
@@ -102,6 +127,33 @@ export const Ollama = ({ apiConfiguration, setApiConfigurationField }: OllamaPro
102127 </ div >
103128 </ VSCodeTextField >
104129 ) }
130+ < Button
131+ variant = "outline"
132+ onClick = { handleRefreshModels }
133+ disabled = { refreshStatus === "loading" }
134+ className = "w-full" >
135+ < div className = "flex items-center gap-2" >
136+ { refreshStatus === "loading" ? (
137+ < span className = "codicon codicon-loading codicon-modifier-spin" />
138+ ) : (
139+ < span className = "codicon codicon-refresh" />
140+ ) }
141+ { t ( "settings:providers.refreshModels.label" ) }
142+ </ div >
143+ </ Button >
144+ { refreshStatus === "loading" && (
145+ < div className = "text-sm text-vscode-descriptionForeground" >
146+ { t ( "settings:providers.refreshModels.loading" ) }
147+ </ div >
148+ ) }
149+ { refreshStatus === "success" && (
150+ < div className = "text-sm text-vscode-foreground" > { t ( "settings:providers.refreshModels.success" ) } </ div >
151+ ) }
152+ { refreshStatus === "error" && (
153+ < div className = "text-sm text-vscode-errorForeground" >
154+ { refreshError || t ( "settings:providers.refreshModels.error" ) }
155+ </ div >
156+ ) }
105157 < ModelPicker
106158 apiConfiguration = { apiConfiguration }
107159 setApiConfigurationField = { setApiConfigurationField }
0 commit comments