UNPKG

@every-env/cli

Version:

Multi-agent orchestrator for AI-powered development workflows

240 lines 11.7 kB
import React, { useState } from "react"; import { Box, Text, useInput } from "ink"; import SelectInput from "ink-select-input"; import { AVAILABLE_AGENTS, DEFAULT_RUNTIME_CONFIG } from "../../types/config.js"; import { getAvailableProjectTypes, getProjectTypeDisplayName, isAmbiguousDetection, getDetectedTypesFromAmbiguous, } from "../../utils/project-detect.js"; export function InitPrompts({ detectedProject, existingConfig, onComplete, onCancel }) { const [state, setState] = useState({ step: "welcome", defaultAgent: existingConfig?.defaultAgent || "claude", projectType: null, enabledAgents: [], agentConfigs: {}, currentAgentConfigIndex: 0, }); useInput((_input, key) => { if (key.escape) { onCancel(); } }); // Effect for auto-advancing from agentConfig to summary React.useEffect(() => { if (state.step === "agentConfig") { setState(prev => ({ ...prev, step: "summary" })); } }, [state.step]); // Effect for auto-exit after completion React.useEffect(() => { if (state.step === "complete") { const timer = setTimeout(() => { process.exit(0); }, 2000); // Show message for 2 seconds return () => clearTimeout(timer); } return undefined; }, [state.step]); const handleDefaultAgentSelect = (item) => { setState((prev) => ({ ...prev, defaultAgent: item.value, step: "projectType" })); }; const handleProjectTypeSelect = (item) => { setState((prev) => ({ ...prev, projectType: item.value, step: "additionalAgents" })); }; // const handleAdditionalAgentsSelect = (items: any[]) => { // const agentNames = items.map(item => item.value); // setState(prev => ({ // ...prev, // enabledAgents: agentNames, // step: agentNames.length > 0 ? 'agentConfig' : 'summary' // })); // }; const handleSummaryConfirm = () => { const agents = {}; const toPersisted = (agentName) => { const meta = AVAILABLE_AGENTS[agentName]; const out = {}; if (meta?.defaultCli) out.cli = meta.defaultCli; // Get default args from the DEFAULT_RUNTIME_CONFIG const defaultArgs = DEFAULT_RUNTIME_CONFIG.agents?.[agentName]?.args || []; out.args = defaultArgs; return out; }; // Persist default agent agents[state.defaultAgent] = toPersisted(state.defaultAgent); // Persist selected additional agents (enabledAgents may include default as first entry) for (const agentName of state.enabledAgents) { if (agentName !== state.defaultAgent && AVAILABLE_AGENTS[agentName]) { agents[agentName] = toPersisted(agentName); } } const config = { projectType: state.projectType, defaultAgent: state.defaultAgent, agents, signals: detectedProject.signals, }; onComplete(config); setState((prev) => ({ ...prev, step: "complete" })); }; if (state.step === "welcome") { return React.createElement(WelcomeStep, { onContinue: () => setState((prev) => ({ ...prev, step: "defaultAgent" })) }); } if (state.step === "defaultAgent") { const agentItems = Object.entries(AVAILABLE_AGENTS).map(([key, agent]) => ({ label: `${agent.displayName}${agent.description ? ` - ${agent.description}` : ""}`, value: key, })); return (React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, { bold: true }, "Select your default agent:"), React.createElement(Text, { color: "gray" }, "This will be used when no specific agent is chosen"), React.createElement(Box, { marginTop: 1 }, React.createElement(SelectInput, { items: agentItems, onSelect: handleDefaultAgentSelect })))); } if (state.step === "projectType") { const isAmbiguous = isAmbiguousDetection(detectedProject); const detectedTypes = isAmbiguous ? getDetectedTypesFromAmbiguous(detectedProject) : []; const projectItems = getAvailableProjectTypes().map((type) => ({ label: type.label, value: type.value, })); return (React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, { bold: true }, "Project type detected:"), isAmbiguous ? (React.createElement(Text, { color: "yellow" }, "Multiple project types detected: ", detectedTypes.map(getProjectTypeDisplayName).join(", "))) : (React.createElement(Text, { color: "green" }, getProjectTypeDisplayName(detectedProject.projectType))), React.createElement(Text, { color: "gray" }, "Signals: ", detectedProject.signals.join(", ")), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, null, "Confirm or override project type:"), React.createElement(SelectInput, { items: projectItems, onSelect: handleProjectTypeSelect })))); } if (state.step === "additionalAgents") { const agentItems = Object.entries(AVAILABLE_AGENTS) .filter(([name]) => name !== state.defaultAgent) .map(([key, agent]) => ({ label: `${agent.displayName}${agent.description ? ` - ${agent.description}` : ""}`, value: key, })); const preselected = Object.entries(existingConfig?.agents || {}) .filter(([name]) => name !== state.defaultAgent) .map(([name]) => name); return (React.createElement(AgentMultiSelect, { items: agentItems, initialSelected: preselected, onSubmit: (selected) => { setState((prev) => ({ ...prev, enabledAgents: [prev.defaultAgent, ...selected], agentConfigs: {}, step: "summary", })); } })); } // Skip agent config step - this should never be reached now if (state.step === "agentConfig") { return React.createElement(Text, null, "Loading..."); } if (state.step === "summary") { return (React.createElement(SummaryStep, { state: state, detectedProject: detectedProject, onConfirm: handleSummaryConfirm, onBack: () => setState((prev) => ({ ...prev, step: "additionalAgents" })) })); } if (state.step === "complete") { return (React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, { color: "green", bold: true }, "\u2713 Configuration saved successfully!"), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, null, "You can now use `every` commands with your configured agents.")), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: "gray" }, "To customize agent settings, edit .every-env/config.json:"), React.createElement(Box, { marginLeft: 2 }, React.createElement(Text, { color: "gray" }, "\u2022 cli: Command to execute"), React.createElement(Text, { color: "gray" }, "\u2022 args: CLI arguments (e.g., --dangerously-skip-permissions)"))))); } return React.createElement(Text, null, "Unknown step"); } function WelcomeStep({ onContinue }) { useInput((input) => { if (input === "\r") { onContinue(); } }); return (React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, { bold: true, color: "blue" }, "Welcome to every-env!"), React.createElement(Text, null, "This will set up agent configuration for your project."), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: "gray" }, "Press Enter to continue, Esc to cancel")))); } function AgentMultiSelect({ items, initialSelected, onSubmit, }) { const [cursor, setCursor] = useState(0); const [selected, setSelected] = useState(new Set(initialSelected || [])); useInput((input, key) => { if (key.upArrow) setCursor((c) => (c + items.length - 1) % items.length); if (key.downArrow) setCursor((c) => (c + 1) % items.length); if (input === " ") { const val = items[cursor]?.value; if (val) { setSelected((prev) => { const next = new Set(prev); if (next.has(val)) next.delete(val); else next.add(val); return next; }); } } if (key.return) { onSubmit(Array.from(selected)); } }); return (React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, { bold: true }, "Select additional agents"), React.createElement(Text, { color: "gray" }, "Use \u2191/\u2193 to move, space to toggle, enter to confirm"), React.createElement(Box, { flexDirection: "column", marginTop: 1 }, items.map((item, idx) => { const isActive = idx === cursor; const isSel = selected.has(item.value); return (React.createElement(Text, { key: item.value, color: isActive ? "cyan" : undefined }, isActive ? ">" : " ", " [", isSel ? "x" : " ", "] ", item.label)); })))); } function SummaryStep({ state, detectedProject, onConfirm, onBack }) { const actionItems = [ { label: "Confirm and save configuration", value: "confirm" }, { label: "Go back to modify settings", value: "back" }, ]; const handleActionSelect = (item) => { if (item.value === "confirm") { onConfirm(); } else { onBack(); } }; return (React.createElement(Box, { flexDirection: "column" }, React.createElement(Text, { bold: true }, "Configuration Summary:"), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, null, "Project Type:", " ", React.createElement(Text, { color: "green" }, getProjectTypeDisplayName(state.projectType ?? detectedProject.projectType))), React.createElement(Text, null, "Default Agent: ", React.createElement(Text, { color: "blue" }, AVAILABLE_AGENTS[state.defaultAgent].displayName)), React.createElement(Text, null, "Additional Agents:", " ", state.enabledAgents.length === 0 ? "None" : state.enabledAgents.map((name) => AVAILABLE_AGENTS[name].displayName).join(", ")), React.createElement(Text, null, "Detection Signals: ", React.createElement(Text, { color: "gray" }, detectedProject.signals.join(", ")))), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: "gray" }, "Agents will be configured with default settings. You can customize them later in:"), React.createElement(Text, { color: "cyan" }, ".every-env/config.json")), React.createElement(Box, { marginTop: 2 }, React.createElement(SelectInput, { items: actionItems, onSelect: handleActionSelect })))); } //# sourceMappingURL=InitPrompts.js.map