@@ -5,8 +5,8 @@ import { MouseButton, TextAttributes } from "@opentui/core"
55import { RouteProvider , useRoute } from "@tui/context/route"
66import { Switch , Match , createEffect , untrack , ErrorBoundary , createSignal , onMount , batch , Show , on } from "solid-js"
77import { win32DisableProcessedInput , win32FlushInputBuffer , win32InstallCtrlCGuard } from "./win32"
8- import { Installation } from "@/installation"
98import { Flag } from "@/flag/flag"
9+ import semver from "semver"
1010import { DialogProvider , useDialog } from "@tui/ui/dialog"
1111import { DialogProvider as DialogProviderList } from "@tui/component/dialog-provider"
1212import { SDKProvider , useSDK } from "@tui/context/sdk"
@@ -29,6 +29,7 @@ import { PromptHistoryProvider } from "./component/prompt/history"
2929import { FrecencyProvider } from "./component/prompt/frecency"
3030import { PromptStashProvider } from "./component/prompt/stash"
3131import { DialogAlert } from "./ui/dialog-alert"
32+ import { DialogConfirm } from "./ui/dialog-confirm"
3233import { ToastProvider , useToast } from "./ui/toast"
3334import { ExitProvider , useExit } from "./context/exit"
3435import { Session as SessionApi } from "@/session"
@@ -103,6 +104,7 @@ async function getTerminalBackgroundColor(): Promise<"dark" | "light"> {
103104}
104105
105106import type { EventSource } from "./context/sdk"
107+ import { Installation } from "@/installation"
106108
107109export function tui ( input : {
108110 url : string
@@ -729,13 +731,51 @@ function App() {
729731 } )
730732 } )
731733
732- sdk . event . on ( Installation . Event . UpdateAvailable . type , ( evt ) => {
734+ sdk . event . on ( "installation.update-available" , async ( evt ) => {
735+ const version = evt . properties . version
736+
737+ const skipped = kv . get ( "skipped_version" )
738+ if ( skipped && ! semver . gt ( version , skipped ) ) return
739+
740+ const choice = await DialogConfirm . show (
741+ dialog ,
742+ `Update Available` ,
743+ `A new release v${ version } is available. Would you like to update now?` ,
744+ "skip" ,
745+ )
746+
747+ if ( choice === false ) {
748+ kv . set ( "skipped_version" , version )
749+ return
750+ }
751+
752+ if ( choice !== true ) return
753+
733754 toast . show ( {
734755 variant : "info" ,
735- title : "Update Available" ,
736- message : `OpenCode v${ evt . properties . version } is available. Run 'opencode upgrade' to update manually.` ,
737- duration : 10000 ,
756+ message : `Updating to v${ version } ...` ,
757+ duration : 30000 ,
738758 } )
759+
760+ const result = await sdk . client . global . upgrade ( { target : version } )
761+
762+ if ( result . error || ! result . data ?. success ) {
763+ toast . show ( {
764+ variant : "error" ,
765+ title : "Update Failed" ,
766+ message : "Update failed" ,
767+ duration : 10000 ,
768+ } )
769+ return
770+ }
771+
772+ await DialogAlert . show (
773+ dialog ,
774+ "Update Complete" ,
775+ `Successfully updated to OpenCode v${ result . data . version } . Please restart the application.` ,
776+ )
777+
778+ exit ( )
739779 } )
740780
741781 return (
0 commit comments