@every-env/cli
Version:
Multi-agent orchestrator for AI-powered development workflows
135 lines • 5.01 kB
JavaScript
import { useInput } from 'ink';
import { useCallback } from 'react';
const phaseActions = {
1: { d: 'delegate', a: 'assess', e: 'edit', x: 'delete' },
2: { a: 'assess', l: 'logs', s: 'stop' },
3: { c: 'codify', d: 'delegate', v: 'view' },
4: { v: 'view', e: 'edit', p: 'publish' }
};
export function useKeyboardNavigation({ state, dispatch, onCreateTask, onExecuteAction }) {
const getCurrentPhaseTasks = useCallback(() => {
const phaseMap = {
1: 'plan',
2: 'delegate',
3: 'assess',
4: 'codify'
};
const phaseKey = phaseMap[state.currentPhase];
return state.tasks[phaseKey];
}, [state.currentPhase, state.tasks]);
const navigateUp = useCallback(() => {
const currentTasks = getCurrentPhaseTasks();
if (currentTasks.length === 0)
return;
if (state.selectedIndex === null || state.selectedIndex === 0) {
dispatch({ type: 'SET_SELECTED_INDEX', index: currentTasks.length - 1 });
}
else {
dispatch({ type: 'SET_SELECTED_INDEX', index: state.selectedIndex - 1 });
}
}, [getCurrentPhaseTasks, state.selectedIndex, dispatch]);
const navigateDown = useCallback(() => {
const currentTasks = getCurrentPhaseTasks();
if (currentTasks.length === 0)
return;
if (state.selectedIndex === null || state.selectedIndex === currentTasks.length - 1) {
dispatch({ type: 'SET_SELECTED_INDEX', index: 0 });
}
else {
dispatch({ type: 'SET_SELECTED_INDEX', index: state.selectedIndex + 1 });
}
}, [getCurrentPhaseTasks, state.selectedIndex, dispatch]);
const jumpToPhase = useCallback((phase) => {
dispatch({ type: 'SET_PHASE', phase });
}, [dispatch]);
const executeDefaultAction = useCallback(() => {
const actions = Object.values(phaseActions[state.currentPhase]);
if (actions.length > 0 && state.selectedIndex !== null) {
onExecuteAction(actions[0]);
}
}, [state.currentPhase, state.selectedIndex, onExecuteAction]);
const startTyping = useCallback((key) => {
dispatch({ type: 'SET_INPUT_MODE', mode: 'typing' });
dispatch({ type: 'SET_INPUT_VALUE', value: key });
}, [dispatch]);
const cancelTyping = useCallback(() => {
dispatch({ type: 'SET_INPUT_MODE', mode: 'idle' });
dispatch({ type: 'SET_INPUT_VALUE', value: '' });
}, [dispatch]);
const handleEscape = useCallback(() => {
if (state.showHelp) {
dispatch({ type: 'SET_SHOW_HELP', show: false });
}
else if (state.showLogs) {
dispatch({ type: 'SET_SHOW_LOGS', taskId: null });
}
else if (state.inputMode === 'typing') {
cancelTyping();
}
}, [state.showHelp, state.showLogs, state.inputMode, dispatch, cancelTyping]);
useInput((input, key) => {
// Handle typing mode differently
if (state.inputMode === 'typing') {
if (key.return) {
onCreateTask(state.inputValue);
cancelTyping();
}
else if (key.escape) {
cancelTyping();
}
else if (key.backspace || key.delete) {
dispatch({ type: 'SET_INPUT_VALUE', value: state.inputValue.slice(0, -1) });
}
else if (input) {
dispatch({ type: 'SET_INPUT_VALUE', value: state.inputValue + input });
}
return;
}
// Navigation keys
if (key.upArrow || input === 'k') {
navigateUp();
}
else if (key.downArrow || input === 'j') {
navigateDown();
}
else if (key.escape) {
handleEscape();
}
else if (key.return) {
executeDefaultAction();
}
// Phase jumping
else if (input === '1') {
jumpToPhase(1);
}
else if (input === '2') {
jumpToPhase(2);
}
else if (input === '3') {
jumpToPhase(3);
}
else if (input === '4') {
jumpToPhase(4);
}
// Help
else if (input === '?') {
dispatch({ type: 'SET_SHOW_HELP', show: true });
}
// Context-aware actions
else if (input && state.selectedIndex !== null) {
const actions = phaseActions[state.currentPhase];
if (actions[input]) {
onExecuteAction(actions[input]);
}
else if (/^[a-zA-Z0-9\s]$/.test(input)) {
// Start typing if it's an alphanumeric key
startTyping(input);
}
}
// Start typing for any alphanumeric key when no selection
else if (input && /^[a-zA-Z0-9\s]$/.test(input)) {
startTyping(input);
}
});
}
//# sourceMappingURL=useKeyboardNavigation.js.map