@maxanatsko/gemini-mcp-tool 2.0.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/LICENSE +25 -0
- package/README.md +230 -0
- package/dist/constants.d.ts +153 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +150 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +188 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/ask-gemini.tool.d.ts +3 -0
- package/dist/tools/ask-gemini.tool.d.ts.map +1 -0
- package/dist/tools/ask-gemini.tool.js +74 -0
- package/dist/tools/ask-gemini.tool.js.map +1 -0
- package/dist/tools/brainstorm.tool.d.ts +3 -0
- package/dist/tools/brainstorm.tool.d.ts.map +1 -0
- package/dist/tools/brainstorm.tool.js +202 -0
- package/dist/tools/brainstorm.tool.js.map +1 -0
- package/dist/tools/fetch-chunk.tool.d.ts +3 -0
- package/dist/tools/fetch-chunk.tool.d.ts.map +1 -0
- package/dist/tools/fetch-chunk.tool.js +62 -0
- package/dist/tools/fetch-chunk.tool.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +25 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +80 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/review-code.tool.d.ts +3 -0
- package/dist/tools/review-code.tool.d.ts.map +1 -0
- package/dist/tools/review-code.tool.js +186 -0
- package/dist/tools/review-code.tool.js.map +1 -0
- package/dist/tools/simple-tools.d.ts +4 -0
- package/dist/tools/simple-tools.d.ts.map +1 -0
- package/dist/tools/simple-tools.js +32 -0
- package/dist/tools/simple-tools.js.map +1 -0
- package/dist/tools/test-tool.example.d.ts +13 -0
- package/dist/tools/test-tool.example.d.ts.map +1 -0
- package/dist/tools/test-tool.example.js +32 -0
- package/dist/tools/test-tool.example.js.map +1 -0
- package/dist/tools/timeout-test.tool.d.ts +3 -0
- package/dist/tools/timeout-test.tool.d.ts.map +1 -0
- package/dist/tools/timeout-test.tool.js +32 -0
- package/dist/tools/timeout-test.tool.js.map +1 -0
- package/dist/utils/askGeminiSessionManager.d.ts +57 -0
- package/dist/utils/askGeminiSessionManager.d.ts.map +1 -0
- package/dist/utils/askGeminiSessionManager.js +110 -0
- package/dist/utils/askGeminiSessionManager.js.map +1 -0
- package/dist/utils/brainstormSessionManager.d.ts +67 -0
- package/dist/utils/brainstormSessionManager.d.ts.map +1 -0
- package/dist/utils/brainstormSessionManager.js +165 -0
- package/dist/utils/brainstormSessionManager.js.map +1 -0
- package/dist/utils/changeModeChunker.d.ts +11 -0
- package/dist/utils/changeModeChunker.d.ts.map +1 -0
- package/dist/utils/changeModeChunker.js +89 -0
- package/dist/utils/changeModeChunker.js.map +1 -0
- package/dist/utils/changeModeParser.d.ts +15 -0
- package/dist/utils/changeModeParser.d.ts.map +1 -0
- package/dist/utils/changeModeParser.js +67 -0
- package/dist/utils/changeModeParser.js.map +1 -0
- package/dist/utils/changeModeTranslator.d.ts +8 -0
- package/dist/utils/changeModeTranslator.d.ts.map +1 -0
- package/dist/utils/changeModeTranslator.js +70 -0
- package/dist/utils/changeModeTranslator.js.map +1 -0
- package/dist/utils/chunkCache.d.ts +22 -0
- package/dist/utils/chunkCache.d.ts.map +1 -0
- package/dist/utils/chunkCache.js +161 -0
- package/dist/utils/chunkCache.js.map +1 -0
- package/dist/utils/commandExecutor.d.ts +2 -0
- package/dist/utils/commandExecutor.d.ts.map +1 -0
- package/dist/utils/commandExecutor.js +74 -0
- package/dist/utils/commandExecutor.js.map +1 -0
- package/dist/utils/geminiExecutor.d.ts +3 -0
- package/dist/utils/geminiExecutor.d.ts.map +1 -0
- package/dist/utils/geminiExecutor.js +170 -0
- package/dist/utils/geminiExecutor.js.map +1 -0
- package/dist/utils/gitStateDetector.d.ts +31 -0
- package/dist/utils/gitStateDetector.d.ts.map +1 -0
- package/dist/utils/gitStateDetector.js +67 -0
- package/dist/utils/gitStateDetector.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +42 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/reviewFormatter.d.ts +35 -0
- package/dist/utils/reviewFormatter.d.ts.map +1 -0
- package/dist/utils/reviewFormatter.js +198 -0
- package/dist/utils/reviewFormatter.js.map +1 -0
- package/dist/utils/reviewPromptBuilder.d.ts +35 -0
- package/dist/utils/reviewPromptBuilder.d.ts.map +1 -0
- package/dist/utils/reviewPromptBuilder.js +146 -0
- package/dist/utils/reviewPromptBuilder.js.map +1 -0
- package/dist/utils/reviewResponseParser.d.ts +20 -0
- package/dist/utils/reviewResponseParser.d.ts.map +1 -0
- package/dist/utils/reviewResponseParser.js +149 -0
- package/dist/utils/reviewResponseParser.js.map +1 -0
- package/dist/utils/reviewSessionCache.d.ts +81 -0
- package/dist/utils/reviewSessionCache.d.ts.map +1 -0
- package/dist/utils/reviewSessionCache.js +220 -0
- package/dist/utils/reviewSessionCache.js.map +1 -0
- package/dist/utils/reviewSessionManager.d.ts +52 -0
- package/dist/utils/reviewSessionManager.d.ts.map +1 -0
- package/dist/utils/reviewSessionManager.js +65 -0
- package/dist/utils/reviewSessionManager.js.map +1 -0
- package/dist/utils/sessionManager.d.ts +94 -0
- package/dist/utils/sessionManager.d.ts.map +1 -0
- package/dist/utils/sessionManager.js +374 -0
- package/dist/utils/sessionManager.js.map +1 -0
- package/dist/utils/sessionSchemas.d.ts +126 -0
- package/dist/utils/sessionSchemas.d.ts.map +1 -0
- package/dist/utils/sessionSchemas.js +2 -0
- package/dist/utils/sessionSchemas.js.map +1 -0
- package/dist/utils/timeoutManager.d.ts +2 -0
- package/dist/utils/timeoutManager.d.ts.map +1 -0
- package/dist/utils/timeoutManager.js +2 -0
- package/dist/utils/timeoutManager.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import { existsSync, constants as fsConstants } from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as os from 'os';
|
|
5
|
+
import { Logger } from './logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Default session configuration for all tools
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_SESSION_CONFIG = {
|
|
10
|
+
ttl: 24 * 60 * 60 * 1000, // 24 hours default
|
|
11
|
+
maxSessions: 20, // 20 sessions default
|
|
12
|
+
evictionPolicy: 'lru' // LRU default
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Default session configurations per tool
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_CONFIGS = {
|
|
18
|
+
'review-code': {
|
|
19
|
+
ttl: 24 * 60 * 60 * 1000, // 24 hours
|
|
20
|
+
maxSessions: 20,
|
|
21
|
+
evictionPolicy: 'lru' // Changed from 'fifo' to 'lru' for consistency
|
|
22
|
+
},
|
|
23
|
+
'ask-gemini': {
|
|
24
|
+
ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
25
|
+
maxSessions: 50,
|
|
26
|
+
evictionPolicy: 'lru'
|
|
27
|
+
},
|
|
28
|
+
'brainstorm': {
|
|
29
|
+
ttl: 14 * 24 * 60 * 60 * 1000, // 14 days
|
|
30
|
+
maxSessions: 30,
|
|
31
|
+
evictionPolicy: 'lru'
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
// Base session storage directory
|
|
35
|
+
const BASE_SESSIONS_DIR = path.join(os.homedir(), '.gemini-mcp', 'sessions');
|
|
36
|
+
/**
|
|
37
|
+
* Generic session manager for all MCP tools
|
|
38
|
+
* Type parameter T ensures type safety for tool-specific session data
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const manager = new SessionManager<MySessionData>('my-tool');
|
|
43
|
+
* manager.save('session-1', { sessionId: 'session-1', ... });
|
|
44
|
+
* const session = manager.load('session-1');
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export class SessionManager {
|
|
48
|
+
config;
|
|
49
|
+
cacheDir;
|
|
50
|
+
initPromise = null;
|
|
51
|
+
constructor(toolName, customConfig) {
|
|
52
|
+
const defaultConfig = DEFAULT_CONFIGS[toolName] || {};
|
|
53
|
+
this.config = {
|
|
54
|
+
toolName,
|
|
55
|
+
ttl: customConfig?.ttl ?? defaultConfig.ttl ?? DEFAULT_SESSION_CONFIG.ttl,
|
|
56
|
+
maxSessions: customConfig?.maxSessions ?? defaultConfig.maxSessions ?? DEFAULT_SESSION_CONFIG.maxSessions,
|
|
57
|
+
evictionPolicy: customConfig?.evictionPolicy ?? defaultConfig.evictionPolicy ?? DEFAULT_SESSION_CONFIG.evictionPolicy
|
|
58
|
+
};
|
|
59
|
+
this.cacheDir = path.join(BASE_SESSIONS_DIR, toolName);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Ensures the tool's session directory exists (lazy initialization)
|
|
63
|
+
*/
|
|
64
|
+
async ensureCacheDirAsync() {
|
|
65
|
+
if (this.initPromise)
|
|
66
|
+
return this.initPromise;
|
|
67
|
+
this.initPromise = (async () => {
|
|
68
|
+
try {
|
|
69
|
+
if (!existsSync(this.cacheDir)) {
|
|
70
|
+
await fs.mkdir(this.cacheDir, { recursive: true });
|
|
71
|
+
Logger.debug(`[${this.config.toolName}] Created session directory: ${this.cacheDir}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
Logger.error(`[${this.config.toolName}] Failed to create session directory ${this.cacheDir}: ${error}`);
|
|
76
|
+
throw new Error(`Session directory initialization failed: ${error}`);
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
return this.initPromise;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Helper method to quickly get session count without parsing files
|
|
83
|
+
*/
|
|
84
|
+
async getSessionCountFast() {
|
|
85
|
+
try {
|
|
86
|
+
const files = await fs.readdir(this.cacheDir);
|
|
87
|
+
return files.filter(f => f.endsWith('.json')).length;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Helper method to read and parse a session file
|
|
95
|
+
*/
|
|
96
|
+
async readSessionFile(filePath) {
|
|
97
|
+
try {
|
|
98
|
+
const fileContent = await fs.readFile(filePath, 'utf-8');
|
|
99
|
+
return JSON.parse(fileContent);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
throw new Error(`Failed to read session file: ${error}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Saves a session to persistent storage
|
|
107
|
+
* @param sessionId User-provided or generated session ID
|
|
108
|
+
* @param data Tool-specific session data
|
|
109
|
+
*/
|
|
110
|
+
async save(sessionId, data) {
|
|
111
|
+
await this.ensureCacheDirAsync();
|
|
112
|
+
// Moderate cleanup: only at 80% threshold
|
|
113
|
+
const sessionCount = await this.getSessionCountFast();
|
|
114
|
+
if (sessionCount >= this.config.maxSessions * 0.8) {
|
|
115
|
+
await this.cleanExpiredSessions();
|
|
116
|
+
}
|
|
117
|
+
const filePath = this.getSessionFilePath(sessionId);
|
|
118
|
+
// Ensure createdAt is always set (Issue #4)
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
const cacheEntry = {
|
|
121
|
+
data: {
|
|
122
|
+
...data,
|
|
123
|
+
sessionId,
|
|
124
|
+
createdAt: data.createdAt || now, // Fallback if not set
|
|
125
|
+
lastAccessedAt: now
|
|
126
|
+
},
|
|
127
|
+
timestamp: now,
|
|
128
|
+
expiryTime: now + this.config.ttl
|
|
129
|
+
};
|
|
130
|
+
try {
|
|
131
|
+
await fs.writeFile(filePath, JSON.stringify(cacheEntry, null, 2), 'utf-8');
|
|
132
|
+
Logger.debug(`[${this.config.toolName}] Saved session: ${sessionId}`);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
Logger.error(`[${this.config.toolName}] Failed to save session ${sessionId}: ${error}`);
|
|
136
|
+
throw new Error(`Failed to save session ${sessionId}: ${error}`);
|
|
137
|
+
}
|
|
138
|
+
// Only enforce limits if over max
|
|
139
|
+
if (sessionCount >= this.config.maxSessions) {
|
|
140
|
+
await this.enforceSessionLimits();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Loads a session from storage
|
|
145
|
+
* @param sessionId The session ID to load
|
|
146
|
+
* @returns Session data or null if not found/expired
|
|
147
|
+
*/
|
|
148
|
+
async load(sessionId) {
|
|
149
|
+
const filePath = this.getSessionFilePath(sessionId);
|
|
150
|
+
try {
|
|
151
|
+
// Check if file exists asynchronously
|
|
152
|
+
try {
|
|
153
|
+
await fs.access(filePath, fsConstants.F_OK);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
Logger.debug(`[${this.config.toolName}] Session not found: ${sessionId}`);
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const cacheEntry = await this.readSessionFile(filePath);
|
|
160
|
+
// Check expiry
|
|
161
|
+
if (Date.now() > cacheEntry.expiryTime) {
|
|
162
|
+
await fs.unlink(filePath);
|
|
163
|
+
Logger.debug(`[${this.config.toolName}] Session expired and deleted: ${sessionId}`);
|
|
164
|
+
// Moderate optimization: run cleanup when we find expired sessions
|
|
165
|
+
await this.cleanExpiredSessions();
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
// Update last accessed time for LRU
|
|
169
|
+
if (this.config.evictionPolicy === 'lru') {
|
|
170
|
+
cacheEntry.data.lastAccessedAt = Date.now();
|
|
171
|
+
cacheEntry.timestamp = Date.now();
|
|
172
|
+
await fs.writeFile(filePath, JSON.stringify(cacheEntry, null, 2), 'utf-8');
|
|
173
|
+
}
|
|
174
|
+
Logger.debug(`[${this.config.toolName}] Loaded session: ${sessionId}`);
|
|
175
|
+
return cacheEntry.data;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
Logger.warn(`[${this.config.toolName}] Failed to load session ${sessionId}: ${error}`);
|
|
179
|
+
// Issue #13: Only delete if file exists and is corrupt (not transient errors)
|
|
180
|
+
try {
|
|
181
|
+
await fs.access(filePath, fsConstants.F_OK);
|
|
182
|
+
// File exists, try to delete it
|
|
183
|
+
try {
|
|
184
|
+
await fs.unlink(filePath);
|
|
185
|
+
Logger.debug(`[${this.config.toolName}] Removed corrupt session file: ${sessionId}`);
|
|
186
|
+
}
|
|
187
|
+
catch (unlinkError) {
|
|
188
|
+
Logger.debug(`[${this.config.toolName}] Could not remove corrupt file ${sessionId}: ${unlinkError}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// File doesn't exist, nothing to clean up
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Lists all active sessions for this tool
|
|
199
|
+
* @returns Array of session data
|
|
200
|
+
*/
|
|
201
|
+
async list() {
|
|
202
|
+
await this.ensureCacheDirAsync();
|
|
203
|
+
const sessions = [];
|
|
204
|
+
const now = Date.now();
|
|
205
|
+
try {
|
|
206
|
+
const files = await fs.readdir(this.cacheDir);
|
|
207
|
+
for (const file of files) {
|
|
208
|
+
if (!file.endsWith('.json'))
|
|
209
|
+
continue;
|
|
210
|
+
const filePath = path.join(this.cacheDir, file);
|
|
211
|
+
try {
|
|
212
|
+
const cacheEntry = await this.readSessionFile(filePath);
|
|
213
|
+
// Skip expired sessions
|
|
214
|
+
if (now <= cacheEntry.expiryTime) {
|
|
215
|
+
sessions.push(cacheEntry.data);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
Logger.debug(`[${this.config.toolName}] Error reading session file ${file}: ${error}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
Logger.error(`[${this.config.toolName}] Failed to list sessions: ${error}`);
|
|
225
|
+
}
|
|
226
|
+
return sessions;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Deletes a specific session
|
|
230
|
+
* @param sessionId The session ID to delete
|
|
231
|
+
* @returns true if deleted, false if not found
|
|
232
|
+
*/
|
|
233
|
+
async delete(sessionId) {
|
|
234
|
+
const filePath = this.getSessionFilePath(sessionId);
|
|
235
|
+
try {
|
|
236
|
+
await fs.unlink(filePath);
|
|
237
|
+
Logger.debug(`[${this.config.toolName}] Deleted session: ${sessionId}`);
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
if (error.code === 'ENOENT') {
|
|
242
|
+
Logger.debug(`[${this.config.toolName}] Session not found for deletion: ${sessionId}`);
|
|
243
|
+
return false; // File doesn't exist, effectively "deleted"
|
|
244
|
+
}
|
|
245
|
+
Logger.error(`[${this.config.toolName}] Failed to delete session ${sessionId}: ${error}`);
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Cleans up expired sessions
|
|
251
|
+
*/
|
|
252
|
+
async cleanExpiredSessions() {
|
|
253
|
+
try {
|
|
254
|
+
await this.ensureCacheDirAsync();
|
|
255
|
+
const files = await fs.readdir(this.cacheDir);
|
|
256
|
+
const now = Date.now();
|
|
257
|
+
let cleaned = 0;
|
|
258
|
+
for (const file of files) {
|
|
259
|
+
if (!file.endsWith('.json'))
|
|
260
|
+
continue;
|
|
261
|
+
const filePath = path.join(this.cacheDir, file);
|
|
262
|
+
try {
|
|
263
|
+
const cacheEntry = await this.readSessionFile(filePath);
|
|
264
|
+
if (now > cacheEntry.expiryTime) {
|
|
265
|
+
await fs.unlink(filePath);
|
|
266
|
+
cleaned++;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
// Issue #3: Log errors instead of empty catch
|
|
271
|
+
Logger.debug(`[${this.config.toolName}] Error checking session file ${file}: ${error}`);
|
|
272
|
+
// Try to remove corrupt file
|
|
273
|
+
try {
|
|
274
|
+
await fs.unlink(filePath);
|
|
275
|
+
cleaned++;
|
|
276
|
+
}
|
|
277
|
+
catch (unlinkError) {
|
|
278
|
+
Logger.debug(`[${this.config.toolName}] Could not remove corrupt file ${file}: ${unlinkError}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (cleaned > 0) {
|
|
283
|
+
Logger.debug(`[${this.config.toolName}] Cleaned ${cleaned} expired sessions`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
Logger.debug(`[${this.config.toolName}] Session cleanup error: ${error}`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Enforces maximum session limits using configured eviction policy
|
|
292
|
+
*/
|
|
293
|
+
async enforceSessionLimits() {
|
|
294
|
+
try {
|
|
295
|
+
const files = await fs.readdir(this.cacheDir);
|
|
296
|
+
const jsonFiles = files.filter(f => f.endsWith('.json'));
|
|
297
|
+
if (jsonFiles.length <= this.config.maxSessions) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
// Get file stats for sorting
|
|
301
|
+
const fileStats = await Promise.all(jsonFiles.map(async (name) => {
|
|
302
|
+
const filePath = path.join(this.cacheDir, name);
|
|
303
|
+
const stat = await fs.stat(filePath);
|
|
304
|
+
return { name, path: filePath, stat };
|
|
305
|
+
}));
|
|
306
|
+
// Sort based on eviction policy
|
|
307
|
+
if (this.config.evictionPolicy === 'fifo') {
|
|
308
|
+
// Sort by creation time (oldest first)
|
|
309
|
+
fileStats.sort((a, b) => a.stat.birthtimeMs - b.stat.birthtimeMs);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// LRU: Sort by modification time (least recently accessed first)
|
|
313
|
+
fileStats.sort((a, b) => a.stat.mtimeMs - b.stat.mtimeMs);
|
|
314
|
+
}
|
|
315
|
+
// Remove oldest files
|
|
316
|
+
const toRemove = fileStats.slice(0, fileStats.length - this.config.maxSessions);
|
|
317
|
+
let removed = 0;
|
|
318
|
+
for (const file of toRemove) {
|
|
319
|
+
try {
|
|
320
|
+
await fs.unlink(file.path);
|
|
321
|
+
removed++;
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
// Issue #3: Log instead of empty catch
|
|
325
|
+
Logger.debug(`[${this.config.toolName}] Failed to remove session file ${file.name}: ${error}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
Logger.debug(`[${this.config.toolName}] Removed ${removed}/${toRemove.length} sessions (${this.config.evictionPolicy} policy)`);
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
Logger.debug(`[${this.config.toolName}] Error enforcing session limits: ${error}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Gets the file path for a session
|
|
336
|
+
*/
|
|
337
|
+
getSessionFilePath(sessionId) {
|
|
338
|
+
// Issue #12: More robust sanitization
|
|
339
|
+
// Replace invalid characters, then clean up consecutive/leading/trailing hyphens
|
|
340
|
+
let safeSessionId = sessionId
|
|
341
|
+
.replace(/[^a-zA-Z0-9-_]/g, '-') // Replace invalid chars
|
|
342
|
+
.replace(/-+/g, '-') // Collapse consecutive hyphens
|
|
343
|
+
.replace(/^-+|-+$/g, ''); // Remove leading/trailing hyphens
|
|
344
|
+
// Ensure we have a valid ID after sanitization
|
|
345
|
+
if (!safeSessionId) {
|
|
346
|
+
safeSessionId = 'session';
|
|
347
|
+
}
|
|
348
|
+
return path.join(this.cacheDir, `${safeSessionId}.json`);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Gets statistics about the session cache
|
|
352
|
+
*/
|
|
353
|
+
async getStats() {
|
|
354
|
+
await this.ensureCacheDirAsync();
|
|
355
|
+
let sessionCount = 0;
|
|
356
|
+
try {
|
|
357
|
+
const files = await fs.readdir(this.cacheDir);
|
|
358
|
+
sessionCount = files.filter(f => f.endsWith('.json')).length;
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
// Issue #9/#14: Log error instead of empty catch
|
|
362
|
+
Logger.debug(`[${this.config.toolName}] Error reading session directory for stats: ${error}`);
|
|
363
|
+
}
|
|
364
|
+
return {
|
|
365
|
+
toolName: this.config.toolName,
|
|
366
|
+
sessionCount,
|
|
367
|
+
ttl: this.config.ttl,
|
|
368
|
+
maxSessions: this.config.maxSessions,
|
|
369
|
+
evictionPolicy: this.config.evictionPolicy,
|
|
370
|
+
cacheDir: this.cacheDir
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
//# sourceMappingURL=sessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionManager.js","sourceRoot":"","sources":["../../src/utils/sessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { SessionData } from './sessionManager.js';
|
|
2
|
+
import { GitState } from './gitStateDetector.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ask-Gemini Session Data
|
|
5
|
+
* Tracks multi-turn Q&A conversations with context
|
|
6
|
+
*/
|
|
7
|
+
export interface AskGeminiSessionData extends SessionData {
|
|
8
|
+
/** History of all conversation rounds */
|
|
9
|
+
conversationHistory: Array<{
|
|
10
|
+
roundNumber: number;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
userPrompt: string;
|
|
13
|
+
geminiResponse: string;
|
|
14
|
+
model: string;
|
|
15
|
+
tokenCount?: number;
|
|
16
|
+
}>;
|
|
17
|
+
/** Total number of rounds in this conversation */
|
|
18
|
+
totalRounds: number;
|
|
19
|
+
/** Files referenced with @ syntax across all rounds */
|
|
20
|
+
contextFiles: string[];
|
|
21
|
+
/** Optional metadata for categorization */
|
|
22
|
+
metadata: {
|
|
23
|
+
primaryTopic?: string;
|
|
24
|
+
tags?: string[];
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Brainstorm Session Data
|
|
29
|
+
* Tracks iterative ideation with ideas and feedback
|
|
30
|
+
*/
|
|
31
|
+
export interface BrainstormSessionData extends SessionData {
|
|
32
|
+
/** Original brainstorming challenge */
|
|
33
|
+
challenge: string;
|
|
34
|
+
/** Methodology used (divergent, scamper, design-thinking, etc.) */
|
|
35
|
+
methodology: string;
|
|
36
|
+
/** Domain context if specified */
|
|
37
|
+
domain?: string;
|
|
38
|
+
/** Constraints if specified */
|
|
39
|
+
constraints?: string;
|
|
40
|
+
/** All brainstorming rounds */
|
|
41
|
+
rounds: Array<{
|
|
42
|
+
roundNumber: number;
|
|
43
|
+
timestamp: number;
|
|
44
|
+
userPrompt: string;
|
|
45
|
+
geminiResponse: string;
|
|
46
|
+
ideasGenerated: Array<{
|
|
47
|
+
ideaId: string;
|
|
48
|
+
name: string;
|
|
49
|
+
description: string;
|
|
50
|
+
feasibility?: number;
|
|
51
|
+
impact?: number;
|
|
52
|
+
innovation?: number;
|
|
53
|
+
status: 'active' | 'refined' | 'merged' | 'discarded';
|
|
54
|
+
notes?: string;
|
|
55
|
+
}>;
|
|
56
|
+
}>;
|
|
57
|
+
/** Total ideas generated across all rounds */
|
|
58
|
+
totalIdeas: number;
|
|
59
|
+
/** Number of ideas still active (not discarded or merged) */
|
|
60
|
+
activeIdeas: number;
|
|
61
|
+
/** History of refinement actions */
|
|
62
|
+
refinementHistory: Array<{
|
|
63
|
+
timestamp: number;
|
|
64
|
+
action: 'refined' | 'merged' | 'discarded';
|
|
65
|
+
ideaIds: string[];
|
|
66
|
+
reason: string;
|
|
67
|
+
}>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Review-Code Session Data
|
|
71
|
+
* Enhanced version of existing review session with shared infrastructure
|
|
72
|
+
* Maintains backward compatibility while integrating with new SessionManager
|
|
73
|
+
*/
|
|
74
|
+
export interface ReviewCodeSessionData extends SessionData {
|
|
75
|
+
/** Initial git state when review started */
|
|
76
|
+
gitState: GitState;
|
|
77
|
+
/** Current git state (updated each round) */
|
|
78
|
+
currentGitState: GitState;
|
|
79
|
+
/** All review rounds */
|
|
80
|
+
rounds: Array<{
|
|
81
|
+
roundNumber: number;
|
|
82
|
+
timestamp: number;
|
|
83
|
+
filesReviewed: string[];
|
|
84
|
+
userPrompt: string;
|
|
85
|
+
geminiResponse: string;
|
|
86
|
+
commentsGenerated: Array<{
|
|
87
|
+
id: string;
|
|
88
|
+
filePattern: string;
|
|
89
|
+
lineRange?: {
|
|
90
|
+
start: number;
|
|
91
|
+
end: number;
|
|
92
|
+
};
|
|
93
|
+
severity: 'critical' | 'important' | 'suggestion' | 'question';
|
|
94
|
+
comment: string;
|
|
95
|
+
roundGenerated: number;
|
|
96
|
+
status: 'pending' | 'accepted' | 'rejected' | 'modified' | 'deferred';
|
|
97
|
+
resolution?: string;
|
|
98
|
+
}>;
|
|
99
|
+
gitState: GitState;
|
|
100
|
+
}>;
|
|
101
|
+
/** All comments across all rounds */
|
|
102
|
+
allComments: Array<{
|
|
103
|
+
id: string;
|
|
104
|
+
filePattern: string;
|
|
105
|
+
lineRange?: {
|
|
106
|
+
start: number;
|
|
107
|
+
end: number;
|
|
108
|
+
};
|
|
109
|
+
severity: 'critical' | 'important' | 'suggestion' | 'question';
|
|
110
|
+
comment: string;
|
|
111
|
+
roundGenerated: number;
|
|
112
|
+
status: 'pending' | 'accepted' | 'rejected' | 'modified' | 'deferred';
|
|
113
|
+
resolution?: string;
|
|
114
|
+
}>;
|
|
115
|
+
/** Files tracked across all rounds */
|
|
116
|
+
filesTracked: string[];
|
|
117
|
+
/** Files to focus on if specified */
|
|
118
|
+
focusFiles?: string[];
|
|
119
|
+
/** Review scope */
|
|
120
|
+
reviewScope?: 'full' | 'changes-only' | 'focused';
|
|
121
|
+
/** Total number of review rounds */
|
|
122
|
+
totalRounds: number;
|
|
123
|
+
/** Current session state */
|
|
124
|
+
sessionState: 'active' | 'paused' | 'completed';
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=sessionSchemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionSchemas.d.ts","sourceRoot":"","sources":["../../src/utils/sessionSchemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionSchemas.js","sourceRoot":"","sources":["../../src/utils/sessionSchemas.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeoutManager.d.ts","sourceRoot":"","sources":["../../src/utils/timeoutManager.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeoutManager.js","sourceRoot":"","sources":["../../src/utils/timeoutManager.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maxanatsko/gemini-mcp-tool",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "MCP server for Gemini CLI integration",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gemini-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "tsc && node dist/index.js",
|
|
14
|
+
"test": "echo \"No tests yet\" && exit 0",
|
|
15
|
+
"lint": "tsc --noEmit",
|
|
16
|
+
"contribute": "tsx src/contribute.ts",
|
|
17
|
+
"prepublishOnly": "echo '⚠️ Remember to test locally first!' && npm run build",
|
|
18
|
+
"docs:dev": "vitepress dev docs",
|
|
19
|
+
"docs:build": "vitepress build docs",
|
|
20
|
+
"docs:preview": "vitepress preview docs"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"modelcontextprotocol",
|
|
25
|
+
"gemini",
|
|
26
|
+
"cli",
|
|
27
|
+
"ai",
|
|
28
|
+
"llm"
|
|
29
|
+
],
|
|
30
|
+
"author": "maxanatsko (fork of jamubc/gemini-mcp-tool)",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/maxanatsko/gemini-mcp-tool.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/maxanatsko/gemini-mcp-tool/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/maxanatsko/gemini-mcp-tool#readme",
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=16.0.0"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist/",
|
|
45
|
+
"README.md",
|
|
46
|
+
"LICENSE"
|
|
47
|
+
],
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
50
|
+
"ai": "^4.3.17",
|
|
51
|
+
"chalk": "^5.0.0",
|
|
52
|
+
"d3-shape": "^3.2.0",
|
|
53
|
+
"inquirer": "^9.0.0",
|
|
54
|
+
"prismjs": "^1.30.0",
|
|
55
|
+
"zod": "^3.25.76",
|
|
56
|
+
"zod-to-json-schema": "^3.24.6"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/inquirer": "^9.0.0",
|
|
60
|
+
"@types/node": "^20.0.0",
|
|
61
|
+
"archiver": "^7.0.1",
|
|
62
|
+
"mermaid": "^11.9.0",
|
|
63
|
+
"tsx": "^4.0.0",
|
|
64
|
+
"typescript": "^5.0.0",
|
|
65
|
+
"vitepress": "^1.6.3",
|
|
66
|
+
"vitepress-plugin-mermaid": "^2.0.17"
|
|
67
|
+
},
|
|
68
|
+
"publishConfig": {
|
|
69
|
+
"access": "public"
|
|
70
|
+
}
|
|
71
|
+
}
|