import { AsyncLocalStorage } from "node:async_hooks"; import type { GatewayRequestContext, GatewayRequestOptions, } from "../../gateway/server-methods/types.js"; import { resolveGlobalSingleton } from "../../shared/global-singleton.js"; export type PluginRuntimeGatewayRequestScope = { context?: GatewayRequestContext; client?: GatewayRequestOptions["client"]; isWebchatConnect: GatewayRequestOptions["isWebchatConnect"]; pluginId?: string; }; const PLUGIN_RUNTIME_GATEWAY_REQUEST_SCOPE_KEY: unique symbol = Symbol.for( "openclaw.pluginRuntimeGatewayRequestScope", ); const pluginRuntimeGatewayRequestScope = resolveGlobalSingleton< AsyncLocalStorage >( PLUGIN_RUNTIME_GATEWAY_REQUEST_SCOPE_KEY, () => new AsyncLocalStorage(), ); /** * Runs plugin gateway handlers with request-scoped context that runtime helpers can read. */ export function withPluginRuntimeGatewayRequestScope( scope: PluginRuntimeGatewayRequestScope, run: () => T, ): T { return pluginRuntimeGatewayRequestScope.run(scope, run); } /** * Runs work under the current gateway request scope while attaching plugin identity. */ export function withPluginRuntimePluginIdScope(pluginId: string, run: () => T): T { const current = pluginRuntimeGatewayRequestScope.getStore(); const scoped: PluginRuntimeGatewayRequestScope = current ? { ...current, pluginId } : { pluginId, isWebchatConnect: () => false, }; return pluginRuntimeGatewayRequestScope.run(scoped, run); } /** * Returns the current plugin gateway request scope when called from a plugin request handler. */ export function getPluginRuntimeGatewayRequestScope(): | PluginRuntimeGatewayRequestScope | undefined { return pluginRuntimeGatewayRequestScope.getStore(); }