feat: add gemini tools (#120)

This commit is contained in:
Charles Packer
2025-11-24 10:50:31 -08:00
committed by GitHub
parent 43813383ac
commit f2ed25bfeb
51 changed files with 1639 additions and 64 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}