@@ -16,7 +16,8 @@ import {
1616 SelectValue ,
1717} from "../../ui/select"
1818import { ExternalLinkIcon } from "../../ui/icons"
19- import { Copy , Check } from "lucide-react"
19+ import { Copy , Check , RefreshCw } from "lucide-react"
20+ import { Button } from "../../ui/button"
2021import { cn } from "../../../lib/utils"
2122
2223// Hook to detect narrow screen
@@ -46,6 +47,40 @@ export function AgentsBetaTab() {
4647 const [ autoOffline , setAutoOffline ] = useAtom ( autoOfflineModeAtom )
4748 const [ selectedOllamaModel , setSelectedOllamaModel ] = useAtom ( selectedOllamaModelAtom )
4849 const [ copied , setCopied ] = useState ( false )
50+ const [ updateStatus , setUpdateStatus ] = useState < "idle" | "checking" | "available" | "not-available" | "error" > ( "idle" )
51+ const [ updateVersion , setUpdateVersion ] = useState < string | null > ( null )
52+ const [ currentVersion , setCurrentVersion ] = useState < string | null > ( null )
53+
54+ // Get current version on mount
55+ useEffect ( ( ) => {
56+ window . desktopApi ?. getVersion ( ) . then ( setCurrentVersion )
57+ } , [ ] )
58+
59+ // Check for updates with force flag to bypass cache
60+ const handleCheckForUpdates = async ( ) => {
61+ // Check if we're in dev mode
62+ const isPackaged = await window . desktopApi ?. isPackaged ?.( )
63+ if ( ! isPackaged ) {
64+ setUpdateStatus ( "error" )
65+ console . log ( "Update check skipped in dev mode" )
66+ return
67+ }
68+
69+ setUpdateStatus ( "checking" )
70+ setUpdateVersion ( null )
71+ try {
72+ const result = await window . desktopApi ?. checkForUpdates ( true )
73+ if ( result ) {
74+ setUpdateStatus ( "available" )
75+ setUpdateVersion ( result . version )
76+ } else {
77+ setUpdateStatus ( "not-available" )
78+ }
79+ } catch ( error ) {
80+ console . error ( "Failed to check for updates:" , error )
81+ setUpdateStatus ( "error" )
82+ }
83+ }
4984
5085 // Get Ollama status
5186 const { data : ollamaStatus } = trpc . ollama . getStatus . useQuery ( undefined , {
@@ -247,6 +282,44 @@ export function AgentsBetaTab() {
247282 </ div >
248283 </ div >
249284 ) }
285+
286+ { /* Updates Section */ }
287+ < div className = "space-y-2" >
288+ < div className = "pb-2" >
289+ < h4 className = "text-sm font-medium text-foreground" > Updates</ h4 >
290+ < p className = "text-xs text-muted-foreground mt-1" >
291+ Check for new versions manually (bypasses CDN cache)
292+ </ p >
293+ </ div >
294+
295+ < div className = "bg-background rounded-lg border border-border overflow-hidden" >
296+ < div className = "p-4" >
297+ < div className = "flex items-center justify-between" >
298+ < div className = "flex flex-col space-y-1" >
299+ < span className = "text-sm font-medium text-foreground" >
300+ { currentVersion ? `Current: v${ currentVersion } ` : "Version" }
301+ </ span >
302+ < span className = "text-xs text-muted-foreground" >
303+ { updateStatus === "checking" && "Checking for updates..." }
304+ { updateStatus === "available" && `Update available: v${ updateVersion } ` }
305+ { updateStatus === "not-available" && "You're on the latest version" }
306+ { updateStatus === "error" && "Failed to check (dev mode?)" }
307+ { updateStatus === "idle" && "Click to check for updates" }
308+ </ span >
309+ </ div >
310+ < Button
311+ variant = "outline"
312+ size = "sm"
313+ onClick = { handleCheckForUpdates }
314+ disabled = { updateStatus === "checking" }
315+ >
316+ < RefreshCw className = { cn ( "h-4 w-4 mr-2" , updateStatus === "checking" && "animate-spin" ) } />
317+ { updateStatus === "checking" ? "Checking..." : "Check Now" }
318+ </ Button >
319+ </ div >
320+ </ div >
321+ </ div >
322+ </ div >
250323 </ div >
251324 )
252325}
0 commit comments