feat: add toolset switching UI (#115)

This commit is contained in:
Charles Packer
2025-11-23 20:02:04 -08:00
committed by GitHub
parent 836a488263
commit 592ed66e1b
4 changed files with 236 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
// Import useInput from vendored Ink for bracketed paste support
import { Box, Text, useInput } from "ink";
import { useState } from "react";
import { colors } from "./colors";
interface ToolsetOption {
id: "codex" | "default";
label: string;
description: string;
tools: string[];
}
const toolsets: ToolsetOption[] = [
{
id: "codex",
label: "Codex Tools",
description: "OpenAI-style tools optimized for GPT models",
tools: [
"shell_command",
"shell",
"read_file",
"list_dir",
"grep_files",
"apply_patch",
],
},
{
id: "default",
label: "Default Tools",
description: "Anthropic-style tools optimized for Claude models",
tools: [
"Bash",
"BashOutput",
"Edit",
"Glob",
"Grep",
"LS",
"MultiEdit",
"Read",
"TodoWrite",
"Write",
],
},
];
interface ToolsetSelectorProps {
currentToolset?: "codex" | "default";
onSelect: (toolsetId: "codex" | "default") => void;
onCancel: () => void;
}
export function ToolsetSelector({
currentToolset,
onSelect,
onCancel,
}: ToolsetSelectorProps) {
const [selectedIndex, setSelectedIndex] = useState(0);
useInput((_input, key) => {
if (key.upArrow) {
setSelectedIndex((prev) => Math.max(0, prev - 1));
} else if (key.downArrow) {
setSelectedIndex((prev) => Math.min(toolsets.length - 1, prev + 1));
} else if (key.return) {
const selectedToolset = toolsets[selectedIndex];
if (selectedToolset) {
onSelect(selectedToolset.id);
}
} else if (key.escape) {
onCancel();
}
});
return (
<Box flexDirection="column" gap={1}>
<Box>
<Text bold color={colors.selector.title}>
Select Toolset ( to navigate, Enter to select, ESC to cancel)
</Text>
</Box>
<Box flexDirection="column">
{toolsets.map((toolset, index) => {
const isSelected = index === selectedIndex;
const isCurrent = toolset.id === currentToolset;
return (
<Box key={toolset.id} flexDirection="column">
<Box flexDirection="row" gap={1}>
<Text
color={
isSelected ? colors.selector.itemHighlighted : undefined
}
>
{isSelected ? "" : " "}
</Text>
<Box flexDirection="column">
<Box flexDirection="row">
<Text
bold={isSelected}
color={
isSelected ? colors.selector.itemHighlighted : undefined
}
>
{toolset.label}
{isCurrent && (
<Text color={colors.selector.itemCurrent}>
{" "}
(current)
</Text>
)}
</Text>
</Box>
<Text dimColor> {toolset.description}</Text>
</Box>
</Box>
</Box>
);
})}
</Box>
</Box>
);
}