UNPKG

@every-env/cli

Version:

Multi-agent orchestrator for AI-powered development workflows

119 lines 6.17 kB
import React, { useReducer, useEffect, useCallback } from 'react'; import { Box } from 'ink'; import { v4 as uuidv4 } from 'uuid'; import { appReducer, initialState } from './state/reducer.js'; import { StatePersistence } from './state/persistence.js'; import { useKeyboardNavigation } from './hooks/useKeyboardNavigation.js'; import { InputBar } from './components/InputBar.js'; import { PhaseNav } from './components/PhaseNav.js'; import { TaskList } from './components/TaskList.js'; import { ActionBar } from './components/ActionBar.js'; import { CommandFeedback } from './components/CommandFeedback.js'; import { HelpView } from './components/HelpView.js'; import { LogsView } from './components/LogsView.js'; export function InteractiveApp() { const [state, dispatch] = useReducer(appReducer, initialState); const persistence = React.useRef(new StatePersistence()); // Load persisted state on mount useEffect(() => { persistence.current.loadState().then(savedState => { if (savedState) { dispatch({ type: 'LOAD_STATE', state: savedState }); } }).catch(error => { console.error('Failed to load persisted state:', error); }); }, []); // Save state on changes useEffect(() => { persistence.current.saveStateDebounced(state); }, [state]); const getCurrentPhaseTasks = useCallback(() => { const phaseMap = { 1: 'plan', 2: 'delegate', 3: 'assess', 4: 'codify' }; return state.tasks[phaseMap[state.currentPhase]]; }, [state.currentPhase, state.tasks]); const handleCreateTask = useCallback((title) => { const newTask = { id: uuidv4(), title, status: 'new', createdAt: new Date() }; dispatch({ type: 'ADD_TASK', phase: 'plan', task: newTask }); dispatch({ type: 'SET_SELECTED_INDEX', index: state.tasks.plan.length }); }, [state.tasks.plan.length]); const handleExecuteAction = useCallback((action) => { if (state.selectedIndex === null) return; const currentTasks = getCurrentPhaseTasks(); const task = currentTasks[state.selectedIndex]; if (!task) return; const phaseKey = ['plan', 'delegate', 'assess', 'codify'][state.currentPhase - 1]; switch (action) { case 'delegate': dispatch({ type: 'SET_COMMAND_FEEDBACK', message: `Delegating "${task.title}" to claude-code...` }); dispatch({ type: 'UPDATE_TASK', phase: phaseKey, taskId: task.id, updates: { status: 'active' } }); dispatch({ type: 'MOVE_TASK', fromPhase: phaseKey, toPhase: 'delegate', taskId: task.id }); setTimeout(() => { dispatch({ type: 'SET_COMMAND_FEEDBACK', message: null }); dispatch({ type: 'SET_PHASE', phase: 2 }); }, 2000); break; case 'assess': dispatch({ type: 'SET_COMMAND_FEEDBACK', message: `Moving "${task.title}" to assessment...` }); dispatch({ type: 'UPDATE_TASK', phase: phaseKey, taskId: task.id, updates: { status: 'in-review' } }); dispatch({ type: 'MOVE_TASK', fromPhase: phaseKey, toPhase: 'assess', taskId: task.id }); setTimeout(() => { dispatch({ type: 'SET_COMMAND_FEEDBACK', message: null }); dispatch({ type: 'SET_PHASE', phase: 3 }); }, 2000); break; case 'codify': dispatch({ type: 'SET_COMMAND_FEEDBACK', message: `Codifying "${task.title}" learnings...` }); dispatch({ type: 'UPDATE_TASK', phase: phaseKey, taskId: task.id, updates: { status: 'completed', patterns: Math.floor(Math.random() * 5) + 1 } }); dispatch({ type: 'MOVE_TASK', fromPhase: phaseKey, toPhase: 'codify', taskId: task.id }); setTimeout(() => { dispatch({ type: 'SET_COMMAND_FEEDBACK', message: null }); dispatch({ type: 'SET_PHASE', phase: 4 }); }, 2000); break; case 'delete': dispatch({ type: 'DELETE_TASK', phase: phaseKey, taskId: task.id }); break; case 'logs': dispatch({ type: 'SET_SHOW_LOGS', taskId: task.id }); break; // TODO: Implement other actions } }, [state.selectedIndex, state.currentPhase, getCurrentPhaseTasks]); useKeyboardNavigation({ state, dispatch, onCreateTask: handleCreateTask, onExecuteAction: handleExecuteAction }); const currentTasks = getCurrentPhaseTasks(); // Get the selected task for logs view const selectedTask = state.selectedIndex !== null ? currentTasks[state.selectedIndex] : null; return (React.createElement(Box, { flexDirection: "column", paddingX: 1 }, React.createElement(InputBar, { state: state }), React.createElement(Box, { marginY: 1 }, React.createElement(PhaseNav, { currentPhase: state.currentPhase })), state.commandFeedback && (React.createElement(CommandFeedback, { message: state.commandFeedback })), React.createElement(TaskList, { tasks: currentTasks, selectedIndex: state.selectedIndex, phase: state.currentPhase }), React.createElement(ActionBar, { currentPhase: state.currentPhase, hasSelection: state.selectedIndex !== null, hasTasks: currentTasks.length > 0 }), state.showHelp && (React.createElement(Box, { position: "absolute", marginTop: 2 }, React.createElement(HelpView, { onClose: () => dispatch({ type: 'SET_SHOW_HELP', show: false }) }))), state.showLogs && selectedTask && (React.createElement(Box, { position: "absolute", marginTop: 2 }, React.createElement(LogsView, { task: selectedTask, onClose: () => dispatch({ type: 'SET_SHOW_LOGS', taskId: null }) }))))); } //# sourceMappingURL=App.js.map