File size: 2,289 Bytes
d197cf3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import { isDeepStrictEqual } from "node:util";
import type { ClawRemoveApplyOptions } from "./lifecycle-remove-contract.js";
import type { ClawPackageRemovalPhaseResult } from "./package-remove-contract.js";
import {
filterReferencedCleanup,
digestClawPackageRemovalPlan,
digestClawRemovalInstall,
orderClawPackageRemovals,
normalizeClawPackageCleanup,
} from "./package-remove-plan.js";
import { applyClawPackageRemovals, type ClawPackageRemovalDecision } from "./package-remove.js";
import { readClawInstallRecord } from "./provenance.js";
export async function applyClawPackageRemovalPhase(
decisions: ClawPackageRemovalDecision[],
options: ClawRemoveApplyOptions & {
agentId: string;
operationId: string;
assertCurrent: () => void;
},
): Promise<ClawPackageRemovalPhaseResult> {
const ordered = orderClawPackageRemovals(decisions);
options.assertCurrent();
const cleanup = normalizeClawPackageCleanup(
filterReferencedCleanup(options.referencedCleanup, "package"),
);
if (
!ordered.some(
(decision) => decision.packageRef.kind === "plugin" && decision.action === "uninstall",
)
) {
return await applyClawPackageRemovals(ordered, { ...options, deps: options.packageDeps });
}
if (!options.packageGateway) {
throw new Error("Plugin cleanup requires the serving Gateway package owner.");
}
// Hand off before taking either cross-process package mutation lease.
const removed = await options.packageGateway({
agentId: options.agentId,
operationId: options.operationId,
expectedInstallDigest: digestClawRemovalInstall(
readClawInstallRecord(options.agentId, options),
),
expectedPackagePlanDigest: digestClawPackageRemovalPlan(ordered, cleanup),
cleanup,
});
options.assertCurrent();
const expected = ordered.map(({ packageRef }) => [
packageRef.kind,
packageRef.ref,
packageRef.version,
]);
const actual = removed.packages.map((pkg) => [pkg.kind, pkg.ref, pkg.version]);
if (
!isDeepStrictEqual(expected, actual) ||
(removed.packages.some((pkg) => pkg.kind === "plugin" && pkg.action === "uninstalled") &&
!removed.application)
) {
throw new Error("Gateway package cleanup returned incomplete removal outcomes.");
}
return removed;
}
|