Initial commit of Gemini Code CLI

This commit introduces the initial codebase for the Gemini Code CLI, a command-line interface designed to facilitate interaction with the Gemini API for software engineering tasks.

The code was migrated from a previous git repository as a single squashed commit.

Core Features & Components:

*   **Gemini Integration:** Leverages the `@google/genai` SDK to interact with the Gemini models, supporting chat history, streaming responses, and function calling (tools).
*   **Terminal UI:** Built with Ink (React for CLIs) providing an interactive chat interface within the terminal, including input prompts, message display, loading indicators, and tool interaction elements.
*   **Tooling Framework:** Implements a robust tool system allowing Gemini to interact with the local environment. Includes tools for:
    *   File system listing (`ls`)
    *   File reading (`read-file`)
    *   Content searching (`grep`)
    *   File globbing (`glob`)
    *   File editing (`edit`)
    *   File writing (`write-file`)
    *   Executing bash commands (`terminal`)
*   **State Management:** Handles the streaming state of Gemini responses and manages the conversation history.
*   **Configuration:** Parses command-line arguments (`yargs`) and loads environment variables (`dotenv`) for setup.
*   **Project Structure:** Organized into `core`, `ui`, `tools`, `config`, and `utils` directories using TypeScript. Includes basic build (`tsc`) and start scripts.

This initial version establishes the foundation for a powerful CLI tool enabling developers to use Gemini for coding assistance directly in their terminal environment.

---
Created by yours truly: __Gemini Code__
This commit is contained in:
Taylor Mullen
2025-04-15 21:41:08 -07:00
commit add233c504
54 changed files with 7920 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
import React, { useState, useEffect } from 'react';
import { Box, Text } from 'ink';
import type { HistoryItem } from './types.js';
import { useGeminiStream } from './hooks/useGeminiStream.js';
import { useLoadingIndicator } from './hooks/useLoadingIndicator.js';
import Header from './components/Header.js';
import Tips from './components/Tips.js';
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 { PartListUnion } from '@google/genai';
interface AppProps {
directory: string;
}
const App = ({ directory }: AppProps) => {
const [query, setQuery] = useState('');
const [history, setHistory] = useState<HistoryItem[]>([]);
const { streamingState, submitQuery, initError } = useGeminiStream(setHistory);
const { elapsedTime, currentLoadingPhrase } = useLoadingIndicator(streamingState);
const handleInputSubmit = (value: PartListUnion) => {
submitQuery(value).then(() => {
setQuery('');
}).catch(() => {
setQuery('');
});
};
useEffect(() => {
if (initError && !history.some(item => item.type === 'error' && item.text?.includes(initError))) {
setHistory(prev => [
...prev,
{ id: Date.now(), type: 'error', text: `Initialization Error: ${initError}. Please check API key and configuration.` } as HistoryItem
]);
}
}, [initError, history]);
const isWaitingForToolConfirmation = history.some(item =>
item.type === 'tool_group' && item.tools.some(tool => tool.confirmationDetails !== undefined)
);
const isInputActive = streamingState === StreamingState.Idle && !initError;
return (
<Box flexDirection="column" padding={1} marginBottom={1} width="100%">
<Header cwd={directory} />
<Tips />
{initError && streamingState !== StreamingState.Responding && !isWaitingForToolConfirmation && (
<Box borderStyle="round" borderColor="red" paddingX={1} marginBottom={1}>
{history.find(item => item.type === 'error' && item.text?.includes(initError))?.text ? (
<Text color="red">{history.find(item => item.type === 'error' && item.text?.includes(initError))?.text}</Text>
) : (
<>
<Text color="red">Initialization Error: {initError}</Text>
<Text color="red"> Please check API key and configuration.</Text>
</>
)}
</Box>
)}
<Box flexDirection="column">
<HistoryDisplay history={history} onSubmit={handleInputSubmit} />
<LoadingIndicator
isLoading={streamingState === StreamingState.Responding}
currentLoadingPhrase={currentLoadingPhrase}
elapsedTime={elapsedTime}
/>
</Box>
{!isWaitingForToolConfirmation && isInputActive && (
<InputPrompt
query={query}
setQuery={setQuery}
onSubmit={handleInputSubmit}
isActive={isInputActive}
/>
)}
<Footer queryLength={query.length} />
</Box>
);
};
export default App;