mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 14:10:37 -07:00
feat(ide extension): introduce debug logging (#10416)
This commit is contained in:
@@ -31,6 +31,16 @@
|
||||
"onStartupFinished"
|
||||
],
|
||||
"contributes": {
|
||||
"configuration": {
|
||||
"title": "Gemini CLI",
|
||||
"properties": {
|
||||
"gemini-cli.debug.logging.enabled": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Enable detailed logging for debugging the Gemini CLI Companion."
|
||||
}
|
||||
}
|
||||
},
|
||||
"languages": [
|
||||
{
|
||||
"id": "gemini-diff-editable"
|
||||
|
||||
@@ -168,7 +168,6 @@ export class DiffManager {
|
||||
async acceptDiff(rightDocUri: vscode.Uri) {
|
||||
const diffInfo = this.diffDocuments.get(rightDocUri.toString());
|
||||
if (!diffInfo) {
|
||||
this.log(`No diff info found for ${rightDocUri.toString()}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -194,8 +193,6 @@ export class DiffManager {
|
||||
async cancelDiff(rightDocUri: vscode.Uri) {
|
||||
const diffInfo = this.diffDocuments.get(rightDocUri.toString());
|
||||
if (!diffInfo) {
|
||||
this.log(`No diff info found for ${rightDocUri.toString()}`);
|
||||
// Even if we don't have diff info, we should still close the editor.
|
||||
await this.closeDiffEditor(rightDocUri);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ vi.mock('vscode', () => ({
|
||||
registerTextDocumentContentProvider: vi.fn(),
|
||||
onDidChangeWorkspaceFolders: vi.fn(),
|
||||
onDidGrantWorkspaceTrust: vi.fn(),
|
||||
getConfiguration: vi.fn(() => ({
|
||||
get: vi.fn(),
|
||||
})),
|
||||
},
|
||||
commands: {
|
||||
registerCommand: vi.fn(),
|
||||
|
||||
@@ -107,13 +107,6 @@ function sendIdeContextUpdateNotification(
|
||||
params: ideContext,
|
||||
});
|
||||
|
||||
log(
|
||||
`Sending IDE context update notification: ${JSON.stringify(
|
||||
notification,
|
||||
null,
|
||||
2,
|
||||
)}`,
|
||||
);
|
||||
transport.send(notification);
|
||||
}
|
||||
|
||||
@@ -190,7 +183,7 @@ export class IDEServer {
|
||||
next();
|
||||
});
|
||||
|
||||
const mcpServer = createMcpServer(this.diffManager);
|
||||
const mcpServer = createMcpServer(this.diffManager, this.log);
|
||||
|
||||
this.openFilesManager = new OpenFilesManager(context);
|
||||
const onDidChangeSubscription = this.openFilesManager.onDidChange(() => {
|
||||
@@ -222,16 +215,27 @@ export class IDEServer {
|
||||
this.transports[newSessionId] = transport;
|
||||
},
|
||||
});
|
||||
let missedPings = 0;
|
||||
const keepAlive = setInterval(() => {
|
||||
try {
|
||||
transport.send({ jsonrpc: '2.0', method: 'ping' });
|
||||
} catch (e) {
|
||||
this.log(
|
||||
'Failed to send keep-alive ping, cleaning up interval.' + e,
|
||||
);
|
||||
clearInterval(keepAlive);
|
||||
}
|
||||
}, 30000); // 30 sec
|
||||
const sessionId = transport.sessionId ?? 'unknown';
|
||||
transport
|
||||
.send({ jsonrpc: '2.0', method: 'ping' })
|
||||
.then(() => {
|
||||
missedPings = 0;
|
||||
})
|
||||
.catch((error) => {
|
||||
missedPings++;
|
||||
this.log(
|
||||
`Failed to send keep-alive ping for session ${sessionId}. Missed pings: ${missedPings}. Error: ${error.message}`,
|
||||
);
|
||||
if (missedPings >= 3) {
|
||||
this.log(
|
||||
`Session ${sessionId} missed ${missedPings} pings. Closing connection and cleaning up interval.`,
|
||||
);
|
||||
clearInterval(keepAlive);
|
||||
}
|
||||
});
|
||||
}, 60000); // 60 sec
|
||||
|
||||
transport.onclose = () => {
|
||||
clearInterval(keepAlive);
|
||||
@@ -315,6 +319,8 @@ export class IDEServer {
|
||||
app.get('/mcp', handleSessionRequest);
|
||||
|
||||
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
|
||||
this.log(`Error processing request: ${err.message}`);
|
||||
this.log(`Stack trace: ${err.stack}`);
|
||||
if (err instanceof CORSError) {
|
||||
res.status(403).json({ error: 'Request denied by CORS policy.' });
|
||||
} else {
|
||||
@@ -349,6 +355,14 @@ export class IDEServer {
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
|
||||
this.server.on('close', () => {
|
||||
this.log('IDE server connection closed.');
|
||||
});
|
||||
|
||||
this.server.on('error', (error) => {
|
||||
this.log(`IDE server error: ${error.message}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -421,7 +435,10 @@ export class IDEServer {
|
||||
}
|
||||
}
|
||||
|
||||
const createMcpServer = (diffManager: DiffManager) => {
|
||||
const createMcpServer = (
|
||||
diffManager: DiffManager,
|
||||
log: (message: string) => void,
|
||||
) => {
|
||||
const server = new McpServer(
|
||||
{
|
||||
name: 'gemini-cli-companion-mcp-server',
|
||||
@@ -437,6 +454,7 @@ const createMcpServer = (diffManager: DiffManager) => {
|
||||
inputSchema: OpenDiffRequestSchema.shape,
|
||||
},
|
||||
async ({ filePath, newContent }: z.infer<typeof OpenDiffRequestSchema>) => {
|
||||
log(`Received openDiff request for filePath: ${filePath}`);
|
||||
await diffManager.showDiff(filePath, newContent);
|
||||
return { content: [] };
|
||||
},
|
||||
@@ -451,6 +469,7 @@ const createMcpServer = (diffManager: DiffManager) => {
|
||||
filePath,
|
||||
suppressNotification,
|
||||
}: z.infer<typeof CloseDiffRequestSchema>) => {
|
||||
log(`Received closeDiff request for filePath: ${filePath}`);
|
||||
const content = await diffManager.closeDiff(
|
||||
filePath,
|
||||
suppressNotification,
|
||||
|
||||
@@ -11,7 +11,13 @@ export function createLogger(
|
||||
logger: vscode.OutputChannel,
|
||||
) {
|
||||
return (message: string) => {
|
||||
if (context.extensionMode === vscode.ExtensionMode.Development) {
|
||||
const isDevMode =
|
||||
context.extensionMode === vscode.ExtensionMode.Development;
|
||||
const isLoggingEnabled = vscode.workspace
|
||||
.getConfiguration('gemini-cli.debug')
|
||||
.get('logging.enabled');
|
||||
|
||||
if (isDevMode || isLoggingEnabled) {
|
||||
logger.appendLine(message);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user