summaryrefslogtreecommitdiff
path: root/packages/cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src')
-rw-r--r--packages/cli/src/core/GeminiStream.ts22
-rw-r--r--packages/cli/src/core/StreamingState.ts4
-rw-r--r--packages/cli/src/core/agent.ts0
-rw-r--r--packages/cli/src/core/constants.ts1
-rw-r--r--packages/cli/src/core/gemini-client.ts (renamed from packages/cli/src/core/GeminiClient.ts)6
-rw-r--r--packages/cli/src/core/gemini-stream.ts (renamed from packages/cli/src/core/geminiStreamProcessor.ts)31
-rw-r--r--packages/cli/src/core/history-updater.ts (renamed from packages/cli/src/core/historyUpdater.ts)7
-rw-r--r--packages/cli/src/core/prompts.ts3
-rw-r--r--packages/cli/src/tools/BaseTool.ts73
-rw-r--r--packages/cli/src/tools/Tool.ts100
-rw-r--r--packages/cli/src/tools/ToolResult.ts22
-rw-r--r--packages/cli/src/tools/edit.tool.ts5
-rw-r--r--packages/cli/src/tools/glob.tool.ts3
-rw-r--r--packages/cli/src/tools/grep.tool.ts3
-rw-r--r--packages/cli/src/tools/ls.tool.ts59
-rw-r--r--packages/cli/src/tools/read-file.tool.ts52
-rw-r--r--packages/cli/src/tools/terminal.tool.ts9
-rw-r--r--packages/cli/src/tools/tool-registry.ts3
-rw-r--r--packages/cli/src/tools/write-file.tool.ts7
-rw-r--r--packages/cli/src/ui/App.tsx2
-rw-r--r--packages/cli/src/ui/components/messages/ToolMessage.tsx2
-rw-r--r--packages/cli/src/ui/hooks/useGeminiStream.ts6
-rw-r--r--packages/cli/src/ui/hooks/useLoadingIndicator.ts2
-rw-r--r--packages/cli/src/ui/types.ts2
-rw-r--r--packages/cli/src/utils/BackgroundTerminalAnalyzer.ts2
25 files changed, 186 insertions, 240 deletions
diff --git a/packages/cli/src/core/GeminiStream.ts b/packages/cli/src/core/GeminiStream.ts
deleted file mode 100644
index 28568306..00000000
--- a/packages/cli/src/core/GeminiStream.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { ToolCallEvent } from "../ui/types.js";
-
-export enum GeminiEventType {
- Content,
- ToolCallInfo,
-}
-
-export interface GeminiContentEvent {
- type: GeminiEventType.Content;
- value: string;
-}
-
-export interface GeminiToolCallInfoEvent {
- type: GeminiEventType.ToolCallInfo;
- value: ToolCallEvent;
-}
-
-export type GeminiEvent =
- | GeminiContentEvent
- | GeminiToolCallInfoEvent;
-
-export type GeminiStream = AsyncIterable<GeminiEvent>;
diff --git a/packages/cli/src/core/StreamingState.ts b/packages/cli/src/core/StreamingState.ts
deleted file mode 100644
index 5aed1ff0..00000000
--- a/packages/cli/src/core/StreamingState.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export enum StreamingState {
- Idle,
- Responding,
-} \ No newline at end of file
diff --git a/packages/cli/src/core/agent.ts b/packages/cli/src/core/agent.ts
deleted file mode 100644
index e69de29b..00000000
--- a/packages/cli/src/core/agent.ts
+++ /dev/null
diff --git a/packages/cli/src/core/constants.ts b/packages/cli/src/core/constants.ts
deleted file mode 100644
index 16ac74d1..00000000
--- a/packages/cli/src/core/constants.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const MEMORY_FILE_NAME = 'GEMINI.md'; \ No newline at end of file
diff --git a/packages/cli/src/core/GeminiClient.ts b/packages/cli/src/core/gemini-client.ts
index 0cdeed86..e41fda6f 100644
--- a/packages/cli/src/core/GeminiClient.ts
+++ b/packages/cli/src/core/gemini-client.ts
@@ -10,9 +10,9 @@ import { CoreSystemPrompt } from './prompts.js';
import { type ToolCallEvent, type ToolCallConfirmationDetails, ToolCallStatus } from '../ui/types.js';
import process from 'node:process';
import { toolRegistry } from '../tools/tool-registry.js';
-import { ToolResult } from '../tools/ToolResult.js';
+import { ToolResult } from '../tools/tool.js';
import { getFolderStructure } from '../utils/getFolderStructure.js';
-import { GeminiEventType, GeminiStream } from './GeminiStream.js';
+import { GeminiEventType, GeminiStream } from './gemini-stream.js';
type ToolExecutionOutcome = {
callId: string;
@@ -62,7 +62,7 @@ ${folderStructure}
try {
const chat = this.ai.chats.create({
- model: 'gemini-2.5-pro-preview-03-25',//'gemini-2.0-flash',
+ model: 'gemini-2.0-flash',//'gemini-2.0-flash',
config: {
systemInstruction: CoreSystemPrompt,
...this.defaultHyperParameters,
diff --git a/packages/cli/src/core/geminiStreamProcessor.ts b/packages/cli/src/core/gemini-stream.ts
index 12de49cb..b47eb1c6 100644
--- a/packages/cli/src/core/geminiStreamProcessor.ts
+++ b/packages/cli/src/core/gemini-stream.ts
@@ -1,7 +1,33 @@
+import { ToolCallEvent } from "../ui/types.js";
import { Part } from '@google/genai';
import { HistoryItem } from '../ui/types.js';
-import { GeminiEventType, GeminiStream } from './GeminiStream.js';
-import { handleToolCallChunk, addErrorMessageToHistory } from './historyUpdater.js';
+import { handleToolCallChunk, addErrorMessageToHistory } from './history-updater.js';
+
+export enum GeminiEventType {
+ Content,
+ ToolCallInfo,
+}
+
+export interface GeminiContentEvent {
+ type: GeminiEventType.Content;
+ value: string;
+}
+
+export interface GeminiToolCallInfoEvent {
+ type: GeminiEventType.ToolCallInfo;
+ value: ToolCallEvent;
+}
+
+export type GeminiEvent =
+ | GeminiContentEvent
+ | GeminiToolCallInfoEvent;
+
+export type GeminiStream = AsyncIterable<GeminiEvent>;
+
+export enum StreamingState {
+ Idle,
+ Responding,
+}
interface StreamProcessorParams {
stream: GeminiStream;
@@ -104,7 +130,6 @@ export const processGeminiStream = async ({ // Renamed function for clarity
clearTimeout(renderTimeoutId);
renderTimeoutId = null;
}
-
// Flush any text buffer content.
render(textBuffer);
currentGeminiMessageId = null; // End text message context
diff --git a/packages/cli/src/core/historyUpdater.ts b/packages/cli/src/core/history-updater.ts
index 39eaca6a..4013728f 100644
--- a/packages/cli/src/core/historyUpdater.ts
+++ b/packages/cli/src/core/history-updater.ts
@@ -1,7 +1,7 @@
import { Part } from "@google/genai";
import { toolRegistry } from "../tools/tool-registry.js";
import { HistoryItem, IndividualToolCallDisplay, ToolCallEvent, ToolCallStatus, ToolConfirmationOutcome, ToolEditConfirmationDetails, ToolExecuteConfirmationDetails } from "../ui/types.js";
-import { ToolResultDisplay } from "../tools/ToolResult.js";
+import { ToolResultDisplay } from "../tools/tool.js";
/**
* Processes a tool call chunk and updates the history state accordingly.
@@ -46,13 +46,9 @@ export const handleToolCallChunk = (
if (!tool) {
throw new Error(`Tool "${chunk.name}" not found or is not registered.`);
}
-
handleToolCallChunk({ ...chunk, status: ToolCallStatus.Invoked, resultDisplay: "Executing...", confirmationDetails: undefined }, setHistory, submitQuery, getNextMessageId, currentToolGroupIdRef);
-
const result = await tool.execute(chunk.args);
-
handleToolCallChunk({ ...chunk, status: ToolCallStatus.Invoked, resultDisplay: result.returnDisplay, confirmationDetails: undefined }, setHistory, submitQuery, getNextMessageId, currentToolGroupIdRef);
-
const functionResponse: Part = {
functionResponse: {
name: chunk.name,
@@ -60,7 +56,6 @@ export const handleToolCallChunk = (
response: { "output": result.llmContent },
},
}
-
await submitQuery(functionResponse);
}
}
diff --git a/packages/cli/src/core/prompts.ts b/packages/cli/src/core/prompts.ts
index 9e1f994f..92a6708d 100644
--- a/packages/cli/src/core/prompts.ts
+++ b/packages/cli/src/core/prompts.ts
@@ -1,6 +1,7 @@
import { ReadFileTool } from "../tools/read-file.tool.js";
import { TerminalTool } from "../tools/terminal.tool.js";
-import { MEMORY_FILE_NAME } from "./constants.js";
+
+const MEMORY_FILE_NAME = 'GEMINI.md';
const contactEmail = '[email protected]';
export const CoreSystemPrompt = `
diff --git a/packages/cli/src/tools/BaseTool.ts b/packages/cli/src/tools/BaseTool.ts
deleted file mode 100644
index 1ab7fbf1..00000000
--- a/packages/cli/src/tools/BaseTool.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import type { FunctionDeclaration, Schema } from '@google/genai';
-import { ToolResult } from './ToolResult.js';
-import { Tool } from './Tool.js';
-import { ToolCallConfirmationDetails } from '../ui/types.js';
-
-/**
- * Base implementation for tools with common functionality
- */
-export abstract class BaseTool<TParams = unknown, TResult extends ToolResult = ToolResult> implements Tool<TParams, TResult> {
- /**
- * Creates a new instance of BaseTool
- * @param name Internal name of the tool (used for API calls)
- * @param displayName User-friendly display name of the tool
- * @param description Description of what the tool does
- * @param parameterSchema JSON Schema defining the parameters
- */
- constructor(
- public readonly name: string,
- public readonly displayName: string,
- public readonly description: string,
- public readonly parameterSchema: Record<string, unknown>
- ) {}
-
- /**
- * Function declaration schema computed from name, description, and parameterSchema
- */
- get schema(): FunctionDeclaration {
- return {
- name: this.name,
- description: this.description,
- parameters: this.parameterSchema as Schema
- };
- }
-
- /**
- * Validates the parameters for the tool
- * This is a placeholder implementation and should be overridden
- * @param params Parameters to validate
- * @returns An error message string if invalid, null otherwise
- */
- invalidParams(params: TParams): string | null {
- // Implementation would typically use a JSON Schema validator
- // This is a placeholder that should be implemented by derived classes
- return null;
- }
-
- /**
- * Gets a pre-execution description of the tool operation
- * Default implementation that should be overridden by derived classes
- * @param params Parameters for the tool execution
- * @returns A markdown string describing what the tool will do
- */
- getDescription(params: TParams): string {
- return JSON.stringify(params);
- }
-
- /**
- * Determines if the tool should prompt for confirmation before execution
- * @param params Parameters for the tool execution
- * @returns Whether or not execute should be confirmed by the user.
- */
- shouldConfirmExecute(params: TParams): Promise<ToolCallConfirmationDetails | false> {
- return Promise.resolve(false);
- }
-
- /**
- * Abstract method to execute the tool with the given parameters
- * Must be implemented by derived classes
- * @param params Parameters for the tool execution
- * @returns Result of the tool execution
- */
- abstract execute(params: TParams): Promise<TResult>;
-} \ No newline at end of file
diff --git a/packages/cli/src/tools/Tool.ts b/packages/cli/src/tools/Tool.ts
index c1ef26ec..21dd88d5 100644
--- a/packages/cli/src/tools/Tool.ts
+++ b/packages/cli/src/tools/Tool.ts
@@ -1,5 +1,4 @@
-import { FunctionDeclaration } from "@google/genai";
-import { ToolResult } from "./ToolResult.js";
+import { FunctionDeclaration, Schema } from "@google/genai";
import { ToolCallConfirmationDetails } from "../ui/types.js";
/**
@@ -25,14 +24,14 @@ export interface Tool<TParams = unknown, TResult extends ToolResult = ToolResult
* Function declaration schema from @google/genai
*/
schema: FunctionDeclaration;
-
+
/**
* Validates the parameters for the tool
* @param params Parameters to validate
* @returns An error message string if invalid, null otherwise
*/
invalidParams(params: TParams): string | null;
-
+
/**
* Gets a pre-execution description of the tool operation
* @param params Parameters for the tool execution
@@ -47,7 +46,7 @@ export interface Tool<TParams = unknown, TResult extends ToolResult = ToolResult
* @returns Whether execute should be confirmed.
*/
shouldConfirmExecute(params: TParams): Promise<ToolCallConfirmationDetails | false>;
-
+
/**
* Executes the tool with the given parameters
* @param params Parameters for the tool execution
@@ -55,3 +54,94 @@ export interface Tool<TParams = unknown, TResult extends ToolResult = ToolResult
*/
execute(params: TParams): Promise<TResult>;
}
+
+
+/**
+ * Base implementation for tools with common functionality
+ */
+export abstract class BaseTool<TParams = unknown, TResult extends ToolResult = ToolResult> implements Tool<TParams, TResult> {
+ /**
+ * Creates a new instance of BaseTool
+ * @param name Internal name of the tool (used for API calls)
+ * @param displayName User-friendly display name of the tool
+ * @param description Description of what the tool does
+ * @param parameterSchema JSON Schema defining the parameters
+ */
+ constructor(
+ public readonly name: string,
+ public readonly displayName: string,
+ public readonly description: string,
+ public readonly parameterSchema: Record<string, unknown>
+ ) {}
+
+ /**
+ * Function declaration schema computed from name, description, and parameterSchema
+ */
+ get schema(): FunctionDeclaration {
+ return {
+ name: this.name,
+ description: this.description,
+ parameters: this.parameterSchema as Schema
+ };
+ }
+
+ /**
+ * Validates the parameters for the tool
+ * This is a placeholder implementation and should be overridden
+ * @param params Parameters to validate
+ * @returns An error message string if invalid, null otherwise
+ */
+ invalidParams(params: TParams): string | null {
+ // Implementation would typically use a JSON Schema validator
+ // This is a placeholder that should be implemented by derived classes
+ return null;
+ }
+
+ /**
+ * Gets a pre-execution description of the tool operation
+ * Default implementation that should be overridden by derived classes
+ * @param params Parameters for the tool execution
+ * @returns A markdown string describing what the tool will do
+ */
+ getDescription(params: TParams): string {
+ return JSON.stringify(params);
+ }
+
+ /**
+ * Determines if the tool should prompt for confirmation before execution
+ * @param params Parameters for the tool execution
+ * @returns Whether or not execute should be confirmed by the user.
+ */
+ shouldConfirmExecute(params: TParams): Promise<ToolCallConfirmationDetails | false> {
+ return Promise.resolve(false);
+ }
+
+ /**
+ * Abstract method to execute the tool with the given parameters
+ * Must be implemented by derived classes
+ * @param params Parameters for the tool execution
+ * @returns Result of the tool execution
+ */
+ abstract execute(params: TParams): Promise<TResult>;
+}
+
+
+export interface ToolResult {
+ /**
+ * Content meant to be included in LLM history.
+ * This should represent the factual outcome of the tool execution.
+ */
+ llmContent: string;
+
+ /**
+ * Markdown string for user display.
+ * This provides a user-friendly summary or visualization of the result.
+ */
+ returnDisplay: ToolResultDisplay;
+}
+
+export type ToolResultDisplay = string | FileDiff;
+
+export interface FileDiff {
+ fileDiff: string
+}
diff --git a/packages/cli/src/tools/ToolResult.ts b/packages/cli/src/tools/ToolResult.ts
deleted file mode 100644
index 674e2fcb..00000000
--- a/packages/cli/src/tools/ToolResult.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Standard tool result interface that all tools should implement
- */
-export interface ToolResult {
- /**
- * Content meant to be included in LLM history.
- * This should represent the factual outcome of the tool execution.
- */
- llmContent: string;
-
- /**
- * Markdown string for user display.
- * This provides a user-friendly summary or visualization of the result.
- */
- returnDisplay: ToolResultDisplay;
-}
-
-export type ToolResultDisplay = string | FileDiff;
-
-export interface FileDiff {
- fileDiff: string
-}
diff --git a/packages/cli/src/tools/edit.tool.ts b/packages/cli/src/tools/edit.tool.ts
index 28199c24..6f7ebe8a 100644
--- a/packages/cli/src/tools/edit.tool.ts
+++ b/packages/cli/src/tools/edit.tool.ts
@@ -2,8 +2,7 @@ import fs from 'fs';
import path from 'path';
import * as Diff from 'diff';
import { SchemaValidator } from '../utils/schemaValidator.js';
-import { ToolResult } from './ToolResult.js';
-import { BaseTool } from './BaseTool.js';
+import { BaseTool, ToolResult } from './tool.js';
import { ToolCallConfirmationDetails, ToolConfirmationOutcome, ToolEditConfirmationDetails } from '../ui/types.js';
import { makeRelative, shortenPath } from '../utils/paths.js';
import { ReadFileTool } from './read-file.tool.js';
@@ -67,7 +66,7 @@ export class EditTool extends BaseTool<EditToolParams, EditToolResult> {
`Replaces a SINGLE, UNIQUE occurrence of text within a file. Requires providing significant context around the change to ensure uniqueness. For moving/renaming files, use the Bash tool with \`mv\`. For replacing entire file contents or creating new files use the ${WriteFileTool.Name} tool. Always use the ${ReadFileTool.Name} tool to examine the file before using this tool.`,
{
properties: {
- file_path: {
+ filePath: {
description: 'The absolute path to the file to modify. Must start with /. When creating a new file, ensure the parent directory exists (use the `LS` tool to verify).',
type: 'string'
},
diff --git a/packages/cli/src/tools/glob.tool.ts b/packages/cli/src/tools/glob.tool.ts
index e6bf1747..5a427e75 100644
--- a/packages/cli/src/tools/glob.tool.ts
+++ b/packages/cli/src/tools/glob.tool.ts
@@ -2,8 +2,7 @@ import fs from 'fs';
import path from 'path';
import fg from 'fast-glob';
import { SchemaValidator } from '../utils/schemaValidator.js';
-import { BaseTool } from './BaseTool.js';
-import { ToolResult } from './ToolResult.js';
+import { BaseTool, ToolResult } from './tool.js';
import { shortenPath, makeRelative } from '../utils/paths.js';
/**
diff --git a/packages/cli/src/tools/grep.tool.ts b/packages/cli/src/tools/grep.tool.ts
index 50a62c47..93c37f82 100644
--- a/packages/cli/src/tools/grep.tool.ts
+++ b/packages/cli/src/tools/grep.tool.ts
@@ -4,8 +4,7 @@ import path from 'path';
import { EOL } from 'os'; // Used for parsing grep output lines
import { spawn } from 'child_process'; // Used for git grep and system grep
import fastGlob from 'fast-glob'; // Used for JS fallback file searching
-import { ToolResult } from './ToolResult.js';
-import { BaseTool } from './BaseTool.js';
+import { BaseTool, ToolResult } from './tool.js';
import { SchemaValidator } from '../utils/schemaValidator.js';
import { makeRelative, shortenPath } from '../utils/paths.js';
diff --git a/packages/cli/src/tools/ls.tool.ts b/packages/cli/src/tools/ls.tool.ts
index f76c8472..9f3714f7 100644
--- a/packages/cli/src/tools/ls.tool.ts
+++ b/packages/cli/src/tools/ls.tool.ts
@@ -1,8 +1,7 @@
import fs from 'fs';
import path from 'path';
-import { BaseTool } from './BaseTool.js';
+import { BaseTool, ToolResult } from './tool.js';
import { SchemaValidator } from '../utils/schemaValidator.js';
-import { ToolResult } from './ToolResult.js';
import { makeRelative, shortenPath } from '../utils/paths.js';
/**
@@ -13,7 +12,7 @@ export interface LSToolParams {
* The absolute path to the directory to list
*/
path: string;
-
+
/**
* List of glob patterns to ignore
*/
@@ -28,22 +27,22 @@ export interface FileEntry {
* Name of the file or directory
*/
name: string;
-
+
/**
* Absolute path to the file or directory
*/
path: string;
-
+
/**
* Whether this entry is a directory
*/
isDirectory: boolean;
-
+
/**
* Size of the file in bytes (0 for directories)
*/
size: number;
-
+
/**
* Last modified timestamp
*/
@@ -58,12 +57,12 @@ export interface LSToolResult extends ToolResult {
* List of file entries
*/
entries: FileEntry[];
-
+
/**
* The directory that was listed
*/
listedPath: string;
-
+
/**
* Total number of entries found
*/
@@ -120,15 +119,13 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
private isWithinRoot(pathToCheck: string): boolean {
const normalizedPath = path.normalize(pathToCheck);
const normalizedRoot = path.normalize(this.rootDirectory);
-
// Ensure the normalizedRoot ends with a path separator for proper path comparison
- const rootWithSep = normalizedRoot.endsWith(path.sep)
- ? normalizedRoot
+ const rootWithSep = normalizedRoot.endsWith(path.sep)
+ ? normalizedRoot
: normalizedRoot + path.sep;
-
return normalizedPath === normalizedRoot || normalizedPath.startsWith(rootWithSep);
}
-
+
/**
* Validates the parameters for the tool
* @param params Parameters to validate
@@ -138,7 +135,6 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
if (this.schema.parameters && !SchemaValidator.validate(this.schema.parameters as Record<string, unknown>, params)) {
return "Parameters failed schema validation.";
}
-
// Ensure path is absolute
if (!path.isAbsolute(params.path)) {
return `Path must be absolute: ${params.path}`;
@@ -148,10 +144,9 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
if (!this.isWithinRoot(params.path)) {
return `Path must be within the root directory (${this.rootDirectory}): ${params.path}`;
}
-
return null;
}
-
+
/**
* Checks if a filename matches any of the ignore patterns
* @param filename Filename to check
@@ -162,26 +157,22 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
if (!patterns || patterns.length === 0) {
return false;
}
-
for (const pattern of patterns) {
// Convert glob pattern to RegExp
const regexPattern = pattern
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
.replace(/\*/g, '.*')
.replace(/\?/g, '.');
-
const regex = new RegExp(`^${regexPattern}$`);
-
if (regex.test(filename)) {
return true;
}
}
-
return false;
}
-
+
/**
- * Gets a description of the file reading operation
+ * Gets a description of the file reading operation
* @param params Parameters for the file reading
* @returns A string describing the file being read
*/
@@ -189,7 +180,7 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
const relativePath = makeRelative(params.path, this.rootDirectory);
return shortenPath(relativePath);
}
-
+
/**
* Executes the LS operation with the given parameters
* @param params Parameters for the LS operation
@@ -206,7 +197,7 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
returnDisplay: "**Error:** Failed to execute tool."
};
}
-
+
try {
// Check if path exists
if (!fs.existsSync(params.path)) {
@@ -218,7 +209,6 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
returnDisplay: `Directory does not exist`
};
}
-
// Check if path is a directory
const stats = fs.statSync(params.path);
if (!stats.isDirectory()) {
@@ -230,11 +220,10 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
returnDisplay: `Path is not a directory`
};
}
-
+
// Read directory contents
const files = fs.readdirSync(params.path);
const entries: FileEntry[] = [];
-
if (files.length === 0) {
return {
entries: [],
@@ -244,20 +233,16 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
returnDisplay: `Directory is empty.`
};
}
-
- // Process each entry
+
for (const file of files) {
- // Skip if the file matches ignore patterns
if (this.shouldIgnore(file, params.ignore)) {
continue;
}
-
const fullPath = path.join(params.path, file);
-
+
try {
const stats = fs.statSync(fullPath);
const isDir = stats.isDirectory();
-
entries.push({
name: file,
path: fullPath,
@@ -270,21 +255,21 @@ export class LSTool extends BaseTool<LSToolParams, LSToolResult> {
console.error(`Error accessing ${fullPath}: ${error}`);
}
}
-
+
// Sort entries (directories first, then alphabetically)
entries.sort((a, b) => {
if (a.isDirectory && !b.isDirectory) return -1;
if (!a.isDirectory && b.isDirectory) return 1;
return a.name.localeCompare(b.name);
});
-
+
// Create formatted content for display
const directoryContent = entries.map(entry => {
const typeIndicator = entry.isDirectory ? 'd' : '-';
const sizeInfo = entry.isDirectory ? '' : ` (${entry.size} bytes)`;
return `${typeIndicator} ${entry.name}${sizeInfo}`;
}).join('\n');
-
+
return {
entries,
listedPath: params.path,
diff --git a/packages/cli/src/tools/read-file.tool.ts b/packages/cli/src/tools/read-file.tool.ts
index 7cbacd96..64d59df0 100644
--- a/packages/cli/src/tools/read-file.tool.ts
+++ b/packages/cli/src/tools/read-file.tool.ts
@@ -1,9 +1,8 @@
import fs from 'fs';
import path from 'path';
-import { ToolResult } from './ToolResult.js';
-import { BaseTool } from './BaseTool.js';
import { SchemaValidator } from '../utils/schemaValidator.js';
import { makeRelative, shortenPath } from '../utils/paths.js';
+import { BaseTool, ToolResult } from './tool.js';
/**
* Parameters for the ReadFile tool
@@ -36,7 +35,7 @@ export interface ReadFileToolResult extends ToolResult {
*/
export class ReadFileTool extends BaseTool<ReadFileToolParams, ReadFileToolResult> {
public static readonly Name: string = 'read_file';
-
+
// Maximum number of lines to read by default
private static readonly DEFAULT_MAX_LINES = 2000;
@@ -108,26 +107,19 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ReadFileToolResul
if (this.schema.parameters && !SchemaValidator.validate(this.schema.parameters as Record<string, unknown>, params)) {
return "Parameters failed schema validation.";
}
-
- // Ensure path is absolute
- if (!path.isAbsolute(params.file_path)) {
- return `File path must be absolute: ${params.file_path}`;
+ const filePath = params.file_path;
+ if (!path.isAbsolute(filePath)) {
+ return `File path must be absolute: ${filePath}`;
}
-
- // Ensure path is within the root directory
- if (!this.isWithinRoot(params.file_path)) {
- return `File path must be within the root directory (${this.rootDirectory}): ${params.file_path}`;
+ if (!this.isWithinRoot(filePath)) {
+ return `File path must be within the root directory (${this.rootDirectory}): ${filePath}`;
}
-
- // Validate offset and limit if provided
if (params.offset !== undefined && params.offset < 0) {
return 'Offset must be a non-negative number';
}
-
if (params.limit !== undefined && params.limit <= 0) {
return 'Limit must be a positive number';
}
-
return null;
}
@@ -208,6 +200,7 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ReadFileToolResul
*/
async execute(params: ReadFileToolParams): Promise<ReadFileToolResult> {
const validationError = this.invalidParams(params);
+ const filePath = params.file_path;
if (validationError) {
return {
llmContent: `Error: Invalid parameters provided. Reason: ${validationError}`,
@@ -216,51 +209,40 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ReadFileToolResul
}
try {
- // Check if file exists
- if (!fs.existsSync(params.file_path)) {
+ if (!fs.existsSync(filePath)) {
return {
- llmContent: `File not found: ${params.file_path}`,
+ llmContent: `File not found: ${filePath}`,
returnDisplay: `File not found.`,
};
}
- // Check if it's a directory
- const stats = fs.statSync(params.file_path);
+ const stats = fs.statSync(filePath);
if (stats.isDirectory()) {
return {
- llmContent: `Path is a directory, not a file: ${params.file_path}`,
+ llmContent: `Path is a directory, not a file: ${filePath}`,
returnDisplay: `File is directory.`,
};
}
- // Detect file type
- const fileType = this.detectFileType(params.file_path);
-
- // Handle binary files differently
+ const fileType = this.detectFileType(filePath);
if (fileType !== 'text') {
return {
- llmContent: `Binary file: ${params.file_path} (${fileType})`,
+ llmContent: `Binary file: ${filePath} (${fileType})`,
returnDisplay: ``,
};
}
- // Read and process text file
- const content = fs.readFileSync(params.file_path, 'utf8');
+ const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
- // Apply offset and limit
const startLine = params.offset || 0;
- // Use the default max lines if no limit is provided
const endLine = params.limit
? startLine + params.limit
: Math.min(startLine + ReadFileTool.DEFAULT_MAX_LINES, lines.length);
const selectedLines = lines.slice(startLine, endLine);
- // Format with line numbers and handle line truncation
let truncated = false;
const formattedLines = selectedLines.map((line) => {
- // Calculate actual line number (1-based)
- // Truncate long lines
let processedLine = line;
if (line.length > ReadFileTool.MAX_LINE_LENGTH) {
processedLine = line.substring(0, ReadFileTool.MAX_LINE_LENGTH) + '... [truncated]';
@@ -270,10 +252,8 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ReadFileToolResul
return processedLine;
});
- // Check if content was truncated due to line limit or max lines limit
const contentTruncated = (endLine < lines.length) || truncated;
- // Create llmContent with truncation info if needed
let llmContent = '';
if (contentTruncated) {
llmContent += `[File truncated: showing lines ${startLine + 1}-${endLine} of ${lines.length} total lines. Use offset parameter to view more.]\n`;
@@ -288,7 +268,7 @@ export class ReadFileTool extends BaseTool<ReadFileToolParams, ReadFileToolResul
const errorMsg = `Error reading file: ${error instanceof Error ? error.message : String(error)}`;
return {
- llmContent: `Error reading file ${params.file_path}: ${errorMsg}`,
+ llmContent: `Error reading file ${filePath}: ${errorMsg}`,
returnDisplay: `Failed to read file: ${errorMsg}`,
};
}
diff --git a/packages/cli/src/tools/terminal.tool.ts b/packages/cli/src/tools/terminal.tool.ts
index ae33c107..fed1a752 100644
--- a/packages/cli/src/tools/terminal.tool.ts
+++ b/packages/cli/src/tools/terminal.tool.ts
@@ -2,13 +2,10 @@ import { spawn, SpawnOptions, ChildProcessWithoutNullStreams, exec } from 'child
import path from 'path';
import os from 'os';
import crypto from 'crypto';
-import { promises as fs } from 'fs'; // Added fs.promises
-import { BaseTool } from './BaseTool.js'; // Adjust path as needed
-import { ToolResult } from './ToolResult.js'; // Adjust path as needed
-import { SchemaValidator } from '../utils/schemaValidator.js'; // Adjust path as needed
+import { promises as fs } from 'fs';
+import { BaseTool, ToolResult } from './tool.js';
+import { SchemaValidator } from '../utils/schemaValidator.js';
import { ToolCallConfirmationDetails, ToolConfirmationOutcome, ToolExecuteConfirmationDetails } from '../ui/types.js'; // Adjust path as needed
-import { GeminiClient } from '../core/GeminiClient.js';
-import { SchemaUnion, Type } from '@google/genai';
import { BackgroundTerminalAnalyzer } from '../utils/BackgroundTerminalAnalyzer.js';
// --- Interfaces ---
diff --git a/packages/cli/src/tools/tool-registry.ts b/packages/cli/src/tools/tool-registry.ts
index f5d661e6..d9f4504c 100644
--- a/packages/cli/src/tools/tool-registry.ts
+++ b/packages/cli/src/tools/tool-registry.ts
@@ -1,6 +1,5 @@
import { ToolListUnion, FunctionDeclaration } from '@google/genai';
-import { Tool } from './Tool.js';
-import { ToolResult } from './ToolResult.js';
+import { Tool } from './tool.js';
class ToolRegistry {
private tools: Map<string, Tool> = new Map();
diff --git a/packages/cli/src/tools/write-file.tool.ts b/packages/cli/src/tools/write-file.tool.ts
index e832357b..aa2b0d85 100644
--- a/packages/cli/src/tools/write-file.tool.ts
+++ b/packages/cli/src/tools/write-file.tool.ts
@@ -1,7 +1,6 @@
import fs from 'fs';
import path from 'path';
-import { ToolResult } from './ToolResult.js';
-import { BaseTool } from './BaseTool.js';
+import { BaseTool, ToolResult } from './tool.js';
import { SchemaValidator } from '../utils/schemaValidator.js';
import { makeRelative, shortenPath } from '../utils/paths.js';
import { ToolCallConfirmationDetails, ToolConfirmationOutcome, ToolEditConfirmationDetails } from '../ui/types.js';
@@ -52,7 +51,7 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, WriteFileToolRe
'Writes content to a specified file in the local filesystem.',
{
properties: {
- file_path: {
+ filePath: {
description: 'The absolute path to the file to write to (e.g., \'/home/user/project/file.txt\'). Relative paths are not supported.',
type: 'string'
},
@@ -61,7 +60,7 @@ export class WriteFileTool extends BaseTool<WriteFileToolParams, WriteFileToolRe
type: 'string'
}
},
- required: ['file_path', 'content'],
+ required: ['filePath', 'content'],
type: 'object'
}
);
diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx
index 32dcaac0..9a2ee49d 100644
--- a/packages/cli/src/ui/App.tsx
+++ b/packages/cli/src/ui/App.tsx
@@ -9,7 +9,7 @@ import HistoryDisplay from './components/HistoryDisplay.js';
import LoadingIndicator from './components/LoadingIndicator.js';
import InputPrompt from './components/InputPrompt.js';
import Footer from './components/Footer.js';
-import { StreamingState } from '../core/StreamingState.js';
+import { StreamingState } from '../core/gemini-stream.js';
import { PartListUnion } from '@google/genai';
interface AppProps {
diff --git a/packages/cli/src/ui/components/messages/ToolMessage.tsx b/packages/cli/src/ui/components/messages/ToolMessage.tsx
index 38bc3de1..4ad947c9 100644
--- a/packages/cli/src/ui/components/messages/ToolMessage.tsx
+++ b/packages/cli/src/ui/components/messages/ToolMessage.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Box, Text } from 'ink';
import Spinner from 'ink-spinner';
import { ToolCallStatus } from '../../types.js';
-import { ToolResultDisplay } from '../../../tools/ToolResult.js';
+import { ToolResultDisplay } from '../../../tools/tool.js';
import DiffRenderer from './DiffRenderer.js';
import { MarkdownRenderer } from '../../utils/MarkdownRenderer.js';
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts
index 71972fbe..c65422ca 100644
--- a/packages/cli/src/ui/hooks/useGeminiStream.ts
+++ b/packages/cli/src/ui/hooks/useGeminiStream.ts
@@ -1,10 +1,10 @@
import { useState, useRef, useCallback, useEffect } from 'react';
import { useInput } from 'ink';
-import { GeminiClient } from '../../core/GeminiClient.js';
+import { GeminiClient } from '../../core/gemini-client.js';
import { type Chat, type PartListUnion } from '@google/genai';
import { HistoryItem } from '../types.js';
-import { processGeminiStream } from '../../core/geminiStreamProcessor.js';
-import { StreamingState } from '../../core/StreamingState.js';
+import { processGeminiStream } from '../../core/gemini-stream.js';
+import { StreamingState } from '../../core/gemini-stream.js';
const addHistoryItem = (
setHistory: React.Dispatch<React.SetStateAction<HistoryItem[]>>,
diff --git a/packages/cli/src/ui/hooks/useLoadingIndicator.ts b/packages/cli/src/ui/hooks/useLoadingIndicator.ts
index f1ab4552..8f440327 100644
--- a/packages/cli/src/ui/hooks/useLoadingIndicator.ts
+++ b/packages/cli/src/ui/hooks/useLoadingIndicator.ts
@@ -1,6 +1,6 @@
import { useState, useEffect, useRef } from 'react';
import { WITTY_LOADING_PHRASES, PHRASE_CHANGE_INTERVAL_MS } from '../constants.js';
-import { StreamingState } from '../../core/StreamingState.js';
+import { StreamingState } from '../../core/gemini-stream.js';
export const useLoadingIndicator = (streamingState: StreamingState) => {
const [elapsedTime, setElapsedTime] = useState(0);
diff --git a/packages/cli/src/ui/types.ts b/packages/cli/src/ui/types.ts
index 0b5dd246..e7c43c44 100644
--- a/packages/cli/src/ui/types.ts
+++ b/packages/cli/src/ui/types.ts
@@ -1,4 +1,4 @@
-import { ToolResultDisplay } from "../tools/ToolResult.js";
+import { ToolResultDisplay } from '../tools/tool.js';
export enum ToolCallStatus {
Pending,
diff --git a/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts b/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts
index 14e17abb..3780b8e8 100644
--- a/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts
+++ b/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts
@@ -1,6 +1,6 @@
import { promises as fs } from 'fs';
import { SchemaUnion, Type } from "@google/genai"; // Assuming these types exist
-import { GeminiClient } from "../core/GeminiClient.js"; // Assuming this path
+import { GeminiClient } from "../core/gemini-client.js"; // Assuming this path
import { exec } from 'child_process'; // Needed for Windows process check
import { promisify } from 'util'; // To promisify exec