mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-28 14:03:34 +00:00
112 lines
3.8 KiB
TypeScript
112 lines
3.8 KiB
TypeScript
// Runtime store exports expose plugin runtime type contracts without loading runtime code.
|
|
export type { PluginRuntime } from "../plugins/runtime/types.js";
|
|
|
|
const pluginRuntimeStoreRegistryKey = Symbol.for("openclaw.plugin-sdk.runtime-store-registry");
|
|
|
|
type PluginRuntimeStoreRegistry = Map<string, { runtime: unknown }>;
|
|
type PluginRuntimeStoreKeyOptions = {
|
|
/** Explicit global registry key for shared runtime slots. */
|
|
key: string;
|
|
/** Error thrown by getRuntime before setRuntime initializes this slot. */
|
|
errorMessage: string;
|
|
};
|
|
type PluginRuntimeStorePluginOptions = {
|
|
/** Plugin id used to derive a stable cross-module runtime slot key. */
|
|
pluginId: string;
|
|
/** Error thrown by getRuntime before setRuntime initializes this slot. */
|
|
errorMessage: string;
|
|
};
|
|
type PluginRuntimeStoreOptions = PluginRuntimeStoreKeyOptions | PluginRuntimeStorePluginOptions;
|
|
|
|
function getPluginRuntimeStoreRegistry(): PluginRuntimeStoreRegistry {
|
|
const globalRecord = globalThis as typeof globalThis & {
|
|
[pluginRuntimeStoreRegistryKey]?: PluginRuntimeStoreRegistry;
|
|
};
|
|
globalRecord[pluginRuntimeStoreRegistryKey] ??= new Map();
|
|
return globalRecord[pluginRuntimeStoreRegistryKey];
|
|
}
|
|
|
|
function pluginRuntimeStoreKeyForPluginId(pluginId: string): string {
|
|
const normalizedPluginId = pluginId.trim();
|
|
if (!normalizedPluginId) {
|
|
throw new Error("createPluginRuntimeStore: pluginId must not be empty");
|
|
}
|
|
return `plugin-runtime:${normalizedPluginId}`;
|
|
}
|
|
|
|
function resolvePluginRuntimeStoreOptions(
|
|
options: string | PluginRuntimeStoreOptions,
|
|
): PluginRuntimeStoreKeyOptions {
|
|
if (typeof options === "string") {
|
|
return { key: options, errorMessage: options };
|
|
}
|
|
if ("pluginId" in options) {
|
|
return {
|
|
key: pluginRuntimeStoreKeyForPluginId(options.pluginId),
|
|
errorMessage: options.errorMessage,
|
|
};
|
|
}
|
|
return options;
|
|
}
|
|
|
|
/**
|
|
* Create a process-local runtime slot that throws when accessed before initialization.
|
|
*
|
|
* String keys create isolated module-local stores; option objects create global
|
|
* named slots so duplicate SDK module instances share the same plugin runtime.
|
|
*/
|
|
export function createPluginRuntimeStore<T>(errorMessage: string): {
|
|
setRuntime: (next: T) => void;
|
|
clearRuntime: () => void;
|
|
tryGetRuntime: () => T | null;
|
|
getRuntime: () => T;
|
|
};
|
|
/** Create a globally shared runtime slot keyed by plugin id or explicit registry key. */
|
|
export function createPluginRuntimeStore<T>(options: PluginRuntimeStoreOptions): {
|
|
setRuntime: (next: T) => void;
|
|
clearRuntime: () => void;
|
|
tryGetRuntime: () => T | null;
|
|
getRuntime: () => T;
|
|
};
|
|
/** Implementation overload accepting either legacy error-message strings or structured options. */
|
|
export function createPluginRuntimeStore<T>(options: string | PluginRuntimeStoreOptions): {
|
|
setRuntime: (next: T) => void;
|
|
clearRuntime: () => void;
|
|
tryGetRuntime: () => T | null;
|
|
getRuntime: () => T;
|
|
} {
|
|
const resolved = resolvePluginRuntimeStoreOptions(options);
|
|
const slot =
|
|
typeof options === "string"
|
|
? { runtime: null }
|
|
: (() => {
|
|
// Store named slots on globalThis so duplicate SDK module instances
|
|
// still share one runtime for the same plugin id or explicit key.
|
|
const registry = getPluginRuntimeStoreRegistry();
|
|
let existingSlot = registry.get(resolved.key);
|
|
if (!existingSlot) {
|
|
existingSlot = { runtime: null };
|
|
registry.set(resolved.key, existingSlot);
|
|
}
|
|
return existingSlot;
|
|
})();
|
|
|
|
return {
|
|
setRuntime(next: T) {
|
|
slot.runtime = next;
|
|
},
|
|
clearRuntime() {
|
|
slot.runtime = null;
|
|
},
|
|
tryGetRuntime() {
|
|
return (slot.runtime as T | null) ?? null;
|
|
},
|
|
getRuntime() {
|
|
if (slot.runtime === null) {
|
|
throw new Error(resolved.errorMessage);
|
|
}
|
|
return slot.runtime as T;
|
|
},
|
|
};
|
|
}
|