openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
156 lines (155 loc) • 6.89 kB
JavaScript
import { t as loadInstalledPluginIndexInstallRecords } from "./installed-plugin-index-record-reader-CPHayOZI.js";
import { o as withoutPluginInstallRecords, s as writePersistedInstalledPluginIndexInstallRecords, t as PLUGIN_INSTALLS_CONFIG_PATH } from "./installed-plugin-index-records-DXbAzXDd.js";
import { m as resolveConfigWriteAfterWrite } from "./runtime-snapshot-D93_HOsR.js";
import { i as replaceConfigFile, o as transformConfigFileWithRetry } from "./config-C9RxTsn1.js";
import { isDeepStrictEqual } from "node:util";
//#region src/cli/plugins-install-record-commit.ts
function mergeUnsetPaths(left, right) {
const merged = [...left ?? [], ...right ?? []];
return merged.length > 0 ? merged : void 0;
}
/** Return whether config still contains legacy/transient plugin install records. */
function hasPendingPluginInstallRecords(config) {
return Object.keys(config.plugins?.installs ?? {}).length > 0;
}
/** Find pending install records that match the base config and can be stripped as unchanged. */
function unchangedPendingPluginInstallRecordIds(config, baseConfig) {
const pendingInstalls = config.plugins?.installs ?? {};
return Object.entries(baseConfig.plugins?.installs ?? {}).filter(([pluginId, baseInstall]) => isDeepStrictEqual(pendingInstalls[pluginId], baseInstall)).map(([pluginId]) => pluginId);
}
/** Remove pending plugin install records from config, optionally only for selected ids. */
function stripPendingPluginInstallRecords(config, pluginIds) {
if (!pluginIds) return withoutPluginInstallRecords(config);
const removeIds = new Set(pluginIds);
if (removeIds.size === 0 || !config.plugins?.installs) return config;
const remainingInstalls = Object.fromEntries(Object.entries(config.plugins.installs).filter(([pluginId]) => !removeIds.has(pluginId)));
if (Object.keys(remainingInstalls).length === 0) return withoutPluginInstallRecords(config);
return {
...config,
plugins: {
...config.plugins,
installs: remainingInstalls
}
};
}
const PLUGIN_SOURCE_CHANGED_RESTART_REASON = "plugin source changed";
function mergeAfterWrite(writeOptions, afterWrite) {
if (afterWrite === void 0) return writeOptions;
return {
...writeOptions,
afterWrite
};
}
async function commitPluginInstallRecordsWithWriter(params) {
const previousInstallRecords = params.previousInstallRecords ?? await loadInstalledPluginIndexInstallRecords();
await writePersistedInstalledPluginIndexInstallRecords(params.nextInstallRecords);
try {
const installRecordsChanged = !isDeepStrictEqual(previousInstallRecords, params.nextInstallRecords);
return await params.commit(params.nextConfig, {
...params.writeOptions,
...installRecordsChanged && params.writeOptions?.afterWrite === void 0 ? { afterWrite: {
mode: "restart",
reason: PLUGIN_SOURCE_CHANGED_RESTART_REASON
} } : {},
unsetPaths: mergeUnsetPaths(params.writeOptions?.unsetPaths, [Array.from(PLUGIN_INSTALLS_CONFIG_PATH)])
});
} catch (error) {
try {
await writePersistedInstalledPluginIndexInstallRecords(previousInstallRecords);
} catch (rollbackError) {
throw new Error("Failed to commit plugin install records and could not restore the previous plugin index", { cause: rollbackError });
}
throw error;
}
}
/** Persist plugin install records and commit the matching config update to disk. */
async function commitPluginInstallRecordsWithConfig(params) {
await commitPluginInstallRecordsWithWriter({
...params,
commit: async (nextConfig, writeOptions) => {
return await replaceConfigFile({
nextConfig,
...params.baseHash !== void 0 ? { baseHash: params.baseHash } : {},
...writeOptions ? { writeOptions } : {}
});
}
});
}
/** Commit config while migrating any pending install records into the install index. */
async function commitConfigWriteWithPendingPluginInstalls(params) {
if (!hasPendingPluginInstallRecords(params.nextConfig)) {
const committed = params.writeOptions ? await params.commit(params.nextConfig, params.writeOptions) : await params.commit(params.nextConfig);
return {
config: params.nextConfig,
installRecords: {},
movedInstallRecords: false,
persistedHash: committed?.persistedHash ?? null
};
}
const pendingInstallRecords = params.nextConfig.plugins?.installs ?? {};
const previousInstallRecords = await loadInstalledPluginIndexInstallRecords();
const nextInstallRecords = {
...previousInstallRecords,
...pendingInstallRecords
};
const strippedConfig = withoutPluginInstallRecords(params.nextConfig);
return {
config: strippedConfig,
installRecords: nextInstallRecords,
movedInstallRecords: true,
persistedHash: (await commitPluginInstallRecordsWithWriter({
previousInstallRecords,
nextInstallRecords,
nextConfig: strippedConfig,
...params.writeOptions ? { writeOptions: params.writeOptions } : {},
commit: params.commit
}))?.persistedHash ?? null
};
}
/** Replace the config file after moving pending plugin install records into the install index. */
async function commitConfigWithPendingPluginInstalls(params) {
return await commitConfigWriteWithPendingPluginInstalls({
nextConfig: params.nextConfig,
...params.writeOptions ? { writeOptions: params.writeOptions } : {},
commit: async (nextConfig, writeOptions) => {
return await replaceConfigFile({
nextConfig,
...params.baseHash !== void 0 ? { baseHash: params.baseHash } : {},
...writeOptions ? { writeOptions } : {}
});
}
});
}
/** Transform config with retry support while preserving plugin install index consistency. */
async function transformConfigWithPendingPluginInstalls(params) {
const commit = async ({ nextConfig, snapshot, baseHash, writeOptions }) => {
const requestedAfterWrite = params.afterWrite ?? params.writeOptions?.afterWrite;
const committed = await commitConfigWriteWithPendingPluginInstalls({
nextConfig,
...writeOptions ? { writeOptions: mergeAfterWrite(writeOptions, params.afterWrite) } : {},
commit: async (config, commitWriteOptions) => {
return await replaceConfigFile({
nextConfig: config,
snapshot,
writeOptions: commitWriteOptions ?? {},
...baseHash !== void 0 ? { baseHash } : {}
});
}
});
const afterWrite = resolveConfigWriteAfterWrite(requestedAfterWrite ?? (committed.movedInstallRecords ? {
mode: "restart",
reason: PLUGIN_SOURCE_CHANGED_RESTART_REASON
} : void 0));
return {
config: committed.config,
persistedHash: committed.persistedHash,
afterWrite
};
};
return await transformConfigFileWithRetry({
...params,
commit
});
}
//#endregion
export { stripPendingPluginInstallRecords as a, hasPendingPluginInstallRecords as i, commitConfigWriteWithPendingPluginInstalls as n, transformConfigWithPendingPluginInstalls as o, commitPluginInstallRecordsWithConfig as r, unchangedPendingPluginInstallRecordIds as s, commitConfigWithPendingPluginInstalls as t };