更新大量 tsx 原始文件; 已经迁移 login panel; 部分 (#121)

* style(B1-1): 格式化 ink/buddy/cli/context/screens/tasks/services/keybindings/state (43 files)

纯格式化:移除分号、React Compiler import、import 多行展开。
修复了 Box.tsx 和 ScrollBox.tsx 中无效的 global.d.ts import。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-2): 格式化 commands (79 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-3): 格式化 components/messages,permissions,mcp,sandbox,shell (104 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-4): 格式化 components/PromptInput,FeedbackSurvey,tasks,agents,skills,design-system,wizard (73 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-5): 格式化 components其余 + hooks + tools (232 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-6): 格式化 main/entrypoints/utils/moreright (21 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 更新 README,新增 Run.ps1/TODO.md,删除 V6.md

- README.md: 大幅重写,更详细版本历史和配置示例
- Run.ps1: 新增 Windows 启动脚本
- TODO.md: 新增包完成清单
- V6.md: 删除(架构重构规划已不适用)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: 修复以前的问题

* fix: 修复 login 面板的问题

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-04-04 23:24:27 +08:00
committed by GitHub
parent 02694918b5
commit 5b1a52b8e0
559 changed files with 103807 additions and 101817 deletions

View File

@@ -1,219 +1,148 @@
import { c as _c } from "react/compiler-runtime";
import figures from 'figures';
import * as React from 'react';
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js';
import { Box, Text } from '../../ink.js';
import { useKeybinding } from '../../keybindings/useKeybinding.js';
import type { Tools } from '../../Tool.js';
import { getAgentColor } from '../../tools/AgentTool/agentColorManager.js';
import { getMemoryScopeDisplay } from '../../tools/AgentTool/agentMemory.js';
import { resolveAgentTools } from '../../tools/AgentTool/agentToolUtils.js';
import { type AgentDefinition, isBuiltInAgent } from '../../tools/AgentTool/loadAgentsDir.js';
import { getAgentModelDisplay } from '../../utils/model/agent.js';
import { Markdown } from '../Markdown.js';
import { getActualRelativeAgentFilePath } from './agentFileUtils.js';
import figures from 'figures'
import * as React from 'react'
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js'
import { Box, Text } from '../../ink.js'
import { useKeybinding } from '../../keybindings/useKeybinding.js'
import type { Tools } from '../../Tool.js'
import { getAgentColor } from '../../tools/AgentTool/agentColorManager.js'
import { getMemoryScopeDisplay } from '../../tools/AgentTool/agentMemory.js'
import { resolveAgentTools } from '../../tools/AgentTool/agentToolUtils.js'
import {
type AgentDefinition,
isBuiltInAgent,
} from '../../tools/AgentTool/loadAgentsDir.js'
import { getAgentModelDisplay } from '../../utils/model/agent.js'
import { Markdown } from '../Markdown.js'
import { getActualRelativeAgentFilePath } from './agentFileUtils.js'
type Props = {
agent: AgentDefinition;
tools: Tools;
allAgents?: AgentDefinition[];
onBack: () => void;
};
export function AgentDetail(t0) {
const $ = _c(48);
const {
agent,
tools,
onBack
} = t0;
const resolvedTools = resolveAgentTools(agent, tools, false);
let t1;
if ($[0] !== agent) {
t1 = getActualRelativeAgentFilePath(agent);
$[0] = agent;
$[1] = t1;
} else {
t1 = $[1];
}
const filePath = t1;
let t2;
if ($[2] !== agent.agentType) {
t2 = getAgentColor(agent.agentType);
$[2] = agent.agentType;
$[3] = t2;
} else {
t2 = $[3];
}
const backgroundColor = t2;
let t3;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t3 = {
context: "Confirmation"
};
$[4] = t3;
} else {
t3 = $[4];
}
useKeybinding("confirm:no", onBack, t3);
let t4;
if ($[5] !== onBack) {
t4 = e => {
if (e.key === "return") {
e.preventDefault();
onBack();
}
};
$[5] = onBack;
$[6] = t4;
} else {
t4 = $[6];
}
const handleKeyDown = t4;
const renderToolsList = function renderToolsList() {
if (resolvedTools.hasWildcard) {
return <Text>All tools</Text>;
}
if (!agent.tools || agent.tools.length === 0) {
return <Text>None</Text>;
}
return <>{resolvedTools.validTools.length > 0 && <Text>{resolvedTools.validTools.join(", ")}</Text>}{resolvedTools.invalidTools.length > 0 && <Text color="warning">{figures.warning} Unrecognized:{" "}{resolvedTools.invalidTools.join(", ")}</Text>}</>;
};
const T0 = Box;
const t5 = "column";
const t6 = 1;
const t7 = 0;
const t8 = true;
let t9;
if ($[7] !== filePath) {
t9 = <Text dimColor={true}>{filePath}</Text>;
$[7] = filePath;
$[8] = t9;
} else {
t9 = $[8];
}
let t10;
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
t10 = <Text><Text bold={true}>Description</Text> (tells Claude when to use this agent):</Text>;
$[9] = t10;
} else {
t10 = $[9];
}
let t11;
if ($[10] !== agent.whenToUse) {
t11 = <Box flexDirection="column">{t10}<Box marginLeft={2}><Text>{agent.whenToUse}</Text></Box></Box>;
$[10] = agent.whenToUse;
$[11] = t11;
} else {
t11 = $[11];
}
const T1 = Box;
let t12;
if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
t12 = <Text><Text bold={true}>Tools</Text>:{" "}</Text>;
$[12] = t12;
} else {
t12 = $[12];
}
const t13 = renderToolsList();
let t14;
if ($[13] !== T1 || $[14] !== t12 || $[15] !== t13) {
t14 = <T1>{t12}{t13}</T1>;
$[13] = T1;
$[14] = t12;
$[15] = t13;
$[16] = t14;
} else {
t14 = $[16];
}
let t15;
if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
t15 = <Text bold={true}>Model</Text>;
$[17] = t15;
} else {
t15 = $[17];
}
let t16;
if ($[18] !== agent.model) {
t16 = getAgentModelDisplay(agent.model);
$[18] = agent.model;
$[19] = t16;
} else {
t16 = $[19];
}
let t17;
if ($[20] !== t16) {
t17 = <Text>{t15}: {t16}</Text>;
$[20] = t16;
$[21] = t17;
} else {
t17 = $[21];
}
let t18;
if ($[22] !== agent.permissionMode) {
t18 = agent.permissionMode && <Text><Text bold={true}>Permission mode</Text>: {agent.permissionMode}</Text>;
$[22] = agent.permissionMode;
$[23] = t18;
} else {
t18 = $[23];
}
let t19;
if ($[24] !== agent.memory) {
t19 = agent.memory && <Text><Text bold={true}>Memory</Text>: {getMemoryScopeDisplay(agent.memory)}</Text>;
$[24] = agent.memory;
$[25] = t19;
} else {
t19 = $[25];
}
let t20;
if ($[26] !== agent.hooks) {
t20 = agent.hooks && Object.keys(agent.hooks).length > 0 && <Text><Text bold={true}>Hooks</Text>: {Object.keys(agent.hooks).join(", ")}</Text>;
$[26] = agent.hooks;
$[27] = t20;
} else {
t20 = $[27];
}
let t21;
if ($[28] !== agent.skills) {
t21 = agent.skills && agent.skills.length > 0 && <Text><Text bold={true}>Skills</Text>:{" "}{agent.skills.length > 10 ? `${agent.skills.length} skills` : agent.skills.join(", ")}</Text>;
$[28] = agent.skills;
$[29] = t21;
} else {
t21 = $[29];
}
let t22;
if ($[30] !== agent.agentType || $[31] !== backgroundColor) {
t22 = backgroundColor && <Box><Text><Text bold={true}>Color</Text>:{" "}<Text backgroundColor={backgroundColor} color="inverseText">{" "}{agent.agentType}{" "}</Text></Text></Box>;
$[30] = agent.agentType;
$[31] = backgroundColor;
$[32] = t22;
} else {
t22 = $[32];
}
let t23;
if ($[33] !== agent) {
t23 = !isBuiltInAgent(agent) && <><Box><Text><Text bold={true}>System prompt</Text>:</Text></Box><Box marginLeft={2} marginRight={2}><Markdown>{agent.getSystemPrompt()}</Markdown></Box></>;
$[33] = agent;
$[34] = t23;
} else {
t23 = $[34];
}
let t24;
if ($[35] !== T0 || $[36] !== handleKeyDown || $[37] !== t11 || $[38] !== t14 || $[39] !== t17 || $[40] !== t18 || $[41] !== t19 || $[42] !== t20 || $[43] !== t21 || $[44] !== t22 || $[45] !== t23 || $[46] !== t9) {
t24 = <T0 flexDirection={t5} gap={t6} tabIndex={t7} autoFocus={t8} onKeyDown={handleKeyDown}>{t9}{t11}{t14}{t17}{t18}{t19}{t20}{t21}{t22}{t23}</T0>;
$[35] = T0;
$[36] = handleKeyDown;
$[37] = t11;
$[38] = t14;
$[39] = t17;
$[40] = t18;
$[41] = t19;
$[42] = t20;
$[43] = t21;
$[44] = t22;
$[45] = t23;
$[46] = t9;
$[47] = t24;
} else {
t24 = $[47];
}
return t24;
agent: AgentDefinition
tools: Tools
allAgents?: AgentDefinition[]
onBack: () => void
}
export function AgentDetail({ agent, tools, onBack }: Props): React.ReactNode {
const resolvedTools = resolveAgentTools(agent, tools, false)
const filePath = getActualRelativeAgentFilePath(agent)
const backgroundColor = getAgentColor(agent.agentType)
// Handle Esc to go back
useKeybinding('confirm:no', onBack, { context: 'Confirmation' })
// Handle Enter to go back
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'return') {
e.preventDefault()
onBack()
}
}
function renderToolsList(): React.ReactNode {
if (resolvedTools.hasWildcard) {
return <Text>All tools</Text>
}
if (!agent.tools || agent.tools.length === 0) {
return <Text>None</Text>
}
return (
<>
{resolvedTools.validTools.length > 0 && (
<Text>{resolvedTools.validTools.join(', ')}</Text>
)}
{resolvedTools.invalidTools.length > 0 && (
<Text color="warning">
{figures.warning} Unrecognized:{' '}
{resolvedTools.invalidTools.join(', ')}
</Text>
)}
</>
)
}
return (
<Box
flexDirection="column"
gap={1}
tabIndex={0}
autoFocus
onKeyDown={handleKeyDown}
>
<Text dimColor>{filePath}</Text>
<Box flexDirection="column">
<Text>
<Text bold>Description</Text> (tells Claude when to use this agent):
</Text>
<Box marginLeft={2}>
<Text>{agent.whenToUse}</Text>
</Box>
</Box>
<Box>
<Text>
<Text bold>Tools</Text>:{' '}
</Text>
{renderToolsList()}
</Box>
<Text>
<Text bold>Model</Text>: {getAgentModelDisplay(agent.model)}
</Text>
{agent.permissionMode && (
<Text>
<Text bold>Permission mode</Text>: {agent.permissionMode}
</Text>
)}
{agent.memory && (
<Text>
<Text bold>Memory</Text>: {getMemoryScopeDisplay(agent.memory)}
</Text>
)}
{agent.hooks && Object.keys(agent.hooks).length > 0 && (
<Text>
<Text bold>Hooks</Text>: {Object.keys(agent.hooks).join(', ')}
</Text>
)}
{agent.skills && agent.skills.length > 0 && (
<Text>
<Text bold>Skills</Text>:{' '}
{agent.skills.length > 10
? `${agent.skills.length} skills`
: agent.skills.join(', ')}
</Text>
)}
{backgroundColor && (
<Box>
<Text>
<Text bold>Color</Text>:{' '}
<Text backgroundColor={backgroundColor} color="inverseText">
{' '}
{agent.agentType}{' '}
</Text>
</Text>
</Box>
)}
{!isBuiltInAgent(agent) && (
<>
<Box>
<Text>
<Text bold>System prompt</Text>:
</Text>
</Box>
<Box marginLeft={2} marginRight={2}>
<Markdown>{agent.getSystemPrompt()}</Markdown>
</Box>
</>
)}
</Box>
)
}

View File

