mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-15 07:04:01 -06:00
8b0735e89f
* refactor(memory): remove qmd backend Make builtin the sole memory-core engine, rename the retained session helper barrel, retire QMD config with doctor migrations, and remove QMD runtime/UI/policy surfaces. * docs(memory): remove qmd backend guidance Delete the QMD concept page, rewrite memory documentation for builtin retrieval, and remove QMD from navigation and taxonomy source. * refactor(memory): remove qmd-only leftovers * refactor(memory): finish qmd integration cleanup * build(deps): align root string-width types * build(deps): model root string-width tooling * refactor(memory): align qmd removal ui and docs * fix(memory): preserve qmd external paths in doctor * test(memory): remove obsolete backend probe case * test(plugin-sdk): refresh private type baseline
121 lines
4.3 KiB
TypeScript
121 lines
4.3 KiB
TypeScript
/**
|
|
* Doctor migration contract for Active Memory state. It moves legacy per-session
|
|
* toggle JSON into the plugin state keyed store used by current runtimes.
|
|
*/
|
|
import crypto from "node:crypto";
|
|
import path from "node:path";
|
|
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
|
|
import {
|
|
asObjectRecord,
|
|
defineLegacyJsonStateMigration,
|
|
type PluginDoctorStateMigration,
|
|
} from "openclaw/plugin-sdk/runtime-doctor-migrations";
|
|
|
|
type ActiveMemoryToggleEntry = {
|
|
sessionKey: string;
|
|
disabled: boolean;
|
|
updatedAt: number;
|
|
};
|
|
|
|
const TOGGLE_STATE_FILE = "session-toggles.json";
|
|
const SESSION_TOGGLES_NAMESPACE = "session-toggles";
|
|
const MAX_TOGGLE_ENTRIES = 10_000;
|
|
const RETIRED_QMD_CONFIG_PATH = ["plugins", "entries", "active-memory", "config", "qmd"];
|
|
|
|
/** Retired Active Memory QMD override detected before strict manifest validation. */
|
|
export const legacyConfigRules = [
|
|
{
|
|
path: RETIRED_QMD_CONFIG_PATH,
|
|
message:
|
|
'plugins.entries.active-memory.config.qmd is retired because the QMD memory backend was removed. Run "openclaw doctor --fix".',
|
|
},
|
|
];
|
|
|
|
/** Removes the retired plugin-owned QMD override. */
|
|
export function normalizeCompatibilityConfig({ cfg }: { cfg: OpenClawConfig }): {
|
|
config: OpenClawConfig;
|
|
changes: string[];
|
|
} {
|
|
const entry = asObjectRecord(cfg.plugins?.entries?.["active-memory"]);
|
|
const pluginConfig = asObjectRecord(entry?.config);
|
|
if (!pluginConfig || !Object.hasOwn(pluginConfig, "qmd")) {
|
|
return { config: cfg, changes: [] };
|
|
}
|
|
|
|
const nextConfig = structuredClone(cfg);
|
|
const nextEntry = asObjectRecord(nextConfig.plugins?.entries?.["active-memory"]);
|
|
const nextPluginConfig = asObjectRecord(nextEntry?.config);
|
|
if (!nextPluginConfig) {
|
|
return { config: cfg, changes: [] };
|
|
}
|
|
delete nextPluginConfig.qmd;
|
|
return {
|
|
config: nextConfig,
|
|
changes: ["Removed retired Active Memory QMD search-mode configuration."],
|
|
};
|
|
}
|
|
|
|
function resolveToggleStatePath(stateDir: string): string {
|
|
return path.join(stateDir, "plugins", "active-memory", TOGGLE_STATE_FILE);
|
|
}
|
|
|
|
function activeMemoryToggleKey(sessionKey: string): string {
|
|
return crypto.createHash("sha256").update(sessionKey, "utf8").digest("hex");
|
|
}
|
|
|
|
function normalizeLegacyUpdatedAt(value: unknown): number {
|
|
return typeof value === "number" && Number.isFinite(value) ? value : Date.now();
|
|
}
|
|
|
|
function parseLegacyToggleEntries(parsed: unknown): ActiveMemoryToggleEntry[] | null {
|
|
if (!parsed || typeof parsed !== "object") {
|
|
return null;
|
|
}
|
|
const sessions = (parsed as { sessions?: unknown }).sessions;
|
|
if (!sessions || typeof sessions !== "object" || Array.isArray(sessions)) {
|
|
return null;
|
|
}
|
|
const entries: ActiveMemoryToggleEntry[] = [];
|
|
for (const [sessionKey, value] of Object.entries(sessions)) {
|
|
if (!sessionKey.trim() || !value || typeof value !== "object" || Array.isArray(value)) {
|
|
continue;
|
|
}
|
|
if ((value as { disabled?: unknown }).disabled !== true) {
|
|
continue;
|
|
}
|
|
const updatedAt = normalizeLegacyUpdatedAt((value as { updatedAt?: unknown }).updatedAt);
|
|
entries.push({ sessionKey, disabled: true, updatedAt });
|
|
}
|
|
return entries;
|
|
}
|
|
|
|
/** State migrations exposed to OpenClaw doctor for Active Memory. */
|
|
export const stateMigrations: PluginDoctorStateMigration[] = [
|
|
defineLegacyJsonStateMigration<ActiveMemoryToggleEntry[]>({
|
|
id: "active-memory-session-toggles-json-to-plugin-state",
|
|
label: "Active Memory session toggles",
|
|
resolvePath: resolveToggleStatePath,
|
|
parse: parseLegacyToggleEntries,
|
|
namespace: SESSION_TOGGLES_NAMESPACE,
|
|
maxEntries: MAX_TOGGLE_ENTRIES,
|
|
capacityPrecheck: {
|
|
warning: ({ available, missing }) =>
|
|
`Skipped Active Memory session toggle migration because plugin state has room for ${available} of ${missing} missing entries; left legacy source in place`,
|
|
},
|
|
describeEntries: (entries) => ({
|
|
preview: [
|
|
`- Active Memory session toggles: ${entries.length} ${entries.length === 1 ? "entry" : "entries"} -> plugin state (${SESSION_TOGGLES_NAMESPACE})`,
|
|
],
|
|
change: ({ imported }) =>
|
|
imported > 0
|
|
? `Migrated ${imported} Active Memory session toggle ${imported === 1 ? "entry" : "entries"} -> plugin state`
|
|
: null,
|
|
}),
|
|
toRows: (entries) =>
|
|
entries.map((entry) => ({
|
|
key: activeMemoryToggleKey(entry.sessionKey),
|
|
value: entry,
|
|
})),
|
|
}),
|
|
];
|