UNPKG

termcode

Version:

Superior terminal AI coding agent with enterprise-grade security, intelligent error recovery, performance monitoring, and plugin system - Advanced Claude Code alternative

148 lines (147 loc) 6.49 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useState, useEffect } from 'react'; import { Box, Text } from 'ink'; import SelectInput from 'ink-select-input'; export const CommandPalette = ({ onClose, onExecute, providers, currentProvider, currentModel, }) => { const [filter, setFilter] = useState(''); // Build command palette items const commands = [ // Provider switching ...providers.map(provider => ({ id: `provider-${provider}`, title: `Switch to ${provider}`, description: `Change provider to ${provider}`, category: 'provider', action: () => onExecute(`/provider ${provider}`), })), // Common models for each provider { id: 'model-gpt4o', title: 'GPT-4o', description: 'OpenAI\'s flagship model', category: 'model', action: () => onExecute('/model gpt-4o'), }, { id: 'model-claude-sonnet', title: 'Claude 3.5 Sonnet', description: 'Anthropic\'s flagship model', category: 'model', action: () => onExecute('/model claude-3-5-sonnet-20241022'), }, { id: 'model-grok', title: 'Grok Beta', description: 'xAI\'s conversational model', category: 'model', action: () => onExecute('/model grok-beta'), }, // Actions { id: 'action-test', title: 'Run Tests', description: 'Execute project test suite', category: 'test', action: () => onExecute('test'), }, { id: 'action-lint', title: 'Run Linter', description: 'Check code style and quality', category: 'test', action: () => onExecute('lint'), }, { id: 'action-build', title: 'Run Build', description: 'Compile and build project', category: 'test', action: () => onExecute('build'), }, // Git actions { id: 'git-rollback', title: 'Rollback Changes', description: 'Discard all changes and return to main', category: 'git', action: () => onExecute('rollback'), }, { id: 'git-merge', title: 'Merge to Main', description: 'Merge current branch to main', category: 'git', action: () => onExecute('merge'), }, // Information commands { id: 'action-whoami', title: 'Session Info', description: 'Show current session details', category: 'action', action: () => onExecute('/whoami'), }, { id: 'action-health', title: 'Health Check', description: 'Check provider connectivity', category: 'action', action: () => onExecute('/health'), }, { id: 'action-budget', title: 'Budget Status', description: 'Show usage and costs', category: 'action', action: () => onExecute('/budget'), }, ]; // Filter commands based on search const filteredCommands = commands.filter(cmd => cmd.title.toLowerCase().includes(filter.toLowerCase()) || cmd.description.toLowerCase().includes(filter.toLowerCase())); // Group by category const groupedCommands = filteredCommands.reduce((groups, cmd) => { if (!groups[cmd.category]) { groups[cmd.category] = []; } groups[cmd.category].push(cmd); return groups; }, {}); // Convert to SelectInput format const selectItems = Object.entries(groupedCommands).flatMap(([category, items]) => [ // Category header { label: `── ${category.toUpperCase()} ──`, value: `header-${category}`, disabled: true, }, // Category items ...items.map(item => ({ label: `${item.title}`, value: item.id, })), ]); const handleSelect = (item) => { if (item.value.startsWith('header-')) { return; // Ignore category headers } const command = commands.find(cmd => cmd.id === item.value); if (command) { command.action(); } onClose(); }; // Handle escape key to close useEffect(() => { const handleKeyPress = (str, key) => { if (key.escape) { onClose(); } }; process.stdin.on('keypress', handleKeyPress); return () => { process.stdin.off('keypress', handleKeyPress); }; }, [onClose]); return (_jsxs(Box, { position: "absolute", top: 2, left: 2, right: 2, bottom: 2, borderStyle: "double", borderColor: "blue", backgroundColor: "black", flexDirection: "column", children: [_jsxs(Box, { paddingX: 2, paddingY: 1, borderStyle: "single", borderTop: false, borderLeft: false, borderRight: false, children: [_jsx(Text, { color: "blue", bold: true, children: "\u26A1 Command Palette" }), _jsx(Box, { marginLeft: "auto", children: _jsx(Text, { color: "gray", dimColor: true, children: "ESC to close" }) })] }), _jsx(Box, { paddingX: 2, paddingBottom: 1, children: _jsxs(Text, { color: "gray", children: ["Provider: ", _jsx(Text, { color: "cyan", children: currentProvider }), " \u2022 Model: ", _jsx(Text, { color: "white", children: currentModel })] }) }), _jsx(Box, { paddingX: 2, paddingY: 1, flexGrow: 1, children: selectItems.length === 0 ? (_jsx(Text, { color: "gray", dimColor: true, children: "No commands found" })) : (_jsx(SelectInput, { items: selectItems, onSelect: handleSelect, indicatorComponent: ({ isSelected }) => (_jsx(Box, { marginRight: 1, children: _jsx(Text, { color: isSelected ? 'blue' : 'gray', children: isSelected ? '▶' : ' ' }) })), itemComponent: ({ isSelected, label }) => (_jsx(Text, { color: isSelected ? 'blue' : 'white', children: label })) })) }), _jsx(Box, { paddingX: 2, paddingY: 1, borderStyle: "single", borderBottom: false, borderLeft: false, borderRight: false, justifyContent: "center", children: _jsx(Text, { color: "gray", dimColor: true, children: "\u2191\u2193 Navigate \u2022 Enter: Execute \u2022 ESC: Cancel" }) })] })); };