Files
openclaw/src/plugins/plugin-registration-transaction.ts

137 lines
4.9 KiB
TypeScript

// Owns atomic plugin registration state across registry and process-global capabilities.
import {
listRegisteredAgentHarnesses,
restoreRegisteredAgentHarnesses,
} from "../agents/harness/registry.js";
import {
getDetachedTaskLifecycleRuntimeRegistration,
restoreDetachedTaskLifecycleRuntimeRegistration,
} from "../tasks/detached-task-runtime-state.js";
import { listRegisteredPluginCommands, restorePluginCommands } from "./command-registry-state.js";
import {
listRegisteredCompactionProviders,
restoreRegisteredCompactionProviders,
} from "./compaction-provider.js";
import {
listRegisteredEmbeddingProviders,
restoreRegisteredEmbeddingProviders,
} from "./embedding-providers.js";
import {
listPluginInteractiveHandlers,
restorePluginInteractiveHandlers,
} from "./interactive-registry.js";
import {
listRegisteredMemoryEmbeddingProviders,
restoreRegisteredMemoryEmbeddingProviders,
} from "./memory-embedding-providers.js";
import {
getMemoryCapabilityRegistration,
listMemoryCorpusSupplements,
listMemoryPromptSupplements,
restoreMemoryPluginState,
} from "./memory-state.js";
import type { PluginRegistry } from "./registry-types.js";
export type PluginProcessGlobalState = {
agentHarnesses: ReturnType<typeof listRegisteredAgentHarnesses>;
commands: ReturnType<typeof listRegisteredPluginCommands>;
compactionProviders: ReturnType<typeof listRegisteredCompactionProviders>;
detachedTaskRuntimeRegistration: ReturnType<typeof getDetachedTaskLifecycleRuntimeRegistration>;
embeddingProviders: ReturnType<typeof listRegisteredEmbeddingProviders>;
interactiveHandlers: ReturnType<typeof listPluginInteractiveHandlers>;
memoryCapability: ReturnType<typeof getMemoryCapabilityRegistration>;
memoryCorpusSupplements: ReturnType<typeof listMemoryCorpusSupplements>;
memoryEmbeddingProviders: ReturnType<typeof listRegisteredMemoryEmbeddingProviders>;
memoryPromptSupplements: ReturnType<typeof listMemoryPromptSupplements>;
};
export function snapshotPluginProcessGlobalState(): PluginProcessGlobalState {
return {
agentHarnesses: listRegisteredAgentHarnesses(),
commands: listRegisteredPluginCommands(),
compactionProviders: listRegisteredCompactionProviders(),
detachedTaskRuntimeRegistration: getDetachedTaskLifecycleRuntimeRegistration(),
embeddingProviders: listRegisteredEmbeddingProviders(),
interactiveHandlers: listPluginInteractiveHandlers(),
memoryCapability: getMemoryCapabilityRegistration(),
memoryCorpusSupplements: listMemoryCorpusSupplements(),
memoryEmbeddingProviders: listRegisteredMemoryEmbeddingProviders(),
memoryPromptSupplements: listMemoryPromptSupplements(),
};
}
export function restorePluginProcessGlobalState(state: PluginProcessGlobalState): void {
restoreRegisteredAgentHarnesses(state.agentHarnesses);
restorePluginCommands(state.commands);
restoreRegisteredCompactionProviders(state.compactionProviders);
restoreDetachedTaskLifecycleRuntimeRegistration(state.detachedTaskRuntimeRegistration);
restoreRegisteredEmbeddingProviders(state.embeddingProviders);
restorePluginInteractiveHandlers(state.interactiveHandlers);
restoreRegisteredMemoryEmbeddingProviders(state.memoryEmbeddingProviders);
restoreMemoryPluginState({
capability: state.memoryCapability,
corpusSupplements: state.memoryCorpusSupplements,
promptSupplements: state.memoryPromptSupplements,
});
}
function snapshotPluginRegistry(registry: PluginRegistry): PluginRegistry {
return Object.fromEntries(
Object.entries(registry).map(([key, value]) => {
if (Array.isArray(value)) {
return [key, [...value]];
}
if (value instanceof Map) {
return [key, new Map(value)];
}
if (value && typeof value === "object") {
return [key, { ...value }];
}
return [key, value];
}),
) as PluginRegistry;
}
function restorePluginRegistry(registry: PluginRegistry, snapshot: PluginRegistry): void {
Object.assign(registry, snapshot);
}
export type PluginRegistrationTransaction = {
commit: (params: { activate: boolean }) => void;
rollback: () => void;
};
export function createPluginRegistrationTransaction(params: {
registry: PluginRegistry;
rollbackGlobalSideEffects?: () => void;
}): PluginRegistrationTransaction {
const registrySnapshot = snapshotPluginRegistry(params.registry);
const processGlobalState = snapshotPluginProcessGlobalState();
let settled = false;
const settle = (action: () => void): void => {
if (settled) {
return;
}
action();
settled = true;
};
return {
commit: ({ activate }) => {
settle(() => {
if (!activate) {
restorePluginProcessGlobalState(processGlobalState);
}
});
},
rollback: () => {
settle(() => {
params.rollbackGlobalSideEffects?.();
restorePluginRegistry(params.registry, registrySnapshot);
restorePluginProcessGlobalState(processGlobalState);
});
},
};
}