Files
openclaw/src/plugins/interactive-registry.ts
2026-04-07 13:01:23 +01:00

73 lines
2.3 KiB
TypeScript

import { normalizeOptionalLowercaseString } from "../shared/string-coerce.js";
import {
normalizePluginInteractiveNamespace,
resolvePluginInteractiveMatch,
toPluginInteractiveRegistryKey,
validatePluginInteractiveNamespace,
} from "./interactive-shared.js";
import {
clearPluginInteractiveHandlersState,
getPluginInteractiveHandlersState,
type RegisteredInteractiveHandler,
} from "./interactive-state.js";
import type { PluginInteractiveHandlerRegistration } from "./types.js";
export type InteractiveRegistrationResult = {
ok: boolean;
error?: string;
};
export function resolvePluginInteractiveNamespaceMatch(
channel: string,
data: string,
): { registration: RegisteredInteractiveHandler; namespace: string; payload: string } | null {
return resolvePluginInteractiveMatch({
interactiveHandlers: getPluginInteractiveHandlersState(),
channel,
data,
});
}
export function registerPluginInteractiveHandler(
pluginId: string,
registration: PluginInteractiveHandlerRegistration,
opts?: { pluginName?: string; pluginRoot?: string },
): InteractiveRegistrationResult {
const interactiveHandlers = getPluginInteractiveHandlersState();
const namespace = normalizePluginInteractiveNamespace(registration.namespace);
const validationError = validatePluginInteractiveNamespace(namespace);
if (validationError) {
return { ok: false, error: validationError };
}
const key = toPluginInteractiveRegistryKey(registration.channel, namespace);
const existing = interactiveHandlers.get(key);
if (existing) {
return {
ok: false,
error: `Interactive handler namespace "${namespace}" already registered by plugin "${existing.pluginId}"`,
};
}
interactiveHandlers.set(key, {
...registration,
namespace,
channel: normalizeOptionalLowercaseString(registration.channel) ?? "",
pluginId,
pluginName: opts?.pluginName,
pluginRoot: opts?.pluginRoot,
});
return { ok: true };
}
export function clearPluginInteractiveHandlers(): void {
clearPluginInteractiveHandlersState();
}
export function clearPluginInteractiveHandlersForPlugin(pluginId: string): void {
const interactiveHandlers = getPluginInteractiveHandlersState();
for (const [key, value] of interactiveHandlers.entries()) {
if (value.pluginId === pluginId) {
interactiveHandlers.delete(key);
}
}
}