From da0610cc0bb7a6b08e67dccfd48c6df9b84437df Mon Sep 17 00:00:00 2001 From: Bradley Axen Date: Sat, 18 Jan 2025 17:08:19 -0800 Subject: [PATCH] hotfix: update system config payloads (#642) Co-authored-by: Mic Neale --- ui/desktop/src/ChatWindow.tsx | 4 +- ui/desktop/src/config.ts | 125 +++++++++++++++----------- ui/desktop/src/utils/providerUtils.ts | 17 ++-- 3 files changed, 80 insertions(+), 66 deletions(-) diff --git a/ui/desktop/src/ChatWindow.tsx b/ui/desktop/src/ChatWindow.tsx index 5a7650f558..b5bdb46e70 100644 --- a/ui/desktop/src/ChatWindow.tsx +++ b/ui/desktop/src/ChatWindow.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef, useState } from "react"; import { Message, useChat } from "./ai-sdk-fork/useChat"; import { Route, Routes, Navigate } from "react-router-dom"; -import { getApiUrl, getSecretKey, addMCP, addMCPSystem } from "./config"; +import { getApiUrl, getSecretKey, extendGoosed, extendGoosedFromUrl } from "./config"; import BottomMenu from "./components/BottomMenu"; import FlappyGoose from "./components/FlappyGoose"; import GooseMessage from "./components/GooseMessage"; @@ -356,7 +356,7 @@ export default function ChatWindow() { // Listen for add-system from main process for a goose:// deep link window.electron.on("add-system", (_, link) => { console.log("Received message for add-system:", link); - addMCPSystem(link); + extendGoosedFromUrl(link); }); }, []); diff --git a/ui/desktop/src/config.ts b/ui/desktop/src/config.ts index bd247b7d41..bc657f357b 100644 --- a/ui/desktop/src/config.ts +++ b/ui/desktop/src/config.ts @@ -1,4 +1,3 @@ - // Helper to construct API endpoints export const getApiUrl = (endpoint: string): string => { const baseUrl = window.appConfig.get('GOOSE_API_HOST') + ':' + window.appConfig.get('GOOSE_PORT'); @@ -10,10 +9,68 @@ export const getSecretKey = (): string => { return window.appConfig.get('secretKey'); } +// Environment variables type matching Rust's Envs +export type Envs = Record; -// add MCP system from a goose://extension url -export const addMCPSystem = async (url: string) => { - console.log("adding MCP from URL", url); +// SystemConfig type matching the Rust version +export type SystemConfig = + | { + type: "sse"; + uri: string; + envs?: Envs; + } + | { + type: "stdio"; + cmd: string; + args: string[]; + envs?: Envs; + } + | { + type: "builtin"; + name: string; + }; + +// Extend Goosed with a new system configuration +export const extendGoosed = async (config: SystemConfig) => { + // allowlist the CMD for stdio type + if (config.type === "stdio") { + const allowedCMDs = ['npx', 'uvx', 'goosed']; + if (!allowedCMDs.includes(config.cmd)) { + console.error(`System ${config.cmd} is not supported right now`); + return; + } + + // if its goosed - we will update the path to the binary + if (config.cmd === 'goosed') { + config = { + ...config, + cmd: await window.electron.getBinaryPath('goosed') + }; + } + } + + try { + const response = await fetch(getApiUrl('/systems/add'), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Secret-Key': getSecretKey(), + }, + body: JSON.stringify(config) + }); + + if (!response.ok) { + throw new Error(`Failed to add system config: ${response.statusText}`); + } + console.log(`Successfully added system config: ${JSON.stringify(config)}`); + } catch (error) { + console.log(`Error adding system config:`, error); + } +}; + +// Extend Goosed from a goose://extension URL +export const extendGoosedFromUrl = async (url: string) => { + console.log("extending Goosed from URL", url); if (!url.startsWith("goose://extension")) { console.log("Invalid URL: URL must use the goose://extension scheme"); } @@ -24,14 +81,12 @@ export const addMCPSystem = async (url: string) => { throw new Error("Invalid protocol: URL must use the goose:// scheme"); } - const system = parsedUrl.searchParams.get("cmd"); - if (!system) { + const cmd = parsedUrl.searchParams.get("cmd"); + if (!cmd) { throw new Error("Missing required 'cmd' parameter in the URL"); } - const argsParam = parsedUrl.searchParams.getAll("arg"); - const args = argsParam; - + const args = parsedUrl.searchParams.getAll("arg"); const envList = parsedUrl.searchParams.getAll("env"); // split env based on delimiter to a map @@ -40,50 +95,14 @@ export const addMCPSystem = async (url: string) => { acc[key] = value; return acc; }, {} as Record); - console.log("envs", envs); - addMCP(system, args, envs); -}; - -// add a MCP system -export const addMCP = async (system: string, args: string[], envs?: Record) => { - - // allowlist the CMD - const allowedCMDs = ['npx', 'uvx', 'goosed']; - - if (!allowedCMDs.includes(system)) { - console.error(`System ${system} is not supported right now`); - return; - } - - if (system === 'goosed') { - // if its something built in - we will append the path to the binary - system = await window.electron.getBinaryPath('goosed'); - } - - const systemConfig = { - type: "Stdio", - cmd: system, - args: args, - envs: envs + // Create a SystemConfig from the URL parameters + const config: SystemConfig = { + type: "stdio", + cmd, + args, + envs: Object.keys(envs).length > 0 ? envs : undefined }; - try { - const response = await fetch(getApiUrl('/systems/add'), { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-Secret-Key': getSecretKey(), - }, - body: JSON.stringify(systemConfig) - }); - - if (!response.ok) { - throw new Error(`Failed to add system config for ${system} args: ${args} envs: ${envs}: ${response.statusText}`); - } - console.log(`Successfully added MCP config for ${system} args: ${args}`); - } catch (error) { - console.log(`Error adding MCP config for ${system} args: ${args} envs: ${envs}:`, error); - } - -}; \ No newline at end of file + await extendGoosed(config); +}; diff --git a/ui/desktop/src/utils/providerUtils.ts b/ui/desktop/src/utils/providerUtils.ts index 80cf39fc14..8bd4573032 100644 --- a/ui/desktop/src/utils/providerUtils.ts +++ b/ui/desktop/src/utils/providerUtils.ts @@ -1,4 +1,4 @@ -import {addMCP, addMCPSystem, getApiUrl, getSecretKey } from "../config"; +import { extendGoosed, extendGoosedFromUrl, getApiUrl, getSecretKey } from "../config"; export const SELECTED_PROVIDER_KEY = "GOOSE_PROVIDER__API_KEY" @@ -40,7 +40,6 @@ export async function getProvidersList(): Promise { const data = await response.json(); console.log("Raw API Response:", data); // Log the raw response - // Format the response into an array of providers return data.map((item: any) => ({ id: item.id, // Root-level ID @@ -68,26 +67,22 @@ const addAgent = async (provider: string) => { return response; }; -const addSystemConfig = async (system: string) => { - await addMCP("goosed", ["mcp", system]); -}; - export const initializeSystem = async (provider: string) => { try { console.log("initializing with provider", provider) await addAgent(provider); - await addSystemConfig("developer2"); + await extendGoosed({ + type: "builtin", + name: "developer2" + }); // Handle deep link if present const deepLink = window.appConfig.get('DEEP_LINK'); if (deepLink) { - await addMCPSystem(deepLink); + await extendGoosedFromUrl(deepLink); } } catch (error) { console.error("Failed to initialize system:", error); throw error; } }; - - -