UNPKG

capsule-ai-cli

Version:

The AI Model Orchestrator - Intelligent multi-model workflows with device-locked licensing

247 lines 9.99 kB
import React from 'react'; import { Box, Text } from 'ink'; import chalk from 'chalk'; function getContentPreview(content, toolName, metadata) { const lines = []; try { if (content.startsWith('{') && content.includes('"')) { return []; } switch (toolName) { case 'Read': case 'Write': { const fileLines = content.split('\n').filter(l => l.trim()); if (fileLines.length > 0) { lines.push(fileLines[0]); if (fileLines.length > 1) { lines.push(fileLines[1]); } } break; } case 'List': { const items = content.split('\n').filter(l => l.trim()).slice(0, 3); items.forEach(item => { lines.push(item); }); break; } case 'Search': case 'Grep': { const matches = content.split('\n').filter(l => l.trim()).slice(0, 2); matches.forEach(match => { const cleaned = match.replace(/^[^:]+:/, ''); lines.push(cleaned); }); break; } case 'Bash': { const outputLines = content.split('\n').filter(l => l.trim()).slice(0, 2); outputLines.forEach(line => { lines.push(line); }); break; } case 'Git': { const gitLines = content.split('\n').filter(l => l.trim()).slice(0, 3); gitLines.forEach(line => { lines.push(line); }); break; } case 'Todo': case 'TodoWrite': if (metadata?.todoDisplay) { const todoLines = metadata.todoDisplay.split('\n') .filter((l) => l.includes('[') && (l.includes('✓') || l.includes('○') || l.includes('→'))) .slice(0, 2); todoLines.forEach((line) => { const cleaned = line.replace(/^\s*\d+\.\s*/, '').trim(); lines.push(cleaned); }); } break; default: { const previewLines = content.split('\n').filter(l => l.trim()).slice(0, 2); previewLines.forEach(line => { lines.push(line); }); } } } catch { const fallbackLines = content.split('\n').filter(l => l.trim()).slice(0, 1); if (fallbackLines.length > 0) { lines.push(fallbackLines[0]); } } return lines; } const TOOL_ICONS = { 'Read': '⏺', 'Write': '⏺', 'Edit': '⏺', 'MultiEdit': '⏺', 'Bash': '⏺', 'Grep': '⏺', 'Glob': '⏺', 'Search': '⏺', 'Sub-Agents': '⏺', 'Todo': '⏺', 'TodoWrite': '⏺', 'LS': '⏺', 'List': '⏺', 'WebFetch': '⏺', 'WebSearch': '⏺', 'Git': '⏺', 'Web Fetch': '⏺', 'Sub-Agent Results': '⏺', 'ExitPlanMode': '⏺', }; const formatCompactSummary = (toolName, metadata) => { const { filePath, additions, deletions, linesRead, matchCount, fileCount, command, error, taskCount, success, todoDisplay, todoCount } = metadata || {}; if (error || success === false) { return chalk.hex('#FF0000')(`Error: ${error || 'Operation failed'}`); } switch (toolName) { case 'Read': return `Read ${linesRead || 0} lines ${filePath ? `from ${filePath}` : ''}`; case 'Write': return `Created ${filePath || 'file'} with ${linesRead || 0} lines`; case 'Edit': case 'MultiEdit': return `Updated ${filePath || 'file'}: +${additions || 0} -${deletions || 0}`; case 'Bash': return `$ ${command || 'command'}`; case 'Grep': return `Found ${matchCount || 0} matches in ${fileCount || 0} files`; case 'Glob': return `Found ${fileCount || 0} files`; case 'Search': if (metadata?.resultCount !== undefined) { return `Found ${metadata.resultCount} results`; } return `Search completed`; case 'Sub-Agents': if (metadata?.agentStatus === 'completed') { return `Sub-agent completed`; } else if (metadata?.agentStatus === 'failed') { return chalk.hex('#FF0000')(`Sub-agent failed`); } else if (metadata?.agentStatus === 'running') { return `Sub-agent running...`; } else if (taskCount && taskCount > 1) { return `Spawned ${taskCount} sub-agents`; } return `Spawned sub-agent`; case 'Todo': case 'TodoWrite': if (todoDisplay) { const lines = todoDisplay.split('\n').filter((line) => line.trim()); const tasks = lines.slice(0, 3).map((line) => { const match = line.match(/[⎿\s]*(☐|☑|◐|☒|⊗)\s*(.+)/); if (match) { const status = match[1]; const description = match[2].trim(); return `${status} ${description}`; } return line.trim(); }).filter((t) => t && !t.startsWith('⎿')); const uniqueTasks = Array.from(new Set(tasks)); if (uniqueTasks.length === 0) { return `No tasks`; } if (uniqueTasks.length === 1) { return uniqueTasks[0]; } else { return uniqueTasks.map((task, index) => { if (index === 0) return task; return '\n' + task; }).join('') + (uniqueTasks.length < tasks.length ? chalk.hex('#808080')(' (deduped)') : ''); } } else if (todoCount !== undefined) { return `${todoCount} task${todoCount !== 1 ? 's' : ''}`; } return `Updated todo list`; case 'LS': case 'List': if (fileCount !== undefined) { return `Listed ${fileCount} items`; } return `Listed directory`; case 'WebFetch': case 'Web Fetch': if (metadata?.status) { return `${metadata.url || 'Web page'} - ${metadata.status}`; } return `Fetched web content`; case 'WebSearch': return `Searched the web`; case 'Git': if (metadata?.gitCommand) { return `git ${metadata.gitCommand}${metadata.gitSummary ? ` - ${metadata.gitSummary}` : ''}`; } return `Git command executed`; case 'ExitPlanMode': return `Exited plan mode`; case 'Sub-Agent Results': if (metadata?.agentCount) { return `${metadata.agentCount} sub-agent${metadata.agentCount > 1 ? 's' : ''} completed`; } return `Sub-agents completed`; default: return `Completed`; } }; export const ToolResultDisplay = ({ toolName, content, metadata }) => { const icon = TOOL_ICONS[toolName] || '⏺'; const isError = metadata?.error || metadata?.success === false; const summaryColor = isError ? '#FF0000' : '#00FF00'; return (React.createElement(Box, { flexDirection: "column", marginTop: 0.25, flexGrow: 1 }, React.createElement(Box, { flexWrap: "wrap" }, React.createElement(Text, { color: summaryColor, wrap: "wrap" }, icon, " ", chalk.bold(toolName), (() => { if (metadata?.filePath) { return `(${metadata.filePath})`; } else if (metadata?.command) { return `(${metadata.command})`; } else if (metadata?.url) { return `(${metadata.url})`; } else if (metadata?.query) { return `(${metadata.query})`; } else if (metadata?.args) { return `(${metadata.args})`; } return ''; })())), (() => { const preview = getContentPreview(content, toolName, metadata); if (preview.length > 0) { return (React.createElement(Box, { marginLeft: 4, flexDirection: "column", flexWrap: "wrap" }, preview.map((line, index) => (React.createElement(Box, { key: `preview-${index}`, flexWrap: "wrap" }, React.createElement(Text, { color: "#808080" }, "\u23BF "), React.createElement(Text, { dimColor: true, wrap: "wrap" }, line)))))); } return null; })(), React.createElement(Box, { marginLeft: 4, flexDirection: "column", flexWrap: "wrap" }, (() => { const summary = formatCompactSummary(toolName, metadata); const lines = summary.split('\n'); return lines.map((line, index) => (React.createElement(Box, { key: index, flexWrap: "wrap" }, index === 0 && React.createElement(Text, { color: "#808080" }, "\u23BF "), index > 0 && React.createElement(Text, null, " "), React.createElement(Text, { color: isError ? '#FF0000' : undefined, wrap: "wrap" }, line)))); })()))); }; //# sourceMappingURL=ToolResultDisplay.js.map