import { createDedupeCache, resolveGlobalDedupeCache } from "../infra/dedupe.js"; import { resolveGlobalSingleton } from "../shared/global-singleton.js"; import type { PluginInteractiveHandlerRegistration } from "./types.js"; export type RegisteredInteractiveHandler = PluginInteractiveHandlerRegistration & { pluginId: string; pluginName?: string; pluginRoot?: string; }; type InteractiveState = { interactiveHandlers: Map; callbackDedupe: ReturnType; inflightCallbackDedupe: Set; }; const PLUGIN_INTERACTIVE_STATE_KEY = Symbol.for("openclaw.pluginInteractiveState"); function getState() { return resolveGlobalSingleton(PLUGIN_INTERACTIVE_STATE_KEY, () => ({ interactiveHandlers: new Map(), callbackDedupe: resolveGlobalDedupeCache( Symbol.for("openclaw.pluginInteractiveCallbackDedupe"), { ttlMs: 5 * 60_000, maxSize: 4096, }, ), inflightCallbackDedupe: new Set(), })); } export function getPluginInteractiveHandlersState() { return getState().interactiveHandlers; } export function getPluginInteractiveCallbackDedupeState() { return getState().callbackDedupe; } export function claimPluginInteractiveCallbackDedupe( dedupeKey: string | undefined, now = Date.now(), ): boolean { if (!dedupeKey) { return true; } const state = getState(); if (state.inflightCallbackDedupe.has(dedupeKey) || state.callbackDedupe.peek(dedupeKey, now)) { return false; } state.inflightCallbackDedupe.add(dedupeKey); return true; } export function commitPluginInteractiveCallbackDedupe( dedupeKey: string | undefined, now = Date.now(), ): void { if (!dedupeKey) { return; } const state = getState(); state.inflightCallbackDedupe.delete(dedupeKey); state.callbackDedupe.check(dedupeKey, now); } export function releasePluginInteractiveCallbackDedupe(dedupeKey: string | undefined): void { if (!dedupeKey) { return; } getState().inflightCallbackDedupe.delete(dedupeKey); } export function clearPluginInteractiveHandlersState(): void { getPluginInteractiveHandlersState().clear(); getPluginInteractiveCallbackDedupeState().clear(); getState().inflightCallbackDedupe.clear(); }