mcp-server-gemini 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +155 -0
- package/LICENSE +21 -0
- package/README.md +180 -0
- package/dist/config/constants.js +71 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/config/models.js +121 -0
- package/dist/config/models.js.map +1 -0
- package/dist/enhanced-stdio-server.js +1164 -0
- package/dist/enhanced-stdio-server.js.map +1 -0
- package/dist/i18n.js +109 -0
- package/dist/i18n.js.map +1 -0
- package/dist/server.js +251 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/analyze-codebase.js +373 -0
- package/dist/tools/analyze-codebase.js.map +1 -0
- package/dist/tools/analyze-content.js +295 -0
- package/dist/tools/analyze-content.js.map +1 -0
- package/dist/tools/brainstorm.js +237 -0
- package/dist/tools/brainstorm.js.map +1 -0
- package/dist/tools/definitions.js +375 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/fix-ui.js +262 -0
- package/dist/tools/fix-ui.js.map +1 -0
- package/dist/tools/generate-ui.js +311 -0
- package/dist/tools/generate-ui.js.map +1 -0
- package/dist/tools/index.js +17 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-models.js +30 -0
- package/dist/tools/list-models.js.map +1 -0
- package/dist/tools/multimodal-query.js +83 -0
- package/dist/tools/multimodal-query.js.map +1 -0
- package/dist/tools/search.js +94 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/error-handler.js +69 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/file-reader.js +470 -0
- package/dist/utils/file-reader.js.map +1 -0
- package/dist/utils/gemini-client.js +184 -0
- package/dist/utils/gemini-client.js.map +1 -0
- package/dist/utils/security.js +370 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/validators.js +150 -0
- package/dist/utils/validators.js.map +1 -0
- package/dist/windows-utils.js +175 -0
- package/dist/windows-utils.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File reading utility module
|
|
3
|
+
* Provides single file reading and directory batch reading functions, supports glob pattern filtering
|
|
4
|
+
*/
|
|
5
|
+
import fg from 'fast-glob';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { validatePath, validateFileSize, validateFileCount, SecurityError, DEFAULT_SECURITY_CONFIG } from './security.js';
|
|
9
|
+
// ============== Constant Definitions ==============
|
|
10
|
+
/**
|
|
11
|
+
* Default exclude patterns
|
|
12
|
+
* These directories/files usually don't need to be analyzed
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_EXCLUDE_PATTERNS = [
|
|
15
|
+
// Dependency directories
|
|
16
|
+
'node_modules/**',
|
|
17
|
+
'vendor/**',
|
|
18
|
+
'bower_components/**',
|
|
19
|
+
// Build output
|
|
20
|
+
'dist/**',
|
|
21
|
+
'build/**',
|
|
22
|
+
'out/**',
|
|
23
|
+
'.next/**',
|
|
24
|
+
'.nuxt/**',
|
|
25
|
+
'.output/**',
|
|
26
|
+
// Test coverage
|
|
27
|
+
'coverage/**',
|
|
28
|
+
'.nyc_output/**',
|
|
29
|
+
// Cache directories
|
|
30
|
+
'.cache/**',
|
|
31
|
+
'.parcel-cache/**',
|
|
32
|
+
'.turbo/**',
|
|
33
|
+
// Lock files
|
|
34
|
+
'*.lock',
|
|
35
|
+
'package-lock.json',
|
|
36
|
+
'yarn.lock',
|
|
37
|
+
'pnpm-lock.yaml',
|
|
38
|
+
// Minified/compiled files
|
|
39
|
+
'*.min.js',
|
|
40
|
+
'*.min.css',
|
|
41
|
+
'*.bundle.js',
|
|
42
|
+
'*.chunk.js',
|
|
43
|
+
// Source map
|
|
44
|
+
'*.map',
|
|
45
|
+
'*.js.map',
|
|
46
|
+
'*.css.map',
|
|
47
|
+
// Version control
|
|
48
|
+
'.git/**',
|
|
49
|
+
'.svn/**',
|
|
50
|
+
'.hg/**',
|
|
51
|
+
// IDE configuration
|
|
52
|
+
'.idea/**',
|
|
53
|
+
'.vscode/**',
|
|
54
|
+
'*.code-workspace',
|
|
55
|
+
// Log files
|
|
56
|
+
'*.log',
|
|
57
|
+
'logs/**',
|
|
58
|
+
// Temporary files
|
|
59
|
+
'tmp/**',
|
|
60
|
+
'temp/**',
|
|
61
|
+
'.tmp/**',
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Binary file extensions
|
|
65
|
+
* These files cannot be read as text and should be skipped
|
|
66
|
+
*/
|
|
67
|
+
export const BINARY_EXTENSIONS = [
|
|
68
|
+
// Images
|
|
69
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.bmp', '.svg', '.tiff', '.avif',
|
|
70
|
+
// Audio
|
|
71
|
+
'.mp3', '.wav', '.ogg', '.flac', '.aac', '.m4a', '.wma',
|
|
72
|
+
// Video
|
|
73
|
+
'.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm', '.m4v',
|
|
74
|
+
// Archives
|
|
75
|
+
'.zip', '.tar', '.gz', '.rar', '.7z', '.bz2', '.xz',
|
|
76
|
+
// Executables
|
|
77
|
+
'.exe', '.dll', '.so', '.dylib', '.bin', '.app', '.msi',
|
|
78
|
+
// Documents (binary formats)
|
|
79
|
+
'.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.odt', '.ods', '.odp',
|
|
80
|
+
// Fonts
|
|
81
|
+
'.woff', '.woff2', '.ttf', '.eot', '.otf',
|
|
82
|
+
// Databases
|
|
83
|
+
'.db', '.sqlite', '.sqlite3', '.mdb',
|
|
84
|
+
// Other binary
|
|
85
|
+
'.class', '.jar', '.pyc', '.pyo', '.o', '.obj', '.a', '.lib',
|
|
86
|
+
'.ico', '.icns', '.cur',
|
|
87
|
+
];
|
|
88
|
+
/**
|
|
89
|
+
* Programming language mapping table
|
|
90
|
+
* Detects programming language based on file extension
|
|
91
|
+
*/
|
|
92
|
+
const LANGUAGE_MAP = {
|
|
93
|
+
// JavaScript/TypeScript
|
|
94
|
+
'.js': 'JavaScript',
|
|
95
|
+
'.jsx': 'JavaScript (JSX)',
|
|
96
|
+
'.ts': 'TypeScript',
|
|
97
|
+
'.tsx': 'TypeScript (TSX)',
|
|
98
|
+
'.mjs': 'JavaScript (ESM)',
|
|
99
|
+
'.cjs': 'JavaScript (CommonJS)',
|
|
100
|
+
// Web
|
|
101
|
+
'.html': 'HTML',
|
|
102
|
+
'.htm': 'HTML',
|
|
103
|
+
'.css': 'CSS',
|
|
104
|
+
'.scss': 'SCSS',
|
|
105
|
+
'.sass': 'Sass',
|
|
106
|
+
'.less': 'Less',
|
|
107
|
+
'.vue': 'Vue',
|
|
108
|
+
'.svelte': 'Svelte',
|
|
109
|
+
// Python
|
|
110
|
+
'.py': 'Python',
|
|
111
|
+
'.pyw': 'Python',
|
|
112
|
+
'.pyx': 'Cython',
|
|
113
|
+
'.pyi': 'Python (Stub)',
|
|
114
|
+
// Java/JVM
|
|
115
|
+
'.java': 'Java',
|
|
116
|
+
'.kt': 'Kotlin',
|
|
117
|
+
'.kts': 'Kotlin Script',
|
|
118
|
+
'.scala': 'Scala',
|
|
119
|
+
'.groovy': 'Groovy',
|
|
120
|
+
// C family
|
|
121
|
+
'.c': 'C',
|
|
122
|
+
'.h': 'C Header',
|
|
123
|
+
'.cpp': 'C++',
|
|
124
|
+
'.cc': 'C++',
|
|
125
|
+
'.cxx': 'C++',
|
|
126
|
+
'.hpp': 'C++ Header',
|
|
127
|
+
'.hxx': 'C++ Header',
|
|
128
|
+
// Go
|
|
129
|
+
'.go': 'Go',
|
|
130
|
+
// Rust
|
|
131
|
+
'.rs': 'Rust',
|
|
132
|
+
// Ruby
|
|
133
|
+
'.rb': 'Ruby',
|
|
134
|
+
'.erb': 'ERB',
|
|
135
|
+
// PHP
|
|
136
|
+
'.php': 'PHP',
|
|
137
|
+
// Swift
|
|
138
|
+
'.swift': 'Swift',
|
|
139
|
+
// Shell
|
|
140
|
+
'.sh': 'Shell',
|
|
141
|
+
'.bash': 'Bash',
|
|
142
|
+
'.zsh': 'Zsh',
|
|
143
|
+
'.fish': 'Fish',
|
|
144
|
+
'.ps1': 'PowerShell',
|
|
145
|
+
'.bat': 'Batch',
|
|
146
|
+
'.cmd': 'Batch',
|
|
147
|
+
// Configuration files
|
|
148
|
+
'.json': 'JSON',
|
|
149
|
+
'.yaml': 'YAML',
|
|
150
|
+
'.yml': 'YAML',
|
|
151
|
+
'.toml': 'TOML',
|
|
152
|
+
'.xml': 'XML',
|
|
153
|
+
'.ini': 'INI',
|
|
154
|
+
'.cfg': 'Config',
|
|
155
|
+
'.conf': 'Config',
|
|
156
|
+
// Data formats
|
|
157
|
+
'.csv': 'CSV',
|
|
158
|
+
'.tsv': 'TSV',
|
|
159
|
+
// Documents
|
|
160
|
+
'.md': 'Markdown',
|
|
161
|
+
'.mdx': 'MDX',
|
|
162
|
+
'.rst': 'reStructuredText',
|
|
163
|
+
'.txt': 'Plain Text',
|
|
164
|
+
// Database
|
|
165
|
+
'.sql': 'SQL',
|
|
166
|
+
'.graphql': 'GraphQL',
|
|
167
|
+
'.gql': 'GraphQL',
|
|
168
|
+
// Other
|
|
169
|
+
'.r': 'R',
|
|
170
|
+
'.R': 'R',
|
|
171
|
+
'.lua': 'Lua',
|
|
172
|
+
'.pl': 'Perl',
|
|
173
|
+
'.ex': 'Elixir',
|
|
174
|
+
'.exs': 'Elixir Script',
|
|
175
|
+
'.erl': 'Erlang',
|
|
176
|
+
'.hrl': 'Erlang Header',
|
|
177
|
+
'.clj': 'Clojure',
|
|
178
|
+
'.cljs': 'ClojureScript',
|
|
179
|
+
'.dart': 'Dart',
|
|
180
|
+
'.zig': 'Zig',
|
|
181
|
+
'.nim': 'Nim',
|
|
182
|
+
'.ml': 'OCaml',
|
|
183
|
+
'.mli': 'OCaml Interface',
|
|
184
|
+
'.fs': 'F#',
|
|
185
|
+
'.fsx': 'F# Script',
|
|
186
|
+
'.hs': 'Haskell',
|
|
187
|
+
// Docker/Container
|
|
188
|
+
'.dockerfile': 'Dockerfile',
|
|
189
|
+
// Templates
|
|
190
|
+
'.ejs': 'EJS',
|
|
191
|
+
'.hbs': 'Handlebars',
|
|
192
|
+
'.pug': 'Pug',
|
|
193
|
+
'.jade': 'Jade',
|
|
194
|
+
'.njk': 'Nunjucks',
|
|
195
|
+
'.twig': 'Twig',
|
|
196
|
+
'.jinja': 'Jinja',
|
|
197
|
+
'.jinja2': 'Jinja2',
|
|
198
|
+
};
|
|
199
|
+
// ============== Error Class Definition ==============
|
|
200
|
+
/**
|
|
201
|
+
* File reading error class
|
|
202
|
+
*/
|
|
203
|
+
export class FileReadError extends Error {
|
|
204
|
+
filePath;
|
|
205
|
+
cause;
|
|
206
|
+
/**
|
|
207
|
+
* Create file reading error instance
|
|
208
|
+
* @param message Error message
|
|
209
|
+
* @param filePath File path
|
|
210
|
+
* @param cause Original error (optional)
|
|
211
|
+
*/
|
|
212
|
+
constructor(message, filePath, cause) {
|
|
213
|
+
super(message);
|
|
214
|
+
this.filePath = filePath;
|
|
215
|
+
this.cause = cause;
|
|
216
|
+
this.name = 'FileReadError';
|
|
217
|
+
Object.setPrototypeOf(this, FileReadError.prototype);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// ============== Utility Functions ==============
|
|
221
|
+
/**
|
|
222
|
+
* Detect programming language based on file extension
|
|
223
|
+
*
|
|
224
|
+
* @param filePath File path
|
|
225
|
+
* @returns Language name, returns undefined if unknown
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* detectLanguage('src/index.ts') // 'TypeScript'
|
|
229
|
+
* detectLanguage('styles/main.css') // 'CSS'
|
|
230
|
+
* detectLanguage('unknown.xyz') // undefined
|
|
231
|
+
*/
|
|
232
|
+
export function detectLanguage(filePath) {
|
|
233
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
234
|
+
// Special filename handling
|
|
235
|
+
const fileName = path.basename(filePath).toLowerCase();
|
|
236
|
+
if (fileName === 'dockerfile') {
|
|
237
|
+
return 'Dockerfile';
|
|
238
|
+
}
|
|
239
|
+
if (fileName === 'makefile' || fileName === 'gnumakefile') {
|
|
240
|
+
return 'Makefile';
|
|
241
|
+
}
|
|
242
|
+
if (fileName === '.gitignore' || fileName === '.dockerignore') {
|
|
243
|
+
return 'Ignore File';
|
|
244
|
+
}
|
|
245
|
+
if (fileName === '.editorconfig') {
|
|
246
|
+
return 'EditorConfig';
|
|
247
|
+
}
|
|
248
|
+
return LANGUAGE_MAP[ext];
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Detect if file is binary
|
|
252
|
+
*
|
|
253
|
+
* @param filePath File path
|
|
254
|
+
* @returns Returns true if it's a binary file
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* isBinaryFile('image.png') // true
|
|
258
|
+
* isBinaryFile('code.ts') // false
|
|
259
|
+
*/
|
|
260
|
+
export function isBinaryFile(filePath) {
|
|
261
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
262
|
+
return BINARY_EXTENSIONS.includes(ext);
|
|
263
|
+
}
|
|
264
|
+
// ============== Main Functions ==============
|
|
265
|
+
/**
|
|
266
|
+
* Read a single file
|
|
267
|
+
*
|
|
268
|
+
* @param filePath File path
|
|
269
|
+
* @param config Security configuration (optional)
|
|
270
|
+
* @returns File content object
|
|
271
|
+
* @throws FileReadError Thrown when file reading fails
|
|
272
|
+
* @throws SecurityError Thrown when security validation fails
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* const file = await readFile('./src/index.ts');
|
|
276
|
+
* console.log(file.content); // File content
|
|
277
|
+
* console.log(file.language); // 'TypeScript'
|
|
278
|
+
*/
|
|
279
|
+
export async function readFile(filePath, config) {
|
|
280
|
+
// 1. Security validation
|
|
281
|
+
await validatePath(filePath, config);
|
|
282
|
+
// 2. Check if it's a binary file
|
|
283
|
+
if (isBinaryFile(filePath)) {
|
|
284
|
+
throw new FileReadError(`Cannot read binary file: "${filePath}"`, filePath);
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
287
|
+
// 3. Get absolute path
|
|
288
|
+
const absolutePath = path.resolve(filePath);
|
|
289
|
+
// 4. Get file information
|
|
290
|
+
const stats = await fs.stat(absolutePath);
|
|
291
|
+
// 5. Validate file size
|
|
292
|
+
const maxSize = config?.maxFileSize ?? DEFAULT_SECURITY_CONFIG.maxFileSize;
|
|
293
|
+
await validateFileSize(absolutePath, maxSize);
|
|
294
|
+
// 6. Read file content
|
|
295
|
+
const content = await fs.readFile(absolutePath, 'utf-8');
|
|
296
|
+
// 7. Detect language
|
|
297
|
+
const language = detectLanguage(filePath);
|
|
298
|
+
return {
|
|
299
|
+
path: filePath,
|
|
300
|
+
absolutePath: absolutePath.replace(/\\/g, '/'),
|
|
301
|
+
content,
|
|
302
|
+
size: stats.size,
|
|
303
|
+
language
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
// If it's a known error type, throw directly
|
|
308
|
+
if (error instanceof FileReadError || error instanceof SecurityError) {
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
// Handle other errors
|
|
312
|
+
const nodeError = error;
|
|
313
|
+
if (nodeError.code === 'ENOENT') {
|
|
314
|
+
throw new FileReadError(`File not found: "${filePath}"`, filePath, nodeError);
|
|
315
|
+
}
|
|
316
|
+
if (nodeError.code === 'EACCES') {
|
|
317
|
+
throw new FileReadError(`No permission to access file: "${filePath}"`, filePath, nodeError);
|
|
318
|
+
}
|
|
319
|
+
if (nodeError.code === 'EISDIR') {
|
|
320
|
+
throw new FileReadError(`Path is a directory, not a file: "${filePath}"`, filePath, nodeError);
|
|
321
|
+
}
|
|
322
|
+
throw new FileReadError(`Failed to read file: "${filePath}" - ${error.message}`, filePath, error);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Read multiple files in batch
|
|
327
|
+
* Automatically skips binary files and files that fail to read
|
|
328
|
+
*
|
|
329
|
+
* @param filePaths Array of file paths
|
|
330
|
+
* @param config Security configuration (optional)
|
|
331
|
+
* @returns Array of successfully read file contents
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* const files = await readFiles(['./src/a.ts', './src/b.ts']);
|
|
335
|
+
*/
|
|
336
|
+
export async function readFiles(filePaths, config) {
|
|
337
|
+
const results = [];
|
|
338
|
+
const errors = [];
|
|
339
|
+
// Read all files in parallel
|
|
340
|
+
const promises = filePaths.map(async (filePath) => {
|
|
341
|
+
try {
|
|
342
|
+
// Skip binary files
|
|
343
|
+
if (isBinaryFile(filePath)) {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
const content = await readFile(filePath, config);
|
|
347
|
+
return content;
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
// Record error but don't interrupt
|
|
351
|
+
errors.push({
|
|
352
|
+
path: filePath,
|
|
353
|
+
error: error.message
|
|
354
|
+
});
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
const settled = await Promise.all(promises);
|
|
359
|
+
// Filter out null results
|
|
360
|
+
for (const result of settled) {
|
|
361
|
+
if (result !== null) {
|
|
362
|
+
results.push(result);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// If there are errors, output warning (but don't throw)
|
|
366
|
+
if (errors.length > 0) {
|
|
367
|
+
console.warn(`[file-reader] Skipped ${errors.length} files:`);
|
|
368
|
+
for (const { path, error } of errors.slice(0, 5)) {
|
|
369
|
+
console.warn(` - ${path}: ${error}`);
|
|
370
|
+
}
|
|
371
|
+
if (errors.length > 5) {
|
|
372
|
+
console.warn(` ... and ${errors.length - 5} other files`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return results;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Read entire directory
|
|
379
|
+
* Supports glob pattern filtering, automatically excludes binary files and common ignored directories
|
|
380
|
+
*
|
|
381
|
+
* @param directory Directory path
|
|
382
|
+
* @param options Reading options
|
|
383
|
+
* @returns Array of file contents
|
|
384
|
+
* @throws SecurityError Thrown when security validation fails
|
|
385
|
+
* @throws FileReadError Thrown when directory doesn't exist
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* // Read all TypeScript files
|
|
389
|
+
* const files = await readDirectory('./src', {
|
|
390
|
+
* include: ['**\/*.ts', '**\/*.tsx'],
|
|
391
|
+
* exclude: ['**\/*.test.ts']
|
|
392
|
+
* });
|
|
393
|
+
*/
|
|
394
|
+
export async function readDirectory(directory, options) {
|
|
395
|
+
// 1. Security validate directory path
|
|
396
|
+
await validatePath(directory, options?.securityConfig);
|
|
397
|
+
// 2. Validate directory existence
|
|
398
|
+
const absoluteDir = path.resolve(directory);
|
|
399
|
+
try {
|
|
400
|
+
const stats = await fs.stat(absoluteDir);
|
|
401
|
+
if (!stats.isDirectory()) {
|
|
402
|
+
throw new FileReadError(`Path is not a directory: "${directory}"`, directory);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
if (error.code === 'ENOENT') {
|
|
407
|
+
throw new FileReadError(`Directory not found: "${directory}"`, directory);
|
|
408
|
+
}
|
|
409
|
+
throw error;
|
|
410
|
+
}
|
|
411
|
+
// 3. Prepare glob patterns
|
|
412
|
+
const include = options?.include || ['**/*'];
|
|
413
|
+
const userExclude = options?.exclude || [];
|
|
414
|
+
// Merge exclude patterns
|
|
415
|
+
const exclude = [...DEFAULT_EXCLUDE_PATTERNS, ...userExclude];
|
|
416
|
+
// Add binary file extensions to exclude patterns
|
|
417
|
+
const binaryExclude = BINARY_EXTENSIONS.map(ext => `**/*${ext}`);
|
|
418
|
+
// 4. Use fast-glob to get file list
|
|
419
|
+
const files = await fg(include, {
|
|
420
|
+
cwd: absoluteDir,
|
|
421
|
+
ignore: [...exclude, ...binaryExclude],
|
|
422
|
+
onlyFiles: true,
|
|
423
|
+
dot: false, // Don't include hidden files (starting with .)
|
|
424
|
+
followSymbolicLinks: false, // Don't follow symbolic links
|
|
425
|
+
absolute: false // Return relative paths
|
|
426
|
+
});
|
|
427
|
+
// 5. Validate file count
|
|
428
|
+
const maxFiles = options?.maxFiles ?? DEFAULT_SECURITY_CONFIG.maxFiles;
|
|
429
|
+
validateFileCount(files.length, maxFiles);
|
|
430
|
+
// 6. Build complete file paths
|
|
431
|
+
const filePaths = files.map(file => path.join(directory, file));
|
|
432
|
+
// 7. Read all files
|
|
433
|
+
const contents = await readFiles(filePaths, options?.securityConfig);
|
|
434
|
+
// 8. Adjust relative paths (relative to the passed directory parameter)
|
|
435
|
+
return contents.map(file => ({
|
|
436
|
+
...file,
|
|
437
|
+
path: path.relative(directory, file.absolutePath).replace(/\\/g, '/')
|
|
438
|
+
}));
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Check if file exists
|
|
442
|
+
*
|
|
443
|
+
* @param filePath File path
|
|
444
|
+
* @returns Returns true if file exists
|
|
445
|
+
*/
|
|
446
|
+
export async function fileExists(filePath) {
|
|
447
|
+
try {
|
|
448
|
+
await fs.access(filePath);
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Check if directory exists
|
|
457
|
+
*
|
|
458
|
+
* @param dirPath Directory path
|
|
459
|
+
* @returns Returns true if directory exists
|
|
460
|
+
*/
|
|
461
|
+
export async function directoryExists(dirPath) {
|
|
462
|
+
try {
|
|
463
|
+
const stats = await fs.stat(dirPath);
|
|
464
|
+
return stats.isDirectory();
|
|
465
|
+
}
|
|
466
|
+
catch {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
//# sourceMappingURL=file-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-reader.js","sourceRoot":"","sources":["../../src/utils/file-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini API client wrapper
|
|
3
|
+
* Provides unified API interface with error handling and retry logic
|
|
4
|
+
*/
|
|
5
|
+
import { GoogleGenAI } from '@google/genai';
|
|
6
|
+
import { API_CONFIG } from '../config/constants.js';
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Get MIME type based on file extension
|
|
11
|
+
*/
|
|
12
|
+
function getMimeType(ext) {
|
|
13
|
+
const mimeTypes = {
|
|
14
|
+
'.png': 'image/png',
|
|
15
|
+
'.jpg': 'image/jpeg',
|
|
16
|
+
'.jpeg': 'image/jpeg',
|
|
17
|
+
'.gif': 'image/gif',
|
|
18
|
+
'.webp': 'image/webp',
|
|
19
|
+
'.bmp': 'image/bmp',
|
|
20
|
+
'.svg': 'image/svg+xml',
|
|
21
|
+
'.ico': 'image/x-icon'
|
|
22
|
+
};
|
|
23
|
+
return mimeTypes[ext.toLowerCase()] || 'image/png';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert image to Base64 inline data format
|
|
27
|
+
* Supports: file path, Base64 data URI
|
|
28
|
+
*/
|
|
29
|
+
export function convertImageToInlineData(image) {
|
|
30
|
+
// 1. Already in Base64 data URI format
|
|
31
|
+
if (image.startsWith('data:')) {
|
|
32
|
+
const [metadata, data] = image.split(',');
|
|
33
|
+
const mimeType = metadata.match(/:(.*?);/)?.[1] || 'image/png';
|
|
34
|
+
return { mimeType, data };
|
|
35
|
+
}
|
|
36
|
+
// 2. URL format - not supported
|
|
37
|
+
if (image.startsWith('http://') || image.startsWith('https://')) {
|
|
38
|
+
throw new Error(`URL images are not supported. Please provide a file path or Base64 data URI instead.`);
|
|
39
|
+
}
|
|
40
|
+
// 3. File path format - read file and convert to Base64
|
|
41
|
+
try {
|
|
42
|
+
// Check if file exists
|
|
43
|
+
if (!fs.existsSync(image)) {
|
|
44
|
+
throw new Error(`Image file not found: ${image}`);
|
|
45
|
+
}
|
|
46
|
+
// Read file and convert to Base64
|
|
47
|
+
const fileBuffer = fs.readFileSync(image);
|
|
48
|
+
const base64Data = fileBuffer.toString('base64');
|
|
49
|
+
// Get MIME type
|
|
50
|
+
const ext = path.extname(image);
|
|
51
|
+
const mimeType = getMimeType(ext);
|
|
52
|
+
return { mimeType, data: base64Data };
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error.message.includes('Image file not found')) {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`Failed to read image file "${image}": ${error.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export class GeminiClient {
|
|
62
|
+
client;
|
|
63
|
+
modelId;
|
|
64
|
+
config;
|
|
65
|
+
constructor(config) {
|
|
66
|
+
this.client = new GoogleGenAI({ apiKey: config.apiKey });
|
|
67
|
+
this.modelId = config.model || 'gemini-3-pro-preview';
|
|
68
|
+
this.config = {
|
|
69
|
+
apiKey: config.apiKey,
|
|
70
|
+
model: this.modelId,
|
|
71
|
+
timeout: config.timeout || API_CONFIG.timeout,
|
|
72
|
+
maxRetries: config.maxRetries || API_CONFIG.maxRetries
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate content (text only)
|
|
77
|
+
*/
|
|
78
|
+
async generate(prompt, options = {}) {
|
|
79
|
+
try {
|
|
80
|
+
const requestBody = {
|
|
81
|
+
model: this.modelId,
|
|
82
|
+
contents: [{
|
|
83
|
+
role: 'user',
|
|
84
|
+
parts: [{ text: prompt }]
|
|
85
|
+
}],
|
|
86
|
+
generationConfig: {
|
|
87
|
+
temperature: options.temperature,
|
|
88
|
+
maxOutputTokens: options.maxTokens,
|
|
89
|
+
topP: options.topP,
|
|
90
|
+
topK: options.topK
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
// Add system instruction (if provided)
|
|
94
|
+
if (options.systemInstruction) {
|
|
95
|
+
requestBody.systemInstruction = {
|
|
96
|
+
parts: [{ text: options.systemInstruction }]
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const result = await this.client.models.generateContent(requestBody);
|
|
100
|
+
return result.text || '';
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw this.handleError(error);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Generate content (multimodal: text + images)
|
|
108
|
+
* Supported image formats:
|
|
109
|
+
* - File path: e.g., "./images/screenshot.png"
|
|
110
|
+
* - Base64 data URI: e.g., "data:image/png;base64,iVBORw0KGgo..."
|
|
111
|
+
*/
|
|
112
|
+
async generateMultimodal(prompt, images, options = {}) {
|
|
113
|
+
try {
|
|
114
|
+
// Build content: text + images
|
|
115
|
+
const parts = [{ text: prompt }];
|
|
116
|
+
// Process each image (supports file path and Base64)
|
|
117
|
+
for (const image of images) {
|
|
118
|
+
const { mimeType, data } = convertImageToInlineData(image);
|
|
119
|
+
parts.push({
|
|
120
|
+
inlineData: {
|
|
121
|
+
mimeType,
|
|
122
|
+
data
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const requestBody = {
|
|
127
|
+
model: this.modelId,
|
|
128
|
+
contents: [{ role: 'user', parts }],
|
|
129
|
+
generationConfig: {
|
|
130
|
+
temperature: options.temperature,
|
|
131
|
+
maxOutputTokens: options.maxTokens,
|
|
132
|
+
topP: options.topP,
|
|
133
|
+
topK: options.topK
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
// Add system instruction (if provided)
|
|
137
|
+
if (options.systemInstruction) {
|
|
138
|
+
requestBody.systemInstruction = {
|
|
139
|
+
parts: [{ text: options.systemInstruction }]
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const result = await this.client.models.generateContent(requestBody);
|
|
143
|
+
return result.text || '';
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
throw this.handleError(error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Switch model
|
|
151
|
+
*/
|
|
152
|
+
setModel(modelId) {
|
|
153
|
+
this.modelId = modelId;
|
|
154
|
+
this.config.model = modelId;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get current model
|
|
158
|
+
*/
|
|
159
|
+
getModel() {
|
|
160
|
+
return this.modelId;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Error handling
|
|
164
|
+
*/
|
|
165
|
+
handleError(error) {
|
|
166
|
+
if (error.message?.includes('API key')) {
|
|
167
|
+
return new Error('Invalid API key');
|
|
168
|
+
}
|
|
169
|
+
if (error.message?.includes('quota')) {
|
|
170
|
+
return new Error('API quota exceeded');
|
|
171
|
+
}
|
|
172
|
+
if (error.message?.includes('timeout')) {
|
|
173
|
+
return new Error('Request timeout');
|
|
174
|
+
}
|
|
175
|
+
return new Error(error.message || 'Unknown error');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Create Gemini client instance
|
|
180
|
+
*/
|
|
181
|
+
export function createGeminiClient(apiKey, model) {
|
|
182
|
+
return new GeminiClient({ apiKey, model });
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=gemini-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-client.js","sourceRoot":"","sources":["../../src/utils/gemini-client.ts"],"names":[],"mappings":"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"}
|