@@ -1,177 +1,246 @@
import chalk from 'chalk';
import figures from 'figures';
import * as React from 'react';
import { useCallback, useMemo, useState } from 'react';
import { useSetAppState } from 'src/state/AppState.js';
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js';
import { Box, Text } from '../../ink.js';
import { useKeybinding } from '../../keybindings/useKeybinding.js';
import type { Tools } from '../../Tool.js';
import { type AgentColorName, setAgentColor } from '../../tools/AgentTool/agentColorManager.js';
import { type AgentDefinition, getActiveAgentsFromList, isCustomAgent, isPluginAgent } from '../../tools/AgentTool/loadAgentsDir.js';
import { editFileInEditor } from '../../utils/promptEditor.js';
import { getActualAgentFilePath, updateAgentFile } from './agentFileUtils.js';
import { ColorPicker } from './ColorPicker.js';
import { ModelSelector } from './ModelSelector.js';
import { ToolSelector } from './ToolSelector.js';
import { getAgentSourceDisplayName } from './utils.js';
import chalk from 'chalk'
import figures from 'figures'
import * as React from 'react'
import { useCallback, useMemo, useState } from 'react'
import { useSetAppState } from 'src/state/AppState.js'
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js'
import { Box, Text } from '../../ink.js'
import { useKeybinding } from '../../keybindings/useKeybinding.js'
import type { Tools } from '../../Tool.js'
import {
type AgentColorName,
setAgentColor,
} from '../../tools/AgentTool/agentColorManager.js'
import {
type AgentDefinition,
getActiveAgentsFromList,
isCustomAgent,
isPluginAgent,
} from '../../tools/AgentTool/loadAgentsDir.js'
import { editFileInEditor } from '../../utils/promptEditor.js'
import { getActualAgentFilePath, updateAgentFile } from './agentFileUtils.js'
import { ColorPicker } from './ColorPicker.js'
import { ModelSelector } from './ModelSelector.js'
import { ToolSelector } from './ToolSelector.js'
import { getAgentSourceDisplayName } from './utils.js'
type Props = {
agent: AgentDefinition;
tools: Tools;
onSaved: (message: string) => void;
onBack: () => void;
};
type EditMode = 'menu' | 'edit-tools' | 'edit-color' | 'edit-model';
agent: AgentDefinition
tools: Tools
onSaved: (message: string) => void
onBack: () => void
}
type EditMode = 'menu' | 'edit-tools' | 'edit-color' | 'edit-model'
type SaveChanges = {
tools?: string[];
color?: AgentColorName;
model?: string;
};
tools?: string[]
color?: AgentColorName
model?: string
}
export function AgentEditor({
agent,
tools,
onSaved,
onBack
onBack,
}: Props): React.ReactNode {
const setAppState = useSetAppState();
const [editMode, setEditMode] = useState<EditMode>('menu');
const [selectedMenuIndex, setSelectedMenuIndex] = useState(0);
const [error, setError] = useState<string | null>(null);
const [selectedColor, setSelectedColor] = useState<AgentColorName | undefined>(agent.color as AgentColorName | undefined);
const setAppState = useSetAppState()
const [editMode, setEditMode] = useState<EditMode>('menu')
const [selectedMenuIndex, setSelectedMenuIndex] = useState(0)
const [error, setError] = useState<string | null>(null)
const [selectedColor, setSelectedColor] = useState<
AgentColorName | undefined
>(agent.color as AgentColorName | undefined)
const handleOpenInEditor = useCallback(async () => {
const filePath = getActualAgentFilePath(agent);
const result = await editFileInEditor(filePath);
const filePath = getActualAgentFilePath(agent)
const result = await editFileInEditor(filePath)
if (result.error) {
setError(result.error);
setError(result.error)
} else {
onSaved(`Opened ${agent.agentType} in editor. If you made edits, restart to load the latest version.`);
onSaved(
`Opened ${agent.agentType} in editor. If you made edits, restart to load the latest version.`,
)
}
}, [agent, onSaved]);
const handleSave = useCallback(async (changes: SaveChanges = {}) => {
const {
tools: newTools,
color: newColor,
model: newModel
} = changes;
const finalColor = newColor ?? selectedColor;
const hasToolsChanged = newTools !== undefined;
const hasModelChanged = newModel !== undefined;
const hasColorChanged = finalColor !== agent.color;
if (!hasToolsChanged && !hasModelChanged && !hasColorChanged) {
return false;
}
try {
// Only custom/plugin agents can be edited
// this is for type safety; the UI shouldn't allow editing otherwise
if (!isCustomAgent(agent) && !isPluginAgent(agent)) {
return false;
}, [agent, onSaved])
const handleSave = useCallback(
async (changes: SaveChanges = {}) => {
const { tools: newTools, color: newColor, model: newModel } = changes
const finalColor = newColor ?? selectedColor
const hasToolsChanged = newTools !== undefined
const hasModelChanged = newModel !== undefined
const hasColorChanged = finalColor !== agent.color
if (!hasToolsChanged && !hasModelChanged && !hasColorChanged) {
return false
}
await updateAgentFile(agent, agent.whenToUse, newTools ?? agent.tools, agent.getSystemPrompt(), finalColor, newModel ?? agent.model);
if (hasColorChanged && finalColor) {
setAgentColor(agent.agentType, finalColor);
}
setAppState(state => {
const allAgents = state.agentDefinitions.allAgents.map(a => a.agentType === agent.agentType ? {
...a,
tools: newTools ?? a.tools,
color: finalColor,
model: newModel ?? a.model
} : a);
return {
...state,
agentDefinitions: {
...state.agentDefinitions,
activeAgents: getActiveAgentsFromList(allAgents),
allAgents
try {
// Only custom/plugin agents can be edited
// this is for type safety; the UI shouldn't allow editing otherwise
if (!isCustomAgent(agent) && !isPluginAgent(agent)) {
return false
}
await updateAgentFile(
agent,
agent.whenToUse,
newTools ?? agent.tools,
agent.getSystemPrompt(),
finalColor,
newModel ?? agent.model,
)
if (hasColorChanged && finalColor) {
setAgentColor(agent.agentType, finalColor)
}
setAppState(state => {
const allAgents = state.agentDefinitions.allAgents.map(a =>
a.agentType === agent.agentType
? {
...a,
tools: newTools ?? a.tools,
color: finalColor,
model: newModel ?? a.model,
}
: a,
)
return {
...state,
agentDefinitions: {
...state.agentDefinitions,
activeAgents: getActiveAgentsFromList(allAgents),
allAgents,
},
}
};
});
onSaved(`Updated agent: ${chalk.bold(agent.agentType)}`);
return true;
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to save agent');
return false;
}
}, [agent, selectedColor, onSaved, setAppState]);
const menuItems = useMemo(() => [{
label: 'Open in editor',
action: handleOpenInEditor
}, {
label: 'Edit tools',
action: () => setEditMode('edit-tools')
}, {
label: 'Edit model',
action: () => setEditMode('edit-model')
}, {
label: 'Edit color',
action: () => setEditMode('edit-color')
}], [handleOpenInEditor]);
const handleEscape = useCallback(() => {
setError(null);
if (editMode === 'menu') {
onBack();
} else {
setEditMode('menu');
}
}, [editMode, onBack]);
const handleMenuKeyDown = useCallback((e: KeyboardEvent) => {
if (e.key === 'up') {
e.preventDefault();
setSelectedMenuIndex(index => Math.max(0, index - 1));
} else if (e.key === 'down') {
e.preventDefault();
setSelectedMenuIndex(index_0 => Math.min(menuItems.length - 1, index_0 + 1));
} else if (e.key === 'return') {
e.preventDefault();
const selectedItem = menuItems[selectedMenuIndex];
if (selectedItem) {
void selectedItem.action();
})
onSaved(`Updated agent: ${chalk.bold(agent.agentType)}`)
return true
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to save agent')
return false
}
},
[agent, selectedColor, onSaved, setAppState],
)
const menuItems = useMemo(
() => [
{ label: 'Open in editor', action: handleOpenInEditor },
{ label: 'Edit tools', action: () => setEditMode('edit-tools') },
{ label: 'Edit model', action: () => setEditMode('edit-model') },
{ label: 'Edit color', action: () => setEditMode('edit-color') },
],
[handleOpenInEditor],
)
const handleEscape = useCallback(() => {
setError(null)
if (editMode === 'menu') {
onBack()
} else {
setEditMode('menu')
}
}, [menuItems, selectedMenuIndex]);
useKeybinding('confirm:no', handleEscape, {
context: 'Confirmation'
});
const renderMenu = (): React.ReactNode => <Box flexDirection="column" tabIndex={0} autoFocus onKeyDown={handleMenuKeyDown}>
}, [editMode, onBack])
const handleMenuKeyDown = useCallback(
(e: KeyboardEvent) => {
if (e.key === 'up') {
e.preventDefault()
setSelectedMenuIndex(index => Math.max(0, index - 1))
} else if (e.key === 'down') {
e.preventDefault()
setSelectedMenuIndex(index => Math.min(menuItems.length - 1, index + 1))
} else if (e.key === 'return') {
e.preventDefault()
const selectedItem = menuItems[selectedMenuIndex]
if (selectedItem) {
void selectedItem.action()
}
}
},
[menuItems, selectedMenuIndex],
)
useKeybinding('confirm:no', handleEscape, { context: 'Confirmation' })
const renderMenu = (): React.ReactNode => (
<Box
flexDirection="column"
tabIndex={0}
autoFocus
onKeyDown={handleMenuKeyDown}
>
<Text dimColor>Source: {getAgentSourceDisplayName(agent.source)}</Text>
<Box marginTop={1} flexDirection="column">
{menuItems.map((item, index_1) => <Text key={item.label} color={index_1 === selectedMenuIndex ? 'suggestion' : undefined}>
{index_1 === selectedMenuIndex ? `${figures.pointer} ` : ' '}
{menuItems.map((item, index) => (
<Text
key={item.label}
color={index === selectedMenuIndex ? 'suggestion' : undefined}
>
{index === selectedMenuIndex ? `${figures.pointer} ` : ' '}
{item.label}
</Text>)}
</Text>
))}
</Box>
{error && <Box marginTop={1}>
{error && (
<Box marginTop={1}>
<Text color="error">{error}</Text>
</Box>}
</Box>;
</Box>
)}
</Box>
)
switch (editMode) {
case 'menu':
return renderMenu();
return renderMenu()
case 'edit-tools':
return <ToolSelector tools={tools} initialTools={agent.tools} onComplete={async finalTools => {
setEditMode('menu');
await handleSave({
tools: finalTools
});
}} />;
return (
<ToolSelector
tools={tools}
initialTools={agent.tools}
onComplete={async finalTools => {
setEditMode('menu')
await handleSave({ tools: finalTools })
}}
/>
)
case 'edit-color':
return <ColorPicker agentName={agent.agentType} currentColor={selectedColor || agent.color as AgentColorName || 'automatic'} onConfirm={async color => {
setSelectedColor(color);
setEditMode('menu');
await handleSave({
color
});
}} />;
return (
<ColorPicker
agentName={agent.agentType}
currentColor={
selectedColor || (agent.color as AgentColorName) || 'automatic'
}
onConfirm={async color => {
setSelectedColor(color)
setEditMode('menu')
await handleSave({ color })
}}
/>
)
case 'edit-model':
return <ModelSelector initialModel={agent.model} onComplete={async model => {
setEditMode('menu');
await handleSave({
model
});
}} />;
return (
<ModelSelector
initialModel={agent.model}
onComplete={async model => {
setEditMode('menu')
await handleSave({ model })
}}
/>
)
default:
return null;
return null
}
}

View File

@@ -1,25 +1,23 @@
import { c as _c } from "react/compiler-runtime";
import * as React from 'react';
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js';
import { Box, Text } from '../../ink.js';
import * as React from 'react'
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js'
import { Box, Text } from '../../ink.js'
type Props = {
instructions?: string;
};
export function AgentNavigationFooter(t0) {
const $ = _c(2);
const {
instructions: t1
} = t0;
const instructions = t1 === undefined ? "Press \u2191\u2193 to navigate \xB7 Enter to select \xB7 Esc to go back" : t1;
const exitState = useExitOnCtrlCDWithKeybindings();
const t2 = exitState.pending ? `Press ${exitState.keyName} again to exit` : instructions;
let t3;
if ($[0] !== t2) {
t3 = <Box marginLeft={2}><Text dimColor={true}>{t2}</Text></Box>;
$[0] = t2;
$[1] = t3;
} else {
t3 = $[1];
}
return t3;
instructions?: string
}
export function AgentNavigationFooter({
instructions = 'Press ↑↓ to navigate · Enter to select · Esc to go back',
}: Props): React.ReactNode {
const exitState = useExitOnCtrlCDWithKeybindings()
return (
<Box marginLeft={2}>
<Text dimColor>
{exitState.pending
? `Press ${exitState.keyName} again to exit`
: instructions}
</Text>
</Box>
)
}

View File

@@ -1,439 +1,342 @@
import { c as _c } from "react/compiler-runtime";
import figures from 'figures';
import * as React from 'react';
import type { SettingSource } from 'src/utils/settings/constants.js';
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js';
import { Box, Text } from '../../ink.js';
import type { ResolvedAgent } from '../../tools/AgentTool/agentDisplay.js';
import { AGENT_SOURCE_GROUPS, compareAgentsByName, getOverrideSourceLabel, resolveAgentModelDisplay } from '../../tools/AgentTool/agentDisplay.js';
import type { AgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js';
import { count } from '../../utils/array.js';
import { Dialog } from '../design-system/Dialog.js';
import { Divider } from '../design-system/Divider.js';
import { getAgentSourceDisplayName } from './utils.js';
import figures from 'figures'
import * as React from 'react'
import type { SettingSource } from 'src/utils/settings/constants.js'
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js'
import { Box, Text } from '../../ink.js'
import type { ResolvedAgent } from '../../tools/AgentTool/agentDisplay.js'
import {
AGENT_SOURCE_GROUPS,
compareAgentsByName,
getOverrideSourceLabel,
resolveAgentModelDisplay,
} from '../../tools/AgentTool/agentDisplay.js'
import type { AgentDefinition } from '../../tools/AgentTool/loadAgentsDir.js'
import { count } from '../../utils/array.js'
import { Dialog } from '../design-system/Dialog.js'
import { Divider } from '../design-system/Divider.js'
import { getAgentSourceDisplayName } from './utils.js'
type Props = {
source: SettingSource | 'all' | 'built-in' | 'plugin';
agents: ResolvedAgent[];
onBack: () => void;
onSelect: (agent: AgentDefinition) => void;
onCreateNew?: () => void;
changes?: string[];
};
export function AgentsList(t0) {
const $ = _c(96);
const {
source,
agents,
onBack,
onSelect,
onCreateNew,
changes
} = t0;
const [selectedAgent, setSelectedAgent] = React.useState(null);
const [isCreateNewSelected, setIsCreateNewSelected] = React.useState(true);
let t1;
if ($[0] !== agents) {
t1 = [...agents].sort(compareAgentsByName);
$[0] = agents;
$[1] = t1;
} else {
t1 = $[1];
}
const sortedAgents = t1;
const getOverrideInfo = _temp;
let t2;
if ($[2] !== isCreateNewSelected) {
t2 = () => <Box><Text color={isCreateNewSelected ? "suggestion" : undefined}>{isCreateNewSelected ? `${figures.pointer} ` : " "}</Text><Text color={isCreateNewSelected ? "suggestion" : undefined}>Create new agent</Text></Box>;
$[2] = isCreateNewSelected;
$[3] = t2;
} else {
t2 = $[3];
}
const renderCreateNewOption = t2;
let t3;
if ($[4] !== isCreateNewSelected || $[5] !== selectedAgent?.agentType || $[6] !== selectedAgent?.source) {
t3 = agent_0 => {
const isBuiltIn = agent_0.source === "built-in";
const isSelected = !isBuiltIn && !isCreateNewSelected && selectedAgent?.agentType === agent_0.agentType && selectedAgent?.source === agent_0.source;
const {
isOverridden,
overriddenBy
} = getOverrideInfo(agent_0);
const dimmed = isBuiltIn || isOverridden;
const textColor = !isBuiltIn && isSelected ? "suggestion" : undefined;
const resolvedModel = resolveAgentModelDisplay(agent_0);
return <Box key={`${agent_0.agentType}-${agent_0.source}`}><Text dimColor={dimmed && !isSelected} color={textColor}>{isBuiltIn ? "" : isSelected ? `${figures.pointer} ` : " "}</Text><Text dimColor={dimmed && !isSelected} color={textColor}>{agent_0.agentType}</Text>{resolvedModel && <Text dimColor={true} color={textColor}>{" \xB7 "}{resolvedModel}</Text>}{agent_0.memory && <Text dimColor={true} color={textColor}>{" \xB7 "}{agent_0.memory} memory</Text>}{overriddenBy && <Text dimColor={!isSelected} color={isSelected ? "warning" : undefined}>{" "}{figures.warning} shadowed by {getOverrideSourceLabel(overriddenBy)}</Text>}</Box>;
};
$[4] = isCreateNewSelected;
$[5] = selectedAgent?.agentType;
$[6] = selectedAgent?.source;
$[7] = t3;
} else {
t3 = $[7];
}
const renderAgent = t3;
let t4;
if ($[8] !== sortedAgents || $[9] !== source) {
bb0: {
const nonBuiltIn = sortedAgents.filter(_temp2);
if (source === "all") {
t4 = AGENT_SOURCE_GROUPS.filter(_temp3).flatMap(t5 => {
const {
source: groupSource
} = t5;
return nonBuiltIn.filter(a_0 => a_0.source === groupSource);
});
break bb0;
}
t4 = nonBuiltIn;
source: SettingSource | 'all' | 'built-in' | 'plugin'
agents: ResolvedAgent[]
onBack: () => void
onSelect: (agent: AgentDefinition) => void
onCreateNew?: () => void
changes?: string[]
}
export function AgentsList({
source,
agents,
onBack,
onSelect,
onCreateNew,
changes,
}: Props): React.ReactNode {
const [selectedAgent, setSelectedAgent] =
React.useState<ResolvedAgent | null>(null)
const [isCreateNewSelected, setIsCreateNewSelected] = React.useState(true)
// Sort agents alphabetically by name within each source group
const sortedAgents = React.useMemo(
() => [...agents].sort(compareAgentsByName),
[agents],
)
const getOverrideInfo = (agent: ResolvedAgent) => {
return {
isOverridden: !!agent.overriddenBy,
overriddenBy: agent.overriddenBy || null,
}
$[8] = sortedAgents;
$[9] = source;
$[10] = t4;
} else {
t4 = $[10];
}
const selectableAgentsInOrder = t4;
let t5;
let t6;
if ($[11] !== isCreateNewSelected || $[12] !== onCreateNew || $[13] !== selectableAgentsInOrder || $[14] !== selectedAgent) {
t5 = () => {
if (!selectedAgent && !isCreateNewSelected && selectableAgentsInOrder.length > 0) {
if (onCreateNew) {
setIsCreateNewSelected(true);
} else {
setSelectedAgent(selectableAgentsInOrder[0] || null);
}
}
};
t6 = [selectableAgentsInOrder, selectedAgent, isCreateNewSelected, onCreateNew];
$[11] = isCreateNewSelected;
$[12] = onCreateNew;
$[13] = selectableAgentsInOrder;
$[14] = selectedAgent;
$[15] = t5;
$[16] = t6;
} else {
t5 = $[15];
t6 = $[16];
const renderCreateNewOption = () => {
return (
<Box>
<Text color={isCreateNewSelected ? 'suggestion' : undefined}>
{isCreateNewSelected ? `${figures.pointer} ` : ' '}
</Text>
<Text color={isCreateNewSelected ? 'suggestion' : undefined}>
Create new agent
</Text>
</Box>
)
}
React.useEffect(t5, t6);
let t7;
if ($[17] !== isCreateNewSelected || $[18] !== onCreateNew || $[19] !== onSelect || $[20] !== selectableAgentsInOrder || $[21] !== selectedAgent) {
t7 = e => {
if (e.key === "return") {
e.preventDefault();
if (isCreateNewSelected && onCreateNew) {
onCreateNew();
} else {
if (selectedAgent) {
onSelect(selectedAgent);
}
}
return;
}
if (e.key !== "up" && e.key !== "down") {
return;
}
e.preventDefault();
const hasCreateOption = !!onCreateNew;
const totalItems = selectableAgentsInOrder.length + (hasCreateOption ? 1 : 0);
if (totalItems === 0) {
return;
}
let currentPosition = 0;
if (!isCreateNewSelected && selectedAgent) {
const agentIndex = selectableAgentsInOrder.findIndex(a_1 => a_1.agentType === selectedAgent.agentType && a_1.source === selectedAgent.source);
if (agentIndex >= 0) {
currentPosition = hasCreateOption ? agentIndex + 1 : agentIndex;
}
}
const newPosition = e.key === "up" ? currentPosition === 0 ? totalItems - 1 : currentPosition - 1 : currentPosition === totalItems - 1 ? 0 : currentPosition + 1;
if (hasCreateOption && newPosition === 0) {
setIsCreateNewSelected(true);
setSelectedAgent(null);
} else {
const agentIndex_0 = hasCreateOption ? newPosition - 1 : newPosition;
const newAgent = selectableAgentsInOrder[agentIndex_0];
if (newAgent) {
setIsCreateNewSelected(false);
setSelectedAgent(newAgent);
}
}
};
$[17] = isCreateNewSelected;
$[18] = onCreateNew;
$[19] = onSelect;
$[20] = selectableAgentsInOrder;
$[21] = selectedAgent;
$[22] = t7;
} else {
t7 = $[22];
const renderAgent = (agent: ResolvedAgent) => {
const isBuiltIn = agent.source === 'built-in'
const isSelected =
!isBuiltIn &&
!isCreateNewSelected &&
selectedAgent?.agentType === agent.agentType &&
selectedAgent?.source === agent.source
const { isOverridden, overriddenBy } = getOverrideInfo(agent)
const dimmed = isBuiltIn || isOverridden
const textColor = !isBuiltIn && isSelected ? 'suggestion' : undefined
const resolvedModel = resolveAgentModelDisplay(agent)
return (
<Box key={`${agent.agentType}-${agent.source}`}>
<Text dimColor={dimmed && !isSelected} color={textColor}>
{isBuiltIn ? '' : isSelected ? `${figures.pointer} ` : ' '}
</Text>
<Text dimColor={dimmed && !isSelected} color={textColor}>
{agent.agentType}
</Text>
{resolvedModel && (
<Text dimColor={true} color={textColor}>
{' · '}
{resolvedModel}
</Text>
)}
{agent.memory && (
<Text dimColor={true} color={textColor}>
{' · '}
{agent.memory} memory
</Text>
)}
{overriddenBy && (
<Text
dimColor={!isSelected}
color={isSelected ? 'warning' : undefined}
>
{' '}
{figures.warning} shadowed by {getOverrideSourceLabel(overriddenBy)}
</Text>
)}
</Box>
)
}
const handleKeyDown = t7;
let t8;
if ($[23] !== renderAgent || $[24] !== sortedAgents) {
t8 = t9 => {
const title = t9 === undefined ? "Built-in (always available):" : t9;
const builtInAgents = sortedAgents.filter(_temp4);
return <Box flexDirection="column" marginBottom={1} paddingLeft={2}><Text bold={true} dimColor={true}>{title}</Text>{builtInAgents.map(renderAgent)}</Box>;
};
$[23] = renderAgent;
$[24] = sortedAgents;
$[25] = t8;
} else {
t8 = $[25];
}
const renderBuiltInAgentsSection = t8;
let t9;
if ($[26] !== renderAgent) {
t9 = (title_0, groupAgents) => {
if (!groupAgents.length) {
return null;
}
const folderPath = groupAgents[0]?.baseDir;
return <Box flexDirection="column" marginBottom={1}><Box paddingLeft={2}><Text bold={true} dimColor={true}>{title_0}</Text>{folderPath && <Text dimColor={true}> ({folderPath})</Text>}</Box>{groupAgents.map(agent_1 => renderAgent(agent_1))}</Box>;
};
$[26] = renderAgent;
$[27] = t9;
} else {
t9 = $[27];
}
const renderAgentGroup = t9;
let t10;
if ($[28] !== source) {
t10 = getAgentSourceDisplayName(source);
$[28] = source;
$[29] = t10;
} else {
t10 = $[29];
}
const sourceTitle = t10;
let T0;
let T1;
let t11;
let t12;
let t13;
let t14;
let t15;
let t16;
let t17;
let t18;
let t19;
let t20;
let t21;
let t22;
if ($[30] !== changes || $[31] !== handleKeyDown || $[32] !== onBack || $[33] !== onCreateNew || $[34] !== renderAgent || $[35] !== renderAgentGroup || $[36] !== renderBuiltInAgentsSection || $[37] !== renderCreateNewOption || $[38] !== sortedAgents || $[39] !== source || $[40] !== sourceTitle) {
t22 = Symbol.for("react.early_return_sentinel");
bb1: {
const builtInAgents_0 = sortedAgents.filter(_temp5);
const hasNoAgents = !sortedAgents.length || source !== "built-in" && !sortedAgents.some(_temp6);
if (hasNoAgents) {
let t23;
if ($[55] !== onCreateNew || $[56] !== renderCreateNewOption) {
t23 = onCreateNew && <Box>{renderCreateNewOption()}</Box>;
$[55] = onCreateNew;
$[56] = renderCreateNewOption;
$[57] = t23;
} else {
t23 = $[57];
}
let t24;
let t25;
let t26;
if ($[58] === Symbol.for("react.memo_cache_sentinel")) {
t24 = <Text dimColor={true}>No agents found. Create specialized subagents that Claude can delegate to.</Text>;
t25 = <Text dimColor={true}>Each subagent has its own context window, custom system prompt, and specific tools.</Text>;
t26 = <Text dimColor={true}>Try creating: Code Reviewer, Code Simplifier, Security Reviewer, Tech Lead, or UX Reviewer.</Text>;
$[58] = t24;
$[59] = t25;
$[60] = t26;
} else {
t24 = $[58];
t25 = $[59];
t26 = $[60];
}
let t27;
if ($[61] !== renderBuiltInAgentsSection || $[62] !== sortedAgents || $[63] !== source) {
t27 = source !== "built-in" && sortedAgents.some(_temp7) && <><Divider />{renderBuiltInAgentsSection()}</>;
$[61] = renderBuiltInAgentsSection;
$[62] = sortedAgents;
$[63] = source;
$[64] = t27;
} else {
t27 = $[64];
}
let t28;
if ($[65] !== handleKeyDown || $[66] !== t23 || $[67] !== t27) {
t28 = <Box flexDirection="column" gap={1} tabIndex={0} autoFocus={true} onKeyDown={handleKeyDown}>{t23}{t24}{t25}{t26}{t27}</Box>;
$[65] = handleKeyDown;
$[66] = t23;
$[67] = t27;
$[68] = t28;
} else {
t28 = $[68];
}
let t29;
if ($[69] !== onBack || $[70] !== sourceTitle || $[71] !== t28) {
t29 = <Dialog title={sourceTitle} subtitle="No agents found" onCancel={onBack} hideInputGuide={true}>{t28}</Dialog>;
$[69] = onBack;
$[70] = sourceTitle;
$[71] = t28;
$[72] = t29;
} else {
t29 = $[72];
}
t22 = t29;
break bb1;
}
T1 = Dialog;
t17 = sourceTitle;
let t23;
if ($[73] !== sortedAgents) {
t23 = count(sortedAgents, _temp8);
$[73] = sortedAgents;
$[74] = t23;
} else {
t23 = $[74];
}
t18 = `${t23} agents`;
t19 = onBack;
t20 = true;
if ($[75] !== changes) {
t21 = changes && changes.length > 0 && <Box marginTop={1}><Text dimColor={true}>{changes[changes.length - 1]}</Text></Box>;
$[75] = changes;
$[76] = t21;
} else {
t21 = $[76];
}
T0 = Box;
t11 = "column";
t12 = 0;
t13 = true;
t14 = handleKeyDown;
if ($[77] !== onCreateNew || $[78] !== renderCreateNewOption) {
t15 = onCreateNew && <Box marginBottom={1}>{renderCreateNewOption()}</Box>;
$[77] = onCreateNew;
$[78] = renderCreateNewOption;
$[79] = t15;
} else {
t15 = $[79];
}
t16 = source === "all" ? <>{AGENT_SOURCE_GROUPS.filter(_temp9).map(t24 => {
const {
label,
source: groupSource_0
} = t24;
return <React.Fragment key={groupSource_0}>{renderAgentGroup(label, sortedAgents.filter(a_7 => a_7.source === groupSource_0))}</React.Fragment>;
})}{builtInAgents_0.length > 0 && <Box flexDirection="column" marginBottom={1} paddingLeft={2}><Text dimColor={true}><Text bold={true}>Built-in agents</Text> (always available)</Text>{builtInAgents_0.map(renderAgent)}</Box>}</> : source === "built-in" ? <><Text dimColor={true} italic={true}>Built-in agents are provided by default and cannot be modified.</Text><Box marginTop={1} flexDirection="column">{sortedAgents.map(agent_2 => renderAgent(agent_2))}</Box></> : <>{sortedAgents.filter(_temp0).map(agent_3 => renderAgent(agent_3))}{sortedAgents.some(_temp1) && <><Divider />{renderBuiltInAgentsSection()}</>}</>;
const selectableAgentsInOrder = React.useMemo(() => {
const nonBuiltIn = sortedAgents.filter(a => a.source !== 'built-in')
if (source === 'all') {
return AGENT_SOURCE_GROUPS.filter(g => g.source !== 'built-in').flatMap(
({ source: groupSource }) =>
nonBuiltIn.filter(a => a.source === groupSource),
)
}
return nonBuiltIn
}, [sortedAgents, source])
// Set initial selection
React.useEffect(() => {
if (
!selectedAgent &&
!isCreateNewSelected &&
selectableAgentsInOrder.length > 0
) {
if (onCreateNew) {
setIsCreateNewSelected(true)
} else {
setSelectedAgent(selectableAgentsInOrder[0] || null)
}
}
}, [selectableAgentsInOrder, selectedAgent, isCreateNewSelected, onCreateNew])
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'return') {
e.preventDefault()
if (isCreateNewSelected && onCreateNew) {
onCreateNew()
} else if (selectedAgent) {
onSelect(selectedAgent)
}
return
}
if (e.key !== 'up' && e.key !== 'down') return
e.preventDefault()
// Handle navigation with "Create New Agent" option
const hasCreateOption = !!onCreateNew
const totalItems =
selectableAgentsInOrder.length + (hasCreateOption ? 1 : 0)
if (totalItems === 0) return
// Calculate current position in list (0 = create new, 1+ = agents)
let currentPosition = 0
if (!isCreateNewSelected && selectedAgent) {
const agentIndex = selectableAgentsInOrder.findIndex(
a =>
a.agentType === selectedAgent.agentType &&
a.source === selectedAgent.source,
)
if (agentIndex >= 0) {
currentPosition = hasCreateOption ? agentIndex + 1 : agentIndex
}
}
// Calculate new position with wrap-around
const newPosition =
e.key === 'up'
? currentPosition === 0
? totalItems - 1
: currentPosition - 1
: currentPosition === totalItems - 1
? 0
: currentPosition + 1
// Update selection based on new position
if (hasCreateOption && newPosition === 0) {
setIsCreateNewSelected(true)
setSelectedAgent(null)
} else {
const agentIndex = hasCreateOption ? newPosition - 1 : newPosition
const newAgent = selectableAgentsInOrder[agentIndex]
if (newAgent) {
setIsCreateNewSelected(false)
setSelectedAgent(newAgent)
}
}
$[30] = changes;
$[31] = handleKeyDown;
$[32] = onBack;
$[33] = onCreateNew;
$[34] = renderAgent;
$[35] = renderAgentGroup;
$[36] = renderBuiltInAgentsSection;
$[37] = renderCreateNewOption;
$[38] = sortedAgents;
$[39] = source;
$[40] = sourceTitle;
$[41] = T0;
$[42] = T1;
$[43] = t11;
$[44] = t12;
$[45] = t13;
$[46] = t14;
$[47] = t15;
$[48] = t16;
$[49] = t17;
$[50] = t18;
$[51] = t19;
$[52] = t20;
$[53] = t21;
$[54] = t22;
} else {
T0 = $[41];
T1 = $[42];
t11 = $[43];
t12 = $[44];
t13 = $[45];
t14 = $[46];
t15 = $[47];
t16 = $[48];
t17 = $[49];
t18 = $[50];
t19 = $[51];
t20 = $[52];
t21 = $[53];
t22 = $[54];
}
if (t22 !== Symbol.for("react.early_return_sentinel")) {
return t22;
const renderBuiltInAgentsSection = (
title = 'Built-in (always available):',
) => {
const builtInAgents = sortedAgents.filter(a => a.source === 'built-in')
return (
<Box flexDirection="column" marginBottom={1} paddingLeft={2}>
<Text bold dimColor>
{title}
</Text>
{builtInAgents.map(renderAgent)}
</Box>
)
}
let t23;
if ($[80] !== T0 || $[81] !== t11 || $[82] !== t12 || $[83] !== t13 || $[84] !== t14 || $[85] !== t15 || $[86] !== t16) {
t23 = <T0 flexDirection={t11} tabIndex={t12} autoFocus={t13} onKeyDown={t14}>{t15}{t16}</T0>;
$[80] = T0;
$[81] = t11;
$[82] = t12;
$[83] = t13;
$[84] = t14;
$[85] = t15;
$[86] = t16;
$[87] = t23;
} else {
t23 = $[87];
const renderAgentGroup = (title: string, groupAgents: ResolvedAgent[]) => {
if (!groupAgents.length) return null
const folderPath = groupAgents[0]?.baseDir
return (
<Box flexDirection="column" marginBottom={1}>
<Box paddingLeft={2}>
<Text bold dimColor>
{title}
</Text>
{folderPath && <Text dimColor> ({folderPath})</Text>}
</Box>
{groupAgents.map(agent => renderAgent(agent))}
</Box>
)
}
let t24;
if ($[88] !== T1 || $[89] !== t17 || $[90] !== t18 || $[91] !== t19 || $[92] !== t20 || $[93] !== t21 || $[94] !== t23) {
t24 = <T1 title={t17} subtitle={t18} onCancel={t19} hideInputGuide={t20}>{t21}{t23}</T1>;
$[88] = T1;
$[89] = t17;
$[90] = t18;
$[91] = t19;
$[92] = t20;
$[93] = t21;
$[94] = t23;
$[95] = t24;
} else {
t24 = $[95];
const sourceTitle = getAgentSourceDisplayName(source)
const builtInAgents = sortedAgents.filter(a => a.source === 'built-in')
const hasNoAgents =
!sortedAgents.length ||
(source !== 'built-in' && !sortedAgents.some(a => a.source !== 'built-in'))
if (hasNoAgents) {
return (
<Dialog
title={sourceTitle}
subtitle="No agents found"
onCancel={onBack}
hideInputGuide
>
<Box
flexDirection="column"
gap={1}
tabIndex={0}
autoFocus
onKeyDown={handleKeyDown}
>
{onCreateNew && <Box>{renderCreateNewOption()}</Box>}
<Text dimColor>
No agents found. Create specialized subagents that Claude can
delegate to.
</Text>
<Text dimColor>
Each subagent has its own context window, custom system prompt, and
specific tools.
</Text>
<Text dimColor>
Try creating: Code Reviewer, Code Simplifier, Security Reviewer,
Tech Lead, or UX Reviewer.
</Text>
{source !== 'built-in' &&
sortedAgents.some(a => a.source === 'built-in') && (
<>
<Divider />
{renderBuiltInAgentsSection()}
</>
)}
</Box>
</Dialog>
)
}
return t24;
}
function _temp1(a_9) {
return a_9.source === "built-in";
}
function _temp0(a_8) {
return a_8.source !== "built-in";
}
function _temp9(g_0) {
return g_0.source !== "built-in";
}
function _temp8(a_6) {
return !a_6.overriddenBy;
}
function _temp7(a_5) {
return a_5.source === "built-in";
}
function _temp6(a_4) {
return a_4.source !== "built-in";
}
function _temp5(a_3) {
return a_3.source === "built-in";
}
function _temp4(a_2) {
return a_2.source === "built-in";
}
function _temp3(g) {
return g.source !== "built-in";
}
function _temp2(a) {
return a.source !== "built-in";
}
function _temp(agent) {
return {
isOverridden: !!agent.overriddenBy,
overriddenBy: agent.overriddenBy || null
};
return (
<Dialog
title={sourceTitle}
subtitle={`${count(sortedAgents, a => !a.overriddenBy)} agents`}
onCancel={onBack}
hideInputGuide
>
{changes && changes.length > 0 && (
<Box marginTop={1}>
<Text dimColor>{changes[changes.length - 1]}</Text>
</Box>
)}
<Box
flexDirection="column"
tabIndex={0}
autoFocus
onKeyDown={handleKeyDown}
>
{onCreateNew && <Box marginBottom={1}>{renderCreateNewOption()}</Box>}
{source === 'all' ? (
<>
{AGENT_SOURCE_GROUPS.filter(g => g.source !== 'built-in').map(
({ label, source: groupSource }) => (
<React.Fragment key={groupSource}>
{renderAgentGroup(
label,
sortedAgents.filter(a => a.source === groupSource),
)}
</React.Fragment>
),
)}
{builtInAgents.length > 0 && (
<Box flexDirection="column" marginBottom={1} paddingLeft={2}>
<Text dimColor>
<Text bold>Built-in agents</Text> (always available)
</Text>
{builtInAgents.map(renderAgent)}
</Box>
)}
</>
) : source === 'built-in' ? (
<>
<Text dimColor italic>
Built-in agents are provided by default and cannot be modified.
</Text>
<Box marginTop={1} flexDirection="column">
{sortedAgents.map(agent => renderAgent(agent))}
</Box>
</>
) : (
<>
{sortedAgents
.filter(a => a.source !== 'built-in')
.map(agent => renderAgent(agent))}
{sortedAgents.some(a => a.source === 'built-in') && (
<>
<Divider />
{renderBuiltInAgentsSection()}
</>
)}
</>
)}
</Box>
</Dialog>
)
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,111 +1,106 @@
import { c as _c } from "react/compiler-runtime";
import figures from 'figures';
import React, { useState } from 'react';
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js';
import { Box, Text } from '../../ink.js';
import { AGENT_COLOR_TO_THEME_COLOR, AGENT_COLORS, type AgentColorName } from '../../tools/AgentTool/agentColorManager.js';
import { capitalize } from '../../utils/stringUtils.js';
type ColorOption = AgentColorName | 'automatic';
const COLOR_OPTIONS: ColorOption[] = ['automatic', ...AGENT_COLORS];
import figures from 'figures'
import React, { useState } from 'react'
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js'
import { Box, Text } from '../../ink.js'
import {
AGENT_COLOR_TO_THEME_COLOR,
AGENT_COLORS,
type AgentColorName,
} from '../../tools/AgentTool/agentColorManager.js'
import { capitalize } from '../../utils/stringUtils.js'
type ColorOption = AgentColorName | 'automatic'
const COLOR_OPTIONS: ColorOption[] = ['automatic', ...AGENT_COLORS]
type Props = {
agentName: string;
currentColor?: AgentColorName | 'automatic';
onConfirm: (color: AgentColorName | undefined) => void;
};
export function ColorPicker(t0) {
const $ = _c(17);
const {
agentName,
currentColor: t1,
onConfirm
} = t0;
const currentColor = t1 === undefined ? "automatic" : t1;
let t2;
if ($[0] !== currentColor) {
t2 = COLOR_OPTIONS.findIndex(opt => opt === currentColor);
$[0] = currentColor;
$[1] = t2;
} else {
t2 = $[1];
}
const [selectedIndex, setSelectedIndex] = useState(Math.max(0, t2));
let t3;
if ($[2] !== onConfirm || $[3] !== selectedIndex) {
t3 = e => {
if (e.key === "up") {
e.preventDefault();
setSelectedIndex(_temp);
} else {
if (e.key === "down") {
e.preventDefault();
setSelectedIndex(_temp2);
} else {
if (e.key === "return") {
e.preventDefault();
const selected = COLOR_OPTIONS[selectedIndex];
onConfirm(selected === "automatic" ? undefined : selected);
}
}
}
};
$[2] = onConfirm;
$[3] = selectedIndex;
$[4] = t3;
} else {
t3 = $[4];
}
const handleKeyDown = t3;
const selectedValue = COLOR_OPTIONS[selectedIndex];
let t4;
if ($[5] !== selectedIndex) {
t4 = COLOR_OPTIONS.map((option, index) => {
const isSelected = index === selectedIndex;
return <Box key={option} flexDirection="row" gap={1}><Text color={isSelected ? "suggestion" : undefined}>{isSelected ? figures.pointer : " "}</Text>{option === "automatic" ? <Text bold={isSelected}>Automatic color</Text> : <Box gap={1}><Text backgroundColor={AGENT_COLOR_TO_THEME_COLOR[option]} color="inverseText">{" "}</Text><Text bold={isSelected}>{capitalize(option)}</Text></Box>}</Box>;
});
$[5] = selectedIndex;
$[6] = t4;
} else {
t4 = $[6];
}
let t5;
if ($[7] !== t4) {
t5 = <Box flexDirection="column">{t4}</Box>;
$[7] = t4;
$[8] = t5;
} else {
t5 = $[8];
}
let t6;
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
t6 = <Text>Preview: </Text>;
$[9] = t6;
} else {
t6 = $[9];
}
let t7;
if ($[10] !== agentName || $[11] !== selectedValue) {
t7 = <Box marginTop={1}>{t6}{selectedValue === undefined || selectedValue === "automatic" ? <Text inverse={true} bold={true}>{" "}@{agentName}{" "}</Text> : <Text backgroundColor={AGENT_COLOR_TO_THEME_COLOR[selectedValue]} color="inverseText" bold={true}>{" "}@{agentName}{" "}</Text>}</Box>;
$[10] = agentName;
$[11] = selectedValue;
$[12] = t7;
} else {
t7 = $[12];
}
let t8;
if ($[13] !== handleKeyDown || $[14] !== t5 || $[15] !== t7) {
t8 = <Box flexDirection="column" gap={1} tabIndex={0} autoFocus={true} onKeyDown={handleKeyDown}>{t5}{t7}</Box>;
$[13] = handleKeyDown;
$[14] = t5;
$[15] = t7;
$[16] = t8;
} else {
t8 = $[16];
}
return t8;
agentName: string
currentColor?: AgentColorName | 'automatic'
onConfirm: (color: AgentColorName | undefined) => void
}
function _temp2(prev_0) {
return prev_0 < COLOR_OPTIONS.length - 1 ? prev_0 + 1 : 0;
}
function _temp(prev) {
return prev > 0 ? prev - 1 : COLOR_OPTIONS.length - 1;
export function ColorPicker({
agentName,
currentColor = 'automatic',
onConfirm,
}: Props): React.ReactNode {
const [selectedIndex, setSelectedIndex] = useState(
Math.max(
0,
COLOR_OPTIONS.findIndex(opt => opt === currentColor),
),
)
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'up') {
e.preventDefault()
setSelectedIndex(prev => (prev > 0 ? prev - 1 : COLOR_OPTIONS.length - 1))
} else if (e.key === 'down') {
e.preventDefault()
setSelectedIndex(prev => (prev < COLOR_OPTIONS.length - 1 ? prev + 1 : 0))
} else if (e.key === 'return') {
e.preventDefault()
const selected = COLOR_OPTIONS[selectedIndex]
onConfirm(selected === 'automatic' ? undefined : selected)
}
}
const selectedValue = COLOR_OPTIONS[selectedIndex]
return (
<Box
flexDirection="column"
gap={1}
tabIndex={0}
autoFocus
onKeyDown={handleKeyDown}
>
<Box flexDirection="column">
{COLOR_OPTIONS.map((option, index) => {
const isSelected = index === selectedIndex
return (
<Box key={option} flexDirection="row" gap={1}>
<Text color={isSelected ? 'suggestion' : undefined}>
{isSelected ? figures.pointer : ' '}
</Text>
{option === 'automatic' ? (
<Text bold={isSelected}>Automatic color</Text>
) : (
<Box gap={1}>
<Text
backgroundColor={AGENT_COLOR_TO_THEME_COLOR[option]}
color="inverseText"
>
{' '}
</Text>
<Text bold={isSelected}>{capitalize(option)}</Text>
</Box>
)}
</Box>
)
})}
</Box>
<Box marginTop={1}>
<Text>Preview: </Text>
{selectedValue === undefined || selectedValue === 'automatic' ? (
<Text inverse bold>
{' '}
@{agentName}{' '}
</Text>
) : (
<Text
backgroundColor={AGENT_COLOR_TO_THEME_COLOR[selectedValue]}
color="inverseText"
bold
>
{' '}
@{agentName}{' '}
</Text>
)}
</Box>
</Box>
)
}

View File

@@ -1,67 +1,52 @@
import { c as _c } from "react/compiler-runtime";
import * as React from 'react';
import { Box, Text } from '../../ink.js';
import { getAgentModelOptions } from '../../utils/model/agent.js';
import { Select } from '../CustomSelect/select.js';
import * as React from 'react'
import { Box, Text } from '../../ink.js'
import { getAgentModelOptions } from '../../utils/model/agent.js'
import { Select } from '../CustomSelect/select.js'
interface ModelSelectorProps {
initialModel?: string;
onComplete: (model?: string) => void;
onCancel?: () => void;
initialModel?: string
onComplete: (model?: string) => void
onCancel?: () => void
}
export function ModelSelector(t0) {
const $ = _c(11);
const {
initialModel,
onComplete,
onCancel
} = t0;
let t1;
if ($[0] !== initialModel) {
bb0: {
const base = getAgentModelOptions();
if (initialModel && !base.some(o => o.value === initialModel)) {
t1 = [{
export function ModelSelector({
initialModel,
onComplete,
onCancel,
}: ModelSelectorProps): React.ReactNode {
const modelOptions = React.useMemo(() => {
const base = getAgentModelOptions()
// If the agent's current model is a full ID (e.g. 'claude-opus-4-5') not
// in the alias list, inject it as an option so it can round-trip through
// confirm without being overwritten.
if (initialModel && !base.some(o => o.value === initialModel)) {
return [
{
value: initialModel,
label: initialModel,
description: "Current model (custom ID)"
}, ...base];
break bb0;
}
t1 = base;
description: 'Current model (custom ID)',
},
...base,
]
}
$[0] = initialModel;
$[1] = t1;
} else {
t1 = $[1];
}
const modelOptions = t1;
const defaultModel = initialModel ?? "sonnet";
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Box marginBottom={1}><Text dimColor={true}>Model determines the agent's reasoning capabilities and speed.</Text></Box>;
$[2] = t2;
} else {
t2 = $[2];
}
let t3;
if ($[3] !== onCancel || $[4] !== onComplete) {
t3 = () => onCancel ? onCancel() : onComplete(undefined);
$[3] = onCancel;
$[4] = onComplete;
$[5] = t3;
} else {
t3 = $[5];
}
let t4;
if ($[6] !== defaultModel || $[7] !== modelOptions || $[8] !== onComplete || $[9] !== t3) {
t4 = <Box flexDirection="column">{t2}<Select options={modelOptions} defaultValue={defaultModel} onChange={onComplete} onCancel={t3} /></Box>;
$[6] = defaultModel;
$[7] = modelOptions;
$[8] = onComplete;
$[9] = t3;
$[10] = t4;
} else {
t4 = $[10];
}
return t4;
return base
}, [initialModel])
const defaultModel = initialModel ?? 'sonnet'
return (
<Box flexDirection="column">
<Box marginBottom={1}>
<Text dimColor>
Model determines the agent&apos;s reasoning capabilities and speed.
</Text>
</Box>
<Select
options={modelOptions}
defaultValue={defaultModel}
onChange={onComplete}
onCancel={() => (onCancel ? onCancel() : onComplete(undefined))}
/>
</Box>
)
}

View File

@@ -1,561 +1,478 @@
import { c as _c } from "react/compiler-runtime";
import figures from 'figures';
import React, { useCallback, useMemo, useState } from 'react';
import { mcpInfoFromString } from 'src/services/mcp/mcpStringUtils.js';
import { isMcpTool } from 'src/services/mcp/utils.js';
import type { Tool, Tools } from 'src/Tool.js';
import { filterToolsForAgent } from 'src/tools/AgentTool/agentToolUtils.js';
import { AGENT_TOOL_NAME } from 'src/tools/AgentTool/constants.js';
import { BashTool } from 'src/tools/BashTool/BashTool.js';
import { ExitPlanModeV2Tool } from 'src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.js';
import { FileEditTool } from 'src/tools/FileEditTool/FileEditTool.js';
import { FileReadTool } from 'src/tools/FileReadTool/FileReadTool.js';
import { FileWriteTool } from 'src/tools/FileWriteTool/FileWriteTool.js';
import { GlobTool } from 'src/tools/GlobTool/GlobTool.js';
import { GrepTool } from 'src/tools/GrepTool/GrepTool.js';
import { ListMcpResourcesTool } from 'src/tools/ListMcpResourcesTool/ListMcpResourcesTool.js';
import { NotebookEditTool } from 'src/tools/NotebookEditTool/NotebookEditTool.js';
import { ReadMcpResourceTool } from 'src/tools/ReadMcpResourceTool/ReadMcpResourceTool.js';
import { TaskOutputTool } from 'src/tools/TaskOutputTool/TaskOutputTool.js';
import { TaskStopTool } from 'src/tools/TaskStopTool/TaskStopTool.js';
import { TodoWriteTool } from 'src/tools/TodoWriteTool/TodoWriteTool.js';
import { TungstenTool } from 'src/tools/TungstenTool/TungstenTool.js';
import { WebFetchTool } from 'src/tools/WebFetchTool/WebFetchTool.js';
import { WebSearchTool } from 'src/tools/WebSearchTool/WebSearchTool.js';
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js';
import { Box, Text } from '../../ink.js';
import { useKeybinding } from '../../keybindings/useKeybinding.js';
import { count } from '../../utils/array.js';
import { plural } from '../../utils/stringUtils.js';
import { Divider } from '../design-system/Divider.js';
import figures from 'figures'
import React, { useCallback, useMemo, useState } from 'react'
import { mcpInfoFromString } from 'src/services/mcp/mcpStringUtils.js'
import { isMcpTool } from 'src/services/mcp/utils.js'
import type { Tool, Tools } from 'src/Tool.js'
import { filterToolsForAgent } from 'src/tools/AgentTool/agentToolUtils.js'
import { AGENT_TOOL_NAME } from 'src/tools/AgentTool/constants.js'
import { BashTool } from 'src/tools/BashTool/BashTool.js'
import { ExitPlanModeV2Tool } from 'src/tools/ExitPlanModeTool/ExitPlanModeV2Tool.js'
import { FileEditTool } from 'src/tools/FileEditTool/FileEditTool.js'
import { FileReadTool } from 'src/tools/FileReadTool/FileReadTool.js'
import { FileWriteTool } from 'src/tools/FileWriteTool/FileWriteTool.js'
import { GlobTool } from 'src/tools/GlobTool/GlobTool.js'
import { GrepTool } from 'src/tools/GrepTool/GrepTool.js'
import { ListMcpResourcesTool } from 'src/tools/ListMcpResourcesTool/ListMcpResourcesTool.js'
import { NotebookEditTool } from 'src/tools/NotebookEditTool/NotebookEditTool.js'
import { ReadMcpResourceTool } from 'src/tools/ReadMcpResourceTool/ReadMcpResourceTool.js'
import { TaskOutputTool } from 'src/tools/TaskOutputTool/TaskOutputTool.js'
import { TaskStopTool } from 'src/tools/TaskStopTool/TaskStopTool.js'
import { TodoWriteTool } from 'src/tools/TodoWriteTool/TodoWriteTool.js'
import { TungstenTool } from 'src/tools/TungstenTool/TungstenTool.js'
import { WebFetchTool } from 'src/tools/WebFetchTool/WebFetchTool.js'
import { WebSearchTool } from 'src/tools/WebSearchTool/WebSearchTool.js'
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js'
import { Box, Text } from '../../ink.js'
import { useKeybinding } from '../../keybindings/useKeybinding.js'
import { count } from '../../utils/array.js'
import { plural } from '../../utils/stringUtils.js'
import { Divider } from '../design-system/Divider.js'
type Props = {
tools: Tools;
initialTools: string[] | undefined;
onComplete: (selectedTools: string[] | undefined) => void;
onCancel?: () => void;
};
tools: Tools
initialTools: string[] | undefined
onComplete: (selectedTools: string[] | undefined) => void
onCancel?: () => void
}
type ToolBucket = {
name: string;
toolNames: Set<string>;
isMcp?: boolean;
};
name: string
toolNames: Set<string>
isMcp?: boolean
}
type ToolBuckets = {
READ_ONLY: ToolBucket;
EDIT: ToolBucket;
EXECUTION: ToolBucket;
MCP: ToolBucket;
OTHER: ToolBucket;
};
READ_ONLY: ToolBucket
EDIT: ToolBucket
EXECUTION: ToolBucket
MCP: ToolBucket
OTHER: ToolBucket
}
function getToolBuckets(): ToolBuckets {
return {
READ_ONLY: {
name: 'Read-only tools',
toolNames: new Set([GlobTool.name, GrepTool.name, ExitPlanModeV2Tool.name, FileReadTool.name, WebFetchTool.name, TodoWriteTool.name, WebSearchTool.name, TaskStopTool.name, TaskOutputTool.name, ListMcpResourcesTool.name, ReadMcpResourceTool.name])
toolNames: new Set([
GlobTool.name,
GrepTool.name,
ExitPlanModeV2Tool.name,
FileReadTool.name,
WebFetchTool.name,
TodoWriteTool.name,
WebSearchTool.name,
TaskStopTool.name,
TaskOutputTool.name,
ListMcpResourcesTool.name,
ReadMcpResourceTool.name,
]),
},
EDIT: {
name: 'Edit tools',
toolNames: new Set([FileEditTool.name, FileWriteTool.name, NotebookEditTool.name])
toolNames: new Set([
FileEditTool.name,
FileWriteTool.name,
NotebookEditTool.name,
]),
},
EXECUTION: {
name: 'Execution tools',
toolNames: new Set([BashTool.name, (process.env.USER_TYPE) === 'ant' ? TungstenTool.name : undefined].filter(n => n !== undefined))
toolNames: new Set(
[
BashTool.name,
process.env.USER_TYPE === 'ant' ? TungstenTool.name : undefined,
].filter(n => n !== undefined),
),
},
MCP: {
name: 'MCP tools',
toolNames: new Set(),
// Dynamic - no static list
isMcp: true
toolNames: new Set(), // Dynamic - no static list
isMcp: true,
},
OTHER: {
name: 'Other tools',
toolNames: new Set() // Dynamic - catch-all for uncategorized tools
}
};
toolNames: new Set(), // Dynamic - catch-all for uncategorized tools
},
}
}
// Helper to get MCP server buckets dynamically
function getMcpServerBuckets(tools: Tools): Array<{
serverName: string;
tools: Tools;
serverName: string
tools: Tools
}> {
const serverMap = new Map<string, Tool[]>();
const serverMap = new Map<string, Tool[]>()
tools.forEach(tool => {
if (isMcpTool(tool)) {
const mcpInfo = mcpInfoFromString(tool.name);
const mcpInfo = mcpInfoFromString(tool.name)
if (mcpInfo?.serverName) {
const existing = serverMap.get(mcpInfo.serverName) || [];
existing.push(tool);
serverMap.set(mcpInfo.serverName, existing);
const existing = serverMap.get(mcpInfo.serverName) || []
existing.push(tool)
serverMap.set(mcpInfo.serverName, existing)
}
}
});
return Array.from(serverMap.entries()).map(([serverName, tools]) => ({
serverName,
tools
})).sort((a, b) => a.serverName.localeCompare(b.serverName));
})
return Array.from(serverMap.entries())
.map(([serverName, tools]) => ({ serverName, tools }))
.sort((a, b) => a.serverName.localeCompare(b.serverName))
}
export function ToolSelector(t0) {
const $ = _c(69);
const {
tools,
initialTools,
onComplete,
onCancel
} = t0;
let t1;
if ($[0] !== tools) {
t1 = filterToolsForAgent({
tools,
isBuiltIn: false,
isAsync: false
});
$[0] = tools;
$[1] = t1;
} else {
t1 = $[1];
export function ToolSelector({
tools,
initialTools,
onComplete,
onCancel,
}: Props): React.ReactNode {
// Filter tools for custom agents
const customAgentTools = useMemo(
() => filterToolsForAgent({ tools, isBuiltIn: false, isAsync: false }),
[tools],
)
// Expand wildcard or undefined to explicit tool list for internal state
const expandedInitialTools =
!initialTools || initialTools.includes('*')
? customAgentTools.map(t => t.name)
: initialTools
const [selectedTools, setSelectedTools] =
useState<string[]>(expandedInitialTools)
const [focusIndex, setFocusIndex] = useState(0)
const [showIndividualTools, setShowIndividualTools] = useState(false)
// Filter selectedTools to only include tools that currently exist
// This handles MCP tools that disconnect while selected
const validSelectedTools = useMemo(() => {
const toolNames = new Set(customAgentTools.map(t => t.name))
return selectedTools.filter(name => toolNames.has(name))
}, [selectedTools, customAgentTools])
const selectedSet = new Set(validSelectedTools)
const isAllSelected =
validSelectedTools.length === customAgentTools.length &&
customAgentTools.length > 0
const handleToggleTool = (toolName: string) => {
if (!toolName) return
setSelectedTools(current =>
current.includes(toolName)
? current.filter(t => t !== toolName)
: [...current, toolName],
)
}
const customAgentTools = t1;
let t2;
if ($[2] !== customAgentTools || $[3] !== initialTools) {
t2 = !initialTools || initialTools.includes("*") ? customAgentTools.map(_temp) : initialTools;
$[2] = customAgentTools;
$[3] = initialTools;
$[4] = t2;
} else {
t2 = $[4];
}
const expandedInitialTools = t2;
const [selectedTools, setSelectedTools] = useState(expandedInitialTools);
const [focusIndex, setFocusIndex] = useState(0);
const [showIndividualTools, setShowIndividualTools] = useState(false);
let t3;
if ($[5] !== customAgentTools) {
t3 = new Set(customAgentTools.map(_temp2));
$[5] = customAgentTools;
$[6] = t3;
} else {
t3 = $[6];
}
const toolNames = t3;
let t4;
if ($[7] !== selectedTools || $[8] !== toolNames) {
let t5;
if ($[10] !== toolNames) {
t5 = name => toolNames.has(name);
$[10] = toolNames;
$[11] = t5;
} else {
t5 = $[11];
}
t4 = selectedTools.filter(t5);
$[7] = selectedTools;
$[8] = toolNames;
$[9] = t4;
} else {
t4 = $[9];
}
const validSelectedTools = t4;
let t5;
if ($[12] !== validSelectedTools) {
t5 = new Set(validSelectedTools);
$[12] = validSelectedTools;
$[13] = t5;
} else {
t5 = $[13];
}
const selectedSet = t5;
const isAllSelected = validSelectedTools.length === customAgentTools.length && customAgentTools.length > 0;
let t6;
if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
t6 = toolName => {
if (!toolName) {
return;
const handleToggleTools = (toolNames: string[], select: boolean) => {
setSelectedTools(current => {
if (select) {
const toolsToAdd = toolNames.filter(t => !current.includes(t))
return [...current, ...toolsToAdd]
} else {
return current.filter(t => !toolNames.includes(t))
}
setSelectedTools(current => current.includes(toolName) ? current.filter(t_1 => t_1 !== toolName) : [...current, toolName]);
};
$[14] = t6;
} else {
t6 = $[14];
})
}
const handleToggleTool = t6;
let t7;
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
t7 = (toolNames_0, select) => {
setSelectedTools(current_0 => {
if (select) {
const toolsToAdd = toolNames_0.filter(t_2 => !current_0.includes(t_2));
return [...current_0, ...toolsToAdd];
} else {
return current_0.filter(t_3 => !toolNames_0.includes(t_3));
}
});
};
$[15] = t7;
} else {
t7 = $[15];
const handleConfirm = () => {
// Convert to undefined if all tools are selected (for cleaner file format)
const allToolNames = customAgentTools.map(t => t.name)
const areAllToolsSelected =
validSelectedTools.length === allToolNames.length &&
allToolNames.every(name => validSelectedTools.includes(name))
const finalTools = areAllToolsSelected ? undefined : validSelectedTools
onComplete(finalTools)
}
const handleToggleTools = t7;
let t8;
if ($[16] !== customAgentTools || $[17] !== onComplete || $[18] !== validSelectedTools) {
t8 = () => {
const allToolNames = customAgentTools.map(_temp3);
const areAllToolsSelected = validSelectedTools.length === allToolNames.length && allToolNames.every(name_0 => validSelectedTools.includes(name_0));
const finalTools = areAllToolsSelected ? undefined : validSelectedTools;
onComplete(finalTools);
};
$[16] = customAgentTools;
$[17] = onComplete;
$[18] = validSelectedTools;
$[19] = t8;
} else {
t8 = $[19];
}
const handleConfirm = t8;
let buckets;
if ($[20] !== customAgentTools) {
const toolBuckets = getToolBuckets();
buckets = {
// Group tools by bucket
const toolsByBucket = useMemo(() => {
const toolBuckets = getToolBuckets()
const buckets = {
readOnly: [] as Tool[],
edit: [] as Tool[],
execution: [] as Tool[],
mcp: [] as Tool[],
other: [] as Tool[]
};
other: [] as Tool[],
}
customAgentTools.forEach(tool => {
// Check if it's an MCP tool first
if (isMcpTool(tool)) {
buckets.mcp.push(tool);
} else {
if (toolBuckets.READ_ONLY.toolNames.has(tool.name)) {
buckets.readOnly.push(tool);
} else {
if (toolBuckets.EDIT.toolNames.has(tool.name)) {
buckets.edit.push(tool);
} else {
if (toolBuckets.EXECUTION.toolNames.has(tool.name)) {
buckets.execution.push(tool);
} else {
if (tool.name !== AGENT_TOOL_NAME) {
buckets.other.push(tool);
}
}
}
}
buckets.mcp.push(tool)
} else if (toolBuckets.READ_ONLY.toolNames.has(tool.name)) {
buckets.readOnly.push(tool)
} else if (toolBuckets.EDIT.toolNames.has(tool.name)) {
buckets.edit.push(tool)
} else if (toolBuckets.EXECUTION.toolNames.has(tool.name)) {
buckets.execution.push(tool)
} else if (tool.name !== AGENT_TOOL_NAME) {
// Catch-all for uncategorized tools (except Task)
buckets.other.push(tool)
}
});
$[20] = customAgentTools;
$[21] = buckets;
} else {
buckets = $[21];
}
const toolsByBucket = buckets;
let t9;
if ($[22] !== selectedSet) {
t9 = bucketTools => {
const selected = count(bucketTools, (t_5: Tool) => selectedSet.has(t_5.name));
const needsSelection = selected < bucketTools.length;
return () => {
const toolNames_1 = bucketTools.map(_temp4);
handleToggleTools(toolNames_1, needsSelection);
};
};
$[22] = selectedSet;
$[23] = t9;
} else {
t9 = $[23];
}
const createBucketToggleAction = t9;
let navigableItems;
if ($[24] !== createBucketToggleAction || $[25] !== customAgentTools || $[26] !== focusIndex || $[27] !== handleConfirm || $[28] !== isAllSelected || $[29] !== selectedSet || $[30] !== showIndividualTools || $[31] !== toolsByBucket.edit || $[32] !== toolsByBucket.execution || $[33] !== toolsByBucket.mcp || $[34] !== toolsByBucket.other || $[35] !== toolsByBucket.readOnly) {
navigableItems = [];
navigableItems.push({
id: "continue",
label: "Continue",
action: handleConfirm,
isContinue: true
});
let t10;
if ($[37] !== customAgentTools || $[38] !== isAllSelected) {
t10 = () => {
const allToolNames_0 = customAgentTools.map(_temp5);
handleToggleTools(allToolNames_0, !isAllSelected);
};
$[37] = customAgentTools;
$[38] = isAllSelected;
$[39] = t10;
} else {
t10 = $[39];
})
return buckets
}, [customAgentTools])
const createBucketToggleAction = (bucketTools: Tool[]) => {
const selected = count(bucketTools, t => selectedSet.has(t.name))
const needsSelection = selected < bucketTools.length
return () => {
const toolNames = bucketTools.map(t => t.name)
handleToggleTools(toolNames, needsSelection)
}
}
// Build navigable items (no separators)
const navigableItems: Array<{
id: string
label: string
action: () => void
isContinue?: boolean
isToggle?: boolean
isHeader?: boolean
}> = []
// Continue button
navigableItems.push({
id: 'continue',
label: 'Continue',
action: handleConfirm,
isContinue: true,
})
// All tools
navigableItems.push({
id: 'bucket-all',
label: `${isAllSelected ? figures.checkboxOn : figures.checkboxOff} All tools`,
action: () => {
const allToolNames = customAgentTools.map(t => t.name)
handleToggleTools(allToolNames, !isAllSelected)
},
})
// Create bucket menu items
const toolBuckets = getToolBuckets()
const bucketConfigs = [
{
id: 'bucket-readonly',
name: toolBuckets.READ_ONLY.name,
tools: toolsByBucket.readOnly,
},
{
id: 'bucket-edit',
name: toolBuckets.EDIT.name,
tools: toolsByBucket.edit,
},
{
id: 'bucket-execution',
name: toolBuckets.EXECUTION.name,
tools: toolsByBucket.execution,
},
{
id: 'bucket-mcp',
name: toolBuckets.MCP.name,
tools: toolsByBucket.mcp,
},
{
id: 'bucket-other',
name: toolBuckets.OTHER.name,
tools: toolsByBucket.other,
},
]
bucketConfigs.forEach(({ id, name, tools: bucketTools }) => {
if (bucketTools.length === 0) return
const selected = count(bucketTools, t => selectedSet.has(t.name))
const isFullySelected = selected === bucketTools.length
navigableItems.push({
id: "bucket-all",
label: `${isAllSelected ? figures.checkboxOn : figures.checkboxOff} All tools`,
action: t10
});
const toolBuckets_0 = getToolBuckets();
const bucketConfigs = [{
id: "bucket-readonly",
name: toolBuckets_0.READ_ONLY.name,
tools: toolsByBucket.readOnly
}, {
id: "bucket-edit",
name: toolBuckets_0.EDIT.name,
tools: toolsByBucket.edit
}, {
id: "bucket-execution",
name: toolBuckets_0.EXECUTION.name,
tools: toolsByBucket.execution
}, {
id: "bucket-mcp",
name: toolBuckets_0.MCP.name,
tools: toolsByBucket.mcp
}, {
id: "bucket-other",
name: toolBuckets_0.OTHER.name,
tools: toolsByBucket.other
}];
bucketConfigs.forEach(t11 => {
const {
id,
name: name_1,
tools: bucketTools_0
} = t11;
if (bucketTools_0.length === 0) {
return;
id,
label: `${isFullySelected ? figures.checkboxOn : figures.checkboxOff} ${name}`,
action: createBucketToggleAction(bucketTools),
})
})
// Toggle button for individual tools
const toggleButtonIndex = navigableItems.length
navigableItems.push({
id: 'toggle-individual',
label: showIndividualTools
? 'Hide advanced options'
: 'Show advanced options',
action: () => {
setShowIndividualTools(!showIndividualTools)
// If hiding tools and focus is on an individual tool, move focus to toggle button
if (showIndividualTools && focusIndex > toggleButtonIndex) {
setFocusIndex(toggleButtonIndex)
}
const selected_0 = count(bucketTools_0, (t_8: Tool) => selectedSet.has(t_8.name));
const isFullySelected = selected_0 === bucketTools_0.length;
},
isToggle: true,
})
// Memoize MCP server buckets (must be outside conditional for hooks rules)
const mcpServerBuckets = useMemo(
() => getMcpServerBuckets(customAgentTools),
[customAgentTools],
)
// Individual tools (only if expanded)
if (showIndividualTools) {
// Add MCP server buckets if any exist
if (mcpServerBuckets.length > 0) {
navigableItems.push({
id,
label: `${isFullySelected ? figures.checkboxOn : figures.checkboxOff} ${name_1}`,
action: createBucketToggleAction(bucketTools_0)
});
});
const toggleButtonIndex = navigableItems.length;
let t12;
if ($[40] !== focusIndex || $[41] !== showIndividualTools || $[42] !== toggleButtonIndex) {
t12 = () => {
setShowIndividualTools(!showIndividualTools);
if (showIndividualTools && focusIndex > toggleButtonIndex) {
setFocusIndex(toggleButtonIndex);
}
};
$[40] = focusIndex;
$[41] = showIndividualTools;
$[42] = toggleButtonIndex;
$[43] = t12;
id: 'mcp-servers-header',
label: 'MCP Servers:',
action: () => {}, // No action - just a header
isHeader: true,
})
mcpServerBuckets.forEach(({ serverName, tools: serverTools }) => {
const selected = count(serverTools, t => selectedSet.has(t.name))
const isFullySelected = selected === serverTools.length
navigableItems.push({
id: `mcp-server-${serverName}`,
label: `${isFullySelected ? figures.checkboxOn : figures.checkboxOff} ${serverName} (${serverTools.length} ${plural(serverTools.length, 'tool')})`,
action: () => {
const toolNames = serverTools.map(t => t.name)
handleToggleTools(toolNames, !isFullySelected)
},
})
})
// Add separator header before individual tools
navigableItems.push({
id: 'tools-header',
label: 'Individual Tools:',
action: () => {},
isHeader: true,
})
}
// Add individual tools
customAgentTools.forEach(tool => {
let displayName = tool.name
if (tool.name.startsWith('mcp__')) {
const mcpInfo = mcpInfoFromString(tool.name)
displayName = mcpInfo
? `${mcpInfo.toolName} (${mcpInfo.serverName})`
: tool.name
}
navigableItems.push({
id: `tool-${tool.name}`,
label: `${selectedSet.has(tool.name) ? figures.checkboxOn : figures.checkboxOff} ${displayName}`,
action: () => handleToggleTool(tool.name),
})
})
}
const handleCancel = useCallback(() => {
if (onCancel) {
onCancel()
} else {
t12 = $[43];
onComplete(initialTools)
}
navigableItems.push({
id: "toggle-individual",
label: showIndividualTools ? "Hide advanced options" : "Show advanced options",
action: t12,
isToggle: true
});
const mcpServerBuckets = getMcpServerBuckets(customAgentTools);
if (showIndividualTools) {
if (mcpServerBuckets.length > 0) {
navigableItems.push({
id: "mcp-servers-header",
label: "MCP Servers:",
action: _temp6,
isHeader: true
});
mcpServerBuckets.forEach(t13 => {
const {
serverName,
tools: serverTools
} = t13;
const selected_1 = count(serverTools, t_9 => selectedSet.has(t_9.name));
const isFullySelected_0 = selected_1 === serverTools.length;
navigableItems.push({
id: `mcp-server-${serverName}`,
label: `${isFullySelected_0 ? figures.checkboxOn : figures.checkboxOff} ${serverName} (${serverTools.length} ${plural(serverTools.length, "tool")})`,
action: () => {
const toolNames_2 = serverTools.map(_temp7);
handleToggleTools(toolNames_2, !isFullySelected_0);
}
});
});
navigableItems.push({
id: "tools-header",
label: "Individual Tools:",
action: _temp8,
isHeader: true
});
}, [onCancel, onComplete, initialTools])
useKeybinding('confirm:no', handleCancel, { context: 'Confirmation' })
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'return') {
e.preventDefault()
const item = navigableItems[focusIndex]
if (item && !item.isHeader) {
item.action()
}
customAgentTools.forEach(tool_0 => {
let displayName = tool_0.name;
if (tool_0.name.startsWith("mcp__")) {
const mcpInfo = mcpInfoFromString(tool_0.name);
displayName = mcpInfo ? `${mcpInfo.toolName} (${mcpInfo.serverName})` : tool_0.name;
}
navigableItems.push({
id: `tool-${tool_0.name}`,
label: `${selectedSet.has(tool_0.name) ? figures.checkboxOn : figures.checkboxOff} ${displayName}`,
action: () => handleToggleTool(tool_0.name)
});
});
} else if (e.key === 'up') {
e.preventDefault()
let newIndex = focusIndex - 1
// Skip headers when navigating up
while (newIndex > 0 && navigableItems[newIndex]?.isHeader) {
newIndex--
}
setFocusIndex(Math.max(0, newIndex))
} else if (e.key === 'down') {
e.preventDefault()
let newIndex = focusIndex + 1
// Skip headers when navigating down
while (
newIndex < navigableItems.length - 1 &&
navigableItems[newIndex]?.isHeader
) {
newIndex++
}
setFocusIndex(Math.min(navigableItems.length - 1, newIndex))
}
$[24] = createBucketToggleAction;
$[25] = customAgentTools;
$[26] = focusIndex;
$[27] = handleConfirm;
$[28] = isAllSelected;
$[29] = selectedSet;
$[30] = showIndividualTools;
$[31] = toolsByBucket.edit;
$[32] = toolsByBucket.execution;
$[33] = toolsByBucket.mcp;
$[34] = toolsByBucket.other;
$[35] = toolsByBucket.readOnly;
$[36] = navigableItems;
} else {
navigableItems = $[36];
}
let t10;
if ($[44] !== initialTools || $[45] !== onCancel || $[46] !== onComplete) {
t10 = () => {
if (onCancel) {
onCancel();
} else {
onComplete(initialTools);
}
};
$[44] = initialTools;
$[45] = onCancel;
$[46] = onComplete;
$[47] = t10;
} else {
t10 = $[47];
}
const handleCancel = t10;
let t11;
if ($[48] === Symbol.for("react.memo_cache_sentinel")) {
t11 = {
context: "Confirmation"
};
$[48] = t11;
} else {
t11 = $[48];
}
useKeybinding("confirm:no", handleCancel, t11);
let t12;
if ($[49] !== focusIndex || $[50] !== navigableItems) {
t12 = e => {
if (e.key === "return") {
e.preventDefault();
const item = navigableItems[focusIndex];
if (item && !item.isHeader) {
item.action();
}
} else {
if (e.key === "up") {
e.preventDefault();
let newIndex = focusIndex - 1;
while (newIndex > 0 && navigableItems[newIndex]?.isHeader) {
newIndex--;
}
setFocusIndex(Math.max(0, newIndex));
} else {
if (e.key === "down") {
e.preventDefault();
let newIndex_0 = focusIndex + 1;
while (newIndex_0 < navigableItems.length - 1 && navigableItems[newIndex_0]?.isHeader) {
newIndex_0++;
}
setFocusIndex(Math.min(navigableItems.length - 1, newIndex_0));
}
}
}
};
$[49] = focusIndex;
$[50] = navigableItems;
$[51] = t12;
} else {
t12 = $[51];
}
const handleKeyDown = t12;
const t13 = focusIndex === 0 ? "suggestion" : undefined;
const t14 = focusIndex === 0;
const t15 = focusIndex === 0 ? `${figures.pointer} ` : " ";
let t16;
if ($[52] !== t13 || $[53] !== t14 || $[54] !== t15) {
t16 = <Text color={t13} bold={t14}>{t15}[ Continue ]</Text>;
$[52] = t13;
$[53] = t14;
$[54] = t15;
$[55] = t16;
} else {
t16 = $[55];
}
let t17;
if ($[56] === Symbol.for("react.memo_cache_sentinel")) {
t17 = <Divider width={40} />;
$[56] = t17;
} else {
t17 = $[56];
}
let t18;
if ($[57] !== navigableItems) {
t18 = navigableItems.slice(1);
$[57] = navigableItems;
$[58] = t18;
} else {
t18 = $[58];
}
let t19;
if ($[59] !== focusIndex || $[60] !== t18) {
t19 = t18.map((item_0, index) => {
const isCurrentlyFocused = index + 1 === focusIndex;
const isToggleButton = item_0.isToggle;
const isHeader = item_0.isHeader;
return <React.Fragment key={item_0.id}>{isToggleButton && <Divider width={40} />}{isHeader && index > 0 && <Box marginTop={1} />}<Text color={isHeader ? undefined : isCurrentlyFocused ? "suggestion" : undefined} dimColor={isHeader} bold={isToggleButton && isCurrentlyFocused}>{isHeader ? "" : isCurrentlyFocused ? `${figures.pointer} ` : " "}{isToggleButton ? `[ ${item_0.label} ]` : item_0.label}</Text></React.Fragment>;
});
$[59] = focusIndex;
$[60] = t18;
$[61] = t19;
} else {
t19 = $[61];
}
const t20 = isAllSelected ? "All tools selected" : `${selectedSet.size} of ${customAgentTools.length} tools selected`;
let t21;
if ($[62] !== t20) {
t21 = <Box marginTop={1} flexDirection="column"><Text dimColor={true}>{t20}</Text></Box>;
$[62] = t20;
$[63] = t21;
} else {
t21 = $[63];
}
let t22;
if ($[64] !== handleKeyDown || $[65] !== t16 || $[66] !== t19 || $[67] !== t21) {
t22 = <Box flexDirection="column" marginTop={1} tabIndex={0} autoFocus={true} onKeyDown={handleKeyDown}>{t16}{t17}{t19}{t21}</Box>;
$[64] = handleKeyDown;
$[65] = t16;
$[66] = t19;
$[67] = t21;
$[68] = t22;
} else {
t22 = $[68];
}
return t22;
}
function _temp8() {}
function _temp7(t_10) {
return t_10.name;
}
function _temp6() {}
function _temp5(t_7) {
return t_7.name;
}
function _temp4(t_6) {
return t_6.name;
}
function _temp3(t_4) {
return t_4.name;
}
function _temp2(t_0) {
return t_0.name;
}
function _temp(t) {
return t.name;
return (
<Box
flexDirection="column"
marginTop={1}
tabIndex={0}
autoFocus
onKeyDown={handleKeyDown}
>
{/* Render Continue button */}
<Text
color={focusIndex === 0 ? 'suggestion' : undefined}
bold={focusIndex === 0}
>
{focusIndex === 0 ? `${figures.pointer} ` : ' '}[ Continue ]
</Text>
{/* Separator */}
<Divider width={40} />
{/* Render all navigable items except Continue (which is at index 0) */}
{navigableItems.slice(1).map((item, index) => {
const isCurrentlyFocused = index + 1 === focusIndex
const isToggleButton = item.isToggle
const isHeader = item.isHeader
return (
<React.Fragment key={item.id}>
{/* Add separator before toggle button */}
{isToggleButton && <Divider width={40} />}
{/* Add margin before headers */}
{isHeader && index > 0 && <Box marginTop={1} />}
<Text
color={
isHeader
? undefined
: isCurrentlyFocused
? 'suggestion'
: undefined
}
dimColor={isHeader}
bold={isToggleButton && isCurrentlyFocused}
>
{isHeader
? ''
: isCurrentlyFocused
? `${figures.pointer} `
: ' '}
{isToggleButton ? `[ ${item.label} ]` : item.label}
</Text>
</React.Fragment>
)
})}
<Box marginTop={1} flexDirection="column">
<Text dimColor>
{isAllSelected
? 'All tools selected'
: `${selectedSet.size} of ${customAgentTools.length} tools selected`}
</Text>
</Box>
</Box>
)
}

View File

@@ -1,96 +1,68 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import { isAutoMemoryEnabled } from '../../../memdir/paths.js';
import type { Tools } from '../../../Tool.js';
import type { AgentDefinition } from '../../../tools/AgentTool/loadAgentsDir.js';
import { WizardProvider } from '../../wizard/index.js';
import type { WizardStepComponent } from '../../wizard/types.js';
import type { AgentWizardData } from './types.js';
import { ColorStep } from './wizard-steps/ColorStep.js';
import { ConfirmStepWrapper } from './wizard-steps/ConfirmStepWrapper.js';
import { DescriptionStep } from './wizard-steps/DescriptionStep.js';
import { GenerateStep } from './wizard-steps/GenerateStep.js';
import { LocationStep } from './wizard-steps/LocationStep.js';
import { MemoryStep } from './wizard-steps/MemoryStep.js';
import { MethodStep } from './wizard-steps/MethodStep.js';
import { ModelStep } from './wizard-steps/ModelStep.js';
import { PromptStep } from './wizard-steps/PromptStep.js';
import { ToolsStep } from './wizard-steps/ToolsStep.js';
import { TypeStep } from './wizard-steps/TypeStep.js';
import React, { type ReactNode } from 'react'
import { isAutoMemoryEnabled } from '../../../memdir/paths.js'
import type { Tools } from '../../../Tool.js'
import type { AgentDefinition } from '../../../tools/AgentTool/loadAgentsDir.js'
import { WizardProvider } from '../../wizard/index.js'
import type { WizardStepComponent } from '../../wizard/types.js'
import type { AgentWizardData } from './types.js'
import { ColorStep } from './wizard-steps/ColorStep.js'
import { ConfirmStepWrapper } from './wizard-steps/ConfirmStepWrapper.js'
import { DescriptionStep } from './wizard-steps/DescriptionStep.js'
import { GenerateStep } from './wizard-steps/GenerateStep.js'
import { LocationStep } from './wizard-steps/LocationStep.js'
import { MemoryStep } from './wizard-steps/MemoryStep.js'
import { MethodStep } from './wizard-steps/MethodStep.js'
import { ModelStep } from './wizard-steps/ModelStep.js'
import { PromptStep } from './wizard-steps/PromptStep.js'
import { ToolsStep } from './wizard-steps/ToolsStep.js'
import { TypeStep } from './wizard-steps/TypeStep.js'
type Props = {
tools: Tools;
existingAgents: AgentDefinition[];
onComplete: (message: string) => void;
onCancel: () => void;
};
export function CreateAgentWizard(t0) {
const $ = _c(17);
const {
tools,
existingAgents,
onComplete,
onCancel
} = t0;
let t1;
if ($[0] !== existingAgents) {
t1 = () => <TypeStep existingAgents={existingAgents} />;
$[0] = existingAgents;
$[1] = t1;
} else {
t1 = $[1];
}
let t2;
if ($[2] !== tools) {
t2 = () => <ToolsStep tools={tools} />;
$[2] = tools;
$[3] = t2;
} else {
t2 = $[3];
}
let t3;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t3 = isAutoMemoryEnabled() ? [MemoryStep] : [];
$[4] = t3;
} else {
t3 = $[4];
}
let t4;
if ($[5] !== existingAgents || $[6] !== onComplete || $[7] !== tools) {
t4 = () => <ConfirmStepWrapper tools={tools} existingAgents={existingAgents} onComplete={onComplete} />;
$[5] = existingAgents;
$[6] = onComplete;
$[7] = tools;
$[8] = t4;
} else {
t4 = $[8];
}
let t5;
if ($[9] !== t1 || $[10] !== t2 || $[11] !== t4) {
t5 = [LocationStep, MethodStep, GenerateStep, t1, PromptStep, DescriptionStep, t2, ModelStep, ColorStep, ...t3, t4];
$[9] = t1;
$[10] = t2;
$[11] = t4;
$[12] = t5;
} else {
t5 = $[12];
}
const steps = t5;
let t6;
if ($[13] === Symbol.for("react.memo_cache_sentinel")) {
t6 = {};
$[13] = t6;
} else {
t6 = $[13];
}
let t7;
if ($[14] !== onCancel || $[15] !== steps) {
t7 = <WizardProvider steps={steps} initialData={t6} onComplete={_temp} onCancel={onCancel} title="Create new agent" showStepCounter={false} />;
$[14] = onCancel;
$[15] = steps;
$[16] = t7;
} else {
t7 = $[16];
}
return t7;
tools: Tools
existingAgents: AgentDefinition[]
onComplete: (message: string) => void
onCancel: () => void
}
export function CreateAgentWizard({
tools,
existingAgents,
onComplete,
onCancel,
}: Props): ReactNode {
// Create step components with props
const steps: WizardStepComponent<AgentWizardData>[] = [
LocationStep, // 0
MethodStep, // 1
GenerateStep, // 2
() => <TypeStep existingAgents={existingAgents} />, // 3
PromptStep, // 4
DescriptionStep, // 5
() => <ToolsStep tools={tools} />, // 6
ModelStep, // 7
ColorStep, // 8
// MemoryStep is conditionally included based on GrowthBook gate
...(isAutoMemoryEnabled() ? [MemoryStep] : []),
() => (
<ConfirmStepWrapper
tools={tools}
existingAgents={existingAgents}
onComplete={onComplete}
/>
),
]
return (
<WizardProvider<AgentWizardData>
steps={steps}
initialData={{}}
onComplete={() => {
// Wizard completion is handled by ConfirmStepWrapper
// which calls onComplete with the appropriate message
}}
onCancel={onCancel}
title="Create new agent"
showStepCounter={false}
/>
)
}
function _temp() {}

View File

@@ -1,83 +1,64 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import { Box } from '../../../../ink.js';
import { useKeybinding } from '../../../../keybindings/useKeybinding.js';
import type { AgentColorName } from '../../../../tools/AgentTool/agentColorManager.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import { ColorPicker } from '../../ColorPicker.js';
import type { AgentWizardData } from '../types.js';
export function ColorStep() {
const $ = _c(14);
const {
goNext,
goBack,
updateWizardData,
wizardData
} = useWizard();
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {
context: "Confirmation"
};
$[0] = t0;
} else {
t0 = $[0];
import React, { type ReactNode } from 'react'
import { Box } from '../../../../ink.js'
import { useKeybinding } from '../../../../keybindings/useKeybinding.js'
import type { AgentColorName } from '../../../../tools/AgentTool/agentColorManager.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import { ColorPicker } from '../../ColorPicker.js'
import type { AgentWizardData } from '../types.js'
export function ColorStep(): ReactNode {
const { goNext, goBack, updateWizardData, wizardData } =
useWizard<AgentWizardData>()
// Handle escape key - ColorPicker handles its own escape internally
useKeybinding('confirm:no', goBack, { context: 'Confirmation' })
const handleConfirm = (color?: string): void => {
updateWizardData({
selectedColor: color,
// Prepare final agent for confirmation
finalAgent: {
agentType: wizardData.agentType!,
whenToUse: wizardData.whenToUse!,
getSystemPrompt: () => wizardData.systemPrompt!,
tools: wizardData.selectedTools,
...(wizardData.selectedModel
? { model: wizardData.selectedModel }
: {}),
...(color ? { color: color as AgentColorName } : {}),
source: wizardData.location!,
},
})
goNext()
}
useKeybinding("confirm:no", goBack, t0);
let t1;
if ($[1] !== goNext || $[2] !== updateWizardData || $[3] !== wizardData.agentType || $[4] !== wizardData.location || $[5] !== wizardData.selectedModel || $[6] !== wizardData.selectedTools || $[7] !== wizardData.systemPrompt || $[8] !== wizardData.whenToUse) {
t1 = color => {
updateWizardData({
selectedColor: color,
finalAgent: {
agentType: wizardData.agentType,
whenToUse: wizardData.whenToUse,
getSystemPrompt: () => wizardData.systemPrompt,
tools: wizardData.selectedTools,
...(wizardData.selectedModel ? {
model: wizardData.selectedModel
} : {}),
...(color ? {
color: color as AgentColorName
} : {}),
source: wizardData.location
}
});
goNext();
};
$[1] = goNext;
$[2] = updateWizardData;
$[3] = wizardData.agentType;
$[4] = wizardData.location;
$[5] = wizardData.selectedModel;
$[6] = wizardData.selectedTools;
$[7] = wizardData.systemPrompt;
$[8] = wizardData.whenToUse;
$[9] = t1;
} else {
t1 = $[9];
}
const handleConfirm = t1;
let t2;
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Byline><KeyboardShortcutHint shortcut={"\u2191\u2193"} action="navigate" /><KeyboardShortcutHint shortcut="Enter" action="select" /><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="go back" /></Byline>;
$[10] = t2;
} else {
t2 = $[10];
}
const t3 = wizardData.agentType || "agent";
let t4;
if ($[11] !== handleConfirm || $[12] !== t3) {
t4 = <WizardDialogLayout subtitle="Choose background color" footerText={t2}><Box><ColorPicker agentName={t3} currentColor="automatic" onConfirm={handleConfirm} /></Box></WizardDialogLayout>;
$[11] = handleConfirm;
$[12] = t3;
$[13] = t4;
} else {
t4 = $[13];
}
return t4;
return (
<WizardDialogLayout
subtitle="Choose background color"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="↑↓" action="navigate" />
<KeyboardShortcutHint shortcut="Enter" action="select" />
<ConfigurableShortcutHint
action="confirm:no"
context="Confirmation"
fallback="Esc"
description="go back"
/>
</Byline>
}
>
<Box>
<ColorPicker
agentName={wizardData.agentType || 'agent'}
currentColor="automatic"
onConfirm={handleConfirm}
/>
</Box>
</WizardDialogLayout>
)
}

View File

@@ -1,377 +1,168 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import type { KeyboardEvent } from '../../../../ink/events/keyboard-event.js';
import { Box, Text } from '../../../../ink.js';
import { useKeybinding } from '../../../../keybindings/useKeybinding.js';
import { isAutoMemoryEnabled } from '../../../../memdir/paths.js';
import type { Tools } from '../../../../Tool.js';
import { getMemoryScopeDisplay } from '../../../../tools/AgentTool/agentMemory.js';
import type { AgentDefinition } from '../../../../tools/AgentTool/loadAgentsDir.js';
import { truncateToWidth } from '../../../../utils/format.js';
import { getAgentModelDisplay } from '../../../../utils/model/agent.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import { getNewRelativeAgentFilePath } from '../../agentFileUtils.js';
import { validateAgent } from '../../validateAgent.js';
import type { AgentWizardData } from '../types.js';
import React, { type ReactNode } from 'react'
import type { KeyboardEvent } from '../../../../ink/events/keyboard-event.js'
import { Box, Text } from '../../../../ink.js'
import { useKeybinding } from '../../../../keybindings/useKeybinding.js'
import { isAutoMemoryEnabled } from '../../../../memdir/paths.js'
import type { Tools } from '../../../../Tool.js'
import { getMemoryScopeDisplay } from '../../../../tools/AgentTool/agentMemory.js'
import type { AgentDefinition } from '../../../../tools/AgentTool/loadAgentsDir.js'
import { truncateToWidth } from '../../../../utils/format.js'
import { getAgentModelDisplay } from '../../../../utils/model/agent.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import { getNewRelativeAgentFilePath } from '../../agentFileUtils.js'
import { validateAgent } from '../../validateAgent.js'
import type { AgentWizardData } from '../types.js'
type Props = {
tools: Tools;
existingAgents: AgentDefinition[];
onSave: () => void;
onSaveAndEdit: () => void;
error?: string | null;
};
export function ConfirmStep(t0) {
const $ = _c(88);
const {
tools,
existingAgents,
onSave,
onSaveAndEdit,
error
} = t0;
const {
goBack,
wizardData
} = useWizard();
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = {
context: "Confirmation"
};
$[0] = t1;
} else {
t1 = $[0];
tools: Tools
existingAgents: AgentDefinition[]
onSave: () => void
onSaveAndEdit: () => void
error?: string | null
}
export function ConfirmStep({
tools,
existingAgents,
onSave,
onSaveAndEdit,
error,
}: Props): ReactNode {
const { goBack, wizardData } = useWizard<AgentWizardData>()
useKeybinding('confirm:no', goBack, { context: 'Confirmation' })
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 's' || e.key === 'return') {
e.preventDefault()
onSave()
} else if (e.key === 'e') {
e.preventDefault()
onSaveAndEdit()
}
}
useKeybinding("confirm:no", goBack, t1);
let t2;
if ($[1] !== onSave || $[2] !== onSaveAndEdit) {
t2 = e => {
if (e.key === "s" || e.key === "return") {
e.preventDefault();
onSave();
} else {
if (e.key === "e") {
e.preventDefault();
onSaveAndEdit();
}
const agent = wizardData.finalAgent!
const validation = validateAgent(agent, tools, existingAgents)
const systemPromptPreview = truncateToWidth(agent.getSystemPrompt(), 240)
const whenToUsePreview = truncateToWidth(agent.whenToUse, 240)
const getToolsDisplay = (toolNames: string[] | undefined): string => {
// undefined means "all tools" per PR semantic
if (toolNames === undefined) return 'All tools'
if (toolNames.length === 0) return 'None'
if (toolNames.length === 1) return toolNames[0] || 'None'
if (toolNames.length === 2) return toolNames.join(' and ')
return `${toolNames.slice(0, -1).join(', ')}, and ${toolNames[toolNames.length - 1]}`
}
// Compute memory display outside JSX
const memoryDisplayElement = isAutoMemoryEnabled() ? (
<Text>
<Text bold>Memory</Text>: {getMemoryScopeDisplay(agent.memory)}
</Text>
) : null
return (
<WizardDialogLayout
subtitle="Confirm and save"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="s/Enter" action="save" />
<KeyboardShortcutHint shortcut="e" action="edit in your editor" />
<ConfigurableShortcutHint
action="confirm:no"
context="Confirmation"
fallback="Esc"
description="cancel"
/>
</Byline>
}
};
$[1] = onSave;
$[2] = onSaveAndEdit;
$[3] = t2;
} else {
t2 = $[3];
}
const handleKeyDown = t2;
const agent = wizardData.finalAgent;
let T0;
let T1;
let t10;
let t11;
let t12;
let t13;
let t14;
let t15;
let t16;
let t17;
let t18;
let t19;
let t3;
let t4;
let t5;
let t6;
let t7;
let t8;
let t9;
if ($[4] !== agent || $[5] !== existingAgents || $[6] !== handleKeyDown || $[7] !== tools || $[8] !== wizardData.location) {
const validation = validateAgent(agent, tools, existingAgents);
let t20;
if ($[28] !== agent) {
t20 = truncateToWidth(agent.getSystemPrompt(), 240);
$[28] = agent;
$[29] = t20;
} else {
t20 = $[29];
}
const systemPromptPreview = t20;
let t21;
if ($[30] !== agent.whenToUse) {
t21 = truncateToWidth(agent.whenToUse, 240);
$[30] = agent.whenToUse;
$[31] = t21;
} else {
t21 = $[31];
}
const whenToUsePreview = t21;
const getToolsDisplay = _temp;
let t22;
if ($[32] !== agent.memory) {
t22 = isAutoMemoryEnabled() ? <Text><Text bold={true}>Memory</Text>: {getMemoryScopeDisplay(agent.memory)}</Text> : null;
$[32] = agent.memory;
$[33] = t22;
} else {
t22 = $[33];
}
const memoryDisplayElement = t22;
T1 = WizardDialogLayout;
t18 = "Confirm and save";
if ($[34] === Symbol.for("react.memo_cache_sentinel")) {
t19 = <Byline><KeyboardShortcutHint shortcut="s/Enter" action="save" /><KeyboardShortcutHint shortcut="e" action="edit in your editor" /><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="cancel" /></Byline>;
$[34] = t19;
} else {
t19 = $[34];
}
T0 = Box;
t3 = "column";
t4 = 0;
t5 = true;
t6 = handleKeyDown;
let t23;
if ($[35] === Symbol.for("react.memo_cache_sentinel")) {
t23 = <Text bold={true}>Name</Text>;
$[35] = t23;
} else {
t23 = $[35];
}
if ($[36] !== agent.agentType) {
t7 = <Text>{t23}: {agent.agentType}</Text>;
$[36] = agent.agentType;
$[37] = t7;
} else {
t7 = $[37];
}
let t24;
if ($[38] === Symbol.for("react.memo_cache_sentinel")) {
t24 = <Text bold={true}>Location</Text>;
$[38] = t24;
} else {
t24 = $[38];
}
let t25;
if ($[39] !== agent.agentType || $[40] !== wizardData.location) {
t25 = getNewRelativeAgentFilePath({
source: wizardData.location,
agentType: agent.agentType
});
$[39] = agent.agentType;
$[40] = wizardData.location;
$[41] = t25;
} else {
t25 = $[41];
}
if ($[42] !== t25) {
t8 = <Text>{t24}:{" "}{t25}</Text>;
$[42] = t25;
$[43] = t8;
} else {
t8 = $[43];
}
let t26;
if ($[44] === Symbol.for("react.memo_cache_sentinel")) {
t26 = <Text bold={true}>Tools</Text>;
$[44] = t26;
} else {
t26 = $[44];
}
let t27;
if ($[45] !== agent.tools) {
t27 = getToolsDisplay(agent.tools);
$[45] = agent.tools;
$[46] = t27;
} else {
t27 = $[46];
}
if ($[47] !== t27) {
t9 = <Text>{t26}: {t27}</Text>;
$[47] = t27;
$[48] = t9;
} else {
t9 = $[48];
}
let t28;
if ($[49] === Symbol.for("react.memo_cache_sentinel")) {
t28 = <Text bold={true}>Model</Text>;
$[49] = t28;
} else {
t28 = $[49];
}
let t29;
if ($[50] !== agent.model) {
t29 = getAgentModelDisplay(agent.model);
$[50] = agent.model;
$[51] = t29;
} else {
t29 = $[51];
}
if ($[52] !== t29) {
t10 = <Text>{t28}: {t29}</Text>;
$[52] = t29;
$[53] = t10;
} else {
t10 = $[53];
}
t11 = memoryDisplayElement;
if ($[54] === Symbol.for("react.memo_cache_sentinel")) {
t12 = <Box marginTop={1}><Text><Text bold={true}>Description</Text> (tells Claude when to use this agent):</Text></Box>;
$[54] = t12;
} else {
t12 = $[54];
}
if ($[55] !== whenToUsePreview) {
t13 = <Box marginLeft={2} marginTop={1}><Text>{whenToUsePreview}</Text></Box>;
$[55] = whenToUsePreview;
$[56] = t13;
} else {
t13 = $[56];
}
if ($[57] === Symbol.for("react.memo_cache_sentinel")) {
t14 = <Box marginTop={1}><Text><Text bold={true}>System prompt</Text>:</Text></Box>;
$[57] = t14;
} else {
t14 = $[57];
}
if ($[58] !== systemPromptPreview) {
t15 = <Box marginLeft={2} marginTop={1}><Text>{systemPromptPreview}</Text></Box>;
$[58] = systemPromptPreview;
$[59] = t15;
} else {
t15 = $[59];
}
t16 = validation.warnings.length > 0 && <Box marginTop={1} flexDirection="column"><Text color="warning">Warnings:</Text>{validation.warnings.map(_temp2)}</Box>;
t17 = validation.errors.length > 0 && <Box marginTop={1} flexDirection="column"><Text color="error">Errors:</Text>{validation.errors.map(_temp3)}</Box>;
$[4] = agent;
$[5] = existingAgents;
$[6] = handleKeyDown;
$[7] = tools;
$[8] = wizardData.location;
$[9] = T0;
$[10] = T1;
$[11] = t10;
$[12] = t11;
$[13] = t12;
$[14] = t13;
$[15] = t14;
$[16] = t15;
$[17] = t16;
$[18] = t17;
$[19] = t18;
$[20] = t19;
$[21] = t3;
$[22] = t4;
$[23] = t5;
$[24] = t6;
$[25] = t7;
$[26] = t8;
$[27] = t9;
} else {
T0 = $[9];
T1 = $[10];
t10 = $[11];
t11 = $[12];
t12 = $[13];
t13 = $[14];
t14 = $[15];
t15 = $[16];
t16 = $[17];
t17 = $[18];
t18 = $[19];
t19 = $[20];
t3 = $[21];
t4 = $[22];
t5 = $[23];
t6 = $[24];
t7 = $[25];
t8 = $[26];
t9 = $[27];
}
let t20;
if ($[60] !== error) {
t20 = error && <Box marginTop={1}><Text color="error">{error}</Text></Box>;
$[60] = error;
$[61] = t20;
} else {
t20 = $[61];
}
let t21;
if ($[62] === Symbol.for("react.memo_cache_sentinel")) {
t21 = <Text bold={true}>s</Text>;
$[62] = t21;
} else {
t21 = $[62];
}
let t22;
if ($[63] === Symbol.for("react.memo_cache_sentinel")) {
t22 = <Text bold={true}>Enter</Text>;
$[63] = t22;
} else {
t22 = $[63];
}
let t23;
if ($[64] === Symbol.for("react.memo_cache_sentinel")) {
t23 = <Box marginTop={2}><Text color="success">Press {t21} or {t22} to save,{" "}<Text bold={true}>e</Text> to save and edit</Text></Box>;
$[64] = t23;
} else {
t23 = $[64];
}
let t24;
if ($[65] !== T0 || $[66] !== t10 || $[67] !== t11 || $[68] !== t12 || $[69] !== t13 || $[70] !== t14 || $[71] !== t15 || $[72] !== t16 || $[73] !== t17 || $[74] !== t20 || $[75] !== t3 || $[76] !== t4 || $[77] !== t5 || $[78] !== t6 || $[79] !== t7 || $[80] !== t8 || $[81] !== t9) {
t24 = <T0 flexDirection={t3} tabIndex={t4} autoFocus={t5} onKeyDown={t6}>{t7}{t8}{t9}{t10}{t11}{t12}{t13}{t14}{t15}{t16}{t17}{t20}{t23}</T0>;
$[65] = T0;
$[66] = t10;
$[67] = t11;
$[68] = t12;
$[69] = t13;
$[70] = t14;
$[71] = t15;
$[72] = t16;
$[73] = t17;
$[74] = t20;
$[75] = t3;
$[76] = t4;
$[77] = t5;
$[78] = t6;
$[79] = t7;
$[80] = t8;
$[81] = t9;
$[82] = t24;
} else {
t24 = $[82];
}
let t25;
if ($[83] !== T1 || $[84] !== t18 || $[85] !== t19 || $[86] !== t24) {
t25 = <T1 subtitle={t18} footerText={t19}>{t24}</T1>;
$[83] = T1;
$[84] = t18;
$[85] = t19;
$[86] = t24;
$[87] = t25;
} else {
t25 = $[87];
}
return t25;
}
function _temp3(err, i_0) {
return <Text key={i_0} color="error">{" "} {err}</Text>;
}
function _temp2(warning, i) {
return <Text key={i} dimColor={true}>{" "} {warning}</Text>;
}
function _temp(toolNames) {
if (toolNames === undefined) {
return "All tools";
}
if (toolNames.length === 0) {
return "None";
}
if (toolNames.length === 1) {
return toolNames[0] || "None";
}
if (toolNames.length === 2) {
return toolNames.join(" and ");
}
return `${toolNames.slice(0, -1).join(", ")}, and ${toolNames[toolNames.length - 1]}`;
>
<Box
flexDirection="column"
tabIndex={0}
autoFocus
onKeyDown={handleKeyDown}
>
<Text>
<Text bold>Name</Text>: {agent.agentType}
</Text>
<Text>
<Text bold>Location</Text>:{' '}
{getNewRelativeAgentFilePath({
source: wizardData.location!,
agentType: agent.agentType,
})}
</Text>
<Text>
<Text bold>Tools</Text>: {getToolsDisplay(agent.tools)}
</Text>
<Text>
<Text bold>Model</Text>: {getAgentModelDisplay(agent.model)}
</Text>
{memoryDisplayElement}
<Box marginTop={1}>
<Text>
<Text bold>Description</Text> (tells Claude when to use this agent):
</Text>
</Box>
<Box marginLeft={2} marginTop={1}>
<Text>{whenToUsePreview}</Text>
</Box>
<Box marginTop={1}>
<Text>
<Text bold>System prompt</Text>:
</Text>
</Box>
<Box marginLeft={2} marginTop={1}>
<Text>{systemPromptPreview}</Text>
</Box>
{validation.warnings.length > 0 && (
<Box marginTop={1} flexDirection="column">
<Text color="warning">Warnings:</Text>
{validation.warnings.map((warning, i) => (
<Text key={i} dimColor>
{' '}
{warning}
</Text>
))}
</Box>
)}
{validation.errors.length > 0 && (
<Box marginTop={1} flexDirection="column">
<Text color="error">Errors:</Text>
{validation.errors.map((err, i) => (
<Text key={i} color="error">
{' '}
{err}
</Text>
))}
</Box>
)}
{error && (
<Box marginTop={1}>
<Text color="error">{error}</Text>
</Box>
)}
<Box marginTop={2}>
<Text color="success">
Press <Text bold>s</Text> or <Text bold>Enter</Text> to save,{' '}
<Text bold>e</Text> to save and edit
</Text>
</Box>
</Box>
</WizardDialogLayout>
)
}

