mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
fix: qwen vscode extension
This commit is contained in:
@@ -1,23 +1,23 @@
|
||||
# Gemini CLI Extensions
|
||||
# Qwen Code Extensions
|
||||
|
||||
Gemini CLI supports extensions that can be used to configure and extend its functionality.
|
||||
Qwen Code supports extensions that can be used to configure and extend its functionality.
|
||||
|
||||
## How it works
|
||||
|
||||
On startup, Gemini CLI looks for extensions in two locations:
|
||||
On startup, Qwen Code looks for extensions in two locations:
|
||||
|
||||
1. `<workspace>/.gemini/extensions`
|
||||
2. `<home>/.gemini/extensions`
|
||||
1. `<workspace>/.qwen/extensions`
|
||||
2. `<home>/.qwen/extensions`
|
||||
|
||||
Gemini CLI loads all extensions from both locations. If an extension with the same name exists in both locations, the extension in the workspace directory takes precedence.
|
||||
Qwen Code loads all extensions from both locations. If an extension with the same name exists in both locations, the extension in the workspace directory takes precedence.
|
||||
|
||||
Within each location, individual extensions exist as a directory that contains a `gemini-extension.json` file. For example:
|
||||
Within each location, individual extensions exist as a directory that contains a `qwen-extension.json` file. For example:
|
||||
|
||||
`<workspace>/.gemini/extensions/my-extension/gemini-extension.json`
|
||||
`<workspace>/.qwen/extensions/my-extension/qwen-extension.json`
|
||||
|
||||
### `gemini-extension.json`
|
||||
### `qwen-extension.json`
|
||||
|
||||
The `gemini-extension.json` file contains the configuration for the extension. The file has the following structure:
|
||||
The `qwen-extension.json` file contains the configuration for the extension. The file has the following structure:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -39,7 +39,7 @@ The `gemini-extension.json` file contains the configuration for the extension. T
|
||||
- `contextFileName`: The name of the file that contains the context for the extension. This will be used to load the context from the workspace. If this property is not used but a `QWEN.md` file is present in your extension directory, then that file will be loaded.
|
||||
- `excludeTools`: An array of tool names to exclude from the model. You can also specify command-specific restrictions for tools that support it, like the `run_shell_command` tool. For example, `"excludeTools": ["run_shell_command(rm -rf)"]` will block the `rm -rf` command.
|
||||
|
||||
When Gemini CLI starts, it loads all the extensions and merges their configurations. If there are any conflicts, the workspace configuration takes precedence.
|
||||
When Qwen Code starts, it loads all the extensions and merges their configurations. If there are any conflicts, the workspace configuration takes precedence.
|
||||
|
||||
## Extension Commands
|
||||
|
||||
@@ -50,8 +50,8 @@ Extensions can provide [custom commands](./cli/commands.md#custom-commands) by p
|
||||
An extension named `gcp` with the following structure:
|
||||
|
||||
```
|
||||
.gemini/extensions/gcp/
|
||||
├── gemini-extension.json
|
||||
.qwen/extensions/gcp/
|
||||
├── qwen-extension.json
|
||||
└── commands/
|
||||
├── deploy.toml
|
||||
└── gcs/
|
||||
|
||||
@@ -1093,7 +1093,7 @@ describe('loadCliConfig ideModeFeature', () => {
|
||||
vi.mocked(os.homedir).mockReturnValue('/mock/home/user');
|
||||
process.env.GEMINI_API_KEY = 'test-api-key';
|
||||
delete process.env.SANDBOX;
|
||||
delete process.env.GEMINI_CLI_IDE_SERVER_PORT;
|
||||
delete process.env.QWEN_CODE_IDE_SERVER_PORT;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -10,7 +10,8 @@ import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
|
||||
export const EXTENSIONS_DIRECTORY_NAME = path.join('.qwen', 'extensions');
|
||||
export const EXTENSIONS_CONFIG_FILENAME = 'gemini-extension.json';
|
||||
export const EXTENSIONS_CONFIG_FILENAME = 'qwen-extension.json';
|
||||
export const EXTENSIONS_CONFIG_FILENAME_OLD = 'gemini-extension.json';
|
||||
|
||||
export interface Extension {
|
||||
path: string;
|
||||
@@ -68,13 +69,20 @@ function loadExtension(extensionDir: string): Extension | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
const configFilePath = path.join(extensionDir, EXTENSIONS_CONFIG_FILENAME);
|
||||
let configFilePath = path.join(extensionDir, EXTENSIONS_CONFIG_FILENAME);
|
||||
if (!fs.existsSync(configFilePath)) {
|
||||
const oldConfigFilePath = path.join(
|
||||
extensionDir,
|
||||
EXTENSIONS_CONFIG_FILENAME_OLD,
|
||||
);
|
||||
if (!fs.existsSync(oldConfigFilePath)) {
|
||||
console.error(
|
||||
`Warning: extension directory ${extensionDir} does not contain a config file ${configFilePath}.`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
configFilePath = oldConfigFilePath;
|
||||
}
|
||||
|
||||
try {
|
||||
const configContent = fs.readFileSync(configFilePath, 'utf-8');
|
||||
|
||||
@@ -631,8 +631,8 @@ export async function start_sandbox(
|
||||
|
||||
// Pass through IDE mode environment variables
|
||||
for (const envVar of [
|
||||
'GEMINI_CLI_IDE_SERVER_PORT',
|
||||
'GEMINI_CLI_IDE_WORKSPACE_PATH',
|
||||
'QWEN_CODE_IDE_SERVER_PORT',
|
||||
'QWEN_CODE_IDE_WORKSPACE_PATH',
|
||||
'TERM_PROGRAM',
|
||||
]) {
|
||||
if (process.env[envVar]) {
|
||||
|
||||
@@ -83,7 +83,7 @@ export class IdeClient {
|
||||
if (!this.currentIde || !this.currentIdeDisplayName) {
|
||||
this.setState(
|
||||
IDEConnectionStatus.Disconnected,
|
||||
`IDE integration is not supported in your current environment. To use this feature, run Gemini CLI in one of these supported IDEs: ${Object.values(
|
||||
`IDE integration is not supported in your current environment. To use this feature, run Qwen Code in one of these supported IDEs: ${Object.values(
|
||||
DetectedIde,
|
||||
)
|
||||
.map((ide) => getIdeDisplayName(ide))
|
||||
@@ -233,7 +233,7 @@ export class IdeClient {
|
||||
}
|
||||
|
||||
private validateWorkspacePath(): boolean {
|
||||
const ideWorkspacePath = process.env['GEMINI_CLI_IDE_WORKSPACE_PATH'];
|
||||
const ideWorkspacePath = process.env['QWEN_CODE_IDE_WORKSPACE_PATH'];
|
||||
if (ideWorkspacePath === undefined) {
|
||||
this.setState(
|
||||
IDEConnectionStatus.Disconnected,
|
||||
@@ -257,7 +257,7 @@ export class IdeClient {
|
||||
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
||||
this.setState(
|
||||
IDEConnectionStatus.Disconnected,
|
||||
`Directory mismatch. Gemini CLI is running in a different location than the open workspace in ${this.currentIdeDisplayName}. Please run the CLI from the same directory as your project's root folder.`,
|
||||
`Directory mismatch. Qwen Code is running in a different location than the open workspace in ${this.currentIdeDisplayName}. Please run the CLI from the same directory as your project's root folder.`,
|
||||
true,
|
||||
);
|
||||
return false;
|
||||
@@ -266,7 +266,7 @@ export class IdeClient {
|
||||
}
|
||||
|
||||
private getPortFromEnv(): string | undefined {
|
||||
const port = process.env['GEMINI_CLI_IDE_SERVER_PORT'];
|
||||
const port = process.env['QWEN_CODE_IDE_SERVER_PORT'];
|
||||
if (!port) {
|
||||
this.setState(
|
||||
IDEConnectionStatus.Disconnected,
|
||||
|
||||
@@ -86,7 +86,7 @@ describe('ide-installer', () => {
|
||||
.mockImplementation(() => '');
|
||||
const result = await installer.install();
|
||||
expect(execSyncSpy).toHaveBeenCalledWith(
|
||||
'npx ovsx get google.gemini-cli-vscode-ide-companion',
|
||||
'npx ovsx get qwenlm.qwen-code-vscode-ide-companion',
|
||||
{ stdio: 'pipe' },
|
||||
);
|
||||
expect(result.success).toBe(true);
|
||||
|
||||
@@ -150,7 +150,7 @@ class VsCodeInstaller implements IdeInstaller {
|
||||
class OpenVSXInstaller implements IdeInstaller {
|
||||
async install(): Promise<InstallResult> {
|
||||
// TODO: Use the correct extension path.
|
||||
const command = `npx ovsx get google.gemini-cli-vscode-ide-companion`;
|
||||
const command = `npx ovsx get qwenlm.qwen-code-vscode-ide-companion`;
|
||||
try {
|
||||
child_process.execSync(command, { stdio: 'pipe' });
|
||||
return {
|
||||
|
||||
@@ -8,9 +8,9 @@ The Qwen Code Companion extension seamlessly integrates [Qwen Code](https://gith
|
||||
|
||||
- Selection Context: Qwen Code can easily access your cursor's position and selected text within the editor, giving it valuable context directly from your current work.
|
||||
|
||||
- Native Diffing: Seamlessly view, modify, and accept code changes suggested by Gemini CLI directly within the editor.
|
||||
- Native Diffing: Seamlessly view, modify, and accept code changes suggested by Qwen Code directly within the editor.
|
||||
|
||||
- Launch Gemini CLI: Quickly start a new Gemini CLI session from the Command Palette (Cmd+Shift+P or Ctrl+Shift+P) by running the "Gemini CLI: Run" command.
|
||||
- Launch Qwen Code: Quickly start a new Qwen Code session from the Command Palette (Cmd+Shift+P or Ctrl+Shift+P) by running the "Qwen Code: Run" command.
|
||||
|
||||
# Requirements
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 52 KiB |
@@ -48,7 +48,7 @@
|
||||
"icon": "$(close)"
|
||||
},
|
||||
{
|
||||
"command": "qwen-code.runGeminiCLI",
|
||||
"command": "qwen-code.runQwenCode",
|
||||
"title": "Qwen Code: Run"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@ export class DiffManager {
|
||||
const diffTitle = `${path.basename(filePath)} ↔ Modified`;
|
||||
await vscode.commands.executeCommand(
|
||||
'setContext',
|
||||
'gemini.diff.isVisible',
|
||||
'qwen.diff.isVisible',
|
||||
true,
|
||||
);
|
||||
|
||||
@@ -228,7 +228,7 @@ export class DiffManager {
|
||||
}
|
||||
await vscode.commands.executeCommand(
|
||||
'setContext',
|
||||
'gemini.diff.isVisible',
|
||||
'qwen.diff.isVisible',
|
||||
isVisible,
|
||||
);
|
||||
}
|
||||
@@ -241,7 +241,7 @@ export class DiffManager {
|
||||
const diffInfo = this.diffDocuments.get(rightDocUri.toString());
|
||||
await vscode.commands.executeCommand(
|
||||
'setContext',
|
||||
'gemini.diff.isVisible',
|
||||
'qwen.diff.isVisible',
|
||||
false,
|
||||
);
|
||||
|
||||
|
||||
@@ -80,8 +80,8 @@ describe('activate', () => {
|
||||
vi.mocked(context.globalState.get).mockReturnValue(undefined);
|
||||
await activate(context);
|
||||
expect(showInformationMessageMock).toHaveBeenCalledWith(
|
||||
'Gemini CLI Companion extension successfully installed. Please restart your terminal to enable full IDE integration.',
|
||||
'Re-launch Gemini CLI',
|
||||
'Qwen Code Companion extension successfully installed. Please restart your terminal to enable full IDE integration.',
|
||||
'Run Qwen Code',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -91,16 +91,16 @@ describe('activate', () => {
|
||||
expect(vscode.window.showInformationMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should launch the Gemini CLI when the user clicks the button', async () => {
|
||||
it('should launch Qwen Code when the user clicks the button', async () => {
|
||||
const showInformationMessageMock = vi
|
||||
.mocked(vscode.window.showInformationMessage)
|
||||
.mockResolvedValue('Re-launch Gemini CLI' as never);
|
||||
.mockResolvedValue('Run Qwen Code' as never);
|
||||
vi.mocked(context.globalState.get).mockReturnValue(undefined);
|
||||
await activate(context);
|
||||
expect(showInformationMessageMock).toHaveBeenCalled();
|
||||
await new Promise(process.nextTick); // Wait for the promise to resolve
|
||||
expect(vscode.commands.executeCommand).toHaveBeenCalledWith(
|
||||
'gemini-cli.runGeminiCLI',
|
||||
'qwen-code.runQwenCode',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,9 +9,9 @@ import { IDEServer } from './ide-server.js';
|
||||
import { DiffContentProvider, DiffManager } from './diff-manager.js';
|
||||
import { createLogger } from './utils/logger.js';
|
||||
|
||||
const INFO_MESSAGE_SHOWN_KEY = 'geminiCliInfoMessageShown';
|
||||
const IDE_WORKSPACE_PATH_ENV_VAR = 'GEMINI_CLI_IDE_WORKSPACE_PATH';
|
||||
export const DIFF_SCHEME = 'gemini-diff';
|
||||
const INFO_MESSAGE_SHOWN_KEY = 'qwenCodeInfoMessageShown';
|
||||
const IDE_WORKSPACE_PATH_ENV_VAR = 'QWEN_CODE_IDE_WORKSPACE_PATH';
|
||||
export const DIFF_SCHEME = 'qwen-diff';
|
||||
|
||||
let ideServer: IDEServer;
|
||||
let logger: vscode.OutputChannel;
|
||||
@@ -35,7 +35,7 @@ function updateWorkspacePath(context: vscode.ExtensionContext) {
|
||||
}
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
logger = vscode.window.createOutputChannel('Gemini CLI IDE Companion');
|
||||
logger = vscode.window.createOutputChannel('Qwen Code Companion');
|
||||
log = createLogger(context, logger);
|
||||
log('Extension activated');
|
||||
|
||||
@@ -54,24 +54,18 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
DIFF_SCHEME,
|
||||
diffContentProvider,
|
||||
),
|
||||
vscode.commands.registerCommand(
|
||||
'gemini.diff.accept',
|
||||
(uri?: vscode.Uri) => {
|
||||
vscode.commands.registerCommand('qwen.diff.accept', (uri?: vscode.Uri) => {
|
||||
const docUri = uri ?? vscode.window.activeTextEditor?.document.uri;
|
||||
if (docUri && docUri.scheme === DIFF_SCHEME) {
|
||||
diffManager.acceptDiff(docUri);
|
||||
}
|
||||
},
|
||||
),
|
||||
vscode.commands.registerCommand(
|
||||
'gemini.diff.cancel',
|
||||
(uri?: vscode.Uri) => {
|
||||
}),
|
||||
vscode.commands.registerCommand('qwen.diff.cancel', (uri?: vscode.Uri) => {
|
||||
const docUri = uri ?? vscode.window.activeTextEditor?.document.uri;
|
||||
if (docUri && docUri.scheme === DIFF_SCHEME) {
|
||||
diffManager.cancelDiff(docUri);
|
||||
}
|
||||
},
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
ideServer = new IDEServer(log, diffManager);
|
||||
@@ -85,13 +79,13 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
if (!context.globalState.get(INFO_MESSAGE_SHOWN_KEY)) {
|
||||
void vscode.window
|
||||
.showInformationMessage(
|
||||
'Gemini CLI Companion extension successfully installed. Please restart your terminal to enable full IDE integration.',
|
||||
'Re-launch Gemini CLI',
|
||||
'Qwen Code Companion extension successfully installed. Please restart your terminal to enable full IDE integration.',
|
||||
'Run Qwen Code',
|
||||
)
|
||||
.then(
|
||||
(selection) => {
|
||||
if (selection === 'Re-launch Gemini CLI') {
|
||||
void vscode.commands.executeCommand('gemini-cli.runGeminiCLI');
|
||||
if (selection === 'Run Qwen Code') {
|
||||
void vscode.commands.executeCommand('qwen-code.runQwenCode');
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
@@ -105,13 +99,13 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
vscode.workspace.onDidChangeWorkspaceFolders(() => {
|
||||
updateWorkspacePath(context);
|
||||
}),
|
||||
vscode.commands.registerCommand('gemini-cli.runGeminiCLI', () => {
|
||||
const geminiCmd = 'gemini';
|
||||
const terminal = vscode.window.createTerminal(`Gemini CLI`);
|
||||
vscode.commands.registerCommand('qwen-code.runQwenCode', () => {
|
||||
const qwenCmd = 'qwen';
|
||||
const terminal = vscode.window.createTerminal(`Qwen Code`);
|
||||
terminal.show();
|
||||
terminal.sendText(geminiCmd);
|
||||
terminal.sendText(qwenCmd);
|
||||
}),
|
||||
vscode.commands.registerCommand('gemini-cli.showNotices', async () => {
|
||||
vscode.commands.registerCommand('qwen-code.showNotices', async () => {
|
||||
const noticePath = vscode.Uri.joinPath(
|
||||
context.extensionUri,
|
||||
'NOTICES.txt',
|
||||
|
||||
@@ -17,7 +17,7 @@ import { DiffManager } from './diff-manager.js';
|
||||
import { OpenFilesManager } from './open-files-manager.js';
|
||||
|
||||
const MCP_SESSION_ID_HEADER = 'mcp-session-id';
|
||||
const IDE_SERVER_PORT_ENV_VAR = 'GEMINI_CLI_IDE_SERVER_PORT';
|
||||
const IDE_SERVER_PORT_ENV_VAR = 'QWEN_CODE_IDE_SERVER_PORT';
|
||||
|
||||
function sendIdeContextUpdateNotification(
|
||||
transport: StreamableHTTPServerTransport,
|
||||
|
||||
Reference in New Issue
Block a user