mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 08:47:44 +00:00
[ide-mode] Create an IDE manager class to handle connecting to and exposing methods from the IDE server (#4797)
This commit is contained in:
100
packages/core/src/ide/ide-client.ts
Normal file
100
packages/core/src/ide/ide-client.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { ideContext, OpenFilesNotificationSchema } from '../ide/ideContext.js';
|
||||
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
||||
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
||||
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) =>
|
||||
console.debug('[DEBUG] [ImportProcessor]', ...args),
|
||||
};
|
||||
|
||||
export type IDEConnectionState = {
|
||||
status: IDEConnectionStatus;
|
||||
details?: string;
|
||||
};
|
||||
|
||||
export enum IDEConnectionStatus {
|
||||
Connected = 'connected',
|
||||
Disconnected = 'disconnected',
|
||||
Connecting = 'connecting',
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages the connection to and interaction with the IDE server.
|
||||
*/
|
||||
export class IdeClient {
|
||||
client: Client | undefined = undefined;
|
||||
connectionStatus: IDEConnectionStatus = IDEConnectionStatus.Disconnected;
|
||||
|
||||
constructor() {
|
||||
this.connectToMcpServer().catch((err) => {
|
||||
logger.debug('Failed to initialize IdeClient:', err);
|
||||
});
|
||||
}
|
||||
getConnectionStatus(): {
|
||||
status: IDEConnectionStatus;
|
||||
details?: string;
|
||||
} {
|
||||
let details: string | undefined;
|
||||
if (this.connectionStatus === IDEConnectionStatus.Disconnected) {
|
||||
if (!process.env['GEMINI_CLI_IDE_SERVER_PORT']) {
|
||||
details = 'GEMINI_CLI_IDE_SERVER_PORT environment variable is not set.';
|
||||
}
|
||||
}
|
||||
return {
|
||||
status: this.connectionStatus,
|
||||
details,
|
||||
};
|
||||
}
|
||||
|
||||
async connectToMcpServer(): Promise<void> {
|
||||
this.connectionStatus = IDEConnectionStatus.Connecting;
|
||||
const idePort = process.env['GEMINI_CLI_IDE_SERVER_PORT'];
|
||||
if (!idePort) {
|
||||
logger.debug(
|
||||
'Unable to connect to IDE mode MCP server. GEMINI_CLI_IDE_SERVER_PORT environment variable is not set.',
|
||||
);
|
||||
this.connectionStatus = IDEConnectionStatus.Disconnected;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.client = new Client({
|
||||
name: 'streamable-http-client',
|
||||
// TODO(#3487): use the CLI version here.
|
||||
version: '1.0.0',
|
||||
});
|
||||
const transport = new StreamableHTTPClientTransport(
|
||||
new URL(`http://localhost:${idePort}/mcp`),
|
||||
);
|
||||
await this.client.connect(transport);
|
||||
this.client.setNotificationHandler(
|
||||
OpenFilesNotificationSchema,
|
||||
(notification) => {
|
||||
ideContext.setOpenFilesContext(notification.params);
|
||||
},
|
||||
);
|
||||
this.client.onerror = (error) => {
|
||||
logger.debug('IDE MCP client error:', error);
|
||||
this.connectionStatus = IDEConnectionStatus.Disconnected;
|
||||
ideContext.clearOpenFilesContext();
|
||||
};
|
||||
this.client.onclose = () => {
|
||||
logger.debug('IDE MCP client connection closed.');
|
||||
this.connectionStatus = IDEConnectionStatus.Disconnected;
|
||||
ideContext.clearOpenFilesContext();
|
||||
};
|
||||
|
||||
this.connectionStatus = IDEConnectionStatus.Connected;
|
||||
} catch (error) {
|
||||
this.connectionStatus = IDEConnectionStatus.Disconnected;
|
||||
logger.debug('Failed to connect to MCP server:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user