View File

@@ -1,73 +1,112 @@
import chalk from 'chalk';
import React, { type ReactNode, useCallback, useState } from 'react';
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js';
import { useSetAppState } from 'src/state/AppState.js';
import type { Tools } from '../../../../Tool.js';
import type { AgentDefinition } from '../../../../tools/AgentTool/loadAgentsDir.js';
import { getActiveAgentsFromList } from '../../../../tools/AgentTool/loadAgentsDir.js';
import { editFileInEditor } from '../../../../utils/promptEditor.js';
import { useWizard } from '../../../wizard/index.js';
import { getNewAgentFilePath, saveAgentToFile } from '../../agentFileUtils.js';
import type { AgentWizardData } from '../types.js';
import { ConfirmStep } from './ConfirmStep.js';
import chalk from 'chalk'
import React, { type ReactNode, useCallback, useState } from 'react'
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
} from 'src/services/analytics/index.js'
import { useSetAppState } from 'src/state/AppState.js'
import type { Tools } from '../../../../Tool.js'
import type { AgentDefinition } from '../../../../tools/AgentTool/loadAgentsDir.js'
import { getActiveAgentsFromList } from '../../../../tools/AgentTool/loadAgentsDir.js'
import { editFileInEditor } from '../../../../utils/promptEditor.js'
import { useWizard } from '../../../wizard/index.js'
import { getNewAgentFilePath, saveAgentToFile } from '../../agentFileUtils.js'
import type { AgentWizardData } from '../types.js'
import { ConfirmStep } from './ConfirmStep.js'
type Props = {
tools: Tools;
existingAgents: AgentDefinition[];
onComplete: (message: string) => void;
};
tools: Tools
existingAgents: AgentDefinition[]
onComplete: (message: string) => void
}
export function ConfirmStepWrapper({
tools,
existingAgents,
onComplete
onComplete,
}: Props): ReactNode {
const {
wizardData
} = useWizard<AgentWizardData>();
const [saveError, setSaveError] = useState<string | null>(null);
const setAppState = useSetAppState();
const saveAgent = useCallback(async (openInEditor: boolean): Promise<void> => {
if (!wizardData?.finalAgent) return;
try {
await saveAgentToFile(wizardData.location!, wizardData.finalAgent.agentType, wizardData.finalAgent.whenToUse, wizardData.finalAgent.tools, wizardData.finalAgent.getSystemPrompt(), true, wizardData.finalAgent.color, wizardData.finalAgent.model, wizardData.finalAgent.memory);
setAppState(state => {
if (!wizardData.finalAgent) return state;
const allAgents = state.agentDefinitions.allAgents.concat(wizardData.finalAgent);
return {
...state,
agentDefinitions: {
...state.agentDefinitions,
activeAgents: getActiveAgentsFromList(allAgents),
allAgents
const { wizardData } = useWizard<AgentWizardData>()
const [saveError, setSaveError] = useState<string | null>(null)
const setAppState = useSetAppState()
const saveAgent = useCallback(
async (openInEditor: boolean): Promise<void> => {
if (!wizardData?.finalAgent) return
try {
await saveAgentToFile(
wizardData.location!,
wizardData.finalAgent.agentType,
wizardData.finalAgent.whenToUse,
wizardData.finalAgent.tools,
wizardData.finalAgent.getSystemPrompt(),
true,
wizardData.finalAgent.color,
wizardData.finalAgent.model,
wizardData.finalAgent.memory,
)
setAppState(state => {
if (!wizardData.finalAgent) return state
const allAgents = state.agentDefinitions.allAgents.concat(
wizardData.finalAgent,
)
return {
...state,
agentDefinitions: {
...state.agentDefinitions,
activeAgents: getActiveAgentsFromList(allAgents),
allAgents,
},
}
};
});
if (openInEditor) {
const filePath = getNewAgentFilePath({
})
if (openInEditor) {
const filePath = getNewAgentFilePath({
source: wizardData.location!,
agentType: wizardData.finalAgent.agentType,
})
await editFileInEditor(filePath)
}
logEvent('tengu_agent_created', {
agent_type: wizardData.finalAgent.agentType,
generation_method: wizardData.wasGenerated ? 'generated' : 'manual',
source: wizardData.location!,
agentType: wizardData.finalAgent.agentType
});
await editFileInEditor(filePath);
tool_count: wizardData.finalAgent.tools?.length ?? 'all',
has_custom_model: !!wizardData.finalAgent.model,
has_custom_color: !!wizardData.finalAgent.color,
has_memory: !!wizardData.finalAgent.memory,
memory_scope: wizardData.finalAgent.memory ?? 'none',
...(openInEditor ? { opened_in_editor: true } : {}),
} as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS)
const message = openInEditor
? `Created agent: ${chalk.bold(wizardData.finalAgent.agentType)} and opened in editor. ` +
`If you made edits, restart to load the latest version.`
: `Created agent: ${chalk.bold(wizardData.finalAgent.agentType)}`
onComplete(message)
} catch (err) {
setSaveError(
err instanceof Error ? err.message : 'Failed to save agent',
)
}
logEvent('tengu_agent_created', {
agent_type: wizardData.finalAgent.agentType,
generation_method: wizardData.wasGenerated ? 'generated' : 'manual',
source: wizardData.location!,
tool_count: wizardData.finalAgent.tools?.length ?? 'all',
has_custom_model: !!wizardData.finalAgent.model,
has_custom_color: !!wizardData.finalAgent.color,
has_memory: !!wizardData.finalAgent.memory,
memory_scope: wizardData.finalAgent.memory ?? 'none',
...(openInEditor ? {
opened_in_editor: true
} : {})
} as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS);
const message = openInEditor ? `Created agent: ${chalk.bold(wizardData.finalAgent.agentType)} and opened in editor. ` + `If you made edits, restart to load the latest version.` : `Created agent: ${chalk.bold(wizardData.finalAgent.agentType)}`;
onComplete(message);
} catch (err) {
setSaveError(err instanceof Error ? err.message : 'Failed to save agent');
}
}, [wizardData, onComplete, setAppState]);
const handleSave = useCallback(() => saveAgent(false), [saveAgent]);
const handleSaveAndEdit = useCallback(() => saveAgent(true), [saveAgent]);
return <ConfirmStep tools={tools} existingAgents={existingAgents} onSave={handleSave} onSaveAndEdit={handleSaveAndEdit} error={saveError} />;
},
[wizardData, onComplete, setAppState],
)
const handleSave = useCallback(() => saveAgent(false), [saveAgent])
const handleSaveAndEdit = useCallback(() => saveAgent(true), [saveAgent])
return (
<ConfirmStep
tools={tools}
existingAgents={existingAgents}
onSave={handleSave}
onSaveAndEdit={handleSaveAndEdit}
error={saveError}
/>
)
}

View File

@@ -1,122 +1,94 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode, useCallback, useState } from 'react';
import { Box, Text } from '../../../../ink.js';
import { useKeybinding } from '../../../../keybindings/useKeybinding.js';
import { editPromptInEditor } from '../../../../utils/promptEditor.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import TextInput from '../../../TextInput.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import type { AgentWizardData } from '../types.js';
export function DescriptionStep() {
const $ = _c(18);
const {
goNext,
goBack,
updateWizardData,
wizardData
} = useWizard();
const [whenToUse, setWhenToUse] = useState(wizardData.whenToUse || "");
const [cursorOffset, setCursorOffset] = useState(whenToUse.length);
const [error, setError] = useState(null);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {
context: "Settings"
};
$[0] = t0;
} else {
t0 = $[0];
import React, { type ReactNode, useCallback, useState } from 'react'
import { Box, Text } from '../../../../ink.js'
import { useKeybinding } from '../../../../keybindings/useKeybinding.js'
import { editPromptInEditor } from '../../../../utils/promptEditor.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import TextInput from '../../../TextInput.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import type { AgentWizardData } from '../types.js'
export function DescriptionStep(): ReactNode {
const { goNext, goBack, updateWizardData, wizardData } =
useWizard<AgentWizardData>()
const [whenToUse, setWhenToUse] = useState(wizardData.whenToUse || '')
const [cursorOffset, setCursorOffset] = useState(whenToUse.length)
const [error, setError] = useState<string | null>(null)
// Handle escape key - use Settings context so 'n' key doesn't cancel (allows typing 'n' in input)
useKeybinding('confirm:no', goBack, { context: 'Settings' })
const handleExternalEditor = useCallback(async () => {
const result = await editPromptInEditor(whenToUse)
if (result.content !== null) {
setWhenToUse(result.content)
setCursorOffset(result.content.length)
}
}, [whenToUse])
useKeybinding('chat:externalEditor', handleExternalEditor, {
context: 'Chat',
})
const handleSubmit = (value: string): void => {
const trimmedValue = value.trim()
if (!trimmedValue) {
setError('Description is required')
return
}
setError(null)
updateWizardData({ whenToUse: trimmedValue })
goNext()
}
useKeybinding("confirm:no", goBack, t0);
let t1;
if ($[1] !== whenToUse) {
t1 = async () => {
const result = await editPromptInEditor(whenToUse);
if (result.content !== null) {
setWhenToUse(result.content);
setCursorOffset(result.content.length);
return (
<WizardDialogLayout
subtitle="Description (tell Claude when to use this agent)"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="Type" action="enter text" />
<KeyboardShortcutHint shortcut="Enter" action="continue" />
<ConfigurableShortcutHint
action="chat:externalEditor"
context="Chat"
fallback="ctrl+g"
description="open in editor"
/>
<ConfigurableShortcutHint
action="confirm:no"
context="Settings"
fallback="Esc"
description="go back"
/>
</Byline>
}
};
$[1] = whenToUse;
$[2] = t1;
} else {
t1 = $[2];
}
const handleExternalEditor = t1;
let t2;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t2 = {
context: "Chat"
};
$[3] = t2;
} else {
t2 = $[3];
}
useKeybinding("chat:externalEditor", handleExternalEditor, t2);
let t3;
if ($[4] !== goNext || $[5] !== updateWizardData) {
t3 = value => {
const trimmedValue = value.trim();
if (!trimmedValue) {
setError("Description is required");
return;
}
setError(null);
updateWizardData({
whenToUse: trimmedValue
});
goNext();
};
$[4] = goNext;
$[5] = updateWizardData;
$[6] = t3;
} else {
t3 = $[6];
}
const handleSubmit = t3;
let t4;
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
t4 = <Byline><KeyboardShortcutHint shortcut="Type" action="enter text" /><KeyboardShortcutHint shortcut="Enter" action="continue" /><ConfigurableShortcutHint action="chat:externalEditor" context="Chat" fallback="ctrl+g" description="open in editor" /><ConfigurableShortcutHint action="confirm:no" context="Settings" fallback="Esc" description="go back" /></Byline>;
$[7] = t4;
} else {
t4 = $[7];
}
let t5;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t5 = <Text>When should Claude use this agent?</Text>;
$[8] = t5;
} else {
t5 = $[8];
}
let t6;
if ($[9] !== cursorOffset || $[10] !== handleSubmit || $[11] !== whenToUse) {
t6 = <Box marginTop={1}><TextInput value={whenToUse} onChange={setWhenToUse} onSubmit={handleSubmit} placeholder="e.g., use this agent after you're done writing code..." columns={80} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} focus={true} showCursor={true} /></Box>;
$[9] = cursorOffset;
$[10] = handleSubmit;
$[11] = whenToUse;
$[12] = t6;
} else {
t6 = $[12];
}
let t7;
if ($[13] !== error) {
t7 = error && <Box marginTop={1}><Text color="error">{error}</Text></Box>;
$[13] = error;
$[14] = t7;
} else {
t7 = $[14];
}
let t8;
if ($[15] !== t6 || $[16] !== t7) {
t8 = <WizardDialogLayout subtitle="Description (tell Claude when to use this agent)" footerText={t4}><Box flexDirection="column">{t5}{t6}{t7}</Box></WizardDialogLayout>;
$[15] = t6;
$[16] = t7;
$[17] = t8;
} else {
t8 = $[17];
}
return t8;
>
<Box flexDirection="column">
<Text>When should Claude use this agent?</Text>
<Box marginTop={1}>
<TextInput
value={whenToUse}
onChange={setWhenToUse}
onSubmit={handleSubmit}
placeholder="e.g., use this agent after you're done writing code..."
columns={80}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
focus
showCursor
/>
</Box>
{error && (
<Box marginTop={1}>
<Text color="error">{error}</Text>
</Box>
)}
</Box>
</WizardDialogLayout>
)
}

