feat: add gemini tools (#120)
This commit is contained in:
@@ -207,7 +207,7 @@ export default function App({
|
||||
const [modelSelectorOpen, setModelSelectorOpen] = useState(false);
|
||||
const [toolsetSelectorOpen, setToolsetSelectorOpen] = useState(false);
|
||||
const [currentToolset, setCurrentToolset] = useState<
|
||||
"codex" | "default" | null
|
||||
"codex" | "default" | "gemini" | null
|
||||
>(null);
|
||||
const [llmConfig, setLlmConfig] = useState<LlmConfig | null>(null);
|
||||
const [agentName, setAgentName] = useState<string | null>(null);
|
||||
@@ -1785,7 +1785,7 @@ export default function App({
|
||||
);
|
||||
|
||||
const handleToolsetSelect = useCallback(
|
||||
async (toolsetId: "codex" | "default") => {
|
||||
async (toolsetId: "codex" | "default" | "gemini") => {
|
||||
setToolsetSelectorOpen(false);
|
||||
|
||||
const cmdId = uid("cmd");
|
||||
|
||||
@@ -71,7 +71,7 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
}) => {
|
||||
const t = toolName.toLowerCase();
|
||||
|
||||
if (t === "bash" || t === "shell_command") {
|
||||
if (t === "bash" || t === "shell_command" || t === "run_shell_command") {
|
||||
const cmdVal = parsedArgs?.command;
|
||||
const cmd =
|
||||
typeof cmdVal === "string" ? cmdVal : toolArgs || "(no arguments)";
|
||||
@@ -105,8 +105,9 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (t === "ls" || t === "list_dir") {
|
||||
const pathVal = parsedArgs?.path || parsedArgs?.target_directory;
|
||||
if (t === "ls" || t === "list_dir" || t === "list_directory") {
|
||||
const pathVal =
|
||||
parsedArgs?.path || parsedArgs?.target_directory || parsedArgs?.dir_path;
|
||||
const path = typeof pathVal === "string" ? pathVal : "(current directory)";
|
||||
const ignoreVal = parsedArgs?.ignore || parsedArgs?.ignore_globs;
|
||||
const ignore =
|
||||
@@ -142,7 +143,7 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (t === "grep" || t === "grep_files") {
|
||||
if (t === "grep" || t === "grep_files" || t === "search_file_content") {
|
||||
const patternVal = parsedArgs?.pattern;
|
||||
const pattern =
|
||||
typeof patternVal === "string" ? patternVal : "(no pattern)";
|
||||
@@ -216,8 +217,32 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
}
|
||||
}
|
||||
|
||||
// File edit previews: write/edit/multi_edit
|
||||
if ((t === "write" || t === "edit" || t === "multiedit") && parsedArgs) {
|
||||
if (t === "glob") {
|
||||
const patternVal = parsedArgs?.pattern;
|
||||
const pattern =
|
||||
typeof patternVal === "string" ? patternVal : "(no pattern)";
|
||||
const dirPathVal = parsedArgs?.dir_path;
|
||||
const dirInfo = typeof dirPathVal === "string" ? ` in ${dirPathVal}` : "";
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" paddingLeft={2}>
|
||||
<Text>
|
||||
Find files matching: {pattern}
|
||||
{dirInfo}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
// File edit previews: write/edit/multi_edit/replace/write_file
|
||||
if (
|
||||
(t === "write" ||
|
||||
t === "edit" ||
|
||||
t === "multiedit" ||
|
||||
t === "replace" ||
|
||||
t === "write_file") &&
|
||||
parsedArgs
|
||||
) {
|
||||
try {
|
||||
const filePath = String(parsedArgs.file_path || "");
|
||||
if (!filePath) throw new Error("no file_path");
|
||||
@@ -225,7 +250,7 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
if (precomputedDiff) {
|
||||
return (
|
||||
<Box flexDirection="column" paddingLeft={2}>
|
||||
{t === "write" ? (
|
||||
{t === "write" || t === "write_file" ? (
|
||||
<AdvancedDiffRenderer
|
||||
precomputed={precomputedDiff}
|
||||
kind="write"
|
||||
@@ -233,7 +258,7 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
content={String(parsedArgs.content ?? "")}
|
||||
showHeader={false}
|
||||
/>
|
||||
) : t === "edit" ? (
|
||||
) : t === "edit" || t === "replace" ? (
|
||||
<AdvancedDiffRenderer
|
||||
precomputed={precomputedDiff}
|
||||
kind="edit"
|
||||
@@ -263,7 +288,7 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
}
|
||||
|
||||
// Fallback to non-precomputed rendering
|
||||
if (t === "write") {
|
||||
if (t === "write" || t === "write_file") {
|
||||
return (
|
||||
<Box flexDirection="column" paddingLeft={2}>
|
||||
<AdvancedDiffRenderer
|
||||
@@ -275,7 +300,7 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
if (t === "edit") {
|
||||
if (t === "edit" || t === "replace") {
|
||||
return (
|
||||
<Box flexDirection="column" paddingLeft={2}>
|
||||
<AdvancedDiffRenderer
|
||||
@@ -313,7 +338,13 @@ const DynamicPreview: React.FC<DynamicPreviewProps> = ({
|
||||
}
|
||||
|
||||
// Default for file-edit tools when args not parseable yet
|
||||
if (t === "write" || t === "edit" || t === "multiedit") {
|
||||
if (
|
||||
t === "write" ||
|
||||
t === "edit" ||
|
||||
t === "multiedit" ||
|
||||
t === "replace" ||
|
||||
t === "write_file"
|
||||
) {
|
||||
return (
|
||||
<Box flexDirection="column" paddingLeft={2}>
|
||||
<Text dimColor>Preparing preview…</Text>
|
||||
@@ -605,5 +636,16 @@ function getHeaderLabel(toolName: string): string {
|
||||
if (t === "grep_files") return "Search in Files";
|
||||
if (t === "apply_patch") return "Apply Patch";
|
||||
if (t === "update_plan") return "Plan update";
|
||||
// Gemini toolset (uses server names)
|
||||
if (t === "run_shell_command") return "Shell command";
|
||||
if (t === "list_directory") return "List Directory";
|
||||
if (t === "search_file_content") return "Search in Files";
|
||||
if (t === "write_todos") return "Update Todos";
|
||||
if (t === "read_many_files") return "Read Multiple Files";
|
||||
// Shared names between toolsets - these get overwritten based on active toolset
|
||||
if (t === "read_file") return "Read File";
|
||||
if (t === "glob") return "Find Files";
|
||||
if (t === "replace") return "Edit File";
|
||||
if (t === "write_file") return "Write File";
|
||||
return toolName;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,12 @@ export const ToolCallMessage = memo(({ line }: { line: ToolCallLine }) => {
|
||||
else if (displayName === "list_dir") displayName = "LS";
|
||||
else if (displayName === "grep_files") displayName = "Grep";
|
||||
else if (displayName === "apply_patch") displayName = "Patch";
|
||||
// Gemini toolset (uses server names)
|
||||
else if (displayName === "run_shell_command") displayName = "Shell";
|
||||
else if (displayName === "list_directory") displayName = "LS";
|
||||
else if (displayName === "search_file_content") displayName = "Grep";
|
||||
else if (displayName === "write_todos") displayName = "TODO";
|
||||
else if (displayName === "read_many_files") displayName = "Read Multiple";
|
||||
|
||||
// Format arguments for display using the old formatting logic
|
||||
const formatted = formatArgsDisplay(argsText);
|
||||
|
||||
@@ -4,27 +4,13 @@ import { useState } from "react";
|
||||
import { colors } from "./colors";
|
||||
|
||||
interface ToolsetOption {
|
||||
id: "codex" | "default";
|
||||
id: "codex" | "default" | "gemini";
|
||||
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",
|
||||
"update_plan",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "default",
|
||||
label: "Default Tools",
|
||||
@@ -42,11 +28,41 @@ const toolsets: ToolsetOption[] = [
|
||||
"Write",
|
||||
],
|
||||
},
|
||||
{
|
||||
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",
|
||||
"update_plan",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "gemini",
|
||||
label: "Gemini Tools",
|
||||
description: "Google-style tools optimized for Gemini models",
|
||||
tools: [
|
||||
"run_shell_command",
|
||||
"read_file_gemini",
|
||||
"list_directory",
|
||||
"glob_gemini",
|
||||
"search_file_content",
|
||||
"replace",
|
||||
"write_file_gemini",
|
||||
"write_todos",
|
||||
"read_many_files",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
interface ToolsetSelectorProps {
|
||||
currentToolset?: "codex" | "default";
|
||||
onSelect: (toolsetId: "codex" | "default") => void;
|
||||
currentToolset?: "codex" | "default" | "gemini";
|
||||
onSelect: (toolsetId: "codex" | "default" | "gemini") => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user