UNPKG

automagik-genie

Version:

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

155 lines (154 loc) 7.47 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createListHandler = createListHandler; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); 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 markdown_formatter_1 = require("../../lib/markdown-formatter"); const utils_1 = require("../../lib/utils"); const COLLECTIVE_MARKER = 'AGENTS.md'; function createListHandler(ctx) { return async (parsed) => { const [targetRaw] = parsed.commandArgs; const target = (targetRaw || 'collectives').toLowerCase(); if (target === 'collectives' || target === 'agents') { return listCollectivesView(ctx, parsed); } if (target === 'workflows') { return listWorkflowsView(ctx, parsed); } if (target === 'skills') { return listSkillsView(ctx, parsed); } if (target === 'tasks' || target === 'sessions') { const forgeExecutor = (0, forge_executor_1.createForgeExecutor)(); // NOTE: Agent profile sync removed - Forge discovers .genie folders natively let forgeAvailable = true; // Assume Forge is available (will fail on listTasks() if not) if (forgeAvailable) { try { const sessions = await forgeExecutor.listTasks(); const markdown = (0, markdown_formatter_1.formatTaskList)(sessions.map((session) => ({ taskId: session.id, agent: session.agent, status: session.status, executor: [session.executor, session.variant].filter(Boolean).join('/'), model: session.model || undefined, started: session.created, updated: session.updated }))); await ctx.emitView(markdown, parsed.options); return; } catch (error) { forgeAvailable = false; const reason = (0, forge_helpers_1.describeForgeError)(error); ctx.recordRuntimeWarning(`Forge session listing failed: ${reason}`); } } const store = ctx.sessionService.load({ onWarning: ctx.recordRuntimeWarning }); const sessions = Object.entries(store.sessions || {}).map(([attemptId, entry]) => ({ taskId: attemptId, // Now truly the UUID (issue #407 fix) agent: entry.agent, status: entry.status || 'unknown', executor: [entry.executor, entry.executorVariant].filter(Boolean).join('/'), model: entry.model || undefined, started: entry.created, updated: entry.lastUsed })); const markdown = (0, markdown_formatter_1.formatTaskList)(sessions); const fallbackLines = [ '⚠️ Forge backend unreachable. Showing cached tasks from `.genie/state/tasks.json`.', forge_helpers_1.FORGE_RECOVERY_HINT, '', markdown.trim() ]; await ctx.emitView(fallbackLines.join('\n'), parsed.options); return; } throw new Error(`Unknown list target '${targetRaw}'. Try 'agents', 'workflows', 'skills', or 'tasks'.`); }; } async function listCollectivesView(ctx, parsed) { const agents = (0, agent_resolver_1.listAgents)(); const lines = []; lines.push(`# Genie Agents (${agents.length} total)\n`); // Group by collective const byCollective = new Map(); agents.forEach(agent => { const key = agent.collective || 'root'; if (!byCollective.has(key)) byCollective.set(key, []); byCollective.get(key).push(agent); }); // Sort collectives const sorted = Array.from(byCollective.entries()).sort((a, b) => a[0].localeCompare(b[0])); sorted.forEach(([collective, items]) => { lines.push(`## ${collective} (${items.length})`); items .sort((a, b) => a.id.localeCompare(b.id)) .forEach(agent => { const desc = agent.meta?.description || agent.meta?.summary || ''; const shortDesc = desc ? ` - ${(0, utils_1.truncateText)(desc.replace(/\s+/g, ' ').trim(), 60)}` : ''; lines.push(` ${agent.id}${shortDesc}`); }); lines.push(''); }); lines.push('Usage: `genie run <agent-id> "<prompt>"`'); await ctx.emitView(lines.join('\n'), parsed.options); } function listMarkdownDocs(dir, exclude = new Set()) { if (!fs_1.default.existsSync(dir) || !fs_1.default.statSync(dir).isDirectory()) return []; return fs_1.default .readdirSync(dir, { withFileTypes: true }) .filter(entry => entry.isFile() && entry.name.endsWith('.md') && !exclude.has(entry.name)) .map(entry => entry.name.replace(/\.md$/i, '')) .sort((a, b) => a.localeCompare(b)); } async function listWorkflowsView(ctx, parsed) { const workspaceRoot = path_1.default.join(process.cwd(), '.genie'); const globalWorkflowsDir = path_1.default.join(workspaceRoot, 'workflows'); const globalWorkflows = listMarkdownDocs(globalWorkflowsDir); const collectives = (0, agent_resolver_1.listCollectives)(); const ordered = collectives.slice().sort((a, b) => a.collective.localeCompare(b.collective)); const lines = []; lines.push(`# Workflows Index`); lines.push(''); lines.push(`## Global (.genie/workflows/)`); lines.push(globalWorkflows.length ? `- ${globalWorkflows.join('\n- ')}` : '_None_'); lines.push(''); ordered.forEach(info => { const wfDir = path_1.default.join(info.root, 'workflows'); const items = listMarkdownDocs(wfDir); lines.push(`## ${info.collective} (${path_1.default.relative(workspaceRoot, wfDir)})`); lines.push(items.length ? `- ${items.join('\n- ')}` : '_None_'); lines.push(''); }); await ctx.emitView(lines.join('\n'), parsed.options); } async function listSkillsView(ctx, parsed) { const workspaceRoot = path_1.default.join(process.cwd(), '.genie'); const globalSkillsDir = path_1.default.join(workspaceRoot, 'skills'); const globalSkills = listMarkdownDocs(globalSkillsDir); const collectives = (0, agent_resolver_1.listCollectives)(); const ordered = collectives.slice().sort((a, b) => a.collective.localeCompare(b.collective)); const lines = []; lines.push(`# Skills Index`); lines.push(''); lines.push(`## Global (.genie/skills/)`); lines.push(globalSkills.length ? `- ${globalSkills.join('\n- ')}` : '_None_'); lines.push(''); ordered.forEach(info => { const skillsDir = path_1.default.join(info.root, 'skills'); const items = listMarkdownDocs(skillsDir); lines.push(`## ${info.collective} (${path_1.default.relative(workspaceRoot, skillsDir)})`); lines.push(items.length ? `- ${items.join('\n- ')}` : '_None_'); lines.push(''); }); await ctx.emitView(lines.join('\n'), parsed.options); }