mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
Add toggleable IDE mode setting (#5146)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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' };
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user