summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShreya Keshive <[email protected]>2025-07-16 17:33:56 -0400
committerGitHub <[email protected]>2025-07-16 21:33:56 +0000
commit69a8ae6a89918f4255304975f8653ff808264bc8 (patch)
treebb32342db9f0406bd4f75ffb9756ac81ff84d5a5
parentf6ee0d182bcb6c9c6e3c9d34174d8d984bbddb37 (diff)
Minor UX updates for IDE mode (#4311)
-rw-r--r--packages/cli/src/config/config.test.ts67
-rw-r--r--packages/cli/src/config/config.ts7
-rw-r--r--packages/core/src/services/ideContext.test.ts15
-rw-r--r--packages/core/src/services/ideContext.ts9
-rw-r--r--packages/core/src/tools/mcp-client.ts3
5 files changed, 99 insertions, 2 deletions
diff --git a/packages/cli/src/config/config.test.ts b/packages/cli/src/config/config.test.ts
index 6aab4487..cd06f5dc 100644
--- a/packages/cli/src/config/config.test.ts
+++ b/packages/cli/src/config/config.test.ts
@@ -955,7 +955,72 @@ describe('loadCliConfig ideMode', () => {
await expect(
loadCliConfig(settings, [], 'test-session', argv),
).rejects.toThrow(
- "Could not run in ide mode, make sure you're running in vs code integrated terminal. Try running in a fresh terminal.",
+ 'Could not connect to IDE. Make sure you have the companion VS Code extension installed from the marketplace or via /ide install.',
);
});
+
+ it('should warn and overwrite if settings contain the reserved _ide_server name and ideMode is active', async () => {
+ const consoleWarnSpy = vi
+ .spyOn(console, 'warn')
+ .mockImplementation(() => {});
+
+ process.argv = ['node', 'script.js', '--ide-mode'];
+ const argv = await parseArguments();
+ process.env.TERM_PROGRAM = 'vscode';
+ process.env.GEMINI_CLI_IDE_SERVER_PORT = '3000';
+ const settings: Settings = {
+ mcpServers: {
+ _ide_server: new ServerConfig.MCPServerConfig(
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ 'http://malicious:1234',
+ ),
+ },
+ };
+
+ const config = await loadCliConfig(settings, [], 'test-session', argv);
+
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
+ '[WARN]',
+ 'Ignoring user-defined MCP server config for "_ide_server" as it is a reserved name.',
+ );
+
+ const mcpServers = config.getMcpServers();
+ expect(mcpServers['_ide_server']).toBeDefined();
+ expect(mcpServers['_ide_server'].httpUrl).toBe('http://localhost:3000/mcp');
+
+ consoleWarnSpy.mockRestore();
+ });
+
+ it('should NOT warn if settings contain the reserved _ide_server name and ideMode is NOT active', async () => {
+ const consoleWarnSpy = vi
+ .spyOn(console, 'warn')
+ .mockImplementation(() => {});
+
+ process.argv = ['node', 'script.js'];
+ const argv = await parseArguments();
+ const settings: Settings = {
+ mcpServers: {
+ _ide_server: new ServerConfig.MCPServerConfig(
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ 'http://malicious:1234',
+ ),
+ },
+ };
+
+ const config = await loadCliConfig(settings, [], 'test-session', argv);
+
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
+
+ const mcpServers = config.getMcpServers();
+ expect(mcpServers['_ide_server']).toBeDefined();
+ expect(mcpServers['_ide_server'].url).toBe('http://malicious:1234');
+
+ consoleWarnSpy.mockRestore();
+ });
});
diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts
index 69708a61..83549139 100644
--- a/packages/cli/src/config/config.ts
+++ b/packages/cli/src/config/config.ts
@@ -306,10 +306,15 @@ export async function loadCliConfig(
}
if (ideMode) {
+ if (mcpServers[IDE_SERVER_NAME]) {
+ logger.warn(
+ `Ignoring user-defined MCP server config for "${IDE_SERVER_NAME}" as it is a reserved name.`,
+ );
+ }
const companionPort = process.env.GEMINI_CLI_IDE_SERVER_PORT;
if (!companionPort) {
throw new Error(
- "Could not run in ide mode, make sure you're running in vs code integrated terminal. Try running in a fresh terminal.",
+ 'Could not connect to IDE. Make sure you have the companion VS Code extension installed from the marketplace or via /ide install.',
);
}
const httpUrl = `http://localhost:${companionPort}/mcp`;
diff --git a/packages/core/src/services/ideContext.test.ts b/packages/core/src/services/ideContext.test.ts
index 0e6ff045..9aa4c013 100644
--- a/packages/core/src/services/ideContext.test.ts
+++ b/packages/core/src/services/ideContext.test.ts
@@ -122,4 +122,19 @@ describe('ideContext - Active File', () => {
const activeFile = ideContext.getActiveFileContext();
expect(activeFile).toEqual(testFile);
});
+
+ it('should clear the active file context', () => {
+ const testFile = {
+ filePath: '/path/to/test/file.ts',
+ cursor: { line: 5, character: 10 },
+ };
+
+ ideContext.setActiveFileContext(testFile);
+
+ expect(ideContext.getActiveFileContext()).toEqual(testFile);
+
+ ideContext.clearActiveFileContext();
+
+ expect(ideContext.getActiveFileContext()).toBeUndefined();
+ });
});
diff --git a/packages/core/src/services/ideContext.ts b/packages/core/src/services/ideContext.ts
index 6bbe8cb9..b5f0b4af 100644
--- a/packages/core/src/services/ideContext.ts
+++ b/packages/core/src/services/ideContext.ts
@@ -69,6 +69,14 @@ export function createIdeContextStore() {
}
/**
+ * Clears the active file context and notifies all registered subscribers of the change.
+ */
+ function clearActiveFileContext(): void {
+ activeFileContext = undefined;
+ notifySubscribers();
+ }
+
+ /**
* Retrieves the current active file context.
* @returns The `ActiveFile` object if a file is active, otherwise `undefined`.
*/
@@ -96,6 +104,7 @@ export function createIdeContextStore() {
setActiveFileContext,
getActiveFileContext,
subscribeToActiveFile,
+ clearActiveFileContext,
};
}
diff --git a/packages/core/src/tools/mcp-client.ts b/packages/core/src/tools/mcp-client.ts
index 24c975c3..5849884d 100644
--- a/packages/core/src/tools/mcp-client.ts
+++ b/packages/core/src/tools/mcp-client.ts
@@ -215,6 +215,9 @@ export async function connectAndDiscover(
mcpClient.onerror = (error) => {
console.error(`MCP ERROR (${mcpServerName}):`, error.toString());
updateMCPServerStatus(mcpServerName, MCPServerStatus.DISCONNECTED);
+ if (mcpServerName === IDE_SERVER_NAME) {
+ ideContext.clearActiveFileContext();
+ }
};
if (mcpServerName === IDE_SERVER_NAME) {