From 4495713967c7293328cc9ee41afc39fdff789859 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Tue, 4 Nov 2025 18:40:12 +1100 Subject: [PATCH] allow setting of tunnel url --- crates/goose-server/src/commands/agent.rs | 4 +- crates/goose-server/src/state.rs | 2 +- crates/goose-server/src/tunnel/config.rs | 50 ------------------- crates/goose-server/src/tunnel/lapstone.rs | 9 +++- .../settings/app/AppSettingsSection.tsx | 8 ++- 5 files changed, 13 insertions(+), 60 deletions(-) diff --git a/crates/goose-server/src/commands/agent.rs b/crates/goose-server/src/commands/agent.rs index 5888bf508d..09bb808337 100644 --- a/crates/goose-server/src/commands/agent.rs +++ b/crates/goose-server/src/commands/agent.rs @@ -63,13 +63,13 @@ pub async fn run() -> Result<()> { let listener = tokio::net::TcpListener::bind(settings.socket_addr()).await?; let local_addr = listener.local_addr()?; info!("listening on {}", local_addr); - + let port = local_addr.port(); let app_state_clone = app_state.clone(); tokio::spawn(async move { app_state_clone.auto_start_tunnel(port).await; }); - + // Ensure the listener/socket is properly closed on cancellation by using graceful shutdown axum::serve(listener, app) .with_graceful_shutdown(shutdown_signal()) diff --git a/crates/goose-server/src/state.rs b/crates/goose-server/src/state.rs index 752ebb87be..51755e7866 100644 --- a/crates/goose-server/src/state.rs +++ b/crates/goose-server/src/state.rs @@ -38,7 +38,7 @@ impl AppState { pub async fn auto_start_tunnel(&self, port: u16) { let status = self.tunnel_manager.get_status().await; - + if status.auto_start && status.state == crate::tunnel::TunnelState::Idle { tracing::info!("Auto-starting tunnel on port {}", port); match self.tunnel_manager.start(port).await { diff --git a/crates/goose-server/src/tunnel/config.rs b/crates/goose-server/src/tunnel/config.rs index 6877c78619..b1cf2579ae 100644 --- a/crates/goose-server/src/tunnel/config.rs +++ b/crates/goose-server/src/tunnel/config.rs @@ -47,53 +47,3 @@ pub async fn save_config(config: &TunnelConfig) -> Result<(), Box Result<(), Box> { - let cfg = Config::global(); - let _ = cfg.delete_secret(SECRET_KEY_SECRET); - let _ = cfg.delete_secret(SECRET_KEY_AGENT_ID); - Ok(()) - } - - #[tokio::test] - async fn test_save_and_load_config() { - let config = TunnelConfig { - auto_start: true, - secret: Some("test_secret_12345".to_string()), - agent_id: Some("test_agent_id_67890".to_string()), - }; - - // Save config - save_config(&config).await.unwrap(); - - // Load config - let loaded = load_config().await; - - assert_eq!(loaded.auto_start, config.auto_start); - assert_eq!(loaded.secret, config.secret); - assert_eq!(loaded.agent_id, config.agent_id); - - // Cleanup - clear_secrets().unwrap(); - } - - #[tokio::test] - async fn test_load_config_defaults() { - // Clear any existing config - let _ = clear_secrets(); - - let cfg = Config::global(); - let _ = cfg.delete(CONFIG_KEY_AUTO_START); - - // Load should return defaults - let loaded = load_config().await; - - assert!(!loaded.auto_start); - assert_eq!(loaded.secret, None); - assert_eq!(loaded.agent_id, None); - } -} diff --git a/crates/goose-server/src/tunnel/lapstone.rs b/crates/goose-server/src/tunnel/lapstone.rs index c8ef2ad7d9..1778e11cee 100644 --- a/crates/goose-server/src/tunnel/lapstone.rs +++ b/crates/goose-server/src/tunnel/lapstone.rs @@ -415,6 +415,13 @@ pub async fn start( agent_id: String, handle: Arc>>>, ) -> Result { + let worker_url = + std::env::var("GOOSE_TUNNEL_WORKER_URL").unwrap_or_else(|_| WORKER_URL.to_string()); + + if worker_url.to_lowercase() == "none" || worker_url.to_lowercase() == "no" { + anyhow::bail!("Tunnel is disabled via GOOSE_TUNNEL_WORKER_URL environment variable"); + } + let agent_id_clone = agent_id.clone(); let server_secret_clone = server_secret; let handle_clone = handle.clone(); @@ -425,8 +432,6 @@ pub async fn start( *handle.write().await = Some(task); - let worker_url = - std::env::var("GOOSE_TUNNEL_WORKER_URL").unwrap_or_else(|_| WORKER_URL.to_string()); let public_url = format!("{}/tunnel/{}", worker_url, agent_id); let hostname = Url::parse(&worker_url)? .host_str() diff --git a/ui/desktop/src/components/settings/app/AppSettingsSection.tsx b/ui/desktop/src/components/settings/app/AppSettingsSection.tsx index d25de5af7c..1c3aa89d26 100644 --- a/ui/desktop/src/components/settings/app/AppSettingsSection.tsx +++ b/ui/desktop/src/components/settings/app/AppSettingsSection.tsx @@ -39,12 +39,11 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti setIsMacOS(window.electron.platform === 'darwin'); }, []); - // Check if platform supports tunnel (macOS or Linux) const supportsTunnel = window.electron.platform === 'darwin' || window.electron.platform === 'linux'; - // Check if experimental features should be hidden - const hideExperimental = window.appConfig.get('GOOSE_HIDE_EXPERIMENTAL') === 'true'; + const tunnelWorkerUrl = window.appConfig.get('GOOSE_TUNNEL_WORKER_URL'); + const hideTunnel = tunnelWorkerUrl === 'none' || tunnelWorkerUrl === 'no'; // Detect theme changes useEffect(() => { @@ -403,8 +402,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti - {/* Experimental Features - only show on macOS and Linux, and not hidden by env var */} - {supportsTunnel && !hideExperimental && ( + {supportsTunnel && !hideTunnel && (