View File

@@ -1,58 +1,57 @@
import { APIUserAbortError } from '@anthropic-ai/sdk';
import React, { type ReactNode, useCallback, useRef, useState } from 'react';
import { useMainLoopModel } from '../../../../hooks/useMainLoopModel.js';
import { Box, Text } from '../../../../ink.js';
import { useKeybinding } from '../../../../keybindings/useKeybinding.js';
import { createAbortController } from '../../../../utils/abortController.js';
import { editPromptInEditor } from '../../../../utils/promptEditor.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { Spinner } from '../../../Spinner.js';
import TextInput from '../../../TextInput.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import { generateAgent } from '../../generateAgent.js';
import type { AgentWizardData } from '../types.js';
import { APIUserAbortError } from '@anthropic-ai/sdk'
import React, { type ReactNode, useCallback, useRef, useState } from 'react'
import { useMainLoopModel } from '../../../../hooks/useMainLoopModel.js'
import { Box, Text } from '../../../../ink.js'
import { useKeybinding } from '../../../../keybindings/useKeybinding.js'
import { createAbortController } from '../../../../utils/abortController.js'
import { editPromptInEditor } from '../../../../utils/promptEditor.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { Spinner } from '../../../Spinner.js'
import TextInput from '../../../TextInput.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import { generateAgent } from '../../generateAgent.js'
import type { AgentWizardData } from '../types.js'
export function GenerateStep(): ReactNode {
const {
updateWizardData,
goBack,
goToStep,
wizardData
} = useWizard<AgentWizardData>();
const [prompt, setPrompt] = useState(wizardData.generationPrompt || '');
const [isGenerating, setIsGenerating] = useState(false);
const [error, setError] = useState<string | null>(null);
const [cursorOffset, setCursorOffset] = useState(prompt.length);
const model = useMainLoopModel();
const abortControllerRef = useRef<AbortController | null>(null);
const { updateWizardData, goBack, goToStep, wizardData } =
useWizard<AgentWizardData>()
const [prompt, setPrompt] = useState(wizardData.generationPrompt || '')
const [isGenerating, setIsGenerating] = useState(false)
const [error, setError] = useState<string | null>(null)
const [cursorOffset, setCursorOffset] = useState(prompt.length)
const model = useMainLoopModel()
const abortControllerRef = useRef<AbortController | null>(null)
// Cancel generation when escape pressed during generation
const handleCancelGeneration = useCallback(() => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
abortControllerRef.current = null;
setIsGenerating(false);
setError('Generation cancelled');
abortControllerRef.current.abort()
abortControllerRef.current = null
setIsGenerating(false)
setError('Generation cancelled')
}
}, []);
}, [])
// Use Settings context so 'n' key doesn't cancel (allows typing 'n' in prompt input)
useKeybinding('confirm:no', handleCancelGeneration, {
context: 'Settings',
isActive: isGenerating
});
isActive: isGenerating,
})
const handleExternalEditor = useCallback(async () => {
const result = await editPromptInEditor(prompt);
const result = await editPromptInEditor(prompt)
if (result.content !== null) {
setPrompt(result.content);
setCursorOffset(result.content.length);
setPrompt(result.content)
setCursorOffset(result.content.length)
}
}, [prompt]);
}, [prompt])
useKeybinding('chat:externalEditor', handleExternalEditor, {
context: 'Chat',
isActive: !isGenerating
});
isActive: !isGenerating,
})
// Go back when escape pressed while not generating
const handleGoBack = useCallback(() => {
@@ -62,81 +61,141 @@ export function GenerateStep(): ReactNode {
systemPrompt: '',
whenToUse: '',
generatedAgent: undefined,
wasGenerated: false
});
setPrompt('');
setError(null);
goBack();
}, [updateWizardData, goBack]);
wasGenerated: false,
})
setPrompt('')
setError(null)
goBack()
}, [updateWizardData, goBack])
// Use Settings context so 'n' key doesn't cancel (allows typing 'n' in prompt input)
useKeybinding('confirm:no', handleGoBack, {
context: 'Settings',
isActive: !isGenerating
});
isActive: !isGenerating,
})
const handleGenerate = async (): Promise<void> => {
const trimmedPrompt = prompt.trim();
const trimmedPrompt = prompt.trim()
if (!trimmedPrompt) {
setError('Please describe what the agent should do');
return;
setError('Please describe what the agent should do')
return
}
setError(null);
setIsGenerating(true);
setError(null)
setIsGenerating(true)
updateWizardData({
generationPrompt: trimmedPrompt,
isGenerating: true
});
isGenerating: true,
})
// Create abort controller for this generation
const controller = createAbortController();
abortControllerRef.current = controller;
const controller = createAbortController()
abortControllerRef.current = controller
try {
const generated = await generateAgent(trimmedPrompt, model, [], controller.signal);
const generated = await generateAgent(
trimmedPrompt,
model,
[],
controller.signal,
)
updateWizardData({
agentType: generated.identifier,
whenToUse: generated.whenToUse,
systemPrompt: generated.systemPrompt,
generatedAgent: generated,
isGenerating: false,
wasGenerated: true
});
wasGenerated: true,
})
// Skip directly to ToolsStep (index 6) - matching original flow
goToStep(6);
goToStep(6)
} catch (err) {
// Don't show error if it was cancelled (already set in escape handler)
if (err instanceof APIUserAbortError) {
// User cancelled - no error to show
} else if (err instanceof Error && !err.message.includes('No assistant message found')) {
setError(err.message || 'Failed to generate agent');
} else if (
err instanceof Error &&
!err.message.includes('No assistant message found')
) {
setError(err.message || 'Failed to generate agent')
}
updateWizardData({
isGenerating: false
});
updateWizardData({ isGenerating: false })
} finally {
setIsGenerating(false);
abortControllerRef.current = null;
setIsGenerating(false)
abortControllerRef.current = null
}
};
const subtitle = 'Describe what this agent should do and when it should be used (be comprehensive for best results)';
}
const subtitle =
'Describe what this agent should do and when it should be used (be comprehensive for best results)'
if (isGenerating) {
return <WizardDialogLayout subtitle={subtitle} footerText={<ConfigurableShortcutHint action="confirm:no" context="Settings" fallback="Esc" description="cancel" />}>
return (
<WizardDialogLayout
subtitle={subtitle}
footerText={
<ConfigurableShortcutHint
action="confirm:no"
context="Settings"
fallback="Esc"
description="cancel"
/>
}
>
<Box flexDirection="row" alignItems="center">
<Spinner />
<Text color="suggestion"> Generating agent from description...</Text>
</Box>
</WizardDialogLayout>;
</WizardDialogLayout>
)
}
return <WizardDialogLayout subtitle={subtitle} footerText={<Byline>
<ConfigurableShortcutHint action="confirm:yes" context="Confirmation" fallback="Enter" description="submit" />
<ConfigurableShortcutHint action="chat:externalEditor" context="Chat" fallback="ctrl+g" description="open in editor" />
<ConfigurableShortcutHint action="confirm:no" context="Settings" fallback="Esc" description="go back" />
</Byline>}>
return (
<WizardDialogLayout
subtitle={subtitle}
footerText={
<Byline>
<ConfigurableShortcutHint
action="confirm:yes"
context="Confirmation"
fallback="Enter"
description="submit"
/>
<ConfigurableShortcutHint
action="chat:externalEditor"
context="Chat"
fallback="ctrl+g"
description="open in editor"
/>
<ConfigurableShortcutHint
action="confirm:no"
context="Settings"
fallback="Esc"
description="go back"
/>
</Byline>
}
>
<Box flexDirection="column">
{error && <Box marginBottom={1}>
{error && (
<Box marginBottom={1}>
<Text color="error">{error}</Text>
</Box>}
<TextInput value={prompt} onChange={setPrompt} onSubmit={handleGenerate} placeholder="e.g., Help me write unit tests for my code..." columns={80} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} focus showCursor />
</Box>
)}
<TextInput
value={prompt}
onChange={setPrompt}
onSubmit={handleGenerate}
placeholder="e.g., Help me write unit tests for my code..."
columns={80}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
focus
showCursor
/>
</Box>
</WizardDialogLayout>;
</WizardDialogLayout>
)
}

