fix: speed up tran apply-patch

This commit is contained in:
Codex
2026-05-25 14:06:40 +00:00
parent 1d56c46546
commit c3c50c3b36
4 changed files with 112 additions and 25 deletions
+2 -2
View File
@@ -895,7 +895,7 @@ async function runRemoteSshWebSocket(
const openTimeoutMs = Math.max(15000, Number(process.env.UNIDESK_SSH_OPEN_TIMEOUT_MS || 60000));
const payload = {
providerId: invocation.providerId,
command: wrapSshRemoteCommand(parsed.remoteCommand),
command: wrapSshRemoteCommand(parsed.remoteCommand, parsed.requiredHelpers),
cwd: invocation.route.plane === "host" ? invocation.route.workspace ?? undefined : undefined,
tty: parsed.remoteCommand === null,
stdinEotOnEnd: parsed.remoteCommand !== null,
@@ -1033,7 +1033,7 @@ export function remoteSshFrontendPlanForTest(target: string, args: string[]): Re
providerId: invocation.providerId,
route: invocation.route,
remoteCommand: invocation.parsed.remoteCommand,
wrappedRemoteCommand: wrapSshRemoteCommand(invocation.parsed.remoteCommand),
wrappedRemoteCommand: wrapSshRemoteCommand(invocation.parsed.remoteCommand, invocation.parsed.requiredHelpers),
requiresStdin: invocation.parsed.requiresStdin,
invocationKind: invocation.parsed.invocationKind,
payloadCwd: invocation.route.plane === "host" ? invocation.route.workspace : null,
+100 -21
View File
@@ -7,9 +7,11 @@ export interface ParsedSshArgs {
invocationKind: SshInvocationKind;
stdinPrefix?: string;
stdinSuffix?: string;
requiredHelpers?: SshHelperName[];
}
export type SshInvocationKind = "interactive" | "argv" | "helper" | "ssh-like";
export type SshHelperName = "apply_patch" | "glob" | "skill-discover";
export interface ParsedSshRoute {
providerId: string;
@@ -104,6 +106,65 @@ line_number_for_prefix() {
printf '%s\n' $((newline_count + 1))
}
replace_once_with_perl() {
command -v perl >/dev/null 2>&1 || return 127
perl -0777 -e '
use strict;
use warnings;
sub fail {
print STDERR "apply_patch: ", @_, "\n";
exit 1;
}
sub read_all {
my ($path, $label) = @_;
open my $fh, "<", $path or fail("failed to read $label");
binmode $fh;
local $/;
my $data = <$fh>;
close $fh;
return defined $data ? $data : "";
}
my ($target, $search_file, $replace_file, $hunk_id, $allow_loose, $out) = @ARGV;
my $old = read_all($target, $target);
my $search = read_all($search_file, "hunk search");
my $replacement = read_all($replace_file, "hunk replacement");
my $new;
if ($search eq "") {
fail("hunk $hunk_id in $target has no context; add unchanged/deleted anchor lines or pass --allow-loose after manual review") if $allow_loose ne "1";
print STDERR "apply_patch: hunk $hunk_id matched $target:1 (loose)\n";
$new = $replacement . $old;
} else {
my $pos = -1;
my $offset = 0;
my $count = 0;
while (1) {
my $found = index($old, $search, $offset);
last if $found < 0;
$pos = $found if $count == 0;
$count += 1;
last if $count > 1 && $allow_loose ne "1";
$offset = $found + length($search);
}
fail("hunk $hunk_id context not found in $target") if $count == 0;
fail("hunk $hunk_id context matched multiple locations in $target; add more unchanged context or pass --allow-loose after manual review") if $count > 1 && $allow_loose ne "1";
my $prefix = substr($old, 0, $pos);
my $suffix = substr($old, $pos + length($search));
my $line = ($prefix =~ tr/\n//) + 1;
print STDERR "apply_patch: hunk $hunk_id matched $target:$line\n";
$new = $prefix . $replacement . $suffix;
}
open my $ofh, ">", $out or fail("failed to render patched file");
binmode $ofh;
print $ofh $new or fail("failed to render patched file");
close $ofh or fail("failed to render patched file");
' "$@"
}
replace_once() {
target=$1
search_file=$2
@@ -111,6 +172,17 @@ replace_once() {
hunk_id=$4
[ -e "$target" ] || die "file not found: $target"
fast_out=$(mk_temp)
if replace_once_with_perl "$target" "$search_file" "$replace_file" "$hunk_id" "$allow_loose" "$fast_out"; then
write_file "$target" "$fast_out"
rm -f "$fast_out"
return 0
else
status=$?
fi
rm -f "$fast_out"
[ "$status" = 127 ] || exit "$status"
marker="__UNIDESK_APPLY_PATCH_EOF_$$__"
old=$(cat "$target"; printf '%s' "$marker") || die "failed to read $target"
old=${"$"}{old%"$marker"}
@@ -707,11 +779,11 @@ export function parseSshArgs(args: string[]): ParsedSshArgs {
const subcommand = args[0] ?? "";
if (isSshSkillDiscoveryArgs(args)) {
const toolArgs = subcommand === "skill" ? ["skill-discover", ...args.slice(2)] : ["skill-discover", ...args.slice(1)];
return { remoteCommand: shellArgv(toolArgs), requiresStdin: false, invocationKind: "helper" };
return { remoteCommand: shellArgv(toolArgs), requiresStdin: false, invocationKind: "helper", requiredHelpers: ["skill-discover"] };
}
if (subcommand === "apply-patch" || subcommand === "patch") {
const toolArgs = ["apply_patch", ...args.slice(1)];
return { remoteCommand: shellArgv(toolArgs), requiresStdin: true, invocationKind: "helper" };
return { remoteCommand: shellArgv(toolArgs), requiresStdin: true, invocationKind: "helper", requiredHelpers: ["apply_patch"] };
}
if (subcommand === "py") {
return { remoteCommand: buildPythonStdinCommand(args.slice(1)), requiresStdin: true, invocationKind: "helper" };
@@ -728,7 +800,7 @@ export function parseSshArgs(args: string[]): ParsedSshArgs {
return { remoteCommand: buildFindCommand(args.slice(1)), requiresStdin: false, invocationKind: "helper" };
}
if (subcommand === "glob") {
return { remoteCommand: shellArgv(["glob", ...args.slice(1)]), requiresStdin: false, invocationKind: "helper" };
return { remoteCommand: shellArgv(["glob", ...args.slice(1)]), requiresStdin: false, invocationKind: "helper", requiredHelpers: ["glob"] };
}
if (subcommand === "k3s") {
throw new Error("ssh k3s shorthand is unsupported; put k3s in the route, for example: ssh D601:k3s kubectl get nodes");
@@ -1412,27 +1484,34 @@ function buildPythonStdinCommand(args: string[]): string {
].join("; ");
}
function remoteToolBootstrapCommand(): string {
const encodedApplyPatch = Buffer.from(remoteApplyPatchSource, "utf8").toString("base64");
const encodedGlob = Buffer.from(remoteGlobSource, "utf8").toString("base64");
const encodedSkillDiscover = Buffer.from(remoteSkillDiscoverSource, "utf8").toString("base64");
return [
const remoteToolSources: Record<SshHelperName, string> = {
apply_patch: remoteApplyPatchSource,
glob: remoteGlobSource,
"skill-discover": remoteSkillDiscoverSource,
};
function remoteToolBootstrapCommand(helpers: readonly SshHelperName[] = []): string {
const uniqueHelpers = [...new Set(helpers)];
if (uniqueHelpers.length === 0) return "";
const commands = [
"UNIDESK_SSH_TOOL_DIR=/tmp/unidesk-ssh-tools",
'mkdir -p "$UNIDESK_SSH_TOOL_DIR"',
`printf %s ${shellQuote(encodedApplyPatch)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/apply_patch"`,
`printf %s ${shellQuote(encodedGlob)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/glob"`,
`printf %s ${shellQuote(encodedSkillDiscover)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/skill-discover"`,
'chmod 700 "$UNIDESK_SSH_TOOL_DIR/apply_patch"',
'chmod 700 "$UNIDESK_SSH_TOOL_DIR/glob"',
'chmod 700 "$UNIDESK_SSH_TOOL_DIR/skill-discover"',
'export PATH="$UNIDESK_SSH_TOOL_DIR:$PATH"',
].join("; ");
];
for (const helper of uniqueHelpers) {
const source = remoteToolSources[helper];
const encoded = Buffer.from(source, "utf8").toString("base64");
commands.push(`printf %s ${shellQuote(encoded)} | base64 -d > "$UNIDESK_SSH_TOOL_DIR/${helper}"`);
commands.push(`chmod 700 "$UNIDESK_SSH_TOOL_DIR/${helper}"`);
}
commands.push('export PATH="$UNIDESK_SSH_TOOL_DIR:$PATH"');
return commands.join("; ");
}
export function wrapSshRemoteCommand(command: string | null): string {
const bootstrap = remoteToolBootstrapCommand();
if (command === null) return `${bootstrap}; exec "\${SHELL:-/bin/bash}" -l`;
return `${bootstrap}; stty -echo 2>/dev/null || true; ${command}`;
export function wrapSshRemoteCommand(command: string | null, helpers: readonly SshHelperName[] = []): string {
const bootstrap = remoteToolBootstrapCommand(helpers);
const prefix = bootstrap.length > 0 ? `${bootstrap}; ` : "";
if (command === null) return `${prefix}exec "\${SHELL:-/bin/bash}" -l`;
return `${prefix}stty -echo 2>/dev/null || true; ${command}`;
}
function safeProviderId(providerId: string): string {
@@ -1615,7 +1694,7 @@ export async function runSsh(config: UniDeskConfig, providerId: string, args: st
const openTimeoutMs = Math.max(15000, Number(process.env.UNIDESK_SSH_OPEN_TIMEOUT_MS || 60000));
const payload = {
providerId: invocation.providerId,
command: wrapSshRemoteCommand(parsed.remoteCommand),
command: wrapSshRemoteCommand(parsed.remoteCommand, parsed.requiredHelpers),
cwd: invocation.route.plane === "host" ? invocation.route.workspace ?? undefined : undefined,
tty: parsed.remoteCommand === null,
stdinEotOnEnd: parsed.remoteCommand !== null,
+9 -1
View File
@@ -126,6 +126,8 @@ export function runSshArgvGuidanceContract(): JsonRecord {
const hostApplyPatchLoose = parseSshArgs(["apply-patch", "--allow-loose"]);
assertCondition(hostApplyPatchLoose.remoteCommand === "'apply_patch' '--allow-loose'", "host apply-patch must pass --allow-loose as an explicit helper argument", hostApplyPatchLoose);
assertCondition(hostApplyPatchLoose.requiredHelpers?.length === 1 && hostApplyPatchLoose.requiredHelpers.includes("apply_patch"), "host apply-patch must request only the apply_patch helper bootstrap", hostApplyPatchLoose);
assertCondition(remoteApplyPatchSource.includes("replace_once_with_perl") && remoteApplyPatchSource.includes("perl -0777"), "apply_patch helper must keep a fast path for large files", {});
const safePatch = applyPatchFixture([], [
"*** Begin Patch",
@@ -287,7 +289,11 @@ export function runSshArgvGuidanceContract(): JsonRecord {
assertCondition(frontendRemoteK3sPlan.transport === "frontend-websocket", "remote frontend ssh must use the streaming websocket bridge", frontendRemoteK3sPlan);
assertCondition(frontendRemoteK3sPlan.providerId === "D601", "remote frontend ssh must dispatch route target to the provider id", frontendRemoteK3sPlan);
assertCondition(frontendRemoteK3sPlan.remoteCommand === "'env' 'KUBECONFIG=/etc/rancher/k3s/k3s.yaml' 'kubectl' 'get' 'nodes' '-o' 'name'", "remote frontend ssh must preserve k3s route command construction", frontendRemoteK3sPlan);
assertCondition(String(frontendRemoteK3sPlan.wrappedRemoteCommand ?? "").includes("UNIDESK_SSH_TOOL_DIR=/tmp/unidesk-ssh-tools"), "remote frontend ssh must use the same remote tool bootstrap as local ssh", frontendRemoteK3sPlan);
assertCondition(!String(frontendRemoteK3sPlan.wrappedRemoteCommand ?? "").includes("UNIDESK_SSH_TOOL_DIR=/tmp/unidesk-ssh-tools"), "remote frontend ssh must not bootstrap helper tools for plain kubectl argv", frontendRemoteK3sPlan);
const frontendRemoteHostPatchPlan = remoteSshFrontendPlanForTest("D601", ["apply-patch"]);
assertCondition(String(frontendRemoteHostPatchPlan.wrappedRemoteCommand ?? "").includes("UNIDESK_SSH_TOOL_DIR=/tmp/unidesk-ssh-tools"), "host apply-patch must bootstrap the remote apply_patch helper", frontendRemoteHostPatchPlan);
assertCondition(String(frontendRemoteHostPatchPlan.wrappedRemoteCommand ?? "").includes("/apply_patch") && !String(frontendRemoteHostPatchPlan.wrappedRemoteCommand ?? "").includes("/glob") && !String(frontendRemoteHostPatchPlan.wrappedRemoteCommand ?? "").includes("/skill-discover"), "host apply-patch must not bootstrap unrelated helper tools", frontendRemoteHostPatchPlan);
const frontendRemotePodArgvPlan = remoteSshFrontendPlanForTest("G14:k3s:unidesk:code-queue", ["argv", "sh", "-c", "command -v tran"]);
assertCondition(frontendRemotePodArgvPlan.providerId === "G14", "remote frontend pod route must dispatch through G14 provider", frontendRemotePodArgvPlan);
@@ -336,6 +342,8 @@ export function runSshArgvGuidanceContract(): JsonRecord {
"help text documents stdin script passthrough and UNIDESK_SSH_HINT",
"provider triage recommendedCrossChecks keeps ssh D601 argv true",
"remote frontend ssh uses the same structured route parser for host, k3s and pod argv routes",
"ssh helper bootstrap is lazy so plain argv/script commands do not transfer helper sources",
"host apply-patch bootstraps only the apply_patch helper and uses a Perl fast path for large files",
"remote frontend ssh uses authenticated /ws/ssh streaming instead of host.ssh dispatch task polling",
"Code Queue runner image installs the tran wrapper and runner tran auto-selects remote frontend transport",
"Code Queue runner remote frontend HTTP uses curl by default for non-ssh API calls to avoid Bun response-body native crashes",