Compare commits

...

2 Commits

Author SHA1 Message Date
yiliang114
052337861b Fix #1416 2026-01-07 21:05:49 +08:00
yiliang114
361492247e fix(vscode-ide-companion): fix cross-platform CLI execution in terminal
- Add platform.ts utility with isWindows constant
- Fix Windows PowerShell execution with & call operator
- Fix macOS Electron helper with ELECTRON_RUN_AS_NODE=1
- Prefer system Node.js, fallback to VS Code runtime
- Refactor platform detection in acpMessageHandler and acpSessionManager

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 01:35:05 +08:00
4 changed files with 47 additions and 4 deletions

View File

@@ -17,11 +17,25 @@ 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';
import { execSync } from 'child_process';
const CLI_IDE_COMPANION_IDENTIFIER = 'qwenlm.qwen-code-vscode-ide-companion';
const INFO_MESSAGE_SHOWN_KEY = 'qwenCodeInfoMessageShown';
export const DIFF_SCHEME = 'qwen-diff';
/**
* Check if Node.js is available in the system PATH
*/
function isNodeAvailable(): boolean {
try {
execSync(isWindows ? 'where node' : 'which node', { stdio: 'ignore' });
return true;
} catch {
return false;
}
}
/**
* IDE environments where the installation greeting is hidden. In these
* environments we either are pre-installed and the installation message is
@@ -312,8 +326,27 @@ 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 quote = (s: string) => `"${s.replace(/"/g, '\\"')}"`;
let qwenCmd: string;
if (isNodeAvailable()) {
// Prefer system Node.js
qwenCmd = `node ${quote(cliEntry)}`;
} else {
// Fallback to VS Code's bundled Node.js runtime
const execPath = process.execPath;
const baseCmd = `${quote(execPath)} ${quote(cliEntry)}`;
if (isWindows) {
// PowerShell requires & call operator for quoted paths
qwenCmd = `& ${baseCmd}`;
} else if (execPath.toLowerCase().includes('code helper')) {
// macOS Electron helper needs ELECTRON_RUN_AS_NODE=1; add -i to force TUI mode
qwenCmd = `ELECTRON_RUN_AS_NODE=1 ${baseCmd} -i`;
} else {
qwenCmd = baseCmd;
}
}
const terminal = vscode.window.createTerminal({
name: `Qwen Code (${selectedFolder.name})`,
cwd: selectedFolder.uri.fsPath,

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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';