UNPKG

automagik-genie

Version:

Self-evolving AI agent orchestration framework with Model Context Protocol support

157 lines (156 loc) 6.96 kB
"use strict"; /** * Talk Command - Interactive browser session with agent * * Creates a Forge task for the agent and opens it in browser. * Similar to 'genie run' but opens browser instead of waiting in terminal. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.runTalk = runTalk; const service_config_js_1 = require("../lib/service-config.js"); const forge_manager_1 = require("../lib/forge-manager"); const agent_resolver_1 = require("../lib/agent-resolver"); const forge_executor_1 = require("../lib/forge-executor"); const forge_helpers_1 = require("../lib/forge-helpers"); const executor_registry_1 = require("../lib/executor-registry"); const path_1 = __importDefault(require("path")); const child_process_1 = require("child_process"); const gradient_string_1 = __importDefault(require("gradient-string")); const fs_1 = __importDefault(require("fs")); // Genie-themed gradients const genieGradient = (0, gradient_string_1.default)(['#0066ff', '#9933ff', '#ff00ff']); const successGradient = (0, gradient_string_1.default)(['#00ff88', '#00ccff', '#0099ff']); async function runTalk(parsed, config, paths) { const [agentName, ...promptParts] = parsed.commandArgs; if (!agentName) { console.error('Usage: genie talk <agent> ["<prompt>"]'); process.exit(1); } const prompt = promptParts.join(' ').trim() || `Start interactive session with ${agentName}`; const resolvedAgentName = (0, agent_resolver_1.resolveAgentIdentifier)(agentName); const agentSpec = (0, agent_resolver_1.loadAgentSpec)(resolvedAgentName); const agentGenie = agentSpec.meta?.genie || {}; // Resolve executor configuration const executorKey = (0, executor_registry_1.normalizeExecutorKeyOrDefault)((0, executor_registry_1.normalizeExecutorValue)(agentGenie.executor) || config.defaults?.executor); const executorVariant = (agentGenie.executorVariant || agentGenie.variant || config.defaults?.executorVariant || 'DEFAULT').trim().toUpperCase(); const model = agentGenie.model || config.defaults?.model; const { baseUrl } = (0, service_config_js_1.getForgeConfig)(); const logDir = path_1.default.join(process.cwd(), '.genie', 'state'); // Start Forge if not running const forgeRunning = await (0, forge_manager_1.isForgeRunning)(baseUrl); if (!forgeRunning) { console.log(''); process.stderr.write('Starting Forge... '); const startTime = Date.now(); const result = (0, forge_manager_1.startForgeInBackground)({ baseUrl, logDir }); if (!result.ok) { const error = 'error' in result ? result.error : new Error('Unknown error'); console.error(''); console.error('❌ Failed to start Forge'); console.error(` ${error.message}`); console.error(` Check logs at ${logDir}/forge.log`); process.exit(1); } const ready = await (0, forge_manager_1.waitForForgeReady)(baseUrl, 60000, 500, false); if (!ready) { console.error(''); console.error('❌ Forge did not start in time (60s)'); console.error(` Check logs at ${logDir}/forge.log`); process.exit(1); } const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); process.stderr.write(`ready (${elapsed}s)\n`); } // Create Forge session const forgeExecutor = (0, forge_executor_1.createForgeExecutor)(); // NOTE: Agent profile sync removed - Forge discovers .genie folders natively let sessionResult; try { sessionResult = await forgeExecutor.createTask({ agentName: resolvedAgentName, prompt, executorKey, executorVariant, executionMode: 'interactive', model }); } catch (error) { const reason = (0, forge_helpers_1.describeForgeError)(error); console.error(`❌ Failed to create session: ${reason}`); console.error(` ${forge_helpers_1.FORGE_RECOVERY_HINT}`); process.exit(1); } const attemptId = sessionResult.attemptId; // Use Forge UUID (issue #407 fix) // Show success message console.log(''); console.log(successGradient('━'.repeat(60))); console.log(successGradient(`✨ ${resolvedAgentName} session ready! ✨`)); console.log(successGradient('━'.repeat(60))); console.log(''); console.log(`📊 Session ID: ${attemptId}`); console.log(`📊 Opening task in browser...`); console.log(''); // Open browser to task URL using Forge's cross-platform logic openBrowserCrossPlatform(sessionResult.forgeUrl); // Exit cleanly (Forge stays running in background) console.log(successGradient('✅ Session started in Forge.')); console.log(''); process.exitCode = 0; } /** * Open URL in browser using cross-platform logic (including WSL support) * Based on Forge's browser opening strategy */ function openBrowserCrossPlatform(url) { try { const platform = process.platform; if (platform === 'darwin') { // macOS (0, child_process_1.execSync)(`open "${url}"`, { stdio: 'ignore' }); } else if (platform === 'win32') { // Windows (0, child_process_1.spawn)('cmd', ['/c', 'start', '', url], { detached: true, stdio: 'ignore' }).unref(); } else if (platform === 'linux') { // Check if running in WSL const isWSL = fs_1.default.existsSync('/proc/version') && fs_1.default.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft'); if (isWSL) { // WSL: Use Windows browser via cmd.exe try { (0, child_process_1.execSync)(`cmd.exe /c start "" "${url}"`, { stdio: 'ignore' }); } catch { // Fallback to wslview if cmd.exe fails try { (0, child_process_1.execSync)(`wslview "${url}"`, { stdio: 'ignore' }); } catch { // Last resort: Linux browser (0, child_process_1.execSync)(`xdg-open "${url}"`, { stdio: 'ignore' }); } } } else { // Native Linux (0, child_process_1.execSync)(`xdg-open "${url}"`, { stdio: 'ignore' }); } } else { // Unknown platform, try xdg-open (0, child_process_1.execSync)(`xdg-open "${url}"`, { stdio: 'ignore' }); } } catch (error) { console.log(`⚠️ Failed to open browser automatically.`); console.log(` Visit: ${url}`); } }