mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-24 08:21:18 +00:00
* feat(control-ui): import coding assistant memory * test(migrate): clean memory import temp dirs * chore: move memory import note to PR body * build: refresh memory import generated artifacts * fix(control-ui): complete memory import checks * build(control-ui): localize memory recovery labels * fix(control-ui): harden memory import recovery * refactor(migrate): keep memory import surfaces bounded * fix(control-ui): use canonical agent row type * fix(codex): drop dead migration type exports * fix(migrate): restrict imported memory permissions * fix(control-ui): preserve memory import recovery state * fix(control-ui): retain memory import results * build(control-ui): preserve translation memory history * fix(control-ui): bind memory import state to agent * fix(control-ui): unlock memory import after refresh * test(gateway): preserve memory method suffix * fix(migrate): bind reviewed memory imports * fix(migrate): make memory imports retry-safe * perf(ui): keep memory import lazy * build: refresh generated artifacts after rebase * chore: keep migration runtime within LOC guard * build: refresh Swift protocol model
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
import crypto from "node:crypto";
|
|
import { readRegularFile } from "../infra/fs-safe.js";
|
|
import type { MigrationItem, MigrationPlan } from "../plugins/types.js";
|
|
|
|
export const MAX_MEMORY_MIGRATION_FILE_BYTES = 64 * 1024 * 1024;
|
|
|
|
/** Bind copyable memory items to the exact source bytes reviewed by an embedded migration UI. */
|
|
export async function bindMemoryMigrationPlanSources(
|
|
plan: MigrationPlan,
|
|
opts: { includeConflicts?: boolean } = {},
|
|
): Promise<MigrationPlan> {
|
|
const items: MigrationItem[] = [];
|
|
for (const item of plan.items) {
|
|
if (
|
|
item.kind !== "memory" ||
|
|
item.action !== "copy" ||
|
|
(item.status !== "planned" && !(opts.includeConflicts && item.status === "conflict")) ||
|
|
!item.source
|
|
) {
|
|
items.push(item);
|
|
continue;
|
|
}
|
|
const { buffer } = await readRegularFile({
|
|
filePath: item.source,
|
|
maxBytes: MAX_MEMORY_MIGRATION_FILE_BYTES,
|
|
});
|
|
items.push({
|
|
...item,
|
|
sourceRevision: {
|
|
algorithm: "sha256",
|
|
digest: crypto.createHash("sha256").update(buffer).digest("hex"),
|
|
},
|
|
});
|
|
}
|
|
return { ...plan, items };
|
|
}
|
|
|
|
/** Reject source bytes that differ from an embedded migration's reviewed plan. */
|
|
export function assertMemoryMigrationSourceRevision(
|
|
item: MigrationItem,
|
|
sourceBuffer: Buffer,
|
|
): void {
|
|
const expectedSourceSha256 = item.sourceRevision?.digest;
|
|
if (
|
|
item.sourceRevision?.algorithm === "sha256" &&
|
|
typeof expectedSourceSha256 === "string" &&
|
|
crypto.createHash("sha256").update(sourceBuffer).digest("hex") !== expectedSourceSha256
|
|
) {
|
|
throw new Error("memory migration source changed; refresh the plan before importing");
|
|
}
|
|
}
|