import React from 'react'; import { PanelLeft } from 'lucide-react'; interface EnvVar { name: string; label: string; } interface GooseDesktopInstallerProps { extensionId: string; extensionName: string; description: string; type?: 'stdio' | 'http'; // Extension type (http maps to streamable_http) // Command-line extension props (optional when using url) command?: string; args?: string[]; // SSE/HTTP extension prop (optional when using command+args) url?: string; envVars?: EnvVar[]; // For stdio: environment variables, for http: headers apiKeyLink?: string; apiKeyLinkText?: string; customStep3?: string; hasEnvVars?: boolean; // Explicit control over configuration steps appendToStep3?: string; } export default function GooseDesktopInstaller({ extensionId, extensionName, description, type, command, args, url, envVars = [], apiKeyLink, apiKeyLinkText, customStep3, hasEnvVars, appendToStep3 }: GooseDesktopInstallerProps) { // Determine extension type with backward compatibility const extensionType = type || (command ? 'stdio' : url ? 'http' : 'stdio'); // Build the goose:// URL const buildGooseUrl = () => { let urlParts = []; // Only add type parameter for http extensions (mapped to streamable_http) // to avoid regressions with existing sse/stdio extensions if (extensionType === 'http') { urlParts.push(`type=streamable_http`); } // Add SSE/HTTP extension URL or command-line extension command+args if (url) { urlParts.push(`url=${encodeURIComponent(url)}`); } else if (command && args) { urlParts.push(`cmd=${encodeURIComponent(command)}`); urlParts.push(...args.map(arg => `arg=${encodeURIComponent(arg)}`)); } // Add common parameters urlParts.push( `id=${encodeURIComponent(extensionId)}`, `name=${encodeURIComponent(extensionName)}`, `description=${encodeURIComponent(description)}` ); // Add environment variables/headers const isHttp = extensionType === 'http'; const paramName = isHttp ? 'header' : 'env'; urlParts.push(...envVars.map(envVar => `${paramName}=${encodeURIComponent(`${envVar.name}=${envVar.label}`)}` )); return `goose://extension?${urlParts.join('&')}`; }; // Generate step 3 content (only if needed) const getStep3Content = () => { if (customStep3) { return customStep3; } if (apiKeyLink && apiKeyLinkText) { return ( <> Get your {apiKeyLinkText} and paste it in ); } if (envVars.length > 0) { const envVarNames = envVars.map(env => env.name).join(', '); const isHttp = extensionType === 'http'; const variableType = isHttp ? 'header' : 'environment variable'; const variableTypes = isHttp ? 'headers' : 'environment variables'; return `Obtain your ${envVarNames} and paste ${envVars.length > 1 ? `them as ${variableTypes}` : `it as a ${variableType}`}`; } return null; // No configuration needed }; const content = getStep3Content(); const step3Content = appendToStep3 ? ( <> {content} {content ?
: null} {appendToStep3} ) : content; const hasConfigurationContent = step3Content !== null; const shouldShowConfigurationSteps = hasEnvVars ?? hasConfigurationContent; return (
  1. Launch the installer
  2. Click Yes to confirm the installation
  3. {shouldShowConfigurationSteps && ( <>
  4. {step3Content}
  5. Click Add Extension
  6. )}
  7. Click the button in the top-left to open the sidebar
  8. Navigate to the chat
); }