openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
195 lines (194 loc) • 10.1 kB
JavaScript
import { a as resolveGlobalSingleton } from "./global-singleton-0m-JziJW.mjs";
import { c as getPluginCache, m as getProcessPluginCache, n as PluginCacheFactInvalidatedError, u as getPluginCacheRetirementSignal, y as preparePluginCacheFact } from "./plugin-cache-CfBhQFSN.mjs";
import { c as isRecord } from "./record-coerce-TIsquoVR.mjs";
import { n as isArtifactPreservingStateRead } from "./artifact-preserving-state-reads-BQnQLAJR.mjs";
import { c as resolveOpenClawStateSqlitePath } from "./openclaw-state-db.paths-CmKkMYdo.mjs";
import { a as isStateDatabaseReadAdmissionInvalidatedError } from "./openclaw-state-db-async-lifecycle-DwFy2ZTk.mjs";
import { n as getActiveOpenClawStateDatabaseReadSnapshot } from "./openclaw-state-db-readonly-ywwvuxdQ.mjs";
import { r as captureOpenClawStateWorkerContext } from "./openclaw-state-worker-context-BvvgY6-t.mjs";
import { n as readConfigMachineState } from "./config-machine-state-BAsvqrtu.mjs";
import { r as resolveActivePluginInstallRoots, t as hasActivePluginInstallRoots } from "./install-root-context-BJfgtQE2.mjs";
import { n as registerPluginMetadataProcessMemoLifecycleClear } from "./plugin-metadata-lifecycle-COmFOHdR.mjs";
import { n as readPluginMetadataStateRowSync, r as readPluginMetadataStateRowsSync } from "./installed-plugin-index-row-CvqFVPqV.mjs";
//#region src/plugins/plugin-metadata-state-worker.ts
async function readPluginMetadataState(selection, options, artifactPreservingReadOnly, decode) {
const preserveArtifacts = artifactPreservingReadOnly || isArtifactPreservingStateRead();
try {
const context = captureOpenClawStateWorkerContext(options);
try {
if (preserveArtifacts && getActiveOpenClawStateDatabaseReadSnapshot(options)) {
context.admission.assertCurrent();
return decode("stateKeys" in selection ? readPluginMetadataStateRowsSync(selection.stateKeys, options, true) : readPluginMetadataStateRowSync(selection.selector, options, true));
}
const { runOpenClawStateWorkerOperation } = await import("./openclaw-state-worker-store-x5r3Lkjl.mjs");
context.admission.assertCurrent();
const result = await runOpenClawStateWorkerOperation(context, async (scope) => {
return decode(await scope.execute({
type: "plugins.metadata.read",
input: {
...selection,
artifactPreservingReadOnly: preserveArtifacts
}
}));
}, { existingOnly: true });
return result === void 0 ? decode(void 0) : result;
} finally {
context.admission.assertCurrent();
}
} catch (error) {
if (isStateDatabaseReadAdmissionInvalidatedError(error)) throw new PluginCacheFactInvalidatedError("Plugin metadata read admission changed during preparation; retry the operation.", { cause: error });
throw error;
}
}
/** Read raw metadata from retained snapshot bytes or the shared inspection actor. */
function readPluginMetadataStateRow(selector, options, artifactPreservingReadOnly = false) {
return readPluginMetadataState({ selector }, options, artifactPreservingReadOnly, (row) => {
if (row === void 0) return;
if (!isRecord(row) || typeof row.value_json !== "string") throw new Error("Shared-state worker returned an invalid plugin metadata row");
return { value_json: row.value_json };
});
}
/** Policy and inventory preparation share one worker request and SQLite snapshot. */
function readPluginMetadataStateRows(stateKeys, options, artifactPreservingReadOnly = false) {
return readPluginMetadataState({ stateKeys }, options, artifactPreservingReadOnly, (rows) => {
if (rows === void 0) return [];
if (!Array.isArray(rows)) throw new Error("Shared-state worker returned invalid plugin metadata rows");
return rows.map((row) => {
if (!isRecord(row) || typeof row.state_key !== "string" || typeof row.value_json !== "string") throw new Error("Shared-state worker returned an invalid plugin metadata row");
return {
state_key: row.state_key,
value_json: row.value_json
};
});
});
}
//#endregion
//#region src/plugins/bundled-discovery-state.ts
function parseBundledDiscoveryMode(value) {
return value === "compat" || value === "allowlist" ? value : void 0;
}
function readBundledDiscoveryFact(read) {
try {
return read();
} catch (error) {
if (isStateDatabaseReadAdmissionInvalidatedError(error)) throw new PluginCacheFactInvalidatedError("Plugin discovery read admission changed during preparation; retry the operation.", { cause: error });
throw error;
}
}
function resolveBundledDiscoveryOptions(options) {
return options.path || options.database || !hasActivePluginInstallRoots() ? options : {
...options,
env: {
...options.env ?? process.env,
OPENCLAW_STATE_DIR: resolveActivePluginInstallRoots(options.env).stateDir
}
};
}
function readBundledDiscoveryMode(options = {}, behavior = {}) {
const resolvedOptions = resolveBundledDiscoveryOptions(options);
return parseBundledDiscoveryMode(readBundledDiscoveryFact(() => readConfigMachineState("plugins.bundledDiscovery", resolvedOptions, behavior)));
}
const discoveryState = resolveGlobalSingleton(Symbol.for("openclaw.bundledDiscoveryMode"), () => ({
generation: {},
snapshotModes: /* @__PURE__ */ new WeakMap()
}));
registerPluginMetadataProcessMemoLifecycleClear(() => {
clearBundledDiscoveryModeMemo();
});
function resolveBundledDiscoveryMemoKey(env) {
const scopedEnv = hasActivePluginInstallRoots() ? {
...env,
OPENCLAW_STATE_DIR: resolveActivePluginInstallRoots(env).stateDir
} : env;
return resolveOpenClawStateSqlitePath(scopedEnv);
}
/**
* Callers loading a registry with an explicit env pass it so the mode comes
* from that env's state root; omitting it reads the process root. Pinned
* install roots win over both, matching readBundledDiscoveryMode.
*/
function readBundledDiscoveryModeMemoized(env = process.env, behavior = {}, readPreparedValue) {
const options = env === process.env ? {} : { env };
const snapshot = behavior.artifactPreservingReadOnly || isArtifactPreservingStateRead() ? readBundledDiscoveryFact(() => getActiveOpenClawStateDatabaseReadSnapshot(resolveBundledDiscoveryOptions(options))) : void 0;
if (snapshot || behavior.artifactPreservingReadOnly) {
const prepared = snapshot && discoveryState.snapshotModes.get(snapshot);
if (prepared) return prepared.value;
const value = readBundledDiscoveryMode(options, behavior);
if (snapshot) discoveryState.snapshotModes.set(snapshot, { value });
return value;
}
const key = resolveBundledDiscoveryMemoKey(env);
if (discoveryState.memoized?.key !== key) {
const owner = getPluginCache();
const prepared = owner.preparedBundledDiscoveryModes.get(key);
if (prepared && "value" in prepared && prepared.value.generation === discoveryState.generation) {
getPluginCacheRetirementSignal(owner).throwIfAborted();
discoveryState.memoized = {
key,
value: prepared.value.value
};
} else discoveryState.memoized = {
key,
value: readPreparedValue ? parseBundledDiscoveryMode(readBundledDiscoveryFact(() => readPreparedValue(key))) : readBundledDiscoveryMode(env === process.env ? {} : { env })
};
}
return discoveryState.memoized.value;
}
/** Prepare the same machine-owned fact for synchronous metadata derivation. */
async function prepareBundledDiscoveryMode(env = process.env, readPreparedRow) {
const owner = getPluginCache();
const options = resolveBundledDiscoveryOptions({ env });
const snapshot = isArtifactPreservingStateRead() ? readBundledDiscoveryFact(() => getActiveOpenClawStateDatabaseReadSnapshot(options)) : void 0;
if (snapshot) {
const metadata = owner.metadata;
const generation = discoveryState.generation;
const signal = getPluginCacheRetirementSignal(owner);
const assertCurrent = () => {
signal.throwIfAborted();
if (owner.metadata !== metadata || discoveryState.generation !== generation || readBundledDiscoveryFact(() => getActiveOpenClawStateDatabaseReadSnapshot(options)) !== snapshot) throw new PluginCacheFactInvalidatedError("Plugin discovery snapshot changed during preparation; retry the operation.");
};
assertCurrent();
return assertCurrent;
}
const cache = owner.preparedBundledDiscoveryModes;
const key = resolveBundledDiscoveryMemoKey(env);
const generation = discoveryState.generation;
const current = cache.get(key);
if (current && "value" in current && current.value.generation !== generation) cache.delete(key);
const prepared = await preparePluginCacheFact(owner, cache, key, async () => {
let value;
if (discoveryState.memoized?.key === key) value = discoveryState.memoized.value;
else {
const row = readPreparedRow ? await readPreparedRow(key) : await readPluginMetadataStateRow("bundled-discovery", resolveBundledDiscoveryOptions({ env }));
value = parseBundledDiscoveryMode(row ? JSON.parse(row.value_json) : void 0);
}
if (discoveryState.generation !== generation) throw new PluginCacheFactInvalidatedError("Plugin discovery state changed during preparation; retry the operation.");
return {
value,
generation
};
});
const activate = () => {
prepared.assertCurrent();
if (discoveryState.generation !== generation) throw new PluginCacheFactInvalidatedError("Plugin discovery state changed during preparation; retry the operation.");
discoveryState.memoized = {
key,
value: prepared.value.value
};
};
activate();
return activate;
}
/**
* Clears the memo after a machine-state write so same-process readers observe
* the new mode. Without this, doctor's migration could cache the pre-migration
* absent mode and rebuild plugin indexes against stale strict-gate decisions.
*/
function clearBundledDiscoveryModeMemo() {
discoveryState.memoized = void 0;
discoveryState.snapshotModes = /* @__PURE__ */ new WeakMap();
discoveryState.generation = {};
for (const cache of /* @__PURE__ */ new Set([getPluginCache(), getProcessPluginCache()])) cache.preparedBundledDiscoveryModes.clear();
}
//#endregion
export { readPluginMetadataStateRow as a, readBundledDiscoveryModeMemoized as i, prepareBundledDiscoveryMode as n, readPluginMetadataStateRows as o, readBundledDiscoveryMode as r, clearBundledDiscoveryModeMemo as t };