From c39abcecdab7e4ec5cf83343ea0290867cf407cd Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 10 Aug 2026 15:34:37 -0700 Subject: [PATCH] fix(security): report DM isolation from effective routing (#121741) * fix(security): audit effective DM session ownership Resolve admitted DM principals through canonical route, account, identity-link, and channel-owned session policy before reporting shared-session risk. Doctor now renders the structured channel security owner instead of duplicating the global-only default-account heuristic.\n\nCloses #121711 * chore(plugin-sdk): refresh API contract baseline * fix(telegram): preserve direct peer SDK export * fix(telegram): preserve direct peer resolver signature * fix(ci): use supported DM audit grouping * fix(protocol): refresh approval reviewer Swift models --- docs/.generated/plugin-sdk-api-baseline.jsonl | 130 ++-- docs/plugins/sdk-channel-plugins.md | 13 + extensions/telegram/api.ts | 2 +- extensions/telegram/src/bot/helpers.test.ts | 15 - extensions/telegram/src/bot/helpers.ts | 20 - extensions/telegram/src/conversation-route.ts | 50 +- .../telegram/src/dm-session-key.test.ts | 68 +++ extensions/telegram/src/dm-session-key.ts | 77 +++ extensions/telegram/src/security.ts | 6 + extensions/zalouser/src/channel.adapters.ts | 4 + src/channels/message-access/dm-allow-state.ts | 19 +- src/channels/plugins/types.adapters.ts | 13 + src/commands/doctor-security.test.ts | 33 +- src/commands/doctor-security.ts | 117 +--- src/plugin-sdk/channel-policy.test.ts | 7 + src/plugin-sdk/channel-policy.ts | 2 + src/plugin-sdk/core.test.ts | 20 + src/plugin-sdk/core.ts | 2 + src/routing/resolve-route.test.ts | 78 +++ src/routing/resolve-route.ts | 21 + src/routing/session-key.ts | 5 +- src/security/audit-channel-dm-policy.test.ts | 572 +++++++++++++++--- src/security/audit-channel.ts | 240 +++++++- 23 files changed, 1133 insertions(+), 381 deletions(-) create mode 100644 extensions/telegram/src/dm-session-key.test.ts create mode 100644 extensions/telegram/src/dm-session-key.ts diff --git a/docs/.generated/plugin-sdk-api-baseline.jsonl b/docs/.generated/plugin-sdk-api-baseline.jsonl index 6a6076e0e4a7..38ae5cf34ba1 100644 --- a/docs/.generated/plugin-sdk-api-baseline.jsonl +++ b/docs/.generated/plugin-sdk-api-baseline.jsonl @@ -53,15 +53,15 @@ {"closureHash":"ff3c4616cd6212a6d698831a8b287ad87e3968c8663f4090d095bb30ec40fc1c","declaration":"export function abortAndDrainAgentHarnessRun(params: { sessionId: string; sessionKey?: string; settleMs?: number; forceClear?: boolean; reason?: string; }): Promise;","entrypoint":"agent-harness","exportName":"abortAndDrainAgentHarnessRun","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"58989e3fa91eecf2e05202e36548e6e64a3b9219e83154bd99866c851604e34e","declaration":"export function createAgentToolResultMiddlewareRunner(ctx: AgentToolResultMiddlewareContext, handlers?: AgentToolResultMiddleware[]): { applyToolResultMiddleware(event: AgentToolResultMiddlewareEvent): Promise; };","entrypoint":"agent-harness","exportName":"createAgentToolResultMiddlewareRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"b8f6355d7ad1700aceecddaa6e9ccf43091a792d5b481a1ee3f55294a881a67d","declaration":"export function createCodexAppServerToolResultExtensionRunner(ctx: CodexAppServerExtensionContext, factories?: CodexAppServerExtensionFactory[]): { applyToolResultExtensions(event: CodexAppServerToolResultEvent): Promise>; };","entrypoint":"agent-harness","exportName":"createCodexAppServerToolResultExtensionRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} -{"closureHash":"82a967232dd50d7c7a42d6a576722af500feba6c6170c808a3297ea36f6a9bec","declaration":"export function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];","entrypoint":"agent-harness","exportName":"createOpenClawCodingTools","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} +{"closureHash":"fd6548682cda2d069f1a9b6eef190102b4ebcadc20d485d5ee9d2cb6e4419011","declaration":"export function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];","entrypoint":"agent-harness","exportName":"createOpenClawCodingTools","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"13649ee853485319e7449fda25c106b3f3f53d3090e53cdbb28e220a8529eb80","declaration":"export function disposeRegisteredAgentHarnesses(): Promise;","entrypoint":"agent-harness","exportName":"disposeRegisteredAgentHarnesses","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"f255a91162ece4c239bb8fa745efa14a1054bc024a291e9954f75f239b2b87c3","declaration":"export function resolveActiveEmbeddedRunSessionId(sessionKey: string): string | undefined;","entrypoint":"agent-harness","exportName":"resolveActiveEmbeddedRunSessionId","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"27d9f61df9ccf68615cb2002a6da891e36ab0c07623bc37c4d07aa980b446881","declaration":"export function resolveWebSearchToolPolicy(params: WebSearchToolPolicyParams): WebSearchToolPolicyResolution;","entrypoint":"agent-harness","exportName":"resolveWebSearchToolPolicy","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} -{"closureHash":"e75e94d131237b4b73c507cad9f2a0940716404531516861497e92ba8d06fb87","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} +{"closureHash":"71e57b87ff6cba595cc4513f2fd68742eb69a234d17e328c6cc6761eec04385e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"4ad0f830bf11a2db48faefb1439b7fbb08d9f22d22083f5e301327e1696f2310","declaration":"export type AgentToolResultMiddleware = AgentToolResultMiddleware;","entrypoint":"agent-harness","exportName":"AgentToolResultMiddleware","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"008b6c78d5e44a9d1df1d7e32e6015382ee9ba1cb9b10bd4c2b467619d1c89d4","declaration":"export type AgentToolResultMiddlewareEvent = AgentToolResultMiddlewareEvent;","entrypoint":"agent-harness","exportName":"AgentToolResultMiddlewareEvent","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"7414a2a79c2d78c1d52538250c827305bba1a2bb25010448837c8524a9f95b3c","declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"agent-harness","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} -{"closureHash":"49c4aa50aa6a16de715caebb9215d233ab86bdc710b457b060c7de3857180b84","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} +{"closureHash":"f975d7a88a7e25914f7a255354a6c2f0ede9281ca793e47ed971450e358dfbb4","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"25c6985c3bef2c6efc6a96e70af6d66fe073be0b0d311681cfc0dfc186528d9a","declaration":"export type OpenClawAgentToolResult = OpenClawAgentToolResult;","entrypoint":"agent-harness","exportName":"OpenClawAgentToolResult","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"category":"runtime","entrypoint":"agent-harness-runtime","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","recordType":"module"} {"closureHash":"fab99dfcb01d475a1bfdbe7a8fac9be10a93dac5f12ac78c2dea673c8ab86abf","declaration":"export function abortAgentHarnessRun(sessionId: string): boolean;\nexport function abortAgentHarnessRun(sessionId: undefined, opts: { mode: \"all\" | \"compacting\"; reason?: \"restart\"; }): boolean;","entrypoint":"agent-harness-runtime","exportName":"abortAgentHarnessRun","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -80,8 +80,8 @@ {"closureHash":"593bc2b598c7715ab011aa6ab5659f02262f134b15f218b02921e1c7e33198ba","declaration":"export function buildAgentRuntimePlan(params: BuildAgentRuntimePlanParams): AgentRuntimePlan;","entrypoint":"agent-harness-runtime","exportName":"buildAgentRuntimePlan","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"528d11abf061b0b303722737de5a6406e7e55bffa38c45144c77d896ae1b3b0a","declaration":"export function buildBootstrapContextForFiles(bootstrapFiles: WorkspaceBootstrapFile[], params: { config?: OpenClawConfig; agentId?: string | null; warn?: (message: string) => void; }): EmbeddedContextFile[];","entrypoint":"agent-harness-runtime","exportName":"buildBootstrapContextForFiles","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"44d5a4667d2f3dc3a28e5c9d7b46765b1fb3c62820288e40251f5174911c8a6a","declaration":"export function buildEmbeddedAttemptToolRunContext(params: { trigger?: EmbeddedRunTrigger; jobId?: string; memoryFlushWritePath?: string; toolsAllow?: string[]; conversationToolPolicy?: GroupToolPolicyConfig; trace?: DiagnosticTraceContext; }): { trigger?: EmbeddedRunTrigger; jobId?: string; memoryFlushWritePath?: string; runtimeToolAllowlist?: string[]; conversationToolPolicy?: GroupToolPolicyConfig; trace?: DiagnosticTraceContext; };","entrypoint":"agent-harness-runtime","exportName":"buildEmbeddedAttemptToolRunContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"0044b5f2a53d7378e9e6f7e60303a99af22ba23d124cfdfbc3d87fe33a15b2a5","declaration":"export function buildHarnessContextEngineRuntimeContext(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"3c5037a93268c28d1d0c1855793cd448d7c40d535422e18245d30a61c12a5e02","declaration":"export function buildHarnessContextEngineRuntimeContextFromUsage(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContextFromUsage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"792093d47cf7874e3a30edca5a3f4e2e3b30237c99e4a567adab2ea74ebb9014","declaration":"export function buildHarnessContextEngineRuntimeContext(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"7371785d39b9e470e35b1cb3bfd4e64ab2a71562a4a4411057999b94eba5d812","declaration":"export function buildHarnessContextEngineRuntimeContextFromUsage(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContextFromUsage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"33a7cd8d63d4ef045ee3a42f806026a8b621e7dd32d8d6fbf4e7b44452d5e0ce","declaration":"export function buildNativeHookRelayCommand(params: { provider: NativeHookRelayProvider; relayId: string; generation?: string; event: NativeHookRelayEvent; preToolUseUnavailable?: \"noop\"; timeoutMs?: number; executable?: string; nice?: number | false; nodeExecutable?: string; }): string;","entrypoint":"agent-harness-runtime","exportName":"buildNativeHookRelayCommand","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"3846647c3c2fb0242f70591cf95c2e02f2a5a3c44447efb4cf7a31b2dc2122fd","declaration":"export function buildSkillWorkshopPromptSection(): string[];","entrypoint":"agent-harness-runtime","exportName":"buildSkillWorkshopPromptSection","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"32e977ece65144a83ae1b0a3c8d1b9b00a2a2506ad9ef1db3b2b9770ce762dbe","declaration":"export function buildWatchedSessionsHarnessContext(params: { config?: OpenClawConfig; sessionKey?: string; sandboxed?: boolean; toolNames: Iterable; capabilityToolNames?: Iterable; }): string | undefined;","entrypoint":"agent-harness-runtime","exportName":"buildWatchedSessionsHarnessContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -98,7 +98,7 @@ {"closureHash":"51f76e9e37b65b358f0313e10152d950b003bc3e50f4bb26fe29a988237772e2","declaration":"export function consumePreExecutionBlockedToolCall(toolCallId: string, runId?: string): boolean;","entrypoint":"agent-harness-runtime","exportName":"consumePreExecutionBlockedToolCall","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"58989e3fa91eecf2e05202e36548e6e64a3b9219e83154bd99866c851604e34e","declaration":"export function createAgentToolResultMiddlewareRunner(ctx: AgentToolResultMiddlewareContext, handlers?: AgentToolResultMiddleware[]): { applyToolResultMiddleware(event: AgentToolResultMiddlewareEvent): Promise; };","entrypoint":"agent-harness-runtime","exportName":"createAgentToolResultMiddlewareRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"b8f6355d7ad1700aceecddaa6e9ccf43091a792d5b481a1ee3f55294a881a67d","declaration":"export function createCodexAppServerToolResultExtensionRunner(ctx: CodexAppServerExtensionContext, factories?: CodexAppServerExtensionFactory[]): { applyToolResultExtensions(event: CodexAppServerToolResultEvent): Promise>; };","entrypoint":"agent-harness-runtime","exportName":"createCodexAppServerToolResultExtensionRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"ceb4f4b948da28b98ff86f7cedfba4e7f17135c7e1321f4b528d8749fa389132","declaration":"export function deliverAgentHarnessUserInputPrompt(params: PromptDeliveryParams, questions: readonly AgentHarnessUserInputQuestion[], options?: AgentHarnessUserInputPromptOptions): Promise;","entrypoint":"agent-harness-runtime","exportName":"deliverAgentHarnessUserInputPrompt","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"149e13ab601ed9304f695360d5ffa481e79d8d3a5cc163357d8a7e7a7e66a7d5","declaration":"export function deliverAgentHarnessUserInputPrompt(params: PromptDeliveryParams, questions: readonly AgentHarnessUserInputQuestion[], options?: AgentHarnessUserInputPromptOptions): Promise;","entrypoint":"agent-harness-runtime","exportName":"deliverAgentHarnessUserInputPrompt","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"6f436485257f69fa07a18203b91d4341690522f12aff4f25805c7a1e21326ee3","declaration":"export function detectAndLoadAgentHarnessPromptImages(params: { prompt: string; workspaceDir: string; model: { input?: string[]; }; existingImages?: ImageContent[]; imageOrder?: PromptImageOrderEntry[]; media?: MediaFact[]; config?: OpenClawConfig; workspaceOnly?: boolean; localRoots?: readonly string[]; sandbox?: { root: string; bridge: SandboxFsBridge; }; }): Promise<{ images: ImageContent[]; detectedRefs: Array<{ raw: string; resolved: string; type: \"path\" | \"media-uri\"; }>; loadedCount: number; skippedCount: number; }>;","entrypoint":"agent-harness-runtime","exportName":"detectAndLoadAgentHarnessPromptImages","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"13649ee853485319e7449fda25c106b3f3f53d3090e53cdbb28e220a8529eb80","declaration":"export function disposeRegisteredAgentHarnesses(): Promise;","entrypoint":"agent-harness-runtime","exportName":"disposeRegisteredAgentHarnesses","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"c38cd390190bb07ddcd247420d6e0b489a0229bd402ddca0440417217a57251a","declaration":"export function emitAgentEvent(event: Omit): void;","entrypoint":"agent-harness-runtime","exportName":"emitAgentEvent","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -195,7 +195,7 @@ {"closureHash":"e4784aeda4c24b60cd49b7f5983e70a380a4759d5176c74d30f2900952ba848f","declaration":"export function runAgentHarnessBeforeAgentFinalizeHook(params: { event: PluginHookBeforeAgentFinalizeEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessBeforeAgentFinalizeHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"8fec73ee8c7c9be3335bd6dc1bac9278f0be5beef22a5975eb06e56f504f4bd6","declaration":"export function runAgentHarnessBeforeCompactionHook(params: { sessionFile: string; messages?: AgentMessage[]; ctx: AgentHarnessHookContext; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessBeforeCompactionHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"021b81820bef2e8d54c50a5fc159d6665b23b50a1f5c40dae76a4833839d89c9","declaration":"export function runAgentHarnessBeforeMessageWriteHook(params: { message: AgentMessage; agentId?: string; sessionKey?: string; }): AgentMessage | null;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessBeforeMessageWriteHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"1707257505ae1574ce02a6fb3ea20bb59dbcad1d324e078d778d0407606d95de","declaration":"export function runAgentHarnessGatewayQuestion(params: RunAgentHarnessGatewayQuestionParams): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessGatewayQuestion","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"1265cab97fe0a20462087f4fd953b2e97e86fe99e0f2433edd1752e187132fd8","declaration":"export function runAgentHarnessGatewayQuestion(params: RunAgentHarnessGatewayQuestionParams): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessGatewayQuestion","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"50a4d7cb20dd8f884abbcb62d77b5b2df183fbfcd058cc7aa76edacd1f7b90d8","declaration":"export function runAgentHarnessLlmInputHook(params: { event: PluginHookLlmInputEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessLlmInputHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"1bd55c141c249b1c04470cafe0cd4d41dce334ea2883ce83235af56d24a15cca","declaration":"export function runAgentHarnessLlmOutputHook(params: { event: PluginHookLlmOutputEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessLlmOutputHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"c4c5131ab7065decd8d8e935ac3779e3baa2c52fbbbd95a6ccb624377db09ca1","declaration":"export function runBeforeToolCallHook(args: { toolName: string; params: unknown; toolKind?: PluginHookToolKind; toolInputKind?: PluginHookToolInputKind; toolCallId?: string; ctx?: HookContext; signal?: AbortSignal; approvalMode?: \"request\" | \"report\" | \"deny\" | \"defer\"; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runBeforeToolCallHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -221,8 +221,8 @@ {"closureHash":"f237bbc11e1d389679cd4e2ad7aa9055951b3029348e3374b81f769786a51d55","declaration":"export type AbortAndDrainAgentHarnessRunResult = AbortAndDrainEmbeddedAgentRunResult;","entrypoint":"agent-harness-runtime","exportName":"AbortAndDrainAgentHarnessRunResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"6f802f46717d28d260bbcb2cf4790dfed4e9ab28c4fe822d259228189cca4665","declaration":"export type AgentApprovalEventData = AgentApprovalEventData;","entrypoint":"agent-harness-runtime","exportName":"AgentApprovalEventData","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"12aac3a57ce200b0f082002be237625729f84ed7c337f1bac90bcd0688a53319","declaration":"export type AgentEventPayload = AgentEventPayload;","entrypoint":"agent-harness-runtime","exportName":"AgentEventPayload","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"e75e94d131237b4b73c507cad9f2a0940716404531516861497e92ba8d06fb87","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness-runtime","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"e75e94d131237b4b73c507cad9f2a0940716404531516861497e92ba8d06fb87","declaration":"export type AgentHarnessAttemptParams = AgentHarnessAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"71e57b87ff6cba595cc4513f2fd68742eb69a234d17e328c6cc6761eec04385e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness-runtime","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"71e57b87ff6cba595cc4513f2fd68742eb69a234d17e328c6cc6761eec04385e","declaration":"export type AgentHarnessAttemptParams = AgentHarnessAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"2dc2a62deea63b316142cc28d40afb88fb0d1e5ce3e048f141420726cda38248","declaration":"export type AgentHarnessAttemptResult = AgentHarnessAttemptResult;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"c7e642234081160830fd9e18a301900f8ee1ea8c88382e5a286f0102de65b714","declaration":"export type AgentHarnessAuthBindingFingerprintParams = AgentHarnessAuthBindingFingerprintParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAuthBindingFingerprintParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"601d68a3c668b18a4009d33b516d577bade06c3f89fafaa19685681c44d801b2","declaration":"export type AgentHarnessCompactParams = CompactEmbeddedAgentSessionParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessCompactParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -271,7 +271,7 @@ {"closureHash":"f30b66fd82f4cd61c60880c42a3b8f152ca64a2216036c99ab4129648ed329e7","declaration":"export type EmbeddedAgentCompactResult = EmbeddedAgentCompactResult;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedAgentCompactResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"1bbefad0193436f7340f9d0dec50be5d482973325c3c65170b1053dd05566f0a","declaration":"export type EmbeddedContextFile = EmbeddedContextFile;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedContextFile","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"f30b66fd82f4cd61c60880c42a3b8f152ca64a2216036c99ab4129648ed329e7","declaration":"export type EmbeddedPiCompactResult = EmbeddedAgentCompactResult;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedPiCompactResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"49c4aa50aa6a16de715caebb9215d233ab86bdc710b457b060c7de3857180b84","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"f975d7a88a7e25914f7a255354a6c2f0ede9281ca793e47ed971450e358dfbb4","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"a6cd2eebe0d06e6578ec8438a207c5acda10ddf01041102d84e4c576a0b6a42f","declaration":"export type EmbeddedRunAttemptResult = EmbeddedRunAttemptResult;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"f6cb2d6411db22cb04220777720d97bcca977351de1cb344ce2ff6ab126a3a08","declaration":"export type ExecApprovalDecision = ExecApprovalDecision;","entrypoint":"agent-harness-runtime","exportName":"ExecApprovalDecision","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"7acb0dffc7bcda6c727e4afc49c955fa8e14f4f8b7b45d197ed794dfa0d73b8e","declaration":"export type ExecAutoReviewDecision = ExecAutoReviewDecision;","entrypoint":"agent-harness-runtime","exportName":"ExecAutoReviewDecision","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -755,37 +755,37 @@ {"closureHash":"3ec2c091f2139a6c20b090ef4aa8a7e052440040bc620ce6cb7b8fd5ced3efa3","declaration":"export function buildThreadAwareOutboundSessionRoute(params: { route: ChannelOutboundSessionRoute; replyToId?: string | number | null; threadId?: string | number | null; currentSessionKey?: string | null; precedence?: readonly ThreadAwareOutboundSessionRouteThreadSource[]; useSuffix?: boolean; parentSessionKey?: string; normalizeThreadId?: (threadId: string) => string; canRecoverCurrentThread?: (context: ThreadAwareOutboundSessionRouteRecoveryContext) => boolean; }): ChannelOutboundSessionRoute;","entrypoint":"channel-core","exportName":"buildThreadAwareOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"9fc7e45343d7bfbc6ed56d05c9f824e2f9cf6dafc3ca4b25437d1f65c2200727","declaration":"export function clearAccountEntryFields(params: { accounts?: Record; accountId: string; fields: string[]; isValueSet?: (value: unknown) => boolean; markClearedOnFieldPresence?: boolean; }): { nextAccounts?: Record; changed: boolean; cleared: boolean; };","entrypoint":"channel-core","exportName":"clearAccountEntryFields","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"f4e084b64b5376268885a73fe507aa5d72bee17a88ec2d7ae1d19b36ea5f1ccb","declaration":"export function createChannelConfigUiHints(params: { channelLabel: string; dmPolicy?: { channelKey: string; includeLegacyNestedPolicy?: boolean; legacyNestedPolicyOrder?: \"before\" | \"after\"; }; configWrites?: boolean; mentionPatterns?: { targetDescription: string; policyTargetDescription?: string; policyNote?: string; denyNote?: string; }; nativeCommands?: boolean; implicitMentions?: boolean; progress?: { includeCommentary?: boolean; commentaryOrder?: \"before-command\" | \"after-command\"; labels?: \"openclaw\"; titleWording?: boolean; }; streaming?: Partial>; retry?: boolean; }): HintMap;","entrypoint":"channel-core","exportName":"createChannelConfigUiHints","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} -{"closureHash":"c26bfcd8451627b0eb75f7837e281b58dc127d19591d7c030691ca9bbe0edbf4","declaration":"export function createChatChannelPlugin(params: { base: ChatChannelPluginBase; security?: ChannelSecurityAdapter | ChatChannelSecurityOptions; pairing?: ChannelPairingAdapter | ChatChannelPairingOptions; threading?: ChannelThreadingAdapter | ChatChannelThreadingOptions; outbound?: ChannelOutboundAdapter | ChatChannelAttachedOutboundOptions; }): ChannelPlugin;","entrypoint":"channel-core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} -{"closureHash":"c4b7032c03cf9c056cfab60aeddd037258981854bd1081a4b88ccfed0306317a","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"channel-core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} +{"closureHash":"b8e27bea2add3eaafac7074cbd44fcf2acea30a1ac125c3551925e8cd0b3378d","declaration":"export function createChatChannelPlugin(params: { base: ChatChannelPluginBase; security?: ChannelSecurityAdapter | ChatChannelSecurityOptions; pairing?: ChannelPairingAdapter | ChatChannelPairingOptions; threading?: ChannelThreadingAdapter | ChatChannelThreadingOptions; outbound?: ChannelOutboundAdapter | ChatChannelAttachedOutboundOptions; }): ChannelPlugin;","entrypoint":"channel-core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} +{"closureHash":"9eec5be09e3eabc56729d2dcf61798420c8b5bd13d732790ab88e951c37156e4","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"channel-core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"0e0a9f6b22c433bdb1165e7707b1f9a1ddac1a544a8add00b503048cf157921f","declaration":"export function defineSetupPluginEntry(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"channel-core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"8895f7af11b994dcd383ebc45d8cfb3c3b1e6d88a64a001b04f604a83f77e517","declaration":"export function parseOptionalDelimitedEntries(value?: string): string[] | undefined;","entrypoint":"channel-core","exportName":"parseOptionalDelimitedEntries","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"3f97534b10d08eda6a556044eaba623b3744b200a2033877e48d2f2ca924d298","declaration":"export function recoverCurrentThreadSessionId(params: { route: ChannelOutboundSessionRoute; currentSessionKey?: string | null; canRecover?: (context: ThreadAwareOutboundSessionRouteRecoveryContext) => boolean; }): string | undefined;","entrypoint":"channel-core","exportName":"recoverCurrentThreadSessionId","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"0f0c9fb9b983b0c977229de86091efa1fbb7c8294657bd993ecd5448b351f371","declaration":"export function stripChannelTargetPrefix(raw: string, ...providers: string[]): string;","entrypoint":"channel-core","exportName":"stripChannelTargetPrefix","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"ba015db1f7f7fad580c6bed6d69816f9ba04dea11bb0605cac1f2f2baddb7bca","declaration":"export function stripTargetKindPrefix(raw: string): string;","entrypoint":"channel-core","exportName":"stripTargetKindPrefix","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"2e6ce1f4c1692270a00dc0cf08e2752a26739c3143f8091cb270063c6034605d","declaration":"export function tryReadSecretFileSync(filePath: string | undefined, label: string, options: CredentialFileReadOptions): string | undefined;\nexport function tryReadSecretFileSync(filePath: string | undefined, label: string, options?: FsSafeSecretFileReadOptions): string | undefined;\nexport function tryReadSecretFileSync(filePath: string, label: string, options: FsSafeSecretFileReadOptions | undefined, diagnostic: { configPath: string; }): ConfiguredCredentialResult;\nexport function tryReadSecretFileSync(filePath: string | undefined, label: string, options: FsSafeSecretFileReadOptions | undefined, diagnostic: { configPath: string; }): CredentialResult;","entrypoint":"channel-core","exportName":"tryReadSecretFileSync","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} -{"closureHash":"a5df78f0e910228e5cdea73e55f0335787437091ea28185ea264724e43b8b167","declaration":"export const createChannelPluginBase: (params: { id: ChannelPlugin[\"id\"]; meta?: Partial[\"meta\"]>>; setupWizard?: NonNullable[\"setupWizard\"]>; capabilities?: ChannelPlugin[\"capabilities\"]; commands?: ChannelPlugin[\"commands\"]; doctor?: ChannelPlugin[\"doctor\"]; agentPrompt?: ChannelPlugin[\"agentPrompt\"]; streaming?: ChannelPlugin[\"streaming\"]; reload?: ChannelPlugin[\"reload\"]; gatewayMethods?: ChannelPlugin[\"gatewayMethods\"]; gatewayMethodDescriptors?: ChannelPlugin[\"gatewayMethodDescriptors\"]; configSchema?: ChannelPlugin[\"configSchema\"]; config?: ChannelConfigAdapter | undefined; security?: ChannelSecurityAdapter | undefined; setup?: NonNullable[\"setup\"]>; setupContract?: NonNullable[\"setupContract\"]>; groups?: ChannelPlugin[\"groups\"];}) => Pick, \"id\" | \"meta\"> & Partial, \"security\" | \"commands\" | \"groups\" | \"capabilities\" | \"streaming\" | \"config\" | \"reload\" | \"configSchema\" | \"setup\" | \"doctor\" | \"gatewayMethodDescriptors\" | \"setupContract\" | \"setupWizard\" | \"gatewayMethods\" | \"agentPrompt\">>;","entrypoint":"channel-core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"const","recordType":"export"} +{"closureHash":"78d00beda3fcd305326e030090a06b90b5567866e1aef144db85fb6bfa8d0a47","declaration":"export const createChannelPluginBase: (params: { id: ChannelPlugin[\"id\"]; meta?: Partial[\"meta\"]>>; setupWizard?: NonNullable[\"setupWizard\"]>; capabilities?: ChannelPlugin[\"capabilities\"]; commands?: ChannelPlugin[\"commands\"]; doctor?: ChannelPlugin[\"doctor\"]; agentPrompt?: ChannelPlugin[\"agentPrompt\"]; streaming?: ChannelPlugin[\"streaming\"]; reload?: ChannelPlugin[\"reload\"]; gatewayMethods?: ChannelPlugin[\"gatewayMethods\"]; gatewayMethodDescriptors?: ChannelPlugin[\"gatewayMethodDescriptors\"]; configSchema?: ChannelPlugin[\"configSchema\"]; config?: ChannelConfigAdapter | undefined; security?: ChannelSecurityAdapter | undefined; setup?: NonNullable[\"setup\"]>; setupContract?: NonNullable[\"setupContract\"]>; groups?: ChannelPlugin[\"groups\"];}) => Pick, \"id\" | \"meta\"> & Partial, \"security\" | \"commands\" | \"groups\" | \"capabilities\" | \"streaming\" | \"config\" | \"reload\" | \"configSchema\" | \"setup\" | \"doctor\" | \"gatewayMethodDescriptors\" | \"setupContract\" | \"setupWizard\" | \"gatewayMethods\" | \"agentPrompt\">>;","entrypoint":"channel-core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"const","recordType":"export"} {"closureHash":"db6db8b2272765050d9dab70b7793f052520d8745923290375a50661f3e33cc8","declaration":"export type ChannelConfigUiHint = ChannelConfigUiHint;","entrypoint":"channel-core","exportName":"ChannelConfigUiHint","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"closureHash":"8126b651a679d5435eaa5d346916792c3600e5f0f75d8492b077dd361854f7dd","declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; currentSessionKey?: string; resolvedTarget?: { to: string; kind: ChannelDirectoryEntryKind | \"channel\"; display?: string; source: \"normalized\" | \"directory\"; }; replyToId?: string | null; threadId?: string | number | null;};","entrypoint":"channel-core","exportName":"ChannelOutboundSessionRouteParams","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} -{"closureHash":"4dd12b961fc300d388143ed5d8dc990e759c382b949c337c8f28ac83ca65aae7","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"channel-core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} +{"closureHash":"18fcab0d5899575a31205732d2be92597e533ad944c7fe11cac2af6fc718ea34","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"channel-core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"channel-core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} -{"closureHash":"fb4fde629072c35c7afe2f3248520c284b439596eb2e25c136b6494b402cee1f","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} +{"closureHash":"b9c63a41b3da754e29aee2040c6b79300801cb59b95dcedf8032f404cd0c9a8d","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"closureHash":"4bf9c20e2a621ecc84998961937887666d84884ef6f8f1993a34c87c11000b60","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"channel-core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"closureHash":"3203c47bc265736977eb102837cf12d2fe8f8dc459389c21f319d9426d83dc8e","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"channel-core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"category":"channel","entrypoint":"channel-dm-policy","importSpecifier":"openclaw/plugin-sdk/channel-dm-policy","recordType":"module"} {"closureHash":"821fe6ccd0d9323322bf70c4d1ca5697071a0e32032f44c1e14157162c2c729d","declaration":"export function createChannelDmPolicy(params: CreateChannelDmPolicyParams): ChannelSetupDmPolicy & { promptAllowFrom: NonNullable; };","entrypoint":"channel-dm-policy","exportName":"createChannelDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-dm-policy","kind":"function","recordType":"export"} {"category":null,"entrypoint":"channel-entry-contract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","recordType":"module"} -{"closureHash":"f926201f9283010418a03fd8ef841fb2616017d05975365dc979bbde0747c7a9","declaration":"export function defineBundledChannelEntry({ id, name, description, importMetaUrl, plugin, outbound, secrets, configSchema, runtime, accountInspect, features, registerCliMetadata, registerFull, registerCapabilities, }: DefineBundledChannelEntryOptions): BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} -{"closureHash":"4d79a9648b7007df00560ca5a1a33e6fccc2d92cd00a0fea8ca52eada4d326ea","declaration":"export function defineBundledChannelSetupEntry({ importMetaUrl, plugin, secrets, runtime, legacyStateMigrations, legacySessionSurface, registerSetupRuntime, features, }: DefineBundledChannelSetupEntryOptions): BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelSetupEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} +{"closureHash":"77ed16a89093257c19f2f0ec5dc040b684d4c96b3a3afb95b5346123128c5910","declaration":"export function defineBundledChannelEntry({ id, name, description, importMetaUrl, plugin, outbound, secrets, configSchema, runtime, accountInspect, features, registerCliMetadata, registerFull, registerCapabilities, }: DefineBundledChannelEntryOptions): BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} +{"closureHash":"c223d3c170b0dc6ed877fd13a05341da5ed89f55a9138de5015cdffcef266fdb","declaration":"export function defineBundledChannelSetupEntry({ importMetaUrl, plugin, secrets, runtime, legacyStateMigrations, legacySessionSurface, registerSetupRuntime, features, }: DefineBundledChannelSetupEntryOptions): BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelSetupEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} {"closureHash":"cd150287d7e286e7a0d7d6caeb05d0a1efa63b5f351f75f69ba932510a108afd","declaration":"export function loadBundledEntryExportSync(importMetaUrl: string, reference: BundledEntryModuleRef, options?: BundledEntryModuleLoadOptions): T;","entrypoint":"channel-entry-contract","exportName":"loadBundledEntryExportSync","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} {"closureHash":"7781a3d570d08929af5b3b6cffbb9ef4b9c8e8f1bed55234e0015a681868c812","declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"channel-entry-contract","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"12459db2b865a0aea85d69e055538a24c0cc3993a083b0630465d909ff4af7f3","declaration":"export type BundledChannelEntryContract = BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"e93a25fc5f26079e40a477b03e7b183c95bbca1c780f5fea98710c4a3196179d","declaration":"export type BundledChannelEntryContract = BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"f4b82dfd995bd6f08b232984743389d1c854866cb845a8dbb3605acb28818688","declaration":"export type BundledChannelEntryFeatures = BundledChannelEntryFeatures;","entrypoint":"channel-entry-contract","exportName":"BundledChannelEntryFeatures","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"960693591b9bdc974bf3f0097076d90490078db3dceb35349a4f851736cde4fc","declaration":"export type BundledChannelLegacySessionSurface = BundledChannelLegacySessionSurface;","entrypoint":"channel-entry-contract","exportName":"BundledChannelLegacySessionSurface","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"edf79e6a736e5c4977e3b86ef21e7fdf0c0b2bc7deacd8edbee2ca76cb8cef43","declaration":"export type BundledChannelLegacyStateMigrationDetector = BundledChannelLegacyStateMigrationDetector;","entrypoint":"channel-entry-contract","exportName":"BundledChannelLegacyStateMigrationDetector","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"68b7d919c703115b3ab0acb41f6fe59c23e4888de19fc7bb8f73e42f9ae1d253","declaration":"export type BundledChannelSetupEntryContract = BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelSetupEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"d9419e11e4b295fa773cabd3e62af412fe761b62f841eafb5c9809636a1258b7","declaration":"export type BundledChannelSetupEntryContract = BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelSetupEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"24679ecdf2ff34157b6345a37b58ec1363ec8cb1969b522599d0d92bb7a113b7","declaration":"export type BundledChannelSetupEntryFeatures = BundledChannelSetupEntryFeatures;","entrypoint":"channel-entry-contract","exportName":"BundledChannelSetupEntryFeatures","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"367219c821915e5be4d1ba3a86754475a5f8a4194512f0401de3be11cc649c60","declaration":"export type BundledEntryModuleLoadOptions = BundledEntryModuleLoadOptions;","entrypoint":"channel-entry-contract","exportName":"BundledEntryModuleLoadOptions","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"6338ff51830d7387f35c03310d140f89d172f45805deb0b480698b4473ab9ef8","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-entry-contract","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"e1750a74dc768e6a21ee2eafbf486b817be19485a063e5a7f0f72d24540e73da","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-entry-contract","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"f22bde542d2dc632b20569c7679ee30a4e88851e0e9dec89350e120f6f456b15","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"channel-entry-contract","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"a0103d278095a8687e571bcc0917c5c87fc1a1c79f151a07c7225c4d8f54a39d","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"channel-entry-contract","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"category":null,"entrypoint":"channel-feedback","importSpecifier":"openclaw/plugin-sdk/channel-feedback","recordType":"module"} @@ -1097,7 +1097,7 @@ {"closureHash":"9555a73ba2717bba0bf94888017be4cecef2c51cc3887ed34f8d8ef3c79d6abf","declaration":"export const DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS: number;","entrypoint":"channel-message","exportName":"DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} {"closureHash":"3a2df3ab656149630c004d2d9f71b8ceda99aa81eb6b72b0cc7b3982ed0ce044","declaration":"export const DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS: 8;","entrypoint":"channel-message","exportName":"DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} {"closureHash":"38c735a14c65067aa7825390d1c5c8876c651d0603e84980dfaf947f5235747a","declaration":"export const INGRESS_CLAIM_PROCESS_ID: string;","entrypoint":"channel-message","exportName":"INGRESS_CLAIM_PROCESS_ID","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} -{"closureHash":"f5d6c974980d1792af370a89adca4417174efdc8bf3b70e140fdfe21d1692cca","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-message","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} +{"closureHash":"16254799487aa48361f99ab341adad98738406e4af686ef50487780450c230fe","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-message","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} {"closureHash":"2c52eff200a5b9bd2d93ee72209c2626bbe165f59b538591db661b94773023b0","declaration":"export type AgentPlanStep = AgentPlanStep;","entrypoint":"channel-message","exportName":"AgentPlanStep","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"} {"closureHash":"1e8bcb2c8d8f5327f5b81b8c217f722f090dccba21ba3943324010f4f80a5a50","declaration":"export type AgentPlanStepStatus = AgentPlanStepStatus;","entrypoint":"channel-message","exportName":"AgentPlanStepStatus","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"} {"closureHash":"b036fc26e5330dfd7da1af8839bb3c23e85283b9e16e252a659dd4bb0c35cd5e","declaration":"export type ChannelDeliveryStreamingConfig = ChannelDeliveryStreamingConfig;","entrypoint":"channel-message","exportName":"ChannelDeliveryStreamingConfig","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"} @@ -1226,7 +1226,7 @@ {"closureHash":"9555a73ba2717bba0bf94888017be4cecef2c51cc3887ed34f8d8ef3c79d6abf","declaration":"export const DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS: number;","entrypoint":"channel-outbound","exportName":"DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} {"closureHash":"3a2df3ab656149630c004d2d9f71b8ceda99aa81eb6b72b0cc7b3982ed0ce044","declaration":"export const DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS: 8;","entrypoint":"channel-outbound","exportName":"DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} {"closureHash":"38c735a14c65067aa7825390d1c5c8876c651d0603e84980dfaf947f5235747a","declaration":"export const INGRESS_CLAIM_PROCESS_ID: string;","entrypoint":"channel-outbound","exportName":"INGRESS_CLAIM_PROCESS_ID","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} -{"closureHash":"f5d6c974980d1792af370a89adca4417174efdc8bf3b70e140fdfe21d1692cca","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-outbound","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} +{"closureHash":"16254799487aa48361f99ab341adad98738406e4af686ef50487780450c230fe","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-outbound","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} {"closureHash":"2c52eff200a5b9bd2d93ee72209c2626bbe165f59b538591db661b94773023b0","declaration":"export type AgentPlanStep = AgentPlanStep;","entrypoint":"channel-outbound","exportName":"AgentPlanStep","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"} {"closureHash":"1e8bcb2c8d8f5327f5b81b8c217f722f090dccba21ba3943324010f4f80a5a50","declaration":"export type AgentPlanStepStatus = AgentPlanStepStatus;","entrypoint":"channel-outbound","exportName":"AgentPlanStepStatus","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"} {"closureHash":"b036fc26e5330dfd7da1af8839bb3c23e85283b9e16e252a659dd4bb0c35cd5e","declaration":"export type ChannelDeliveryStreamingConfig = ChannelDeliveryStreamingConfig;","entrypoint":"channel-outbound","exportName":"ChannelDeliveryStreamingConfig","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"} @@ -1291,8 +1291,8 @@ {"closureHash":"b40933a11984425d14a7a479bda0d2cd14cbfa9371164774f39bebbf12861df7","declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"channel-plugin-common","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"const","recordType":"export"} {"closureHash":"cd6b0d3f962c8cb40d405e92bb06bb8e9285b386200897f550d21036022262c1","declaration":"export const PAIRING_APPROVED_MESSAGE: \"✅ OpenClaw access approved. Send a message to start chatting.\";","entrypoint":"channel-plugin-common","exportName":"PAIRING_APPROVED_MESSAGE","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"const","recordType":"export"} {"closureHash":"712435252d2fe5135542ca6b5a4375a6edea24e83829338011dc6ae7e9802fbb","declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-plugin-common","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} -{"closureHash":"4dd12b961fc300d388143ed5d8dc990e759c382b949c337c8f28ac83ca65aae7","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"channel-plugin-common","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} -{"closureHash":"fb4fde629072c35c7afe2f3248520c284b439596eb2e25c136b6494b402cee1f","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-plugin-common","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} +{"closureHash":"18fcab0d5899575a31205732d2be92597e533ad944c7fe11cac2af6fc718ea34","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"channel-plugin-common","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} +{"closureHash":"b9c63a41b3da754e29aee2040c6b79300801cb59b95dcedf8032f404cd0c9a8d","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-plugin-common","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} {"closureHash":"3203c47bc265736977eb102837cf12d2fe8f8dc459389c21f319d9426d83dc8e","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"channel-plugin-common","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} {"category":null,"entrypoint":"channel-policy","importSpecifier":"openclaw/plugin-sdk/channel-policy","recordType":"module"} {"closureHash":"017ab29d16d0f3d02d60f3513e65a373868d26496bc93d020d8fc8c17fd875f4","declaration":"export function buildAccountScopedDmSecurityPolicy(params: { cfg: OpenClawConfig; channelKey: string; accountId?: string | null; fallbackAccountId?: string | null; policy?: string | null; allowFrom?: Array | null; defaultPolicy?: string; allowFromPathSuffix?: string; policyPathSuffix?: string; approveChannelId?: string; approveHint?: string; normalizeEntry?: (raw: string) => string; inheritSharedDefaultsFromDefaultAccount?: boolean; }): ChannelSecurityDmPolicy;","entrypoint":"channel-policy","exportName":"buildAccountScopedDmSecurityPolicy","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} @@ -1320,7 +1320,7 @@ {"closureHash":"02363b81b54c30225eb6e3f0519b41cbe7d3138a2f246f98a603edf39f25ed32","declaration":"export function createOpenGroupPolicyRestrictSendersWarningCollector(params: { resolveGroupPolicy: (account: ResolvedAccount) => GroupPolicy | null | undefined; defaultGroupPolicy?: GroupPolicy; } & Omit[0], \"groupPolicy\">): (account: ResolvedAccount) => string[];","entrypoint":"channel-policy","exportName":"createOpenGroupPolicyRestrictSendersWarningCollector","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} {"closureHash":"cbfd724680731a8586992b442db7c33029ad6eff20785686d5b383223b553e4a","declaration":"export function createOpenProviderConfiguredRouteWarningCollector(params: { providerConfigPresent: (cfg: OpenClawConfig) => boolean; resolveGroupPolicy: (account: ResolvedAccount) => GroupPolicy | null | undefined; resolveRouteAllowlistConfigured: (account: ResolvedAccount) => boolean; configureRouteAllowlist: Parameters[0]; missingRouteAllowlist: Parameters[0]; }): AccountGroupPolicyWarningCollector;","entrypoint":"channel-policy","exportName":"createOpenProviderConfiguredRouteWarningCollector","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} {"closureHash":"92c797e68f69341c7b377821234cd9b27a8be1593249e956c4f1f1fe72bd65d7","declaration":"export function createOpenProviderGroupPolicyWarningCollector(params: { providerConfigPresent: (cfg: OpenClawConfig) => boolean; resolveGroupPolicy: (params: Params) => GroupPolicy | null | undefined; collect: (params: Params & { groupPolicy: GroupPolicy; }) => string[]; }): ConfigGroupPolicyWarningCollector;","entrypoint":"channel-policy","exportName":"createOpenProviderGroupPolicyWarningCollector","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} -{"closureHash":"30a586ad5e032fa84b001e73af62870c9a682e84c0616077a06e24fe9cc09b60","declaration":"export function createRestrictSendersChannelSecurity(params: { channelKey: string; resolveDmPolicy: (account: ResolvedAccount) => string | null | undefined; resolveDmAllowFrom: (account: ResolvedAccount) => Array | null | undefined; resolveGroupPolicy: (account: ResolvedAccount) => GroupPolicy | null | undefined; surface: string; openScope: string; groupPolicyPath: string; groupAllowFromPath: string; mentionGated?: boolean; providerConfigPresent?: (cfg: OpenClawConfig) => boolean; resolveFallbackAccountId?: (account: ResolvedAccount) => string | null | undefined; defaultDmPolicy?: string; allowFromPathSuffix?: string; policyPathSuffix?: string; approveChannelId?: string; approveHint?: string; normalizeDmEntry?: (raw: string) => string; inheritSharedDefaultsFromDefaultAccount?: boolean; }): ChannelSecurityAdapter;","entrypoint":"channel-policy","exportName":"createRestrictSendersChannelSecurity","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} +{"closureHash":"3498d7988e1de695e02d420fb41202d80418f2758577289ff002332747eb4346","declaration":"export function createRestrictSendersChannelSecurity(params: { channelKey: string; resolveDmPolicy: (account: ResolvedAccount) => string | null | undefined; resolveDmAllowFrom: (account: ResolvedAccount) => Array | null | undefined; resolveGroupPolicy: (account: ResolvedAccount) => GroupPolicy | null | undefined; surface: string; openScope: string; groupPolicyPath: string; groupAllowFromPath: string; mentionGated?: boolean; providerConfigPresent?: (cfg: OpenClawConfig) => boolean; resolveFallbackAccountId?: (account: ResolvedAccount) => string | null | undefined; defaultDmPolicy?: string; allowFromPathSuffix?: string; policyPathSuffix?: string; approveChannelId?: string; approveHint?: string; normalizeDmEntry?: (raw: string) => string; inheritSharedDefaultsFromDefaultAccount?: boolean; dmRouting?: ChannelSecurityAdapter[\"dmRouting\"]; }): ChannelSecurityAdapter;","entrypoint":"channel-policy","exportName":"createRestrictSendersChannelSecurity","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} {"closureHash":"b6b34cd3844debbe7cda17ad7703e4fcffe4489789ae1763df8f8ab027150203","declaration":"export function evaluateGroupRouteAccessForPolicy(params: { groupPolicy: GroupPolicy; routeAllowlistConfigured: boolean; routeMatched: boolean; routeEnabled?: boolean; }): GroupRouteAccessDecision;","entrypoint":"channel-policy","exportName":"evaluateGroupRouteAccessForPolicy","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} {"closureHash":"182fa4fc45ddd20915ce722f255d301180b06a33d25aa2b4d771ced127558035","declaration":"export function evaluateSenderGroupAccessForPolicy(params: { groupPolicy: GroupPolicy; providerMissingFallbackApplied?: boolean; groupAllowFrom: string[]; senderId: string; isSenderAllowed: (senderId: string, allowFrom: string[]) => boolean; }): SenderGroupAccessDecision;","entrypoint":"channel-policy","exportName":"evaluateSenderGroupAccessForPolicy","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} {"closureHash":"cf41bc7efb2e5e5a031c236a14192bedba5a02d93aae3306ae5793d632d93692","declaration":"export function normalizeAllowFromList(list: Array | undefined | null): string[];","entrypoint":"channel-policy","exportName":"normalizeAllowFromList","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} @@ -1887,12 +1887,12 @@ {"closureHash":"544219cddcce81cf5c8239f6ea9908fbeb809dba370b34e4928be95ee639057c","declaration":"export function channelTargetsSchema(options?: { description?: string; }): Type.TArray;","entrypoint":"core","exportName":"channelTargetsSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"9fc7e45343d7bfbc6ed56d05c9f824e2f9cf6dafc3ca4b25437d1f65c2200727","declaration":"export function clearAccountEntryFields(params: { accounts?: Record; accountId: string; fields: string[]; isValueSet?: (value: unknown) => boolean; markClearedOnFieldPresence?: boolean; }): { nextAccounts?: Record; changed: boolean; cleared: boolean; };","entrypoint":"core","exportName":"clearAccountEntryFields","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"0438c0afd280cc2df90e7ffe221ce3133e6f742e9dc725ff34bbdeb90eeab2c8","declaration":"export function createActionGate>(actions: T | undefined): ActionGate;","entrypoint":"core","exportName":"createActionGate","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"7c5b67965c77dc8d16606890f53057c8835c3b502559d2b4c97bb73488f84617","declaration":"export function createChannelPluginBase(params: CreateChannelPluginBaseOptions): CreatedChannelPluginBase;","entrypoint":"core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"c26bfcd8451627b0eb75f7837e281b58dc127d19591d7c030691ca9bbe0edbf4","declaration":"export function createChatChannelPlugin(params: { base: ChatChannelPluginBase; security?: ChannelSecurityAdapter | ChatChannelSecurityOptions; pairing?: ChannelPairingAdapter | ChatChannelPairingOptions; threading?: ChannelThreadingAdapter | ChatChannelThreadingOptions; outbound?: ChannelOutboundAdapter | ChatChannelAttachedOutboundOptions; }): ChannelPlugin;","entrypoint":"core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"990d66feef26f2c87a46c85726a0b0eb3c39254e631cbcbb752ec0fe1d363fbf","declaration":"export function createChannelPluginBase(params: CreateChannelPluginBaseOptions): CreatedChannelPluginBase;","entrypoint":"core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"b8e27bea2add3eaafac7074cbd44fcf2acea30a1ac125c3551925e8cd0b3378d","declaration":"export function createChatChannelPlugin(params: { base: ChatChannelPluginBase; security?: ChannelSecurityAdapter | ChatChannelSecurityOptions; pairing?: ChannelPairingAdapter | ChatChannelPairingOptions; threading?: ChannelThreadingAdapter | ChatChannelThreadingOptions; outbound?: ChannelOutboundAdapter | ChatChannelAttachedOutboundOptions; }): ChannelPlugin;","entrypoint":"core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"785b0f750c5bd20f9f3ca081886a5af79ee0e4d2c38f78f769bf994b234f5076","declaration":"export function createDedupeCache(options: DedupeCacheOptions): DedupeCache;","entrypoint":"core","exportName":"createDedupeCache","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"e2df8d235401aebf58eb71652fbeaedb42ca00aaa5042a76909ff2c48ba6fd54","declaration":"export function createSubsystemLogger(subsystem: string): SubsystemLogger;","entrypoint":"core","exportName":"createSubsystemLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"c4b7032c03cf9c056cfab60aeddd037258981854bd1081a4b88ccfed0306317a","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"0e3a6175467adf8ff674c52bb0ae1af57d2e52f33448416e5d11b4eca1685baf","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"9eec5be09e3eabc56729d2dcf61798420c8b5bd13d732790ab88e951c37156e4","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"a4f0792ef70bd2b09bf37e9c37943284c8f93b82bd3864cf6f3739033c2878a6","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"0e0a9f6b22c433bdb1165e7707b1f9a1ddac1a544a8add00b503048cf157921f","declaration":"export function defineSetupPluginEntry(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"3c5ce0c3733cbb038aeb914af1df5d701f362f0521921b8abd0c9214db9cc4b8","declaration":"export function delegateCompactionToRuntime(params: Parameters[0]): Promise;","entrypoint":"core","exportName":"delegateCompactionToRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"2c282e0e308f9442bca7cdeb8e89a097531b1d54a692c9d86e5f39a8db1c2537","declaration":"export function deleteAccountFromConfigSection(params: { cfg: OpenClawConfig; sectionKey: string; accountId: string; clearBaseFields?: string[]; }): OpenClawConfig;","entrypoint":"core","exportName":"deleteAccountFromConfigSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} @@ -1939,7 +1939,7 @@ {"closureHash":"2e6ce1f4c1692270a00dc0cf08e2752a26739c3143f8091cb270063c6034605d","declaration":"export function tryReadSecretFileSync(filePath: string | undefined, label: string, options: CredentialFileReadOptions): string | undefined;\nexport function tryReadSecretFileSync(filePath: string | undefined, label: string, options?: FsSafeSecretFileReadOptions): string | undefined;\nexport function tryReadSecretFileSync(filePath: string, label: string, options: FsSafeSecretFileReadOptions | undefined, diagnostic: { configPath: string; }): ConfiguredCredentialResult;\nexport function tryReadSecretFileSync(filePath: string | undefined, label: string, options: FsSafeSecretFileReadOptions | undefined, diagnostic: { configPath: string; }): CredentialResult;","entrypoint":"core","exportName":"tryReadSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"b40933a11984425d14a7a479bda0d2cd14cbfa9371164774f39bebbf12861df7","declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"core","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export"} {"closureHash":null,"declaration":"export const DEFAULT_SECRET_FILE_MAX_BYTES: number;","entrypoint":"core","exportName":"DEFAULT_SECRET_FILE_MAX_BYTES","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export"} -{"closureHash":"e75e94d131237b4b73c507cad9f2a0940716404531516861497e92ba8d06fb87","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"core","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"71e57b87ff6cba595cc4513f2fd68742eb69a234d17e328c6cc6761eec04385e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"core","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"d2ff4de9ee3fd111c2cc64a3ee7e557d9f161af1b6b437ee7886bcb16e426317","declaration":"export type AgentPromptGuidance = AgentPromptGuidance;","entrypoint":"core","exportName":"AgentPromptGuidance","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"2841127a90e04467adfea8126cbf03655f44ddb089ad9e0d48833c2beea39cbd","declaration":"export type AgentPromptGuidanceEntry = AgentPromptGuidanceEntry;","entrypoint":"core","exportName":"AgentPromptGuidanceEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"aa0412acefe62caff12e5271ead0545504874e824380dc21cfc0566388a05f33","declaration":"export type AgentPromptSurfaceKind = \"openclaw_main\" | \"pi_main\" | \"codex_app_server\" | \"cli_backend\" | \"acp_backend\" | \"subagent\";","entrypoint":"core","exportName":"AgentPromptSurfaceKind","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} @@ -1957,7 +1957,7 @@ {"closureHash":"ec916ca974bd0242329b6532fb8467a63d038f1182ae9b2af3aa3b979b5fa589","declaration":"export type ChannelOutboundAdapter = ChannelOutboundAdapter;","entrypoint":"core","exportName":"ChannelOutboundAdapter","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"7b39a17fc562efc5af466006bcdedc6182567effce66c775b565317fb59b0295","declaration":"export type ChannelOutboundSessionRoute = ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"ChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"8126b651a679d5435eaa5d346916792c3600e5f0f75d8492b077dd361854f7dd","declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; currentSessionKey?: string; resolvedTarget?: { to: string; kind: ChannelDirectoryEntryKind | \"channel\"; display?: string; source: \"normalized\" | \"directory\"; }; replyToId?: string | null; threadId?: string | number | null;};","entrypoint":"core","exportName":"ChannelOutboundSessionRouteParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"4dd12b961fc300d388143ed5d8dc990e759c382b949c337c8f28ac83ca65aae7","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"18fcab0d5899575a31205732d2be92597e533ad944c7fe11cac2af6fc718ea34","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"c7f4189c00fda265d2124e4603f9a2936229c7bf5dcc246e5d6f831179d18182","declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"core","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"5fd0fa51b352b25b111be12e2fbc79648bb5e9cf5f55cbe7131c8c60e54787b2","declaration":"export type ChatType = ChatType;","entrypoint":"core","exportName":"ChatType","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"e4880dcde69275f17e135c15682e5195e4817e0b0ed06763703145086fc2e721","declaration":"export type ContextEngineSessionTarget = ContextEngineSessionTarget;","entrypoint":"core","exportName":"ContextEngineSessionTarget","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} @@ -1971,10 +1971,10 @@ {"closureHash":"54ea426dde51859b572b4c1079d2b70b412096f73da2b8c265f2749d9f01cbb5","declaration":"export type NormalizedLocation = NormalizedLocation;","entrypoint":"core","exportName":"NormalizedLocation","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"5189698d102b8b064eefe1442b008312973c3994fd6b203d2205725d7ee9d118","declaration":"export type OpenClawPluginActiveModelContext = OpenClawPluginActiveModelContext;","entrypoint":"core","exportName":"OpenClawPluginActiveModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"fb4fde629072c35c7afe2f3248520c284b439596eb2e25c136b6494b402cee1f","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"b9c63a41b3da754e29aee2040c6b79300801cb59b95dcedf8032f404cd0c9a8d","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"69fefc8092c1cea366c48505c8423ff0f8f995caef3d259d177346b1687541aa","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"365beb5cee974639c2f35fc7a39088721ca8e9c618442830298b98033e9c768c","declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"c8efb9154eafc9061e7b6bf41fd001a4c2b38e0645d6382ad9e493d3f12a3664","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"2614b3215fe42678ee92b6d077aaf2ddea54294b486b5bc3dbffde10cff679ac","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"a7ed83f0924f818b23cecb5a1f3591ff28b9499ccac9667a2b8505c2bc608ea9","declaration":"export type OpenClawPluginGatewayEventScope = OpenClawPluginGatewayEventScope;","entrypoint":"core","exportName":"OpenClawPluginGatewayEventScope","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"f81f224d9b837e6353b7a546c5a76b124bcf568fd1f1fd0c6881fda30c53120a","declaration":"export type OpenClawPluginGatewayEvents = OpenClawPluginGatewayEvents;","entrypoint":"core","exportName":"OpenClawPluginGatewayEvents","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"ddc2738dd0ece94ddde9a7c655f92c15ec6416645ecf932d4aa404c7b7761159","declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} @@ -2195,13 +2195,13 @@ {"closureHash":"4d4a0ece3ccb6d5020047cb2478574e012716748c8849e78b740dfd3bdc588f4","declaration":"export function unbindThreadBindingsBySessionKey(params: { targetSessionKey: string; accountId?: string; targetKind?: ThreadBindingTargetKind; reason?: string; sendFarewell?: boolean; farewellText?: string; }): ThreadBindingRecord[];","entrypoint":"discord","exportName":"unbindThreadBindingsBySessionKey","importSpecifier":"openclaw/plugin-sdk/discord","kind":"function","recordType":"export"} {"closureHash":"b40933a11984425d14a7a479bda0d2cd14cbfa9371164774f39bebbf12861df7","declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"discord","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/discord","kind":"const","recordType":"export"} {"closureHash":"cd6b0d3f962c8cb40d405e92bb06bb8e9285b386200897f550d21036022262c1","declaration":"export const PAIRING_APPROVED_MESSAGE: \"✅ OpenClaw access approved. Send a message to start chatting.\";","entrypoint":"discord","exportName":"PAIRING_APPROVED_MESSAGE","importSpecifier":"openclaw/plugin-sdk/discord","kind":"const","recordType":"export"} -{"closureHash":"1c7d6b7fb8094571ea44338cc968e915c65ed09ac437780f9fd16c59d731f438","declaration":"export const buildDiscordComponentMessage: BuildDiscordComponentMessage;","entrypoint":"discord","exportName":"buildDiscordComponentMessage","importSpecifier":"openclaw/plugin-sdk/discord","kind":"const","recordType":"export"} +{"closureHash":"83e88b20d1d794e442f7a4c245b9d557b3f95276fad4a0758466c60c9f12997c","declaration":"export const buildDiscordComponentMessage: BuildDiscordComponentMessage;","entrypoint":"discord","exportName":"buildDiscordComponentMessage","importSpecifier":"openclaw/plugin-sdk/discord","kind":"const","recordType":"export"} {"closureHash":"7ca7125928ab0b6f04d47bfba94b9a50e3dfcc56717a413d24e4794ef91a091e","declaration":"export const discordOnboardingAdapter: {};","entrypoint":"discord","exportName":"discordOnboardingAdapter","importSpecifier":"openclaw/plugin-sdk/discord","kind":"const","recordType":"export"} {"closureHash":"d619ec239abd45d5be76c3c58acc82f7a25f8f66352d2afc6453e13c4c7a82e7","declaration":"export const editDiscordComponentMessage: EditDiscordComponentMessage;","entrypoint":"discord","exportName":"editDiscordComponentMessage","importSpecifier":"openclaw/plugin-sdk/discord","kind":"const","recordType":"export"} {"closureHash":"d619ec239abd45d5be76c3c58acc82f7a25f8f66352d2afc6453e13c4c7a82e7","declaration":"export const registerBuiltDiscordComponentMessage: RegisterBuiltDiscordComponentMessage;","entrypoint":"discord","exportName":"registerBuiltDiscordComponentMessage","importSpecifier":"openclaw/plugin-sdk/discord","kind":"const","recordType":"export"} {"closureHash":"75b9b07bac5eabd3e05c7d3e33b28c53db35410e6ba9b2f8bb5406a3849e2c11","declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"discord","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"0a4bc843eaab5feec0a0085b0bc501a0e0b3f4b87b0e05b40c5ea1ce874fad02","declaration":"export type ChannelMessageActionName = \"search\" | \"broadcast\" | \"read\" | \"edit\" | \"delete\" | \"timeout\" | \"send\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"sticker\" | \"sticker-search\" | \"member-info\" | \"role-info\" | \"emoji-list\" | \"emoji-upload\" | \"sticker-upload\" | \"role-add\" | \"role-remove\" | \"channel-info\" | \"channel-list\" | \"channel-create\" | \"channel-edit\" | \"channel-delete\" | \"channel-move\" | \"category-create\" | \"category-edit\" | \"category-delete\" | \"topic-create\" | \"topic-edit\" | \"voice-status\" | \"event-list\" | \"event-create\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\" | \"upload-file\";","entrypoint":"discord","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} -{"closureHash":"4dd12b961fc300d388143ed5d8dc990e759c382b949c337c8f28ac83ca65aae7","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"discord","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} +{"closureHash":"18fcab0d5899575a31205732d2be92597e533ad944c7fe11cac2af6fc718ea34","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"discord","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"68c829c145de778dc26f5f89ba81aa0087171cf6b8f2bb79530247c14af4ba0e","declaration":"export type DiscordAccountConfig = { accounts?: Record; defaultAccount?: string;} & Omit, \"groupAllowFrom\"> & ChannelBotInteractionConfig & { reactionNotifications?: undefined; reactionLevel?: undefined; ackReaction?: string | undefined;} & Record & { commands?: ProviderCommandsConfig; token?: SecretInput; applicationId?: string; activities?: { clientSecret?: string; applicationId?: string; }; proxy?: string; mentionAliases?: DiscordMentionAliasesConfig; suppressEmbeds?: boolean; maxLinesPerMessage?: number; actions?: DiscordActionConfig; thread?: DiscordThreadConfig; dm?: DiscordDmConfig; guilds?: Record; execApprovals?: DiscordExecApprovalConfig; agentComponents?: DiscordAgentComponentsConfig; slashCommand?: DiscordSlashCommandConfig; threadBindings?: DiscordThreadBindingsConfig; subagentProgress?: boolean; intents?: DiscordIntentsConfig; voice?: DiscordVoiceConfig; pluralkit?: DiscordPluralKitConfig; ackReactionScope?: \"group-mentions\" | \"group-all\" | \"direct\" | \"all\" | \"off\" | \"none\"; activity?: string; status?: \"online\" | \"dnd\" | \"idle\" | \"invisible\"; autoPresence?: DiscordAutoPresenceConfig; activityType?: 0 | 1 | 2 | 3 | 4 | 5; activityUrl?: string; inboundWorker?: { runTimeoutMs?: number; };};","entrypoint":"discord","exportName":"DiscordAccountConfig","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"ae9fb82eaf8d09709d4f8c26f7419827741faa40a3fae83864863cdae7e86250","declaration":"export type DiscordComponentBuildResult = DiscordComponentBuildResult;","entrypoint":"discord","exportName":"DiscordComponentBuildResult","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"5c5d9351a7f45d03bd5b0f2b116db5484bc5073b02f717b353420369a8f48556","declaration":"export type DiscordComponentMessageSpec = DiscordComponentMessageSpec;","entrypoint":"discord","exportName":"DiscordComponentMessageSpec","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} @@ -2209,7 +2209,7 @@ {"closureHash":"0db968dad99d84ecef5202167daadd092e3b4f456270283d3fd61585ac2bbd5a","declaration":"export type DiscordComponentSendResult = DiscordComponentSendResult;","entrypoint":"discord","exportName":"DiscordComponentSendResult","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"084b46d7dd510eb182a4705559251e824220b57dbfa6dc54392507b72ba1815e","declaration":"export type DiscordOutboundTargetResolution = DiscordOutboundTargetResolution;","entrypoint":"discord","exportName":"DiscordOutboundTargetResolution","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"discord","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} -{"closureHash":"fb4fde629072c35c7afe2f3248520c284b439596eb2e25c136b6494b402cee1f","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"discord","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} +{"closureHash":"b9c63a41b3da754e29aee2040c6b79300801cb59b95dcedf8032f404cd0c9a8d","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"discord","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"3203c47bc265736977eb102837cf12d2fe8f8dc459389c21f319d9426d83dc8e","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"discord","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"6b9967e919c1cd420c8356b4f9d40dbc81932b4b15a733eecdcfb2ad84f8e5d8","declaration":"export type ResolvedDiscordAccount = ResolvedDiscordAccount;","entrypoint":"discord","exportName":"ResolvedDiscordAccount","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"6bed5ca896b7034117e4757e2c6b4111dd5293dbad9416e3828dd6afa4e858ce","declaration":"export type ThreadBindingRecord = ThreadBindingRecord;","entrypoint":"discord","exportName":"ThreadBindingRecord","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} @@ -2354,7 +2354,7 @@ {"closureHash":"98e0cc16352b7dfcceb4957f8cd2acfe3c2b3acb223c42a5cfb885e088fcb04c","declaration":"export function resolveInboundReplyDispatchCounts(result: ChannelTurnDispatchResultLike): Record;","entrypoint":"inbound-reply-dispatch","exportName":"resolveInboundReplyDispatchCounts","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} {"closureHash":"9d503d05e408ddd1a1c373e3c4485b1f9acff4c240fdc241840a2cfa8b55c3a7","declaration":"export function runChannelInboundEvent(params: RunChannelTurnParams): Promise>;\nexport function runChannelInboundEvent(params: ChannelInboundEventRunnerParams): Promise>;","entrypoint":"inbound-reply-dispatch","exportName":"runChannelInboundEvent","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} {"closureHash":"2c68496a174872b31aaf1ac8fad2789deb79d490c5ffbcb157325f1c95d1b51f","declaration":"export function runPreparedInboundReply(params: PreparedChannelTurn): Promise>;","entrypoint":"inbound-reply-dispatch","exportName":"runPreparedInboundReply","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} -{"closureHash":"f5d6c974980d1792af370a89adca4417174efdc8bf3b70e140fdfe21d1692cca","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"inbound-reply-dispatch","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"const","recordType":"export"} +{"closureHash":"16254799487aa48361f99ab341adad98738406e4af686ef50487780450c230fe","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"inbound-reply-dispatch","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"const","recordType":"export"} {"closureHash":"278dc8a410230012ddbc3552ec621a224e6f7c5dd4cd3904c943ac98dd4259e4","declaration":"export type AssembledInboundReply = AssembledChannelTurn;","entrypoint":"inbound-reply-dispatch","exportName":"AssembledInboundReply","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"} {"closureHash":"3de0d6d1bb8f9a83bd1c6e57aa8618e3fea71054236cd530c555e348bd0b7702","declaration":"export type ChannelBotLoopProtectionFacts = ChannelBotLoopProtectionFacts;","entrypoint":"inbound-reply-dispatch","exportName":"ChannelBotLoopProtectionFacts","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"} {"closureHash":"f0da845bbdf49b30f6718a4b7ff012a0536deb98f65418583555dc90825797ca","declaration":"export type ChannelInboundDroppedHistoryOptions = ChannelTurnDroppedHistoryOptions;","entrypoint":"inbound-reply-dispatch","exportName":"ChannelInboundDroppedHistoryOptions","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"} @@ -3189,19 +3189,19 @@ {"closureHash":"50394942e0a454c742e80a4f3c8739c80258b387ade498eb5aed66df887108be","declaration":"export function callMeetingBrowserProxyOnNode(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; } & MeetingBrowserRequestParams): Promise;","entrypoint":"meeting-runtime","exportName":"callMeetingBrowserProxyOnNode","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"c5fcd1d157edcb4773235adfaf8051e3ec7ca428cb7916b6d55f2511affab56c","declaration":"export function convertMeetingBridgeAudioForStt(audio: Buffer, audioFormat: MeetingRealtimeAudioFormat): Buffer;","entrypoint":"meeting-runtime","exportName":"convertMeetingBridgeAudioForStt","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"aa9063c27c5ff714d3653571c4a2a71e9d2eea5609b161f03e4738e15411358b","declaration":"export function convertMeetingTtsAudioForBridge(audio: Buffer, sampleRate: number, audioFormat: MeetingRealtimeAudioFormat, outputFormat?: string, platformName?: string): Buffer;","entrypoint":"meeting-runtime","exportName":"convertMeetingTtsAudioForBridge","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"c8f1a9163a69ca61d4f88f8129e5f23719f921e5245e060c7a6c77bfaae8c34a","declaration":"export function createLocalMeetingRealtimeAudioTransport(params: { inputCommand: string[]; outputCommand: string[]; bargeInInputCommand?: string[]; bargeInRmsThreshold: number; bargeInPeakThreshold: number; bargeInCooldownMs: number; logger: RuntimeLogger; logScope: string; audioFormat?: MeetingRealtimeAudioFormat; spawn?: MeetingRealtimeAudioSpawn; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createLocalMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"cc82f299f781157a633a599387ba8190b4f9163b031ea44cb27df50b0aeed48f","declaration":"export function createLocalMeetingRealtimeAudioTransport(params: { inputCommand: string[]; outputCommand: string[]; bargeInInputCommand?: string[]; bargeInRmsThreshold: number; bargeInPeakThreshold: number; bargeInCooldownMs: number; logger: RuntimeLogger; logScope: string; audioFormat?: MeetingRealtimeAudioFormat; spawn?: MeetingRealtimeAudioSpawn; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createLocalMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"9cb63eefd2e5a70aea960bf17fcf570ef02a2d7b5afd5ad9451802964c653fcf","declaration":"export function createMeetingBrowserNodeCaller(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; }): MeetingBrowserRequestCaller;","entrypoint":"meeting-runtime","exportName":"createMeetingBrowserNodeCaller","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"f244ca8c47f556c9f388953cf9a7581c7d4d413af93e0dfa1462779e6a687a7c","declaration":"export function createMeetingBrowserNodeInvokePolicy(options: MeetingBrowserNodePolicyOptions): OpenClawPluginNodeInvokePolicy;","entrypoint":"meeting-runtime","exportName":"createMeetingBrowserNodeInvokePolicy","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"1aa4e3ff39a2cbe162421c62b1fa4a362973381d4d9ff15c671249b1ebd566bc","declaration":"export function createMeetingNodeHost(options: MeetingNodeHostOptions): { handleCommand(paramsJSON?: string | null): Promise; };","entrypoint":"meeting-runtime","exportName":"createMeetingNodeHost","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"2493d5d6a3b2128c167ae4c42129ff96b2dddaac7c12c87fc442ff304b01ca3a","declaration":"export function createMeetingRealtimeEngineBindings(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { agentId?: string; toolPolicy: RealtimeVoiceAgentConsultToolPolicy; }; }; fullConfig: OpenClawConfig; runtime: PluginRuntime; logger: RuntimeLogger; }): { platform: MeetingRuntimePlatform; consultAgent: (consult: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (call: MeetingRealtimeToolCallParams) => Promise; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"6030bd4718a6362627f0388a624505ad6680512881e27c42a7792ec0d52f9d58","declaration":"export function createMeetingRealtimeEngineBindings(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { agentId?: string; toolPolicy: RealtimeVoiceAgentConsultToolPolicy; }; }; fullConfig: OpenClawConfig; runtime: PluginRuntime; logger: RuntimeLogger; }): { platform: MeetingRuntimePlatform; consultAgent: (consult: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (call: MeetingRealtimeToolCallParams) => Promise; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"9124db05923060c467edb149bd8abdc8be1d00d00f867cf84600972923a58489","declaration":"export function createMeetingSession(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { provider?: string; voiceProvider?: string; transcriptionProvider?: string; model?: string; toolPolicy: TToolPolicy; }; }; resolved: MeetingResolvedJoin; createdAt: string; }): MeetingSessionRecord;","entrypoint":"meeting-runtime","exportName":"createMeetingSession","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"fb276e07e395ab19177b3d7967fd0a8fcda79130883f15092a4a306b826481b9","declaration":"export function createMeetingSetupStatus(checks: MeetingSetupCheck[]): MeetingSetupStatus;","entrypoint":"meeting-runtime","exportName":"createMeetingSetupStatus","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"93c4bb70429a2739151e6f900e67bed81f3cd8f597811220e790341edb0d6008","declaration":"export function createMeetingVoiceCallGateway(params: { config: MeetingVoiceCallConfig; runtime: PluginRuntime; surface: MeetingVoiceCallSurface; connectClient: (params: { config: MeetingVoiceCallConfig; surface: MeetingVoiceCallSurface; }) => Promise; }): MeetingVoiceCallGateway;","entrypoint":"meeting-runtime","exportName":"createMeetingVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"cdf4e39ad1cf11a2826425997ccaea4ffedb057b543b355c375885891476bf23","declaration":"export function createNodeMeetingRealtimeAudioTransport(params: { runtime: PluginRuntime; nodeId: string; bridgeId: string; logger: RuntimeLogger; commandName: string; logScope: string; logPrefix: string; audioFormat?: MeetingRealtimeAudioFormat; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createNodeMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"e1c082dd9e7ecc190f8cbd1e9706e37a805d64a55ee7256f84f5d39dc2edaaf4","declaration":"export function createNodeMeetingRealtimeAudioTransport(params: { runtime: PluginRuntime; nodeId: string; bridgeId: string; logger: RuntimeLogger; commandName: string; logScope: string; logPrefix: string; audioFormat?: MeetingRealtimeAudioFormat; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createNodeMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"c0987b15a391a92d53d3e4e12b61eb122f9547fcf4f45478cdd3c5a8973a3e52","declaration":"export function endMeetingVoiceCallGatewayCall(params: { gateway: MeetingVoiceCallGateway; callId: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"endMeetingVoiceCallGatewayCall","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"b3ebc10fe7ab372e1317eaa8f78621cf277bba1e33fda57acf2254f6759d1e9d","declaration":"export function getMeetingVoiceCallGatewayCall(params: { gateway: MeetingVoiceCallGateway; callId: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"getMeetingVoiceCallGatewayCall","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"aac088df8e80d9ce89c45feccdb04ace3ae4417b3fcdd0f058410ddf25c96b46","declaration":"export function isMeetingVoiceCallMissingError(error: unknown): boolean;","entrypoint":"meeting-runtime","exportName":"isMeetingVoiceCallMissingError","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"337f14177df4f0a622be4d97495e99706782e43917ff560c5fbb439263f89457","declaration":"export function joinMeetingViaVoiceCallGateway(params: { config: MeetingVoiceCallConfig; gateway: MeetingVoiceCallGateway; surface: MeetingVoiceCallSurface; dialInNumber: string; dtmfSequence?: string; logger?: RuntimeLogger; message?: string; requesterSessionKey?: string; agentId?: string; sessionKey?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"59bf540846422a2078a247b42ea08bba1bf81b46b732a19180790f2a73568f11","declaration":"export function joinMeetingViaVoiceCallGateway(params: { config: MeetingVoiceCallConfig; gateway: MeetingVoiceCallGateway; surface: MeetingVoiceCallSurface; dialInNumber: string; dtmfSequence?: string; logger?: RuntimeLogger; message?: string; requesterSessionKey?: string; agentId?: string; sessionKey?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"bac9621cd025754fbcd4c21409b06eb0503405db81f35cac993aaf0b881ab3e1","declaration":"export function leaveMeetingWithBrowser(params: { adapter: BrowserAdapter; callBrowser: MeetingBrowserRequestCaller; launch: boolean; meetingSessionId?: string; meetingUrl: string; tab: MeetingBrowserTab; timeoutMs: number; }): Promise<{ left: boolean; note: string; }>;","entrypoint":"meeting-runtime","exportName":"leaveMeetingWithBrowser","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"c7b1aeac134b2070d053adf33026d876998b852ccd65cd2c9667119b1a1abee2","declaration":"export function openMeetingWithBrowser, Mode extends string, Health extends MeetingBrowserHealth & { browserTitle?: string; browserUrl?: string; notes?: string[]; }, Transcript extends MeetingTranscriptSnapshot>(params: { adapter: BrowserAdapter; callBrowser: MeetingBrowserRequestCaller; config: MeetingBrowserControllerConfig; session: Session; }): Promise<{ launched: boolean; browser?: Health; tab?: MeetingBrowserTab; }>;","entrypoint":"meeting-runtime","exportName":"openMeetingWithBrowser","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"34858979bd248799c2215d9c7bdd5d4a6b27660c9173bfca2e50dd4373ac27db","declaration":"export function readMeetingBrowserTab(result: unknown): MeetingBrowserCandidateTab | undefined;","entrypoint":"meeting-runtime","exportName":"readMeetingBrowserTab","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} @@ -3212,8 +3212,8 @@ {"closureHash":"56874c5b2ced5af647b1dff296c931f0d8b85b1318e98c741aa88b58a9c5c606","declaration":"export function resolveMeetingBrowserNodeInfo(params: { runtime: PluginRuntime; adapter: NodeAdapter; requestedNode?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"resolveMeetingBrowserNodeInfo","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"f21196c9ea8ab90248ffdcdef3e942f1247ee2b9064ddb9757fffe352362c779","declaration":"export function resolveMeetingRealtimeAudioFormat(audioFormat: MeetingRealtimeAudioFormat): RealtimeVoiceAudioFormat;","entrypoint":"meeting-runtime","exportName":"resolveMeetingRealtimeAudioFormat","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"521dc5c262524a709cdd27cdc88e95004073da8223537bcbc73d5d423172dc2b","declaration":"export function speakMeetingViaVoiceCallGateway(params: { gateway: MeetingVoiceCallGateway; callId: string; message: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"speakMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"318770156465bcaef766d607ed73d3d3ceea9a3d148c80980bed8da4d33ae94e","declaration":"export function startMeetingAgentRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeTranscriptionProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"90ca9e0ecea498d28aad6e0d5b1a098779002ff2229035ad43e7c6eae9411f23","declaration":"export function startMeetingRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; talkSessionId?: string; talkContext?: { nodeId: string; bridgeId: string; }; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeVoiceProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (params: MeetingRealtimeToolCallParams) => Promise; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"3130ab53a021c7e3f2970bf24e318a1f06ca09ea91d3c9bd51581bf39481d229","declaration":"export function startMeetingAgentRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeTranscriptionProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"b943ecbbcebec424120f28f33fb2f8b382d2ae91adad8fac853496bd2eed1984","declaration":"export function startMeetingRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; talkSessionId?: string; talkContext?: { nodeId: string; bridgeId: string; }; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeVoiceProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (params: MeetingRealtimeToolCallParams) => Promise; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"663b9c77231b21af697efd5042e22d1c33e9ee972adeb312ad86d81a2b2e36f7","declaration":"export type MeetingAgentConsultParams = MeetingAgentConsultParams;","entrypoint":"meeting-runtime","exportName":"MeetingAgentConsultParams","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"adf0745c611bf737fc28978d766fc2a25b7104e71b6b2fed4e9b95e519c7b115","declaration":"export type MeetingBrowserCandidateTab = MeetingBrowserCandidateTab;","entrypoint":"meeting-runtime","exportName":"MeetingBrowserCandidateTab","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"59b1526172b7491b85f14f13c1ee26d8d6726f33093770748580c767b1689a17","declaration":"export type MeetingBrowserControllerConfig = MeetingBrowserControllerConfig;","entrypoint":"meeting-runtime","exportName":"MeetingBrowserControllerConfig","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} @@ -3245,7 +3245,7 @@ {"closureHash":"8244b408803f57cf2004157e96f2ce11bb036cdf864123b15ba2fac7f03b5d43","declaration":"export type MeetingSessionRuntimeHandles = MeetingSessionRuntimeHandles;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeHandles","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"aa8054fc2c442891197e89bdad61e79999ea15d813c4b127fb6150607b9e67e7","declaration":"export type MeetingSessionRuntimeJoinContext, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab> = MeetingSessionRuntimeJoinContext;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeJoinContext","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"325241724edd38da439c5df03d225e2a7cb8e56d817e98ed7c37850656d3744b","declaration":"export type MeetingSessionRuntimeMessages = MeetingSessionRuntimeMessages;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeMessages","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} -{"closureHash":"bc3ec8d61eeca24b6d2d5d56b91479aed7c4e8bf0b7e86945a1eedc562a9e42e","declaration":"export type MeetingSessionRuntimeOptions, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeOptions","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} +{"closureHash":"8345dc18050019a013d34a7653ed0d12e6178bcc18dfdb52f85a05a46bbd4e22","declaration":"export type MeetingSessionRuntimeOptions, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeOptions","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"d3c730cba02d30512c4cdae6e2367c662982e2c25671833ecd8701283924c642","declaration":"export type MeetingSessionState = MeetingSessionState;","entrypoint":"meeting-runtime","exportName":"MeetingSessionState","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"2496931157bf64fdb16013172ab9c023e60c5f85b98f46a3ee9532ce58d636d6","declaration":"export type MeetingSetupCheck = MeetingSetupCheck;","entrypoint":"meeting-runtime","exportName":"MeetingSetupCheck","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"f0aed6f7955a43fc387d8bbc072cb6276b0f2d18e7f829441a2ad45974bb3831","declaration":"export type MeetingSetupStatus = MeetingSetupStatus;","entrypoint":"meeting-runtime","exportName":"MeetingSetupStatus","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} @@ -3259,9 +3259,9 @@ {"closureHash":"20c70a94483aeddda4d1500cfcc5e71fab844b474ba4061c55d6c8693d40821b","declaration":"export type MeetingVoiceCallJoinResult = MeetingVoiceCallJoinResult;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallJoinResult","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"4fb2c5928aa6f809dd4c604d71c5c99cdfe3e98b6e9c1662601c9b4ad9738162","declaration":"export type MeetingVoiceCallStatusResult = MeetingVoiceCallStatusResult;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallStatusResult","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"5ef812397b6409a4ca228943dd1080661365959477b42e705a9aaa219757d14f","declaration":"export type MeetingVoiceCallSurface = MeetingVoiceCallSurface;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallSurface","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} -{"closureHash":"647fd7d11823c5e1228d0cb75a7dfed96c63e16087f74f7dc6c48afaebaf417d","declaration":"export interface MeetingPlatformAdapter extends MeetingPlatformAdapterContract {\n}","entrypoint":"meeting-runtime","exportName":"MeetingPlatformAdapter","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"} +{"closureHash":"4eaf1fc1a9108206f22d89e18f61a55a34c7270419bd533692cb6106b0491dff","declaration":"export interface MeetingPlatformAdapter extends MeetingPlatformAdapterContract {\n}","entrypoint":"meeting-runtime","exportName":"MeetingPlatformAdapter","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"} {"closureHash":"79884bd1df1ea0d07d5ceb4c62d93c1ee744b75d31c94c988845869c0f3cbd2d","declaration":"export interface MeetingRealtimeAudioTransport {\n onFatal(handler: () => void): void;\n startInput(onAudio: (audio: Buffer) => void): void;\n beginOutput?(): void;\n stop(): Promise;\n writeOutput(audio: Buffer): Promise;\n clearOutput(): Promise;\n dispose(): Promise;\n getHealth?(): MeetingRealtimeAudioTransportHealth;\n startBargeInMonitor?(onBargeIn: (audio: Buffer) => boolean): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"} -{"closureHash":"d3d839a5d9a3361c282ff6d2713defc867be38fef32cb3e2731fcd4fbf6645a7","declaration":"export class MeetingSessionRuntime, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map;\n readonly #sessionLeaves: Map>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map Promise>;\n readonly #sessionSpeakers: Map void>;\n readonly #sessionHealth: Map Partial>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts;\n readonly #transcriptStore: MeetingSessionTranscriptStore;\n constructor(private readonly options: MeetingSessionRuntimeOptions);\n list(): TSession[];\n getSession(sessionId: string): TSession | undefined;\n async status(sessionId?: string): Promise<{\n found: boolean;\n session?: TSession;\n sessions?: TSession[];\n }>;\n async transcript(sessionId: string, options: {\n sinceIndex?: number;\n }): Promise<{ found: boolean; sessionId?: string; startIndex?: number; nextIndex?: number; droppedLines?: number; evicted?: boolean; lines?: MeetingTranscriptLine[]; }>;\n async startTranscriptSource(request: TranscriptStartRequest): Promise;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin): boolean;\n async join(request: TRequest): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async leave(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async speak(sessionId: string, instructions?: string): Promise<{\n found: boolean;\n spoken: boolean;\n session?: TSession;\n }>;\n async speakWhenReady(session: TSession, instructions: string): Promise;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise;\n async refreshCaptionHealth(session: TSession): Promise;\n refreshSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n markSessionEnded(session: TSession, reason: string): void;\n async #joinUnlocked(request: TRequest, resolved: MeetingResolvedJoin): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n #meetingKey(transport: TTransport, url: string): string;\n #inheritBrowserTabOwnership(params: {\n session: TSession;\n transport: TTransport;\n nodeId?: string;\n meetingUrl: string;\n tab?: TTab;\n }): TTab | undefined;\n async #settleRetainedBrowserTabs(retained: Array<{\n session: TSession;\n tab: TTab;\n }>, adopted?: {\n transport: TTransport;\n nodeId?: string;\n tab: TTab;\n }): Promise;\n async #rollbackFailedJoinSession(session: TSession): Promise;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles): void;\n #dropRuntimeHandles(sessionId: string): void;\n #isManagedBrowserSession(session: TSession): boolean;\n #evaluateSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n #noteSession(session: TSession, note: string): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"class","recordType":"export"} +{"closureHash":"42723d088f7aacd0105697bace2776af0f0b6634c40183ad06a24f563ecca26f","declaration":"export class MeetingSessionRuntime, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map;\n readonly #sessionLeaves: Map>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map Promise>;\n readonly #sessionSpeakers: Map void>;\n readonly #sessionHealth: Map Partial>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts;\n readonly #transcriptStore: MeetingSessionTranscriptStore;\n constructor(private readonly options: MeetingSessionRuntimeOptions);\n list(): TSession[];\n getSession(sessionId: string): TSession | undefined;\n async status(sessionId?: string): Promise<{\n found: boolean;\n session?: TSession;\n sessions?: TSession[];\n }>;\n async transcript(sessionId: string, options: {\n sinceIndex?: number;\n }): Promise<{ found: boolean; sessionId?: string; startIndex?: number; nextIndex?: number; droppedLines?: number; evicted?: boolean; lines?: MeetingTranscriptLine[]; }>;\n async startTranscriptSource(request: TranscriptStartRequest): Promise;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin): boolean;\n async join(request: TRequest): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async leave(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async speak(sessionId: string, instructions?: string): Promise<{\n found: boolean;\n spoken: boolean;\n session?: TSession;\n }>;\n async speakWhenReady(session: TSession, instructions: string): Promise;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise;\n async refreshCaptionHealth(session: TSession): Promise;\n refreshSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n markSessionEnded(session: TSession, reason: string): void;\n async #joinUnlocked(request: TRequest, resolved: MeetingResolvedJoin): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n #meetingKey(transport: TTransport, url: string): string;\n #inheritBrowserTabOwnership(params: {\n session: TSession;\n transport: TTransport;\n nodeId?: string;\n meetingUrl: string;\n tab?: TTab;\n }): TTab | undefined;\n async #settleRetainedBrowserTabs(retained: Array<{\n session: TSession;\n tab: TTab;\n }>, adopted?: {\n transport: TTransport;\n nodeId?: string;\n tab: TTab;\n }): Promise;\n async #rollbackFailedJoinSession(session: TSession): Promise;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles): void;\n #dropRuntimeHandles(sessionId: string): void;\n #isManagedBrowserSession(session: TSession): boolean;\n #evaluateSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n #noteSession(session: TSession, note: string): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"class","recordType":"export"} {"category":null,"entrypoint":"memory-core-host-engine-foundation","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","recordType":"module"} {"closureHash":"e2df8d235401aebf58eb71652fbeaedb42ca00aaa5042a76909ff2c48ba6fd54","declaration":"export function createSubsystemLogger(subsystem: string): SubsystemLogger;","entrypoint":"memory-core-host-engine-foundation","exportName":"createSubsystemLogger","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"function","recordType":"export"} {"closureHash":null,"declaration":"export function isPathInside(root: string, target: string): boolean;","entrypoint":"memory-core-host-engine-foundation","exportName":"isPathInside","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"function","recordType":"export"} @@ -3388,9 +3388,9 @@ {"category":"core","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","recordType":"module"} {"closureHash":"3d27406644141af2733cfca6e8c1240fc62327910109f585ce9073cafd7fd89c","declaration":"export function buildJsonPluginConfigSchema(schema: JsonSchemaObject, options?: BuildJsonPluginConfigSchemaOptions): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"buildJsonPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} {"closureHash":"aff66c792d532642afb9c6e5a03c8d220f219250c3a8b49733f32058f22f98ca","declaration":"export function buildPluginConfigSchema(schema: ZodTypeAny, options?: BuildPluginConfigSchemaOptions): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"buildPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} -{"closureHash":"0e3a6175467adf8ff674c52bb0ae1af57d2e52f33448416e5d11b4eca1685baf","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} +{"closureHash":"a4f0792ef70bd2b09bf37e9c37943284c8f93b82bd3864cf6f3739033c2878a6","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} {"closureHash":"0ef1dfa3b5deeb456480e292c0e835c3cd6d13e7bb7059fc735546507da51594","declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} -{"closureHash":"e75e94d131237b4b73c507cad9f2a0940716404531516861497e92ba8d06fb87","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"plugin-entry","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"71e57b87ff6cba595cc4513f2fd68742eb69a234d17e328c6cc6761eec04385e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"plugin-entry","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"d2ff4de9ee3fd111c2cc64a3ee7e557d9f161af1b6b437ee7886bcb16e426317","declaration":"export type AgentPromptGuidance = AgentPromptGuidance;","entrypoint":"plugin-entry","exportName":"AgentPromptGuidance","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"2841127a90e04467adfea8126cbf03655f44ddb089ad9e0d48833c2beea39cbd","declaration":"export type AgentPromptGuidanceEntry = AgentPromptGuidanceEntry;","entrypoint":"plugin-entry","exportName":"AgentPromptGuidanceEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"aa0412acefe62caff12e5271ead0545504874e824380dc21cfc0566388a05f33","declaration":"export type AgentPromptSurfaceKind = \"openclaw_main\" | \"pi_main\" | \"codex_app_server\" | \"cli_backend\" | \"acp_backend\" | \"subagent\";","entrypoint":"plugin-entry","exportName":"AgentPromptSurfaceKind","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} @@ -3406,10 +3406,10 @@ {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"plugin-entry","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"2f6e368fff73e942044cdf95c7c751b46c741e22ac0d2d4d97f45a3158f758ae","declaration":"export type OpenClawGatewayDiscoveryAdvertiseContext = OpenClawGatewayDiscoveryAdvertiseContext;","entrypoint":"plugin-entry","exportName":"OpenClawGatewayDiscoveryAdvertiseContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"b198058e0065e5c60b729a5bdf568f7e2436a006d8c4a7c63de764c7283f96ba","declaration":"export type OpenClawGatewayDiscoveryService = OpenClawGatewayDiscoveryService;","entrypoint":"plugin-entry","exportName":"OpenClawGatewayDiscoveryService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"fb4fde629072c35c7afe2f3248520c284b439596eb2e25c136b6494b402cee1f","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"b9c63a41b3da754e29aee2040c6b79300801cb59b95dcedf8032f404cd0c9a8d","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"69fefc8092c1cea366c48505c8423ff0f8f995caef3d259d177346b1687541aa","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"365beb5cee974639c2f35fc7a39088721ca8e9c618442830298b98033e9c768c","declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"c8efb9154eafc9061e7b6bf41fd001a4c2b38e0645d6382ad9e493d3f12a3664","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"2614b3215fe42678ee92b6d077aaf2ddea54294b486b5bc3dbffde10cff679ac","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"a7ed83f0924f818b23cecb5a1f3591ff28b9499ccac9667a2b8505c2bc608ea9","declaration":"export type OpenClawPluginGatewayEventScope = OpenClawPluginGatewayEventScope;","entrypoint":"plugin-entry","exportName":"OpenClawPluginGatewayEventScope","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"f81f224d9b837e6353b7a546c5a76b124bcf568fd1f1fd0c6881fda30c53120a","declaration":"export type OpenClawPluginGatewayEvents = OpenClawPluginGatewayEvents;","entrypoint":"plugin-entry","exportName":"OpenClawPluginGatewayEvents","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"7470b211ac4d3449cd0fc353ee2eb48e9fbc2dbc9259d21c680d0203577aa94f","declaration":"export type OpenClawPluginHttpRouteHandler = OpenClawPluginHttpRouteHandler;","entrypoint":"plugin-entry","exportName":"OpenClawPluginHttpRouteHandler","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} @@ -3558,14 +3558,14 @@ {"closureHash":"5e57188ea41861c5108f8a07d6a2a1902ced52b5f1708a70d702dc4ba3ce5e0b","declaration":"export function executePluginCommand(params: { command: RegisteredPluginCommand; args?: string; senderId?: string; channel: string; channelId?: PluginCommandContext[\"channelId\"]; isAuthorizedSender: boolean; senderIsOwner?: boolean; gatewayClientScopes?: PluginCommandContext[\"gatewayClientScopes\"]; agentId?: string; sessionKey?: PluginCommandContext[\"sessionKey\"]; sessionId?: PluginCommandContext[\"sessionId\"]; sessionTarget?: PluginCommandContext[\"sessionTarget\"]; sessionFile?: PluginCommandContext[\"sessionFile\"]; authProfileId?: string; commandBody: string; config: OpenClawConfig; from?: PluginCommandContext[\"from\"]; to?: PluginCommandContext[\"to\"]; originatingTo?: string; accountId?: PluginCommandContext[\"accountId\"]; messageThreadId?: PluginCommandContext[\"messageThreadId\"]; threadParentId?: PluginCommandContext[\"threadParentId\"]; diagnosticsSessions?: PluginCommandContext[\"diagnosticsSessions\"]; diagnosticsUploadApproved?: PluginCommandContext[\"diagnosticsUploadApproved\"]; diagnosticsPreviewOnly?: PluginCommandContext[\"diagnosticsPreviewOnly\"]; diagnosticsPrivateRouted?: PluginCommandContext[\"diagnosticsPrivateRouted\"]; }): Promise;","entrypoint":"plugin-runtime","exportName":"executePluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"7e75fc04d621dc8d12f459d5b5b0c039a39b77c30c2b51af481e123c352f57b8","declaration":"export function getGlobalHookRunner(): HookRunner | null;","entrypoint":"plugin-runtime","exportName":"getGlobalHookRunner","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"db6583607237e4081814e2c5d4f8fb6f216ad3bbfe623bf16fc1a9c09c15f64b","declaration":"export function getPluginCommandSpecs(provider?: string, options?: PluginCommandSpecOptions): Array<{ name: string; description: string; descriptionLocalizations?: Record; acceptsArgs: boolean; }>;","entrypoint":"plugin-runtime","exportName":"getPluginCommandSpecs","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} -{"closureHash":"e9dd89081dbc3593fa3f2db4c3aa9b09a87f04b30f77e5e9f9ea85e6338a6af9","declaration":"export function getPluginRuntimeGatewayRequestScope(): PluginRuntimeGatewayRequestScope | undefined;","entrypoint":"plugin-runtime","exportName":"getPluginRuntimeGatewayRequestScope","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} +{"closureHash":"6ac38086644eb07b191025bb303de3621cb9f801ecc1a11dd06a9896c0c9815d","declaration":"export function getPluginRuntimeGatewayRequestScope(): PluginRuntimeGatewayRequestScope | undefined;","entrypoint":"plugin-runtime","exportName":"getPluginRuntimeGatewayRequestScope","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"cfe277ce6de0c6ed50f1f54b66c889f6c95e91b058e8bcdc27aa37317a93a447","declaration":"export function listRegisteredPluginAgentPromptGuidance(params?: { surface?: AgentPromptSurfaceKind; includeLegacyGlobalGuidance?: boolean; }): string[];","entrypoint":"plugin-runtime","exportName":"listRegisteredPluginAgentPromptGuidance","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"ef4872995ac1acbe1b2046397e3ddc5d9a4315cb0bd0dfddfac6222418e7c048","declaration":"export function matchPluginCommand(commandBody: string, options?: { channel?: string; }): { command: RegisteredPluginCommand; args?: string; } | null;","entrypoint":"plugin-runtime","exportName":"matchPluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"e02d3651398ab23c38e91a52fc1502e7a97490f17047b4f558b87c94731b0344","declaration":"export function registerPluginCommand(pluginId: string, command: OpenClawPluginCommandDefinition, opts?: { pluginName?: string; pluginRoot?: string; allowReservedCommandNames?: boolean; allowOwnerStatusExposure?: boolean; }): CommandRegistrationResult;","entrypoint":"plugin-runtime","exportName":"registerPluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"16986e5d431f584c2d5053289eca3d2225bbe47a92cdfbbc2af91b264a165846","declaration":"export function registerPluginInteractiveHandler(pluginId: string, registration: PluginInteractiveHandlerRegistration, opts?: { pluginName?: string; pluginRoot?: string; }): InteractiveRegistrationResult;","entrypoint":"plugin-runtime","exportName":"registerPluginInteractiveHandler","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"f20c07a48e2c949fbc889e7a32760f4e52339d9f6d3eab49e00ff249266e2396","declaration":"export function startLazyPluginServiceModule(params: { skipEnvVar?: string; overrideEnvVar?: string; validateOverrideSpecifier?: (specifier: string) => string; loadDefaultModule: () => Promise; loadOverrideModule?: (specifier: string) => Promise; startExportNames: string[]; stopExportNames?: string[]; }): Promise;","entrypoint":"plugin-runtime","exportName":"startLazyPluginServiceModule","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"bad43ffe69d1d9d6c92c79df4c388b3dda685013a92392daef456f1622ade659","declaration":"export type LazyPluginServiceHandle = LazyPluginServiceHandle;","entrypoint":"plugin-runtime","exportName":"LazyPluginServiceHandle","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} -{"closureHash":"fb4fde629072c35c7afe2f3248520c284b439596eb2e25c136b6494b402cee1f","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-runtime","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} +{"closureHash":"b9c63a41b3da754e29aee2040c6b79300801cb59b95dcedf8032f404cd0c9a8d","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-runtime","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"365beb5cee974639c2f35fc7a39088721ca8e9c618442830298b98033e9c768c","declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-runtime","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"f06379ada10ce0eca4e66bdf978db2c0035e054a135dc044c6d831ac7797c08f","declaration":"export type PluginConversationBinding = PluginConversationBinding;","entrypoint":"plugin-runtime","exportName":"PluginConversationBinding","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"a1223d674b2b66918a576ae05b04318d7b8cbe9b1d3bc6dd7a08d1a4fa79b291","declaration":"export type PluginConversationBindingRequestParams = PluginConversationBindingRequestParams;","entrypoint":"plugin-runtime","exportName":"PluginConversationBindingRequestParams","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} @@ -3655,10 +3655,10 @@ {"closureHash":"e66adcb55dec79be73a52bc76594b7e9210fd93c69a85b56098fbb58cecbb354","declaration":"export type WriteOAuthCredentialsOptions = WriteOAuthCredentialsOptions;","entrypoint":"provider-auth","exportName":"WriteOAuthCredentialsOptions","importSpecifier":"openclaw/plugin-sdk/provider-auth","kind":"type","recordType":"export"} {"category":null,"entrypoint":"provider-catalog-runtime","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","recordType":"module"} {"closureHash":"b5665596a3f011454a5614681513516acd50b6c749536c43842d811980cf7ad3","declaration":"export function augmentModelCatalogWithProviderPlugins(params: { config?: OpenClawConfig; workspaceDir?: string; env?: NodeJS.ProcessEnv; metadataSnapshot?: PluginMetadataSnapshot; context: ProviderAugmentModelCatalogContext; }): Promise;","entrypoint":"provider-catalog-runtime","exportName":"augmentModelCatalogWithProviderPlugins","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"94876118e27fd3a011c350765bc51c045da727a430bf560b76b13c36815e2a21","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"baabd4ac04b433e27916ad3bfeee5a95952afce9e0685ae5acf3b7dceea69507","declaration":"export function resolveCatalogHookProviderPluginIds(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; metadataSnapshot?: ProviderManifestLoadParams[\"metadataSnapshot\"]; }): string[];","entrypoint":"provider-catalog-runtime","exportName":"resolveCatalogHookProviderPluginIds","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"c21aedf5df214eee9f68930c1aaeef0b9ef5ec66df0a09dc9db095aa1764bd58","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"37b37fd3da65fed3572a4e2d9784e79a338a26b85cacd87039c4741cfb41b07b","declaration":"export function resolvePluginProviders(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; bundledProviderVitestCompat?: boolean; onlyPluginIds?: string[]; providerRefs?: readonly string[]; modelRefs?: readonly string[]; activate?: boolean; cache?: boolean; applyAutoEnable?: boolean; pluginSdkResolution?: PluginLoadOptions[\"pluginSdkResolution\"]; mode?: \"runtime\" | \"setup\"; includeUntrustedWorkspacePlugins?: boolean; pluginMetadataSnapshot?: PluginMetadataRegistryView; skipIfLoadInFlight?: boolean; }): ProviderPlugin[];","entrypoint":"provider-catalog-runtime","exportName":"resolvePluginProviders","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"77aaebb98084205149391d11ef31ffa8a2f29a42271a5f0b47e97e101d581c8c","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"33a282a2bcfe6babd26520c27b40d86b143d487b044fa25adb696b621f099685","declaration":"export function resolveCatalogHookProviderPluginIds(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; metadataSnapshot?: ProviderManifestLoadParams[\"metadataSnapshot\"]; }): string[];","entrypoint":"provider-catalog-runtime","exportName":"resolveCatalogHookProviderPluginIds","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"3932fb64965f1f19ca12606778b78bb13beab0fd953b7b4025f84edb91c68206","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"35714460e5a066deaceac3617abe4a955bdb14e563c1e76412d65ef9da774e83","declaration":"export function resolvePluginProviders(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; bundledProviderVitestCompat?: boolean; onlyPluginIds?: string[]; providerRefs?: readonly string[]; modelRefs?: readonly string[]; activate?: boolean; cache?: boolean; applyAutoEnable?: boolean; pluginSdkResolution?: PluginLoadOptions[\"pluginSdkResolution\"]; mode?: \"runtime\" | \"setup\"; includeUntrustedWorkspacePlugins?: boolean; pluginMetadataSnapshot?: PluginMetadataRegistryView; skipIfLoadInFlight?: boolean; }): ProviderPlugin[];","entrypoint":"provider-catalog-runtime","exportName":"resolvePluginProviders","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} {"category":null,"entrypoint":"proxy-capture","importSpecifier":"openclaw/plugin-sdk/proxy-capture","recordType":"module"} {"closureHash":"d0e4e026d736bc00b1758d1089c44c3c5f3a09c7254291584de8cb297365804c","declaration":"export function acquireDebugProxyCaptureStore(dbPath: string, blobDir: string): { store: LegacyDebugProxyCaptureStore; release: () => void; };\nexport function acquireDebugProxyCaptureStore(options?: DebugProxyCaptureStoreOptions): { store: SharedDebugProxyCaptureStore; release: () => void; };","entrypoint":"proxy-capture","exportName":"acquireDebugProxyCaptureStore","importSpecifier":"openclaw/plugin-sdk/proxy-capture","kind":"function","recordType":"export"} {"closureHash":"d41cbb9de51b7aee1c6cf8c713b0bc44f27ac926fbb6422c05726f196d11964e","declaration":"export function captureHttpExchange(params: { url: string; method: string; requestHeaders?: Headers | Record | undefined; requestBody?: BodyInit | Buffer | string | null; response: Response; transport?: \"http\" | \"sse\"; flowId?: string; meta?: Record; }, resolved?: DebugProxySettings, deps?: DebugProxyCaptureRuntimeDeps): void;","entrypoint":"proxy-capture","exportName":"captureHttpExchange","importSpecifier":"openclaw/plugin-sdk/proxy-capture","kind":"function","recordType":"export"} @@ -4620,16 +4620,16 @@ {"closureHash":"e365d7ad911453b5139ba700931b061e560cff80b50d4cbe5e9615b5d7e13a52","declaration":"export type ScopedExpiringIdCache = ScopedExpiringIdCache;","entrypoint":"text-runtime","exportName":"ScopedExpiringIdCache","importSpecifier":"openclaw/plugin-sdk/text-runtime","kind":"type","recordType":"export"} {"closureHash":"af5502c92594c2e9049a4b4994e17c00d3adee3f6d1e68edd818a539c74c8787","declaration":"export interface CodeRegion {\n start: number;\n end: number;\n}","entrypoint":"text-runtime","exportName":"CodeRegion","importSpecifier":"openclaw/plugin-sdk/text-runtime","kind":"interface","recordType":"export"} {"category":null,"entrypoint":"tool-plugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin","recordType":"module"} -{"closureHash":"f26f6685ad31a4537184db05b259bef8d78bc3501b70f7ec1e47beda686a7bb2","declaration":"export function defineToolPlugin(definition: DefineToolPluginOptions): DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"defineToolPlugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"function","recordType":"export"} +{"closureHash":"bf00fd6de784c5fb00679a000d469fb50e1f18a72969292bf854e183852b719b","declaration":"export function defineToolPlugin(definition: DefineToolPluginOptions): DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"defineToolPlugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"function","recordType":"export"} {"closureHash":"36ef907ce20f885b5f3068cbf0475dc442a68da9652579bb5bf8fb83ad34c38b","declaration":"export function getToolPluginMetadata(entry: unknown): ToolPluginMetadata | undefined;","entrypoint":"tool-plugin","exportName":"getToolPluginMetadata","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"function","recordType":"export"} {"closureHash":"bdc58154e36b2625fb3daccca3eab248d981077d04d747f0ad507cb2ff565198","declaration":"export const toolPluginMetadataSymbol: typeof toolPluginMetadataSymbol;","entrypoint":"tool-plugin","exportName":"toolPluginMetadataSymbol","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"const","recordType":"export"} -{"closureHash":"b50a3bde4f3d253d2096b9e2b626836024852e8839598169e92baadcb356b15a","declaration":"export type DefineToolPluginOptions = DefineToolPluginOptions;","entrypoint":"tool-plugin","exportName":"DefineToolPluginOptions","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"d4e2d9bd9e458ac4d17c8dcaa0d241398a9eaca9733c95c89fbb8e6d8cfa5325","declaration":"export type DefinedToolPluginEntry = DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"DefinedToolPluginEntry","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"6bad0c83f5fc9f0c47fe985a7fff2886edd0ee6e832ba29aeb57828d64f4d267","declaration":"export type ToolPluginExecutionContext = ToolPluginExecutionContext;","entrypoint":"tool-plugin","exportName":"ToolPluginExecutionContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"2bb77f487dcd21094e6ced1e7dcec12bd89a4fce580fe129ad07cbf55eb74c6a","declaration":"export type ToolPluginFactoryContext = ToolPluginFactoryContext;","entrypoint":"tool-plugin","exportName":"ToolPluginFactoryContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"68f0e8143972deac8790ce2848dcd32cff726dcdf12b6ff06ddcc468616c4fad","declaration":"export type DefineToolPluginOptions = DefineToolPluginOptions;","entrypoint":"tool-plugin","exportName":"DefineToolPluginOptions","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"6bc77664b7b686d12de72ac99dc2fa28c5dfa8ad51ea71d807d86f04dd06402a","declaration":"export type DefinedToolPluginEntry = DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"DefinedToolPluginEntry","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"549a9c7e0542a3cd423b640f655906849da3e1cb54d5c306009b218ed52bef15","declaration":"export type ToolPluginExecutionContext = ToolPluginExecutionContext;","entrypoint":"tool-plugin","exportName":"ToolPluginExecutionContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"bc673018ec3efc5797a01f9786263a24eccdf0eddb857ddb6e967dff3a2d3c4d","declaration":"export type ToolPluginFactoryContext = ToolPluginFactoryContext;","entrypoint":"tool-plugin","exportName":"ToolPluginFactoryContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} {"closureHash":"f774bd092f51a31fbb34847213f9583234f585f66918d0af55e81bbbae40463b","declaration":"export type ToolPluginMetadata = ToolPluginMetadata;","entrypoint":"tool-plugin","exportName":"ToolPluginMetadata","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} {"closureHash":"414a89d0c80eaaf682dc25d306e7223c981c6fd25366adb973a106f4268a6a54","declaration":"export type ToolPluginStaticToolMetadata = ToolPluginStaticToolMetadata;","entrypoint":"tool-plugin","exportName":"ToolPluginStaticToolMetadata","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"3b13d82cf0d5c6358ff9b1c182ade424886c2806387ecdb5b7ad96cd7801ff3c","declaration":"export type ToolPluginToolDefinition = ToolPluginToolDefinition;","entrypoint":"tool-plugin","exportName":"ToolPluginToolDefinition","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"6304d369f4a05607a4e5a9631c757956f5387f0efdfc3984ac3331915b9a9ccf","declaration":"export type ToolPluginToolDefinition = ToolPluginToolDefinition;","entrypoint":"tool-plugin","exportName":"ToolPluginToolDefinition","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} {"category":null,"entrypoint":"tool-results","importSpecifier":"openclaw/plugin-sdk/tool-results","recordType":"module"} {"closureHash":"c5b0951c3629834dff78f92317cf1421a6bbc0faf9307be1cabb915055665280","declaration":"export function jsonResult(payload: TDetails): AgentToolResult;","entrypoint":"tool-results","exportName":"jsonResult","importSpecifier":"openclaw/plugin-sdk/tool-results","kind":"function","recordType":"export"} {"closureHash":"b9aefc637a694c74e028e92006004bef18185ed569af48ac43d36b646b0af2f3","declaration":"export function textResult(text: string, details: TDetails): AgentToolResult;","entrypoint":"tool-results","exportName":"textResult","importSpecifier":"openclaw/plugin-sdk/tool-results","kind":"function","recordType":"export"} @@ -4663,9 +4663,9 @@ {"closureHash":"9f9174f1023a8a451232f5d97d1e922b7faa88b76b58cffbfbe246a1488e0ddd","declaration":"export function readJsonWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse; maxBytes?: number; timeoutMs?: number; profile?: WebhookBodyReadProfile; emptyObjectOnEmpty?: boolean; invalidJsonMessage?: string; }): Promise<{ ok: true; value: unknown; } | { ok: false; }>;","entrypoint":"webhook-ingress","exportName":"readJsonWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"1bbddd5d1c8297e315275db4d5e1c8748ff09c0be7c37b0cf456db4fc69f8909","declaration":"export function readRequestBodyWithLimit(req: IncomingMessage, options: ReadRequestBodyOptions): Promise;","entrypoint":"webhook-ingress","exportName":"readRequestBodyWithLimit","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"e8a1174cac83ce346a231fd25e82bb5f7618ffb57cdd9af6eaa208411f70646d","declaration":"export function readWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse; maxBytes?: number; timeoutMs?: number; profile?: WebhookBodyReadProfile; invalidBodyMessage?: string; }): Promise<{ ok: true; value: string; } | { ok: false; }>;","entrypoint":"webhook-ingress","exportName":"readWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} -{"closureHash":"3abffbfcb38d18170a05d42b16be25b736f400980aa67c26a77702434576f8d6","declaration":"export function registerPluginHttpRoute(params: { path?: string | null; fallbackPath?: string | null; handler: PluginHttpRouteHandler; auth: PluginHttpRouteRegistration[\"auth\"]; match?: PluginHttpRouteRegistration[\"match\"]; gatewayRuntimeScopeSurface?: PluginHttpRouteRegistration[\"gatewayRuntimeScopeSurface\"]; replaceExisting?: boolean; reuseExistingSameOwner?: boolean; throwOnFailure?: boolean; pluginId?: string; source?: string; accountId?: string; log?: (message: string) => void; registry?: PluginRegistry; }): () => void;","entrypoint":"webhook-ingress","exportName":"registerPluginHttpRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} +{"closureHash":"61e4874e70d24a93651b78454fa1190f5c0a1e1683e648f63333ef37ba9c1365","declaration":"export function registerPluginHttpRoute(params: { path?: string | null; fallbackPath?: string | null; handler: PluginHttpRouteHandler; auth: PluginHttpRouteRegistration[\"auth\"]; match?: PluginHttpRouteRegistration[\"match\"]; gatewayRuntimeScopeSurface?: PluginHttpRouteRegistration[\"gatewayRuntimeScopeSurface\"]; replaceExisting?: boolean; reuseExistingSameOwner?: boolean; throwOnFailure?: boolean; pluginId?: string; source?: string; accountId?: string; log?: (message: string) => void; registry?: PluginRegistry; }): () => void;","entrypoint":"webhook-ingress","exportName":"registerPluginHttpRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"05835f2f66f906f736b82b332a84a9714bc3a6b211890a62d8fc4dbf9258a7d4","declaration":"export function registerWebhookTarget(targetsByPath: Map, target: T, opts?: RegisterWebhookTargetOptions): RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"registerWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} -{"closureHash":"ffe4d07bee504fb97a834400f1cf0de4ccc0ffc95b51b1f571bc16627407174d","declaration":"export function registerWebhookTargetWithPluginRoute(params: { targetsByPath: Map; target: T; route: RegisterWebhookPluginRouteOptions; onLastPathTargetRemoved?: RegisterWebhookTargetOptions[\"onLastPathTargetRemoved\"]; }): RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"registerWebhookTargetWithPluginRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} +{"closureHash":"cd5965420fb37544c6a32e98232b117c8fd2074aca149daffacff656a782e60f","declaration":"export function registerWebhookTargetWithPluginRoute(params: { targetsByPath: Map; target: T; route: RegisterWebhookPluginRouteOptions; onLastPathTargetRemoved?: RegisterWebhookTargetOptions[\"onLastPathTargetRemoved\"]; }): RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"registerWebhookTargetWithPluginRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"ec2f47e9bd7a075a3dd4302ac9e4c0bfe20630445db6735cf803f2d354275841","declaration":"export function requestBodyErrorToText(code: RequestBodyLimitErrorCode): string;","entrypoint":"webhook-ingress","exportName":"requestBodyErrorToText","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"5e1f3b468d56eb0f82104184077fdf4b6bd0c1444aa10b71a65fcaa2ec0298a2","declaration":"export function resolveRequestClientIp(req?: IncomingMessage, trustedProxies?: string[], allowRealIpFallback?: boolean): string | undefined;","entrypoint":"webhook-ingress","exportName":"resolveRequestClientIp","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"56c3e9868dfa6ee2a7a128eb02039a16b52696759adadbd3fe0a3bd7a6a07eeb","declaration":"export function resolveSingleWebhookTarget(targets: readonly T[], isMatch: (target: T) => boolean): WebhookTargetMatchResult;","entrypoint":"webhook-ingress","exportName":"resolveSingleWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} @@ -4683,7 +4683,7 @@ {"closureHash":"efb74e84339c15d6f607b38d1d477b0504d47d04ae78e77083a1893c756a0b54","declaration":"export const WEBHOOK_RATE_LIMIT_DEFAULTS: Readonly<{ windowMs: 60000; maxRequests: 120; maxTrackedKeys: 4096;}>;","entrypoint":"webhook-ingress","exportName":"WEBHOOK_RATE_LIMIT_DEFAULTS","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"const","recordType":"export"} {"closureHash":"13b28ec9acae43c3bdcd683b9831154f88118dee8142e42b7eebfd59f08c602c","declaration":"export type BoundedCounter = BoundedCounter;","entrypoint":"webhook-ingress","exportName":"BoundedCounter","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"9e737ae8c17038ef7becbd2bf1b756cfeaed571e2ded368c0fe3a446ebd1f666","declaration":"export type FixedWindowRateLimiter = FixedWindowRateLimiter;","entrypoint":"webhook-ingress","exportName":"FixedWindowRateLimiter","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} -{"closureHash":"9e6c519882ad4d8c8be55237efb109352dd2c39c8dfe17a8e874a77905ceba96","declaration":"export type RegisterWebhookPluginRouteOptions = RegisterWebhookPluginRouteOptions;","entrypoint":"webhook-ingress","exportName":"RegisterWebhookPluginRouteOptions","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} +{"closureHash":"63f32cd8136d7ae5eb5d5a81e0a22cc20c8f90c8717b4a83f6931255a1d44b16","declaration":"export type RegisterWebhookPluginRouteOptions = RegisterWebhookPluginRouteOptions;","entrypoint":"webhook-ingress","exportName":"RegisterWebhookPluginRouteOptions","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"b3e98619854462acfac6538ac9a2d0cefb88704a0eac712563f0996b07364152","declaration":"export type RegisterWebhookTargetOptions = RegisterWebhookTargetOptions;","entrypoint":"webhook-ingress","exportName":"RegisterWebhookTargetOptions","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"964c2bfd8f268c411ee7b982c9de02c207f4bec402dd62c9f998a59752bb9d1f","declaration":"export type RegisteredWebhookTarget = RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"RegisteredWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"aa552e5bdaefc9eb94d3b5a5cdf8c413fad555d9f452c6a2a6af5a3ce695c9d1","declaration":"export type WebhookAnomalyTracker = WebhookAnomalyTracker;","entrypoint":"webhook-ingress","exportName":"WebhookAnomalyTracker","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} diff --git a/docs/plugins/sdk-channel-plugins.md b/docs/plugins/sdk-channel-plugins.md index d79ea2aa2e14..b31b79e4c643 100644 --- a/docs/plugins/sdk-channel-plugins.md +++ b/docs/plugins/sdk-channel-plugins.md @@ -870,6 +870,19 @@ unrelated inbound runtime helpers. For channels that accept both canonical top-level DM keys and legacy nested keys, use the helpers from `plugin-sdk/channel-config-helpers`: `resolveChannelDmAccess`, `resolveChannelDmPolicy`, `resolveChannelDmAllowFrom`, and `normalizeChannelDmPolicy` keep account-local values ahead of inherited root values. Pair the same resolver with doctor repair through `normalizeLegacyDmAliases` so runtime and migration read the same contract. + If a channel intentionally applies stricter DM session routing than the + global config, expose that behavior through `security.dmRouting` so Doctor + and security audit resolve the same session owner as runtime. The optional + `resolveDmScope` callback runs before core route resolution; its context + includes `cfg`, `accountId`, the resolved `account`, and a `principalId` + for finite allowlist entries. `resolveDmRoute` receives those fields plus + the resolved core `route`; it may return `{ sessionKey }` for a shared final + bucket, `{ kind: "isolated" }` for an unknown peer, or `{ kind: "core" }` + to preserve core `dmScope` namespace analysis. For wildcard/open policy, + `principalId` is absent and an undefined result is reported as unverified. + Diagnostics never invent a peer ID. Keep both callbacks pure and + import-safe because read-only diagnostics run without channel runtime. + Instead of implementing low-level adapter interfaces manually, you pass declarative options and the builder composes them: diff --git a/extensions/telegram/api.ts b/extensions/telegram/api.ts index 909ad990158b..48fb66cd3a02 100644 --- a/extensions/telegram/api.ts +++ b/extensions/telegram/api.ts @@ -51,7 +51,6 @@ export { isBinaryContent, normalizeForwardedContext, resetTelegramForumFlagCacheForTest, - resolveTelegramDirectPeerId, resolveTelegramForumFlag, resolveTelegramForumThreadId, resolveTelegramGroupAllowFromContext, @@ -64,6 +63,7 @@ export { type TelegramThreadSpec, withResolvedTelegramForumFlag, } from "./src/bot/helpers.js"; +export { resolveTelegramDirectPeerId } from "./src/dm-session-key.js"; export { normalizeTelegramCommandDescription, normalizeTelegramCommandName, diff --git a/extensions/telegram/src/bot/helpers.test.ts b/extensions/telegram/src/bot/helpers.test.ts index c804c65ff3d3..d5c7b593fe1a 100644 --- a/extensions/telegram/src/bot/helpers.test.ts +++ b/extensions/telegram/src/bot/helpers.test.ts @@ -7,7 +7,6 @@ import { hasBotMention, isBinaryContent, normalizeForwardedContext, - resolveTelegramDirectPeerId, resolveTelegramBotHasTopicsEnabled, resolveTelegramForumFlag, resolveTelegramForumThreadId, @@ -216,20 +215,6 @@ describe("resolveTelegramBotHasTopicsEnabled", () => { }); }); -describe("resolveTelegramDirectPeerId", () => { - it("prefers sender id when available", () => { - expect(resolveTelegramDirectPeerId({ chatId: 777777777, senderId: 123456789 })).toBe( - "123456789", - ); - }); - - it("falls back to chat id when sender id is missing", () => { - expect(resolveTelegramDirectPeerId({ chatId: 777777777, senderId: undefined })).toBe( - "777777777", - ); - }); -}); - describe("normalizeForwardedContext", () => { it("handles forward_origin users", () => { const ctx = normalizeForwardedContext({ diff --git a/extensions/telegram/src/bot/helpers.ts b/extensions/telegram/src/bot/helpers.ts index d151b395ccae..9e89640d0647 100644 --- a/extensions/telegram/src/bot/helpers.ts +++ b/extensions/telegram/src/bot/helpers.ts @@ -19,7 +19,6 @@ import { resolveExpiresAtMsFromDurationMs, } from "openclaw/plugin-sdk/number-runtime"; import { normalizeAccountId } from "openclaw/plugin-sdk/routing"; -import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime"; import { expandTelegramAllowFromWithAccessGroups } from "../access-groups.js"; import { firstDefined, @@ -546,25 +545,6 @@ export function buildTelegramGroupPeerId(chatId: number | string, messageThreadI return messageThreadId != null ? `${chatId}:topic:${messageThreadId}` : String(chatId); } -/** - * Resolve the direct-message peer identifier for Telegram routing/session keys. - * - * In some Telegram DM deliveries (for example certain business/chat bridge flows), - * `chat.id` can differ from the actual sender user id. Prefer sender id when present - * so per-peer DM scopes isolate users correctly. - */ -export function resolveTelegramDirectPeerId(params: { - chatId: number | string; - senderId?: number | string | null; -}) { - const senderId = - params.senderId != null ? (normalizeOptionalString(String(params.senderId)) ?? "") : ""; - if (senderId) { - return senderId; - } - return String(params.chatId); -} - export function buildTelegramGroupFrom(chatId: number | string, messageThreadId?: number) { return `telegram:group:${buildTelegramGroupPeerId(chatId, messageThreadId)}`; } diff --git a/extensions/telegram/src/conversation-route.ts b/extensions/telegram/src/conversation-route.ts index ec649f236c9c..da796726467b 100644 --- a/extensions/telegram/src/conversation-route.ts +++ b/extensions/telegram/src/conversation-route.ts @@ -8,18 +8,17 @@ import { import { buildAgentSessionKey, deriveLastRoutePolicy, - normalizeAccountId, resolveAgentRoute, } from "openclaw/plugin-sdk/routing"; import { buildAgentMainSessionKey, sanitizeAgentId } from "openclaw/plugin-sdk/routing"; import { logVerbose } from "openclaw/plugin-sdk/runtime-env"; import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime"; import { resolveDefaultTelegramAccountId } from "./accounts.js"; +import { buildTelegramGroupPeerId, buildTelegramParentPeer } from "./bot/helpers.js"; import { - buildTelegramGroupPeerId, - buildTelegramParentPeer, resolveTelegramDirectPeerId, -} from "./bot/helpers.js"; + resolveTelegramNamedAccountBaseSessionKey, +} from "./dm-session-key.js"; type TelegramResolvedRoute = ReturnType; type ConfiguredTelegramBinding = NonNullable; @@ -54,10 +53,7 @@ export function resolveTelegramConversationRoute(params: { }): TelegramConversationRouteResult { const peerId = params.isGroup ? buildTelegramGroupPeerId(params.chatId, params.resolvedThreadId) - : resolveTelegramDirectPeerId({ - chatId: params.chatId, - senderId: params.senderId, - }); + : resolveTelegramDirectPeerId({ chatId: params.chatId, senderId: params.senderId }); const parentPeer = buildTelegramParentPeer({ isGroup: params.isGroup, resolvedThreadId: params.resolvedThreadId, @@ -158,37 +154,11 @@ export function resolveTelegramConversationRoute(params: { }; } -export function resolveTelegramConversationBaseSessionKey(params: { - cfg: OpenClawConfig; - route: Pick< - ReturnType["route"], - "agentId" | "accountId" | "matchedBy" | "sessionKey" - >; - chatId: number | string; - isGroup: boolean; - senderId?: string | number | null; -}): string { - const routeAccountId = normalizeAccountId(params.route.accountId); - const defaultAccountId = normalizeAccountId(resolveDefaultTelegramAccountId(params.cfg)); - const isNamedAccountFallback = - routeAccountId !== defaultAccountId && params.route.matchedBy === "default"; - if (!isNamedAccountFallback || params.isGroup) { - return params.route.sessionKey; - } - return normalizeLowercaseStringOrEmpty( - buildAgentSessionKey({ - agentId: params.route.agentId, - channel: "telegram", - accountId: params.route.accountId, - peer: { - kind: "direct", - id: resolveTelegramDirectPeerId({ - chatId: params.chatId, - senderId: params.senderId, - }), - }, - dmScope: "per-account-channel-peer", - identityLinks: params.cfg.session?.identityLinks, - }), +export function resolveTelegramConversationBaseSessionKey( + params: Parameters[1], +): string { + return resolveTelegramNamedAccountBaseSessionKey( + resolveDefaultTelegramAccountId(params.cfg), + params, ); } diff --git a/extensions/telegram/src/dm-session-key.test.ts b/extensions/telegram/src/dm-session-key.test.ts new file mode 100644 index 000000000000..82308f1a55a8 --- /dev/null +++ b/extensions/telegram/src/dm-session-key.test.ts @@ -0,0 +1,68 @@ +import { describe, expect, it } from "vitest"; +import { resolveTelegramDirectPeerId, resolveTelegramSecurityDmRoute } from "./dm-session-key.js"; + +describe("Telegram DM session keys", () => { + it("prefers sender id and falls back to chat id", () => { + expect(resolveTelegramDirectPeerId({ chatId: 777777777, senderId: 123456789 })).toBe( + "123456789", + ); + expect(resolveTelegramDirectPeerId({ chatId: 777777777 })).toBe("777777777"); + }); + + it.each([ + { + name: "named-account default fallback", + accountId: "personal", + fallbackRoute: { dmScope: "main" as const, matchedBy: "default" as const }, + expected: "isolated", + }, + { + name: "default-account main scope", + accountId: "default", + fallbackRoute: { dmScope: "main" as const, matchedBy: "default" as const }, + expected: "shared", + }, + { + name: "named account with a winning binding", + accountId: "personal", + fallbackRoute: { dmScope: "main" as const, matchedBy: "binding.account" as const }, + expected: "shared", + }, + { + name: "account-isolated core scope", + accountId: "default", + fallbackRoute: { + dmScope: "per-account-channel-peer" as const, + matchedBy: "default" as const, + }, + expected: "isolated", + }, + { + name: "per-peer core namespace", + accountId: "default", + fallbackRoute: { dmScope: "per-peer" as const, matchedBy: "default" as const }, + expected: "core", + }, + { + name: "per-channel core namespace", + accountId: "default", + fallbackRoute: { dmScope: "per-channel-peer" as const, matchedBy: "default" as const }, + expected: "core", + }, + ])("classifies $name as $expected", ({ accountId, fallbackRoute, expected }) => { + const result = resolveTelegramSecurityDmRoute("default", { + cfg: {}, + accountId, + route: { + ...fallbackRoute, + agentId: "main", + accountId, + channel: "telegram", + sessionKey: "agent:main:main", + mainSessionKey: "agent:main:main", + lastRoutePolicy: "main", + }, + }); + expect("kind" in result ? result.kind : "shared").toBe(expected); + }); +}); diff --git a/extensions/telegram/src/dm-session-key.ts b/extensions/telegram/src/dm-session-key.ts new file mode 100644 index 000000000000..5ac2f4f58ed4 --- /dev/null +++ b/extensions/telegram/src/dm-session-key.ts @@ -0,0 +1,77 @@ +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts"; +import { + buildAgentSessionKey, + normalizeAccountId, + type ResolvedAgentRoute, +} from "openclaw/plugin-sdk/routing"; + +export function resolveTelegramDirectPeerId(params: { + chatId: number | string; + senderId?: number | string | null; +}) { + const normalized = params.senderId == null ? "" : String(params.senderId).trim(); + return normalized || String(params.chatId); +} + +export function resolveTelegramNamedAccountBaseSessionKey( + defaultAccountId: string, + params: { + cfg: OpenClawConfig; + route: Pick; + chatId: number | string; + isGroup: boolean; + senderId?: string | number | null; + }, +): string { + const routeAccountId = normalizeAccountId(params.route.accountId); + const normalizedDefaultAccountId = normalizeAccountId(defaultAccountId); + const isNamedAccountFallback = + routeAccountId !== normalizedDefaultAccountId && params.route.matchedBy === "default"; + if (!isNamedAccountFallback || params.isGroup) { + return params.route.sessionKey; + } + return buildAgentSessionKey({ + agentId: params.route.agentId, + channel: "telegram", + accountId: params.route.accountId, + peer: { + kind: "direct", + id: resolveTelegramDirectPeerId({ + chatId: params.chatId, + senderId: params.senderId, + }), + }, + dmScope: "per-account-channel-peer", + identityLinks: params.cfg.session?.identityLinks, + }); +} + +export function resolveTelegramSecurityDmRoute( + defaultAccountId: string, + params: { + cfg: OpenClawConfig; + accountId: string; + route: ResolvedAgentRoute; + principalId?: string; + }, +): { kind: "core" | "isolated" } | { sessionKey: string } { + if (params.principalId !== undefined) { + return { + sessionKey: resolveTelegramNamedAccountBaseSessionKey(defaultAccountId, { + ...params, + chatId: params.principalId, + isGroup: false, + senderId: params.principalId, + }), + }; + } + const isNamedAccountFallback = + normalizeAccountId(params.accountId) !== normalizeAccountId(defaultAccountId) && + params.route.matchedBy === "default"; + if (isNamedAccountFallback || params.route.dmScope === "per-account-channel-peer") { + return { kind: "isolated" }; + } + return params.route.dmScope === "main" + ? { sessionKey: params.route.sessionKey } + : { kind: "core" }; +} diff --git a/extensions/telegram/src/security.ts b/extensions/telegram/src/security.ts index cb3884590b50..b310a7847d28 100644 --- a/extensions/telegram/src/security.ts +++ b/extensions/telegram/src/security.ts @@ -2,7 +2,9 @@ import { createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers"; import type { ChannelPlugin } from "openclaw/plugin-sdk/channel-core"; import { createAllowlistProviderRouteAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy"; +import { resolveDefaultTelegramAccountId } from "./account-selection.js"; import type { ResolvedTelegramAccount } from "./accounts.js"; +import { resolveTelegramSecurityDmRoute } from "./dm-session-key.js"; import { collectTelegramSecurityAuditFindings } from "./security-audit.js"; const resolveTelegramDmPolicy = createScopedDmSecurityResolver({ @@ -36,6 +38,10 @@ const collectTelegramSecurityWarnings = export const telegramSecurityAdapter = { resolveDmPolicy: resolveTelegramDmPolicy, + dmRouting: { + resolveDmRoute: (ctx) => + resolveTelegramSecurityDmRoute(resolveDefaultTelegramAccountId(ctx.cfg), ctx), + }, collectWarnings: collectTelegramSecurityWarnings, collectAuditFindings: collectTelegramSecurityAuditFindings, } satisfies NonNullable["security"]>; diff --git a/extensions/zalouser/src/channel.adapters.ts b/extensions/zalouser/src/channel.adapters.ts index 8f41d141c124..bf92e97b3576 100644 --- a/extensions/zalouser/src/channel.adapters.ts +++ b/extensions/zalouser/src/channel.adapters.ts @@ -49,6 +49,7 @@ import { parseZalouserOutboundTarget, resolveZalouserOutboundSessionRoute, } from "./session-route.js"; +import { resolveZalouserDmSessionScope } from "./session-scope.js"; import type { ZaloSendResult } from "./types.js"; const loadZalouserChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime.js")); @@ -435,6 +436,9 @@ export const zalouserAuthAdapter = { export const zalouserSecurityAdapter = { resolveDmPolicy: resolveZalouserDmPolicy, + dmRouting: { + resolveDmScope: ({ cfg }: { cfg: OpenClawConfig }) => resolveZalouserDmSessionScope(cfg), + }, collectAuditFindings: async (params: { accountId?: string | null; account: ResolvedZalouserAccount; diff --git a/src/channels/message-access/dm-allow-state.ts b/src/channels/message-access/dm-allow-state.ts index eb05d51a7621..fb262e8c1939 100644 --- a/src/channels/message-access/dm-allow-state.ts +++ b/src/channels/message-access/dm-allow-state.ts @@ -1,8 +1,4 @@ -/** - * Direct-message allowlist audit state. - * - * Merges configured and persisted allowFrom entries for setup/status prompts. - */ +/** Merges configured and persisted allowFrom entries for channel security audit. */ import { normalizeStringEntries } from "@openclaw/normalization-core/string-normalization"; import type { ChannelId } from "../plugins/types.public.js"; import { readChannelIngressStoreAllowFromForDmPolicy } from "./store-allow-from.js"; @@ -14,12 +10,7 @@ export async function resolveDmAllowAuditState(params: { dmPolicy?: string | null; normalizeEntry?: (raw: string) => string; readStore?: (provider: ChannelId, accountId: string) => Promise; -}): Promise<{ - configAllowFrom: string[]; - hasWildcard: boolean; - allowCount: number; - isMultiUserDm: boolean; -}> { +}) { const configAllowFrom = normalizeStringEntries( Array.isArray(params.allowFrom) ? params.allowFrom : undefined, ); @@ -37,11 +28,9 @@ export async function resolveDmAllowAuditState(params: { const normalizedStore = normalizeStringEntries( storeAllowFrom.map((value) => normalizeEntry(value)), ); - const allowCount = new Set([...normalizedCfg, ...normalizedStore]).size; + const admittedPrincipals = Array.from(new Set([...normalizedCfg, ...normalizedStore])); return { - configAllowFrom, hasWildcard, - allowCount, - isMultiUserDm: hasWildcard || allowCount > 1, + admittedPrincipals, }; } diff --git a/src/channels/plugins/types.adapters.ts b/src/channels/plugins/types.adapters.ts index 0a82d26ac862..8ece288aae1e 100644 --- a/src/channels/plugins/types.adapters.ts +++ b/src/channels/plugins/types.adapters.ts @@ -6,6 +6,7 @@ import type { ReplyPayload } from "../../auto-reply/reply-payload.js"; import type { LegacyConfigRule } from "../../config/legacy.shared.js"; import type { AgentBinding } from "../../config/types.agents.js"; +import type { DmScope } from "../../config/types.base.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import type { GroupToolPolicyConfig } from "../../config/types.tools.js"; import type { ChannelApprovalNativeRuntimeAdapter } from "../../infra/approval-handler-runtime-types.js"; @@ -15,6 +16,7 @@ import type { PluginApprovalRequest, PluginApprovalResolved, } from "../../infra/plugin-approvals.js"; +import type { ResolvedAgentRoute } from "../../routing/resolve-route.js"; import type { RuntimeEnv } from "../../runtime.js"; import type { ResolverContext, SecretDefaults } from "../../secrets/runtime-shared.js"; import type { SecretTargetRegistryEntry } from "../../secrets/target-registry-types.js"; @@ -810,6 +812,11 @@ export type ChannelConversationBindingSupport = { }>; }; +type ChannelSecurityDmRouteContext = ChannelSecurityContext & { + accountId: string; + principalId?: string; +}; + export type ChannelSecurityAdapter = { applyConfigFixes?: (params: { cfg: OpenClawConfig; @@ -818,6 +825,12 @@ export type ChannelSecurityAdapter = { resolveDmPolicy?: ChannelAdapterCallback< (ctx: ChannelSecurityContext) => ChannelSecurityDmPolicy | null >; + dmRouting?: { + resolveDmScope?: (ctx: ChannelSecurityDmRouteContext) => DmScope | undefined; + resolveDmRoute?: ( + ctx: ChannelSecurityDmRouteContext & { route: ResolvedAgentRoute }, + ) => { kind: "core" | "isolated" } | { sessionKey: string } | undefined; + }; collectWarnings?: ChannelAdapterCallback< (ctx: ChannelSecurityContext) => Promise | string[] >; diff --git a/src/commands/doctor-security.test.ts b/src/commands/doctor-security.test.ts index f7cea167129c..467710234f2f 100644 --- a/src/commands/doctor-security.test.ts +++ b/src/commands/doctor-security.test.ts @@ -271,25 +271,39 @@ describe("noteSecurityWarnings gateway exposure", () => { expect(note).not.toHaveBeenCalled(); }); - it("shows explicit dmScope config command for multi-user DMs", async () => { + it("renders the structured non-default-account DM collision guidance", async () => { pluginRegistry.list = [ { id: "test-channel", meta: { label: "Test Channel" }, config: { - listAccountIds: () => ["default"], - inspectAccount: () => ({ enabled: true, configured: true }), - resolveAccount: () => ({}), + listAccountIds: () => ["default", "secondary"], + defaultAccountId: () => "default", + inspectAccount: (_cfg: OpenClawConfig, accountId: string) => ({ + accountId, + enabled: true, + configured: true, + }), + resolveAccount: (_cfg: OpenClawConfig, accountId: string) => ({ accountId }), isEnabled: () => true, isConfigured: () => true, }, security: { - resolveDmPolicy: () => ({ + resolveDmPolicy: ({ accountId }: { accountId?: string | null }) => ({ policy: "allowlist", - allowFrom: ["alice", "bob"], - allowFromPath: "channels.whatsapp.", + allowFrom: accountId === "secondary" ? ["alice", "bob"] : ["owner"], + allowFromPath: `channels.test-channel.accounts.${accountId}.`, approveHint: "approve", }), + collectWarnings: () => ["- plugin warning remains visible"], + collectAuditFindings: () => [ + { + checkId: "channels.test-channel.audit_only", + severity: "warn", + title: "audit-only plugin finding", + detail: "must not appear in Doctor", + }, + ], }, }, ]; @@ -300,7 +314,10 @@ describe("noteSecurityWarnings gateway exposure", () => { includeSetupFallbackPlugins: true, }); const message = lastMessage(); - expect(message).toContain('config set session.dmScope "per-channel-peer"'); + expect(message).toContain("matching binding or session.dmScope"); + expect(message).toContain("secondary"); + expect(message).toContain("plugin warning remains visible"); + expect(message).not.toContain("audit-only plugin finding"); }); it("clarifies approvals.exec forwarding-only behavior", async () => { diff --git a/src/commands/doctor-security.ts b/src/commands/doctor-security.ts index c68767d89b61..d694f95eac8c 100644 --- a/src/commands/doctor-security.ts +++ b/src/commands/doctor-security.ts @@ -1,10 +1,7 @@ /** Security warnings for gateway exposure, exec policy drift, channel DMs, and plaintext secrets. */ import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce"; import { note } from "../../packages/terminal-core/src/note.js"; -import { resolveDefaultChannelAccountContext } from "../channels/account-context.js"; -import { resolveDmAllowAuditState } from "../channels/message-access/dm-allow-state.js"; import { listReadOnlyChannelPluginsForConfig } from "../channels/plugins/read-only.js"; -import type { ChannelId } from "../channels/plugins/types.public.js"; import { formatCliCommand } from "../cli/command-format.js"; import type { OpenClawConfig, GatewayBindMode } from "../config/config.js"; import type { AgentConfig } from "../config/types.agents.js"; @@ -23,6 +20,7 @@ import { import { isLikelySensitiveModelProviderHeaderName } from "../secrets/model-provider-header-policy.js"; import { hasConfiguredPlaintextSecretValue } from "../secrets/secret-value.js"; import { discoverConfigSecretTargets } from "../secrets/target-registry.js"; +import { collectChannelSecurityFindings } from "../security/audit-channel.js"; import { collectExecFilesystemPolicyDriftHits } from "../security/exec-filesystem-policy.js"; function collectImplicitHeartbeatDirectPolicyWarnings(cfg: OpenClawConfig): string[] { @@ -342,107 +340,18 @@ export async function collectSecurityWarnings( warnings.push(...tokenConflict.warningLines); } - const warnDmPolicy = async (params: { - label: string; - provider: ChannelId; - accountId: string; - dmPolicy: string; - allowFrom?: Array | null; - policyPath?: string; - allowFromPath: string; - approveHint: string; - normalizeEntry?: (raw: string) => string; - }) => { - const dmPolicy = params.dmPolicy; - const policyPath = params.policyPath ?? `${params.allowFromPath}policy`; - const { hasWildcard, allowCount, isMultiUserDm } = await resolveDmAllowAuditState({ - provider: params.provider, - accountId: params.accountId, - allowFrom: params.allowFrom, - dmPolicy, - normalizeEntry: params.normalizeEntry, - }); - const dmScope = cfg.session?.dmScope ?? "main"; - - if (dmPolicy === "open") { - const allowFromPath = `${params.allowFromPath}allowFrom`; - warnings.push(`- ${params.label} DMs: OPEN (${policyPath}="open"). Anyone can DM it.`); - if (!hasWildcard) { - warnings.push( - `- ${params.label} DMs: config invalid — "open" requires ${allowFromPath} to include "*".`, - ); - } - } - - if (dmPolicy === "disabled") { - warnings.push(`- ${params.label} DMs: disabled (${policyPath}="disabled").`); - return; - } - - if (dmPolicy !== "open" && allowCount === 0) { - warnings.push( - `- ${params.label} DMs: locked (${policyPath}="${dmPolicy}") with no allowlist; unknown senders will be blocked / get a pairing code.`, - ); - warnings.push(` ${params.approveHint}`); - } - - if (dmScope === "main" && isMultiUserDm) { - warnings.push( - `- ${params.label} DMs: multiple senders share the main session; run: ` + - formatCliCommand('openclaw config set session.dmScope "per-channel-peer"') + - ' (or "per-account-channel-peer" for multi-account channels) to isolate sessions.', - ); - } - }; - - for (const plugin of listReadOnlyChannelPluginsForConfig(cfg, { - includePersistedAuthState: true, - includeSetupFallbackPlugins: true, - })) { - if (!plugin.security) { - continue; - } - const { defaultAccountId, account, enabled, configured, diagnostics } = - await resolveDefaultChannelAccountContext(plugin, cfg, { - mode: "read_only", - commandName: "doctor", - }); - for (const diagnostic of diagnostics) { - warnings.push(`- [secrets] ${diagnostic}`); - } - if (!enabled) { - continue; - } - if (!configured) { - continue; - } - const dmPolicy = plugin.security.resolveDmPolicy?.({ - cfg, - accountId: defaultAccountId, - account, - }); - if (dmPolicy) { - await warnDmPolicy({ - label: plugin.meta.label ?? plugin.id, - provider: plugin.id, - accountId: defaultAccountId, - dmPolicy: dmPolicy.policy, - allowFrom: dmPolicy.allowFrom, - policyPath: dmPolicy.policyPath, - allowFromPath: dmPolicy.allowFromPath, - approveHint: dmPolicy.approveHint, - normalizeEntry: dmPolicy.normalizeEntry, - }); - } - if (plugin.security.collectWarnings) { - const extra = await plugin.security.collectWarnings({ - cfg, - accountId: defaultAccountId, - account, - }); - if (extra?.length) { - warnings.push(...extra); - } + const channelFindings = await collectChannelSecurityFindings({ + cfg, + mode: "doctor", + plugins: listReadOnlyChannelPluginsForConfig(cfg, { + includePersistedAuthState: true, + includeSetupFallbackPlugins: true, + }), + }); + for (const finding of channelFindings) { + warnings.push(`- ${finding.title}: ${finding.detail}`); + if (finding.remediation) { + warnings.push(` ${finding.remediation}`); } } return warnings; diff --git a/src/plugin-sdk/channel-policy.test.ts b/src/plugin-sdk/channel-policy.test.ts index 40dba1734129..3ef32c468e24 100644 --- a/src/plugin-sdk/channel-policy.test.ts +++ b/src/plugin-sdk/channel-policy.test.ts @@ -49,6 +49,10 @@ describe("mutable allowlist table helpers", () => { describe("createRestrictSendersChannelSecurity", () => { it("builds dm policy resolution and open-group warnings from one descriptor", () => { + const dmRouting = { + resolveDmScope: () => "per-peer" as const, + resolveDmRoute: () => ({ kind: "core" as const }), + }; const security = createRestrictSendersChannelSecurity<{ accountId: string; allowFrom?: string[]; @@ -65,8 +69,11 @@ describe("createRestrictSendersChannelSecurity", () => { groupAllowFromPath: "channels.line.groupAllowFrom", mentionGated: false, policyPathSuffix: "dmPolicy", + dmRouting, }); + expect(security.dmRouting).toBe(dmRouting); + expect( security.resolveDmPolicy?.({ cfg: { channels: {} } as never, diff --git a/src/plugin-sdk/channel-policy.ts b/src/plugin-sdk/channel-policy.ts index 04a236573ad7..0b0fc3733f55 100644 --- a/src/plugin-sdk/channel-policy.ts +++ b/src/plugin-sdk/channel-policy.ts @@ -306,6 +306,7 @@ export function createRestrictSendersChannelSecurity< normalizeDmEntry?: (raw: string) => string; /** Allows non-default accounts to inherit shared defaults from the default account. */ inheritSharedDefaultsFromDefaultAccount?: boolean; + dmRouting?: ChannelSecurityAdapter["dmRouting"]; }): ChannelSecurityAdapter { return { resolveDmPolicy: createScopedDmSecurityResolver({ @@ -321,6 +322,7 @@ export function createRestrictSendersChannelSecurity< normalizeEntry: params.normalizeDmEntry, inheritSharedDefaultsFromDefaultAccount: params.inheritSharedDefaultsFromDefaultAccount, }), + ...(params.dmRouting ? { dmRouting: params.dmRouting } : {}), collectWarnings: createAllowlistProviderRestrictSendersWarningCollector({ providerConfigPresent: params.providerConfigPresent ?? ((cfg) => cfg.channels?.[params.channelKey] !== undefined), diff --git a/src/plugin-sdk/core.test.ts b/src/plugin-sdk/core.test.ts index da39c678aee4..59fa8f66bd25 100644 --- a/src/plugin-sdk/core.test.ts +++ b/src/plugin-sdk/core.test.ts @@ -183,6 +183,26 @@ describe("createChannelPluginBase", () => { }); describe("createChatChannelPlugin", () => { + it("preserves DM routing through the declarative security shorthand", () => { + const dmRouting = { + resolveDmScope: () => "per-peer" as const, + resolveDmRoute: () => ({ kind: "core" as const }), + }; + const plugin = createChatChannelPlugin({ + base: createChannelPlugin("security-routing") as ChannelPlugin<{ accountId: string }>, + security: { + dm: { + channelKey: "security-routing", + resolvePolicy: () => "allowlist", + resolveAllowFrom: () => [], + }, + dmRouting, + }, + }); + + expect(plugin.security?.dmRouting).toBe(dmRouting); + }); + it("preserves account-scoped current-conversation binding support", () => { const conversationBindings: NonNullable = { isCurrentConversationBindingSupported: ({ accountId }) => accountId !== "enterprise", diff --git a/src/plugin-sdk/core.ts b/src/plugin-sdk/core.ts index ec1b766bb6e3..a72335a2fc73 100644 --- a/src/plugin-sdk/core.ts +++ b/src/plugin-sdk/core.ts @@ -650,6 +650,7 @@ type ChatChannelSecurityOptions string; inheritSharedDefaultsFromDefaultAccount?: boolean; }; + dmRouting?: ChannelSecurityAdapter["dmRouting"]; collectWarnings?: ChannelSecurityAdapter["collectWarnings"]; collectAuditFindings?: ChannelSecurityAdapter["collectAuditFindings"]; }; @@ -760,6 +761,7 @@ function resolveChatChannelSecurity { }); }); +describe("unknown direct-message route decisions", () => { + test("lists unique exact peers from normalized account and any-account bindings", () => { + const binding = (peerId: string, accountId: string, kind: "direct" | "group" = "direct") => ({ + agentId: "main", + match: { channel: "Telegram", accountId, peer: { kind, id: peerId } }, + }); + const cfg = { + bindings: [ + binding("peer-b", "*"), + binding("peer-a", " WORK "), + binding("peer-b", "work"), + binding("*", "work"), + binding("room", "work", "group"), + binding("other", "other"), + ], + } satisfies OpenClawConfig; + + expect( + listExactDirectMessageBindingPeerIds({ cfg, channel: " telegram ", accountId: " work " }), + ).toEqual(["peer-b", "peer-a"]); + }); + + test.each([ + { + name: "direct wildcard outranks account and channel", + wildcard: true, + account: true, + expectedMatchedBy: "binding.peer.wildcard", + }, + { + name: "account outranks channel when no wildcard exists", + wildcard: false, + account: true, + expectedMatchedBy: "binding.account", + }, + { + name: "channel matches when no narrower fallback exists", + wildcard: false, + account: false, + expectedMatchedBy: "binding.channel", + }, + ] as const)("$name", ({ wildcard, account, expectedMatchedBy }) => { + const bindings: NonNullable = [ + { + agentId: "exact", + match: { channel: "telegram", peer: { kind: "direct", id: "known-user" } }, + }, + ]; + if (wildcard) { + bindings.push({ + agentId: "wildcard", + match: { channel: "telegram", peer: { kind: "direct", id: "*" } }, + }); + } + if (account) { + bindings.push({ + agentId: "account", + match: { channel: "telegram" }, + }); + } + bindings.push({ + agentId: "channel", + match: { channel: "telegram", accountId: "*" }, + }); + + const route = resolveUnknownDirectMessageRoute({ + cfg: { bindings }, + channel: "telegram", + accountId: "default", + }); + + expect(route.matchedBy).toBe(expectedMatchedBy); + expect(route.agentId).not.toBe("exact"); + }); +}); + describe("wildcard peer bindings (peer.id=*)", () => { test("peer.id=* matches any direct peer and routes to the bound agent", () => { const cfg: OpenClawConfig = { diff --git a/src/routing/resolve-route.ts b/src/routing/resolve-route.ts index f4a6fa773e07..9833dbd7dd4c 100644 --- a/src/routing/resolve-route.ts +++ b/src/routing/resolve-route.ts @@ -466,6 +466,20 @@ function getEvaluatedBindingIndexForChannelAccount( return built; } +/** @internal Lists exact DM peers from the canonical channel/account binding index. */ +export function listExactDirectMessageBindingPeerIds( + input: Pick, +): string[] { + const prefix = "direct:"; + return [ + ...getEvaluatedBindingIndexForChannelAccount( + input.cfg, + normalizeLowercaseStringOrEmpty(input.channel), + normalizeAccountId(input.accountId), + ).byPeer.keys(), + ].flatMap((key) => (key.startsWith(prefix) ? [key.slice(prefix.length)] : [])); +} + function normalizePeerConstraint( peer: { kind?: string; id?: string } | undefined, ): NormalizedPeerConstraint { @@ -773,4 +787,11 @@ export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentR return choose(resolveDefaultAgentId(input.cfg), "default"); } + +/** @internal Resolves fallback precedence for an unknown direct peer. */ +export function resolveUnknownDirectMessageRoute( + input: Pick, +): ResolvedAgentRoute { + return resolveAgentRoute({ ...input, peer: { kind: "direct", id: "" } }); +} /* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */ diff --git a/src/routing/session-key.ts b/src/routing/session-key.ts index 9660c40f8340..28525acc4de0 100644 --- a/src/routing/session-key.ts +++ b/src/routing/session-key.ts @@ -226,7 +226,7 @@ export function buildAgentPeerSessionKey(params: { const linkedPeerId = dmScope === "main" ? null - : resolveLinkedPeerId({ + : resolveLinkedDirectPeerId({ identityLinks: params.identityLinks, channel: params.channel, peerId, @@ -262,7 +262,8 @@ export function buildAgentPeerSessionKey(params: { return `agent:${normalizeAgentId(params.agentId)}:${channel}:${peerKind}:${peerId}`; } -function resolveLinkedPeerId(params: { +/** @internal Resolves a declared cross-channel identity for one direct peer. */ +export function resolveLinkedDirectPeerId(params: { identityLinks?: Record; channel: string; peerId: string; diff --git a/src/security/audit-channel-dm-policy.test.ts b/src/security/audit-channel-dm-policy.test.ts index af438f7a84dc..d1e9acfec7b7 100644 --- a/src/security/audit-channel-dm-policy.test.ts +++ b/src/security/audit-channel-dm-policy.test.ts @@ -1,5 +1,5 @@ // Covers direct-message policy audit findings for channels. -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import type { ChannelPlugin } from "../channels/plugins/types.public.js"; import type { OpenClawConfig } from "../config/config.js"; import { collectChannelSecurityFindings } from "./audit-channel.js"; @@ -17,104 +17,502 @@ function requireFinding( return finding; } -describe("security audit channel dm policy", () => { - it("warns when multiple DM senders share the main session", async () => { - const cfg: OpenClawConfig = { - session: { dmScope: "main" }, - channels: { whatsapp: { enabled: true } }, - }; - const plugins: ChannelPlugin[] = [ - { - id: "whatsapp", - meta: { - id: "whatsapp", - label: "WhatsApp", - selectionLabel: "WhatsApp", - docsPath: "/channels/whatsapp", - blurb: "Test", - }, - capabilities: { chatTypes: ["direct"] }, - config: { - listAccountIds: () => ["default"], - inspectAccount: () => ({ enabled: true, configured: true }), - resolveAccount: () => ({}), - isEnabled: () => true, - isConfigured: () => true, - }, - security: { - resolveDmPolicy: () => ({ - policy: "allowlist", - allowFrom: ["user-a", "user-b"], - policyPath: "channels.whatsapp.dmPolicy", - allowFromPath: "channels.whatsapp.", - approveHint: "approve", - }), - }, - }, - ]; +function collisionFindings(findings: ChannelSecurityFinding[]): ChannelSecurityFinding[] { + return findings.filter((finding) => finding.checkId.includes(".dm.session_collision.")); +} +function createDmPlugin( + params: { + id?: "telegram" | "whatsapp"; + accounts?: Record }>; + dmRouting?: NonNullable["dmRouting"]; + } = {}, +): ChannelPlugin { + const id = params.id ?? "whatsapp"; + const accounts = params.accounts ?? { + default: { policy: "allowlist", allowFrom: ["user-a", "user-b"] }, + }; + const accountIds = Object.keys(accounts); + const security: NonNullable = { + resolveDmPolicy: ({ accountId }: { accountId?: string | null }) => { + const resolvedAccountId = accountId ?? "default"; + const policy = accounts[resolvedAccountId]; + return policy + ? { + policy: policy.policy ?? "allowlist", + allowFrom: policy.allowFrom, + policyPath: `channels.${id}.accounts.${resolvedAccountId}.dmPolicy`, + allowFromPath: `channels.${id}.accounts.${resolvedAccountId}.`, + approveHint: `approve ${resolvedAccountId}`, + } + : null; + }, + ...(params.dmRouting ? { dmRouting: params.dmRouting } : {}), + }; + + const label = id === "telegram" ? "Telegram" : "WhatsApp"; + return { + id, + meta: { + id, + label, + selectionLabel: label, + docsPath: `/channels/${id}`, + blurb: "Test", + }, + capabilities: { chatTypes: ["direct"] }, + config: { + listAccountIds: () => accountIds, + defaultAccountId: () => accountIds[0] ?? "default", + inspectAccount: (_cfg, accountId) => ({ + accountId: accountId ?? "default", + enabled: true, + configured: true, + }), + resolveAccount: (_cfg, accountId) => ({ accountId: accountId ?? "default" }), + isEnabled: () => true, + isConfigured: () => true, + }, + security, + }; +} + +describe("security audit channel dm policy", () => { + it.each([ + { + name: "global main + winning isolated binding is safe", + cfg: { + session: { dmScope: "main" }, + bindings: [ + { + agentId: "main", + match: { channel: "whatsapp", peer: { kind: "direct", id: "*" } }, + session: { dmScope: "per-channel-peer" }, + }, + ], + } satisfies OpenClawConfig, + expectedCollisions: 0, + }, + { + name: "global isolated + winning main binding collides", + cfg: { + session: { dmScope: "per-channel-peer" }, + bindings: [ + { + agentId: "main", + match: { channel: "whatsapp", peer: { kind: "direct", id: "*" } }, + session: { dmScope: "main" }, + }, + ], + } satisfies OpenClawConfig, + expectedCollisions: 1, + remediation: "matching binding or session.dmScope", + }, + { + name: "exact peer bindings outrank a colliding channel binding", + cfg: { + session: { dmScope: "main" }, + bindings: [ + { + agentId: "main", + match: { channel: "whatsapp" }, + session: { dmScope: "main" }, + }, + { + agentId: "main", + match: { channel: "whatsapp", peer: { kind: "direct", id: "user-a" } }, + session: { dmScope: "per-channel-peer" }, + }, + { + agentId: "main", + match: { channel: "whatsapp", peer: { kind: "direct", id: "user-b" } }, + session: { dmScope: "per-channel-peer" }, + }, + ], + } satisfies OpenClawConfig, + expectedCollisions: 0, + }, + { + name: "global session aliases remain isolated by routed agent store", + cfg: { + agents: { list: [{ id: "agent-a" }, { id: "agent-b", default: true }] }, + session: { scope: "global", dmScope: "main" }, + bindings: [ + { + agentId: "agent-a", + match: { channel: "whatsapp", peer: { kind: "direct", id: "user-a" } }, + }, + { + agentId: "agent-b", + match: { channel: "whatsapp", peer: { kind: "direct", id: "user-b" } }, + }, + ], + } satisfies OpenClawConfig, + expectedCollisions: 0, + }, + ])("$name", async ({ cfg, expectedCollisions, remediation }) => { const findings = await collectChannelSecurityFindings({ cfg, - plugins, + plugins: [createDmPlugin()], }); - const sharedScopeFinding = requireFinding( - findings, - "channels.whatsapp.dm.scope_main_multiuser", - ); - expect(sharedScopeFinding.severity).toBe("warn"); - expect(sharedScopeFinding.remediation).toContain( - 'config set session.dmScope "per-channel-peer"', - ); + const collisions = collisionFindings(findings); + expect(collisions).toHaveLength(expectedCollisions); + if (remediation) { + expect(collisions[0]?.remediation).toContain(remediation); + } }); - it("flags public DMs and shared main-session scope together", async () => { - const cfg: OpenClawConfig = { - session: { dmScope: "main" }, - channels: { telegram: { enabled: true } }, - }; - const plugins: ChannelPlugin[] = [ - { - id: "telegram", - meta: { - id: "telegram", - label: "Telegram", - selectionLabel: "Telegram", - docsPath: "/channels/telegram", - blurb: "Test", - }, - capabilities: { chatTypes: ["direct"] }, - config: { - listAccountIds: () => ["default"], - inspectAccount: () => ({ enabled: true, configured: true }), - resolveAccount: () => ({}), - isEnabled: () => true, - isConfigured: () => true, - }, - security: { - resolveDmPolicy: () => ({ - policy: "open", - allowFrom: ["*"], - policyPath: "channels.telegram.dmPolicy", - allowFromPath: "channels.telegram.", - approveHint: "approve", - }), - }, - }, - ]; - + it("detects cross-account collisions with one admitted sender per account", async () => { const findings = await collectChannelSecurityFindings({ - cfg, - plugins, + cfg: { session: { dmScope: "main" } }, + plugins: [ + createDmPlugin({ + accounts: { + "Personal Account": { allowFrom: ["user-a"] }, + "work@example": { allowFrom: ["user-b"] }, + }, + }), + ], }); - const openDmFinding = requireFinding(findings, "channels.telegram.dm.open"); - expect(openDmFinding.severity).toBe("critical"); + const collisions = collisionFindings(findings); + expect(collisions).toHaveLength(1); + expect(collisions[0]?.checkId).toContain("whatsapp-personal-account_whatsapp-work-example"); + expect(collisions[0]?.checkId).toMatch(/^[a-z0-9._-]+$/); + expect(collisions[0]?.detail).toContain("personal-account"); + expect(collisions[0]?.detail).toContain("work-example"); + }); - const sharedScopeFinding = requireFinding( + it("keeps same-named accounts attributed across channels", async () => { + const findings = await collectChannelSecurityFindings({ + cfg: { session: { dmScope: "main" } }, + plugins: [ + createDmPlugin({ accounts: { default: { allowFrom: ["user-a"] } } }), + createDmPlugin({ + id: "telegram", + accounts: { default: { allowFrom: ["user-b"] } }, + }), + ], + }); + + const collision = collisionFindings(findings)[0]; + expect(collision?.checkId).toContain("telegram-default_whatsapp-default"); + expect(collision?.detail).toContain("telegram-default, whatsapp-default"); + }); + + it("counts identity-linked aliases as one logical principal", async () => { + const cfg: OpenClawConfig = { + session: { + dmScope: "main", + identityLinks: { alice: ["whatsapp:user-a", "whatsapp:user-b"] }, + }, + }; + const plugin = createDmPlugin(); + + const linkedFindings = await collectChannelSecurityFindings({ cfg, plugins: [plugin] }); + const distinctFindings = await collectChannelSecurityFindings({ + cfg: { session: { dmScope: "main" } }, + plugins: [plugin], + }); + + expect(collisionFindings(linkedFindings)).toHaveLength(0); + expect(collisionFindings(distinctFindings)).toHaveLength(1); + }); + + it("keeps separate collision topologies distinct", async () => { + const findings = await collectChannelSecurityFindings({ + cfg: { + agents: { list: [{ id: "alpha", default: true }, { id: "beta" }] }, + session: { dmScope: "main" }, + bindings: [ + { agentId: "alpha", match: { channel: "whatsapp", accountId: "a" } }, + { agentId: "alpha", match: { channel: "whatsapp", accountId: "b" } }, + { agentId: "beta", match: { channel: "whatsapp", accountId: "c" } }, + { agentId: "beta", match: { channel: "whatsapp", accountId: "d" } }, + ], + }, + plugins: [ + createDmPlugin({ + accounts: { + a: { allowFrom: ["user-a"] }, + b: { allowFrom: ["user-b"] }, + c: { allowFrom: ["user-c"] }, + d: { allowFrom: ["user-d"] }, + }, + }), + ], + }); + + const collisions = collisionFindings(findings); + expect(collisions).toHaveLength(2); + expect(new Set(collisions.map((finding) => finding.checkId)).size).toBe(2); + expect(new Set(collisions.map((finding) => finding.detail)).size).toBe(2); + }); + + it("uses the channel-owned DM route for wildcard senders", async () => { + const findings = await collectChannelSecurityFindings({ + cfg: { session: { dmScope: "main" } }, + plugins: [ + createDmPlugin({ + accounts: { default: { policy: "open", allowFrom: ["*"] } }, + dmRouting: { resolveDmScope: () => "per-channel-peer" }, + }), + ], + }); + + expect(collisionFindings(findings)).toHaveLength(0); + }); + + it.each([ + { + name: "per-channel-peer collides across accounts", + dmScope: "per-channel-peer" as const, + plugins: () => [ + createDmPlugin({ + accounts: { + personal: { policy: "open", allowFrom: ["*"] }, + work: { policy: "open", allowFrom: ["*"] }, + }, + }), + ], + expectedCollisions: 1, + }, + { + name: "per-peer collides across channels", + dmScope: "per-peer" as const, + plugins: () => [ + createDmPlugin({ accounts: { default: { policy: "open", allowFrom: ["*"] } } }), + createDmPlugin({ + id: "telegram", + accounts: { default: { policy: "open", allowFrom: ["*"] } }, + }), + ], + expectedCollisions: 1, + }, + { + name: "per-account-channel-peer stays isolated", + dmScope: "per-account-channel-peer" as const, + plugins: () => [ + createDmPlugin({ + accounts: { + personal: { policy: "open", allowFrom: ["*"] }, + work: { policy: "open", allowFrom: ["*"] }, + }, + }), + ], + expectedCollisions: 0, + }, + ])("models wildcard namespace: $name", async ({ dmScope, plugins, expectedCollisions }) => { + const findings = await collectChannelSecurityFindings({ + cfg: { session: { dmScope } }, + plugins: plugins(), + }); + const collisions = collisionFindings(findings); + + expect(collisions).toHaveLength(expectedCollisions); + if (expectedCollisions > 0) { + expect(collisions[0]?.detail).toContain("can resolve to the same session bucket"); + } + }); + + it.each([ + { + name: "per-channel wildcard intersects a concrete sender on the same channel", + cfg: { session: { dmScope: "per-channel-peer" as const } }, + plugins: [ + createDmPlugin({ + accounts: { + open: { policy: "open", allowFrom: ["*"] }, + finite: { allowFrom: ["user-b"] }, + }, + dmRouting: { + resolveDmRoute: ({ principalId }) => + principalId === undefined ? { kind: "core" } : undefined, + }, + }), + ], + expectedCollisions: 1, + }, + { + name: "per-peer wildcard intersects a concrete sender on another channel", + cfg: { session: { dmScope: "per-peer" as const } }, + plugins: [ + createDmPlugin({ accounts: { open: { policy: "open", allowFrom: ["*"] } } }), + createDmPlugin({ + id: "telegram", + accounts: { finite: { allowFrom: ["user-b"] } }, + }), + ], + expectedCollisions: 1, + }, + { + name: "per-channel wildcards on different channels stay separate", + cfg: { session: { dmScope: "per-channel-peer" as const } }, + plugins: [ + createDmPlugin({ accounts: { open: { policy: "open", allowFrom: ["*"] } } }), + createDmPlugin({ + id: "telegram", + accounts: { open: { policy: "open", allowFrom: ["*"] } }, + }), + ], + expectedCollisions: 0, + }, + { + name: "per-peer wildcard subsumes an overlapping per-channel wildcard", + cfg: {}, + plugins: [ + createDmPlugin({ + accounts: { open: { policy: "open", allowFrom: ["*"] } }, + dmRouting: { resolveDmScope: () => "per-peer" }, + }), + createDmPlugin({ + id: "telegram", + accounts: { open: { policy: "open", allowFrom: ["*"] } }, + dmRouting: { resolveDmScope: () => "per-channel-peer" }, + }), + ], + expectedCollisions: 1, + }, + ])("intersects wildcard namespace: $name", async ({ cfg, plugins, expectedCollisions }) => { + const findings = await collectChannelSecurityFindings({ cfg, plugins }); + const collisions = collisionFindings(findings); + + expect(collisions).toHaveLength(expectedCollisions); + for (const collision of collisions) { + expect(collision.title).toContain("may share"); + expect(collision.detail).toContain("can resolve to the same session bucket"); + } + }); + + it("does not let exact bindings on finite probe strings hide an open-DM collision", async () => { + const findings = await collectChannelSecurityFindings({ + cfg: { + session: { dmScope: "main" }, + bindings: [ + { + agentId: "main", + match: { + channel: "whatsapp", + peer: { kind: "direct", id: "__openclaw_audit_unmatched_dm_1__" }, + }, + session: { dmScope: "per-channel-peer" }, + }, + { + agentId: "main", + match: { + channel: "whatsapp", + peer: { kind: "direct", id: "__openclaw_audit_unmatched_dm_2__" }, + }, + session: { dmScope: "per-channel-peer" }, + }, + ], + }, + plugins: [ + createDmPlugin({ + accounts: { default: { policy: "open", allowFrom: ["*"] } }, + }), + ], + }); + + expect(collisionFindings(findings)).toHaveLength(1); + }); + + it("audits exact DM bindings admitted by wildcard policy", async () => { + const findings = await collectChannelSecurityFindings({ + cfg: { + session: { dmScope: "per-account-channel-peer" }, + bindings: [ + { + agentId: "main", + match: { + channel: "whatsapp", + accountId: "*", + peer: { kind: "direct", id: "bound-a" }, + }, + session: { dmScope: "main" }, + }, + { + agentId: "main", + match: { + channel: "whatsapp", + accountId: " WORK ", + peer: { kind: "direct", id: "bound-b" }, + }, + session: { dmScope: "main" }, + }, + ], + }, + plugins: [ + createDmPlugin({ + accounts: { work: { policy: "open", allowFrom: ["*"] } }, + }), + ], + }); + + const collisions = collisionFindings(findings); + expect(collisions).toHaveLength(1); + expect(collisions[0]?.title).toBe("DM principals share a session"); + expect(collisions[0]?.detail).toContain("2 distinct admitted DM principals"); + }); + + it("does not invoke finite session routing for wildcard analysis", async () => { + const resolveDmRoute = vi.fn(({ principalId, route }) => { + if (principalId === undefined) { + return { kind: "isolated" as const }; + } + if (!/^\d+$/.test(principalId)) { + throw new Error("principal must be numeric"); + } + return { sessionKey: route.sessionKey }; + }); + const findings = await collectChannelSecurityFindings({ + cfg: { session: { dmScope: "main" } }, + plugins: [ + createDmPlugin({ + accounts: { default: { policy: "open", allowFrom: ["*"] } }, + dmRouting: { resolveDmRoute }, + }), + ], + }); + + expect(resolveDmRoute).toHaveBeenCalledOnce(); + expect(resolveDmRoute.mock.calls[0]?.[0].principalId).toBeUndefined(); + expect(collisionFindings(findings)).toHaveLength(0); + }); + + it("warns when custom finite routing omits an unknown-principal policy", async () => { + const findings = await collectChannelSecurityFindings({ + cfg: { session: { dmScope: "main" } }, + plugins: [ + createDmPlugin({ + accounts: { default: { policy: "open", allowFrom: ["*"] } }, + dmRouting: { + resolveDmRoute: ({ principalId, route }) => + principalId === undefined ? undefined : { sessionKey: route.sessionKey }, + }, + }), + ], + }); + + const finding = requireFinding( findings, - "channels.telegram.dm.scope_main_multiuser", + "channels.whatsapp.dm.wildcard_routing_unverified.default", ); - expect(sharedScopeFinding.severity).toBe("warn"); + expect(finding.detail).toContain("resolveDmRoute returned no unknown-principal policy"); + }); + + it("flags public DMs and shared session ownership together", async () => { + const findings = await collectChannelSecurityFindings({ + cfg: { session: { dmScope: "main" } }, + plugins: [ + createDmPlugin({ + accounts: { default: { policy: "open", allowFrom: ["*"] } }, + }), + ], + }); + + expect(requireFinding(findings, "channels.whatsapp.dm.open").severity).toBe("critical"); + expect(collisionFindings(findings)).toHaveLength(1); }); }); diff --git a/src/security/audit-channel.ts b/src/security/audit-channel.ts index 7e425ff4d414..2ba91fc7a37d 100644 --- a/src/security/audit-channel.ts +++ b/src/security/audit-channel.ts @@ -1,3 +1,4 @@ +import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce"; // Audits channel configuration for exposure, auth, and trust risks. import { uniqueStrings } from "@openclaw/normalization-core/string-normalization"; import { @@ -9,12 +10,25 @@ import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js"; import type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; import type { ChannelId } from "../channels/plugins/types.public.js"; import { inspectReadOnlyChannelAccount } from "../channels/read-only-account-inspect.js"; -import { formatCliCommand } from "../cli/command-format.js"; import { isDangerousNameMatchingEnabled } from "../config/dangerous-name-matching.js"; +import { canonicalizeMainSessionAlias } from "../config/sessions/main-session.js"; import type { OpenClawConfig } from "../config/types.openclaw.js"; import { formatErrorMessage } from "../infra/errors.js"; +import { + listExactDirectMessageBindingPeerIds, + resolveAgentRoute, + resolveUnknownDirectMessageRoute, + type ResolvedAgentRoute, +} from "../routing/resolve-route.js"; +import { parseSessionDeliveryRoute, resolveLinkedDirectPeerId } from "../routing/session-key.js"; import type { SecurityAuditFinding, SecurityAuditSeverity } from "./audit.types.js"; +type DmPrincipalRoute = { + accountKey: string; + logicalPrincipalKey: string; + bucketKey: string; +}; + /** Classify free-form channel warnings into audit severities. */ function classifyChannelWarningSeverity(message: string): SecurityAuditSeverity { const s = message.toLowerCase(); @@ -85,9 +99,46 @@ export async function collectChannelSecurityFindings(params: { cfg: OpenClawConfig; sourceConfig?: OpenClawConfig; plugins: ChannelPlugin[]; + mode?: "audit" | "doctor"; }): Promise { const findings: SecurityAuditFinding[] = []; + const principalRoutes: DmPrincipalRoute[] = []; const sourceConfig = params.sourceConfig ?? params.cfg; + const includeAuditOnly = params.mode !== "doctor"; + const recordPrincipal = ( + plugin: ChannelPlugin, + route: ResolvedAgentRoute, + sessionKey: string, + logicalPrincipalKey: string, + indexNamespaces = false, + ) => { + const canonicalKey = canonicalizeMainSessionAlias({ + cfg: params.cfg, + agentId: route.agentId, + sessionKey, + }); + const principal = { + accountKey: `${plugin.id}-${route.accountId}`, + logicalPrincipalKey, + bucketKey: `${route.agentId}\0${canonicalKey}`, + }; + principalRoutes.push(principal); + if (!indexNamespaces) { + return; + } + const parsed = parseSessionDeliveryRoute(canonicalKey); + const directChannel = + parsed?.peerKind === "direct" || parsed?.peerKind === "dm" ? parsed.channel : undefined; + if (directChannel || (sessionKey === route.sessionKey && route.dmScope === "per-peer")) { + principalRoutes.push({ ...principal, bucketKey: `${route.agentId}\0symbolic:dm:peer` }); + } + if (directChannel) { + principalRoutes.push({ + ...principal, + bucketKey: `${route.agentId}\0symbolic:dm:channel:${directChannel}`, + }); + } + }; const inspectChannelAccount = async ( plugin: (typeof params.plugins)[number], @@ -210,19 +261,20 @@ export async function collectChannelSecurityFindings(params: { allowFrom?: Array | null; policyPath?: string; allowFromPath: string; + approveHint: string; normalizeEntry?: (raw: string) => string; }) => { const policyPath = input.policyPath ?? `${input.allowFromPath}policy`; // DM allowlist audit may need channel-specific normalization and async // account ownership checks before classifying open/multi-user exposure. - const { hasWildcard, isMultiUserDm } = await resolveDmAllowAuditState({ + const auditState = await resolveDmAllowAuditState({ provider: input.provider, accountId: input.accountId, allowFrom: input.allowFrom, dmPolicy: input.dmPolicy, normalizeEntry: input.normalizeEntry, }); - const dmScope = params.cfg.session?.dmScope ?? "main"; + const { hasWildcard } = auditState; if (input.dmPolicy === "open") { const allowFromKey = `${input.allowFromPath}allowFrom`; @@ -250,22 +302,19 @@ export async function collectChannelSecurityFindings(params: { title: `${input.label} DMs are disabled`, detail: `${policyPath}="disabled" ignores inbound DMs.`, }); - return; + return auditState; } - if (dmScope === "main" && isMultiUserDm) { + if (input.dmPolicy !== "open" && auditState.admittedPrincipals.length === 0) { findings.push({ - checkId: `channels.${input.provider}.dm.scope_main_multiuser`, - severity: "warn", - title: `${input.label} DMs share the main session`, - detail: - "Multiple DM senders currently share the main session, which can leak context across users.", - remediation: - "Run: " + - formatCliCommand('openclaw config set session.dmScope "per-channel-peer"') + - ' (or "per-account-channel-peer" for multi-account channels) to isolate DM sessions per sender.', + checkId: `channels.${input.provider}.dm.locked`, + severity: "info", + title: `${input.label} DMs are locked`, + detail: `${policyPath}="${input.dmPolicy}" has no admitted senders; unknown senders are blocked or receive a pairing code.`, + remediation: input.approveHint, }); } + return auditState; }; for (const plugin of params.plugins) { @@ -294,7 +343,7 @@ export async function collectChannelSecurityFindings(params: { findings.push({ checkId: `channels.${plugin.id}.account.read_only_resolution`, severity: "warn", - title: `${plugin.meta.label ?? plugin.id} account could not be fully resolved`, + title: `[secrets] ${plugin.meta.label ?? plugin.id} account could not be fully resolved`, detail: diagnostic, remediation: "Ensure referenced secrets are available in this shell or run with a running gateway snapshot so security audit can inspect the full channel configuration.", @@ -307,14 +356,14 @@ export async function collectChannelSecurityFindings(params: { continue; } + const accountNote = formatChannelAccountNote({ + orderedAccountIds, + hasExplicitAccountPath, + accountId, + }); const accountConfig = (account as { config?: Record } | null | undefined) ?.config; - if (isDangerousNameMatchingEnabled(accountConfig)) { - const accountNote = formatChannelAccountNote({ - orderedAccountIds, - hasExplicitAccountPath, - accountId, - }); + if (includeAuditOnly && isDangerousNameMatchingEnabled(accountConfig)) { findings.push({ checkId: `channels.${plugin.id}.allowFrom.dangerous_name_matching_enabled`, severity: "info", @@ -332,16 +381,109 @@ export async function collectChannelSecurityFindings(params: { account, }); if (dmPolicy) { - await warnDmPolicy({ - label: plugin.meta.label ?? plugin.id, + const auditState = await warnDmPolicy({ + label: `${plugin.meta.label ?? plugin.id}${accountNote}`, provider: plugin.id, accountId, dmPolicy: dmPolicy.policy, allowFrom: dmPolicy.allowFrom, policyPath: dmPolicy.policyPath, allowFromPath: dmPolicy.allowFromPath, + approveHint: dmPolicy.approveHint, normalizeEntry: dmPolicy.normalizeEntry, }); + if (dmPolicy.policy !== "disabled") { + const dmRouting = plugin.security.dmRouting; + const admittedPrincipals = uniqueStrings([ + ...auditState.admittedPrincipals, + ...(auditState.hasWildcard + ? listExactDirectMessageBindingPeerIds({ + cfg: params.cfg, + channel: plugin.id, + accountId, + }) + : []), + ]); + for (const principalId of admittedPrincipals) { + const principalContext = { cfg: params.cfg, accountId, account, principalId }; + const channelDmScope = dmRouting?.resolveDmScope?.(principalContext); + const route = resolveAgentRoute({ + cfg: params.cfg, + channel: plugin.id, + accountId, + peer: { kind: "direct", id: principalId }, + dmScope: channelDmScope, + }); + const result = dmRouting?.resolveDmRoute?.({ ...principalContext, route }); + const sessionKey = + result && "sessionKey" in result ? result.sessionKey : route.sessionKey; + const linkedIdentity = resolveLinkedDirectPeerId({ + identityLinks: params.cfg.session?.identityLinks, + channel: plugin.id, + peerId: principalId, + }); + recordPrincipal( + plugin, + route, + sessionKey, + linkedIdentity + ? `linked:${normalizeLowercaseStringOrEmpty(linkedIdentity)}` + : `direct:${plugin.id}:${route.accountId}:${normalizeLowercaseStringOrEmpty(principalId)}`, + true, + ); + } + if (auditState.hasWildcard) { + const unknownContext = { cfg: params.cfg, accountId, account }; + const route = resolveUnknownDirectMessageRoute({ + cfg: params.cfg, + channel: plugin.id, + accountId, + dmScope: dmRouting?.resolveDmScope?.(unknownContext), + }); + const customRoute = dmRouting?.resolveDmRoute; + const result = customRoute?.({ ...unknownContext, route }); + if (customRoute && !result) { + findings.push({ + checkId: `channels.${plugin.id}.dm.wildcard_routing_unverified.${route.accountId}`, + severity: "warn", + title: `${plugin.meta.label ?? plugin.id}${accountNote} wildcard DM isolation is unverified`, + detail: + "dmRouting.resolveDmRoute returned no unknown-principal policy; isolation for arbitrary senders cannot be established.", + }); + } + const useCoreRoute = + !customRoute || Boolean(result && "kind" in result && result.kind === "core"); + const sessionKey = + result && "sessionKey" in result + ? result.sessionKey + : useCoreRoute && route.dmScope === "main" + ? route.sessionKey + : undefined; + if (sessionKey) { + for (const suffix of ["1", "2"]) { + recordPrincipal( + plugin, + route, + sessionKey, + `wildcard:shared:${plugin.id}-${route.accountId}:${suffix}`, + ); + } + } else if ( + useCoreRoute && + (route.dmScope === "per-channel-peer" || route.dmScope === "per-peer") + ) { + const namespaces = + route.dmScope === "per-peer" ? ["peer"] : [`channel:${plugin.id}`, "peer"]; + for (const namespace of namespaces) { + principalRoutes.push({ + accountKey: `${plugin.id}-${route.accountId}`, + logicalPrincipalKey: `wildcard:${route.dmScope}:${plugin.id}-${route.accountId}`, + bucketKey: `${route.agentId}\0symbolic:dm:${namespace}`, + }); + } + } + } + } } if (plugin.security.collectWarnings) { @@ -363,7 +505,7 @@ export async function collectChannelSecurityFindings(params: { }); } } - if (plugin.security.collectAuditFindings) { + if (includeAuditOnly && plugin.security.collectAuditFindings) { const auditFindings = await plugin.security.collectAuditFindings({ cfg: params.cfg, sourceConfig, @@ -379,5 +521,55 @@ export async function collectChannelSecurityFindings(params: { } } + const routesByBucket = new Map(); + for (const route of principalRoutes) { + const routes = routesByBucket.get(route.bucketKey) ?? []; + routes.push(route); + routesByBucket.set(route.bucketKey, routes); + } + const groupedRoutes = [...routesByBucket.entries()].filter( + ([, routes]) => new Set(routes.map((route) => route.logicalPrincipalKey)).size > 1, + ); + const broadWildcardAgents = new Set( + groupedRoutes + .filter( + ([bucketKey, routes]) => + bucketKey.endsWith("\0symbolic:dm:peer") && + routes.some((route) => route.logicalPrincipalKey.startsWith("wildcard:per-peer:")), + ) + .map(([bucketKey]) => bucketKey.split("\0", 1)[0]), + ); + const collisions = groupedRoutes + .filter(([bucketKey, routes]) => { + if (!bucketKey.includes("\0symbolic:")) { + return true; + } + const agentId = bucketKey.split("\0", 1)[0]; + if (bucketKey.endsWith("\0symbolic:dm:peer")) { + return routes.some((route) => route.logicalPrincipalKey.startsWith("wildcard:per-peer:")); + } + return ( + !broadWildcardAgents.has(agentId) && + routes.some((route) => route.logicalPrincipalKey.startsWith("wildcard:per-channel-peer:")) + ); + }) + .toSorted(([left], [right]) => left.localeCompare(right)); + for (const [collisionIndex, [bucketKey, routes]] of collisions.entries()) { + const accountKeys = uniqueStrings(routes.map((route) => route.accountKey)).toSorted(); + const symbolic = bucketKey.includes("\0symbolic:"); + findings.push({ + checkId: `channels.dm.session_collision.${accountKeys.join("_")}.${collisionIndex + 1}`, + severity: "warn", + title: symbolic ? "DM principals may share a session" : "DM principals share a session", + detail: + `Collision topology ${collisionIndex + 1}: ${new Set(routes.map((route) => route.logicalPrincipalKey)).size} distinct admitted DM principals from ${accountKeys.join(", ")} ` + + `${symbolic ? "can resolve" : "resolve"} to the same session bucket owned by agent "${bucketKey.split("\0", 1)[0]}"` + + (params.cfg.session?.scope === "global" ? ' under session.scope="global".' : ".") + + " This can leak context across users.", + remediation: + "Set the effective DM route to an account-safe isolated scope; update the matching binding or session.dmScope as applicable.", + }); + } + return dedupeFindings(findings); }