This commit is contained in:
LukeParkerDev
2026-04-28 12:20:01 +10:00
parent 70443cd2de
commit 9cd611780f
4 changed files with 59 additions and 94 deletions

View File

@@ -44,7 +44,6 @@ function versionOlderThan(current: string | null | undefined, expected: string |
}
interface DialogSelectServerProps {
initialView?: "add-wsl"
onNavigateHome?: () => void
}
@@ -163,7 +162,7 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) {
showForm: false,
},
addWsl: {
showWizard: props.initialView === "add-wsl",
showWizard: false,
},
editServer: {
id: undefined as string | undefined,
@@ -550,21 +549,6 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) {
if (server.defaultKey() === key) await server.setDefault(null)
}
function handleRemoveWsl(conn: ServerConnection.Any) {
if (!isWslSidecar(conn)) return
removeWslMutation.mutate(ServerConnection.key(conn))
}
function handleRetryWsl(conn: ServerConnection.Any) {
if (!isWslSidecar(conn)) return
retryWslMutation.mutate(ServerConnection.key(conn))
}
function handleUpdateWsl(conn: ServerConnection.Any) {
if (!isWslSidecar(conn)) return
updateWslMutation.mutate(conn.distro)
}
return (
<Dialog
title={formTitle()}
@@ -621,7 +605,6 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) {
const blocked = () => health(key)?.healthy === false
const canChangeDefault = () => server.canDefault() && i.type !== "ssh"
const canRemove = () => i.type === "http" || wsl
const hasMenuActionsBeforeDelete = () => canRemove() && (i.type === "http" || canChangeDefault() || canRetryWsl(i))
const outdated = () => {
const check = wslCheck(i)
return versionOlderThan(check?.version, check?.expectedVersion)
@@ -668,7 +651,7 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) {
onPointerDown={(e: PointerEvent) => e.stopPropagation()}
onClick={(e: MouseEvent) => {
e.stopPropagation()
handleUpdateWsl(i)
if (wslDistro) updateWslMutation.mutate(wslDistro)
}}
>
{updating() ? "Updating OpenCode..." : label()}
@@ -702,7 +685,7 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) {
</DropdownMenu.Item>
</Show>
<Show when={wsl && canRetryWsl(i)}>
<DropdownMenu.Item onSelect={() => handleRetryWsl(i)}>
<DropdownMenu.Item onSelect={() => retryWslMutation.mutate(key)}>
<DropdownMenu.ItemLabel>Retry start</DropdownMenu.ItemLabel>
</DropdownMenu.Item>
</Show>
@@ -720,14 +703,14 @@ export function DialogSelectServer(props: DialogSelectServerProps = {}) {
</DropdownMenu.ItemLabel>
</DropdownMenu.Item>
</Show>
<Show when={hasMenuActionsBeforeDelete()}>
<Show when={canRemove() && (i.type === "http" || canChangeDefault() || canRetryWsl(i))}>
<DropdownMenu.Separator />
</Show>
<Show when={canRemove()}>
<DropdownMenu.Item
onSelect={() => {
if (wsl) {
handleRemoveWsl(i)
removeWslMutation.mutate(key)
return
}
void handleRemove(key)

View File

@@ -244,20 +244,39 @@ export function DialogWslServer(props: DialogWslServerProps = {}) {
}
}
const steps = createMemo(() =>
STEPS.map((step) => ({
step,
title: stepTitle(step),
state: stepState(step, {
active: activeStep(),
wslReady: wslReady(),
distroReady: distroReady(),
opencodeReady: opencodeReady(),
opencodeMismatch: opencodeCheck()?.matchesDesktop === false,
}),
locked: stepIndex(step) > stepIndex(recommendedStep()),
})),
)
const steps = createMemo(() => {
const active = activeStep()
const activeIndex = STEPS.indexOf(active)
const recommendedIndex = STEPS.indexOf(recommendedStep())
return STEPS.map((step) => {
const index = STEPS.indexOf(step)
return {
step,
title: step === "wsl" ? "WSL" : step === "distro" ? "Choose distro" : "OpenCode",
state:
active === step
? "current"
: step === "wsl"
? wslReady()
? "done"
: "warning"
: step === "distro"
? distroReady()
? "done"
: index > activeIndex
? "locked"
: "warning"
: opencodeCheck()?.matchesDesktop === false
? "warning"
: opencodeReady()
? "done"
: index > activeIndex
? "locked"
: "warning",
locked: index > recommendedIndex,
}
})
})
const loadError = createMemo(() => {
const error = wslServers.error
if (!error) return "Failed to load WSL state."
@@ -554,36 +573,3 @@ function requestError(language: ReturnType<typeof useLanguage>, err: unknown) {
description: err instanceof Error ? err.message : String(err),
})
}
function stepIndex(step: WslServerStep) {
return STEPS.indexOf(step)
}
function stepTitle(step: WslServerStep) {
if (step === "wsl") return "WSL"
if (step === "distro") return "Choose distro"
return "OpenCode"
}
function stepState(
step: WslServerStep,
state: {
active: WslServerStep
wslReady: boolean
distroReady: boolean
opencodeReady: boolean
opencodeMismatch: boolean
},
) {
if (state.active === step) return "current"
if (step === "wsl") return state.wslReady ? "done" : "warning"
if (step === "distro")
return state.distroReady ? "done" : stepIndex(step) > stepIndex(state.active) ? "locked" : "warning"
return state.opencodeMismatch
? "warning"
: state.opencodeReady
? "done"
: stepIndex(step) > stepIndex(state.active)
? "locked"
: "warning"
}

View File

@@ -265,10 +265,6 @@ export function runWslSh(script: string, distro?: string | null, opts?: RunWslOp
return runWslInDistro(["sh", "-lc", script], distro, opts)
}
export function runWslBash(script: string, distro?: string | null, opts?: RunWslOptions) {
return runWslInDistro(["bash", "-lc", script], distro, opts)
}
export async function probeWslRuntime(opts?: RunWslOptions): Promise<WslRuntimeCheck> {
const version = await runWsl(["--version"], opts).catch((error) => ({
code: 1,

42
todo.md
View File

@@ -21,30 +21,30 @@
- [x] [High][L] Revisit `DefaultServer` context; fold into server ownership or make it a real provider instead of ad hoc query hooks.
- [x] [High][L] Collapse duplicated server health loops/logging across `ConnectionGate`, `ServerProvider`, dialog, and status popover.
- [ ] [Medium][S] Remove `initialView?: "add-wsl"` from `DialogSelectServer` if no callsites need it.
- [ ] [Medium][S] Remove `handleRemoveWsl`, `handleRetryWsl`, `handleUpdateWsl` guard helpers; callers already know when item is WSL.
- [ ] [Medium][S] Remove `hasMenuActionsBeforeDelete()` from `dialog-select-server.tsx`; inline or always render the separator in the delete block.
- [x] [Medium][S] Remove `initialView?: "add-wsl"` from `DialogSelectServer` if no callsites need it.
- [x] [Medium][S] Remove `handleRemoveWsl`, `handleRetryWsl`, `handleUpdateWsl` guard helpers; callers already know when item is WSL.
- [x] [Medium][S] Remove `hasMenuActionsBeforeDelete()` from `dialog-select-server.tsx`; inline or always render the separator in the delete block.
- [x] [Medium][S] Remove UI-only `parseProgressPercent()` and percent display in WSL wizard unless progress is structured by backend.
- [ ] [Medium][S] Remove hard-coded Ubuntu installable distro special-case from UI; backend/platform should return installable distros.
- [ ] [Medium][S] Remove `isHiddenDistro()` UI filter for `docker-desktop`; backend/platform should decide hidden distros if needed.
- [ ] ~~[Medium][S] Remove hard-coded Ubuntu installable distro special-case from UI; backend/platform should return installable distros.~~ (Skipped: changes distro list behavior)
- [ ] ~~[Medium][S] Remove `isHiddenDistro()` UI filter for `docker-desktop`; backend/platform should decide hidden distros if needed.~~ (Skipped: changes visible distro behavior)
- [x] [Medium][S] Remove `installProgress()` transcript shaping in WSL wizard; render raw transcript or structured progress.
- [ ] [Medium][S] Remove `stepIndex` / `stepTitle` / `stepState` helpers in WSL wizard; inline the 3-step UI state.
- [ ] [Medium][S] Remove `runWslBash()` from `wsl.ts`; it is unused.
- [x] [Medium][S] Remove `stepIndex` / `stepTitle` / `stepState` helpers in WSL wizard; inline the 3-step UI state.
- [x] [Medium][S] Remove `runWslBash()` from `wsl.ts`; it is unused.
- [x] [Medium][S] Remove progress-line de-duping from either `wsl-pty.ts` or `wsl-servers.ts`; keep only one place if kept.
- [ ] [Medium][S] Remove `ensureLoopbackNoProxy()` and Chromium proxy-bypass mutation unless a measured proxy repro exists.
- [ ] [Medium][S] Remove broad renderer global error/rejection logging in Electron renderer unless this PR intentionally adds diagnostics.
- [ ] [Medium][S] Remove `wireWindowDiagnostics()` or move it to a separate diagnostics PR; it is unrelated WSL feature plumbing.
- [ ] [Medium][S] Remove terminal debug logging helpers/calls once current investigation is done.
- [ ] [Medium][S] Remove server-health retry logging helpers (`serializeError`, `stringifyLog`, per-attempt logs`) or dev-gate one final warning.
- [ ] [Medium][S] Remove `resolveSystem32Command()` if no PATH failure is proven; call `wsl.exe` directly.
- [ ] [Medium][S] Remove WSL path picker catch fallbacks in Electron renderer; for active WSL, failed conversion should fail, not pass Windows paths through.
- [ ] [Medium][M] Remove `createOutputDecoder()` / `detectOutputEncoding()` heuristic unless logs prove UTF-16 WSL output occurs.
- [ ] [Medium][M] Remove registry parsing/default-user discovery in `wsl.ts` if not proven necessary; use the actual WSL command context consistently.
- [ ] [Medium][M] Simplify `resolveWslOpencode()` fallback path search; prefer `command -v opencode` unless installer/PATH proves otherwise.
- [ ] [Medium][M] Simplify WSL sidecar shell script env/path/watchman workarounds in `server.ts`; add back only with repro/logs.
- [ ] [Medium][M] Remove `startAttempts` stale-start guard in WSL controller unless start/remove/stop race is reproduced.
- [ ] [Medium][M] Remove `acknowledgements` model/API/IPC if UI does not consume it.
- [ ] [Medium][M] Remove `Promise.allSettled` distro-list fallback; let listing errors surface instead of showing empty distros.
- [ ] ~~[Medium][S] Remove `ensureLoopbackNoProxy()` and Chromium proxy-bypass mutation unless a measured proxy repro exists.~~ (Skipped: networking behavior change)
- [ ] ~~[Medium][S] Remove broad renderer global error/rejection logging in Electron renderer unless this PR intentionally adds diagnostics.~~ (Skipped: keep diagnostics)
- [ ] ~~[Medium][S] Remove `wireWindowDiagnostics()` or move it to a separate diagnostics PR; it is unrelated WSL feature plumbing.~~ (Skipped: keep diagnostics)
- [ ] ~~[Medium][S] Remove terminal debug logging helpers/calls once current investigation is done.~~ (Skipped: keep diagnostics)
- [ ] ~~[Medium][S] Remove server-health retry logging helpers (`serializeError`, `stringifyLog`, per-attempt logs`) or dev-gate one final warning.~~ (Skipped: keep diagnostics)
- [ ] ~~[Medium][S] Remove `resolveSystem32Command()` if no PATH failure is proven; call `wsl.exe` directly.~~ (Skipped: PATH behavior change)
- [ ] ~~[Medium][S] Remove WSL path picker catch fallbacks in Electron renderer; for active WSL, failed conversion should fail, not pass Windows paths through.~~ (Skipped: behavior change)
- [ ] ~~[Medium][M] Remove `createOutputDecoder()` / `detectOutputEncoding()` heuristic unless logs prove UTF-16 WSL output occurs.~~ (Skipped: output compatibility change)
- [ ] ~~[Medium][M] Remove registry parsing/default-user discovery in `wsl.ts` if not proven necessary; use the actual WSL command context consistently.~~ (Skipped: opencode discovery behavior change)
- [ ] ~~[Medium][M] Simplify `resolveWslOpencode()` fallback path search; prefer `command -v opencode` unless installer/PATH proves otherwise.~~ (Skipped: opencode discovery behavior change)
- [ ] ~~[Medium][M] Simplify WSL sidecar shell script env/path/watchman workarounds in `server.ts`; add back only with repro/logs.~~ (Skipped: runtime environment behavior change)
- [ ] ~~[Medium][M] Remove `startAttempts` stale-start guard in WSL controller unless start/remove/stop race is reproduced.~~ (Skipped: race-safety behavior change)
- [x] [Medium][M] Remove `acknowledgements` model/API/IPC if UI does not consume it.
- [ ] ~~[Medium][M] Remove `Promise.allSettled` distro-list fallback; let listing errors surface instead of showing empty distros.~~ (Skipped: error/empty-list behavior change)
- [ ] [Medium][M] Collapse WSL persisted config + state mutations into one owner/path, or derive runtime state instead of mutating both.
- [ ] [Medium][M] Remove bespoke WSL subscribe/unsubscribe IPC lifecycle if broadcast event pattern is acceptable.
- [ ] [Medium][M] Collapse repeated WSL IPC method lists in `ipc.ts`, `index.ts`, and preload into one simpler mapping or smaller API surface.