Run `npm run format`

- This has the entirety of the changes.

Part of https://b.corp.google.com/issues/411720532
This commit is contained in:
Taylor Mullen 2025-04-18 18:08:43 -04:00 committed by N. Taylor Mullen
parent fa264e4286
commit 383b917784
26 changed files with 211 additions and 208 deletions

View File

@ -4,9 +4,9 @@ name: Gemini Code CI
on: on:
push: push:
branches: [ main ] # Run on pushes to the main branch branches: [main] # Run on pushes to the main branch
pull_request: pull_request:
branches: [ main ] # Run on pull requests targeting the main branch branches: [main] # Run on pull requests targeting the main branch
jobs: jobs:
build_and_test: build_and_test:
@ -16,7 +16,7 @@ jobs:
strategy: strategy:
matrix: matrix:
# Specify the Node.js versions you want to test against # Specify the Node.js versions you want to test against
node-version: [ 20.x ] # You can add more like [18.x, 20.x] node-version: [20.x] # You can add more like [18.x, 20.x]
steps: steps:
# 1. Checkout Code # 1. Checkout Code

View File

@ -35,7 +35,7 @@ export function loadConfig(): Config {
loadEnvironment(); loadEnvironment();
const argv = parseArguments(); const argv = parseArguments();
return new Config( return new Config(
process.env.GEMINI_API_KEY || "", process.env.GEMINI_API_KEY || '',
argv.model || process.env.GEMINI_API_KEY || DEFAULT_GEMINI_MODEL, argv.model || process.env.GEMINI_API_KEY || DEFAULT_GEMINI_MODEL,
argv.target_dir || process.cwd(), argv.target_dir || process.cwd(),
); );
@ -66,15 +66,13 @@ function parseArguments(): CliArgs {
}) })
.help() .help()
.alias('h', 'help') .alias('h', 'help')
.strict() // Keep strict mode to error on unknown options .strict().argv; // Keep strict mode to error on unknown options
.argv;
// Cast to the interface to ensure the structure aligns with expectations // Cast to the interface to ensure the structure aligns with expectations
// Use `unknown` first for safer casting if types might not perfectly match // Use `unknown` first for safer casting if types might not perfectly match
return argv as unknown as CliArgs; return argv as unknown as CliArgs;
} }
function findEnvFile(startDir: string): string | null { function findEnvFile(startDir: string): string | null {
// Start search from the provided directory (e.g., current working directory) // Start search from the provided directory (e.g., current working directory)
let currentDir = path.resolve(startDir); // Ensure absolute path let currentDir = path.resolve(startDir); // Ensure absolute path

View File

@ -21,7 +21,6 @@ import { getFolderStructure } from '../utils/getFolderStructure.js';
import { GeminiEventType, GeminiStream } from './gemini-stream.js'; import { GeminiEventType, GeminiStream } from './gemini-stream.js';
import { Config } from '../config/config.js'; import { Config } from '../config/config.js';
type ToolExecutionOutcome = { type ToolExecutionOutcome = {
callId: string; callId: string;
name: string; name: string;

View File

@ -1,4 +1,4 @@
import { ToolCallEvent , HistoryItem } from '../ui/types.js'; import { ToolCallEvent, HistoryItem } from '../ui/types.js';
import { Part } from '@google/genai'; import { Part } from '@google/genai';
import { import {
handleToolCallChunk, handleToolCallChunk,
@ -161,7 +161,11 @@ export const processGeminiStream = async ({
renderTimeoutId = null; renderTimeoutId = null;
} }
// Delegate history update for error message // Delegate history update for error message
addErrorMessageToHistory(error as (Error | DOMException), setHistory, getNextMessageId); addErrorMessageToHistory(
error as Error | DOMException,
setHistory,
getNextMessageId,
);
} finally { } finally {
isStreamComplete = true; // Signal stream end for render loop completion isStreamComplete = true; // Signal stream end for render loop completion
if (renderTimeoutId) { if (renderTimeoutId) {

View File

@ -116,8 +116,12 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> {
* @returns An error message string if invalid, null otherwise * @returns An error message string if invalid, null otherwise
*/ */
validateToolParams(params: LSToolParams): string | null { validateToolParams(params: LSToolParams): string | null {
if (this.schema.parameters && if (
!SchemaValidator.validate(this.schema.parameters as Record<string, unknown>, params) this.schema.parameters &&
!SchemaValidator.validate(
this.schema.parameters as Record<string, unknown>,
params,
)
) { ) {
return 'Parameters failed schema validation.'; return 'Parameters failed schema validation.';
} }
@ -181,7 +185,8 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> {
if (validationError) { if (validationError) {
return this.errorResult( return this.errorResult(
`Error: Invalid parameters provided. Reason: ${validationError}`, `Error: Invalid parameters provided. Reason: ${validationError}`,
`Failed to execute tool.`); `Failed to execute tool.`,
);
} }
try { try {
@ -189,12 +194,14 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> {
if (!stats) { if (!stats) {
return this.errorResult( return this.errorResult(
`Directory does not exist: ${params.path}`, `Directory does not exist: ${params.path}`,
`Directory does not exist.`); `Directory does not exist.`,
);
} }
if (!stats.isDirectory()) { if (!stats.isDirectory()) {
return this.errorResult( return this.errorResult(
`Path is not a directory: ${params.path}`, `Path is not a directory: ${params.path}`,
`Path is not a directory.`); `Path is not a directory.`,
);
} }
const files = fs.readdirSync(params.path); const files = fs.readdirSync(params.path);
@ -202,7 +209,8 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> {
if (files.length === 0) { if (files.length === 0) {
return this.errorResult( return this.errorResult(
`Directory is empty: ${params.path}`, `Directory is empty: ${params.path}`,
`Directory is empty.`); `Directory is empty.`,
);
} }
for (const file of files) { for (const file of files) {
@ -249,7 +257,8 @@ export class LSTool extends BaseTool<LSToolParams, ToolResult> {
} catch (error) { } catch (error) {
return this.errorResult( return this.errorResult(
`Error listing directory: ${error instanceof Error ? error.message : String(error)}`, `Error listing directory: ${error instanceof Error ? error.message : String(error)}`,
'Failed to list directory.'); 'Failed to list directory.',
);
} }
} }
} }

View File

@ -27,10 +27,7 @@ export interface ReadFileToolParams {
/** /**
* Implementation of the ReadFile tool that reads files from the filesystem * Implementation of the ReadFile tool that reads files from the filesystem
*/ */
export class ReadFileTool extends BaseTool< export class ReadFileTool extends BaseTool<ReadFileToolParams, ToolResult> {
ReadFileToolParams,
ToolResult
> {
static readonly Name: string = 'read_file'; static readonly Name: string = 'read_file';
// Maximum number of lines to read by default // Maximum number of lines to read by default

View File

@ -115,10 +115,7 @@ interface QueuedCommand {
/** /**
* Implementation of the terminal tool that executes shell commands within a persistent session. * Implementation of the terminal tool that executes shell commands within a persistent session.
*/ */
export class TerminalTool extends BaseTool< export class TerminalTool extends BaseTool<TerminalToolParams, ToolResult> {
TerminalToolParams,
ToolResult
> {
static Name: string = 'execute_bash_command'; static Name: string = 'execute_bash_command';
private readonly rootDirectory: string; private readonly rootDirectory: string;
@ -134,10 +131,7 @@ export class TerminalTool extends BaseTool<
private rejectShellReady: ((reason?: unknown) => void) | undefined; // Definite assignment assertion private rejectShellReady: ((reason?: unknown) => void) | undefined; // Definite assignment assertion
private readonly backgroundTerminalAnalyzer: BackgroundTerminalAnalyzer; private readonly backgroundTerminalAnalyzer: BackgroundTerminalAnalyzer;
constructor( constructor(rootDirectory: string, outputLimit: number = MAX_OUTPUT_LENGTH) {
rootDirectory: string,
outputLimit: number = MAX_OUTPUT_LENGTH,
) {
const toolDisplayName = 'Terminal'; const toolDisplayName = 'Terminal';
// --- LLM-Facing Description --- // --- LLM-Facing Description ---
// Updated description for background tasks to mention polling and LLM analysis // 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 // Define temp file paths here to be accessible throughout
let tempStdoutPath: string | null = null; let tempStdoutPath: string | null = null;
let tempStderrPath: string | null = null; let tempStderrPath: string | null = null;
let originalResolve: ( let originalResolve: (value: ToolResult | PromiseLike<ToolResult>) => void; // To pass to polling
value: ToolResult | PromiseLike<ToolResult>,
) => void; // To pass to polling
let originalReject: (reason?: unknown) => void; let originalReject: (reason?: unknown) => void;
const promise = new Promise<ToolResult>((resolve, reject) => { 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 initialStderr: string, // Stderr during launch phase
tempStdoutPath: string, // Path to redirected stdout tempStdoutPath: string, // Path to redirected stdout
tempStderrPath: string, // Path to redirected stderr tempStderrPath: string, // Path to redirected stderr
resolve: ( resolve: (value: ToolResult | PromiseLike<ToolResult>) => void, // The original promise's resolve
value: ToolResult | PromiseLike<ToolResult>,
) => void, // The original promise's resolve
): Promise<void> { ): Promise<void> {
// This function manages its own lifecycle but resolves the outer promise // This function manages its own lifecycle but resolves the outer promise
let finalStdout = ''; let finalStdout = '';

View File

@ -90,9 +90,7 @@ export class WebFetchTool extends BaseTool<
getDescription(params: WebFetchToolParams): string { getDescription(params: WebFetchToolParams): string {
// Shorten long URLs for display // Shorten long URLs for display
const displayUrl = const displayUrl =
params.url.length > 80 params.url.length > 80 ? params.url.substring(0, 77) + '...' : params.url;
? params.url.substring(0, 77) + '...'
: params.url;
return `Fetching content from ${displayUrl}`; return `Fetching content from ${displayUrl}`;
} }
@ -130,7 +128,7 @@ export class WebFetchTool extends BaseTool<
headers: { headers: {
'User-Agent': 'GeminiCode-CLI/1.0', 'User-Agent': 'GeminiCode-CLI/1.0',
}, },
signal: AbortSignal.timeout(15000) // 15 seconds timeout signal: AbortSignal.timeout(15000), // 15 seconds timeout
}); });
if (!response.ok) { if (!response.ok) {

View File

@ -28,10 +28,7 @@ export interface WriteFileToolParams {
/** /**
* Implementation of the WriteFile tool that writes files to the filesystem * Implementation of the WriteFile tool that writes files to the filesystem
*/ */
export class WriteFileTool extends BaseTool< export class WriteFileTool extends BaseTool<WriteFileToolParams, ToolResult> {
WriteFileToolParams,
ToolResult
> {
static readonly Name: string = 'write_file'; static readonly Name: string = 'write_file';
private shouldAlwaysWrite = false; private shouldAlwaysWrite = false;

View File

@ -6,12 +6,12 @@ interface FooterProps {
} }
const Footer: React.FC<FooterProps> = ({ queryLength }) => ( const Footer: React.FC<FooterProps> = ({ queryLength }) => (
<Box marginTop={1} justifyContent="space-between"> <Box marginTop={1} justifyContent="space-between">
<Box minWidth={15}> <Box minWidth={15}>
<Text color="gray">{queryLength === 0 ? '? for shortcuts' : ''}</Text> <Text color="gray">{queryLength === 0 ? '? for shortcuts' : ''}</Text>
</Box>
<Text color="blue">Gemini</Text>
</Box> </Box>
); <Text color="blue">Gemini</Text>
</Box>
);
export default Footer; export default Footer;

View File

@ -8,31 +8,31 @@ interface HeaderProps {
} }
const Header: React.FC<HeaderProps> = ({ cwd }) => ( const Header: React.FC<HeaderProps> = ({ cwd }) => (
<> <>
{/* Static Header Art */} {/* Static Header Art */}
<Box marginBottom={1}> <Box marginBottom={1}>
<Text color="blue">{` <Text color="blue">{`
______ ________ ____ ____ _____ ____ _____ _____ ______ ________ ____ ____ _____ ____ _____ _____
.' ___ ||_ __ ||_ \\ / _||_ _||_ \\|_ _||_ _| .' ___ ||_ __ ||_ \\ / _||_ _||_ \\|_ _||_ _|
/ .' \\_| | |_ \\_| | \\/ | | | | \\ | | | | / .' \\_| | |_ \\_| | \\/ | | | | \\ | | | |
| | ____ | _| _ | |\\ /| | | | | |\\ \\| | | | | | ____ | _| _ | |\\ /| | | | | |\\ \\| | | |
\\ \`.___] |_| |__/ | _| |_\\/_| |_ _| |_ _| |_\\ |_ _| |_ \\ \`.___] |_| |__/ | _| |_\\/_| |_ _| |_ _| |_\\ |_ _| |_
\`._____.'|________||_____||_____||_____||_____|\\____||_____|`}</Text> \`._____.'|________||_____||_____||_____||_____|\\____||_____|`}</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>
{/* CWD Display */} </Box>
<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>
</>
);
export default Header; export default Header;

View File

@ -17,26 +17,23 @@ interface HistoryDisplayProps {
const HistoryDisplay: React.FC<HistoryDisplayProps> = ({ const HistoryDisplay: React.FC<HistoryDisplayProps> = ({
history, history,
onSubmit, onSubmit,
}) => }) => (
// No grouping logic needed here anymore // No grouping logic needed here anymore
( <Box flexDirection="column">
<Box flexDirection="column"> {history.map((item) => (
{history.map((item) => ( <Box key={item.id} marginBottom={1}>
<Box key={item.id} marginBottom={1}> {/* Render standard message types */}
{/* Render standard message types */} {item.type === 'user' && <UserMessage text={item.text} />}
{item.type === 'user' && <UserMessage text={item.text} />} {item.type === 'gemini' && <GeminiMessage text={item.text} />}
{item.type === 'gemini' && <GeminiMessage text={item.text} />} {item.type === 'info' && <InfoMessage text={item.text} />}
{item.type === 'info' && <InfoMessage text={item.text} />} {item.type === 'error' && <ErrorMessage 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>
)
;
{/* Render the tool group component */}
{item.type === 'tool_group' && (
<ToolGroupMessage toolCalls={item.tools} onSubmit={onSubmit} />
)}
</Box>
))}
</Box>
);
export default HistoryDisplay; export default HistoryDisplay;

View File

@ -3,8 +3,6 @@ import { Box, Text } from 'ink';
import TextInput from 'ink-text-input'; import TextInput from 'ink-text-input';
import { globalConfig } from '../../config/config.js'; import { globalConfig } from '../../config/config.js';
interface InputPromptProps { interface InputPromptProps {
query: string; query: string;
setQuery: (value: string) => void; setQuery: (value: string) => void;
@ -34,6 +32,6 @@ const InputPrompt: React.FC<InputPromptProps> = ({
</Box> </Box>
</Box> </Box>
); );
} };
export default InputPrompt; export default InputPrompt;

View File

@ -3,18 +3,18 @@ import { Box, Text } from 'ink';
import { UI_WIDTH } from '../constants.js'; import { UI_WIDTH } from '../constants.js';
const Tips: React.FC = () => ( const Tips: React.FC = () => (
<Box flexDirection="column" marginBottom={1} width={UI_WIDTH}> <Box flexDirection="column" marginBottom={1} width={UI_WIDTH}>
<Text>Tips for getting started:</Text> <Text>Tips for getting started:</Text>
<Text> <Text>
1. <Text bold>/help</Text> for more information. 1. <Text bold>/help</Text> for more information.
</Text> </Text>
<Text> <Text>
2. <Text bold>/init</Text> to create a GEMINI.md for instructions & 2. <Text bold>/init</Text> to create a GEMINI.md for instructions &
context. context.
</Text> </Text>
<Text>3. Ask coding questions, edit code or run commands.</Text> <Text>3. Ask coding questions, edit code or run commands.</Text>
<Text>4. Be specific for the best results.</Text> <Text>4. Be specific for the best results.</Text>
</Box> </Box>
); );
export default Tips; export default Tips;

View File

@ -21,23 +21,23 @@ const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
return ( return (
<Box flexDirection="column" borderStyle="round" borderColor={borderColor}> <Box flexDirection="column" borderStyle="round" borderColor={borderColor}>
{toolCalls.map((tool) => ( {toolCalls.map((tool) => (
<React.Fragment key={tool.callId}> <React.Fragment key={tool.callId}>
<ToolMessage <ToolMessage
key={tool.callId} // Use callId as the key key={tool.callId} // Use callId as the key
name={tool.name} name={tool.name}
description={tool.description} description={tool.description}
resultDisplay={tool.resultDisplay} resultDisplay={tool.resultDisplay}
status={tool.status} status={tool.status}
/> />
{tool.status === ToolCallStatus.Confirming && {tool.status === ToolCallStatus.Confirming &&
tool.confirmationDetails && ( tool.confirmationDetails && (
<ToolConfirmationMessage <ToolConfirmationMessage
confirmationDetails={tool.confirmationDetails} confirmationDetails={tool.confirmationDetails}
onSubmit={onSubmit} onSubmit={onSubmit}
></ToolConfirmationMessage> ></ToolConfirmationMessage>
)} )}
</React.Fragment> </React.Fragment>
))} ))}
{/* Optional: Add padding below the last item if needed, {/* Optional: Add padding below the last item if needed,
though ToolMessage already has some vertical space implicitly */} though ToolMessage already has some vertical space implicitly */}
{/* {tools.length > 0 && <Box height={1} />} */} {/* {tools.length > 0 && <Box height={1} />} */}

View File

@ -3,7 +3,10 @@ import { useInput } from 'ink';
import { GeminiClient } from '../../core/gemini-client.js'; import { GeminiClient } from '../../core/gemini-client.js';
import { type Chat, type PartListUnion } from '@google/genai'; import { type Chat, type PartListUnion } from '@google/genai';
import { HistoryItem } from '../types.js'; 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 { globalConfig } from '../../config/config.js';
import { getErrorMessage, isNodeError } from '../../utils/errors.js'; import { getErrorMessage, isNodeError } from '../../utils/errors.js';

View File

@ -14,7 +14,7 @@ export interface AiClient {
generateJson( generateJson(
prompt: Content[], // Keep flexible or define a stricter prompt structure type prompt: Content[], // Keep flexible or define a stricter prompt structure type
schema: SchemaUnion, 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 ): 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 // Reread files one last time in case output was written just before exit
try { try {
currentStdout = await fs.readFile(tempStdoutFilePath, 'utf-8'); currentStdout = await fs.readFile(tempStdoutFilePath, 'utf-8');
} catch { /* ignore */ } } catch {
/* ignore */
}
try { try {
currentStderr = await fs.readFile(tempStderrFilePath, 'utf-8'); currentStderr = await fs.readFile(tempStderrFilePath, 'utf-8');
} catch { /* ignore */ } } catch {
/* ignore */
}
lastAnalysisResult = await this.analyzeOutputWithLLM( lastAnalysisResult = await this.analyzeOutputWithLLM(
currentStdout, currentStdout,

View File

@ -1,18 +1,18 @@
export function isNodeError(error: unknown): error is NodeJS.ErrnoException { 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 { export function getErrorMessage(error: unknown): string {
if (error instanceof Error) { if (error instanceof Error) {
return error.message; return error.message;
} else { } else {
// Attempt to convert the non-Error value to a string for logging // Attempt to convert the non-Error value to a string for logging
try { try {
const errorMessage = String(error); const errorMessage = String(error);
return errorMessage; return errorMessage;
} catch { } catch {
// If String() itself fails (highly unlikely) // If String() itself fails (highly unlikely)
return 'Failed to get error details'; return 'Failed to get error details';
} }
} }
} }

View File

@ -137,7 +137,10 @@ async function readFullStructure(
folderInfo.subFolders.length + folderInfo.subFolders.length +
folderInfo.subFolders.reduce((sum, sf) => sum + sf.totalChildren, 0); folderInfo.subFolders.reduce((sum, sf) => sum + sf.totalChildren, 0);
} catch (error: unknown) { } catch (error: unknown) {
if (isNodeError(error) && (error.code === 'EACCES' || error.code === 'ENOENT')) { if (
isNodeError(error) &&
(error.code === 'EACCES' || error.code === 'ENOENT')
) {
console.warn( console.warn(
`Warning: Could not read directory ${folderPath}: ${error.message}`, `Warning: Could not read directory ${folderPath}: ${error.message}`,
); );
@ -345,10 +348,7 @@ export async function getFolderStructure(
} }
// 2. Reduce the structure (handles ignored folders specifically) // 2. Reduce the structure (handles ignored folders specifically)
const reducedRoot = reduceStructure( const reducedRoot = reduceStructure(fullInfo, mergedOptions.maxItems);
fullInfo,
mergedOptions.maxItems,
);
// 3. Count items in the *reduced* structure for the summary // 3. Count items in the *reduced* structure for the summary
const rootNodeItselfCount = 0; // Don't count the root node in the items summary const rootNodeItselfCount = 0; // Don't count the root node in the items summary

View File

@ -13,7 +13,5 @@
}, },
"exclude": ["node_modules", "dist"], "exclude": ["node_modules", "dist"],
"include": ["src"], "include": ["src"],
"references": [ "references": [{ "path": "../server" }]
{ "path": "../server" },
]
} }

View File

@ -1,24 +1,23 @@
{ {
"name": "@gemini-code/server", "name": "@gemini-code/server",
"version": "1.0.0", "version": "1.0.0",
"description": "Gemini Code Server", "description": "Gemini Code Server",
"type": "module", "type": "module",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {
"build": "tsc && cp package.json dist/", "build": "tsc && cp package.json dist/",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"lint": "eslint . --ext .ts,.tsx", "lint": "eslint . --ext .ts,.tsx",
"format": "prettier --write ." "format": "prettier --write ."
}, },
"files": [ "files": [
"dist" "dist"
], ],
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"typescript": "^5.3.3" "typescript": "^5.3.3"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"
}
} }
}

View File

@ -1,3 +1,3 @@
export function helloServer() { export function helloServer() {
// TODO: add more things in this package // TODO: add more things in this package
} }

View File

@ -1,13 +1,12 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"rootDir": ".", "rootDir": ".",
"lib": ["DOM", "DOM.Iterable", "ES2020"], "lib": ["DOM", "DOM.Iterable", "ES2020"],
"module": "Node16", "module": "Node16",
"target": "ES2022", "target": "ES2022",
"composite": true, "composite": true
}, },
"exclude": ["node_modules", "dist"], "exclude": ["node_modules", "dist"]
} }

View File

@ -6,7 +6,10 @@ import os from 'os'; // Import os module
const cliPackageDir = path.resolve('packages', 'cli'); // Base directory for the CLI package const cliPackageDir = path.resolve('packages', 'cli'); // Base directory for the CLI package
const buildTimestampPath = path.join(cliPackageDir, 'dist', '.last_build'); // Path to the timestamp file within the CLI package const buildTimestampPath = path.join(cliPackageDir, 'dist', '.last_build'); // Path to the timestamp file within the CLI package
const sourceDirs = [path.join(cliPackageDir, 'src')]; // Source directory within the CLI package const sourceDirs = [path.join(cliPackageDir, 'src')]; // Source directory within the CLI package
const filesToWatch = [path.join(cliPackageDir, 'package.json'), path.join(cliPackageDir, 'tsconfig.json')]; // Specific files within the CLI package const filesToWatch = [
path.join(cliPackageDir, 'package.json'),
path.join(cliPackageDir, 'tsconfig.json'),
]; // Specific files within the CLI package
const buildDir = path.join(cliPackageDir, 'dist'); // Build output directory within the CLI package const buildDir = path.join(cliPackageDir, 'dist'); // Build output directory within the CLI package
const warningsFilePath = path.join(os.tmpdir(), 'gemini-code-cli-warnings.txt'); // Temp file for warnings const warningsFilePath = path.join(os.tmpdir(), 'gemini-code-cli-warnings.txt'); // Temp file for warnings
// --------------------- // ---------------------
@ -28,7 +31,11 @@ function findSourceFiles(dir, allFiles = []) {
for (const entry of entries) { for (const entry of entries) {
const fullPath = path.join(dir, entry.name); const fullPath = path.join(dir, entry.name);
// Simple check to avoid recursing into node_modules or build dir itself // Simple check to avoid recursing into node_modules or build dir itself
if (entry.isDirectory() && entry.name !== 'node_modules' && fullPath !== buildDir) { if (
entry.isDirectory() &&
entry.name !== 'node_modules' &&
fullPath !== buildDir
) {
findSourceFiles(fullPath, allFiles); findSourceFiles(fullPath, allFiles);
} else if (entry.isFile()) { } else if (entry.isFile()) {
allFiles.push(fullPath); allFiles.push(fullPath);
@ -45,7 +52,9 @@ try {
fs.unlinkSync(warningsFilePath); fs.unlinkSync(warningsFilePath);
} }
} catch (err) { } catch (err) {
console.warn(`[Check Script] Warning: Could not delete previous warnings file: ${err.message}`); console.warn(
`[Check Script] Warning: Could not delete previous warnings file: ${err.message}`,
);
} }
const buildMtime = getMtime(buildTimestampPath); const buildMtime = getMtime(buildTimestampPath);
@ -56,7 +65,9 @@ if (!buildMtime) {
try { try {
fs.writeFileSync(warningsFilePath, errorMessage); fs.writeFileSync(warningsFilePath, errorMessage);
} catch (writeErr) { } catch (writeErr) {
console.error(`[Check Script] Error writing missing build warning file: ${writeErr.message}`); console.error(
`[Check Script] Error writing missing build warning file: ${writeErr.message}`,
);
} }
process.exit(0); // Allow app to start and show the error process.exit(0); // Allow app to start and show the error
} }
@ -67,25 +78,24 @@ const allSourceFiles = [];
// Collect files from specified directories // Collect files from specified directories
sourceDirs.forEach((dir) => { sourceDirs.forEach((dir) => {
const dirPath = path.resolve(dir); const dirPath = path.resolve(dir);
if (fs.existsSync(dirPath)) { if (fs.existsSync(dirPath)) {
findSourceFiles(dirPath, allSourceFiles); findSourceFiles(dirPath, allSourceFiles);
} else { } else {
console.warn(`Warning: Source directory "${dir}" not found.`); console.warn(`Warning: Source directory "${dir}" not found.`);
} }
}); });
// Add specific files // Add specific files
filesToWatch.forEach((file) => { filesToWatch.forEach((file) => {
const filePath = path.resolve(file); const filePath = path.resolve(file);
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
allSourceFiles.push(filePath); allSourceFiles.push(filePath);
} else { } else {
console.warn(`Warning: Watched file "${file}" not found.`); console.warn(`Warning: Watched file "${file}" not found.`);
} }
}); });
// Check modification times // Check modification times
for (const file of allSourceFiles) { for (const file of allSourceFiles) {
const sourceMtime = getMtime(file); const sourceMtime = getMtime(file);
@ -102,7 +112,8 @@ for (const file of allSourceFiles) {
} }
if (newerSourceFileFound) { if (newerSourceFileFound) {
const finalWarning = '\nRun "npm run build" to incorporate changes before starting.'; const finalWarning =
'\nRun "npm run build" to incorporate changes before starting.';
warningMessages.push(finalWarning); warningMessages.push(finalWarning);
console.warn(finalWarning); console.warn(finalWarning);
@ -118,11 +129,13 @@ if (newerSourceFileFound) {
console.log('Build is up-to-date.'); console.log('Build is up-to-date.');
// Ensure no stale warning file exists if build is ok // Ensure no stale warning file exists if build is ok
try { try {
if (fs.existsSync(warningsFilePath)) { if (fs.existsSync(warningsFilePath)) {
fs.unlinkSync(warningsFilePath); fs.unlinkSync(warningsFilePath);
} }
} catch (err) { } catch (err) {
console.warn(`[Check Script] Warning: Could not delete previous warnings file: ${err.message}`); console.warn(
`[Check Script] Warning: Could not delete previous warnings file: ${err.message}`,
);
} }
} }

View File

@ -12,6 +12,6 @@
"target": "ES2020", "target": "ES2020",
"module": "Node16", "module": "Node16",
"declaration": true, "declaration": true,
"moduleResolution": "node16", "moduleResolution": "node16"
} }
} }