View File

@@ -1,79 +1,55 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import { Box } from '../../../../ink.js';
import type { SettingSource } from '../../../../utils/settings/constants.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Select } from '../../../CustomSelect/select.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import type { AgentWizardData } from '../types.js';
export function LocationStep() {
const $ = _c(11);
const {
goNext,
updateWizardData,
cancel
} = useWizard();
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {
label: "Project (.claude/agents/)",
value: "projectSettings" as SettingSource
};
$[0] = t0;
} else {
t0 = $[0];
}
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = [t0, {
label: "Personal (~/.claude/agents/)",
value: "userSettings" as SettingSource
}];
$[1] = t1;
} else {
t1 = $[1];
}
const locationOptions = t1;
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Byline><KeyboardShortcutHint shortcut={"\u2191\u2193"} action="navigate" /><KeyboardShortcutHint shortcut="Enter" action="select" /><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="cancel" /></Byline>;
$[2] = t2;
} else {
t2 = $[2];
}
let t3;
if ($[3] !== goNext || $[4] !== updateWizardData) {
t3 = value => {
updateWizardData({
location: value as SettingSource
});
goNext();
};
$[3] = goNext;
$[4] = updateWizardData;
$[5] = t3;
} else {
t3 = $[5];
}
let t4;
if ($[6] !== cancel) {
t4 = () => cancel();
$[6] = cancel;
$[7] = t4;
} else {
t4 = $[7];
}
let t5;
if ($[8] !== t3 || $[9] !== t4) {
t5 = <WizardDialogLayout subtitle="Choose location" footerText={t2}><Box><Select key="location-select" options={locationOptions} onChange={t3} onCancel={t4} /></Box></WizardDialogLayout>;
$[8] = t3;
$[9] = t4;
$[10] = t5;
} else {
t5 = $[10];
}
return t5;
import React, { type ReactNode } from 'react'
import { Box } from '../../../../ink.js'
import type { SettingSource } from '../../../../utils/settings/constants.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Select } from '../../../CustomSelect/select.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import type { AgentWizardData } from '../types.js'
export function LocationStep(): ReactNode {
const { goNext, updateWizardData, cancel } = useWizard<AgentWizardData>()
const locationOptions = [
{
label: 'Project (.claude/agents/)',
value: 'projectSettings' as SettingSource,
},
{
label: 'Personal (~/.claude/agents/)',
value: 'userSettings' as SettingSource,
},
]
return (
<WizardDialogLayout
subtitle="Choose location"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="↑↓" action="navigate" />
<KeyboardShortcutHint shortcut="Enter" action="select" />
<ConfigurableShortcutHint
action="confirm:no"
context="Confirmation"
fallback="Esc"
description="cancel"
/>
</Byline>
}
>
<Box>
<Select
key="location-select"
options={locationOptions}
onChange={(value: string) => {
updateWizardData({ location: value as SettingSource })
goNext()
}}
onCancel={() => cancel()}
/>
</Box>
</WizardDialogLayout>
)
}

