diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index 801b6a1f80..211969fde7 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -31,7 +31,6 @@ import { Suspense, } from "solid-js" import { Dynamic } from "solid-js/web" -import { serverSwitching, withServerSwitchOverlay } from "@/utils/server-switch" import { CommandProvider } from "@/context/command" import { CommentsProvider } from "@/context/comments" import { FileProvider } from "@/context/file" @@ -52,7 +51,7 @@ import { WslServersProvider } from "@/context/wsl-servers" import DirectoryLayout from "@/pages/directory-layout" import Layout from "@/pages/layout" import { ErrorPage } from "./pages/error" -import { isPlaceholderServerUrl, useCheckServerHealth } from "./utils/server-health" +import { useCheckServerHealth } from "./utils/server-health" const HomeRoute = lazy(() => import("@/pages/home")) const loadSession = () => import("@/pages/session") @@ -198,8 +197,6 @@ function ConnectionGate(props: ParentProps<{ disableHealthCheck?: boolean }>) { : Effect.gen(function* () { if (!server.current) return true const { http, type } = server.current - if (isPlaceholderServerUrl(http.url)) return false - while (true) { const res = yield* Effect.promise(() => checkServerHealth(http)) if (res.healthy) return true @@ -233,14 +230,12 @@ function ConnectionGate(props: ParentProps<{ disableHealthCheck?: boolean }>) { if (checkMode() === "background") void healthCheckActions.refetch() }} onServerSelected={(key) => { - void withServerSwitchOverlay(() => - startTransition(() => { - batch(() => { - setCheckMode("blocking") - server.setActive(key) - }) - }), - ) + startTransition(() => { + batch(() => { + setCheckMode("blocking") + server.setActive(key) + }) + }) }} /> } @@ -362,11 +357,6 @@ export function AppInterface(props: { servers={props.servers} > - -
- -
-
diff --git a/packages/app/src/components/dialog-select-server.tsx b/packages/app/src/components/dialog-select-server.tsx index e8eed170c9..a684a350e9 100644 --- a/packages/app/src/components/dialog-select-server.tsx +++ b/packages/app/src/components/dialog-select-server.tsx @@ -17,11 +17,9 @@ import { useLanguage } from "@/context/language" import { usePlatform } from "@/context/platform" import { normalizeServerUrl, ServerConnection, useServer } from "@/context/server" import { useWslServers } from "@/context/wsl-servers" -import { isPlaceholderServerUrl, type ServerHealth, useCheckServerHealth } from "@/utils/server-health" -import { withServerSwitchOverlay } from "@/utils/server-switch" +import { type ServerHealth, useCheckServerHealth } from "@/utils/server-health" const DEFAULT_USERNAME = "opencode" -const cachedServerStatus = new Map() function versionOlderThan(current: string | null | undefined, expected: string | null | undefined) { if (!current || !expected) return false @@ -168,7 +166,6 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { }, addWsl: { showWizard: props.initialView === "add-wsl", - pendingSelectKey: undefined as ServerConnection.Key | undefined, }, editServer: { id: undefined as string | undefined, @@ -322,8 +319,7 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { ) .join("\n\n"), ) - const health = (key: ServerConnection.Key) => store.status[key] ?? cachedServerStatus.get(key) - const isSelectable = (conn: ServerConnection.Any) => !isPlaceholderServerUrl(conn.http.url) + const health = (key: ServerConnection.Key) => store.status[key] const wslRuntime = (conn: ServerConnection.Any) => { if (!isWslSidecar(conn)) return return wslState()?.servers.find((item) => item.config.id === ServerConnection.key(conn))?.runtime @@ -361,9 +357,6 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { }), ) if (disposed) return - for (const [key, value] of Object.entries(results)) { - cachedServerStatus.set(ServerConnection.Key.make(key), value) - } setStore("status", reconcile(results)) } @@ -380,7 +373,6 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { } async function select(conn: ServerConnection.Any, persist?: boolean) { - if (!isSelectable(conn)) return if (!persist && health(ServerConnection.key(conn))?.healthy === false) return const nextKey = ServerConnection.key(conn) const changed = server.key !== nextKey @@ -413,18 +405,9 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { return } - await withServerSwitchOverlay(apply) + apply() } - createEffect(() => { - const key = store.addWsl.pendingSelectKey - if (!key) return - const conn = items().find((item) => ServerConnection.key(item) === key) - if (!conn || !isSelectable(conn)) return - setStore("addWsl", "pendingSelectKey", undefined) - void select(conn) - }) - const handleAddChange = (value: string) => { if (addMutation.isPending) return setStore("addServer", { url: value, error: "" }) @@ -480,7 +463,6 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { const resetForm = () => { resetAdd() resetEdit() - setStore("addWsl", "pendingSelectKey", undefined) setStore("addWsl", "showWizard", false) } @@ -513,19 +495,14 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { const startAddWsl = () => { resetAdd() resetEdit() - setStore("addWsl", "pendingSelectKey", undefined) setStore("addWsl", "showWizard", true) } const handleAddedWsl = async (distro: string) => { const key = ServerConnection.Key.make(`wsl:${distro}`) setStore("addWsl", "showWizard", false) - setStore("addWsl", "pendingSelectKey", key) const conn = items().find((item) => ServerConnection.key(item) === key) - if (conn && isSelectable(conn)) { - await select(conn) - setStore("addWsl", "pendingSelectKey", undefined) - } + if (conn) await select(conn) } const submitForm = () => { @@ -593,7 +570,6 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { return ( @@ -644,7 +620,7 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) { const key = ServerConnection.key(i) const wsl = isWslSidecar(i) const wslDistro = wsl ? i.distro : undefined - const blocked = () => !isSelectable(i) || health(key)?.healthy === false + const blocked = () => health(key)?.healthy === false const canChangeDefault = () => canDefault() && i.type !== "ssh" const canRemove = () => i.type === "http" || wsl const hasMenuActionsBeforeDelete = () => canRemove() && (i.type === "http" || canChangeDefault() || canRetryWsl(i)) diff --git a/packages/app/src/components/dialog-wsl-server.tsx b/packages/app/src/components/dialog-wsl-server.tsx index 8f79955403..e400da6c58 100644 --- a/packages/app/src/components/dialog-wsl-server.tsx +++ b/packages/app/src/components/dialog-wsl-server.tsx @@ -1,12 +1,11 @@ import { Button } from "@opencode-ai/ui/button" import { useDialog } from "@opencode-ai/ui/context/dialog" import { Spinner } from "@opencode-ai/ui/spinner" -import { useMutation } from "@tanstack/solid-query" import { showToast } from "@opencode-ai/ui/toast" import { createEffect, createMemo, For, Match, onCleanup, Show, Switch } from "solid-js" import { createStore } from "solid-js/store" import { useLanguage } from "@/context/language" -import type { WslServersPlatform, WslServerStep } from "@/context/platform" +import type { WslServerStep } from "@/context/platform" import { usePlatform } from "@/context/platform" import { useWslServers } from "@/context/wsl-servers" @@ -16,14 +15,6 @@ function isHiddenDistro(name: string) { return /^docker-desktop(?:-data)?$/i.test(name) } -function parseProgressPercent(text: string) { - const match = text.match(/(\d{1,3}(?:[.,]\d+)?)\s*%/) - if (!match) return null - const value = Number.parseFloat(match[1]!.replace(",", ".")) - if (!Number.isFinite(value)) return null - return Math.max(0, Math.min(99, Math.floor(value))) -} - interface DialogWslServerProps { onAdded?: (distro: string) => void | Promise } @@ -33,6 +24,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { const platform = usePlatform() const dialog = useDialog() const wslServers = useWslServers() + const api = platform.wslServers! const [store, setStore] = createStore({ step: undefined as WslServerStep | undefined, selectedDistro: null as string | null, @@ -40,12 +32,6 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { adding: false, }) const current = () => wslServers.data - const wslApi = () => platform.wslServers - const withWslApi = async (run: (api: WslServersPlatform) => Promise) => { - const api = wslApi() - if (!api) return - return run(api) - } let disposed = false onCleanup(() => { disposed = true @@ -104,15 +90,6 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { }) const installTarget = createMemo(() => installableDistros().find((item) => item.name === store.installTarget) ?? null) const installingDistro = createMemo(() => current()?.job?.kind === "install-distro") - const installDistroPercent = createMemo(() => { - if (!installingDistro()) return null - const transcript = current()?.transcript ?? [] - for (let i = transcript.length - 1; i >= 0; i--) { - const percent = parseProgressPercent(transcript[i]!.text) - if (percent !== null) return percent - } - return null - }) const wslReady = createMemo(() => !!current()?.runtime?.available && !current()?.pendingRestart) const distroReady = createMemo(() => { const probe = selectedProbe() @@ -135,58 +112,22 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { // them back when a probe result updates recommendedStep. const activeStep = createMemo(() => store.step ?? recommendedStep()) - const probeRuntimeMutation = useMutation(() => ({ - mutationFn: () => withWslApi((api) => api.probeRuntime()), - })) - - const refreshDistrosMutation = useMutation(() => ({ - mutationFn: () => withWslApi((api) => api.refreshDistros()), - })) - - const installWslMutation = useMutation(() => ({ - mutationFn: () => withWslApi((api) => api.installWsl()), - })) - - const installDistroMutation = useMutation(() => ({ - mutationFn: (name: string) => withWslApi((api) => api.installDistro(name)), - })) - - const probeDistroMutation = useMutation(() => ({ - mutationFn: (name: string) => withWslApi((api) => api.probeDistro(name)), - })) - - const probeOpencodeMutation = useMutation(() => ({ - mutationFn: (name: string) => withWslApi((api) => api.probeOpencode(name)), - })) - - const installOpencodeMutation = useMutation(() => ({ - mutationFn: (name: string) => withWslApi((api) => api.installOpencode(name)), - })) - - const openTerminalMutation = useMutation(() => ({ - mutationFn: (name: string) => withWslApi((api) => api.openTerminal(name)), - })) - - const addServerMutation = useMutation(() => ({ - mutationFn: (distro: string) => withWslApi((api) => api.addServer(distro)), - })) - const autoProbe = createMemo(() => { const state = current() - if (!state || !wslApi() || busy()) return null + if (!state || busy()) return null if (state.pendingRestart) return null - if (!state.runtime) return { key: "runtime", run: () => probeRuntimeMutation.mutateAsync() } + if (!state.runtime) return { key: "runtime", run: () => api.probeRuntime() } if (!wslReady()) return null if (!state.installed.length && !state.online.length) { - return { key: "distros", run: () => refreshDistrosMutation.mutateAsync() } + return { key: "distros", run: () => api.refreshDistros() } } const distro = store.selectedDistro if (distro && !state.distroProbes[distro]) { - return { key: `probe-distro:${distro}`, run: () => probeDistroMutation.mutateAsync(distro) } + return { key: `probe-distro:${distro}`, run: () => api.probeDistro(distro) } } if (!distro || !distroReady()) return null if (!state.opencodeChecks[distro]) { - return { key: `probe-opencode:${distro}`, run: () => probeOpencodeMutation.mutateAsync(distro) } + return { key: `probe-opencode:${distro}`, run: () => api.probeOpencode(distro) } } return null }) @@ -266,18 +207,6 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { return distro ? `Install OpenCode in ${distro}.` : "Choose a distro first." }) - const installProgress = createMemo(() => { - const state = current() - if (!state?.job) return null - const transcript = state.transcript.filter((line) => line.text.trim()) - const title = transcript[0]?.text - if (!title?.startsWith("Installing ")) return null - return { - title, - lines: transcript.slice(1).slice(-8), - } - }) - const run = async (action: () => Promise) => { try { await action() @@ -302,7 +231,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { if (!distro) return setStore("adding", true) try { - await addServerMutation.mutateAsync(distro) + await api.addServer(distro) if (props.onAdded) { await props.onAdded(distro) } else { @@ -370,7 +299,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { variant="secondary" size="large" disabled={busy()} - onClick={() => void run(() => installWslMutation.mutateAsync())} + onClick={() => void run(() => api.installWsl())} > Install WSL @@ -402,7 +331,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { variant="ghost" size="small" disabled={busy()} - onClick={() => runSelectedDistro((distro) => probeDistroMutation.mutateAsync(distro))} + onClick={() => runSelectedDistro((distro) => api.probeDistro(distro))} > Refresh @@ -446,11 +375,6 @@ export function DialogWslServer(props: DialogWslServerProps = {}) {
Install
- - - {installDistroPercent()}% - - @@ -458,7 +382,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { variant="secondary" size="small" disabled={busy() || !installTarget()} - onClick={() => void run(() => installDistroMutation.mutateAsync(installTarget()!.name))} + onClick={() => void run(() => api.installDistro(installTarget()!.name))} > {installingDistro() ? "Installing..." : "Install"} @@ -531,7 +455,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { variant="secondary" size="large" disabled={busy() || !selectedInstalled()} - onClick={() => runSelectedDistro((distro) => openTerminalMutation.mutateAsync(distro))} + onClick={() => runSelectedDistro((distro) => api.openTerminal(distro))} > Open terminal @@ -539,7 +463,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { variant="ghost" size="large" disabled={busy() || !store.selectedDistro} - onClick={() => runSelectedDistro((distro) => probeDistroMutation.mutateAsync(distro))} + onClick={() => runSelectedDistro((distro) => api.probeDistro(distro))} > Refresh @@ -568,7 +492,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { variant="ghost" size="large" disabled={busy()} - onClick={() => runSelectedDistro((distro) => probeOpencodeMutation.mutateAsync(distro))} + onClick={() => runSelectedDistro((distro) => api.probeOpencode(distro))} > Refresh @@ -578,7 +502,7 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { variant="secondary" size="large" disabled={busy()} - onClick={() => runSelectedDistro((distro) => installOpencodeMutation.mutateAsync(distro))} + onClick={() => runSelectedDistro((distro) => api.installOpencode(distro))} > {opencodeCheck()?.resolvedPath ? "Update OpenCode" : "Install OpenCode"} @@ -606,47 +530,6 @@ export function DialogWslServer(props: DialogWslServerProps = {}) { - - {(progress) => ( -
-
- -
Progress
-
-
{progress().title}
-
- - {(line) => ( -
- {line.text} -
- )} -
-
-
- )} -
- - 0}> -
-
Diagnostics
-
- {(line) =>
{line.text}
}
-
-
-
-