@graphteon/juricode
Version:
We are forging the future with lines of digital steel
806 lines • 55.3 kB
JavaScript
"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