View File

@@ -1,112 +1,102 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import { Box } from '../../../../ink.js';
import { useKeybinding } from '../../../../keybindings/useKeybinding.js';
import { isAutoMemoryEnabled } from '../../../../memdir/paths.js';
import { type AgentMemoryScope, loadAgentMemoryPrompt } from '../../../../tools/AgentTool/agentMemory.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Select } from '../../../CustomSelect/select.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import type { AgentWizardData } from '../types.js';
import React, { type ReactNode } from 'react'
import { Box } from '../../../../ink.js'
import { useKeybinding } from '../../../../keybindings/useKeybinding.js'
import { isAutoMemoryEnabled } from '../../../../memdir/paths.js'
import {
type AgentMemoryScope,
loadAgentMemoryPrompt,
} from '../../../../tools/AgentTool/agentMemory.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Select } from '../../../CustomSelect/select.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import type { AgentWizardData } from '../types.js'
type MemoryOption = {
label: string;
value: AgentMemoryScope | 'none';
};
export function MemoryStep() {
const $ = _c(13);
const {
goNext,
goBack,
updateWizardData,
wizardData
} = useWizard();
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {
context: "Confirmation"
};
$[0] = t0;
} else {
t0 = $[0];
}
useKeybinding("confirm:no", goBack, t0);
const isUserScope = wizardData.location === "userSettings";
let t1;
if ($[1] !== isUserScope) {
t1 = isUserScope ? [{
label: "User scope (~/.claude/agent-memory/) (Recommended)",
value: "user"
}, {
label: "None (no persistent memory)",
value: "none"
}, {
label: "Project scope (.claude/agent-memory/)",
value: "project"
}, {
label: "Local scope (.claude/agent-memory-local/)",
value: "local"
}] : [{
label: "Project scope (.claude/agent-memory/) (Recommended)",
value: "project"
}, {
label: "None (no persistent memory)",
value: "none"
}, {
label: "User scope (~/.claude/agent-memory/)",
value: "user"
}, {
label: "Local scope (.claude/agent-memory-local/)",
value: "local"
}];
$[1] = isUserScope;
$[2] = t1;
} else {
t1 = $[2];
}
const memoryOptions = t1;
let t2;
if ($[3] !== goNext || $[4] !== updateWizardData || $[5] !== wizardData.finalAgent || $[6] !== wizardData.systemPrompt) {
t2 = value => {
const memory = value === "none" ? undefined : value as AgentMemoryScope;
const agentType = wizardData.finalAgent?.agentType;
updateWizardData({
selectedMemory: memory,
finalAgent: wizardData.finalAgent ? {
...wizardData.finalAgent,
memory,
getSystemPrompt: isAutoMemoryEnabled() && memory && agentType ? () => wizardData.systemPrompt + "\n\n" + loadAgentMemoryPrompt(agentType, memory) : () => wizardData.systemPrompt
} : undefined
});
goNext();
};
$[3] = goNext;
$[4] = updateWizardData;
$[5] = wizardData.finalAgent;
$[6] = wizardData.systemPrompt;
$[7] = t2;
} else {
t2 = $[7];
}
const handleSelect = t2;
let t3;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t3 = <Byline><KeyboardShortcutHint shortcut={"\u2191\u2193"} action="navigate" /><KeyboardShortcutHint shortcut="Enter" action="select" /><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="go back" /></Byline>;
$[8] = t3;
} else {
t3 = $[8];
}
let t4;
if ($[9] !== goBack || $[10] !== handleSelect || $[11] !== memoryOptions) {
t4 = <WizardDialogLayout subtitle="Configure agent memory" footerText={t3}><Box><Select key="memory-select" options={memoryOptions} onChange={handleSelect} onCancel={goBack} /></Box></WizardDialogLayout>;
$[9] = goBack;
$[10] = handleSelect;
$[11] = memoryOptions;
$[12] = t4;
} else {
t4 = $[12];
}
return t4;
label: string
value: AgentMemoryScope | 'none'
}
export function MemoryStep(): ReactNode {
const { goNext, goBack, updateWizardData, wizardData } =
useWizard<AgentWizardData>()
useKeybinding('confirm:no', goBack, { context: 'Confirmation' })
const isUserScope = wizardData.location === 'userSettings'
// Build options with the recommended default first, then alternatives
// The recommended scope matches the agent's location (project agent → project memory, user agent → user memory)
const memoryOptions: MemoryOption[] = isUserScope
? [
{
label: 'User scope (~/.claude/agent-memory/) (Recommended)',
value: 'user',
},
{ label: 'None (no persistent memory)', value: 'none' },
{ label: 'Project scope (.claude/agent-memory/)', value: 'project' },
{ label: 'Local scope (.claude/agent-memory-local/)', value: 'local' },
]
: [
{
label: 'Project scope (.claude/agent-memory/) (Recommended)',
value: 'project',
},
{ label: 'None (no persistent memory)', value: 'none' },
{ label: 'User scope (~/.claude/agent-memory/)', value: 'user' },
{ label: 'Local scope (.claude/agent-memory-local/)', value: 'local' },
]
const handleSelect = (value: string): void => {
const memory = value === 'none' ? undefined : (value as AgentMemoryScope)
const agentType = wizardData.finalAgent?.agentType
updateWizardData({
selectedMemory: memory,
// Update finalAgent with memory and rewire getSystemPrompt to include memory loading.
// Explicitly set memory (not conditional spread) so selecting 'none' after going back clears it.
finalAgent: wizardData.finalAgent
? {
...wizardData.finalAgent,
memory,
getSystemPrompt:
isAutoMemoryEnabled() && memory && agentType
? () =>
wizardData.systemPrompt! +
'\n\n' +
loadAgentMemoryPrompt(agentType, memory)
: () => wizardData.systemPrompt!,
}
: undefined,
})
goNext()
}
return (
<WizardDialogLayout
subtitle="Configure agent memory"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="↑↓" action="navigate" />
<KeyboardShortcutHint shortcut="Enter" action="select" />
<ConfigurableShortcutHint
action="confirm:no"
context="Confirmation"
fallback="Esc"
description="go back"
/>
</Byline>
}
>
<Box>
<Select
key="memory-select"
options={memoryOptions}
onChange={handleSelect}
onCancel={goBack}
/>
</Box>
</WizardDialogLayout>
)
}

