Add toggleable IDE mode setting (#5146)

This commit is contained in:
christine betts
2025-07-30 22:36:24 +00:00
committed by GitHub
parent ac1bb5ee42
commit 325bb89137
13 changed files with 231 additions and 123 deletions

View File

@@ -184,6 +184,7 @@ export interface ConfigParameters {
blockedMcpServers?: Array<{ name: string; extensionName: string }>;
noBrowser?: boolean;
summarizeToolOutput?: Record<string, SummarizeToolOutputSettings>;
ideModeFeature?: boolean;
ideMode?: boolean;
ideClient: IdeClient;
}
@@ -228,8 +229,9 @@ export class Config {
private readonly model: string;
private readonly extensionContextFilePaths: string[];
private readonly noBrowser: boolean;
private readonly ideMode: boolean;
private readonly ideClient: IdeClient;
private readonly ideModeFeature: boolean;
private ideMode: boolean;
private ideClient: IdeClient;
private inFallbackMode = false;
private readonly maxSessionTurns: number;
private readonly listExtensions: boolean;
@@ -298,7 +300,8 @@ export class Config {
this._blockedMcpServers = params.blockedMcpServers ?? [];
this.noBrowser = params.noBrowser ?? false;
this.summarizeToolOutput = params.summarizeToolOutput;
this.ideMode = params.ideMode ?? false;
this.ideModeFeature = params.ideModeFeature ?? false;
this.ideMode = params.ideMode ?? true;
this.ideClient = params.ideClient;
if (params.contextFileName) {
@@ -589,14 +592,30 @@ export class Config {
return this.summarizeToolOutput;
}
getIdeMode(): boolean {
return this.ideMode;
getIdeModeFeature(): boolean {
return this.ideModeFeature;
}
getIdeClient(): IdeClient {
return this.ideClient;
}
getIdeMode(): boolean {
return this.ideMode;
}
setIdeMode(value: boolean): void {
this.ideMode = value;
}
setIdeClientDisconnected(): void {
this.ideClient.setDisconnected();
}
setIdeClientConnected(): void {
this.ideClient.reconnect(this.ideMode && this.ideModeFeature);
}
async getGitService(): Promise<GitService> {
if (!this.gitService) {
this.gitService = new GitService(this.targetDir);

View File

@@ -199,7 +199,8 @@ describe('Gemini Client (client.ts)', () => {
setQuotaErrorOccurred: vi.fn(),
getNoBrowser: vi.fn().mockReturnValue(false),
getUsageStatisticsEnabled: vi.fn().mockReturnValue(true),
getIdeMode: vi.fn().mockReturnValue(false),
getIdeModeFeature: vi.fn().mockReturnValue(false),
getIdeMode: vi.fn().mockReturnValue(true),
getWorkspaceContext: vi.fn().mockReturnValue({
getDirectories: vi.fn().mockReturnValue(['/test/dir']),
}),
@@ -649,7 +650,7 @@ describe('Gemini Client (client.ts)', () => {
});
describe('sendMessageStream', () => {
it('should include IDE context when ideMode is enabled', async () => {
it('should include IDE context when ideModeFeature is enabled', async () => {
// Arrange
vi.mocked(ideContext.getIdeContext).mockReturnValue({
workspaceState: {
@@ -673,7 +674,7 @@ describe('Gemini Client (client.ts)', () => {
},
});
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
vi.spyOn(client['config'], 'getIdeModeFeature').mockReturnValue(true);
const mockStream = (async function* () {
yield { type: 'content', value: 'Hello' };
@@ -724,7 +725,7 @@ Here are some other files the user has open, with the most recent at the top:
);
});
it('should not add context if ideMode is enabled but no open files', async () => {
it('should not add context if ideModeFeature is enabled but no open files', async () => {
// Arrange
vi.mocked(ideContext.getIdeContext).mockReturnValue({
workspaceState: {
@@ -732,7 +733,7 @@ Here are some other files the user has open, with the most recent at the top:
},
});
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
vi.spyOn(client['config'], 'getIdeModeFeature').mockReturnValue(true);
const mockStream = (async function* () {
yield { type: 'content', value: 'Hello' };
@@ -771,7 +772,7 @@ Here are some other files the user has open, with the most recent at the top:
);
});
it('should add context if ideMode is enabled and there is one active file', async () => {
it('should add context if ideModeFeature is enabled and there is one active file', async () => {
// Arrange
vi.mocked(ideContext.getIdeContext).mockReturnValue({
workspaceState: {
@@ -787,7 +788,7 @@ Here are some other files the user has open, with the most recent at the top:
},
});
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
vi.spyOn(client['config'], 'getIdeModeFeature').mockReturnValue(true);
const mockStream = (async function* () {
yield { type: 'content', value: 'Hello' };
@@ -835,7 +836,7 @@ This is the selected text in the file:
);
});
it('should add context if ideMode is enabled and there are open files but no active file', async () => {
it('should add context if ideModeFeature is enabled and there are open files but no active file', async () => {
// Arrange
vi.mocked(ideContext.getIdeContext).mockReturnValue({
workspaceState: {
@@ -852,7 +853,7 @@ This is the selected text in the file:
},
});
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
vi.spyOn(client['config'], 'getIdeModeFeature').mockReturnValue(true);
const mockStream = (async function* () {
yield { type: 'content', value: 'Hello' };

View File

@@ -339,7 +339,7 @@ export class GeminiClient {
yield { type: GeminiEventType.ChatCompressed, value: compressed };
}
if (this.config.getIdeMode()) {
if (this.config.getIdeModeFeature() && this.config.getIdeMode()) {
const ideContextState = ideContext.getIdeContext();
const openFiles = ideContextState?.workspaceState?.openFiles;

View File

@@ -41,14 +41,14 @@ export class IdeClient {
private readonly currentIde: DetectedIde | undefined;
private readonly currentIdeDisplayName: string | undefined;
private constructor(ideMode: boolean) {
if (!ideMode) {
return;
}
constructor(ideMode: boolean) {
this.currentIde = detectIde();
if (this.currentIde) {
this.currentIdeDisplayName = getIdeDisplayName(this.currentIde);
}
if (!ideMode) {
return;
}
this.init().catch((err) => {
logger.debug('Failed to initialize IdeClient:', err);
});
@@ -130,6 +130,10 @@ export class IdeClient {
};
}
async reconnect(ideMode: boolean) {
IdeClient.instance = new IdeClient(ideMode);
}
private async establishConnection(port: string) {
let transport: StreamableHTTPClientTransport | undefined;
try {
@@ -189,7 +193,15 @@ export class IdeClient {
await this.establishConnection(port);
}
dispose() {
this.client?.close();
}
getDetectedIdeDisplayName(): string | undefined {
return this.currentIdeDisplayName;
}
setDisconnected() {
this.setState(IDEConnectionStatus.Disconnected);
}
}