mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 06:15:51 +00:00
更新大量 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:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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's reasoning capabilities and speed.
|
||||
</Text>
|
||||
</Box>
|
||||
<Select
|
||||
options={modelOptions}
|
||||
defaultValue={defaultModel}
|
||||
onChange={onComplete}
|
||||
onCancel={() => (onCancel ? onCancel() : onComplete(undefined))}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user