View File

@@ -1,79 +1,65 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import { Box } from '../../../../ink.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Select } from '../../../CustomSelect/select.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import type { AgentWizardData } from '../types.js';
export function MethodStep() {
const $ = _c(11);
const {
goNext,
goBack,
updateWizardData,
goToStep
} = useWizard();
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = [{
label: "Generate with Claude (recommended)",
value: "generate"
}, {
label: "Manual configuration",
value: "manual"
}];
$[0] = t0;
} else {
t0 = $[0];
}
const methodOptions = t0;
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <Byline><KeyboardShortcutHint shortcut={"\u2191\u2193"} action="navigate" /><KeyboardShortcutHint shortcut="Enter" action="select" /><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="go back" /></Byline>;
$[1] = t1;
} else {
t1 = $[1];
}
let t2;
if ($[2] !== goNext || $[3] !== goToStep || $[4] !== updateWizardData) {
t2 = value => {
const method = value as 'generate' | 'manual';
updateWizardData({
method,
wasGenerated: method === "generate"
});
if (method === "generate") {
goNext();
} else {
goToStep(3);
import React, { type ReactNode } from 'react'
import { Box } from '../../../../ink.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Select } from '../../../CustomSelect/select.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import type { AgentWizardData } from '../types.js'
export function MethodStep(): ReactNode {
const { goNext, goBack, updateWizardData, goToStep } =
useWizard<AgentWizardData>()
const methodOptions = [
{
label: 'Generate with Claude (recommended)',
value: 'generate',
},
{
label: 'Manual configuration',
value: 'manual',
},
]
return (
<WizardDialogLayout
subtitle="Creation method"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="↑↓" action="navigate" />
<KeyboardShortcutHint shortcut="Enter" action="select" />
<ConfigurableShortcutHint
action="confirm:no"
context="Confirmation"
fallback="Esc"
description="go back"
/>
</Byline>
}
};
$[2] = goNext;
$[3] = goToStep;
$[4] = updateWizardData;
$[5] = t2;
} else {
t2 = $[5];
}
let t3;
if ($[6] !== goBack) {
t3 = () => goBack();
$[6] = goBack;
$[7] = t3;
} else {
t3 = $[7];
}
let t4;
if ($[8] !== t2 || $[9] !== t3) {
t4 = <WizardDialogLayout subtitle="Creation method" footerText={t1}><Box><Select key="method-select" options={methodOptions} onChange={t2} onCancel={t3} /></Box></WizardDialogLayout>;
$[8] = t2;
$[9] = t3;
$[10] = t4;
} else {
t4 = $[10];
}
return t4;
>
<Box>
<Select
key="method-select"
options={methodOptions}
onChange={(value: string) => {
const method = value as 'generate' | 'manual'
updateWizardData({
method,
wasGenerated: method === 'generate',
})
// Dynamic navigation based on method
if (method === 'generate') {
goNext() // Go to GenerateStep (index 2)
} else {
goToStep(3) // Skip to TypeStep (index 3)
}
}}
onCancel={() => goBack()}
/>
</Box>
</WizardDialogLayout>
)
}

