diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index a9f47f0b0..8dd09a238 100755 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -170,7 +170,17 @@ function normalizeOutputFormat( } export async function parseArguments(settings: Settings): Promise { - const rawArgv = hideBin(process.argv); + let rawArgv = hideBin(process.argv); + + // hack: if the first argument is the CLI entry point, remove it + if ( + rawArgv.length > 0 && + (rawArgv[0].endsWith('/dist/qwen-cli/cli.js') || + rawArgv[0].endsWith('/dist/cli.js')) + ) { + rawArgv = rawArgv.slice(1); + } + const yargsInstance = yargs(rawArgv) .locale('en') .scriptName('qwen') diff --git a/packages/vscode-ide-companion/src/extension.ts b/packages/vscode-ide-companion/src/extension.ts index 2f2b462f7..be0f669e6 100644 --- a/packages/vscode-ide-companion/src/extension.ts +++ b/packages/vscode-ide-companion/src/extension.ts @@ -17,6 +17,7 @@ import { import { WebViewProvider } from './webview/WebViewProvider.js'; import { registerNewCommands } from './commands/index.js'; import { ReadonlyFileSystemProvider } from './services/readonlyFileSystemProvider.js'; +import { isWindows } from './utils/platform.js'; const CLI_IDE_COMPANION_IDENTIFIER = 'qwenlm.qwen-code-vscode-ide-companion'; const INFO_MESSAGE_SHOWN_KEY = 'qwenCodeInfoMessageShown'; @@ -312,13 +313,38 @@ export async function activate(context: vscode.ExtensionContext) { 'qwen-cli', 'cli.js', ).fsPath; - const quote = (s: string) => `"${s.replaceAll('"', '\\"')}"`; - const qwenCmd = `${quote(process.execPath)} ${quote(cliEntry)}`; - const terminal = vscode.window.createTerminal({ + const execPath = process.execPath; + const lowerExecPath = execPath.toLowerCase(); + const needsElectronRunAsNode = + lowerExecPath.includes('code') || + lowerExecPath.includes('electron'); + + let qwenCmd: string; + const terminalOptions: vscode.TerminalOptions = { name: `Qwen Code (${selectedFolder.name})`, cwd: selectedFolder.uri.fsPath, location, - }); + }; + + if (isWindows) { + // Use system Node via cmd.exe; avoid PowerShell parsing issues + const quoteCmd = (s: string) => `"${s.replace(/"/g, '""')}"`; + const cliQuoted = quoteCmd(cliEntry); + // TODO: @yiliang114, temporarily run through node, and later hope to decouple from the local node + qwenCmd = `node ${cliQuoted}`; + terminalOptions.shellPath = process.env.ComSpec; + } else { + const quotePosix = (s: string) => `"${s.replace(/"/g, '\\"')}"`; + const baseCmd = `${quotePosix(execPath)} ${quotePosix(cliEntry)}`; + if (needsElectronRunAsNode) { + // macOS Electron helper needs ELECTRON_RUN_AS_NODE=1; + qwenCmd = `ELECTRON_RUN_AS_NODE=1 ${baseCmd}`; + } else { + qwenCmd = baseCmd; + } + } + + const terminal = vscode.window.createTerminal(terminalOptions); terminal.show(); terminal.sendText(qwenCmd); } diff --git a/packages/vscode-ide-companion/src/services/acpMessageHandler.ts b/packages/vscode-ide-companion/src/services/acpMessageHandler.ts index 8766fdf31..c2fad7701 100644 --- a/packages/vscode-ide-companion/src/services/acpMessageHandler.ts +++ b/packages/vscode-ide-companion/src/services/acpMessageHandler.ts @@ -26,6 +26,7 @@ import type { } from '../types/connectionTypes.js'; import { AcpFileHandler } from '../services/acpFileHandler.js'; import type { ChildProcess } from 'child_process'; +import { isWindows } from '../utils/platform.js'; /** * ACP Message Handler Class @@ -47,7 +48,7 @@ export class AcpMessageHandler { sendResponseMessage(child: ChildProcess | null, response: AcpResponse): void { if (child?.stdin) { const jsonString = JSON.stringify(response); - const lineEnding = process.platform === 'win32' ? '\r\n' : '\n'; + const lineEnding = isWindows ? '\r\n' : '\n'; child.stdin.write(jsonString + lineEnding); } } diff --git a/packages/vscode-ide-companion/src/services/acpSessionManager.ts b/packages/vscode-ide-companion/src/services/acpSessionManager.ts index e2055a3a2..2d85d20aa 100644 --- a/packages/vscode-ide-companion/src/services/acpSessionManager.ts +++ b/packages/vscode-ide-companion/src/services/acpSessionManager.ts @@ -19,6 +19,7 @@ import type { ApprovalModeValue } from '../types/approvalModeValueTypes.js'; import { AGENT_METHODS } from '../constants/acpSchema.js'; import type { PendingRequest } from '../types/connectionTypes.js'; import type { ChildProcess } from 'child_process'; +import { isWindows } from '../utils/platform.js'; /** * ACP Session Manager Class @@ -102,7 +103,7 @@ export class AcpSessionManager { ): void { if (child?.stdin) { const jsonString = JSON.stringify(message); - const lineEnding = process.platform === 'win32' ? '\r\n' : '\n'; + const lineEnding = isWindows ? '\r\n' : '\n'; child.stdin.write(jsonString + lineEnding); } } diff --git a/packages/vscode-ide-companion/src/utils/platform.ts b/packages/vscode-ide-companion/src/utils/platform.ts new file mode 100644 index 000000000..994aadc3f --- /dev/null +++ b/packages/vscode-ide-companion/src/utils/platform.ts @@ -0,0 +1,8 @@ +/** + * @license + * Copyright 2025 Qwen Team + * SPDX-License-Identifier: Apache-2.0 + */ + +/** Whether the current platform is Windows */ +export const isWindows = process.platform === 'win32';