Explorar el Código

desktop: don't spawn sidecar if default is localhost server

Brendan Allan hace 1 mes
padre
commit
1c2416b6de

+ 15 - 4
packages/desktop/src-tauri/src/lib.rs

@@ -40,7 +40,9 @@ use crate::windows::{LoadingWindow, MainWindow};
 #[derive(Clone, serde::Serialize, specta::Type, Debug)]
 struct ServerReadyData {
     url: String,
+    username: Option<String>,
     password: Option<String>,
+    is_sidecar: bool
 }
 
 #[derive(Clone, Copy, serde::Serialize, specta::Type, Debug)]
@@ -605,6 +607,7 @@ async fn initialize(app: AppHandle) {
                     child,
                     health_check,
                     url,
+                    username,
                     password,
                 } => {
                     let app = app.clone();
@@ -631,7 +634,7 @@ async fn initialize(app: AppHandle) {
 
                             app.state::<ServerState>().set_child(Some(child));
 
-                            Ok(ServerReadyData { url, password })
+                            Ok(ServerReadyData { url, username,password, is_sidecar: true })
                         }
                         .map(move |res| {
                             let _ = server_ready_tx.send(res);
@@ -641,7 +644,9 @@ async fn initialize(app: AppHandle) {
                 ServerConnection::Existing { url } => {
                     let _ = server_ready_tx.send(Ok(ServerReadyData {
                         url: url.to_string(),
+                        username: None,
                         password: None,
+                        is_sidecar: false,
                     }));
                     None
                 }
@@ -719,6 +724,7 @@ enum ServerConnection {
     },
     CLI {
         url: String,
+        username: Option<String>,
         password: Option<String>,
         child: CommandChild,
         health_check: server::HealthCheck,
@@ -730,11 +736,15 @@ async fn setup_server_connection(app: AppHandle) -> ServerConnection {
 
     tracing::info!(?custom_url, "Attempting server connection");
 
-    if let Some(url) = custom_url
-        && server::check_health_or_ask_retry(&app, &url).await
+    if let Some(url) = &custom_url
+        && server::check_health_or_ask_retry(&app, url).await
     {
         tracing::info!(%url, "Connected to custom server");
-        return ServerConnection::Existing { url: url.clone() };
+        // If the default server is already local, no need to also spawn a sidecar
+        if server::is_localhost_url(url) {
+            return ServerConnection::Existing { url: url.clone() };
+        }
+        // Remote default server: fall through and also spawn a local sidecar
     }
 
     let local_port = get_sidecar_port();
@@ -755,6 +765,7 @@ async fn setup_server_connection(app: AppHandle) -> ServerConnection {
 
     ServerConnection::CLI {
         url: local_url,
+        username: Some("opencode".to_string()),
         password: Some(password),
         child,
         health_check,

+ 5 - 1
packages/desktop/src-tauri/src/server.rs

@@ -150,7 +150,7 @@ pub async fn check_health(url: &str, password: Option<&str>) -> bool {
         return false;
     };
 
-    let mut builder = reqwest::Client::builder().timeout(Duration::from_secs(3));
+    let mut builder = reqwest::Client::builder().timeout(Duration::from_secs(7));
 
     if url_is_localhost(&url) {
         // Some environments set proxy variables (HTTP_PROXY/HTTPS_PROXY/ALL_PROXY) without
@@ -178,6 +178,10 @@ pub async fn check_health(url: &str, password: Option<&str>) -> bool {
         .unwrap_or(false)
 }
 
+pub fn is_localhost_url(url: &str) -> bool {
+    reqwest::Url::parse(url).is_ok_and(|u| url_is_localhost(&u))
+}
+
 fn url_is_localhost(url: &reqwest::Url) -> bool {
     url.host_str().is_some_and(|host| {
         host.eq_ignore_ascii_case("localhost")

+ 2 - 0
packages/desktop/src/bindings.ts

@@ -35,7 +35,9 @@ export type LoadingWindowComplete = null;
 
 export type ServerReadyData = {
 		url: string,
+		username: string | null,
 		password: string | null,
+		is_sidecar: boolean,
 	};
 
 export type SqliteMigrationProgress = { type: "InProgress"; value: number } | { type: "Done" };

+ 16 - 15
packages/desktop/src/index.tsx

@@ -23,7 +23,7 @@ import { relaunch } from "@tauri-apps/plugin-process"
 import { open as shellOpen } from "@tauri-apps/plugin-shell"
 import { Store } from "@tauri-apps/plugin-store"
 import { check, type Update } from "@tauri-apps/plugin-updater"
-import { type Accessor, createResource, type JSX, onCleanup, onMount, Show } from "solid-js"
+import { createResource, type JSX, onCleanup, onMount, Show } from "solid-js"
 import { render } from "solid-js/web"
 import pkg from "../package.json"
 import { initI18n, t } from "./i18n"
@@ -31,7 +31,7 @@ import { UPDATER_ENABLED } from "./updater"
 import { webviewZoom } from "./webview-zoom"
 import "./styles.css"
 import { Channel } from "@tauri-apps/api/core"
-import { commands, type InitStep } from "./bindings"
+import { commands, ServerReadyData, type InitStep } from "./bindings"
 import { createMenu } from "./menu"
 
 const root = document.getElementById("root")
@@ -452,16 +452,19 @@ render(() => {
       <AppBaseProviders>
         <ServerGate>
           {(data) => {
-            const server: ServerConnection.Sidecar = {
-              displayName: "Local Server",
-              type: "sidecar",
-              variant: "base",
-              http: {
-                url: data().url,
-                username: "opencode",
-                password: data().password ?? undefined,
-              },
+            const http = {
+              url: data.url,
+              username: data.username ?? undefined,
+              password: data.password ?? undefined,
             }
+            const server: ServerConnection.Any = data.is_sidecar
+              ? {
+                  displayName: "Local Server",
+                  type: "sidecar",
+                  variant: "base",
+                  http,
+                }
+              : { type: "http", http }
 
             function Inner() {
               const cmd = useCommand()
@@ -485,10 +488,8 @@ render(() => {
   )
 }, root!)
 
-type ServerReadyData = { url: string; password: string | null }
-
 // Gate component that waits for the server to be ready
-function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.Element }) {
+function ServerGate(props: { children: (data: ServerReadyData) => JSX.Element }) {
   const [serverData] = createResource(() => commands.awaitInitialization(new Channel<InitStep>() as any))
 
   return (
@@ -516,7 +517,7 @@ function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.
           </div>
         }
       >
-        {(data) => props.children(data)}
+        {(data) => props.children(data())}
       </Show>
     </Show>
   )