mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
sync gemini-cli 0.1.17
Co-Authored-By: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -4,154 +4,158 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { fileURLToPath } from 'url';
|
||||
import { Config, IDEConnectionStatus } from '@qwen-code/qwen-code-core';
|
||||
import {
|
||||
Config,
|
||||
DetectedIde,
|
||||
IDEConnectionStatus,
|
||||
getIdeDisplayName,
|
||||
getIdeInstaller,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import {
|
||||
CommandContext,
|
||||
SlashCommand,
|
||||
SlashCommandActionReturn,
|
||||
CommandKind,
|
||||
} from './types.js';
|
||||
import * as child_process from 'child_process';
|
||||
import * as process from 'process';
|
||||
import { glob } from 'glob';
|
||||
import * as path from 'path';
|
||||
|
||||
const VSCODE_COMMAND = process.platform === 'win32' ? 'code.cmd' : 'code';
|
||||
const VSCODE_COMPANION_EXTENSION_FOLDER = 'vscode-ide-companion';
|
||||
|
||||
function isVSCodeInstalled(): boolean {
|
||||
try {
|
||||
child_process.execSync(
|
||||
process.platform === 'win32'
|
||||
? `where.exe ${VSCODE_COMMAND}`
|
||||
: `command -v ${VSCODE_COMMAND}`,
|
||||
{ stdio: 'ignore' },
|
||||
);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
import { SettingScope } from '../../config/settings.js';
|
||||
|
||||
export const ideCommand = (config: Config | null): SlashCommand | null => {
|
||||
if (!config?.getIdeMode()) {
|
||||
if (!config || !config.getIdeModeFeature()) {
|
||||
return null;
|
||||
}
|
||||
const ideClient = config.getIdeClient();
|
||||
const currentIDE = ideClient.getCurrentIde();
|
||||
if (!currentIDE || !ideClient.getDetectedIdeDisplayName()) {
|
||||
return {
|
||||
name: 'ide',
|
||||
description: 'manage IDE integration',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: (): SlashCommandActionReturn =>
|
||||
({
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content: `IDE integration is not supported in your current environment. To use this feature, run Gemini CLI in one of these supported IDEs: ${Object.values(
|
||||
DetectedIde,
|
||||
)
|
||||
.map((ide) => getIdeDisplayName(ide))
|
||||
.join(', ')}`,
|
||||
}) as const,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
const ideSlashCommand: SlashCommand = {
|
||||
name: 'ide',
|
||||
description: 'manage IDE integration',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
subCommands: [
|
||||
{
|
||||
name: 'status',
|
||||
description: 'check status of IDE integration',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: (_context: CommandContext): SlashCommandActionReturn => {
|
||||
const connection = config.getIdeClient()?.getConnectionStatus();
|
||||
switch (connection?.status) {
|
||||
case IDEConnectionStatus.Connected:
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `🟢 Connected`,
|
||||
} as const;
|
||||
case IDEConnectionStatus.Connecting:
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `🟡 Connecting...`,
|
||||
} as const;
|
||||
default: {
|
||||
let content = `🔴 Disconnected`;
|
||||
if (connection?.details) {
|
||||
content += `: ${connection.details}`;
|
||||
}
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content,
|
||||
} as const;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'install',
|
||||
description: 'install required VS Code companion extension',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context) => {
|
||||
if (!isVSCodeInstalled()) {
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'error',
|
||||
text: `VS Code command-line tool "${VSCODE_COMMAND}" not found in your PATH.`,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const bundleDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
// The VSIX file is copied to the bundle directory as part of the build.
|
||||
let vsixFiles = glob.sync(path.join(bundleDir, '*.vsix'));
|
||||
if (vsixFiles.length === 0) {
|
||||
// If the VSIX file is not in the bundle, it might be a dev
|
||||
// environment running with `npm start`. Look for it in the original
|
||||
// package location, relative to the bundle dir.
|
||||
const devPath = path.join(
|
||||
bundleDir,
|
||||
'..',
|
||||
'..',
|
||||
'..',
|
||||
'..',
|
||||
'..',
|
||||
VSCODE_COMPANION_EXTENSION_FOLDER,
|
||||
'*.vsix',
|
||||
);
|
||||
vsixFiles = glob.sync(devPath);
|
||||
}
|
||||
if (vsixFiles.length === 0) {
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'error',
|
||||
text: 'Could not find the required VS Code companion extension. Please file a bug via /bug.',
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const vsixPath = vsixFiles[0];
|
||||
const command = `${VSCODE_COMMAND} --install-extension ${vsixPath} --force`;
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'info',
|
||||
text: `Installing VS Code companion extension...`,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
try {
|
||||
child_process.execSync(command, { stdio: 'pipe' });
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'info',
|
||||
text: 'VS Code companion extension installed successfully. Restart gemini-cli in a fresh terminal window.',
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
} catch (_error) {
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'error',
|
||||
text: `Failed to install VS Code companion extension.`,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
subCommands: [],
|
||||
};
|
||||
|
||||
const statusCommand: SlashCommand = {
|
||||
name: 'status',
|
||||
description: 'check status of IDE integration',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: (_context: CommandContext): SlashCommandActionReturn => {
|
||||
const connection = ideClient.getConnectionStatus();
|
||||
switch (connection.status) {
|
||||
case IDEConnectionStatus.Connected:
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `🟢 Connected to ${ideClient.getDetectedIdeDisplayName()}`,
|
||||
} as const;
|
||||
case IDEConnectionStatus.Connecting:
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content: `🟡 Connecting...`,
|
||||
} as const;
|
||||
default: {
|
||||
let content = `🔴 Disconnected`;
|
||||
if (connection?.details) {
|
||||
content += `: ${connection.details}`;
|
||||
}
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'error',
|
||||
content,
|
||||
} as const;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const installCommand: SlashCommand = {
|
||||
name: 'install',
|
||||
description: `install required IDE companion for ${ideClient.getDetectedIdeDisplayName()}`,
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context) => {
|
||||
const installer = getIdeInstaller(currentIDE);
|
||||
if (!installer) {
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'error',
|
||||
text: `No installer is available for ${ideClient.getDetectedIdeDisplayName()}. Please install the IDE companion manually from its marketplace.`,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'info',
|
||||
text: `Installing IDE companion...`,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
|
||||
const result = await installer.install();
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: result.success ? 'info' : 'error',
|
||||
text: result.message,
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const enableCommand: SlashCommand = {
|
||||
name: 'enable',
|
||||
description: 'enable IDE integration',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context: CommandContext) => {
|
||||
context.services.settings.setValue(SettingScope.User, 'ideMode', true);
|
||||
config.setIdeMode(true);
|
||||
config.setIdeClientConnected();
|
||||
},
|
||||
};
|
||||
|
||||
const disableCommand: SlashCommand = {
|
||||
name: 'disable',
|
||||
description: 'disable IDE integration',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (context: CommandContext) => {
|
||||
context.services.settings.setValue(SettingScope.User, 'ideMode', false);
|
||||
config.setIdeMode(false);
|
||||
config.setIdeClientDisconnected();
|
||||
},
|
||||
};
|
||||
|
||||
const ideModeEnabled = config.getIdeMode();
|
||||
if (ideModeEnabled) {
|
||||
ideSlashCommand.subCommands = [
|
||||
disableCommand,
|
||||
statusCommand,
|
||||
installCommand,
|
||||
];
|
||||
} else {
|
||||
ideSlashCommand.subCommands = [
|
||||
enableCommand,
|
||||
statusCommand,
|
||||
installCommand,
|
||||
];
|
||||
}
|
||||
|
||||
return ideSlashCommand;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user