fix: filter codex subthreads during auto import

This commit is contained in:
kris
2026-03-30 14:25:25 +08:00
parent 03ac40f427
commit 40861c63da
7 changed files with 145 additions and 6 deletions

View File

@@ -5455,6 +5455,7 @@ export async function upsertDeviceHeartbeat(payload: {
deviceId: payload.deviceId,
appliedBy: "system:auto_sync",
draftId: autoSyncDraft.draftId,
pruneMissingCandidates: true,
});
draft = applied.draft;
}
@@ -5824,12 +5825,50 @@ function buildImportedThreadProject(device: Device, candidate: DeviceImportCandi
});
}
function candidateThreadSignature(candidate: DeviceImportCandidate) {
return (
trimToDefined(candidate.codexThreadRef) ??
trimToDefined(candidate.threadId) ??
`${candidate.folderName}:${candidate.threadDisplayName}`
);
}
function projectThreadSignature(project: Project) {
return (
trimToDefined(project.threadMeta.codexThreadRef) ??
trimToDefined(project.threadMeta.threadId) ??
`${project.threadMeta.folderName}:${project.threadMeta.threadDisplayName}`
);
}
function pruneStaleAutoImportedProjectsForDevice(
state: BossState,
device: Device,
selectedCandidates: DeviceImportCandidate[],
) {
const activeSignatures = new Set(selectedCandidates.map((candidate) => candidateThreadSignature(candidate)));
const reservedProjectIds = new Set(["master-agent", "boss-console", "audit-collab"]);
state.projects = state.projects.filter((project) => {
if (reservedProjectIds.has(project.id)) return true;
if (project.isGroup) return true;
if (!project.createdByAgent) return true;
if (!project.deviceIds.includes(device.id)) return true;
if (project.deviceIds.length !== 1) return true;
if (!trimToDefined(project.threadMeta.codexFolderRef) && !trimToDefined(project.threadMeta.folderName)) {
return true;
}
return activeSignatures.has(projectThreadSignature(project));
});
}
function applyDeviceImportResolutionInState(
state: BossState,
input: {
deviceId: string;
appliedBy: string;
draftId?: string;
pruneMissingCandidates?: boolean;
},
) {
const draft =
@@ -5844,6 +5883,9 @@ function applyDeviceImportResolutionInState(
const device = state.devices.find((item) => item.id === input.deviceId);
if (!device) throw new Error("DEVICE_NOT_FOUND");
const selectedCandidates = draft.candidates.filter((candidate) =>
draft.selectedCandidateIds.includes(candidate.candidateId),
);
const importedProjects: Project[] = [];
for (const item of resolution.items) {
const candidate = draft.candidates.find((entry) => entry.candidateId === item.candidateId);
@@ -5890,10 +5932,12 @@ function applyDeviceImportResolutionInState(
importedProjects.push({ ...targetProject });
}
if (input.pruneMissingCandidates) {
pruneStaleAutoImportedProjectsForDevice(state, device, selectedCandidates);
}
device.projects = dedupeStrings(
draft.candidates
.filter((candidate) => draft.selectedCandidateIds.includes(candidate.candidateId))
.map((candidate) => candidate.folderName),
selectedCandidates.map((candidate) => candidate.folderName),
);
resolution.status = "applied";