@@ -7,7 +7,6 @@ import { createClient } from "../../app/lib/opencode";
77import {
88 buildOpenworkWorkspaceBaseUrl ,
99 createOpenworkServerClient ,
10- normalizeOpenworkServerUrl ,
1110 readOpenworkServerSettings ,
1211 type OpenworkServerCapabilities ,
1312 type OpenworkServerClient ,
@@ -46,7 +45,6 @@ import {
4645 useWorkspaceShellLayout ,
4746} from "./workspace-shell-layout" ;
4847import {
49- openworkServerInfo ,
5048 pickDirectory ,
5149 resolveWorkspaceListSelectedId ,
5250 workspaceBootstrap ,
@@ -65,6 +63,7 @@ import { ModelPickerModal } from "../domains/session/modals/model-picker-modal";
6563import type { ModelOption , ModelRef } from "../../app/types" ;
6664import { recordInspectorEvent } from "./app-inspector" ;
6765import { ensureDesktopLocalOpenworkConnection } from "./desktop-local-openwork" ;
66+ import { resolveOpenworkConnection } from "./openwork-connection" ;
6867import { abortSessionSafe } from "../../app/lib/opencode-session" ;
6968import { useReloadCoordinator } from "./reload-coordinator" ;
7069
@@ -173,27 +172,13 @@ function folderNameFromPath(path: string) {
173172 return parts [ parts . length - 1 ] ?? "workspace" ;
174173}
175174
176- async function resolveRouteOpenworkConnection ( ) {
177- const settings = readOpenworkServerSettings ( ) ;
178- let normalizedBaseUrl = normalizeOpenworkServerUrl ( settings . urlOverride ?? "" ) ?? "" ;
179- let resolvedToken = settings . token ?. trim ( ) ?? "" ;
180-
181- if ( isDesktopRuntime ( ) ) {
182- try {
183- const info = await openworkServerInfo ( ) ;
184- // Desktop-hosted servers use a fresh loopback port and freshly minted
185- // owner token per boot. Prefer the live runtime info over localStorage;
186- // stored settings may belong to a previous server process.
187- normalizedBaseUrl =
188- normalizeOpenworkServerUrl ( info . connectUrl ?? info . baseUrl ?? info . lanUrl ?? info . mdnsUrl ?? "" ) ??
189- normalizedBaseUrl ;
190- resolvedToken = info . ownerToken ?. trim ( ) || info . clientToken ?. trim ( ) || resolvedToken ;
191- } catch {
192- // ignore and fall back to stored settings only
193- }
175+ function isLoopbackServerUrl ( raw : string ) {
176+ try {
177+ const parsed = new URL ( raw ) ;
178+ return parsed . hostname === "127.0.0.1" || parsed . hostname === "localhost" || parsed . hostname === "::1" ;
179+ } catch {
180+ return false ;
194181 }
195-
196- return { normalizedBaseUrl, resolvedToken } ;
197182}
198183
199184type PersistedThemeMode = "light" | "dark" | "system" ;
@@ -482,11 +467,13 @@ export function SettingsRoute() {
482467 ( ) =>
483468 createOpenworkServerStore ( {
484469 startupPreference : ( ) => {
485- // In Tauri desktop mode, prefer the embedded host server (hostInfo.baseUrl)
486- // unless the user has explicitly pinned a remote urlOverride.
470+ // In desktop mode, loopback URLs are ephemeral local runtime details.
471+ // Only non-loopback stored URLs indicate an explicit remote/manual
472+ // server connection preference.
487473 if ( ! isDesktopRuntime ( ) ) return "server" ;
488474 const stored = readOpenworkServerSettings ( ) ;
489- return stored . urlOverride ?. trim ( ) ? "server" : "local" ;
475+ const urlOverride = stored . urlOverride ?. trim ( ) ?? "" ;
476+ return urlOverride && ! isLoopbackServerUrl ( urlOverride ) ? "server" : "local" ;
490477 } ,
491478 documentVisible : ( ) => typeof document === "undefined" || document . visibilityState === "visible" ,
492479 developerMode : ( ) => routeStateRef . current . developerMode ,
@@ -703,7 +690,7 @@ export function SettingsRoute() {
703690 desktopWorkspaces = workspacesRef . current ;
704691 }
705692 }
706- const { normalizedBaseUrl, resolvedToken } = await resolveRouteOpenworkConnection ( ) ;
693+ const { normalizedBaseUrl, resolvedToken } = await resolveOpenworkConnection ( ) ;
707694
708695 if ( ! normalizedBaseUrl || ! resolvedToken ) {
709696 setOpenworkClient ( null ) ;
0 commit comments