fix: improve trans windows route hints
This commit is contained in:
+66
-1
@@ -1147,6 +1147,9 @@ function parseWinRouteArgs(route: ParsedSshRoute, args: string[]): ParsedSshArgs
|
||||
if (operation.length === 0) {
|
||||
throw new Error(`ssh ${route.raw} requires a Windows operation, for example: ssh ${route.providerId}:win cmd ver or ssh ${route.providerId}:win skills`);
|
||||
}
|
||||
if (operation === "win") {
|
||||
throw new Error(windowsRouteRepeatedWinOperationMessage(route, args.slice(1)));
|
||||
}
|
||||
if (operation === "upload" || operation === "download") {
|
||||
return { remoteCommand: null, requiresStdin: false, invocationKind: "helper" };
|
||||
}
|
||||
@@ -1179,6 +1182,9 @@ function parseWinRouteArgs(route: ParsedSshRoute, args: string[]): ParsedSshArgs
|
||||
invocationKind: "helper",
|
||||
};
|
||||
}
|
||||
if (operation === "git") {
|
||||
return parseWindowsGitInvocation(route, args.slice(1));
|
||||
}
|
||||
if (operation === "ps" || operation === "powershell" || operation === "powershell.exe") {
|
||||
const commandArgs = args[1] === "--" ? args.slice(2) : args.slice(1);
|
||||
if (commandArgs.length >= 2 && (commandArgs[0] === "-File" || commandArgs[0] === "-file")) {
|
||||
@@ -1203,7 +1209,7 @@ function parseWinRouteArgs(route: ParsedSshRoute, args: string[]): ParsedSshArgs
|
||||
};
|
||||
}
|
||||
if (operation !== "cmd" && operation !== "cmd.exe") {
|
||||
throw new Error(`unsupported ssh win operation: ${operation}; use ssh ${route.providerId}:win ps, ssh ${route.providerId}:win cmd <command-line>, ssh ${route.providerId}:win <pwd|ls|cat|head|tail|stat|wc|rg>, ssh ${route.providerId}:win apply-patch, or ssh ${route.providerId}:win skills`);
|
||||
throw new Error(windowsUnsupportedOperationMessage(route, operation));
|
||||
}
|
||||
const commandArgs = args[1] === "--" ? args.slice(2) : args.slice(1);
|
||||
if (commandArgs.length === 0) {
|
||||
@@ -1220,6 +1226,56 @@ function parseWinRouteArgs(route: ParsedSshRoute, args: string[]): ParsedSshArgs
|
||||
};
|
||||
}
|
||||
|
||||
function windowsRouteRepeatedWinOperationMessage(route: ParsedSshRoute, nextArgs: string[]): string {
|
||||
const entrypoint = sshDisplayEntrypoint();
|
||||
const suffix = nextArgs.length > 0 ? ` ${nextArgs.join(" ")}` : " ps";
|
||||
return `unsupported ssh win operation: win; route ${route.raw} already selects the Windows plane. ` +
|
||||
`Write the operation directly after the route, for example \`${entrypoint} ${route.raw}${suffix}\`, not \`${entrypoint} ${route.raw} win${suffix}\`.`;
|
||||
}
|
||||
|
||||
function windowsUnsupportedOperationMessage(route: ParsedSshRoute, operation: string): string {
|
||||
const entrypoint = sshDisplayEntrypoint();
|
||||
const gitHint = operation === "sed" || operation === "bash" || operation === "sh"
|
||||
? ` For repository commands on Windows, use \`${entrypoint} ${route.raw} git status --short --branch\`, \`${entrypoint} ${route.raw} git commit -m <message>\`, or wrap custom commands with \`${entrypoint} ${route.raw} ps <<'PS'\`.`
|
||||
: ` If you meant to run a repository command, use \`${entrypoint} ${route.raw} git status --short --branch\`, \`${entrypoint} ${route.raw} git commit -m <message>\`, or wrap it with \`${entrypoint} ${route.raw} ps <<'PS'\`.`;
|
||||
return `unsupported ssh win operation: ${operation}; Windows route operations are ps, cmd, skills, apply-patch, upload/download, git, and read-only fs helpers pwd|ls|cat|head|tail|stat|wc|rg.${gitHint}`;
|
||||
}
|
||||
|
||||
function parseWindowsGitInvocation(route: ParsedSshRoute, gitArgs: string[]): ParsedSshArgs {
|
||||
const subcommand = gitArgs[0] ?? "";
|
||||
if (subcommand.length === 0) throw new Error(`ssh ${route.raw} git requires a git subcommand, for example: ${sshDisplayEntrypoint()} ${route.raw} git status --short --branch`);
|
||||
if (subcommand === "commit") validateWindowsGitCommitArgs(route, gitArgs);
|
||||
const commandLine = ["git", ...gitArgs].map((value) => windowsCmdArgument(value, route)).join(" ");
|
||||
return {
|
||||
remoteCommand: buildWindowsPowerShellInvocation(buildWindowsCmdLauncherScript(buildWindowsCmdLine(commandLine, route.workspace))),
|
||||
requiresStdin: false,
|
||||
invocationKind: "argv",
|
||||
};
|
||||
}
|
||||
|
||||
function validateWindowsGitCommitArgs(route: ParsedSshRoute, gitArgs: string[]): void {
|
||||
const hasNonInteractiveMessage = gitArgs.slice(1).some((arg) => (
|
||||
arg === "--dry-run" ||
|
||||
arg === "--no-edit" ||
|
||||
arg === "-m" ||
|
||||
arg.startsWith("-m") ||
|
||||
arg === "--message" ||
|
||||
arg.startsWith("--message=") ||
|
||||
arg === "-F" ||
|
||||
arg.startsWith("-F") ||
|
||||
arg === "--file" ||
|
||||
arg.startsWith("--file=") ||
|
||||
arg === "-C" ||
|
||||
arg.startsWith("-C") ||
|
||||
arg === "--reuse-message" ||
|
||||
arg.startsWith("--reuse-message=") ||
|
||||
arg.startsWith("--fixup=")
|
||||
));
|
||||
if (hasNonInteractiveMessage) return;
|
||||
const entrypoint = sshDisplayEntrypoint();
|
||||
throw new Error(`ssh win git commit would open an editor; use ${entrypoint} ${route.raw} git commit -m <message>, ${entrypoint} ${route.raw} git commit --no-edit, or wrap an interactive command with ${entrypoint} ${route.raw} ps <<'PS'`);
|
||||
}
|
||||
|
||||
type WindowsFsReadOnlyOperation = "pwd" | "ls" | "cat" | "head" | "tail" | "stat" | "wc" | "rg";
|
||||
const windowsFsReadOnlyOperations = new Set<string>(["pwd", "ls", "cat", "head", "tail", "stat", "wc", "rg"]);
|
||||
const windowsFsReadOnlyDefaultMaxBytes = 256 * 1024;
|
||||
@@ -1281,6 +1337,15 @@ function windowsCmdQuote(value: string): string {
|
||||
return `"${value}"`;
|
||||
}
|
||||
|
||||
function windowsCmdArgument(value: string, route: ParsedSshRoute): string {
|
||||
if (value.length === 0) return "\"\"";
|
||||
if (/[\r\n"]/u.test(value) || /[&|<>^%!]/u.test(value)) {
|
||||
const entrypoint = sshDisplayEntrypoint();
|
||||
throw new Error(`ssh win git argument contains characters that require shell review; use ${entrypoint} ${route.raw} ps <<'PS' for this command`);
|
||||
}
|
||||
return /\s/u.test(value) ? `"${value}"` : value;
|
||||
}
|
||||
|
||||
function parseWindowsSkillsOptions(args: string[]): { limit: number; scopes: Array<"agents" | "codex"> } {
|
||||
let limit = 100;
|
||||
let scope: "agents" | "codex" | "all" = "agents";
|
||||
|
||||
Reference in New Issue
Block a user