@every-env/cli
Version:
Multi-agent orchestrator for AI-powered development workflows
119 lines • 6.17 kB
JavaScript
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