mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-21 09:17:53 +00:00
feat(cli): Introduce arguments for shell execution in custom commands (#5966)
This commit is contained in:
@@ -5,6 +5,102 @@
|
||||
*/
|
||||
|
||||
import { Config } from '../config/config.js';
|
||||
import os from 'os';
|
||||
import { quote } from 'shell-quote';
|
||||
|
||||
/**
|
||||
* An identifier for the shell type.
|
||||
*/
|
||||
export type ShellType = 'cmd' | 'powershell' | 'bash';
|
||||
|
||||
/**
|
||||
* Defines the configuration required to execute a command string within a specific shell.
|
||||
*/
|
||||
export interface ShellConfiguration {
|
||||
/** The path or name of the shell executable (e.g., 'bash', 'cmd.exe'). */
|
||||
executable: string;
|
||||
/**
|
||||
* The arguments required by the shell to execute a subsequent string argument.
|
||||
*/
|
||||
argsPrefix: string[];
|
||||
/** An identifier for the shell type. */
|
||||
shell: ShellType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the appropriate shell configuration for the current platform.
|
||||
*
|
||||
* This ensures we can execute command strings predictably and securely across platforms
|
||||
* using the `spawn(executable, [...argsPrefix, commandString], { shell: false })` pattern.
|
||||
*
|
||||
* @returns The ShellConfiguration for the current environment.
|
||||
*/
|
||||
export function getShellConfiguration(): ShellConfiguration {
|
||||
if (isWindows()) {
|
||||
const comSpec = process.env.ComSpec || 'cmd.exe';
|
||||
const executable = comSpec.toLowerCase();
|
||||
|
||||
if (
|
||||
executable.endsWith('powershell.exe') ||
|
||||
executable.endsWith('pwsh.exe')
|
||||
) {
|
||||
// For PowerShell, the arguments are different.
|
||||
// -NoProfile: Speeds up startup.
|
||||
// -Command: Executes the following command.
|
||||
return {
|
||||
executable: comSpec,
|
||||
argsPrefix: ['-NoProfile', '-Command'],
|
||||
shell: 'powershell',
|
||||
};
|
||||
}
|
||||
|
||||
// Default to cmd.exe for anything else on Windows.
|
||||
// Flags for CMD:
|
||||
// /d: Skip execution of AutoRun commands.
|
||||
// /s: Modifies the treatment of the command string (important for quoting).
|
||||
// /c: Carries out the command specified by the string and then terminates.
|
||||
return {
|
||||
executable: comSpec,
|
||||
argsPrefix: ['/d', '/s', '/c'],
|
||||
shell: 'cmd',
|
||||
};
|
||||
}
|
||||
|
||||
// Unix-like systems (Linux, macOS)
|
||||
return { executable: 'bash', argsPrefix: ['-c'], shell: 'bash' };
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the platform detection constant for use in process management (e.g., killing processes).
|
||||
*/
|
||||
export const isWindows = () => os.platform() === 'win32';
|
||||
|
||||
/**
|
||||
* Escapes a string so that it can be safely used as a single argument
|
||||
* in a shell command, preventing command injection.
|
||||
*
|
||||
* @param arg The argument string to escape.
|
||||
* @param shell The type of shell the argument is for.
|
||||
* @returns The shell-escaped string.
|
||||
*/
|
||||
export function escapeShellArg(arg: string, shell: ShellType): string {
|
||||
if (!arg) {
|
||||
return '';
|
||||
}
|
||||
|
||||
switch (shell) {
|
||||
case 'powershell':
|
||||
// For PowerShell, wrap in single quotes and escape internal single quotes by doubling them.
|
||||
return `'${arg.replace(/'/g, "''")}'`;
|
||||
case 'cmd':
|
||||
// Simple Windows escaping for cmd.exe: wrap in double quotes and escape inner double quotes.
|
||||
return `"${arg.replace(/"/g, '""')}"`;
|
||||
case 'bash':
|
||||
default:
|
||||
// POSIX shell escaping using shell-quote.
|
||||
return quote([arg]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a shell command into a list of individual commands, respecting quotes.
|
||||
|
||||
Reference in New Issue
Block a user