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