diff options
| author | Taylor Mullen <[email protected]> | 2025-04-18 18:08:43 -0400 |
|---|---|---|
| committer | N. Taylor Mullen <[email protected]> | 2025-04-18 18:10:57 -0400 |
| commit | 383b9177848eeefb8c123a7a7ecc0ee391380eea (patch) | |
| tree | 4b1e06d5e74500ad81a61f9442581648063f86c0 /packages/cli/src | |
| parent | fa264e42863474a809d06ef569f7ad5388d48072 (diff) | |
Run `npm run format`
- This has the entirety of the changes.
Part of https://b.corp.google.com/issues/411720532
Diffstat (limited to 'packages/cli/src')
19 files changed, 136 insertions, 142 deletions
diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index f02fea98..28e755e8 100644 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -35,7 +35,7 @@ export function loadConfig(): Config { loadEnvironment(); const argv = parseArguments(); return new Config( - process.env.GEMINI_API_KEY || "", + process.env.GEMINI_API_KEY || '', argv.model || process.env.GEMINI_API_KEY || DEFAULT_GEMINI_MODEL, argv.target_dir || process.cwd(), ); @@ -66,15 +66,13 @@ function parseArguments(): CliArgs { }) .help() .alias('h', 'help') - .strict() // Keep strict mode to error on unknown options - .argv; + .strict().argv; // Keep strict mode to error on unknown options // Cast to the interface to ensure the structure aligns with expectations // Use `unknown` first for safer casting if types might not perfectly match return argv as unknown as CliArgs; } - function findEnvFile(startDir: string): string | null { // Start search from the provided directory (e.g., current working directory) let currentDir = path.resolve(startDir); // Ensure absolute path diff --git a/packages/cli/src/core/gemini-client.ts b/packages/cli/src/core/gemini-client.ts index 64bf87a3..a488b982 100644 --- a/packages/cli/src/core/gemini-client.ts +++ b/packages/cli/src/core/gemini-client.ts @@ -21,7 +21,6 @@ import { getFolderStructure } from '../utils/getFolderStructure.js'; import { GeminiEventType, GeminiStream } from './gemini-stream.js'; import { Config } from '../config/config.js'; - type ToolExecutionOutcome = { callId: string; name: string; diff --git a/packages/cli/src/core/gemini-stream.ts b/packages/cli/src/core/gemini-stream.ts index 70361f10..0e3ca025 100644 --- a/packages/cli/src/core/gemini-stream.ts +++ b/packages/cli/src/core/gemini-stream.ts @@ -1,4 +1,4 @@ -import { ToolCallEvent , HistoryItem } from '../ui/types.js'; +import { ToolCallEvent, HistoryItem } from '../ui/types.js'; import { Part } from '@google/genai'; import { handleToolCallChunk, @@ -161,7 +161,11 @@ export const processGeminiStream = async ({ renderTimeoutId = null; } // Delegate history update for error message - addErrorMessageToHistory(error as (Error | DOMException), setHistory, getNextMessageId); + addErrorMessageToHistory( + error as Error | DOMException, + setHistory, + getNextMessageId, + ); } finally { isStreamComplete = true; // Signal stream end for render loop completion if (renderTimeoutId) { diff --git a/packages/cli/src/tools/ls.tool.ts b/packages/cli/src/tools/ls.tool.ts index d2f6a3c7..4b015fa5 100644 --- a/packages/cli/src/tools/ls.tool.ts +++ b/packages/cli/src/tools/ls.tool.ts @@ -116,8 +116,12 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> { * @returns An error message string if invalid, null otherwise */ validateToolParams(params: LSToolParams): string | null { - if (this.schema.parameters && - !SchemaValidator.validate(this.schema.parameters as Record<string, unknown>, params) + if ( + this.schema.parameters && + !SchemaValidator.validate( + this.schema.parameters as Record<string, unknown>, + params, + ) ) { return 'Parameters failed schema validation.'; } @@ -181,7 +185,8 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> { if (validationError) { return this.errorResult( `Error: Invalid parameters provided. Reason: ${validationError}`, - `Failed to execute tool.`); + `Failed to execute tool.`, + ); } try { @@ -189,12 +194,14 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> { if (!stats) { return this.errorResult( `Directory does not exist: ${params.path}`, - `Directory does not exist.`); + `Directory does not exist.`, + ); } if (!stats.isDirectory()) { return this.errorResult( `Path is not a directory: ${params.path}`, - `Path is not a directory.`); + `Path is not a directory.`, + ); } const files = fs.readdirSync(params.path); @@ -202,7 +209,8 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> { if (files.length === 0) { return this.errorResult( `Directory is empty: ${params.path}`, - `Directory is empty.`); + `Directory is empty.`, + ); } for (const file of files) { @@ -249,7 +257,8 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> { } catch (error) { return this.errorResult( `Error listing directory: ${error instanceof Error ? error.message : String(error)}`, - 'Failed to list directory.'); + 'Failed to list directory.', + ); } } } diff --git a/packages/cli/src/tools/read-file.tool.ts b/packages/cli/src/tools/read-file.tool.ts index feb9cbae..9bc10491 100644 --- a/packages/cli/src/tools/read-file.tool.ts +++ b/packages/cli/src/tools/read-file.tool.ts @@ -27,10 +27,7 @@ export interface ReadFileToolParams { /** * Implementation of the ReadFile tool that reads files from the filesystem */ -export class ReadFileTool extends BaseTool< - ReadFileToolParams, - ToolResult -> { +export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> { static readonly Name: string = 'read_file'; // Maximum number of lines to read by default diff --git a/packages/cli/src/tools/terminal.tool.ts b/packages/cli/src/tools/terminal.tool.ts index 1049a224..dacfb0be 100644 --- a/packages/cli/src/tools/terminal.tool.ts +++ b/packages/cli/src/tools/terminal.tool.ts @@ -115,10 +115,7 @@ interface QueuedCommand { /** * Implementation of the terminal tool that executes shell commands within a persistent session. */ -export class TerminalTool extends BaseTool< - TerminalToolParams, - ToolResult -> { +export class TerminalTool extends BaseTool<TerminalToolParams, ToolResult> { static Name: string = 'execute_bash_command'; private readonly rootDirectory: string; @@ -134,10 +131,7 @@ export class TerminalTool extends BaseTool< private rejectShellReady: ((reason?: unknown) => void) | undefined; // Definite assignment assertion private readonly backgroundTerminalAnalyzer: BackgroundTerminalAnalyzer; - constructor( - rootDirectory: string, - outputLimit: number = MAX_OUTPUT_LENGTH, - ) { + constructor(rootDirectory: string, outputLimit: number = MAX_OUTPUT_LENGTH) { const toolDisplayName = 'Terminal'; // --- LLM-Facing Description --- // Updated description for background tasks to mention polling and LLM analysis @@ -454,9 +448,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es // Define temp file paths here to be accessible throughout let tempStdoutPath: string | null = null; let tempStderrPath: string | null = null; - let originalResolve: ( - value: ToolResult | PromiseLike<ToolResult>, - ) => void; // To pass to polling + let originalResolve: (value: ToolResult | PromiseLike<ToolResult>) => void; // To pass to polling let originalReject: (reason?: unknown) => void; const promise = new Promise<ToolResult>((resolve, reject) => { @@ -939,9 +931,7 @@ Use this tool for running build steps (\`npm install\`, \`make\`), linters (\`es initialStderr: string, // Stderr during launch phase tempStdoutPath: string, // Path to redirected stdout tempStderrPath: string, // Path to redirected stderr - resolve: ( - value: ToolResult | PromiseLike<ToolResult>, - ) => void, // The original promise's resolve + resolve: (value: ToolResult | PromiseLike<ToolResult>) => void, // The original promise's resolve ): Promise<void> { // This function manages its own lifecycle but resolves the outer promise let finalStdout = ''; diff --git a/packages/cli/src/tools/web-fetch.tool.ts b/packages/cli/src/tools/web-fetch.tool.ts index 74467605..4fc1e45e 100644 --- a/packages/cli/src/tools/web-fetch.tool.ts +++ b/packages/cli/src/tools/web-fetch.tool.ts @@ -90,9 +90,7 @@ export class WebFetchTool extends BaseTool< getDescription(params: WebFetchToolParams): string { // Shorten long URLs for display const displayUrl = - params.url.length > 80 - ? params.url.substring(0, 77) + '...' - : params.url; + params.url.length > 80 ? params.url.substring(0, 77) + '...' : params.url; return `Fetching content from ${displayUrl}`; } @@ -130,7 +128,7 @@ export class WebFetchTool extends BaseTool< headers: { 'User-Agent': 'GeminiCode-CLI/1.0', }, - signal: AbortSignal.timeout(15000) // 15 seconds timeout + signal: AbortSignal.timeout(15000), // 15 seconds timeout }); if (!response.ok) { diff --git a/packages/cli/src/tools/write-file.tool.ts b/packages/cli/src/tools/write-file.tool.ts index cc0d5511..af0adc8d 100644 --- a/packages/cli/src/tools/write-file.tool.ts +++ b/packages/cli/src/tools/write-file.tool.ts @@ -28,10 +28,7 @@ export interface WriteFileToolParams { /** * Implementation of the WriteFile tool that writes files to the filesystem */ -export class WriteFileTool extends BaseTool< - WriteFileToolParams, - ToolResult -> { +export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> { static readonly Name: string = 'write_file'; private shouldAlwaysWrite = false; diff --git a/packages/cli/src/ui/components/Footer.tsx b/packages/cli/src/ui/components/Footer.tsx index 6b069a2f..f2afc1bd 100644 --- a/packages/cli/src/ui/components/Footer.tsx +++ b/packages/cli/src/ui/components/Footer.tsx @@ -6,12 +6,12 @@ interface FooterProps { } const Footer: React.FC<FooterProps> = ({ queryLength }) => ( - <Box marginTop={1} justifyContent="space-between"> - <Box minWidth={15}> - <Text color="gray">{queryLength === 0 ? '? for shortcuts' : ''}</Text> - </Box> - <Text color="blue">Gemini</Text> + <Box marginTop={1} justifyContent="space-between"> + <Box minWidth={15}> + <Text color="gray">{queryLength === 0 ? '? for shortcuts' : ''}</Text> </Box> - ); + <Text color="blue">Gemini</Text> + </Box> +); export default Footer; diff --git a/packages/cli/src/ui/components/Header.tsx b/packages/cli/src/ui/components/Header.tsx index d3f0f9d5..f8f7d27e 100644 --- a/packages/cli/src/ui/components/Header.tsx +++ b/packages/cli/src/ui/components/Header.tsx @@ -8,31 +8,31 @@ interface HeaderProps { } const Header: React.FC<HeaderProps> = ({ cwd }) => ( - <> - {/* Static Header Art */} - <Box marginBottom={1}> - <Text color="blue">{` + <> + {/* Static Header Art */} + <Box marginBottom={1}> + <Text color="blue">{` ______ ________ ____ ____ _____ ____ _____ _____ .' ___ ||_ __ ||_ \\ / _||_ _||_ \\|_ _||_ _| / .' \\_| | |_ \\_| | \\/ | | | | \\ | | | | | | ____ | _| _ | |\\ /| | | | | |\\ \\| | | | \\ \`.___] |_| |__/ | _| |_\\/_| |_ _| |_ _| |_\\ |_ _| |_ \`._____.'|________||_____||_____||_____||_____|\\____||_____|`}</Text> + </Box> + {/* CWD Display */} + <Box + borderStyle="round" + borderColor="blue" + paddingX={BOX_PADDING_X} + flexDirection="column" + marginBottom={1} + width={UI_WIDTH} + > + <Box paddingLeft={2}> + <Text color="gray">cwd: {shortenPath(cwd, /*maxLength*/ 70)}</Text> </Box> - {/* CWD Display */} - <Box - borderStyle="round" - borderColor="blue" - paddingX={BOX_PADDING_X} - flexDirection="column" - marginBottom={1} - width={UI_WIDTH} - > - <Box paddingLeft={2}> - <Text color="gray">cwd: {shortenPath(cwd, /*maxLength*/ 70)}</Text> - </Box> - </Box> - </> - ); + </Box> + </> +); export default Header; diff --git a/packages/cli/src/ui/components/HistoryDisplay.tsx b/packages/cli/src/ui/components/HistoryDisplay.tsx index fe0bf4c1..7565c5bc 100644 --- a/packages/cli/src/ui/components/HistoryDisplay.tsx +++ b/packages/cli/src/ui/components/HistoryDisplay.tsx @@ -17,26 +17,23 @@ interface HistoryDisplayProps { const HistoryDisplay: React.FC<HistoryDisplayProps> = ({ history, onSubmit, -}) => +}) => ( // No grouping logic needed here anymore - ( - <Box flexDirection="column"> - {history.map((item) => ( - <Box key={item.id} marginBottom={1}> - {/* Render standard message types */} - {item.type === 'user' && <UserMessage text={item.text} />} - {item.type === 'gemini' && <GeminiMessage text={item.text} />} - {item.type === 'info' && <InfoMessage text={item.text} />} - {item.type === 'error' && <ErrorMessage text={item.text} />} - - {/* Render the tool group component */} - {item.type === 'tool_group' && ( - <ToolGroupMessage toolCalls={item.tools} onSubmit={onSubmit} /> - )} - </Box> - ))} - </Box> - ) -; + <Box flexDirection="column"> + {history.map((item) => ( + <Box key={item.id} marginBottom={1}> + {/* Render standard message types */} + {item.type === 'user' && <UserMessage text={item.text} />} + {item.type === 'gemini' && <GeminiMessage text={item.text} />} + {item.type === 'info' && <InfoMessage text={item.text} />} + {item.type === 'error' && <ErrorMessage text={item.text} />} + {/* Render the tool group component */} + {item.type === 'tool_group' && ( + <ToolGroupMessage toolCalls={item.tools} onSubmit={onSubmit} /> + )} + </Box> + ))} + </Box> +); export default HistoryDisplay; diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx index 1102e75d..96089eec 100644 --- a/packages/cli/src/ui/components/InputPrompt.tsx +++ b/packages/cli/src/ui/components/InputPrompt.tsx @@ -3,8 +3,6 @@ import { Box, Text } from 'ink'; import TextInput from 'ink-text-input'; import { globalConfig } from '../../config/config.js'; - - interface InputPromptProps { query: string; setQuery: (value: string) => void; @@ -34,6 +32,6 @@ const InputPrompt: React.FC<InputPromptProps> = ({ </Box> </Box> ); -} +}; export default InputPrompt; diff --git a/packages/cli/src/ui/components/Tips.tsx b/packages/cli/src/ui/components/Tips.tsx index 6be53360..aa8d39d6 100644 --- a/packages/cli/src/ui/components/Tips.tsx +++ b/packages/cli/src/ui/components/Tips.tsx @@ -3,18 +3,18 @@ import { Box, Text } from 'ink'; import { UI_WIDTH } from '../constants.js'; const Tips: React.FC = () => ( - <Box flexDirection="column" marginBottom={1} width={UI_WIDTH}> - <Text>Tips for getting started:</Text> - <Text> - 1. <Text bold>/help</Text> for more information. - </Text> - <Text> - 2. <Text bold>/init</Text> to create a GEMINI.md for instructions & - context. - </Text> - <Text>3. Ask coding questions, edit code or run commands.</Text> - <Text>4. Be specific for the best results.</Text> - </Box> - ); + <Box flexDirection="column" marginBottom={1} width={UI_WIDTH}> + <Text>Tips for getting started:</Text> + <Text> + 1. <Text bold>/help</Text> for more information. + </Text> + <Text> + 2. <Text bold>/init</Text> to create a GEMINI.md for instructions & + context. + </Text> + <Text>3. Ask coding questions, edit code or run commands.</Text> + <Text>4. Be specific for the best results.</Text> + </Box> +); export default Tips; diff --git a/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx b/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx index 6627faee..6644cd5f 100644 --- a/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx @@ -21,23 +21,23 @@ const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({ return ( <Box flexDirection="column" borderStyle="round" borderColor={borderColor}> {toolCalls.map((tool) => ( - <React.Fragment key={tool.callId}> - <ToolMessage - key={tool.callId} // Use callId as the key - name={tool.name} - description={tool.description} - resultDisplay={tool.resultDisplay} - status={tool.status} - /> - {tool.status === ToolCallStatus.Confirming && - tool.confirmationDetails && ( - <ToolConfirmationMessage - confirmationDetails={tool.confirmationDetails} - onSubmit={onSubmit} - ></ToolConfirmationMessage> - )} - </React.Fragment> - ))} + <React.Fragment key={tool.callId}> + <ToolMessage + key={tool.callId} // Use callId as the key + name={tool.name} + description={tool.description} + resultDisplay={tool.resultDisplay} + status={tool.status} + /> + {tool.status === ToolCallStatus.Confirming && + tool.confirmationDetails && ( + <ToolConfirmationMessage + confirmationDetails={tool.confirmationDetails} + onSubmit={onSubmit} + ></ToolConfirmationMessage> + )} + </React.Fragment> + ))} {/* Optional: Add padding below the last item if needed, though ToolMessage already has some vertical space implicitly */} {/* {tools.length > 0 && <Box height={1} />} */} diff --git a/packages/cli/src/ui/hooks/useAppEffects.ts b/packages/cli/src/ui/hooks/useAppEffects.ts index 16f862b0..7bd7c6d6 100644 --- a/packages/cli/src/ui/hooks/useAppEffects.ts +++ b/packages/cli/src/ui/hooks/useAppEffects.ts @@ -58,4 +58,4 @@ export function useInitializationErrorEffect( ]); } }, [initError, history, setHistory]); // Include setHistory in dependency array -}
\ No newline at end of file +} diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts index f97f5e27..7fffa3fe 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.ts +++ b/packages/cli/src/ui/hooks/useGeminiStream.ts @@ -3,7 +3,10 @@ import { useInput } from 'ink'; import { GeminiClient } from '../../core/gemini-client.js'; import { type Chat, type PartListUnion } from '@google/genai'; import { HistoryItem } from '../types.js'; -import { processGeminiStream , StreamingState } from '../../core/gemini-stream.js'; +import { + processGeminiStream, + StreamingState, +} from '../../core/gemini-stream.js'; import { globalConfig } from '../../config/config.js'; import { getErrorMessage, isNodeError } from '../../utils/errors.js'; diff --git a/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts b/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts index 10448859..ae02e571 100644 --- a/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts +++ b/packages/cli/src/utils/BackgroundTerminalAnalyzer.ts @@ -14,7 +14,7 @@ export interface AiClient { generateJson( prompt: Content[], // Keep flexible or define a stricter prompt structure type schema: SchemaUnion, - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any ): Promise<any>; // Ideally, specify the expected JSON structure TAnalysisResult | TAnalysisFailure } @@ -127,10 +127,14 @@ export class BackgroundTerminalAnalyzer { // Reread files one last time in case output was written just before exit try { currentStdout = await fs.readFile(tempStdoutFilePath, 'utf-8'); - } catch { /* ignore */ } + } catch { + /* ignore */ + } try { currentStderr = await fs.readFile(tempStderrFilePath, 'utf-8'); - } catch { /* ignore */ } + } catch { + /* ignore */ + } lastAnalysisResult = await this.analyzeOutputWithLLM( currentStdout, diff --git a/packages/cli/src/utils/errors.ts b/packages/cli/src/utils/errors.ts index 7708895a..a7fcc5a3 100644 --- a/packages/cli/src/utils/errors.ts +++ b/packages/cli/src/utils/errors.ts @@ -1,18 +1,18 @@ export function isNodeError(error: unknown): error is NodeJS.ErrnoException { - return error instanceof Error && 'code' in error; + return error instanceof Error && 'code' in error; } export function getErrorMessage(error: unknown): string { - if (error instanceof Error) { - return error.message; - } else { - // Attempt to convert the non-Error value to a string for logging - try { - const errorMessage = String(error); - return errorMessage; - } catch { - // If String() itself fails (highly unlikely) - return 'Failed to get error details'; - } - } -}
\ No newline at end of file + if (error instanceof Error) { + return error.message; + } else { + // Attempt to convert the non-Error value to a string for logging + try { + const errorMessage = String(error); + return errorMessage; + } catch { + // If String() itself fails (highly unlikely) + return 'Failed to get error details'; + } + } +} diff --git a/packages/cli/src/utils/getFolderStructure.ts b/packages/cli/src/utils/getFolderStructure.ts index 8192fc96..42d6bbc3 100644 --- a/packages/cli/src/utils/getFolderStructure.ts +++ b/packages/cli/src/utils/getFolderStructure.ts @@ -137,7 +137,10 @@ async function readFullStructure( folderInfo.subFolders.length + folderInfo.subFolders.reduce((sum, sf) => sum + sf.totalChildren, 0); } catch (error: unknown) { - if (isNodeError(error) && (error.code === 'EACCES' || error.code === 'ENOENT')) { + if ( + isNodeError(error) && + (error.code === 'EACCES' || error.code === 'ENOENT') + ) { console.warn( `Warning: Could not read directory ${folderPath}: ${error.message}`, ); @@ -345,10 +348,7 @@ export async function getFolderStructure( } // 2. Reduce the structure (handles ignored folders specifically) - const reducedRoot = reduceStructure( - fullInfo, - mergedOptions.maxItems, - ); + const reducedRoot = reduceStructure(fullInfo, mergedOptions.maxItems); // 3. Count items in the *reduced* structure for the summary const rootNodeItselfCount = 0; // Don't count the root node in the items summary |
