Files
agent-radar 2ed3415fb7
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
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

136 lines
3.8 KiB
TypeScript

import { formatWorkspaceFilePathForDisplay } from "@tutti-os/workspace-file-manager/services";
import type {
AgentTurnSummaryFileVM,
AgentTurnSummaryPatchChangeVM
} from "../contracts/agentTurnSummaryRowVM";
import { normalizeWorkspaceFilePath } from "../../../actions/workspaceFilePathCandidate";
export function fileCanBuildPatch(file: AgentTurnSummaryFileVM): boolean {
if (file.unifiedDiff != null) {
return true;
}
if (file.changeType === "created") {
return file.content != null || file.newString != null;
}
if (file.changeType === "deleted") {
return file.oldString != null || file.content != null;
}
return file.oldString != null && file.newString != null;
}
export function patchBatchDirectoryCwd(
cwd: string | null,
changes: readonly Pick<AgentTurnSummaryPatchChangeVM, "path">[],
workspaceRoot?: string | null
): string | null {
const normalizedCwd = normalizePatchHostPath(cwd ?? "", workspaceRoot);
if (!normalizedCwd) {
return null;
}
const cwdIsChangedFilePath = changes.some(
(change) =>
normalizePatchHostPath(change.path, workspaceRoot) === normalizedCwd
);
return cwdIsChangedFilePath
? dirnameForPatchHostPath(normalizedCwd)
: normalizedCwd;
}
export function resolvePatchExecutionCwd(
cwd: string | null,
workspaceRoot?: string | null
): string | null {
const normalizedRoot = normalizePatchHostPath(
workspaceRoot ?? "",
workspaceRoot
);
const normalizedCwd = normalizePatchHostPath(cwd ?? "", normalizedRoot);
if (!normalizedCwd) {
return normalizedRoot || null;
}
if (!normalizedRoot) {
return normalizedCwd;
}
if (isSyntheticWorkspacePath(normalizedRoot)) {
return normalizedCwd;
}
if (normalizedCwd === "/workspace") {
return normalizedRoot;
}
if (normalizedCwd.startsWith("/workspace/")) {
return `${normalizedRoot}/${normalizedCwd.slice("/workspace/".length)}`;
}
return normalizedCwd;
}
export function resolvePatchDiffCwd({
sourceCwd,
executionCwd,
changes
}: {
sourceCwd: string | null;
executionCwd: string | null;
changes: readonly Pick<AgentTurnSummaryPatchChangeVM, "path">[];
}): string | null {
const normalizedSourceCwd = normalizePatchHostPath(sourceCwd ?? "");
const normalizedExecutionCwd = normalizePatchHostPath(executionCwd ?? "");
if (
!isSyntheticWorkspacePath(normalizedSourceCwd) ||
!normalizedExecutionCwd
) {
return sourceCwd;
}
const hasSyntheticChangePath = changes.some((change) =>
isInsideOrEqualPatchPath(
normalizePatchHostPath(change.path),
normalizedSourceCwd
)
);
const hasHostChangePath = changes.some((change) =>
isInsideOrEqualPatchPath(
normalizePatchHostPath(change.path),
normalizedExecutionCwd
)
);
return hasHostChangePath && !hasSyntheticChangePath
? normalizedExecutionCwd
: sourceCwd;
}
function normalizePatchHostPath(
path: string,
workspaceRoot?: string | null
): string {
const trimmed = path.trim();
if (!trimmed) {
return "";
}
const normalized = normalizeWorkspaceFilePath(trimmed, workspaceRoot);
if (/^\/?[A-Za-z]:\//.test(normalized)) {
return formatWorkspaceFilePathForDisplay(normalized, "win32")
.replaceAll("\\", "/")
.replace(/\/+$/, "");
}
return normalized.replace(/\/+$/, "");
}
function dirnameForPatchHostPath(path: string): string {
const normalized = normalizePatchHostPath(path);
const index = normalized.lastIndexOf("/");
if (index < 0) {
return "";
}
if (index === 0) {
return "/";
}
return normalized.slice(0, index);
}
function isSyntheticWorkspacePath(path: string): boolean {
return path === "/workspace" || path.startsWith("/workspace/");
}
function isInsideOrEqualPatchPath(path: string, root: string): boolean {
return path === root || path.startsWith(`${root}/`);
}