Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
136 lines
3.2 KiB
TypeScript
136 lines
3.2 KiB
TypeScript
import { normalizeAgentPatchText } from "./agentPatchMetadata";
|
|
|
|
const UNIFIED_DIFF_HUNK_PATTERN =
|
|
/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(?:.*)$/;
|
|
|
|
export function isAgentUnifiedDiffText(value: string): boolean {
|
|
const normalized = normalizeAgentPatchText(value).replace(/\r/g, "\n").trim();
|
|
if (!normalized) {
|
|
return false;
|
|
}
|
|
|
|
const lines = normalized.split("\n");
|
|
const isApplyPatch =
|
|
normalized.includes("*** Begin Patch") &&
|
|
(normalized.includes("*** Add File:") ||
|
|
normalized.includes("*** Delete File:") ||
|
|
normalized.includes("*** Update File:"));
|
|
let hasHunk = false;
|
|
let hunkActive = false;
|
|
let hunkHasCounts = false;
|
|
let hunkHasChange = false;
|
|
let oldCount = 0;
|
|
let newCount = 0;
|
|
let expectedOld = 0;
|
|
let expectedNew = 0;
|
|
|
|
const finishHunk = (): boolean => {
|
|
if (!hunkActive) {
|
|
return true;
|
|
}
|
|
if (!hunkHasCounts) {
|
|
return isApplyPatch && hunkHasChange;
|
|
}
|
|
return (
|
|
oldCount === expectedOld && newCount === expectedNew && hunkHasChange
|
|
);
|
|
};
|
|
|
|
for (const line of lines) {
|
|
const hunkMatch = line.match(UNIFIED_DIFF_HUNK_PATTERN);
|
|
if (hunkMatch) {
|
|
if (!finishHunk()) {
|
|
return false;
|
|
}
|
|
hasHunk = true;
|
|
hunkActive = true;
|
|
hunkHasCounts = true;
|
|
hunkHasChange = false;
|
|
oldCount = 0;
|
|
newCount = 0;
|
|
expectedOld = hunkCount(hunkMatch[2]);
|
|
expectedNew = hunkCount(hunkMatch[4]);
|
|
continue;
|
|
}
|
|
|
|
if (line === "@@" && isApplyPatch) {
|
|
if (!finishHunk()) {
|
|
return false;
|
|
}
|
|
hasHunk = true;
|
|
hunkActive = true;
|
|
hunkHasCounts = false;
|
|
hunkHasChange = false;
|
|
continue;
|
|
}
|
|
|
|
if (hunkActive && line.startsWith("diff --git ")) {
|
|
if (!finishHunk()) {
|
|
return false;
|
|
}
|
|
hunkActive = false;
|
|
continue;
|
|
}
|
|
|
|
if (
|
|
!hunkActive &&
|
|
(line.startsWith("diff --git ") ||
|
|
line.startsWith("index ") ||
|
|
line.startsWith("--- ") ||
|
|
line.startsWith("+++ ") ||
|
|
line.startsWith("new file mode ") ||
|
|
line.startsWith("deleted file mode ") ||
|
|
line.startsWith("old mode ") ||
|
|
line.startsWith("new mode ") ||
|
|
line.startsWith("similarity index ") ||
|
|
line.startsWith("rename from ") ||
|
|
line.startsWith("rename to ") ||
|
|
line.startsWith("*** "))
|
|
) {
|
|
continue;
|
|
}
|
|
if (hunkActive && isApplyPatch && line.startsWith("*** ")) {
|
|
continue;
|
|
}
|
|
if (line === "\\ No newline at end of file") {
|
|
continue;
|
|
}
|
|
if (!hasHunk) {
|
|
continue;
|
|
}
|
|
|
|
if (!hunkHasCounts && isApplyPatch) {
|
|
if (line.startsWith("+") || line.startsWith("-")) {
|
|
hunkHasChange = true;
|
|
continue;
|
|
}
|
|
if (line.startsWith(" ")) {
|
|
continue;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (line.startsWith("+")) {
|
|
newCount += 1;
|
|
hunkHasChange = true;
|
|
} else if (line.startsWith("-")) {
|
|
oldCount += 1;
|
|
hunkHasChange = true;
|
|
} else if (line.startsWith(" ")) {
|
|
oldCount += 1;
|
|
newCount += 1;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return hasHunk && finishHunk();
|
|
}
|
|
|
|
function hunkCount(value: string | undefined): number {
|
|
if (!value) {
|
|
return 1;
|
|
}
|
|
return Number.parseInt(value, 10);
|
|
}
|