diff --git a/Justfile b/Justfile index 047ddd94..dbe99a53 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 3b0b5e1c..802df11a 100644 --- a/ui/desktop/src/goosed.ts +++ b/ui/desktop/src/goosed.ts @@ -59,8 +59,30 @@ 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}`); + } + + const mockProcess = { + pid: undefined, + kill: () => { + log.info(`Not killing external process that is managed externally`); + }, + } as ChildProcess; + + return [port, workingDir, mockProcess]; +}; + interface GooseProcessEnv { [key: string]: string | undefined; + HOME: string; USERPROFILE: string; APPDATA: string; @@ -75,18 +97,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 078949ac..1934ac4e 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -463,7 +463,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; }; @@ -2081,7 +2081,7 @@ app.whenReady().then(async () => { 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. */