From 4fd0f9b949338649c3e6492af5a553e34d90a0cd Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Fri, 18 Jul 2025 14:33:41 +0200 Subject: [PATCH 1/4] Rust debug --- Justfile | 8 +++++++ ui/desktop/src/goosed.ts | 47 ++++++++++++++++++++++++++++++++++++---- ui/desktop/src/main.ts | 12 +++++----- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/Justfile b/Justfile index 047ddd94acd4..dbe99a53b350 100644 --- a/Justfile +++ b/Justfile @@ -147,6 +147,13 @@ run-ui-only: @echo "Running UI..." cd ui/desktop && npm install && npm run start-gui +debug-ui: + @echo "🚀 Starting Goose frontend in external backend mode" + cd ui/desktop && \ + export GOOSE_EXTERNAL_BACKEND=true && \ + export GOOSE_EXTERNAL_PORT=3000 && \ + npm install && \ + npm run start-gui # Run UI with alpha changes run-ui-alpha temporal="true": @@ -453,3 +460,4 @@ kotlin-example: -Djna.library.path=$HOME/Development/goose/target/debug \ -classpath "example.jar:libs/kotlin-stdlib-1.9.0.jar:libs/kotlinx-coroutines-core-jvm-1.7.3.jar:libs/jna-5.13.0.jar" \ UsageKt + diff --git a/ui/desktop/src/goosed.ts b/ui/desktop/src/goosed.ts index 3b0b5e1cb2bd..41a9d727b347 100644 --- a/ui/desktop/src/goosed.ts +++ b/ui/desktop/src/goosed.ts @@ -1,4 +1,4 @@ -import { spawn, ChildProcess } from 'child_process'; +import { spawn, ChildProcess, execSync } from 'child_process'; import { createServer } from 'net'; import os from 'node:os'; import path from 'node:path'; @@ -59,8 +59,46 @@ const checkServerStatus = async ( return false; }; +const connectToExternalBackend = async ( + workingDir: string, + port: number = 3000 +): Promise<[number, string, ChildProcess]> => { + log.info(`Using external goosed backend on port ${port}`); + + const isReady = await checkServerStatus(port); + if (!isReady) { + throw new Error(`External goosed server not accessible on port ${port}`); + } + + if (process.platform === 'win32') { + throw new Error('External backend process discovery not supported on Windows'); + } + + let pid: number; + try { + const stdout = execSync(`lsof -ti:${port}`, { encoding: 'utf8' }); + const parsedPid = parseInt(stdout.trim()); + if (isNaN(parsedPid)) { + throw new Error('Could not parse PID from lsof output'); + } + pid = parsedPid; + } catch (error) { + throw new Error(`Could not find process for external backend on port ${port}: ${error}`); + } + + const mockProcess = { + pid, + kill: () => { + log.info(`Not killing external process ${pid} - managed externally`); + }, + } as ChildProcess; + + return [port, workingDir, mockProcess]; +}; + interface GooseProcessEnv { [key: string]: string | undefined; + HOME: string; USERPROFILE: string; APPDATA: string; @@ -75,18 +113,19 @@ export const startGoosed = async ( dir: string | null = null, env: Partial = {} ): Promise<[number, string, ChildProcess]> => { - // we default to running goosed in home dir - if not specified const homeDir = os.homedir(); const isWindows = process.platform === 'win32'; - // Ensure dir is properly normalized for the platform and validate it if (!dir) { dir = homeDir; } - // Sanitize and validate the directory path dir = path.resolve(path.normalize(dir)); + if (process.env.GOOSE_EXTERNAL_BACKEND) { + return connectToExternalBackend(dir, 3000); + } + // Validate that the directory actually exists and is a directory try { const stats = fs.lstatSync(dir); diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index f3745ac4b073..36e1fa03cf0f 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -452,7 +452,7 @@ const getGooseProvider = () => { }; const generateSecretKey = () => { - const key = crypto.randomBytes(32).toString('hex'); + const key = process.env.GOOSE_EXTERNAL_BACKEND ? 'test' : crypto.randomBytes(32).toString('hex'); process.env.GOOSE_SERVER__SECRET_KEY = key; return key; }; @@ -2028,11 +2028,11 @@ app.whenReady().then(async () => { * ```yaml: extensions: - - id: slack - command: uvx mcp_slack - - id: knowledge_graph_memory - command: npx -y @modelcontextprotocol/server-memory - ``` + - id: slack + command: uvx mcp_slack + - id: knowledge_graph_memory + command: npx -y @modelcontextprotocol/server-memory + ``` * * @returns A promise that resolves to an array of extension commands that are allowed. */ From ad31299e93e9ea1bf02c8e6b32a39ac54b918448 Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Sat, 19 Jul 2025 18:57:00 +0200 Subject: [PATCH 2/4] Another thing --- ui/desktop/src/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index deb0e479eee5..03f64f3a2373 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -2063,9 +2063,9 @@ app.whenReady().then(async () => { ```yaml: extensions: - id: slack - command: uvx mcp_slack + command: uvx mcp_slack - id: knowledge_graph_memory - command: npx -y @modelcontextprotocol/server-memory + command: npx -y @modelcontextprotocol/server-memory ``` * * @returns A promise that resolves to an array of extension commands that are allowed. From 90512c7b098200264426e5851ecc5180519c8c4a Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Sat, 19 Jul 2025 19:05:08 +0200 Subject: [PATCH 3/4] Ugh --- ui/desktop/src/main.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index 03f64f3a2373..dadebb4222ac 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -2062,10 +2062,10 @@ app.whenReady().then(async () => { * ```yaml: extensions: - - id: slack - command: uvx mcp_slack - - id: knowledge_graph_memory - command: npx -y @modelcontextprotocol/server-memory + - id: slack + command: uvx mcp_slack + - id: knowledge_graph_memory + command: npx -y @modelcontextprotocol/server-memory ``` * * @returns A promise that resolves to an array of extension commands that are allowed. From 2744497f909c27eb15f4d1300951f35da793c1fd Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Sat, 19 Jul 2025 19:32:52 +0200 Subject: [PATCH 4/4] Now do it for real? --- ui/desktop/src/goosed.ts | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/ui/desktop/src/goosed.ts b/ui/desktop/src/goosed.ts index 41a9d727b347..802df11a93d5 100644 --- a/ui/desktop/src/goosed.ts +++ b/ui/desktop/src/goosed.ts @@ -1,4 +1,4 @@ -import { spawn, ChildProcess, execSync } from 'child_process'; +import { spawn, ChildProcess } from 'child_process'; import { createServer } from 'net'; import os from 'node:os'; import path from 'node:path'; @@ -70,26 +70,10 @@ const connectToExternalBackend = async ( throw new Error(`External goosed server not accessible on port ${port}`); } - if (process.platform === 'win32') { - throw new Error('External backend process discovery not supported on Windows'); - } - - let pid: number; - try { - const stdout = execSync(`lsof -ti:${port}`, { encoding: 'utf8' }); - const parsedPid = parseInt(stdout.trim()); - if (isNaN(parsedPid)) { - throw new Error('Could not parse PID from lsof output'); - } - pid = parsedPid; - } catch (error) { - throw new Error(`Could not find process for external backend on port ${port}: ${error}`); - } - const mockProcess = { - pid, + pid: undefined, kill: () => { - log.info(`Not killing external process ${pid} - managed externally`); + log.info(`Not killing external process that is managed externally`); }, } as ChildProcess;