fix: 收敛 trans 远端文本短路径

This commit is contained in:
Codex
2026-07-13 05:20:27 +02:00
parent 18937da9db
commit c04983455e
16 changed files with 498 additions and 70 deletions
+21 -6
View File
@@ -168,11 +168,11 @@ export function isApplyPatchV2HelpArgs(args: string[] = []): boolean {
export function applyPatchV2HelpPayload() {
return {
ok: true,
command: "trans <route> apply-patch < patch.diff",
command: "trans <route> apply-patch <<'PATCH'",
summary: "Apply a standard apply_patch patch to a remote route with the local v2 line-based engine.",
usage: [
"trans G14:/root/hwlab/.worktree/task apply-patch < patch.diff",
"trans D601:/tmp apply-patch < patch.diff"
"trans G14:/root/hwlab/.worktree/task apply-patch <<'PATCH'",
"trans D601:/tmp apply-patch <<'PATCH'"
],
input: {
required: true,
@@ -201,7 +201,7 @@ export function applyPatchV2HelpPayload() {
"Add File has no @@ hunk marker: put content immediately after `*** Add File: <path>` and prefix every content line with +.",
"A blank line in Add File is a line containing only +.",
"Update File uses @@ or @@ context markers, followed by context lines starting with one extra space prefix and changed lines starting with - or +; for a column-0 source line `const x`, write ` const x`, and for a two-space-indented source line write three spaces total. Unified-diff line-range headers are accepted with hints for MiniMax compatibility.",
"Prefer `trans <route> apply-patch < /tmp/patch.diff` for long patches, Windows paths, or quoting-sensitive content.",
"Send the patch directly through a quoted `<<'PATCH'` heredoc so paths, quotes, `$`, and backticks reach apply-patch unchanged; do not create a temporary patch file.",
"If `failed to find expected lines` reports stale or oversized context for a block/function replacement, re-read the exact current block and retry with a smaller Update File hunk or split hunks around unique anchors.",
"MiniMax compatibility: stray @@ or unprefixed content inside Add File, unprefixed Update File context lines, and extra hunk/body lines after Delete File, are accepted with stderr hints.",
"MiniMax/MXCX concatenated patch compatibility: repeated nested Begin Patch / End Patch markers are accepted with stderr hints, but the CLI still uses only the v2 engine and never auto-falls back to apply-patch-v1."
@@ -233,7 +233,7 @@ export function applyPatchV2HelpPayload() {
"Do not recover from apply-patch context mismatch by switching to download/upload, remote Python/Perl/sed, or whole-file rewrites; retry with corrected v2 hunks.",
"Do not use remote Python/Perl/sed heredocs for text patches when `trans <route> apply-patch` is available."
],
note: "apply-patch reads patch text from stdin and uses the v2 engine by default. Use `apply-patch-v1` only for the legacy helper."
note: "apply-patch reads patch text directly from stdin and uses the v2 engine by default. Use `apply-patch-v1` only for the legacy helper."
};
}
@@ -373,9 +373,13 @@ export async function runApplyPatchV2(options: ApplyPatchV2Options): Promise<num
stderr.write("ssh apply-patch uses the v2 engine and accepts no helper flags. Use apply-patch-v1 for legacy helper options.\n");
return 2;
}
if ((options.stdin as Readable & { isTTY?: boolean }).isTTY === true) {
stderr.write(`${applyPatchV2StdinHint("interactive-tty-without-stdin")}\n`);
return 2;
}
const patchText = await readStreamText(options.stdin);
if (!patchText.trim()) {
stderr.write("ssh apply-patch requires patch text on stdin.\n");
stderr.write(`${applyPatchV2StdinHint("empty-stdin")}\n`);
return 2;
}
const startedAtMs = Date.now();
@@ -416,6 +420,17 @@ export async function runApplyPatchV2(options: ApplyPatchV2Options): Promise<num
}
}
function applyPatchV2StdinHint(reason: "interactive-tty-without-stdin" | "empty-stdin"): string {
return `UNIDESK_APPLY_PATCH_INPUT ${JSON.stringify({
code: "apply-patch-stdin-required",
reason,
message: "apply-patch requires patch text from stdin and will not wait on an interactive TTY.",
try: "trans <route> apply-patch <<'PATCH'",
envelope: [beginMarker, "*** Update File: <path>", "@@", "-old", "+new", endMarker, "PATCH"],
temporaryFileRequired: false,
})}`;
}
function createApplyPatchV2RemoteMetrics(): ApplyPatchV2RemoteMetrics {
return { remoteOperationCount: 0, remoteOperationCounts: {}, remoteElapsedMs: 0, remoteFailureCount: 0 };
}