UNPKG

@graphteon/juricode

Version:

We are forging the future with lines of digital steel

806 lines 55.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = __importStar(require("react")); const ink_1 = require("ink"); const ws_client_1 = require("../api/ws-client"); const format_message_1 = require("../utils/format-message"); const open_hands_1 = __importDefault(require("../api/open-hands")); const index_1 = require("../index"); const ConversationTUI = react_1.default.memo(({ taskId }) => { const [messages, setMessages] = (0, react_1.useState)([]); const [inputValue, setInputValue] = (0, react_1.useState)(''); const [isConnected, setIsConnected] = (0, react_1.useState)(false); const [agentState, setAgentState] = (0, react_1.useState)('connecting'); const [isInputMode, setIsInputMode] = (0, react_1.useState)(false); const [currentTaskId, setCurrentTaskId] = (0, react_1.useState)(taskId || ''); const wsRef = (0, react_1.useRef)(null); const inputValueRef = (0, react_1.useRef)(''); (0, react_1.useEffect)(() => { inputValueRef.current = inputValue; }, [inputValue]); const [currentMode, setCurrentMode] = (0, react_1.useState)(taskId ? 'conversation' : 'menu'); const [selectedIndex, setSelectedIndex] = (0, react_1.useState)(0); const [loading, setLoading] = (0, react_1.useState)(false); const [error, setError] = (0, react_1.useState)(null); const [tasks, setTasks] = (0, react_1.useState)([]); const [suggestedTasks, setSuggestedTasks] = (0, react_1.useState)([]); const [repositories, setRepositories] = (0, react_1.useState)([]); const [branches, setBranches] = (0, react_1.useState)([]); const [filteredRepos, setFilteredRepos] = (0, react_1.useState)([]); const [selectedRepo, setSelectedRepo] = (0, react_1.useState)(null); const [createStep, setCreateStep] = (0, react_1.useState)(0); const [createForm, setCreateForm] = (0, react_1.useState)({ title: '', message: '', repository: '', gitProvider: '', branch: 'main' }); const [selectedRepoIndex, setSelectedRepoIndex] = (0, react_1.useState)(0); const [selectedBranchIndex, setSelectedBranchIndex] = (0, react_1.useState)(0); const [creating, setCreating] = (0, react_1.useState)(false); const [searchMode, setSearchMode] = (0, react_1.useState)(false); const [searchTerm, setSearchTerm] = (0, react_1.useState)(''); const { exit } = (0, ink_1.useApp)(); const forceExit = (0, react_1.useCallback)(() => { try { if (wsRef.current) { wsRef.current.disconnect(); } exit(); setTimeout(() => { process.exit(0); }, 100); } catch (error) { process.exit(0); } }, [exit]); const menuItems = [ { title: '📋 View All Tasks', value: 'tasks' }, { title: '💡 Suggested Tasks', value: 'suggested' }, { title: '📚 Browse Repositories', value: 'repositories' }, { title: '📝 Create New Task', value: 'create' }, { title: '🚪 Exit', value: 'exit' } ]; const createSteps = [ 'Enter Task Title', 'Enter Initial Message (Optional)', 'Select Repository', 'Select Branch', 'Review & Create' ]; (0, react_1.useEffect)(() => { if (currentTaskId && currentMode === 'conversation') { setMessages([]); const ws = new ws_client_1.WSClient(); wsRef.current = ws; const processedMessageIds = new Set(); ws.onConnect(() => { setIsConnected(true); setAgentState('ready'); }); ws.onMessage((event) => { const messageId = `${event.id}-${event.timestamp}`; if (processedMessageIds.has(messageId)) { return; } processedMessageIds.add(messageId); if (event.source === 'agent' && event.action === 'system') { return; } const formatted = (0, format_message_1.formatMessage)(event); const newMessage = { id: messageId, source: event.source, content: formatted.text, timestamp: new Date(event.timestamp), status: 'success' }; setMessages((prev) => { const exists = prev.some(msg => msg.id === messageId); if (exists) { return prev; } return [...prev, newMessage]; }); }); ws.onError((error) => { const errorMessage = { id: `error-${Date.now()}`, source: 'system', content: `Error: ${error.message}`, timestamp: new Date(), status: 'error' }; setMessages((prev) => [...prev, errorMessage]); }); ws.onStateChange((state) => { setAgentState(state); if (state === 'awaiting_user_input' || state === 'finished') { setIsInputMode(true); } else { setIsInputMode(false); } }); ws.connect(currentTaskId).catch((error) => { const errorMessage = { id: `connect-error-${Date.now()}`, source: 'system', content: `Failed to connect: ${error.message}`, timestamp: new Date(), status: 'error' }; setMessages((prev) => [...prev, errorMessage]); }); return () => { ws.disconnect(); processedMessageIds.clear(); }; } }, [currentTaskId, currentMode]); (0, react_1.useEffect)(() => { switch (currentMode) { case 'tasks': fetchTasks(); break; case 'suggested': fetchSuggestedTasks(); break; case 'repositories': fetchRepositories(); break; case 'create': if (createStep === 2) fetchRepositories(); if (createStep === 3 && createForm.repository && createForm.repository.trim() !== '') fetchBranches(); break; } }, [currentMode, createStep, createForm.repository]); (0, react_1.useEffect)(() => { if (searchTerm) { const filtered = repositories.filter(repo => repo.full_name.toLowerCase().includes(searchTerm.toLowerCase())); setFilteredRepos(filtered); setSelectedIndex(0); } else { setFilteredRepos(repositories); } }, [searchTerm, repositories]); const fetchTasks = async () => { try { setLoading(true); const userTasks = await open_hands_1.default.getUserConversations(); setTasks(userTasks); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch tasks'); } finally { setLoading(false); } }; const fetchSuggestedTasks = async () => { try { setLoading(true); const suggested = await open_hands_1.default.getSuggestedTasks(); setSuggestedTasks(suggested); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch suggested tasks'); } finally { setLoading(false); } }; const fetchRepositories = async () => { try { setLoading(true); const repos = await open_hands_1.default.retrieveUserGitRepositories(); setRepositories(repos); setFilteredRepos(repos); setSelectedRepoIndex(-1); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch repositories'); } finally { setLoading(false); } }; const fetchBranches = async () => { try { setLoading(true); const repoBranches = await open_hands_1.default.getRepositoryBranches(createForm.repository); setBranches(repoBranches); setSelectedBranchIndex(0); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch branches'); } finally { setLoading(false); } }; const createTask = async () => { try { setCreating(true); const conversation = await open_hands_1.default.createConversation(createForm.repository || undefined, createForm.gitProvider || undefined, createForm.message || undefined, [], undefined, createForm.repository ? createForm.branch : undefined); setCurrentTaskId(conversation.conversation_id); setCurrentMode('conversation'); setMessages([]); setCreateStep(0); setCreateForm({ title: '', message: '', repository: '', gitProvider: '', branch: 'main' }); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create task'); } finally { setCreating(false); } }; const selectTask = (task) => { setCurrentTaskId(task.conversation_id); setCurrentMode('conversation'); setMessages([]); }; const selectSuggestedTask = async (task) => { try { setLoading(true); const conversation = await open_hands_1.default.createConversationFromSuggestedTask(task); setCurrentTaskId(conversation.conversation_id); setCurrentMode('conversation'); setMessages([]); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create conversation from suggested task'); } finally { setLoading(false); } }; const selectRepository = (repo) => { setSelectedRepo(repo); setCurrentMode('branches'); fetchRepositoryBranches(repo); }; const fetchRepositoryBranches = async (repo) => { try { setLoading(true); const repoBranches = await open_hands_1.default.getRepositoryBranches(repo.full_name); setBranches(repoBranches); setSelectedIndex(0); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch branches'); } finally { setLoading(false); } }; const selectBranch = async (repo, branch) => { try { setLoading(true); const conversation = await open_hands_1.default.createConversation(repo.full_name, repo.git_provider, undefined, [], undefined, branch.name); setCurrentTaskId(conversation.conversation_id); setCurrentMode('conversation'); setMessages([]); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create conversation from repository'); } finally { setLoading(false); } }; const goBack = () => { if (currentMode === 'conversation') { setCurrentMode('menu'); setCurrentTaskId(''); setMessages([]); if (wsRef.current) { wsRef.current.disconnect(); } } else if (currentMode === 'branches') { setCurrentMode('repositories'); } else if (currentMode === 'create' && createStep > 0) { setCreateStep(createStep - 1); } else { setCurrentMode('menu'); setSelectedIndex(0); } }; const handleEditorCommand = (0, react_1.useCallback)(async () => { try { setAgentState('processing'); const processingMessage = { id: Date.now().toString(), source: 'system', content: 'Setting up VSCode editor tunnel...', timestamp: new Date(), status: 'pending' }; setMessages((prev) => [...prev, processingMessage]); const vscodeUrl = await (0, index_1.setupVSCodeTunnelFromAPI)(currentTaskId); const successMessage = { id: Date.now().toString(), source: 'system', content: `VSCode editor is now available at: ${vscodeUrl}`, timestamp: new Date(), status: 'success' }; setMessages((prev) => [...prev, successMessage]); setAgentState('ready'); setIsInputMode(true); } catch (error) { const errorMessage = { id: Date.now().toString(), source: 'system', content: `Failed to setup VSCode editor: ${error instanceof Error ? error.message : 'Unknown error'}`, timestamp: new Date(), status: 'error' }; setMessages((prev) => [...prev, errorMessage]); setAgentState('ready'); setIsInputMode(true); } }, [currentTaskId]); const handleInput = (0, react_1.useCallback)((input, key) => { if (key.escape) { if (currentMode === 'menu') { forceExit(); return; } else { goBack(); return; } } if (input === 'q' || input === 'Q') { forceExit(); return; } if (loading || creating) return; if (currentMode === 'conversation') { if (!isInputMode) return; if (key.return) { if (inputValue.trim()) { const userMessage = { id: Date.now().toString(), source: 'user', content: inputValue, timestamp: new Date(), status: 'success' }; setMessages((prev) => [...prev, userMessage]); if (inputValue.trim() === '/editor') { handleEditorCommand(); } else { if (wsRef.current) { wsRef.current.send(inputValue); } } inputValueRef.current = ''; setInputValue(''); setIsInputMode(false); setAgentState('processing'); } } else if (key.backspace || key.delete) { const newValue = inputValueRef.current.slice(0, -1); inputValueRef.current = newValue; setImmediate(() => setInputValue(newValue)); } else if (input) { const newValue = inputValueRef.current + input; inputValueRef.current = newValue; setImmediate(() => setInputValue(newValue)); } return; } if (currentMode === 'menu') { if (key.upArrow && selectedIndex > 0) { setSelectedIndex(selectedIndex - 1); } if (key.downArrow && selectedIndex < menuItems.length - 1) { setSelectedIndex(selectedIndex + 1); } if (key.return) { const selectedItem = menuItems[selectedIndex]; if (selectedItem.value === 'exit') { forceExit(); } else { setCurrentMode(selectedItem.value); setSelectedIndex(0); } } return; } if (currentMode === 'tasks') { if (key.upArrow && selectedIndex > 0) { setSelectedIndex(selectedIndex - 1); } if (key.downArrow && selectedIndex < tasks.length - 1) { setSelectedIndex(selectedIndex + 1); } if (key.return && tasks.length > 0) { selectTask(tasks[selectedIndex]); } return; } if (currentMode === 'suggested') { if (key.upArrow && selectedIndex > 0) { setSelectedIndex(selectedIndex - 1); } if (key.downArrow && selectedIndex < suggestedTasks.length - 1) { setSelectedIndex(selectedIndex + 1); } if (key.return && suggestedTasks.length > 0) { selectSuggestedTask(suggestedTasks[selectedIndex]); } return; } if (currentMode === 'repositories') { if (searchMode) { if (key.return) { setSearchMode(false); return; } if (key.backspace || key.delete) { setSearchTerm(prev => prev.slice(0, -1)); return; } if (input && input.length === 1) { setSearchTerm(prev => prev + input); return; } return; } if (key.upArrow && selectedIndex > 0) { setSelectedIndex(selectedIndex - 1); } if (key.downArrow && selectedIndex < filteredRepos.length - 1) { setSelectedIndex(selectedIndex + 1); } if (key.return && filteredRepos.length > 0) { selectRepository(filteredRepos[selectedIndex]); } if (input === 's') { setSearchMode(true); } return; } if (currentMode === 'branches') { if (key.upArrow && selectedIndex > 0) { setSelectedIndex(selectedIndex - 1); } if (key.downArrow && selectedIndex < branches.length - 1) { setSelectedIndex(selectedIndex + 1); } if (key.return && branches.length > 0 && selectedRepo) { selectBranch(selectedRepo, branches[selectedIndex]); } return; } if (currentMode === 'create') { if (createStep === 0) { if (key.return && createForm.title.trim()) { setCreateStep(1); return; } if (key.backspace || key.delete) { setCreateForm(prev => ({ ...prev, title: prev.title.slice(0, -1) })); return; } if (input && input.length === 1) { setCreateForm(prev => ({ ...prev, title: prev.title + input })); return; } } if (createStep === 1) { if (key.return) { setCreateStep(2); return; } if (key.backspace || key.delete) { setCreateForm(prev => ({ ...prev, message: prev.message.slice(0, -1) })); return; } if (input && input.length === 1) { setCreateForm(prev => ({ ...prev, message: prev.message + input })); return; } } if (createStep === 2) { if (searchMode) { if (key.return) { if (selectedRepoIndex === -1) { setCreateForm(prev => ({ ...prev, repository: '', gitProvider: '', branch: 'main' })); setCreateStep(4); setSearchMode(false); setSearchTerm(''); } else { setSearchMode(false); setSelectedRepoIndex(0); } return; } if (key.backspace || key.delete) { setSearchTerm(prev => prev.slice(0, -1)); return; } if (input && input.length === 1) { setSearchTerm(prev => prev + input); return; } return; } const filteredRepos = searchTerm ? repositories.filter(repo => repo.full_name.toLowerCase().includes(searchTerm.toLowerCase())) : repositories; if (key.upArrow) { setSelectedRepoIndex(Math.max(-1, selectedRepoIndex - 1)); } if (key.downArrow) { setSelectedRepoIndex(Math.min(filteredRepos.length - 1, selectedRepoIndex + 1)); } if (key.return) { if (selectedRepoIndex === -1) { setCreateForm(prev => ({ ...prev, repository: '', gitProvider: '', branch: 'main' })); setCreateStep(4); } else if (filteredRepos.length > 0 && selectedRepoIndex < filteredRepos.length) { const selectedRepo = filteredRepos[selectedRepoIndex]; setCreateForm(prev => ({ ...prev, repository: selectedRepo.full_name, gitProvider: selectedRepo.git_provider })); setCreateStep(3); } return; } if (input === 'n' || input === 'N') { setCreateForm(prev => ({ ...prev, repository: '', gitProvider: '', branch: 'main' })); setCreateStep(4); return; } if (input === 's' || input === 'S') { setSearchMode(true); setSearchTerm(''); return; } } if (createStep === 3) { if (key.upArrow && selectedBranchIndex > 0) { setSelectedBranchIndex(selectedBranchIndex - 1); } if (key.downArrow && selectedBranchIndex < branches.length - 1) { setSelectedBranchIndex(selectedBranchIndex + 1); } if (key.return && branches.length > 0) { const selectedBranch = branches[selectedBranchIndex]; setCreateForm(prev => ({ ...prev, branch: selectedBranch.name })); setCreateStep(4); return; } } if (createStep === 4) { if (key.return) { createTask(); return; } } return; } }, [currentMode, loading, creating, isInputMode, inputValue, handleEditorCommand, goBack, forceExit, selectedIndex, menuItems, tasks, suggestedTasks, filteredRepos, branches, selectedRepo, createStep, createForm, selectedRepoIndex, repositories, selectedBranchIndex, searchMode, searchTerm]); (0, ink_1.useInput)(handleInput); const getStatusIcon = (0, react_1.useCallback)((status) => { switch (status) { case 'success': return '✓'; case 'error': return '✗'; case 'pending': return '⏳'; default: return ''; } }, []); const getSourceIcon = (0, react_1.useCallback)((source) => { switch (source) { case 'user': return '🧔'; case 'agent': return '🤖'; case 'system': return '💻'; default: return ''; } }, []); const getAgentStateText = (0, react_1.useCallback)(() => { switch (agentState) { case 'connecting': return 'Connecting...'; case 'ready': return 'Ready for input'; case 'processing': return 'Agent is processing'; case 'awaiting_user_input': return 'Ready for input'; case 'finished': return 'Agent finished'; default: return agentState; } }, [agentState]); const getStatusColor = (status) => { switch (status.toLowerCase()) { case 'running': return 'green'; case 'stopped': return 'red'; case 'finished': return 'blue'; default: return 'yellow'; } }; const formatDate = (dateString) => { return new Date(dateString).toLocaleDateString(); }; const getHeaderTitle = () => { switch (currentMode) { case 'menu': return '🏠 JuriCode Main Menu'; case 'conversation': return '💬 JuriCode Conversation'; case 'tasks': return '📋 All Tasks'; case 'suggested': return '💡 Suggested Tasks'; case 'repositories': return '📚 Browse Repositories'; case 'branches': return `🌿 Select Branch - ${selectedRepo?.full_name}`; case 'create': return `📝 Create New Task - Step ${createStep + 1} of ${createSteps.length}: ${createSteps[createStep]}`; default: return '🏠 JuriCode'; } }; const visibleMessages = (0, react_1.useMemo)(() => { const maxVisibleMessages = 10; return messages.slice(-maxVisibleMessages); }, [messages]); const messageComponents = (0, react_1.useMemo)(() => { return visibleMessages.map((message) => ((0, jsx_runtime_1.jsxs)(ink_1.Box, { marginBottom: 1, children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: message.source === 'user' ? 'blue' : message.source === 'agent' ? 'green' : 'yellow', children: [getSourceIcon(message.source), " ", message.source === 'user' ? 'You' : message.source === 'agent' ? 'Assistant' : 'System', " ", message.timestamp.toLocaleTimeString(), " ", getStatusIcon(message.status)] }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginLeft: 2, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { wrap: "wrap", children: message.content }) })] }, message.id))); }, [visibleMessages, getSourceIcon, getStatusIcon]); const inputDisplayText = (0, react_1.useMemo)(() => { return isInputMode ? inputValue : 'Waiting for agent...'; }, [isInputMode, inputValue]); const cursorComponent = (0, react_1.useMemo)(() => { return isInputMode ? (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "\u2588" }) : null; }, [isInputMode]); const inputArea = (0, react_1.useMemo)(() => ((0, jsx_runtime_1.jsxs)(ink_1.Box, { borderStyle: "single", borderColor: isInputMode ? 'green' : 'gray', paddingX: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: isInputMode ? 'green' : 'gray', children: isInputMode ? '> ' : '⏸ ' }), (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: isInputMode ? 'white' : 'gray', children: [inputDisplayText, cursorComponent] })] })), [isInputMode, inputDisplayText, cursorComponent]); const renderContent = (0, react_1.useCallback)(() => { if (currentMode === 'conversation') { return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", flexGrow: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: messages.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: agentState === 'connecting' ? 'Connecting to conversation...' : 'No messages yet. Start typing below!' })) : ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [messages.length > 10 ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: ["... ", messages.length - 10, " older messages"] })) : null, messageComponents] })) }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: ["Status: ", getAgentStateText()] }), (0, jsx_runtime_1.jsx)(ink_1.Spacer, {}), (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: ["Task ID: ", currentTaskId] })] }), inputArea, (0, jsx_runtime_1.jsx)(ink_1.Box, { paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: [isInputMode ? 'Type your message and press Enter to send' : 'Please wait for the agent to finish processing', ' • Press ESC to go back to menu'] }) })] })); } if (currentMode === 'menu') { return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: menuItems.map((item, index) => ((0, jsx_runtime_1.jsx)(ink_1.Box, { children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: index === selectedIndex ? 'green' : 'white', bold: true, children: [index === selectedIndex ? '▶ ' : ' ', item.title] }) }, item.value))) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "\u2191\u2193 Navigate \u2022 Enter Select \u2022 Q Quit" }) })] })); } if (currentMode === 'tasks') { return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: loading ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { justifyContent: "center", alignItems: "center", height: "100%", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading tasks..." }) })) : error ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { justifyContent: "center", alignItems: "center", height: "100%", children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] }) })) : tasks.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { justifyContent: "center", alignItems: "center", height: "100%", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "No tasks found. Create a new task to get started!" }) })) : (tasks.map((task, index) => ((0, jsx_runtime_1.jsxs)(ink_1.Box, { children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: index === selectedIndex ? 'green' : 'white', bold: true, children: [index === selectedIndex ? '▶ ' : ' ', task.title || 'Untitled Task'] }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginLeft: 2, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "ID: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "cyan", children: task.conversation_id }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | Status: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: getStatusColor(task.status), children: task.status }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | Created: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", children: formatDate(task.created_at) })] })] }, task.conversation_id)))) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [tasks.length > 0 ? '↑↓ Navigate • Enter Select • ' : '', "ESC Back \u2022 Q Quit"] }) })] })); } if (currentMode === 'suggested') { return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", flexGrow: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: loading ? ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading suggested tasks..." })) : error ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] })) : suggestedTasks.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "No suggested tasks available at the moment." })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [suggestedTasks.length, " suggested tasks found \u2022 Showing ", selectedIndex + 1, "/", suggestedTasks.length] }) }), (() => { const maxVisible = 20; const startIndex = Math.max(0, selectedIndex - Math.floor(maxVisible / 2)); const endIndex = Math.min(suggestedTasks.length, startIndex + maxVisible); const adjustedStartIndex = Math.max(0, endIndex - maxVisible); const visibleTasks = suggestedTasks.slice(adjustedStartIndex, endIndex); return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [adjustedStartIndex > 0 ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: ["\u2191 ", adjustedStartIndex, " more tasks above"] })) : null, visibleTasks.map((task, index) => { const actualIndex = adjustedStartIndex + index; return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: actualIndex === selectedIndex ? 'green' : 'white', bold: true, children: [actualIndex === selectedIndex ? '▶ ' : ' ', task.title] }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginLeft: 2, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Repository: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "cyan", children: task.repo }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | Provider: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", children: task.git_provider }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | Type: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: task.task_type }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | Issue #" }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "magenta", children: task.issue_number })] })] }, actualIndex)); }), endIndex < suggestedTasks.length ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: ["\u2193 ", suggestedTasks.length - endIndex, " more tasks below"] })) : null] })); })()] })) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [suggestedTasks.length > 0 ? `${selectedIndex + 1}/${suggestedTasks.length} • ↑↓ Navigate • Enter Select • ` : '', "ESC Back \u2022 Q Quit"] }) })] })); } if (currentMode === 'repositories') { return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", flexGrow: 1, children: [searchMode ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: ["Search: ", searchTerm, "\u2588"] }) })) : null, (0, jsx_runtime_1.jsx)(ink_1.Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: loading ? ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading repositories..." })) : error ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] })) : filteredRepos.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: searchTerm ? `No repositories found matching "${searchTerm}"` : 'No repositories found.' })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { marginBottom: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [filteredRepos.length, " repositories found \u2022 Showing ", selectedIndex + 1, "/", filteredRepos.length] }) }), (() => { const maxVisible = 20; const startIndex = Math.max(0, selectedIndex - Math.floor(maxVisible / 2)); const endIndex = Math.min(filteredRepos.length, startIndex + maxVisible); const adjustedStartIndex = Math.max(0, endIndex - maxVisible); const visibleRepos = filteredRepos.slice(adjustedStartIndex, endIndex); return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [adjustedStartIndex > 0 ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: ["\u2191 ", adjustedStartIndex, " more repositories above"] })) : null, visibleRepos.map((repo, index) => { const actualIndex = adjustedStartIndex + index; return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: actualIndex === selectedIndex ? 'green' : 'white', bold: true, children: [actualIndex === selectedIndex ? '▶ ' : ' ', repo.full_name, repo.stargazers_count && repo.stargazers_count > 0 ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: [" \u2605", repo.stargazers_count] })) : null] }), (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginLeft: 2, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Provider: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", children: repo.git_provider }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: repo.is_public ? 'green' : 'yellow', children: repo.is_public ? 'Public' : 'Private' })] })] }, repo.full_name)); }), endIndex < filteredRepos.length ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: ["\u2193 ", filteredRepos.length - endIndex, " more repositories below"] })) : null] })); })()] })) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [filteredRepos.length > 0 ? `${selectedIndex + 1}/${filteredRepos.length} • ↑↓ Navigate • Enter Select • ` : '', "S Search \u2022 ESC Back \u2022 Q Quit"] }) })] })); } if (currentMode === 'branches') { return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, paddingY: 1, children: loading ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { justifyContent: "center", alignItems: "center", height: "100%", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading branches..." }) })) : branches.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { justifyContent: "center", alignItems: "center", height: "100%", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "No branches found." }) })) : (branches.map((branch, index) => ((0, jsx_runtime_1.jsxs)(ink_1.Box, { children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: index === selectedIndex ? 'green' : 'white', bold: true, children: [index === selectedIndex ? '▶ ' : ' ', branch.name, branch.protected ? (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "red", children: " \uD83D\uDD12" }) : null] }), branch.last_push_date ? ((0, jsx_runtime_1.jsxs)(ink_1.Box, { marginLeft: 2, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Last push: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", children: new Date(branch.last_push_date).toLocaleDateString() })] })) : null] }, branch.name)))) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { borderStyle: "single", borderColor: "gray", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [branches.length > 0 ? '↑↓ Navigate • Enter Select • ' : '', "ESC Back \u2022 Q Quit"] }) })] })); } if (currentMode === 'create') { const renderCreateStep = () => { switch (createStep) { case 0: return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "Enter a title for your task:" }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { children: [createForm.title, "\u2588"] }) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Press Enter to continue" }) })] })); case 1: return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "Enter an initial message (optional):" }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, borderStyle: "single", borderColor: "blue", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { children: [createForm.message, "\u2588"] }) }), (0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Press Enter to continue (can be empty)" }) })] })); case 2: return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "Select a repository:" }), searchMode ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: ["Search: ", searchTerm || '', "\u2588"] }) })) : null, loading ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, justifyContent: "center", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading repositories..." }) })) : error ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] }) })) : ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", marginTop: 1, children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: selectedRepoIndex === -1 ? 'green' : 'white', bold: true, children: [selectedRepoIndex === -1 ? '▶ ' : ' ', "\u23ED\uFE0F Skip No Repository"] }) }), repositories.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "No repositories available." }) })) : ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (() => { const maxVisible = 19; const filteredRepos = searchTerm ? repositories.filter(repo => repo.full_name.toLowerCase().includes(searchTerm.toLowerCase())) : repositories; if (filteredRepos.length === 0) { return ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: searchTerm ? `No repositories found matching "${searchTerm}"` : 'No repositories available.' }) })); } const startIndex = Math.max(0, selectedRepoIndex - Math.floor(maxVisible / 2)); const endIndex = Math.min(filteredRepos.length, startIndex + maxVisible); const adjustedStartIndex = Math.max(0, endIndex - maxVisible); const visibleRepos = filteredRepos.slice(adjustedStartIndex, endIndex); return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, marginBottom: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", children: [filteredRepos.length, " repositories found \u2022 Showing ", selectedRepoIndex >= 0 ? `${selectedRepoIndex + 1}` : 'Skip', "/", filteredRepos.length + 1] }) }), adjustedStartIndex > 0 ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: ["\u2191 ", adjustedStartIndex, " more repositories above"] })) : null, visibleRepos.map((repo, index) => { const actualIndex = adjustedStartIndex + index; return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: actualIndex === selectedRepoIndex ? 'green' : 'white', bold: true, children: [actualIndex === selectedRepoIndex ? '▶ ' : ' ', repo.full_name || 'Unknown Repository'] }), repo.stargazers_count && repo.stargazers_count > 0 ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: [" \u2605", repo.stargazers_count] })) : null, (0, jsx_runtime_1.jsxs)(ink_1.Box, { marginLeft: 2, children: [(0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "Provider: " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "blue", children: repo.git_provider || 'Unknown' }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: " | " }), (0, jsx_runtime_1.jsx)(ink_1.Text, { color: repo.is_public ? 'green' : 'yellow', children: repo.is_public ? 'Public' : 'Private' })] })] }, repo.full_name || `repo-${index}`)); }), endIndex < filteredRepos.length ? ((0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "gray", dimColor: true, children: ["\u2193 ", filteredRepos.length - endIndex, " more repositories below"] })) : null] })); })() }))] }))] })); case 3: if (!createForm.repository || createForm.repository.trim() === '') { setCreateStep(4); return null; } return ((0, jsx_runtime_1.jsxs)(ink_1.Box, { flexDirection: "column", children: [(0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "yellow", children: ["Select a branch for ", createForm.repository, ":"] }), loading ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, justifyContent: "center", children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "yellow", children: "\u23F3 Loading branches..." }) })) : error ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsxs)(ink_1.Text, { color: "red", children: ["\u274C Error: ", error] }) })) : branches.length === 0 ? ((0, jsx_runtime_1.jsx)(ink_1.Box, { marginTop: 1, children: (0, jsx_runtime_1.jsx)(ink_1.Text, { color: "gray", children: "No branches found." }) })) : ((0, jsx_runtime_1.jsxs)(ink_1.Box