import { resolvePluginInteractiveNamespaceMatch } from "./interactive-registry.js"; import { claimPluginInteractiveCallbackDedupe, commitPluginInteractiveCallbackDedupe, releasePluginInteractiveCallbackDedupe, type RegisteredInteractiveHandler, } from "./interactive-state.js"; type InteractiveDispatchResult = | { matched: false; handled: false; duplicate: false } | { matched: true; handled: boolean; duplicate: boolean; result?: TResult }; type PluginInteractiveDispatchRegistration = { channel: string; namespace: string; }; export type PluginInteractiveMatch = { registration: RegisteredInteractiveHandler & TRegistration; namespace: string; payload: string; }; export { clearPluginInteractiveHandlers, clearPluginInteractiveHandlersForPlugin, registerPluginInteractiveHandler, } from "./interactive-registry.js"; export type { InteractiveRegistrationResult } from "./interactive-registry.js"; export async function dispatchPluginInteractiveHandler< TRegistration extends PluginInteractiveDispatchRegistration, TResult extends { handled?: boolean } | void = { handled?: boolean } | void, >(params: { channel: TRegistration["channel"]; data: string; dedupeId?: string; onMatched?: () => Promise | void; invoke: (match: PluginInteractiveMatch) => Promise | TResult; }): Promise> { const match = resolvePluginInteractiveNamespaceMatch(params.channel, params.data); if (!match) { return { matched: false, handled: false, duplicate: false }; } const dedupeKey = params.dedupeId?.trim(); if (dedupeKey && !claimPluginInteractiveCallbackDedupe(dedupeKey)) { return { matched: true, handled: true, duplicate: true }; } try { await params.onMatched?.(); const resolved = await params.invoke(match as PluginInteractiveMatch); if (dedupeKey) { commitPluginInteractiveCallbackDedupe(dedupeKey); } const shouldExposeResult = !!resolved && typeof resolved === "object" && Object.keys(resolved as Record).some((key) => key !== "handled"); return { matched: true, handled: resolved?.handled ?? true, duplicate: false, ...(shouldExposeResult ? { result: resolved } : {}), }; } catch (error) { if (dedupeKey) { releasePluginInteractiveCallbackDedupe(dedupeKey); } throw error; } }