mirror of
https://github.com/luckyyzh/pi-agent-integrated.git
synced 2026-10-03 11:09:34 +00:00
feat: integrate Pi backend and Pi Web
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
export type SplitDiffCellType = "context" | "removed" | "added" | "empty";
|
||||
|
||||
export interface SplitDiffCell {
|
||||
lineNo: number | null;
|
||||
text: string;
|
||||
type: SplitDiffCellType;
|
||||
}
|
||||
|
||||
export type SplitDiffRow =
|
||||
| { type: "hunk"; text: string }
|
||||
| { type: "line"; left: SplitDiffCell; right: SplitDiffCell };
|
||||
|
||||
export interface SplitDiffFile {
|
||||
oldPath?: string;
|
||||
newPath?: string;
|
||||
rows: SplitDiffRow[];
|
||||
}
|
||||
|
||||
interface PendingChangeLine {
|
||||
lineNo: number;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export function parseUnifiedPatch(text: string): SplitDiffFile[] | null {
|
||||
const files: SplitDiffFile[] = [];
|
||||
let current: SplitDiffFile | null = null;
|
||||
let pendingOldPath: string | undefined;
|
||||
let oldLineNo = 0;
|
||||
let newLineNo = 0;
|
||||
let removed: PendingChangeLine[] = [];
|
||||
let added: PendingChangeLine[] = [];
|
||||
|
||||
const emptyCell = (): SplitDiffCell => ({ lineNo: null, text: "", type: "empty" });
|
||||
const flushChanges = () => {
|
||||
if (!current) {
|
||||
removed = [];
|
||||
added = [];
|
||||
return;
|
||||
}
|
||||
const count = Math.max(removed.length, added.length);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const left = removed[i]
|
||||
? { lineNo: removed[i].lineNo, text: removed[i].text, type: "removed" as const }
|
||||
: emptyCell();
|
||||
const right = added[i]
|
||||
? { lineNo: added[i].lineNo, text: added[i].text, type: "added" as const }
|
||||
: emptyCell();
|
||||
current.rows.push({ type: "line", left, right });
|
||||
}
|
||||
removed = [];
|
||||
added = [];
|
||||
};
|
||||
|
||||
for (const line of text.split(/\r?\n/)) {
|
||||
if (line.startsWith("--- ")) {
|
||||
flushChanges();
|
||||
pendingOldPath = cleanPatchPath(line.slice(4));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith("+++ ")) {
|
||||
flushChanges();
|
||||
current = { oldPath: pendingOldPath, newPath: cleanPatchPath(line.slice(4)), rows: [] };
|
||||
files.push(current);
|
||||
continue;
|
||||
}
|
||||
|
||||
const hunk = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
|
||||
if (hunk) {
|
||||
if (!current) {
|
||||
current = { rows: [] };
|
||||
files.push(current);
|
||||
}
|
||||
flushChanges();
|
||||
oldLineNo = Number(hunk[1]);
|
||||
newLineNo = Number(hunk[2]);
|
||||
current.rows.push({ type: "hunk", text: line });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!current) continue;
|
||||
|
||||
if (line.startsWith("\\ ")) {
|
||||
flushChanges();
|
||||
current.rows.push({ type: "hunk", text: line });
|
||||
continue;
|
||||
}
|
||||
|
||||
const prefix = line[0];
|
||||
const content = line.slice(1);
|
||||
|
||||
if (prefix === " ") {
|
||||
flushChanges();
|
||||
current.rows.push({
|
||||
type: "line",
|
||||
left: { lineNo: oldLineNo++, text: content, type: "context" },
|
||||
right: { lineNo: newLineNo++, text: content, type: "context" },
|
||||
});
|
||||
} else if (prefix === "-") {
|
||||
removed.push({ lineNo: oldLineNo++, text: content });
|
||||
} else if (prefix === "+") {
|
||||
added.push({ lineNo: newLineNo++, text: content });
|
||||
} else if (line !== "") {
|
||||
flushChanges();
|
||||
current.rows.push({ type: "hunk", text: line });
|
||||
}
|
||||
}
|
||||
|
||||
flushChanges();
|
||||
|
||||
const parsed = files.filter((file) => file.rows.some((row) => row.type === "line"));
|
||||
return parsed.length > 0 ? parsed : null;
|
||||
}
|
||||
|
||||
function cleanPatchPath(path: string): string {
|
||||
return path.split("\t")[0].trim();
|
||||
}
|
||||
Reference in New Issue
Block a user