View File

@@ -1,51 +1,42 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import { ModelSelector } from '../../ModelSelector.js';
import type { AgentWizardData } from '../types.js';
export function ModelStep() {
const $ = _c(8);
const {
goNext,
goBack,
updateWizardData,
wizardData
} = useWizard();
let t0;
if ($[0] !== goNext || $[1] !== updateWizardData) {
t0 = model => {
updateWizardData({
selectedModel: model
});
goNext();
};
$[0] = goNext;
$[1] = updateWizardData;
$[2] = t0;
} else {
t0 = $[2];
import React, { type ReactNode } from 'react'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import { ModelSelector } from '../../ModelSelector.js'
import type { AgentWizardData } from '../types.js'
export function ModelStep(): ReactNode {
const { goNext, goBack, updateWizardData, wizardData } =
useWizard<AgentWizardData>()
const handleComplete = (model?: string): void => {
updateWizardData({ selectedModel: model })
goNext()
}
const handleComplete = t0;
let t1;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <Byline><KeyboardShortcutHint shortcut={"\u2191\u2193"} action="navigate" /><KeyboardShortcutHint shortcut="Enter" action="select" /><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="go back" /></Byline>;
$[3] = t1;
} else {
t1 = $[3];
}
let t2;
if ($[4] !== goBack || $[5] !== handleComplete || $[6] !== wizardData.selectedModel) {
t2 = <WizardDialogLayout subtitle="Select model" footerText={t1}><ModelSelector initialModel={wizardData.selectedModel} onComplete={handleComplete} onCancel={goBack} /></WizardDialogLayout>;
$[4] = goBack;
$[5] = handleComplete;
$[6] = wizardData.selectedModel;
$[7] = t2;
} else {
t2 = $[7];
}
return t2;
return (
<WizardDialogLayout
subtitle="Select model"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="↑↓" action="navigate" />
<KeyboardShortcutHint shortcut="Enter" action="select" />
<ConfigurableShortcutHint
action="confirm:no"
context="Confirmation"
fallback="Esc"
description="go back"
/>
</Byline>
}
>
<ModelSelector
initialModel={wizardData.selectedModel}
onComplete={handleComplete}
onCancel={goBack}
/>
</WizardDialogLayout>
)
}

View File

@@ -1,127 +1,97 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode, useCallback, useState } from 'react';
import { Box, Text } from '../../../../ink.js';
import { useKeybinding } from '../../../../keybindings/useKeybinding.js';
import { editPromptInEditor } from '../../../../utils/promptEditor.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import TextInput from '../../../TextInput.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import type { AgentWizardData } from '../types.js';
export function PromptStep() {
const $ = _c(20);
const {
goNext,
goBack,
updateWizardData,
wizardData
} = useWizard();
const [systemPrompt, setSystemPrompt] = useState(wizardData.systemPrompt || "");
const [cursorOffset, setCursorOffset] = useState(systemPrompt.length);
const [error, setError] = useState(null);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {
context: "Settings"
};
$[0] = t0;
} else {
t0 = $[0];
import React, { type ReactNode, useCallback, useState } from 'react'
import { Box, Text } from '../../../../ink.js'
import { useKeybinding } from '../../../../keybindings/useKeybinding.js'
import { editPromptInEditor } from '../../../../utils/promptEditor.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import TextInput from '../../../TextInput.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import type { AgentWizardData } from '../types.js'
export function PromptStep(): ReactNode {
const { goNext, goBack, updateWizardData, wizardData } =
useWizard<AgentWizardData>()
const [systemPrompt, setSystemPrompt] = useState(
wizardData.systemPrompt || '',
)
const [cursorOffset, setCursorOffset] = useState(systemPrompt.length)
const [error, setError] = useState<string | null>(null)
// Handle escape key - use Settings context so 'n' key doesn't cancel (allows typing 'n' in input)
useKeybinding('confirm:no', goBack, { context: 'Settings' })
const handleExternalEditor = useCallback(async () => {
const result = await editPromptInEditor(systemPrompt)
if (result.content !== null) {
setSystemPrompt(result.content)
setCursorOffset(result.content.length)
}
}, [systemPrompt])
useKeybinding('chat:externalEditor', handleExternalEditor, {
context: 'Chat',
})
const handleSubmit = (): void => {
const trimmedPrompt = systemPrompt.trim()
if (!trimmedPrompt) {
setError('System prompt is required')
return
}
setError(null)
updateWizardData({ systemPrompt: trimmedPrompt })
goNext()
}
useKeybinding("confirm:no", goBack, t0);
let t1;
if ($[1] !== systemPrompt) {
t1 = async () => {
const result = await editPromptInEditor(systemPrompt);
if (result.content !== null) {
setSystemPrompt(result.content);
setCursorOffset(result.content.length);
return (
<WizardDialogLayout
subtitle="System prompt"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="Type" action="enter text" />
<KeyboardShortcutHint shortcut="Enter" action="continue" />
<ConfigurableShortcutHint
action="chat:externalEditor"
context="Chat"
fallback="ctrl+g"
description="open in editor"
/>
<ConfigurableShortcutHint
action="confirm:no"
context="Settings"
fallback="Esc"
description="go back"
/>
</Byline>
}
};
$[1] = systemPrompt;
$[2] = t1;
} else {
t1 = $[2];
}
const handleExternalEditor = t1;
let t2;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t2 = {
context: "Chat"
};
$[3] = t2;
} else {
t2 = $[3];
}
useKeybinding("chat:externalEditor", handleExternalEditor, t2);
let t3;
if ($[4] !== goNext || $[5] !== systemPrompt || $[6] !== updateWizardData) {
t3 = () => {
const trimmedPrompt = systemPrompt.trim();
if (!trimmedPrompt) {
setError("System prompt is required");
return;
}
setError(null);
updateWizardData({
systemPrompt: trimmedPrompt
});
goNext();
};
$[4] = goNext;
$[5] = systemPrompt;
$[6] = updateWizardData;
$[7] = t3;
} else {
t3 = $[7];
}
const handleSubmit = t3;
let t4;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t4 = <Byline><KeyboardShortcutHint shortcut="Type" action="enter text" /><KeyboardShortcutHint shortcut="Enter" action="continue" /><ConfigurableShortcutHint action="chat:externalEditor" context="Chat" fallback="ctrl+g" description="open in editor" /><ConfigurableShortcutHint action="confirm:no" context="Settings" fallback="Esc" description="go back" /></Byline>;
$[8] = t4;
} else {
t4 = $[8];
}
let t5;
let t6;
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
t5 = <Text>Enter the system prompt for your agent:</Text>;
t6 = <Text dimColor={true}>Be comprehensive for best results</Text>;
$[9] = t5;
$[10] = t6;
} else {
t5 = $[9];
t6 = $[10];
}
let t7;
if ($[11] !== cursorOffset || $[12] !== handleSubmit || $[13] !== systemPrompt) {
t7 = <Box marginTop={1}><TextInput value={systemPrompt} onChange={setSystemPrompt} onSubmit={handleSubmit} placeholder="You are a helpful code reviewer who..." columns={80} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} focus={true} showCursor={true} /></Box>;
$[11] = cursorOffset;
$[12] = handleSubmit;
$[13] = systemPrompt;
$[14] = t7;
} else {
t7 = $[14];
}
let t8;
if ($[15] !== error) {
t8 = error && <Box marginTop={1}><Text color="error">{error}</Text></Box>;
$[15] = error;
$[16] = t8;
} else {
t8 = $[16];
}
let t9;
if ($[17] !== t7 || $[18] !== t8) {
t9 = <WizardDialogLayout subtitle="System prompt" footerText={t4}><Box flexDirection="column">{t5}{t6}{t7}{t8}</Box></WizardDialogLayout>;
$[17] = t7;
$[18] = t8;
$[19] = t9;
} else {
t9 = $[19];
}
return t9;
>
<Box flexDirection="column">
<Text>Enter the system prompt for your agent:</Text>
<Text dimColor>Be comprehensive for best results</Text>
<Box marginTop={1}>
<TextInput
value={systemPrompt}
onChange={setSystemPrompt}
onSubmit={handleSubmit}
placeholder="You are a helpful code reviewer who..."
columns={80}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
focus
showCursor
/>
</Box>
{error && (
<Box marginTop={1}>
<Text color="error">{error}</Text>
</Box>
)}
</Box>
</WizardDialogLayout>
)
}

View File

@@ -1,60 +1,52 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode } from 'react';
import type { Tools } from '../../../../Tool.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import { ToolSelector } from '../../ToolSelector.js';
import type { AgentWizardData } from '../types.js';
import React, { type ReactNode } from 'react'
import type { Tools } from '../../../../Tool.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import { ToolSelector } from '../../ToolSelector.js'
import type { AgentWizardData } from '../types.js'
type Props = {
tools: Tools;
};
export function ToolsStep(t0) {
const $ = _c(9);
const {
tools
} = t0;
const {
goNext,
goBack,
updateWizardData,
wizardData
} = useWizard();
let t1;
if ($[0] !== goNext || $[1] !== updateWizardData) {
t1 = selectedTools => {
updateWizardData({
selectedTools
});
goNext();
};
$[0] = goNext;
$[1] = updateWizardData;
$[2] = t1;
} else {
t1 = $[2];
}
const handleComplete = t1;
const initialTools = wizardData.selectedTools;
let t2;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Byline><KeyboardShortcutHint shortcut="Enter" action="toggle selection" /><KeyboardShortcutHint shortcut={"\u2191\u2193"} action="navigate" /><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="go back" /></Byline>;
$[3] = t2;
} else {
t2 = $[3];
}
let t3;
if ($[4] !== goBack || $[5] !== handleComplete || $[6] !== initialTools || $[7] !== tools) {
t3 = <WizardDialogLayout subtitle="Select tools" footerText={t2}><ToolSelector tools={tools} initialTools={initialTools} onComplete={handleComplete} onCancel={goBack} /></WizardDialogLayout>;
$[4] = goBack;
$[5] = handleComplete;
$[6] = initialTools;
$[7] = tools;
$[8] = t3;
} else {
t3 = $[8];
}
return t3;
tools: Tools
}
export function ToolsStep({ tools }: Props): ReactNode {
const { goNext, goBack, updateWizardData, wizardData } =
useWizard<AgentWizardData>()
const handleComplete = (selectedTools: string[] | undefined): void => {
updateWizardData({ selectedTools })
goNext()
}
// Pass through undefined to preserve "all tools" semantic
// ToolSelector will expand it internally for display purposes
const initialTools = wizardData.selectedTools
return (
<WizardDialogLayout
subtitle="Select tools"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="Enter" action="toggle selection" />
<KeyboardShortcutHint shortcut="↑↓" action="navigate" />
<ConfigurableShortcutHint
action="confirm:no"
context="Confirmation"
fallback="Esc"
description="go back"
/>
</Byline>
}
>
<ToolSelector
tools={tools}
initialTools={initialTools}
onComplete={handleComplete}
onCancel={goBack}
/>
</WizardDialogLayout>
)
}

View File

@@ -1,102 +1,83 @@
import { c as _c } from "react/compiler-runtime";
import React, { type ReactNode, useState } from 'react';
import { Box, Text } from '../../../../ink.js';
import { useKeybinding } from '../../../../keybindings/useKeybinding.js';
import type { AgentDefinition } from '../../../../tools/AgentTool/loadAgentsDir.js';
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js';
import { Byline } from '../../../design-system/Byline.js';
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js';
import TextInput from '../../../TextInput.js';
import { useWizard } from '../../../wizard/index.js';
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js';
import { validateAgentType } from '../../validateAgent.js';
import type { AgentWizardData } from '../types.js';
import React, { type ReactNode, useState } from 'react'
import { Box, Text } from '../../../../ink.js'
import { useKeybinding } from '../../../../keybindings/useKeybinding.js'
import type { AgentDefinition } from '../../../../tools/AgentTool/loadAgentsDir.js'
import { ConfigurableShortcutHint } from '../../../ConfigurableShortcutHint.js'
import { Byline } from '../../../design-system/Byline.js'
import { KeyboardShortcutHint } from '../../../design-system/KeyboardShortcutHint.js'
import TextInput from '../../../TextInput.js'
import { useWizard } from '../../../wizard/index.js'
import { WizardDialogLayout } from '../../../wizard/WizardDialogLayout.js'
import { validateAgentType } from '../../validateAgent.js'
import type { AgentWizardData } from '../types.js'
type Props = {
existingAgents: AgentDefinition[];
};
export function TypeStep(_props) {
const $ = _c(15);
const {
goNext,
goBack,
updateWizardData,
wizardData
} = useWizard();
const [agentType, setAgentType] = useState(wizardData.agentType || "");
const [error, setError] = useState(null);
const [cursorOffset, setCursorOffset] = useState(agentType.length);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {
context: "Settings"
};
$[0] = t0;
} else {
t0 = $[0];
}
useKeybinding("confirm:no", goBack, t0);
let t1;
if ($[1] !== goNext || $[2] !== updateWizardData) {
t1 = value => {
const trimmedValue = value.trim();
const validationError = validateAgentType(trimmedValue);
if (validationError) {
setError(validationError);
return;
}
setError(null);
updateWizardData({
agentType: trimmedValue
});
goNext();
};
$[1] = goNext;
$[2] = updateWizardData;
$[3] = t1;
} else {
t1 = $[3];
}
const handleSubmit = t1;
let t2;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Byline><KeyboardShortcutHint shortcut="Type" action="enter text" /><KeyboardShortcutHint shortcut="Enter" action="continue" /><ConfigurableShortcutHint action="confirm:no" context="Settings" fallback="Esc" description="go back" /></Byline>;
$[4] = t2;
} else {
t2 = $[4];
}
let t3;
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
t3 = <Text>Enter a unique identifier for your agent:</Text>;
$[5] = t3;
} else {
t3 = $[5];
}
let t4;
if ($[6] !== agentType || $[7] !== cursorOffset || $[8] !== handleSubmit) {
t4 = <Box marginTop={1}><TextInput value={agentType} onChange={setAgentType} onSubmit={handleSubmit} placeholder="e.g., test-runner, tech-lead, etc" columns={60} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} focus={true} showCursor={true} /></Box>;
$[6] = agentType;
$[7] = cursorOffset;
$[8] = handleSubmit;
$[9] = t4;
} else {
t4 = $[9];
}
let t5;
if ($[10] !== error) {
t5 = error && <Box marginTop={1}><Text color="error">{error}</Text></Box>;
$[10] = error;
$[11] = t5;
} else {
t5 = $[11];
}
let t6;
if ($[12] !== t4 || $[13] !== t5) {
t6 = <WizardDialogLayout subtitle="Agent type (identifier)" footerText={t2}><Box flexDirection="column">{t3}{t4}{t5}</Box></WizardDialogLayout>;
$[12] = t4;
$[13] = t5;
$[14] = t6;
} else {
t6 = $[14];
}
return t6;
existingAgents: AgentDefinition[]
}
export function TypeStep(_props: Props): ReactNode {
const { goNext, goBack, updateWizardData, wizardData } =
useWizard<AgentWizardData>()
const [agentType, setAgentType] = useState(wizardData.agentType || '')
const [error, setError] = useState<string | null>(null)
const [cursorOffset, setCursorOffset] = useState(agentType.length)
// Handle escape key - Go back to MethodStep
// Use Settings context so 'n' key doesn't cancel (allows typing 'n' in input)
useKeybinding('confirm:no', goBack, { context: 'Settings' })
const handleSubmit = (value: string): void => {
const trimmedValue = value.trim()
const validationError = validateAgentType(trimmedValue)
if (validationError) {
setError(validationError)
return
}
setError(null)
updateWizardData({ agentType: trimmedValue })
goNext()
}
return (
<WizardDialogLayout
subtitle="Agent type (identifier)"
footerText={
<Byline>
<KeyboardShortcutHint shortcut="Type" action="enter text" />
<KeyboardShortcutHint shortcut="Enter" action="continue" />
<ConfigurableShortcutHint
action="confirm:no"
context="Settings"
fallback="Esc"
description="go back"
/>
</Byline>
}
>
<Box flexDirection="column">
<Text>Enter a unique identifier for your agent:</Text>
<Box marginTop={1}>
<TextInput
value={agentType}
onChange={setAgentType}
onSubmit={handleSubmit}
placeholder="e.g., test-runner, tech-lead, etc"
columns={60}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
focus
showCursor
/>
</Box>
{error && (
<Box marginTop={1}>
<Text color="error">{error}</Text>
</Box>
)}
</Box>
</WizardDialogLayout>
)
}