From f59d0eac687fe2b36216911a97f1b6362fb6daca Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 3 Apr 2026 13:07:04 +0100 Subject: [PATCH] refactor(plugin-runtime): remove plugin-specific core seams --- docs/.generated/plugin-sdk-api-baseline.json | 142 +++---- docs/.generated/plugin-sdk-api-baseline.jsonl | 140 +++---- extensions/discord/src/channel.ts | 56 +-- extensions/line/src/channel.logout.test.ts | 1 - extensions/line/src/channel.ts | 8 +- extensions/line/src/gateway.ts | 9 +- extensions/line/src/outbound.ts | 36 +- extensions/signal/src/channel.ts | 13 +- extensions/slack/index.ts | 2 + extensions/slack/src/channel.ts | 44 +-- extensions/slack/src/http/plugin-routes.ts | 23 ++ extensions/telegram/src/approval-native.ts | 29 +- extensions/whatsapp/src/shared.ts | 2 + scripts/lib/plugin-sdk-facades.mjs | 347 ------------------ .../tool-result-truncation.test.ts | 2 + .../transcript-rewrite.test.ts | 2 + src/auto-reply/reply.test-harness.ts | 2 +- src/auto-reply/reply/commands-approve.ts | 45 +-- src/auto-reply/reply/commands-session.ts | 122 ++---- src/auto-reply/reply/commands.test.ts | 20 + src/auto-reply/reply/followup-runner.test.ts | 1 + src/auto-reply/reply/session.test.ts | 1 + src/channel-web.ts | 20 +- src/channels/channels-misc.test.ts | 20 +- src/channels/plugins/approvals.ts | 5 + src/channels/plugins/types.adapters.ts | 13 + src/channels/plugins/types.core.ts | 4 + ...ad-only-account-inspect.discord.runtime.ts | 11 - ...read-only-account-inspect.slack.runtime.ts | 11 - src/cli/deps.test.ts | 18 - src/cli/send-runtime/discord.ts | 14 +- src/cli/send-runtime/plugin-boundary-send.ts | 37 ++ src/cli/send-runtime/signal.ts | 14 +- src/cli/send-runtime/slack.ts | 14 +- src/cli/send-runtime/whatsapp.ts | 14 +- src/commands/health.snapshot.test.ts | 2 +- src/commands/status.test.ts | 2 +- src/config/channel-configured.ts | 21 +- ...explicit-session-key-normalization.test.ts | 56 ++- .../explicit-session-key-normalization.ts | 70 ++-- src/config/sessions/session-key.test.ts | 56 ++- .../isolated-agent/delivery-target.test.ts | 51 +-- src/cron/isolated-agent/delivery-target.ts | 50 +-- src/gateway/server-http.ts | 10 +- ...sessions.gateway-server-sessions-a.test.ts | 35 +- src/gateway/session-reset-service.ts | 13 +- src/gateway/test-helpers.mocks.ts | 8 +- .../plugin-sdk-facade-type-map.generated.ts | 201 ---------- src/infra/tsdown-config.test.ts | 1 - src/library.test.ts | 2 +- src/library.ts | 14 +- src/plugin-activation-boundary.test.ts | 26 +- src/plugin-sdk/approval-delivery-helpers.ts | 4 + src/plugin-sdk/discord-maintenance.ts | 16 - src/plugin-sdk/discord-runtime-surface.ts | 185 ---------- src/plugin-sdk/discord-send.ts | 42 --- src/plugin-sdk/signal-runtime-surface.ts | 34 -- src/plugin-sdk/slack-runtime-surface.ts | 64 ---- .../contracts/plugin-sdk-subpaths.test.ts | 2 +- .../runtime/local-runtime-module.test.ts | 14 +- src/plugins/runtime/runtime-channel.ts | 81 +--- .../runtime/runtime-discord-ops.runtime.ts | 64 ---- src/plugins/runtime/runtime-discord.ts | 122 ------ src/plugins/runtime/runtime-line.contract.ts | 38 -- src/plugins/runtime/runtime-line.runtime.ts | 11 - src/plugins/runtime/runtime-line.ts | 46 --- .../runtime/runtime-matrix-boundary.ts | 68 ---- .../runtime/runtime-matrix-contract.ts | 178 --------- src/plugins/runtime/runtime-matrix-surface.ts | 22 -- src/plugins/runtime/runtime-matrix.ts | 14 - .../runtime/runtime-plugin-boundary.ts | 51 +++ src/plugins/runtime/runtime-signal.ts | 16 - .../runtime/runtime-slack-ops.runtime.ts | 34 -- src/plugins/runtime/runtime-slack.ts | 48 --- .../runtime/runtime-web-channel-boundary.ts | 286 --------------- .../runtime/runtime-web-channel-plugin.ts | 289 +++++++++++++++ src/plugins/runtime/types-channel.ts | 95 +---- test/helpers/plugins/plugin-runtime-mock.ts | 5 - tsdown.config.ts | 1 - 79 files changed, 1062 insertions(+), 2628 deletions(-) create mode 100644 extensions/slack/src/http/plugin-routes.ts delete mode 100644 src/channels/read-only-account-inspect.discord.runtime.ts delete mode 100644 src/channels/read-only-account-inspect.slack.runtime.ts create mode 100644 src/cli/send-runtime/plugin-boundary-send.ts delete mode 100644 src/plugin-sdk/discord-maintenance.ts delete mode 100644 src/plugin-sdk/discord-runtime-surface.ts delete mode 100644 src/plugin-sdk/discord-send.ts delete mode 100644 src/plugin-sdk/signal-runtime-surface.ts delete mode 100644 src/plugin-sdk/slack-runtime-surface.ts delete mode 100644 src/plugins/runtime/runtime-discord-ops.runtime.ts delete mode 100644 src/plugins/runtime/runtime-discord.ts delete mode 100644 src/plugins/runtime/runtime-line.contract.ts delete mode 100644 src/plugins/runtime/runtime-line.runtime.ts delete mode 100644 src/plugins/runtime/runtime-line.ts delete mode 100644 src/plugins/runtime/runtime-matrix-boundary.ts delete mode 100644 src/plugins/runtime/runtime-matrix-contract.ts delete mode 100644 src/plugins/runtime/runtime-matrix-surface.ts delete mode 100644 src/plugins/runtime/runtime-matrix.ts delete mode 100644 src/plugins/runtime/runtime-signal.ts delete mode 100644 src/plugins/runtime/runtime-slack-ops.runtime.ts delete mode 100644 src/plugins/runtime/runtime-slack.ts delete mode 100644 src/plugins/runtime/runtime-web-channel-boundary.ts create mode 100644 src/plugins/runtime/runtime-web-channel-plugin.ts diff --git a/docs/.generated/plugin-sdk-api-baseline.json b/docs/.generated/plugin-sdk-api-baseline.json index bd1ed77c562..ce78e343b27 100644 --- a/docs/.generated/plugin-sdk-api-baseline.json +++ b/docs/.generated/plugin-sdk-api-baseline.json @@ -127,7 +127,7 @@ "exportName": "ChannelConfiguredBindingConversationRef", "kind": "type", "source": { - "line": 659, + "line": 675, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -136,7 +136,7 @@ "exportName": "ChannelConfiguredBindingMatch", "kind": "type", "source": { - "line": 664, + "line": 680, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -145,7 +145,7 @@ "exportName": "ChannelConfiguredBindingProvider", "kind": "type", "source": { - "line": 680, + "line": 696, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -154,7 +154,7 @@ "exportName": "ChannelGatewayContext", "kind": "type", "source": { - "line": 271, + "line": 275, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -172,7 +172,7 @@ "exportName": "ChannelMessageActionAdapter", "kind": "type", "source": { - "line": 556, + "line": 560, "path": "src/channels/plugins/types.core.ts" } }, @@ -181,7 +181,7 @@ "exportName": "ChannelMessageActionContext", "kind": "type", "source": { - "line": 520, + "line": 524, "path": "src/channels/plugins/types.core.ts" } }, @@ -1240,7 +1240,7 @@ "exportName": "BlockStreamingCoalesceSchema", "kind": "const", "source": { - "line": 341, + "line": 414, "path": "src/config/zod-schema.core.ts" } }, @@ -1249,7 +1249,7 @@ "exportName": "ContextVisibilityModeSchema", "kind": "const", "source": { - "line": 339, + "line": 412, "path": "src/config/zod-schema.core.ts" } }, @@ -1267,7 +1267,7 @@ "exportName": "DmConfigSchema", "kind": "const", "source": { - "line": 294, + "line": 367, "path": "src/config/zod-schema.core.ts" } }, @@ -1276,7 +1276,7 @@ "exportName": "DmPolicySchema", "kind": "const", "source": { - "line": 338, + "line": 411, "path": "src/config/zod-schema.core.ts" } }, @@ -1294,7 +1294,7 @@ "exportName": "GroupPolicySchema", "kind": "const", "source": { - "line": 336, + "line": 409, "path": "src/config/zod-schema.core.ts" } }, @@ -1312,7 +1312,7 @@ "exportName": "MarkdownConfigSchema", "kind": "const", "source": { - "line": 374, + "line": 447, "path": "src/config/zod-schema.core.ts" } }, @@ -1330,7 +1330,7 @@ "exportName": "ReplyRuntimeConfigSchemaShape", "kind": "const", "source": { - "line": 349, + "line": 422, "path": "src/config/zod-schema.core.ts" } }, @@ -1339,7 +1339,7 @@ "exportName": "requireOpenAllowFrom", "kind": "const", "source": { - "line": 489, + "line": 562, "path": "src/config/zod-schema.core.ts" } }, @@ -1404,7 +1404,7 @@ "exportName": "BaseProbeResult", "kind": "type", "source": { - "line": 599, + "line": 603, "path": "src/channels/plugins/types.core.ts" } }, @@ -1413,7 +1413,7 @@ "exportName": "BaseTokenResolution", "kind": "type", "source": { - "line": 605, + "line": 609, "path": "src/channels/plugins/types.core.ts" } }, @@ -1440,7 +1440,7 @@ "exportName": "ChannelApprovalAdapter", "kind": "type", "source": { - "line": 597, + "line": 613, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -1449,7 +1449,7 @@ "exportName": "ChannelApprovalCapability", "kind": "type", "source": { - "line": 592, + "line": 602, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -1458,7 +1458,7 @@ "exportName": "ChannelCommandConversationContext", "kind": "type", "source": { - "line": 668, + "line": 684, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -1467,7 +1467,7 @@ "exportName": "ChannelDirectoryAdapter", "kind": "type", "source": { - "line": 454, + "line": 459, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -1485,7 +1485,7 @@ "exportName": "ChannelMessageActionAdapter", "kind": "type", "source": { - "line": 556, + "line": 560, "path": "src/channels/plugins/types.core.ts" } }, @@ -1494,7 +1494,7 @@ "exportName": "ChannelMessageActionContext", "kind": "type", "source": { - "line": 520, + "line": 524, "path": "src/channels/plugins/types.core.ts" } }, @@ -1941,7 +1941,7 @@ "exportName": "BaseProbeResult", "kind": "type", "source": { - "line": 599, + "line": 603, "path": "src/channels/plugins/types.core.ts" } }, @@ -1950,7 +1950,7 @@ "exportName": "BaseTokenResolution", "kind": "type", "source": { - "line": 605, + "line": 609, "path": "src/channels/plugins/types.core.ts" } }, @@ -1986,7 +1986,7 @@ "exportName": "ChannelAgentPromptAdapter", "kind": "type", "source": { - "line": 493, + "line": 497, "path": "src/channels/plugins/types.core.ts" } }, @@ -2013,7 +2013,7 @@ "exportName": "ChannelAllowlistAdapter", "kind": "type", "source": { - "line": 603, + "line": 619, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2022,7 +2022,7 @@ "exportName": "ChannelApprovalAdapter", "kind": "type", "source": { - "line": 597, + "line": 613, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2031,7 +2031,7 @@ "exportName": "ChannelApprovalCapability", "kind": "type", "source": { - "line": 592, + "line": 602, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2058,7 +2058,7 @@ "exportName": "ChannelAuthAdapter", "kind": "type", "source": { - "line": 395, + "line": 399, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2103,7 +2103,7 @@ "exportName": "ChannelCommandAdapter", "kind": "type", "source": { - "line": 492, + "line": 497, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2112,7 +2112,7 @@ "exportName": "ChannelCommandConversationContext", "kind": "type", "source": { - "line": 668, + "line": 684, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2130,7 +2130,7 @@ "exportName": "ChannelConfiguredBindingConversationRef", "kind": "type", "source": { - "line": 659, + "line": 675, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2139,7 +2139,7 @@ "exportName": "ChannelConfiguredBindingMatch", "kind": "type", "source": { - "line": 664, + "line": 680, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2148,7 +2148,7 @@ "exportName": "ChannelConfiguredBindingProvider", "kind": "type", "source": { - "line": 680, + "line": 696, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2157,7 +2157,7 @@ "exportName": "ChannelConversationBindingSupport", "kind": "type", "source": { - "line": 696, + "line": 712, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2166,7 +2166,7 @@ "exportName": "ChannelDirectoryAdapter", "kind": "type", "source": { - "line": 454, + "line": 459, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2175,7 +2175,7 @@ "exportName": "ChannelDirectoryEntry", "kind": "type", "source": { - "line": 507, + "line": 511, "path": "src/channels/plugins/types.core.ts" } }, @@ -2184,7 +2184,7 @@ "exportName": "ChannelDirectoryEntryKind", "kind": "type", "source": { - "line": 505, + "line": 509, "path": "src/channels/plugins/types.core.ts" } }, @@ -2193,7 +2193,7 @@ "exportName": "ChannelElevatedAdapter", "kind": "type", "source": { - "line": 485, + "line": 490, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2202,7 +2202,7 @@ "exportName": "ChannelGatewayAdapter", "kind": "type", "source": { - "line": 379, + "line": 383, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2211,7 +2211,7 @@ "exportName": "ChannelGatewayContext", "kind": "type", "source": { - "line": 271, + "line": 275, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2220,7 +2220,7 @@ "exportName": "ChannelGroupAdapter", "kind": "type", "source": { - "line": 129, + "line": 133, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2238,7 +2238,7 @@ "exportName": "ChannelHeartbeatAdapter", "kind": "type", "source": { - "line": 420, + "line": 425, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2265,7 +2265,7 @@ "exportName": "ChannelLifecycleAdapter", "kind": "type", "source": { - "line": 497, + "line": 502, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2274,7 +2274,7 @@ "exportName": "ChannelLoginWithQrStartResult", "kind": "type", "source": { - "line": 350, + "line": 354, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2283,7 +2283,7 @@ "exportName": "ChannelLoginWithQrWaitResult", "kind": "type", "source": { - "line": 355, + "line": 359, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2292,7 +2292,7 @@ "exportName": "ChannelLogoutContext", "kind": "type", "source": { - "line": 360, + "line": 364, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2301,7 +2301,7 @@ "exportName": "ChannelLogoutResult", "kind": "type", "source": { - "line": 344, + "line": 348, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2328,7 +2328,7 @@ "exportName": "ChannelMessageActionAdapter", "kind": "type", "source": { - "line": 556, + "line": 560, "path": "src/channels/plugins/types.core.ts" } }, @@ -2337,7 +2337,7 @@ "exportName": "ChannelMessageActionContext", "kind": "type", "source": { - "line": 520, + "line": 524, "path": "src/channels/plugins/types.core.ts" } }, @@ -2409,7 +2409,7 @@ "exportName": "ChannelOutboundAdapter", "kind": "type", "source": { - "line": 175, + "line": 179, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2418,7 +2418,7 @@ "exportName": "ChannelOutboundContext", "kind": "type", "source": { - "line": 135, + "line": 139, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2427,7 +2427,7 @@ "exportName": "ChannelOutboundPayloadHint", "kind": "type", "source": { - "line": 160, + "line": 164, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2445,7 +2445,7 @@ "exportName": "ChannelOutboundTargetRef", "kind": "type", "source": { - "line": 164, + "line": 168, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2454,7 +2454,7 @@ "exportName": "ChannelPairingAdapter", "kind": "type", "source": { - "line": 368, + "line": 372, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2472,7 +2472,7 @@ "exportName": "ChannelPollContext", "kind": "type", "source": { - "line": 587, + "line": 591, "path": "src/channels/plugins/types.core.ts" } }, @@ -2481,7 +2481,7 @@ "exportName": "ChannelPollResult", "kind": "type", "source": { - "line": 578, + "line": 582, "path": "src/channels/plugins/types.core.ts" } }, @@ -2490,7 +2490,7 @@ "exportName": "ChannelResolveKind", "kind": "type", "source": { - "line": 465, + "line": 470, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2499,7 +2499,7 @@ "exportName": "ChannelResolverAdapter", "kind": "type", "source": { - "line": 475, + "line": 480, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2508,7 +2508,7 @@ "exportName": "ChannelResolveResult", "kind": "type", "source": { - "line": 467, + "line": 472, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2517,7 +2517,7 @@ "exportName": "ChannelSecurityAdapter", "kind": "type", "source": { - "line": 727, + "line": 743, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2562,7 +2562,7 @@ "exportName": "ChannelStatusAdapter", "kind": "type", "source": { - "line": 217, + "line": 221, "path": "src/channels/plugins/types.adapters.ts" } }, @@ -2625,7 +2625,7 @@ "exportName": "ChannelToolSend", "kind": "type", "source": { - "line": 549, + "line": 553, "path": "src/channels/plugins/types.core.ts" } }, @@ -3237,11 +3237,11 @@ } }, { - "declaration": "export function resolveStoredModelOverride(params: { sessionEntry?: SessionEntry | undefined; sessionStore?: Record | undefined; sessionKey?: string | undefined; parentSessionKey?: string | undefined; }): StoredModelOverride | null;", + "declaration": "export function resolveStoredModelOverride(params: { sessionEntry?: SessionEntry | undefined; sessionStore?: Record | undefined; sessionKey?: string | undefined; parentSessionKey?: string | undefined; defaultProvider: string; }): StoredModelOverride | null;", "exportName": "resolveStoredModelOverride", "kind": "function", "source": { - "line": 156, + "line": 145, "path": "src/auto-reply/reply/model-selection.ts" } }, @@ -3502,7 +3502,7 @@ "exportName": "StoredModelOverride", "kind": "type", "source": { - "line": 123, + "line": 124, "path": "src/auto-reply/reply/model-selection.ts" } } @@ -3954,7 +3954,7 @@ "exportName": "ChannelMessageActionContext", "kind": "type", "source": { - "line": 520, + "line": 524, "path": "src/channels/plugins/types.core.ts" } }, @@ -5308,7 +5308,7 @@ "exportName": "ModelApi", "kind": "type", "source": { - "line": 16, + "line": 17, "path": "src/config/types.models.ts" } }, @@ -5317,7 +5317,7 @@ "exportName": "ModelDefinitionConfig", "kind": "type", "source": { - "line": 49, + "line": 50, "path": "src/config/types.models.ts" } }, @@ -5326,7 +5326,7 @@ "exportName": "ModelProviderConfig", "kind": "type", "source": { - "line": 67, + "line": 68, "path": "src/config/types.models.ts" } }, @@ -6099,7 +6099,7 @@ "exportName": "ChannelGatewayContext", "kind": "type", "source": { - "line": 271, + "line": 275, "path": "src/channels/plugins/types.adapters.ts" } }, diff --git a/docs/.generated/plugin-sdk-api-baseline.jsonl b/docs/.generated/plugin-sdk-api-baseline.jsonl index 4c820e3a296..9bc8ad5fe40 100644 --- a/docs/.generated/plugin-sdk-api-baseline.jsonl +++ b/docs/.generated/plugin-sdk-api-baseline.jsonl @@ -12,13 +12,13 @@ {"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"index","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelConfigSchema = ChannelConfigSchema;","entrypoint":"index","exportName":"ChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":71,"sourcePath":"src/channels/plugins/types.plugin.ts"} {"declaration":"export type ChannelConfigUiHint = ChannelConfigUiHint;","entrypoint":"index","exportName":"ChannelConfigUiHint","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":40,"sourcePath":"src/channels/plugins/types.plugin.ts"} -{"declaration":"export type ChannelConfiguredBindingConversationRef = ChannelConfiguredBindingConversationRef;","entrypoint":"index","exportName":"ChannelConfiguredBindingConversationRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":659,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"index","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":664,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"index","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":680,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext;","entrypoint":"index","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":271,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelConfiguredBindingConversationRef = ChannelConfiguredBindingConversationRef;","entrypoint":"index","exportName":"ChannelConfiguredBindingConversationRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":675,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"index","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":680,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"index","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":696,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext;","entrypoint":"index","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":275,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelId = ChannelId;","entrypoint":"index","exportName":"ChannelId","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"index","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":556,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"index","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":520,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"index","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":560,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"index","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"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\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\" | \"upload-file\";","entrypoint":"index","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"} {"declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"index","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":81,"sourcePath":"src/channels/plugins/types.plugin.ts"} {"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"index","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.adapters.ts"} @@ -135,35 +135,35 @@ {"declaration":"export function buildChannelConfigSchema(schema: ZodType>, options?: BuildChannelConfigSchemaOptions | undefined): ChannelConfigSchema;","entrypoint":"channel-config-schema","exportName":"buildChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"function","recordType":"export","sourceLine":76,"sourcePath":"src/channels/plugins/config-schema.ts"} {"declaration":"export function buildNestedDmConfigSchema(extraShape?: TExtraShape | undefined): ZodOptional; policy: ZodOptional>; allowFrom: ZodOptional<...>; }, $strip>>;","entrypoint":"channel-config-schema","exportName":"buildNestedDmConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"function","recordType":"export","sourceLine":21,"sourcePath":"src/channels/plugins/config-schema.ts"} {"declaration":"export const AllowFromListSchema: z.ZodOptional>>;","entrypoint":"channel-config-schema","exportName":"AllowFromListSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":19,"sourcePath":"src/channels/plugins/config-schema.ts"} -{"declaration":"export const BlockStreamingCoalesceSchema: z.ZodObject<{ minChars: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"BlockStreamingCoalesceSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":341,"sourcePath":"src/config/zod-schema.core.ts"} -{"declaration":"export const ContextVisibilityModeSchema: z.ZodEnum<{ allowlist: \"allowlist\"; all: \"all\"; allowlist_quote: \"allowlist_quote\"; }>;","entrypoint":"channel-config-schema","exportName":"ContextVisibilityModeSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":339,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const BlockStreamingCoalesceSchema: z.ZodObject<{ minChars: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"BlockStreamingCoalesceSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":414,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const ContextVisibilityModeSchema: z.ZodEnum<{ allowlist: \"allowlist\"; all: \"all\"; allowlist_quote: \"allowlist_quote\"; }>;","entrypoint":"channel-config-schema","exportName":"ContextVisibilityModeSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":412,"sourcePath":"src/config/zod-schema.core.ts"} {"declaration":"export const DiscordConfigSchema: z.ZodObject<{ name: z.ZodOptional; capabilities: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; commands: z.ZodOptional]>>; nativeSkills: z.ZodOptional]>>; }, z.core.$strict>>; configWrites: z.ZodOptional; token: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; proxy: z.ZodOptional; allowBots: z.ZodOptional]>>; dangerouslyAllowNameMatching: z.ZodOptional; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streaming: z.ZodOptional]>>; streamMode: z.ZodOptional>; draftChunk: z.ZodOptional; maxChars: z.ZodOptional; breakPreference: z.ZodOptional, z.ZodLiteral<\"newline\">, z.ZodLiteral<\"sentence\">]>>; }, z.core.$strict>>; maxLinesPerMessage: z.ZodOptional; mediaMaxMb: z.ZodOptional; retry: z.ZodOptional; minDelayMs: z.ZodOptional; maxDelayMs: z.ZodOptional; jitter: z.ZodOptional; }, z.core.$strict>>; actions: z.ZodOptional; stickers: z.ZodOptional; emojiUploads: z.ZodOptional; stickerUploads: z.ZodOptional; polls: z.ZodOptional; permissions: z.ZodOptional; messages: z.ZodOptional; threads: z.ZodOptional; pins: z.ZodOptional; search: z.ZodOptional; memberInfo: z.ZodOptional; roleInfo: z.ZodOptional; roles: z.ZodOptional; channelInfo: z.ZodOptional; voiceStatus: z.ZodOptional; events: z.ZodOptional; moderation: z.ZodOptional; channels: z.ZodOptional; presence: z.ZodOptional; }, z.core.$strict>>; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; dmPolicy: z.ZodOptional>; allowFrom: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; defaultTo: z.ZodOptional; dm: z.ZodOptional; policy: z.ZodOptional>; allowFrom: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; groupEnabled: z.ZodOptional; groupChannels: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; }, z.core.$strict>>; guilds: z.ZodOptional; requireMention: z.ZodOptional; ignoreOtherMentions: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; reactionNotifications: z.ZodOptional>; users: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; roles: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; channels: z.ZodOptional; requireMention: z.ZodOptional; ignoreOtherMentions: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; skills: z.ZodOptional>; enabled: z.ZodOptional; users: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; roles: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; systemPrompt: z.ZodOptional; includeThreadStarter: z.ZodOptional; autoThread: z.ZodOptional; autoThreadName: z.ZodOptional>; autoArchiveDuration: z.ZodOptional, z.ZodLiteral<60>, z.ZodLiteral<1440>, z.ZodLiteral<4320>, z.ZodLiteral<10080>]>>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; execApprovals: z.ZodOptional; approvers: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; agentFilter: z.ZodOptional>; sessionFilter: z.ZodOptional>; cleanupAfterResolve: z.ZodOptional; target: z.ZodOptional>; }, z.core.$strict>>; agentComponents: z.ZodOptional; }, z.core.$strict>>; ui: z.ZodOptional; }, z.core.$strict>>; }, z.core.$strict>>; slashCommand: z.ZodOptional; }, z.core.$strict>>; threadBindings: z.ZodOptional; idleHours: z.ZodOptional; maxAgeHours: z.ZodOptional; spawnSubagentSessions: z.ZodOptional; spawnAcpSessions: z.ZodOptional; }, z.core.$strict>>; intents: z.ZodOptional; guildMembers: z.ZodOptional; }, z.core.$strict>>; voice: z.ZodOptional; autoJoin: z.ZodOptional>>; daveEncryption: z.ZodOptional; decryptionFailureTolerance: z.ZodOptional; tts: z.ZodOptional>; enabled: z.ZodOptional; mode: z.ZodOptional>; provider: z.ZodOptional; summaryModel: z.ZodOptional; modelOverrides: z.ZodOptional; allowText: z.ZodOptional; allowProvider: z.ZodOptional; allowVoice: z.ZodOptional; allowModelId: z.ZodOptional; allowVoiceSettings: z.ZodOptional; allowNormalization: z.ZodOptional; allowSeed: z.ZodOptional; }, z.core.$strict>>; providers: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; }, z.core.$catchall, z.ZodRecord]>>>>>; prefsPath: z.ZodOptional; maxTextLength: z.ZodOptional; timeoutMs: z.ZodOptional; }, z.core.$strict>>>; }, z.core.$strict>>; pluralkit: z.ZodOptional; token: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; }, z.core.$strict>>; responsePrefix: z.ZodOptional; ackReaction: z.ZodOptional; ackReactionScope: z.ZodOptional>; activity: z.ZodOptional; status: z.ZodOptional>; autoPresence: z.ZodOptional; intervalMs: z.ZodOptional; minUpdateIntervalMs: z.ZodOptional; healthyText: z.ZodOptional; degradedText: z.ZodOptional; exhaustedText: z.ZodOptional; }, z.core.$strict>>; activityType: z.ZodOptional, z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>, z.ZodLiteral<5>]>>; activityUrl: z.ZodOptional; inboundWorker: z.ZodOptional; }, z.core.$strict>>; eventQueue: z.ZodOptional; maxQueueSize: z.ZodOptional; maxConcurrency: z.ZodOptional; }, z.core.$strict>>; accounts: z.ZodOptional; capabilities: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; commands: z.ZodOptional]>>; nativeSkills: z.ZodOptional]>>; }, z.core.$strict>>; configWrites: z.ZodOptional; token: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; proxy: z.ZodOptional; allowBots: z.ZodOptional]>>; dangerouslyAllowNameMatching: z.ZodOptional; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streaming: z.ZodOptional]>>; streamMode: z.ZodOptional>; draftChunk: z.ZodOptional; maxChars: z.ZodOptional; breakPreference: z.ZodOptional, z.ZodLiteral<\"newline\">, z.ZodLiteral<\"sentence\">]>>; }, z.core.$strict>>; maxLinesPerMessage: z.ZodOptional; mediaMaxMb: z.ZodOptional; retry: z.ZodOptional; minDelayMs: z.ZodOptional; maxDelayMs: z.ZodOptional; jitter: z.ZodOptional; }, z.core.$strict>>; actions: z.ZodOptional; stickers: z.ZodOptional; emojiUploads: z.ZodOptional; stickerUploads: z.ZodOptional; polls: z.ZodOptional; permissions: z.ZodOptional; messages: z.ZodOptional; threads: z.ZodOptional; pins: z.ZodOptional; search: z.ZodOptional; memberInfo: z.ZodOptional; roleInfo: z.ZodOptional; roles: z.ZodOptional; channelInfo: z.ZodOptional; voiceStatus: z.ZodOptional; events: z.ZodOptional; moderation: z.ZodOptional; channels: z.ZodOptional; presence: z.ZodOptional; }, z.core.$strict>>; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; dmPolicy: z.ZodOptional>; allowFrom: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; defaultTo: z.ZodOptional; dm: z.ZodOptional; policy: z.ZodOptional>; allowFrom: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; groupEnabled: z.ZodOptional; groupChannels: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; }, z.core.$strict>>; guilds: z.ZodOptional; requireMention: z.ZodOptional; ignoreOtherMentions: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; reactionNotifications: z.ZodOptional>; users: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; roles: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; channels: z.ZodOptional; requireMention: z.ZodOptional; ignoreOtherMentions: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; skills: z.ZodOptional>; enabled: z.ZodOptional; users: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; roles: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; systemPrompt: z.ZodOptional; includeThreadStarter: z.ZodOptional; autoThread: z.ZodOptional; autoThreadName: z.ZodOptional>; autoArchiveDuration: z.ZodOptional, z.ZodLiteral<60>, z.ZodLiteral<1440>, z.ZodLiteral<4320>, z.ZodLiteral<10080>]>>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; execApprovals: z.ZodOptional; approvers: z.ZodOptional, z.ZodTransform>, z.ZodString>>>; agentFilter: z.ZodOptional>; sessionFilter: z.ZodOptional>; cleanupAfterResolve: z.ZodOptional; target: z.ZodOptional>; }, z.core.$strict>>; agentComponents: z.ZodOptional; }, z.core.$strict>>; ui: z.ZodOptional; }, z.core.$strict>>; }, z.core.$strict>>; slashCommand: z.ZodOptional; }, z.core.$strict>>; threadBindings: z.ZodOptional; idleHours: z.ZodOptional; maxAgeHours: z.ZodOptional; spawnSubagentSessions: z.ZodOptional; spawnAcpSessions: z.ZodOptional; }, z.core.$strict>>; intents: z.ZodOptional; guildMembers: z.ZodOptional; }, z.core.$strict>>; voice: z.ZodOptional; autoJoin: z.ZodOptional>>; daveEncryption: z.ZodOptional; decryptionFailureTolerance: z.ZodOptional; tts: z.ZodOptional>; enabled: z.ZodOptional; mode: z.ZodOptional>; provider: z.ZodOptional; summaryModel: z.ZodOptional; modelOverrides: z.ZodOptional; allowText: z.ZodOptional; allowProvider: z.ZodOptional; allowVoice: z.ZodOptional; allowModelId: z.ZodOptional; allowVoiceSettings: z.ZodOptional; allowNormalization: z.ZodOptional; allowSeed: z.ZodOptional; }, z.core.$strict>>; providers: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; }, z.core.$catchall, z.ZodRecord]>>>>>; prefsPath: z.ZodOptional; maxTextLength: z.ZodOptional; timeoutMs: z.ZodOptional; }, z.core.$strict>>>; }, z.core.$strict>>; pluralkit: z.ZodOptional; token: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; }, z.core.$strict>>; responsePrefix: z.ZodOptional; ackReaction: z.ZodOptional; ackReactionScope: z.ZodOptional>; activity: z.ZodOptional; status: z.ZodOptional>; autoPresence: z.ZodOptional; intervalMs: z.ZodOptional; minUpdateIntervalMs: z.ZodOptional; healthyText: z.ZodOptional; degradedText: z.ZodOptional; exhaustedText: z.ZodOptional; }, z.core.$strict>>; activityType: z.ZodOptional, z.ZodLiteral<1>, z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<4>, z.ZodLiteral<5>]>>; activityUrl: z.ZodOptional; inboundWorker: z.ZodOptional; }, z.core.$strict>>; eventQueue: z.ZodOptional; maxQueueSize: z.ZodOptional; maxConcurrency: z.ZodOptional; }, z.core.$strict>>; }, z.core.$strict>>>>; defaultAccount: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"DiscordConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":710,"sourcePath":"src/config/zod-schema.providers-core.ts"} -{"declaration":"export const DmConfigSchema: z.ZodObject<{ historyLimit: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"DmConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":294,"sourcePath":"src/config/zod-schema.core.ts"} -{"declaration":"export const DmPolicySchema: z.ZodEnum<{ disabled: \"disabled\"; pairing: \"pairing\"; allowlist: \"allowlist\"; open: \"open\"; }>;","entrypoint":"channel-config-schema","exportName":"DmPolicySchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":338,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const DmConfigSchema: z.ZodObject<{ historyLimit: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"DmConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":367,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const DmPolicySchema: z.ZodEnum<{ disabled: \"disabled\"; pairing: \"pairing\"; allowlist: \"allowlist\"; open: \"open\"; }>;","entrypoint":"channel-config-schema","exportName":"DmPolicySchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":411,"sourcePath":"src/config/zod-schema.core.ts"} {"declaration":"export const GoogleChatConfigSchema: z.ZodObject<{ name: z.ZodOptional; capabilities: z.ZodOptional>; enabled: z.ZodOptional; configWrites: z.ZodOptional; allowBots: z.ZodOptional; dangerouslyAllowNameMatching: z.ZodOptional; requireMention: z.ZodOptional; groupPolicy: z.ZodDefault>>; groupAllowFrom: z.ZodOptional>>; groups: z.ZodOptional; allow: z.ZodOptional; requireMention: z.ZodOptional; users: z.ZodOptional>>; systemPrompt: z.ZodOptional; }, z.core.$strict>>>>; defaultTo: z.ZodOptional; serviceAccount: z.ZodOptional, z.ZodDiscriminatedUnion<[z.ZodObject<{ source: z.ZodLiteral<\"env\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; serviceAccountRef: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">>; serviceAccountFile: z.ZodOptional; audienceType: z.ZodOptional>; audience: z.ZodOptional; appPrincipal: z.ZodOptional; webhookPath: z.ZodOptional; webhookUrl: z.ZodOptional; botUser: z.ZodOptional; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streamMode: z.ZodDefault>>; mediaMaxMb: z.ZodOptional; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; actions: z.ZodOptional; }, z.core.$strict>>; dm: z.ZodOptional; policy: z.ZodDefault>>; allowFrom: z.ZodOptional>>; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; typingIndicator: z.ZodOptional>; responsePrefix: z.ZodOptional; accounts: z.ZodOptional; capabilities: z.ZodOptional>; enabled: z.ZodOptional; configWrites: z.ZodOptional; allowBots: z.ZodOptional; dangerouslyAllowNameMatching: z.ZodOptional; requireMention: z.ZodOptional; groupPolicy: z.ZodDefault>>; groupAllowFrom: z.ZodOptional>>; groups: z.ZodOptional; allow: z.ZodOptional; requireMention: z.ZodOptional; users: z.ZodOptional>>; systemPrompt: z.ZodOptional; }, z.core.$strict>>>>; defaultTo: z.ZodOptional; serviceAccount: z.ZodOptional, z.ZodDiscriminatedUnion<[z.ZodObject<{ source: z.ZodLiteral<\"env\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; serviceAccountRef: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">>; serviceAccountFile: z.ZodOptional; audienceType: z.ZodOptional>; audience: z.ZodOptional; appPrincipal: z.ZodOptional; webhookPath: z.ZodOptional; webhookUrl: z.ZodOptional; botUser: z.ZodOptional; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streamMode: z.ZodDefault>>; mediaMaxMb: z.ZodOptional; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; actions: z.ZodOptional; }, z.core.$strict>>; dm: z.ZodOptional; policy: z.ZodDefault>>; allowFrom: z.ZodOptional>>; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; typingIndicator: z.ZodOptional>; responsePrefix: z.ZodOptional; }, z.core.$strict>>>>; defaultAccount: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"GoogleChatConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":849,"sourcePath":"src/config/zod-schema.providers-core.ts"} -{"declaration":"export const GroupPolicySchema: z.ZodEnum<{ disabled: \"disabled\"; allowlist: \"allowlist\"; open: \"open\"; }>;","entrypoint":"channel-config-schema","exportName":"GroupPolicySchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":336,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const GroupPolicySchema: z.ZodEnum<{ disabled: \"disabled\"; allowlist: \"allowlist\"; open: \"open\"; }>;","entrypoint":"channel-config-schema","exportName":"GroupPolicySchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":409,"sourcePath":"src/config/zod-schema.core.ts"} {"declaration":"export const IMessageConfigSchema: z.ZodObject<{ name: z.ZodOptional; capabilities: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; configWrites: z.ZodOptional; cliPath: z.ZodOptional; dbPath: z.ZodOptional; remoteHost: z.ZodOptional; service: z.ZodOptional, z.ZodLiteral<\"sms\">, z.ZodLiteral<\"auto\">]>>; region: z.ZodOptional; dmPolicy: z.ZodDefault>>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional; groupAllowFrom: z.ZodOptional>>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; includeAttachments: z.ZodOptional; attachmentRoots: z.ZodOptional>; remoteAttachmentRoots: z.ZodOptional>; mediaMaxMb: z.ZodOptional; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; groups: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; accounts: z.ZodOptional; capabilities: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; configWrites: z.ZodOptional; cliPath: z.ZodOptional; dbPath: z.ZodOptional; remoteHost: z.ZodOptional; service: z.ZodOptional, z.ZodLiteral<\"sms\">, z.ZodLiteral<\"auto\">]>>; region: z.ZodOptional; dmPolicy: z.ZodDefault>>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional; groupAllowFrom: z.ZodOptional>>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; includeAttachments: z.ZodOptional; attachmentRoots: z.ZodOptional>; remoteAttachmentRoots: z.ZodOptional>; mediaMaxMb: z.ZodOptional; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; groups: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; }, z.core.$strict>>>>; defaultAccount: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"IMessageConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":1363,"sourcePath":"src/config/zod-schema.providers-core.ts"} -{"declaration":"export const MarkdownConfigSchema: z.ZodOptional>; }, z.core.$strict>>;","entrypoint":"channel-config-schema","exportName":"MarkdownConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":374,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const MarkdownConfigSchema: z.ZodOptional>; }, z.core.$strict>>;","entrypoint":"channel-config-schema","exportName":"MarkdownConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":447,"sourcePath":"src/config/zod-schema.core.ts"} {"declaration":"export const MSTeamsConfigSchema: z.ZodObject<{ enabled: z.ZodOptional; capabilities: z.ZodOptional>; dangerouslyAllowNameMatching: z.ZodOptional; markdown: z.ZodOptional>; }, z.core.$strict>>; configWrites: z.ZodOptional; appId: z.ZodOptional; appPassword: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; tenantId: z.ZodOptional; webhook: z.ZodOptional; path: z.ZodOptional; }, z.core.$strict>>; dmPolicy: z.ZodDefault>>; allowFrom: z.ZodOptional>; defaultTo: z.ZodOptional; groupAllowFrom: z.ZodOptional>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; mediaAllowHosts: z.ZodOptional>; mediaAuthAllowHosts: z.ZodOptional>; requireMention: z.ZodOptional; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; replyStyle: z.ZodOptional>; teams: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; replyStyle: z.ZodOptional>; channels: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; replyStyle: z.ZodOptional>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; mediaMaxMb: z.ZodOptional; sharePointSiteId: z.ZodOptional; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; welcomeCard: z.ZodOptional; promptStarters: z.ZodOptional>; groupWelcomeCard: z.ZodOptional; feedbackEnabled: z.ZodOptional; feedbackReflection: z.ZodOptional; feedbackReflectionCooldownMs: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"MSTeamsConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":1547,"sourcePath":"src/config/zod-schema.providers-core.ts"} -{"declaration":"export const ReplyRuntimeConfigSchemaShape: { historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; contextVisibility: z.ZodOptional>; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; mediaMaxMb: z.ZodOptional; };","entrypoint":"channel-config-schema","exportName":"ReplyRuntimeConfigSchemaShape","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":349,"sourcePath":"src/config/zod-schema.core.ts"} -{"declaration":"export const requireOpenAllowFrom: (params: { policy?: string; allowFrom?: Array; ctx: z.RefinementCtx; path: Array; message: string; }) => void;","entrypoint":"channel-config-schema","exportName":"requireOpenAllowFrom","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":489,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const ReplyRuntimeConfigSchemaShape: { historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; contextVisibility: z.ZodOptional>; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; mediaMaxMb: z.ZodOptional; };","entrypoint":"channel-config-schema","exportName":"ReplyRuntimeConfigSchemaShape","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":422,"sourcePath":"src/config/zod-schema.core.ts"} +{"declaration":"export const requireOpenAllowFrom: (params: { policy?: string; allowFrom?: Array; ctx: z.RefinementCtx; path: Array; message: string; }) => void;","entrypoint":"channel-config-schema","exportName":"requireOpenAllowFrom","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":562,"sourcePath":"src/config/zod-schema.core.ts"} {"declaration":"export const SignalConfigSchema: z.ZodObject<{ name: z.ZodOptional; capabilities: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; configWrites: z.ZodOptional; account: z.ZodOptional; accountUuid: z.ZodOptional; httpUrl: z.ZodOptional; httpHost: z.ZodOptional; httpPort: z.ZodOptional; cliPath: z.ZodOptional; autoStart: z.ZodOptional; startupTimeoutMs: z.ZodOptional; receiveMode: z.ZodOptional, z.ZodLiteral<\"manual\">]>>; ignoreAttachments: z.ZodOptional; ignoreStories: z.ZodOptional; sendReadReceipts: z.ZodOptional; dmPolicy: z.ZodDefault>>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional; groupAllowFrom: z.ZodOptional>>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; groups: z.ZodOptional; ingest: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; mediaMaxMb: z.ZodOptional; reactionNotifications: z.ZodOptional>; reactionAllowlist: z.ZodOptional>>; actions: z.ZodOptional; }, z.core.$strict>>; reactionLevel: z.ZodOptional>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; accounts: z.ZodOptional; capabilities: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; configWrites: z.ZodOptional; account: z.ZodOptional; accountUuid: z.ZodOptional; httpUrl: z.ZodOptional; httpHost: z.ZodOptional; httpPort: z.ZodOptional; cliPath: z.ZodOptional; autoStart: z.ZodOptional; startupTimeoutMs: z.ZodOptional; receiveMode: z.ZodOptional, z.ZodLiteral<\"manual\">]>>; ignoreAttachments: z.ZodOptional; ignoreStories: z.ZodOptional; sendReadReceipts: z.ZodOptional; dmPolicy: z.ZodDefault>>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional; groupAllowFrom: z.ZodOptional>>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; groups: z.ZodOptional; ingest: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; mediaMaxMb: z.ZodOptional; reactionNotifications: z.ZodOptional>; reactionAllowlist: z.ZodOptional>>; actions: z.ZodOptional; }, z.core.$strict>>; reactionLevel: z.ZodOptional>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; }, z.core.$strict>>>>; defaultAccount: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"SignalConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":1119,"sourcePath":"src/config/zod-schema.providers-core.ts"} {"declaration":"export const SlackConfigSchema: z.ZodObject<{ name: z.ZodOptional; capabilities: z.ZodOptional, z.ZodObject<{ interactiveReplies: z.ZodOptional; }, z.core.$strict>]>>; execApprovals: z.ZodOptional; approvers: z.ZodOptional>>; agentFilter: z.ZodOptional>; sessionFilter: z.ZodOptional>; target: z.ZodOptional>; }, z.core.$strict>>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; commands: z.ZodOptional]>>; nativeSkills: z.ZodOptional]>>; }, z.core.$strict>>; configWrites: z.ZodOptional; botToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; appToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; userToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; userTokenReadOnly: z.ZodDefault>; allowBots: z.ZodOptional; dangerouslyAllowNameMatching: z.ZodOptional; requireMention: z.ZodOptional; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streaming: z.ZodOptional]>>; nativeStreaming: z.ZodOptional; streamMode: z.ZodOptional>; mediaMaxMb: z.ZodOptional; reactionNotifications: z.ZodOptional>; reactionAllowlist: z.ZodOptional>>; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; replyToModeByChatType: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; group: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; channel: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; }, z.core.$strict>>; thread: z.ZodOptional>; inheritParent: z.ZodOptional; initialHistoryLimit: z.ZodOptional; }, z.core.$strict>>; actions: z.ZodOptional; messages: z.ZodOptional; pins: z.ZodOptional; search: z.ZodOptional; permissions: z.ZodOptional; memberInfo: z.ZodOptional; channelInfo: z.ZodOptional; emojiList: z.ZodOptional; }, z.core.$strict>>; slashCommand: z.ZodOptional; name: z.ZodOptional; sessionPrefix: z.ZodOptional; ephemeral: z.ZodOptional; }, z.core.$strict>>; dmPolicy: z.ZodOptional>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional; dm: z.ZodOptional; policy: z.ZodOptional>; allowFrom: z.ZodOptional>>; groupEnabled: z.ZodOptional; groupChannels: z.ZodOptional>>; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; }, z.core.$strict>>; channels: z.ZodOptional; allow: z.ZodOptional; requireMention: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; allowBots: z.ZodOptional; users: z.ZodOptional>>; skills: z.ZodOptional>; systemPrompt: z.ZodOptional; }, z.core.$strict>>>>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; ackReaction: z.ZodOptional; typingReaction: z.ZodOptional; mode: z.ZodDefault>>; signingSecret: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; webhookPath: z.ZodDefault>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; accounts: z.ZodOptional; mode: z.ZodOptional>; signingSecret: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; webhookPath: z.ZodOptional; capabilities: z.ZodOptional, z.ZodObject<{ interactiveReplies: z.ZodOptional; }, z.core.$strict>]>>; execApprovals: z.ZodOptional; approvers: z.ZodOptional>>; agentFilter: z.ZodOptional>; sessionFilter: z.ZodOptional>; target: z.ZodOptional>; }, z.core.$strict>>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; commands: z.ZodOptional]>>; nativeSkills: z.ZodOptional]>>; }, z.core.$strict>>; configWrites: z.ZodOptional; botToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; appToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; userToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; userTokenReadOnly: z.ZodDefault>; allowBots: z.ZodOptional; dangerouslyAllowNameMatching: z.ZodOptional; requireMention: z.ZodOptional; groupPolicy: z.ZodOptional>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streaming: z.ZodOptional]>>; nativeStreaming: z.ZodOptional; streamMode: z.ZodOptional>; mediaMaxMb: z.ZodOptional; reactionNotifications: z.ZodOptional>; reactionAllowlist: z.ZodOptional>>; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; replyToModeByChatType: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; group: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; channel: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; }, z.core.$strict>>; thread: z.ZodOptional>; inheritParent: z.ZodOptional; initialHistoryLimit: z.ZodOptional; }, z.core.$strict>>; actions: z.ZodOptional; messages: z.ZodOptional; pins: z.ZodOptional; search: z.ZodOptional; permissions: z.ZodOptional; memberInfo: z.ZodOptional; channelInfo: z.ZodOptional; emojiList: z.ZodOptional; }, z.core.$strict>>; slashCommand: z.ZodOptional; name: z.ZodOptional; sessionPrefix: z.ZodOptional; ephemeral: z.ZodOptional; }, z.core.$strict>>; dmPolicy: z.ZodOptional>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional; dm: z.ZodOptional; policy: z.ZodOptional>; allowFrom: z.ZodOptional>>; groupEnabled: z.ZodOptional; groupChannels: z.ZodOptional>>; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; }, z.core.$strict>>; channels: z.ZodOptional; allow: z.ZodOptional; requireMention: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; allowBots: z.ZodOptional; users: z.ZodOptional>>; skills: z.ZodOptional>; systemPrompt: z.ZodOptional; }, z.core.$strict>>>>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; responsePrefix: z.ZodOptional; ackReaction: z.ZodOptional; typingReaction: z.ZodOptional; }, z.core.$strict>>>>; defaultAccount: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"SlackConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":984,"sourcePath":"src/config/zod-schema.providers-core.ts"} {"declaration":"export const TelegramConfigSchema: z.ZodObject<{ name: z.ZodOptional; capabilities: z.ZodOptional, z.ZodObject<{ inlineButtons: z.ZodOptional>; }, z.core.$strict>]>>; execApprovals: z.ZodOptional; approvers: z.ZodOptional>>; agentFilter: z.ZodOptional>; sessionFilter: z.ZodOptional>; target: z.ZodOptional>; }, z.core.$strict>>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; commands: z.ZodOptional]>>; nativeSkills: z.ZodOptional]>>; }, z.core.$strict>>; customCommands: z.ZodOptional>>; configWrites: z.ZodOptional; dmPolicy: z.ZodDefault>>; botToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; tokenFile: z.ZodOptional; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; groups: z.ZodOptional; ingest: z.ZodOptional; disableAudioPreflight: z.ZodOptional; groupPolicy: z.ZodOptional>; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; topics: z.ZodOptional; ingest: z.ZodOptional; disableAudioPreflight: z.ZodOptional; groupPolicy: z.ZodOptional>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; agentId: z.ZodOptional; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; }, z.core.$strict>>>>; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; }, z.core.$strict>>>>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional>; groupAllowFrom: z.ZodOptional>>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; direct: z.ZodOptional>; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; topics: z.ZodOptional; ingest: z.ZodOptional; disableAudioPreflight: z.ZodOptional; groupPolicy: z.ZodOptional>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; agentId: z.ZodOptional; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; }, z.core.$strict>>>>; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; requireTopic: z.ZodOptional; autoTopicLabel: z.ZodOptional; prompt: z.ZodOptional; }, z.core.$strict>]>>; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; streaming: z.ZodOptional]>>; blockStreaming: z.ZodOptional; draftChunk: z.ZodOptional; maxChars: z.ZodOptional; breakPreference: z.ZodOptional, z.ZodLiteral<\"newline\">, z.ZodLiteral<\"sentence\">]>>; }, z.core.$strict>>; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streamMode: z.ZodOptional>; mediaMaxMb: z.ZodOptional; timeoutSeconds: z.ZodOptional; retry: z.ZodOptional; minDelayMs: z.ZodOptional; maxDelayMs: z.ZodOptional; jitter: z.ZodOptional; }, z.core.$strict>>; network: z.ZodOptional; dnsResultOrder: z.ZodOptional>; dangerouslyAllowPrivateNetwork: z.ZodOptional; }, z.core.$strict>>; proxy: z.ZodOptional; webhookUrl: z.ZodOptional; webhookSecret: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; webhookPath: z.ZodOptional; webhookHost: z.ZodOptional; webhookPort: z.ZodOptional; webhookCertPath: z.ZodOptional; actions: z.ZodOptional; sendMessage: z.ZodOptional; poll: z.ZodOptional; deleteMessage: z.ZodOptional; editMessage: z.ZodOptional; sticker: z.ZodOptional; createForumTopic: z.ZodOptional; editForumTopic: z.ZodOptional; }, z.core.$strict>>; threadBindings: z.ZodOptional; idleHours: z.ZodOptional; maxAgeHours: z.ZodOptional; spawnSubagentSessions: z.ZodOptional; spawnAcpSessions: z.ZodOptional; }, z.core.$strict>>; reactionNotifications: z.ZodOptional>; reactionLevel: z.ZodOptional>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; linkPreview: z.ZodOptional; silentErrorReplies: z.ZodOptional; responsePrefix: z.ZodOptional; ackReaction: z.ZodOptional; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; apiRoot: z.ZodOptional; autoTopicLabel: z.ZodOptional; prompt: z.ZodOptional; }, z.core.$strict>]>>; accounts: z.ZodOptional; capabilities: z.ZodOptional, z.ZodObject<{ inlineButtons: z.ZodOptional>; }, z.core.$strict>]>>; execApprovals: z.ZodOptional; approvers: z.ZodOptional>>; agentFilter: z.ZodOptional>; sessionFilter: z.ZodOptional>; target: z.ZodOptional>; }, z.core.$strict>>; markdown: z.ZodOptional>; }, z.core.$strict>>; enabled: z.ZodOptional; commands: z.ZodOptional]>>; nativeSkills: z.ZodOptional]>>; }, z.core.$strict>>; customCommands: z.ZodOptional>>; configWrites: z.ZodOptional; dmPolicy: z.ZodDefault>>; botToken: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; tokenFile: z.ZodOptional; replyToMode: z.ZodOptional, z.ZodLiteral<\"first\">, z.ZodLiteral<\"all\">]>>; groups: z.ZodOptional; ingest: z.ZodOptional; disableAudioPreflight: z.ZodOptional; groupPolicy: z.ZodOptional>; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; topics: z.ZodOptional; ingest: z.ZodOptional; disableAudioPreflight: z.ZodOptional; groupPolicy: z.ZodOptional>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; agentId: z.ZodOptional; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; }, z.core.$strict>>>>; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; }, z.core.$strict>>>>; allowFrom: z.ZodOptional>>; defaultTo: z.ZodOptional>; groupAllowFrom: z.ZodOptional>>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; direct: z.ZodOptional>; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; topics: z.ZodOptional; ingest: z.ZodOptional; disableAudioPreflight: z.ZodOptional; groupPolicy: z.ZodOptional>; skills: z.ZodOptional>; enabled: z.ZodOptional; allowFrom: z.ZodOptional>>; systemPrompt: z.ZodOptional; agentId: z.ZodOptional; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; }, z.core.$strict>>>>; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; requireTopic: z.ZodOptional; autoTopicLabel: z.ZodOptional; prompt: z.ZodOptional; }, z.core.$strict>]>>; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; streaming: z.ZodOptional]>>; blockStreaming: z.ZodOptional; draftChunk: z.ZodOptional; maxChars: z.ZodOptional; breakPreference: z.ZodOptional, z.ZodLiteral<\"newline\">, z.ZodLiteral<\"sentence\">]>>; }, z.core.$strict>>; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; streamMode: z.ZodOptional>; mediaMaxMb: z.ZodOptional; timeoutSeconds: z.ZodOptional; retry: z.ZodOptional; minDelayMs: z.ZodOptional; maxDelayMs: z.ZodOptional; jitter: z.ZodOptional; }, z.core.$strict>>; network: z.ZodOptional; dnsResultOrder: z.ZodOptional>; dangerouslyAllowPrivateNetwork: z.ZodOptional; }, z.core.$strict>>; proxy: z.ZodOptional; webhookUrl: z.ZodOptional; webhookSecret: z.ZodOptional; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"file\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>, z.ZodObject<{ source: z.ZodLiteral<\"exec\">; provider: z.ZodString; id: z.ZodString; }, z.core.$strict>], \"source\">]>>; webhookPath: z.ZodOptional; webhookHost: z.ZodOptional; webhookPort: z.ZodOptional; webhookCertPath: z.ZodOptional; actions: z.ZodOptional; sendMessage: z.ZodOptional; poll: z.ZodOptional; deleteMessage: z.ZodOptional; editMessage: z.ZodOptional; sticker: z.ZodOptional; createForumTopic: z.ZodOptional; editForumTopic: z.ZodOptional; }, z.core.$strict>>; threadBindings: z.ZodOptional; idleHours: z.ZodOptional; maxAgeHours: z.ZodOptional; spawnSubagentSessions: z.ZodOptional; spawnAcpSessions: z.ZodOptional; }, z.core.$strict>>; reactionNotifications: z.ZodOptional>; reactionLevel: z.ZodOptional>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; linkPreview: z.ZodOptional; silentErrorReplies: z.ZodOptional; responsePrefix: z.ZodOptional; ackReaction: z.ZodOptional; errorPolicy: z.ZodOptional>; errorCooldownMs: z.ZodOptional; apiRoot: z.ZodOptional; autoTopicLabel: z.ZodOptional; prompt: z.ZodOptional; }, z.core.$strict>]>>; }, z.core.$strict>>>>; defaultAccount: z.ZodOptional; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"TelegramConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":342,"sourcePath":"src/config/zod-schema.providers-core.ts"} {"declaration":"export const ToolPolicySchema: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>;","entrypoint":"channel-config-schema","exportName":"ToolPolicySchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":253,"sourcePath":"src/config/zod-schema.agent-runtime.ts"} {"declaration":"export const WhatsAppConfigSchema: z.ZodObject<{ enabled: z.ZodOptional; capabilities: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; configWrites: z.ZodOptional; sendReadReceipts: z.ZodOptional; messagePrefix: z.ZodOptional; responsePrefix: z.ZodOptional; dmPolicy: z.ZodDefault>>; selfChatMode: z.ZodOptional; allowFrom: z.ZodOptional>; defaultTo: z.ZodOptional; groupAllowFrom: z.ZodOptional>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; groups: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; ackReaction: z.ZodOptional; direct: z.ZodDefault>; group: z.ZodDefault>>; }, z.core.$strict>>; reactionLevel: z.ZodOptional>; debounceMs: z.ZodDefault>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; accounts: z.ZodOptional>; markdown: z.ZodOptional>; }, z.core.$strict>>; configWrites: z.ZodOptional; sendReadReceipts: z.ZodOptional; messagePrefix: z.ZodOptional; responsePrefix: z.ZodOptional; dmPolicy: z.ZodDefault>>; selfChatMode: z.ZodOptional; allowFrom: z.ZodOptional>; defaultTo: z.ZodOptional; groupAllowFrom: z.ZodOptional>; groupPolicy: z.ZodDefault>>; contextVisibility: z.ZodOptional>; historyLimit: z.ZodOptional; dmHistoryLimit: z.ZodOptional; dms: z.ZodOptional; }, z.core.$strict>>>>; textChunkLimit: z.ZodOptional; chunkMode: z.ZodOptional>; blockStreaming: z.ZodOptional; blockStreamingCoalesce: z.ZodOptional; maxChars: z.ZodOptional; idleMs: z.ZodOptional; }, z.core.$strict>>; groups: z.ZodOptional; tools: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>; toolsBySender: z.ZodOptional>; alsoAllow: z.ZodOptional>; deny: z.ZodOptional>; }, z.core.$strict>>>>; }, z.core.$strict>>>>; ackReaction: z.ZodOptional; direct: z.ZodDefault>; group: z.ZodDefault>>; }, z.core.$strict>>; reactionLevel: z.ZodOptional>; debounceMs: z.ZodDefault>; heartbeat: z.ZodOptional; showAlerts: z.ZodOptional; useIndicator: z.ZodOptional; }, z.core.$strict>>; healthMonitor: z.ZodOptional; }, z.core.$strict>>; name: z.ZodOptional; enabled: z.ZodOptional; authDir: z.ZodOptional; mediaMaxMb: z.ZodOptional; }, z.core.$strict>>>>; defaultAccount: z.ZodOptional; mediaMaxMb: z.ZodDefault>; actions: z.ZodOptional; sendMessage: z.ZodOptional; polls: z.ZodOptional; }, z.core.$strict>>; }, z.core.$strict>;","entrypoint":"channel-config-schema","exportName":"WhatsAppConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":122,"sourcePath":"src/config/zod-schema.providers-whatsapp.ts"} {"category":"channel","entrypoint":"channel-contract","importSpecifier":"openclaw/plugin-sdk/channel-contract","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-contract.ts"} -{"declaration":"export type BaseProbeResult = BaseProbeResult;","entrypoint":"channel-contract","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":599,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-contract","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":605,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type BaseProbeResult = BaseProbeResult;","entrypoint":"channel-contract","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":603,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-contract","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":609,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-contract","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":147,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-contract","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelApprovalAdapter = ChannelApprovalAdapter;","entrypoint":"channel-contract","exportName":"ChannelApprovalAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":597,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelApprovalCapability = ChannelApprovalCapability;","entrypoint":"channel-contract","exportName":"ChannelApprovalCapability","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":592,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelCommandConversationContext = ChannelCommandConversationContext;","entrypoint":"channel-contract","exportName":"ChannelCommandConversationContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":668,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelDirectoryAdapter = ChannelDirectoryAdapter;","entrypoint":"channel-contract","exportName":"ChannelDirectoryAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":454,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelApprovalAdapter = ChannelApprovalAdapter;","entrypoint":"channel-contract","exportName":"ChannelApprovalAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":613,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelApprovalCapability = ChannelApprovalCapability;","entrypoint":"channel-contract","exportName":"ChannelApprovalCapability","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":602,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelCommandConversationContext = ChannelCommandConversationContext;","entrypoint":"channel-contract","exportName":"ChannelCommandConversationContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":684,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelDirectoryAdapter = ChannelDirectoryAdapter;","entrypoint":"channel-contract","exportName":"ChannelDirectoryAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":459,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-contract","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":219,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-contract","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":556,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":520,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-contract","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":560,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"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\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\" | \"upload-file\";","entrypoint":"channel-contract","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"} {"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-contract","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":57,"sourcePath":"src/channels/plugins/types.core.ts"} @@ -212,51 +212,51 @@ {"declaration":"export function waitUntilAbort(signal?: AbortSignal | undefined, onAbort?: (() => void | Promise) | undefined): Promise;","entrypoint":"channel-runtime","exportName":"waitUntilAbort","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":30,"sourcePath":"src/plugin-sdk/channel-lifecycle.core.ts"} {"declaration":"export const CHANNEL_MESSAGE_ACTION_NAMES: readonly [\"send\", \"broadcast\", \"poll\", \"poll-vote\", \"react\", \"reactions\", \"read\", \"edit\", \"unsend\", \"reply\", \"sendWithEffect\", \"renameGroup\", \"setGroupIcon\", \"addParticipant\", \"removeParticipant\", \"leaveGroup\", \"sendAttachment\", \"delete\", \"pin\", \"unpin\", \"list-pins\", \"permissions\", \"thread-create\", \"thread-list\", \"thread-reply\", \"search\", \"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\", \"timeout\", \"kick\", \"ban\", \"set-profile\", \"set-presence\", \"set-profile\", \"download-file\", \"upload-file\"];","entrypoint":"channel-runtime","exportName":"CHANNEL_MESSAGE_ACTION_NAMES","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"const","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/message-action-names.ts"} {"declaration":"export const CHANNEL_MESSAGE_CAPABILITIES: readonly [\"interactive\", \"buttons\", \"cards\", \"components\", \"blocks\"];","entrypoint":"channel-runtime","exportName":"CHANNEL_MESSAGE_CAPABILITIES","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"const","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/message-capabilities.ts"} -{"declaration":"export type BaseProbeResult = BaseProbeResult;","entrypoint":"channel-runtime","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":599,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-runtime","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":605,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type BaseProbeResult = BaseProbeResult;","entrypoint":"channel-runtime","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":603,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-runtime","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":609,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-runtime","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":147,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelAccountState = ChannelAccountState;","entrypoint":"channel-runtime","exportName":"ChannelAccountState","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":110,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelActionAvailabilityState = ChannelActionAvailabilityState;","entrypoint":"channel-runtime","exportName":"ChannelActionAvailabilityState","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelAgentPromptAdapter = ChannelAgentPromptAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAgentPromptAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":493,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelAgentPromptAdapter = ChannelAgentPromptAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAgentPromptAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":497,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-runtime","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"channel-runtime","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":24,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelAllowlistAdapter = ChannelAllowlistAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAllowlistAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":603,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelApprovalAdapter = ChannelApprovalAdapter;","entrypoint":"channel-runtime","exportName":"ChannelApprovalAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":597,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelApprovalCapability = ChannelApprovalCapability;","entrypoint":"channel-runtime","exportName":"ChannelApprovalCapability","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":592,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelAllowlistAdapter = ChannelAllowlistAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAllowlistAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":619,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelApprovalAdapter = ChannelApprovalAdapter;","entrypoint":"channel-runtime","exportName":"ChannelApprovalAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":613,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelApprovalCapability = ChannelApprovalCapability;","entrypoint":"channel-runtime","exportName":"ChannelApprovalCapability","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":602,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelApprovalForwardTarget = ChannelApprovalForwardTarget;","entrypoint":"channel-runtime","exportName":"ChannelApprovalForwardTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":39,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelApprovalInitiatingSurfaceState = ChannelActionAvailabilityState;","entrypoint":"channel-runtime","exportName":"ChannelApprovalInitiatingSurfaceState","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":37,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelAuthAdapter = ChannelAuthAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAuthAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelAuthAdapter = ChannelAuthAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAuthAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":399,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"channel-runtime","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelCapabilitiesDiagnostics = ChannelCapabilitiesDiagnostics;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDiagnostics","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelCapabilitiesDisplayLine = ChannelCapabilitiesDisplayLine;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDisplayLine","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelCapabilitiesDisplayTone = ChannelCapabilitiesDisplayTone;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDisplayTone","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelCommandAdapter = ChannelCommandAdapter;","entrypoint":"channel-runtime","exportName":"ChannelCommandAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":492,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelCommandConversationContext = ChannelCommandConversationContext;","entrypoint":"channel-runtime","exportName":"ChannelCommandConversationContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":668,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelCommandAdapter = ChannelCommandAdapter;","entrypoint":"channel-runtime","exportName":"ChannelCommandAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":497,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelCommandConversationContext = ChannelCommandConversationContext;","entrypoint":"channel-runtime","exportName":"ChannelCommandConversationContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":684,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelConfigAdapter = ChannelConfigAdapter;","entrypoint":"channel-runtime","exportName":"ChannelConfigAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":98,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelConfiguredBindingConversationRef = ChannelConfiguredBindingConversationRef;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingConversationRef","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":659,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":664,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":680,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelConversationBindingSupport = ChannelConversationBindingSupport;","entrypoint":"channel-runtime","exportName":"ChannelConversationBindingSupport","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":696,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelDirectoryAdapter = ChannelDirectoryAdapter;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":454,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelDirectoryEntry = ChannelDirectoryEntry;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntry","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":507,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelDirectoryEntryKind = ChannelDirectoryEntryKind;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntryKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":505,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelElevatedAdapter = ChannelElevatedAdapter;","entrypoint":"channel-runtime","exportName":"ChannelElevatedAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":485,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelGatewayAdapter = ChannelGatewayAdapter;","entrypoint":"channel-runtime","exportName":"ChannelGatewayAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":379,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext;","entrypoint":"channel-runtime","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":271,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelGroupAdapter = ChannelGroupAdapter;","entrypoint":"channel-runtime","exportName":"ChannelGroupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":129,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelConfiguredBindingConversationRef = ChannelConfiguredBindingConversationRef;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingConversationRef","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":675,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":680,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":696,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelConversationBindingSupport = ChannelConversationBindingSupport;","entrypoint":"channel-runtime","exportName":"ChannelConversationBindingSupport","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":712,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelDirectoryAdapter = ChannelDirectoryAdapter;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":459,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelDirectoryEntry = ChannelDirectoryEntry;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntry","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":511,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelDirectoryEntryKind = ChannelDirectoryEntryKind;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntryKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":509,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelElevatedAdapter = ChannelElevatedAdapter;","entrypoint":"channel-runtime","exportName":"ChannelElevatedAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":490,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelGatewayAdapter = ChannelGatewayAdapter;","entrypoint":"channel-runtime","exportName":"ChannelGatewayAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":383,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext;","entrypoint":"channel-runtime","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":275,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelGroupAdapter = ChannelGroupAdapter;","entrypoint":"channel-runtime","exportName":"ChannelGroupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":133,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-runtime","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":219,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelHeartbeatAdapter = ChannelHeartbeatAdapter;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":420,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelHeartbeatAdapter = ChannelHeartbeatAdapter;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":425,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelHeartbeatDeps = ChannelHeartbeatDeps;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatDeps","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":118,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelId = ChannelId;","entrypoint":"channel-runtime","exportName":"ChannelId","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelLifecycleAdapter = ChannelLifecycleAdapter;","entrypoint":"channel-runtime","exportName":"ChannelLifecycleAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":497,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelLoginWithQrStartResult = ChannelLoginWithQrStartResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrStartResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":350,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelLoginWithQrWaitResult = ChannelLoginWithQrWaitResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrWaitResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":355,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelLogoutContext = ChannelLogoutContext;","entrypoint":"channel-runtime","exportName":"ChannelLogoutContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":360,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelLogoutResult = ChannelLogoutResult;","entrypoint":"channel-runtime","exportName":"ChannelLogoutResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":344,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelLifecycleAdapter = ChannelLifecycleAdapter;","entrypoint":"channel-runtime","exportName":"ChannelLifecycleAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":502,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelLoginWithQrStartResult = ChannelLoginWithQrStartResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrStartResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":354,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelLoginWithQrWaitResult = ChannelLoginWithQrWaitResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrWaitResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":359,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelLogoutContext = ChannelLogoutContext;","entrypoint":"channel-runtime","exportName":"ChannelLogoutContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":364,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelLogoutResult = ChannelLogoutResult;","entrypoint":"channel-runtime","exportName":"ChannelLogoutResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":348,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelLogSink = ChannelLogSink;","entrypoint":"channel-runtime","exportName":"ChannelLogSink","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":212,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMentionAdapter = ChannelMentionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMentionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":263,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":556,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":520,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":560,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"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\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\" | \"upload-file\";","entrypoint":"channel-runtime","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"} {"declaration":"export type ChannelMessageCapability = \"interactive\" | \"buttons\" | \"cards\" | \"components\" | \"blocks\";","entrypoint":"channel-runtime","exportName":"ChannelMessageCapability","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/channels/plugins/message-capabilities.ts"} @@ -264,31 +264,31 @@ {"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":52,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":398,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMeta = ChannelMeta;","entrypoint":"channel-runtime","exportName":"ChannelMeta","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":124,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelOutboundAdapter = ChannelOutboundAdapter;","entrypoint":"channel-runtime","exportName":"ChannelOutboundAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":175,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelOutboundContext = ChannelOutboundContext;","entrypoint":"channel-runtime","exportName":"ChannelOutboundContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":135,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelOutboundPayloadHint = ChannelOutboundPayloadHint;","entrypoint":"channel-runtime","exportName":"ChannelOutboundPayloadHint","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":160,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelOutboundAdapter = ChannelOutboundAdapter;","entrypoint":"channel-runtime","exportName":"ChannelOutboundAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":179,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelOutboundContext = ChannelOutboundContext;","entrypoint":"channel-runtime","exportName":"ChannelOutboundContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelOutboundPayloadHint = ChannelOutboundPayloadHint;","entrypoint":"channel-runtime","exportName":"ChannelOutboundPayloadHint","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":164,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelOutboundTargetMode = ChannelOutboundTargetMode;","entrypoint":"channel-runtime","exportName":"ChannelOutboundTargetMode","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelOutboundTargetRef = ChannelOutboundTargetRef;","entrypoint":"channel-runtime","exportName":"ChannelOutboundTargetRef","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":164,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelPairingAdapter = ChannelPairingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelPairingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":368,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelOutboundTargetRef = ChannelOutboundTargetRef;","entrypoint":"channel-runtime","exportName":"ChannelOutboundTargetRef","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":168,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelPairingAdapter = ChannelPairingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelPairingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":372,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"channel-runtime","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":81,"sourcePath":"src/channels/plugins/types.plugin.ts"} -{"declaration":"export type ChannelPollContext = ChannelPollContext;","entrypoint":"channel-runtime","exportName":"ChannelPollContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":587,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelPollResult = ChannelPollResult;","entrypoint":"channel-runtime","exportName":"ChannelPollResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":578,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelResolveKind = ChannelResolveKind;","entrypoint":"channel-runtime","exportName":"ChannelResolveKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":465,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelResolverAdapter = ChannelResolverAdapter;","entrypoint":"channel-runtime","exportName":"ChannelResolverAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":475,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelResolveResult = ChannelResolveResult;","entrypoint":"channel-runtime","exportName":"ChannelResolveResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":467,"sourcePath":"src/channels/plugins/types.adapters.ts"} -{"declaration":"export type ChannelSecurityAdapter = ChannelSecurityAdapter;","entrypoint":"channel-runtime","exportName":"ChannelSecurityAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":727,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelPollContext = ChannelPollContext;","entrypoint":"channel-runtime","exportName":"ChannelPollContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":591,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelPollResult = ChannelPollResult;","entrypoint":"channel-runtime","exportName":"ChannelPollResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":582,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelResolveKind = ChannelResolveKind;","entrypoint":"channel-runtime","exportName":"ChannelResolveKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":470,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelResolverAdapter = ChannelResolverAdapter;","entrypoint":"channel-runtime","exportName":"ChannelResolverAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":480,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelResolveResult = ChannelResolveResult;","entrypoint":"channel-runtime","exportName":"ChannelResolveResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":472,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelSecurityAdapter = ChannelSecurityAdapter;","entrypoint":"channel-runtime","exportName":"ChannelSecurityAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":743,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelSecurityContext = ChannelSecurityContext;","entrypoint":"channel-runtime","exportName":"ChannelSecurityContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":257,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelSecurityDmPolicy = ChannelSecurityDmPolicy;","entrypoint":"channel-runtime","exportName":"ChannelSecurityDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":248,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"channel-runtime","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-runtime","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":64,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelStatusAdapter = ChannelStatusAdapter;","entrypoint":"channel-runtime","exportName":"ChannelStatusAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":217,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelStatusAdapter = ChannelStatusAdapter;","entrypoint":"channel-runtime","exportName":"ChannelStatusAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":221,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-runtime","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":102,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelStreamingAdapter = ChannelStreamingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelStreamingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":282,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelStructuredComponents = ChannelStructuredComponents;","entrypoint":"channel-runtime","exportName":"ChannelStructuredComponents","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":291,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelThreadingAdapter = ChannelThreadingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelThreadingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":325,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":368,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":382,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelToolSend = ChannelToolSend;","entrypoint":"channel-runtime","exportName":"ChannelToolSend","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":549,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelToolSend = ChannelToolSend;","entrypoint":"channel-runtime","exportName":"ChannelToolSend","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":553,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChatType = ChatType;","entrypoint":"channel-runtime","exportName":"ChatType","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/channels/chat-type.ts"} {"declaration":"export type CreateTypingCallbacksParams = CreateTypingCallbacksParams;","entrypoint":"channel-runtime","exportName":"CreateTypingCallbacksParams","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":11,"sourcePath":"src/channels/typing.ts"} {"declaration":"export type HeartbeatEventPayload = HeartbeatEventPayload;","entrypoint":"channel-runtime","exportName":"HeartbeatEventPayload","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/infra/heartbeat-events.ts"} @@ -356,7 +356,7 @@ {"declaration":"export function resolveSenderCommandAuthorization(params: ResolveSenderCommandAuthorizationParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":151,"sourcePath":"src/plugin-sdk/command-auth.ts"} {"declaration":"export function resolveSenderCommandAuthorizationWithRuntime(params: ResolveSenderCommandAuthorizationWithRuntimeParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorizationWithRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":140,"sourcePath":"src/plugin-sdk/command-auth.ts"} {"declaration":"export function resolveSkillCommandInvocation(params: { commandBodyNormalized: string; skillCommands: SkillCommandSpec[]; }): { command: SkillCommandSpec; args?: string | undefined; } | null;","entrypoint":"command-auth","exportName":"resolveSkillCommandInvocation","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":58,"sourcePath":"src/auto-reply/skill-commands-base.ts"} -{"declaration":"export function resolveStoredModelOverride(params: { sessionEntry?: SessionEntry | undefined; sessionStore?: Record | undefined; sessionKey?: string | undefined; parentSessionKey?: string | undefined; }): StoredModelOverride | null;","entrypoint":"command-auth","exportName":"resolveStoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":156,"sourcePath":"src/auto-reply/reply/model-selection.ts"} +{"declaration":"export function resolveStoredModelOverride(params: { sessionEntry?: SessionEntry | undefined; sessionStore?: Record | undefined; sessionKey?: string | undefined; parentSessionKey?: string | undefined; defaultProvider: string; }): StoredModelOverride | null;","entrypoint":"command-auth","exportName":"resolveStoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":145,"sourcePath":"src/auto-reply/reply/model-selection.ts"} {"declaration":"export function resolveTextCommand(raw: string, cfg?: OpenClawConfig | undefined): { command: ChatCommandDefinition; args?: string | undefined; } | null;","entrypoint":"command-auth","exportName":"resolveTextCommand","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":494,"sourcePath":"src/auto-reply/commands-registry.ts"} {"declaration":"export function serializeCommandArgs(command: ChatCommandDefinition, args?: CommandArgs | undefined): string | undefined;","entrypoint":"command-auth","exportName":"serializeCommandArgs","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":271,"sourcePath":"src/auto-reply/commands-registry.ts"} {"declaration":"export function shouldComputeCommandAuthorized(text?: string | undefined, cfg?: OpenClawConfig | undefined, options?: CommandNormalizeOptions | undefined): boolean;","entrypoint":"command-auth","exportName":"shouldComputeCommandAuthorized","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":88,"sourcePath":"src/auto-reply/command-detection.ts"} @@ -385,7 +385,7 @@ {"declaration":"export type ResolveSenderCommandAuthorizationWithRuntimeParams = ResolveSenderCommandAuthorizationWithRuntimeParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationWithRuntimeParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":114,"sourcePath":"src/plugin-sdk/command-auth.ts"} {"declaration":"export type ShouldHandleTextCommandsParams = ShouldHandleTextCommandsParams;","entrypoint":"command-auth","exportName":"ShouldHandleTextCommandsParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":83,"sourcePath":"src/auto-reply/commands-registry.types.ts"} {"declaration":"export type SkillCommandSpec = SkillCommandSpec;","entrypoint":"command-auth","exportName":"SkillCommandSpec","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":51,"sourcePath":"src/agents/skills/types.ts"} -{"declaration":"export type StoredModelOverride = StoredModelOverride;","entrypoint":"command-auth","exportName":"StoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":123,"sourcePath":"src/auto-reply/reply/model-selection.ts"} +{"declaration":"export type StoredModelOverride = StoredModelOverride;","entrypoint":"command-auth","exportName":"StoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":124,"sourcePath":"src/auto-reply/reply/model-selection.ts"} {"category":"core","entrypoint":"core","importSpecifier":"openclaw/plugin-sdk/core","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/core.ts"} {"declaration":"export function applyAccountNameToChannelSection(params: { cfg: OpenClawConfig; channelKey: string; accountId: string; name?: string | undefined; alwaysUseAccounts?: boolean | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"applyAccountNameToChannelSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":34,"sourcePath":"src/channels/plugins/setup-helpers.ts"} {"declaration":"export function buildAgentSessionKey(params: { agentId: string; channel: string; accountId?: string | null | undefined; peer?: RoutePeer | null | undefined; dmScope?: \"main\" | \"per-peer\" | \"per-channel-peer\" | \"per-account-channel-peer\" | undefined; identityLinks?: Record<...> | undefined; }): string;","entrypoint":"core","exportName":"buildAgentSessionKey","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":92,"sourcePath":"src/routing/resolve-route.ts"} @@ -435,7 +435,7 @@ {"declaration":"export type BoundTaskFlowsRuntime = BoundTaskFlowsRuntime;","entrypoint":"core","exportName":"BoundTaskFlowsRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":74,"sourcePath":"src/plugins/runtime/runtime-tasks.ts"} {"declaration":"export type BoundTaskRunsRuntime = BoundTaskRunsRuntime;","entrypoint":"core","exportName":"BoundTaskRunsRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/runtime-tasks.ts"} {"declaration":"export type ChannelConfigUiHint = ChannelConfigUiHint;","entrypoint":"core","exportName":"ChannelConfigUiHint","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":40,"sourcePath":"src/channels/plugins/types.plugin.ts"} -{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"core","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":520,"sourcePath":"src/channels/plugins/types.core.ts"} +{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"core","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"core","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":398,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelOutboundSessionRoute = ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"ChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":312,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; resolvedTarget?: { to: string; kind: import(\"../channels/plugins/types.core.js\").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","sourceLine":181,"sourcePath":"src/plugin-sdk/core.ts"} @@ -585,9 +585,9 @@ {"declaration":"export function resolveAgentModelPrimaryValue(model?: AgentModelConfig | undefined): string | undefined;","entrypoint":"provider-onboard","exportName":"resolveAgentModelPrimaryValue","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":8,"sourcePath":"src/config/model-input.ts"} {"declaration":"export function withAgentModelAliases(existing: Record | undefined, aliases: readonly AgentModelAliasEntry[]): Record;","entrypoint":"provider-onboard","exportName":"withAgentModelAliases","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":233,"sourcePath":"src/plugin-sdk/provider-onboard.ts"} {"declaration":"export type AgentModelAliasEntry = AgentModelAliasEntry;","entrypoint":"provider-onboard","exportName":"AgentModelAliasEntry","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":25,"sourcePath":"src/plugin-sdk/provider-onboard.ts"} -{"declaration":"export type ModelApi = \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\" | \"azure-openai-responses\";","entrypoint":"provider-onboard","exportName":"ModelApi","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/config/types.models.ts"} -{"declaration":"export type ModelDefinitionConfig = ModelDefinitionConfig;","entrypoint":"provider-onboard","exportName":"ModelDefinitionConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/config/types.models.ts"} -{"declaration":"export type ModelProviderConfig = ModelProviderConfig;","entrypoint":"provider-onboard","exportName":"ModelProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":67,"sourcePath":"src/config/types.models.ts"} +{"declaration":"export type ModelApi = \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\" | \"azure-openai-responses\";","entrypoint":"provider-onboard","exportName":"ModelApi","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/config/types.models.ts"} +{"declaration":"export type ModelDefinitionConfig = ModelDefinitionConfig;","entrypoint":"provider-onboard","exportName":"ModelDefinitionConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":50,"sourcePath":"src/config/types.models.ts"} +{"declaration":"export type ModelProviderConfig = ModelProviderConfig;","entrypoint":"provider-onboard","exportName":"ModelProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":68,"sourcePath":"src/config/types.models.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"provider-onboard","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} {"declaration":"export type ProviderOnboardPresetAppliers = ProviderOnboardPresetAppliers;","entrypoint":"provider-onboard","exportName":"ProviderOnboardPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/plugin-sdk/provider-onboard.ts"} {"category":"utilities","entrypoint":"reply-payload","importSpecifier":"openclaw/plugin-sdk/reply-payload","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/reply-payload.ts"} @@ -672,7 +672,7 @@ {"declaration":"export const __testing: { resetAcpSessionManagerForTests(): void; setAcpSessionManagerForTests(manager: unknown): void; };","entrypoint":"testing","exportName":"acpManagerTesting","importSpecifier":"openclaw/plugin-sdk/testing","kind":"const","recordType":"export","sourceLine":25,"sourcePath":"src/acp/control-plane/manager.ts"} {"declaration":"export const handleAcpCommand: CommandHandler;","entrypoint":"testing","exportName":"handleAcpCommand","importSpecifier":"openclaw/plugin-sdk/testing","kind":"const","recordType":"export","sourceLine":75,"sourcePath":"src/auto-reply/reply/commands-acp.ts"} {"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"testing","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":147,"sourcePath":"src/channels/plugins/types.core.ts"} -{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext;","entrypoint":"testing","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":271,"sourcePath":"src/channels/plugins/types.adapters.ts"} +{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext;","entrypoint":"testing","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":275,"sourcePath":"src/channels/plugins/types.adapters.ts"} {"declaration":"export type CliMockOutputRuntime = CliMockOutputRuntime;","entrypoint":"testing","exportName":"CliMockOutputRuntime","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":5,"sourcePath":"src/cli/test-runtime-capture.ts"} {"declaration":"export type CliRuntimeCapture = CliRuntimeCapture;","entrypoint":"testing","exportName":"CliRuntimeCapture","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/cli/test-runtime-capture.ts"} {"declaration":"export type MockFn = MockFn;","entrypoint":"testing","exportName":"MockFn","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":5,"sourcePath":"src/test-utils/vitest-mock-fn.ts"} diff --git a/extensions/discord/src/channel.ts b/extensions/discord/src/channel.ts index 294bebc7ee0..3e36db68a6d 100644 --- a/extensions/discord/src/channel.ts +++ b/extensions/discord/src/channel.ts @@ -30,10 +30,12 @@ import { } from "./accounts.js"; import { getDiscordApprovalCapability } from "./approval-native.js"; import { auditDiscordChannelPermissions, collectDiscordAuditChannelIds } from "./audit.js"; +import { discordMessageActions } from "./channel-actions.js"; import { listDiscordDirectoryGroupsFromConfig, listDiscordDirectoryPeersFromConfig, } from "./directory-config.js"; +import { listDiscordDirectoryGroupsLive, listDiscordDirectoryPeersLive } from "./directory-live.js"; import { shouldSuppressLocalDiscordExecApprovalPrompt } from "./exec-approvals.js"; import { resolveDiscordGroupRequireMention, @@ -46,10 +48,10 @@ import { } from "./normalize.js"; import { resolveDiscordOutboundSessionRoute } from "./outbound-session-route.js"; import type { DiscordProbe } from "./probe.js"; +import { resolveDiscordChannelAllowlist } from "./resolve-channels.js"; import { resolveDiscordUserAllowlist } from "./resolve-users.js"; import { buildTokenChannelStatusSummary, - type ChannelMessageActionAdapter, type ChannelPlugin, DEFAULT_ACCOUNT_ID, getChatChannelMeta, @@ -59,16 +61,15 @@ import { type OpenClawConfig, } from "./runtime-api.js"; import { getDiscordRuntime } from "./runtime.js"; -import { fetchChannelPermissionsDiscord } from "./send.js"; +import { fetchChannelPermissionsDiscord, sendMessageDiscord, sendPollDiscord } from "./send.js"; +import { normalizeExplicitDiscordSessionKey } from "./session-key-normalization.js"; import { discordSetupAdapter } from "./setup-core.js"; import { createDiscordPluginBase, discordConfigAdapter } from "./shared.js"; import { collectDiscordStatusIssues } from "./status-issues.js"; import { parseDiscordTarget } from "./targets.js"; import { DiscordUiContainer } from "./ui.js"; -type DiscordSendFn = ReturnType< - typeof getDiscordRuntime ->["channel"]["discord"]["sendMessageDiscord"]; +type DiscordSendFn = typeof sendMessageDiscord; let discordProviderRuntimePromise: | Promise @@ -128,22 +129,6 @@ function formatDiscordIntents(intents?: { ].join(" "); } -const discordMessageActions: ChannelMessageActionAdapter = { - describeMessageTool: (ctx) => - getDiscordRuntime().channel.discord.messageActions?.describeMessageTool?.(ctx) ?? null, - extractToolSend: (ctx) => - getDiscordRuntime().channel.discord.messageActions?.extractToolSend?.(ctx) ?? null, - handleAction: async (ctx) => { - const ma = getDiscordRuntime().channel.discord.messageActions; - if (!ma?.handleAction) { - throw new Error("Discord message actions not available"); - } - return ma.handleAction(ctx); - }, - requiresTrustedRequesterSender: ({ action, toolContext }) => - Boolean(toolContext && (action === "timeout" || action === "kick" || action === "ban")), -}; - function buildDiscordCrossContextComponents(params: { originLabel: string; message: string; @@ -329,6 +314,8 @@ export const discordPlugin: ChannelPlugin }, messaging: { normalizeTarget: normalizeDiscordMessagingTarget, + normalizeExplicitSessionKey: ({ sessionKey, ctx }) => + normalizeExplicitDiscordSessionKey(sessionKey, ctx), resolveSessionTarget: ({ id }) => normalizeDiscordMessagingTarget(`channel:${id}`), parseExplicitTarget: ({ raw }) => parseDiscordExplicitTarget(raw), inferTargetChatType: ({ to }) => parseDiscordExplicitTarget(to)?.chatType, @@ -344,7 +331,10 @@ export const discordPlugin: ChannelPlugin listPeers: async (params) => listDiscordDirectoryPeersFromConfig(params), listGroups: async (params) => listDiscordDirectoryGroupsFromConfig(params), ...createRuntimeDirectoryLiveAdapter({ - getRuntime: () => getDiscordRuntime().channel.discord, + getRuntime: () => ({ + listDirectoryGroupsLive: listDiscordDirectoryGroupsLive, + listDirectoryPeersLive: listDiscordDirectoryPeersLive, + }), listPeersLive: (runtime) => runtime.listDirectoryPeersLive, listGroupsLive: (runtime) => runtime.listDirectoryGroupsLive, }), @@ -358,10 +348,7 @@ export const discordPlugin: ChannelPlugin inputs, missingTokenNote: "missing Discord token", resolveWithToken: ({ token, inputs }) => - getDiscordRuntime().channel.discord.resolveChannelAllowlist({ - token, - entries: inputs, - }), + resolveDiscordChannelAllowlist({ token, entries: inputs }), mapResolved: (entry) => ({ input: entry.input, resolved: entry.resolved, @@ -379,10 +366,7 @@ export const discordPlugin: ChannelPlugin inputs, missingTokenNote: "missing Discord token", resolveWithToken: ({ token, inputs }) => - getDiscordRuntime().channel.discord.resolveUserAllowlist({ - token, - entries: inputs, - }), + resolveDiscordUserAllowlist({ token, entries: inputs }), mapResolved: (entry) => ({ input: entry.input, resolved: entry.resolved, @@ -638,7 +622,7 @@ export const discordPlugin: ChannelPlugin message: PAIRING_APPROVED_MESSAGE, normalizeAllowEntry: createPairingPrefixStripper(/^(discord|user):/i), notify: async ({ id, message }) => { - await getDiscordRuntime().channel.discord.sendMessageDiscord(`user:${id}`, message); + await sendMessageDiscord(`user:${id}`, message); }, }, }, @@ -666,9 +650,7 @@ export const discordPlugin: ChannelPlugin attachedResults: { channel: "discord", sendText: async ({ cfg, to, text, accountId, deps, replyToId, silent }) => { - const send = - resolveOutboundSendDep(deps, "discord") ?? - getDiscordRuntime().channel.discord.sendMessageDiscord; + const send = resolveOutboundSendDep(deps, "discord") ?? sendMessageDiscord; return await send(to, text, { verbose: false, cfg, @@ -688,9 +670,7 @@ export const discordPlugin: ChannelPlugin replyToId, silent, }) => { - const send = - resolveOutboundSendDep(deps, "discord") ?? - getDiscordRuntime().channel.discord.sendMessageDiscord; + const send = resolveOutboundSendDep(deps, "discord") ?? sendMessageDiscord; return await send(to, text, { verbose: false, cfg, @@ -702,7 +682,7 @@ export const discordPlugin: ChannelPlugin }); }, sendPoll: async ({ cfg, to, poll, accountId, silent }) => - await getDiscordRuntime().channel.discord.sendPollDiscord(to, poll, { + await sendPollDiscord(to, poll, { cfg, accountId: accountId ?? undefined, silent: silent ?? undefined, diff --git a/extensions/line/src/channel.logout.test.ts b/extensions/line/src/channel.logout.test.ts index ea739819651..94952624d7f 100644 --- a/extensions/line/src/channel.logout.test.ts +++ b/extensions/line/src/channel.logout.test.ts @@ -37,7 +37,6 @@ function createRuntime(): { runtime: PluginRuntime; mocks: LineRuntimeMocks } { const runtime = { config: { writeConfigFile }, - channel: { line: { resolveLineAccount } }, } as unknown as PluginRuntime; return { runtime, mocks: { writeConfigFile, resolveLineAccount } }; diff --git a/extensions/line/src/channel.ts b/extensions/line/src/channel.ts index 713c86d741d..27a5b65354c 100644 --- a/extensions/line/src/channel.ts +++ b/extensions/line/src/channel.ts @@ -3,11 +3,12 @@ import { createRestrictSendersChannelSecurity } from "openclaw/plugin-sdk/channe import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { createEmptyChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime"; import { type ChannelPlugin, type ResolvedLineAccount } from "../api.js"; +import { resolveLineAccount } from "./accounts.js"; import { lineChannelPluginCommon } from "./channel-shared.js"; import { lineGatewayAdapter } from "./gateway.js"; import { resolveLineGroupRequireMention } from "./group-policy.js"; import { lineOutboundAdapter } from "./outbound.js"; -import { getLineRuntime } from "./runtime.js"; +import { pushMessageLine } from "./send.js"; import { lineSetupAdapter } from "./setup-core.js"; import { lineSetupWizard } from "./setup-surface.js"; import { lineStatusAdapter } from "./status.js"; @@ -157,12 +158,11 @@ export const linePlugin: ChannelPlugin = createChatChannelP message: "OpenClaw: your access has been approved.", normalizeAllowEntry: createPairingPrefixStripper(/^line:(?:user:)?/i), notify: async ({ cfg, id, message }) => { - const line = getLineRuntime().channel.line; - const account = line.resolveLineAccount({ cfg }); + const account = resolveLineAccount({ cfg }); if (!account.channelAccessToken) { throw new Error("LINE channel access token not configured"); } - await line.pushMessageLine(id, message, { + await pushMessageLine(id, message, { accountId: account.accountId, channelAccessToken: account.channelAccessToken, }); diff --git a/extensions/line/src/gateway.ts b/extensions/line/src/gateway.ts index fe0083657a7..43037f225fb 100644 --- a/extensions/line/src/gateway.ts +++ b/extensions/line/src/gateway.ts @@ -6,6 +6,9 @@ import { type OpenClawConfig, type ResolvedLineAccount, } from "../api.js"; +import { resolveLineAccount } from "./accounts.js"; +import { monitorLineProvider } from "./monitor.js"; +import { probeLineBot } from "./probe.js"; import { getLineRuntime } from "./runtime.js"; export const lineGatewayAdapter: NonNullable["gateway"]> = { @@ -26,7 +29,7 @@ export const lineGatewayAdapter: NonNullable[ let lineBotLabel = ""; try { - const probe = await getLineRuntime().channel.line.probeLineBot(token, 2500); + const probe = await probeLineBot(token, 2500); const displayName = probe.ok ? probe.bot?.displayName?.trim() : null; if (displayName) { lineBotLabel = ` (${displayName})`; @@ -39,7 +42,7 @@ export const lineGatewayAdapter: NonNullable[ ctx.log?.info(`[${account.accountId}] starting LINE provider${lineBotLabel}`); - return await getLineRuntime().channel.line.monitorLineProvider({ + return await monitorLineProvider({ channelAccessToken: token, channelSecret: secret, accountId: account.accountId, @@ -106,7 +109,7 @@ export const lineGatewayAdapter: NonNullable[ await getLineRuntime().config.writeConfigFile(nextCfg); } - const resolved = getLineRuntime().channel.line.resolveLineAccount({ + const resolved = resolveLineAccount({ cfg: changed ? nextCfg : cfg, accountId, }); diff --git a/extensions/line/src/outbound.ts b/extensions/line/src/outbound.ts index f3d4d49f329..517b7c751ab 100644 --- a/extensions/line/src/outbound.ts +++ b/extensions/line/src/outbound.ts @@ -11,6 +11,17 @@ import { } from "../api.js"; import { resolveLineOutboundMedia, type LineOutboundMediaResolved } from "./outbound-media.js"; import { getLineRuntime } from "./runtime.js"; +import { + createQuickReplyItems, + pushFlexMessage, + pushLocationMessage, + pushMessageLine, + pushMessagesLine, + pushTemplateMessage, + pushTextMessageWithQuickReplies, + sendMessageLine, +} from "./send.js"; +import { buildTemplateMessageFromPayload } from "./template-messages.js"; type LineChannelDataWithMedia = LineChannelData & { mediaKind?: "image" | "video" | "audio"; @@ -77,14 +88,13 @@ export const lineOutboundAdapter: NonNullable sendPayload: async ({ to, payload, accountId, cfg }) => { const runtime = getLineRuntime(); const lineData = (payload.channelData?.line as LineChannelDataWithMedia | undefined) ?? {}; - const sendText = runtime.channel.line.pushMessageLine; - const sendBatch = runtime.channel.line.pushMessagesLine; - const sendFlex = runtime.channel.line.pushFlexMessage; - const sendTemplate = runtime.channel.line.pushTemplateMessage; - const sendLocation = runtime.channel.line.pushLocationMessage; - const sendQuickReplies = runtime.channel.line.pushTextMessageWithQuickReplies; - const buildTemplate = runtime.channel.line.buildTemplateMessageFromPayload; - const createQuickReplyItems = runtime.channel.line.createQuickReplyItems; + const sendText = pushMessageLine; + const sendBatch = pushMessagesLine; + const sendFlex = pushFlexMessage; + const sendTemplate = pushTemplateMessage; + const sendLocation = pushLocationMessage; + const sendQuickReplies = pushTextMessageWithQuickReplies; + const buildTemplate = buildTemplateMessageFromPayload; let lastResult: { messageId: string; chatId: string } | null = null; const quickReplies = lineData.quickReplies ?? []; @@ -129,7 +139,7 @@ export const lineOutboundAdapter: NonNullable continue; } if (!useLineSpecificMedia) { - lastResult = await runtime.channel.line.sendMessageLine(to, "", { + lastResult = await sendMessageLine(to, "", { verbose: false, mediaUrl: trimmed, cfg, @@ -143,7 +153,7 @@ export const lineOutboundAdapter: NonNullable durationMs: lineData.durationMs, trackingId: lineData.trackingId, }); - lastResult = await runtime.channel.line.sendMessageLine(to, "", { + lastResult = await sendMessageLine(to, "", { verbose: false, mediaUrl: resolved.mediaUrl, mediaKind: resolved.mediaKind, @@ -294,8 +304,8 @@ export const lineOutboundAdapter: NonNullable channel: "line", sendText: async ({ cfg, to, text, accountId }) => { const runtime = getLineRuntime(); - const sendText = runtime.channel.line.pushMessageLine; - const sendFlex = runtime.channel.line.pushFlexMessage; + const sendText = pushMessageLine; + const sendFlex = pushFlexMessage; const processed = processLineMessage(text); let result: { messageId: string; chatId: string }; if (processed.text.trim()) { @@ -318,7 +328,7 @@ export const lineOutboundAdapter: NonNullable return result; }, sendMedia: async ({ cfg, to, text, mediaUrl, accountId }) => - await getLineRuntime().channel.line.sendMessageLine(to, text, { + await sendMessageLine(to, text, { verbose: false, mediaUrl, cfg, diff --git a/extensions/signal/src/channel.ts b/extensions/signal/src/channel.ts index 09d3ac10a99..5b23325b696 100644 --- a/extensions/signal/src/channel.ts +++ b/extensions/signal/src/channel.ts @@ -14,6 +14,7 @@ import { resolveSignalAccount, type ResolvedSignalAccount } from "./accounts.js" import { signalApprovalAuth } from "./approval-auth.js"; import { markdownToSignalTextChunks } from "./format.js"; import { signalMessageActions } from "./message-actions.js"; +import { monitorSignalProvider } from "./monitor.js"; import { looksLikeSignalTargetId, normalizeSignalMessagingTarget } from "./normalize.js"; import { resolveSignalOutboundTarget } from "./outbound-session.js"; import { probeSignal, type SignalProbe } from "./probe.js"; @@ -29,7 +30,7 @@ import { resolveChannelMediaMaxBytes, type ChannelPlugin, } from "./runtime-api.js"; -import { getSignalRuntime } from "./runtime.js"; +import { sendMessageSignal } from "./send.js"; import { signalSetupAdapter } from "./setup-core.js"; import { signalConfigAdapter, @@ -37,16 +38,14 @@ import { signalSecurityAdapter, signalSetupWizard, } from "./shared.js"; -type SignalSendFn = ReturnType["channel"]["signal"]["sendMessageSignal"]; +type SignalSendFn = typeof sendMessageSignal; function resolveSignalSendContext(params: { cfg: Parameters[0]["cfg"]; accountId?: string; deps?: { [channelId: string]: unknown }; }) { - const send = - resolveOutboundSendDep(params.deps, "signal") ?? - getSignalRuntime().channel.signal.sendMessageSignal; + const send = resolveOutboundSendDep(params.deps, "signal") ?? sendMessageSignal; const maxBytes = resolveChannelMediaMaxBytes({ cfg: params.cfg, resolveChannelLimitMb: ({ cfg, accountId }) => @@ -299,7 +298,7 @@ export const signalPlugin: ChannelPlugin = }); ctx.log?.info(`[${account.accountId}] starting provider (${account.baseUrl})`); // Lazy import: the monitor pulls the reply pipeline; avoid ESM init cycles. - return getSignalRuntime().channel.signal.monitorSignalProvider({ + return monitorSignalProvider({ accountId: account.accountId, config: ctx.cfg, runtime: ctx.runtime, @@ -315,7 +314,7 @@ export const signalPlugin: ChannelPlugin = message: PAIRING_APPROVED_MESSAGE, normalizeAllowEntry: createPairingPrefixStripper(/^signal:/i), notify: async ({ id, message }) => { - await getSignalRuntime().channel.signal.sendMessageSignal(id, message); + await sendMessageSignal(id, message); }, }, }, diff --git a/extensions/slack/index.ts b/extensions/slack/index.ts index f59b28f1f94..924e6bc50eb 100644 --- a/extensions/slack/index.ts +++ b/extensions/slack/index.ts @@ -1,5 +1,6 @@ import { defineChannelPluginEntry } from "openclaw/plugin-sdk/core"; import { slackPlugin } from "./src/channel.js"; +import { registerSlackPluginHttpRoutes } from "./src/http/plugin-routes.js"; import { setSlackRuntime } from "./src/runtime.js"; export { slackPlugin } from "./src/channel.js"; @@ -11,4 +12,5 @@ export default defineChannelPluginEntry({ description: "Slack channel plugin", plugin: slackPlugin, setRuntime: setSlackRuntime, + registerFull: registerSlackPluginHttpRoutes, }); diff --git a/extensions/slack/src/channel.ts b/extensions/slack/src/channel.ts index a37531784de..5175e9a3cd5 100644 --- a/extensions/slack/src/channel.ts +++ b/extensions/slack/src/channel.ts @@ -36,7 +36,7 @@ import { resolveSlackReplyToMode, type ResolvedSlackAccount, } from "./accounts.js"; -import type { SlackActionContext } from "./action-runtime.js"; +import { handleSlackAction, type SlackActionContext } from "./action-runtime.js"; import { resolveSlackAutoThreadId } from "./action-threading.js"; import { slackApprovalCapability } from "./approval-native.js"; import { createSlackActions } from "./channel-actions.js"; @@ -45,13 +45,16 @@ import { listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig, } from "./directory-config.js"; +import { listSlackDirectoryGroupsLive, listSlackDirectoryPeersLive } from "./directory-live.js"; import { shouldSuppressLocalSlackExecApprovalPrompt } from "./exec-approvals.js"; import { resolveSlackGroupRequireMention, resolveSlackGroupToolPolicy } from "./group-policy.js"; import { isSlackInteractiveRepliesEnabled } from "./interactive-replies.js"; import { SLACK_TEXT_LIMIT } from "./limits.js"; +import { monitorSlackProvider } from "./monitor.js"; import { slackOutbound } from "./outbound-adapter.js"; import { probeSlack, type SlackProbe } from "./probe.js"; import { resolveSlackReplyBlocks } from "./reply-blocks.js"; +import { resolveSlackChannelAllowlist } from "./resolve-channels.js"; import { resolveSlackUserAllowlist } from "./resolve-users.js"; import { DEFAULT_ACCOUNT_ID, @@ -65,6 +68,7 @@ import { } from "./runtime-api.js"; import { getSlackRuntime } from "./runtime.js"; import { fetchSlackScopes } from "./scopes.js"; +import { sendMessageSlack } from "./send.js"; import { slackSetupAdapter } from "./setup-core.js"; import { slackSetupWizard } from "./setup-surface.js"; import { @@ -89,14 +93,7 @@ const resolveSlackDmPolicy = createScopedDmSecurityResolver["channel"]["slack"]["sendMessageSlack"]; +type SlackSendFn = typeof sendMessageSlack; function resolveSlackSendContext(params: { cfg: Parameters[0]["cfg"]; @@ -125,9 +122,7 @@ function resolveSlackSendContext(params: { replyToId?: string | number | null; threadId?: string | number | null; }) { - const send = - resolveOutboundSendDep(params.deps, "slack") ?? - getSlackRuntime().channel.slack.sendMessageSlack; + const send = resolveOutboundSendDep(params.deps, "slack") ?? sendMessageSlack; const account = resolveSlackAccount({ cfg: params.cfg, accountId: params.accountId }); const token = getTokenForOperation(account, "write"); const botToken = account.botToken?.trim(); @@ -323,7 +318,10 @@ export const slackPlugin: ChannelPlugin = crea listPeers: async (params) => listSlackDirectoryPeersFromConfig(params), listGroups: async (params) => listSlackDirectoryGroupsFromConfig(params), ...createRuntimeDirectoryLiveAdapter({ - getRuntime: () => getSlackRuntime().channel.slack, + getRuntime: () => ({ + listDirectoryGroupsLive: listSlackDirectoryGroupsLive, + listDirectoryPeersLive: listSlackDirectoryPeersLive, + }), listPeersLive: (runtime) => runtime.listDirectoryPeersLive, listGroupsLive: (runtime) => runtime.listDirectoryGroupsLive, }), @@ -349,10 +347,7 @@ export const slackPlugin: ChannelPlugin = crea inputs, missingTokenNote: "missing Slack token", resolveWithToken: ({ token, inputs }) => - getSlackRuntime().channel.slack.resolveChannelAllowlist({ - token, - entries: inputs, - }), + resolveSlackChannelAllowlist({ token, entries: inputs }), mapResolved: (entry) => toResolvedTarget(entry, entry.archived ? "archived" : undefined), }); @@ -362,17 +357,14 @@ export const slackPlugin: ChannelPlugin = crea inputs, missingTokenNote: "missing Slack token", resolveWithToken: ({ token, inputs }) => - getSlackRuntime().channel.slack.resolveUserAllowlist({ - token, - entries: inputs, - }), + resolveSlackUserAllowlist({ token, entries: inputs }), mapResolved: (entry) => toResolvedTarget(entry, entry.note), }); }, }, actions: createSlackActions(SLACK_CHANNEL, { invoke: async (action, cfg, toolContext) => - await getSlackRuntime().channel.slack.handleSlackAction( + await handleSlackAction( action, cfg as OpenClawConfig, toolContext as SlackActionContext | undefined, @@ -450,7 +442,7 @@ export const slackPlugin: ChannelPlugin = crea const botToken = account.botToken?.trim(); const appToken = account.appToken?.trim(); ctx.log?.info(`[${account.accountId}] starting provider`); - return getSlackRuntime().channel.slack.monitorSlackProvider({ + return monitorSlackProvider({ botToken: botToken ?? "", appToken: appToken ?? "", accountId: account.accountId, @@ -480,11 +472,11 @@ export const slackPlugin: ChannelPlugin = crea const botToken = account.botToken?.trim(); const tokenOverride = token && token !== botToken ? token : undefined; if (tokenOverride) { - await getSlackRuntime().channel.slack.sendMessageSlack(`user:${id}`, message, { + await sendMessageSlack(`user:${id}`, message, { token: tokenOverride, }); } else { - await getSlackRuntime().channel.slack.sendMessageSlack(`user:${id}`, message); + await sendMessageSlack(`user:${id}`, message); } }, }, diff --git a/extensions/slack/src/http/plugin-routes.ts b/extensions/slack/src/http/plugin-routes.ts new file mode 100644 index 00000000000..5bce8d12574 --- /dev/null +++ b/extensions/slack/src/http/plugin-routes.ts @@ -0,0 +1,23 @@ +import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { listSlackAccountIds, resolveSlackAccount } from "../accounts.js"; +import { handleSlackHttpRequest, normalizeSlackWebhookPath } from "./registry.js"; + +export function registerSlackPluginHttpRoutes(api: OpenClawPluginApi): void { + const accountIds = new Set([DEFAULT_ACCOUNT_ID, ...listSlackAccountIds(api.config)]); + const registeredPaths = new Set(); + for (const accountId of accountIds) { + const account = resolveSlackAccount({ cfg: api.config, accountId }); + registeredPaths.add(normalizeSlackWebhookPath(account.config.webhookPath)); + } + if (registeredPaths.size === 0) { + registeredPaths.add(normalizeSlackWebhookPath()); + } + for (const path of registeredPaths) { + api.registerHttpRoute({ + path, + auth: "plugin", + handler: async (req, res) => await handleSlackHttpRequest(req, res), + }); + } +} diff --git a/extensions/telegram/src/approval-native.ts b/extensions/telegram/src/approval-native.ts index b0812774664..2a11cba52fa 100644 --- a/extensions/telegram/src/approval-native.ts +++ b/extensions/telegram/src/approval-native.ts @@ -4,6 +4,7 @@ import { createApproverRestrictedNativeApprovalCapability, splitChannelApprovalCapability, } from "openclaw/plugin-sdk/approval-runtime"; +import type { ChannelApprovalCapability } from "openclaw/plugin-sdk/channel-contract"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime"; import { listTelegramAccountIds } from "./accounts.js"; @@ -84,7 +85,7 @@ const resolveTelegramApproverDmTargets = createChannelApproverDmTargetResolver({ mapApprover: (approver) => ({ to: approver }), }); -export const telegramApprovalCapability = createApproverRestrictedNativeApprovalCapability({ +const telegramNativeApprovalCapability = createApproverRestrictedNativeApprovalCapability({ channel: "telegram", channelLabel: "Telegram", listAccountIds: listTelegramAccountIds, @@ -105,6 +106,32 @@ export const telegramApprovalCapability = createApproverRestrictedNativeApproval resolveApproverDmTargets: resolveTelegramApproverDmTargets, }); +const resolveTelegramApproveCommandBehavior: NonNullable< + ChannelApprovalCapability["resolveApproveCommandBehavior"] +> = ({ cfg, accountId, senderId, approvalKind }) => { + if (approvalKind !== "exec") { + return undefined; + } + if (isTelegramExecApprovalClientEnabled({ cfg, accountId })) { + return undefined; + } + if ( + isTelegramExecApprovalAuthorizedSender({ cfg, accountId, senderId }) && + !isTelegramExecApprovalApprover({ cfg, accountId, senderId }) + ) { + return { kind: "ignore" }; + } + return { + kind: "reply", + text: "❌ Telegram exec approvals are not enabled for this bot account.", + }; +}; + +export const telegramApprovalCapability: ChannelApprovalCapability = { + ...telegramNativeApprovalCapability, + resolveApproveCommandBehavior: resolveTelegramApproveCommandBehavior, +}; + export const telegramNativeApprovalAdapter = splitChannelApprovalCapability( telegramApprovalCapability, ); diff --git a/extensions/whatsapp/src/shared.ts b/extensions/whatsapp/src/shared.ts index fd7834cf03f..c0b085e679e 100644 --- a/extensions/whatsapp/src/shared.ts +++ b/extensions/whatsapp/src/shared.ts @@ -14,6 +14,7 @@ import { listWhatsAppAccountIds, resolveDefaultWhatsAppAccountId, resolveWhatsAppAccount, + hasAnyWhatsAppAuth, type ResolvedWhatsAppAccount, } from "./accounts.js"; import { WhatsAppChannelConfigSchema } from "./config-schema.js"; @@ -141,6 +142,7 @@ export function createWhatsAppPluginBase(params: { isEnabled: (account, cfg) => account.enabled && cfg.web?.enabled !== false, disabledReason: () => "disabled", isConfigured: params.isConfigured, + hasPersistedAuthState: ({ cfg }) => hasAnyWhatsAppAuth(cfg), unconfiguredReason: () => "not linked", describeAccount: (account) => describeAccountSnapshot({ diff --git a/scripts/lib/plugin-sdk-facades.mjs b/scripts/lib/plugin-sdk-facades.mjs index e6317475cfe..3172b2e40fa 100644 --- a/scripts/lib/plugin-sdk-facades.mjs +++ b/scripts/lib/plugin-sdk-facades.mjs @@ -40,154 +40,6 @@ export const GENERATED_PLUGIN_SDK_FACADES = [ "resolveAnthropicVertexRegionFromBaseUrl", ], }, - { - subpath: "discord-account", - source: pluginSource("discord", "api.js"), - exports: ["resolveDiscordAccount", "ResolvedDiscordAccount"], - typeExports: ["ResolvedDiscordAccount"], - }, - { - subpath: "discord-runtime-surface", - source: pluginSource("discord", "runtime-api.js"), - // Runtime entrypoints should be blocked until the owning plugin is active. - loadPolicy: "activated", - exports: [ - "addRoleDiscord", - "auditDiscordChannelPermissions", - "banMemberDiscord", - "collectDiscordAuditChannelIds", - "createChannelDiscord", - "createScheduledEventDiscord", - "createThreadDiscord", - "deleteChannelDiscord", - "deleteMessageDiscord", - "discordMessageActions", - "editChannelDiscord", - "editDiscordComponentMessage", - "editMessageDiscord", - "fetchChannelInfoDiscord", - "fetchChannelPermissionsDiscord", - "fetchMemberInfoDiscord", - "fetchMessageDiscord", - "fetchReactionsDiscord", - "fetchRoleInfoDiscord", - "fetchVoiceStatusDiscord", - "getGateway", - "getPresence", - "hasAnyGuildPermissionDiscord", - "kickMemberDiscord", - "listDiscordDirectoryGroupsLive", - "listDiscordDirectoryPeersLive", - "listGuildChannelsDiscord", - "listGuildEmojisDiscord", - "listPinsDiscord", - "listScheduledEventsDiscord", - "listThreadsDiscord", - "monitorDiscordProvider", - "moveChannelDiscord", - "pinMessageDiscord", - "probeDiscord", - "reactMessageDiscord", - "readMessagesDiscord", - "registerBuiltDiscordComponentMessage", - "removeChannelPermissionDiscord", - "removeOwnReactionsDiscord", - "removeReactionDiscord", - "removeRoleDiscord", - "resolveDiscordChannelAllowlist", - "resolveDiscordOutboundSessionRoute", - "resolveDiscordUserAllowlist", - "searchMessagesDiscord", - "sendDiscordComponentMessage", - "sendMessageDiscord", - "sendPollDiscord", - "sendStickerDiscord", - "sendTypingDiscord", - "sendVoiceMessageDiscord", - "setChannelPermissionDiscord", - "timeoutMemberDiscord", - "unpinMessageDiscord", - "uploadEmojiDiscord", - "uploadStickerDiscord", - ], - }, - { - subpath: "discord-session-key", - source: pluginSource("discord", "session-key-api.js"), - exports: ["normalizeExplicitDiscordSessionKey"], - }, - { - subpath: "discord-surface", - source: pluginSource("discord", "api.js"), - exports: [ - "buildDiscordComponentMessage", - "collectDiscordStatusIssues", - "createDiscordActionGate", - "DiscordComponentMessageSpec", - "DiscordSendComponents", - "DiscordSendEmbeds", - "DiscordSendResult", - "handleDiscordMessageAction", - "inspectDiscordAccount", - "isDiscordExecApprovalApprover", - "isDiscordExecApprovalClientEnabled", - "InspectedDiscordAccount", - "listDiscordAccountIds", - "listDiscordDirectoryGroupsFromConfig", - "listDiscordDirectoryPeersFromConfig", - "looksLikeDiscordTargetId", - "normalizeDiscordMessagingTarget", - "normalizeDiscordOutboundTarget", - "readDiscordComponentSpec", - "ResolvedDiscordAccount", - "resolveDefaultDiscordAccountId", - "resolveDiscordAccount", - "resolveDiscordChannelId", - "resolveDiscordRuntimeGroupPolicy", - "resolveDiscordGroupRequireMention", - "resolveDiscordGroupToolPolicy", - ], - typeExports: [ - "DiscordComponentMessageSpec", - "DiscordProbe", - "DiscordSendComponents", - "DiscordSendEmbeds", - "DiscordSendResult", - "DiscordTokenResolution", - "InspectedDiscordAccount", - "ResolvedDiscordAccount", - ], - }, - { - subpath: "discord-thread-bindings", - source: pluginSource("discord", "runtime-api.js"), - loadPolicy: "activated", - directExports: { - unbindThreadBindingsBySessionKey: "./discord-maintenance.js", - }, - exports: [ - "autoBindSpawnedDiscordSubagent", - "createThreadBindingManager", - "getThreadBindingManager", - "listThreadBindingsBySessionKey", - "resolveThreadBindingIdleTimeoutMs", - "resolveThreadBindingInactivityExpiresAt", - "resolveThreadBindingMaxAgeExpiresAt", - "resolveThreadBindingMaxAgeMs", - "setThreadBindingIdleTimeoutBySessionKey", - "setThreadBindingMaxAgeBySessionKey", - "ThreadBindingManager", - "ThreadBindingRecord", - "ThreadBindingTargetKind", - "unbindThreadBindingsBySessionKey", - ], - typeExports: ["ThreadBindingManager", "ThreadBindingRecord", "ThreadBindingTargetKind"], - }, - { - subpath: "discord-timeouts", - source: pluginSource("discord", "timeouts.js"), - exports: ["DISCORD_DEFAULT_INBOUND_WORKER_TIMEOUT_MS", "DISCORD_DEFAULT_LISTENER_TIMEOUT_MS"], - }, { subpath: "anthropic-cli", source: pluginSource("anthropic", "api.js"), @@ -836,32 +688,6 @@ export const GENERATED_PLUGIN_SDK_FACADES = [ source: pluginSource("qianfan", "api.js"), exports: ["QIANFAN_BASE_URL", "QIANFAN_DEFAULT_MODEL_ID", "buildQianfanProvider"], }, - { - subpath: "signal-account", - source: pluginSource("signal", "api.js"), - exports: ["resolveSignalAccount", "ResolvedSignalAccount"], - typeExports: ["ResolvedSignalAccount"], - }, - { - subpath: "signal-surface", - source: pluginSource("signal", "api.js"), - exports: [ - "isSignalSenderAllowed", - "listEnabledSignalAccounts", - "listSignalAccountIds", - "monitorSignalProvider", - "probeSignal", - "removeReactionSignal", - "ResolvedSignalAccount", - "resolveDefaultSignalAccountId", - "resolveSignalReactionLevel", - "sendMessageSignal", - "sendReactionSignal", - "signalMessageActions", - "SignalSender", - ], - typeExports: ["ResolvedSignalAccount", "SignalProbe", "SignalSender"], - }, { subpath: "provider-reasoning", source: pluginSource("ollama", "api.js"), @@ -938,84 +764,6 @@ export const GENERATED_PLUGIN_SDK_FACADES = [ "SYNTHETIC_MODEL_CATALOG", ], }, - { - subpath: "slack-target-parser", - source: pluginSource("slack", "api.js"), - exports: ["parseSlackTarget", "resolveSlackChannelId"], - }, - { - subpath: "slack-account", - source: pluginSource("slack", "api.js"), - exports: ["resolveSlackAccount", "ResolvedSlackAccount"], - typeExports: ["ResolvedSlackAccount"], - }, - { - subpath: "slack-runtime-surface", - source: pluginSource("slack", "runtime-api.js"), - loadPolicy: "activated", - exports: [ - "handleSlackAction", - "listSlackDirectoryGroupsLive", - "listSlackDirectoryPeersLive", - "monitorSlackProvider", - "probeSlack", - "resolveSlackChannelAllowlist", - "resolveSlackUserAllowlist", - "sendMessageSlack", - "SlackActionContext", - ], - typeExports: ["SlackActionContext"], - }, - { - subpath: "slack-surface", - source: pluginSource("slack", "api.js"), - functionExports: [ - "listSlackAccountIds", - "listSlackDirectoryGroupsFromConfig", - "listSlackDirectoryPeersFromConfig", - "resolveDefaultSlackAccountId", - "resolveSlackRuntimeGroupPolicy", - ], - exports: [ - "buildSlackThreadingToolContext", - "createSlackWebClient", - "deleteSlackMessage", - "downloadSlackFile", - "editSlackMessage", - "extractSlackToolSend", - "getSlackMemberInfo", - "handleSlackHttpRequest", - "inspectSlackAccount", - "InspectedSlackAccount", - "isSlackInteractiveRepliesEnabled", - "listEnabledSlackAccounts", - "listSlackAccountIds", - "listSlackDirectoryGroupsFromConfig", - "listSlackDirectoryPeersFromConfig", - "listSlackEmojis", - "listSlackMessageActions", - "listSlackPins", - "listSlackReactions", - "normalizeAllowListLower", - "parseSlackBlocksInput", - "recordSlackThreadParticipation", - "resolveDefaultSlackAccountId", - "resolveSlackAutoThreadId", - "resolveSlackGroupRequireMention", - "resolveSlackRuntimeGroupPolicy", - "resolveSlackGroupToolPolicy", - "resolveSlackReplyToMode", - "ResolvedSlackAccount", - "sendSlackMessage", - "pinSlackMessage", - "reactSlackMessage", - "readSlackMessages", - "removeOwnSlackReactions", - "removeSlackReaction", - "unpinSlackMessage", - ], - typeExports: ["InspectedSlackAccount", "ResolvedSlackAccount", "SlackProbe"], - }, { subpath: "together", source: pluginSource("together", "api.js"), @@ -1040,71 +788,6 @@ export const GENERATED_PLUGIN_SDK_FACADES = [ "VENICE_MODEL_CATALOG", ], }, - { - subpath: "telegram-account", - source: pluginSource("telegram", "api.js"), - exports: ["resolveTelegramAccount", "ResolvedTelegramAccount"], - typeExports: ["ResolvedTelegramAccount"], - }, - { - subpath: "telegram-allow-from", - source: pluginSource("telegram", "api.js"), - exports: ["isNumericTelegramUserId", "normalizeTelegramAllowFromEntry"], - }, - { - subpath: "telegram-surface", - source: pluginSource("telegram", "api.js"), - exports: [ - "buildBrowseProvidersButton", - "buildModelsKeyboard", - "buildProviderKeyboard", - "buildTelegramGroupPeerId", - "calculateTotalPages", - "createTelegramActionGate", - "fetchTelegramChatId", - "getCacheStats", - "getModelsPageSize", - "inspectTelegramAccount", - "InspectedTelegramAccount", - "isTelegramExecApprovalApprover", - "isTelegramExecApprovalAuthorizedSender", - "isTelegramExecApprovalClientEnabled", - "isTelegramExecApprovalTargetRecipient", - "listTelegramAccountIds", - "listTelegramDirectoryGroupsFromConfig", - "listTelegramDirectoryPeersFromConfig", - "looksLikeTelegramTargetId", - "lookupTelegramChatId", - "normalizeTelegramMessagingTarget", - "parseTelegramReplyToMessageId", - "parseTelegramTarget", - "parseTelegramThreadId", - "ProviderInfo", - "ResolvedTelegramAccount", - "resolveTelegramAutoThreadId", - "resolveTelegramGroupRequireMention", - "resolveTelegramGroupToolPolicy", - "resolveTelegramInlineButtonsScope", - "resolveTelegramPollActionGateState", - "resolveTelegramReactionLevel", - "resolveTelegramTargetChatType", - "searchStickers", - "sendTelegramPayloadMessages", - "StickerMetadata", - "TelegramButtonStyle", - "TelegramInlineButtons", - ], - typeExports: [ - "InspectedTelegramAccount", - "ProviderInfo", - "ResolvedTelegramAccount", - "StickerMetadata", - "TelegramButtonStyle", - "TelegramInlineButtons", - "TelegramProbe", - "TelegramTokenResolution", - ], - }, { subpath: "vercel-ai-gateway", source: pluginSource("vercel-ai-gateway", "api.js"), @@ -1193,36 +876,6 @@ export const GENERATED_PLUGIN_SDK_FACADES = [ "ZAI_GLOBAL_BASE_URL", ], }, - { - subpath: "whatsapp-targets", - source: pluginSource("whatsapp", "api.js"), - exports: ["isWhatsAppGroupJid", "isWhatsAppUserTarget", "normalizeWhatsAppTarget"], - }, - { - subpath: "whatsapp-surface", - source: pluginSource("whatsapp", "api.js"), - exportSources: { - DEFAULT_WEB_MEDIA_BYTES: pluginSource("whatsapp", "constants.js"), - }, - exports: [ - "DEFAULT_WEB_MEDIA_BYTES", - "hasAnyWhatsAppAuth", - "listEnabledWhatsAppAccounts", - "listWhatsAppDirectoryGroupsFromConfig", - "listWhatsAppDirectoryPeersFromConfig", - "resolveWhatsAppAccount", - "resolveWhatsAppGroupRequireMention", - "resolveWhatsAppGroupToolPolicy", - "resolveWhatsAppOutboundTarget", - "whatsappAccessControlTesting", - ], - typeExports: [ - "WebChannelStatus", - "WebInboundMessage", - "WebListenerCloseReason", - "WebMonitorTuning", - ], - }, { subpath: "zalo-setup", source: pluginSource("zalo", "api.js"), diff --git a/src/agents/pi-embedded-runner/tool-result-truncation.test.ts b/src/agents/pi-embedded-runner/tool-result-truncation.test.ts index a37a7ba289f..54a73e4f250 100644 --- a/src/agents/pi-embedded-runner/tool-result-truncation.test.ts +++ b/src/agents/pi-embedded-runner/tool-result-truncation.test.ts @@ -11,6 +11,7 @@ const acquireSessionWriteLockMock = vi.hoisted(() => vi.mock("../session-write-lock.js", () => ({ acquireSessionWriteLock: (params: unknown) => acquireSessionWriteLockMock(params), + resolveSessionLockMaxHoldFromTimeout: () => 1, })); let truncateToolResultText: typeof import("./tool-result-truncation.js").truncateToolResultText; @@ -28,6 +29,7 @@ async function loadFreshToolResultTruncationModuleForTest() { vi.resetModules(); vi.doMock("../session-write-lock.js", () => ({ acquireSessionWriteLock: (params: unknown) => acquireSessionWriteLockMock(params), + resolveSessionLockMaxHoldFromTimeout: () => 1, })); ({ onSessionTranscriptUpdate } = await import("../../sessions/transcript-events.js")); ({ diff --git a/src/agents/pi-embedded-runner/transcript-rewrite.test.ts b/src/agents/pi-embedded-runner/transcript-rewrite.test.ts index 021475eb9c5..09a9e5a4466 100644 --- a/src/agents/pi-embedded-runner/transcript-rewrite.test.ts +++ b/src/agents/pi-embedded-runner/transcript-rewrite.test.ts @@ -9,6 +9,7 @@ const acquireSessionWriteLockMock = vi.hoisted(() => vi.mock("../session-write-lock.js", () => ({ acquireSessionWriteLock: (params: unknown) => acquireSessionWriteLockMock(params), + resolveSessionLockMaxHoldFromTimeout: () => 1, })); let rewriteTranscriptEntriesInSessionFile: typeof import("./transcript-rewrite.js").rewriteTranscriptEntriesInSessionFile; @@ -20,6 +21,7 @@ async function loadFreshTranscriptRewriteModuleForTest() { vi.resetModules(); vi.doMock("../session-write-lock.js", () => ({ acquireSessionWriteLock: (params: unknown) => acquireSessionWriteLockMock(params), + resolveSessionLockMaxHoldFromTimeout: () => 1, })); ({ onSessionTranscriptUpdate } = await import("../../sessions/transcript-events.js")); ({ installSessionToolResultGuard } = await import("../session-tool-result-guard.js")); diff --git a/src/auto-reply/reply.test-harness.ts b/src/auto-reply/reply.test-harness.ts index fa0fd5ce801..4e079d22c61 100644 --- a/src/auto-reply/reply.test-harness.ts +++ b/src/auto-reply/reply.test-harness.ts @@ -141,7 +141,7 @@ export function installReplyRuntimeMocks(mocks: ReplyRuntimeMocks) { listSkillCommandsForWorkspace: () => [], })); - vi.mock("../plugins/runtime/runtime-web-channel-boundary.js", () => ({ + vi.mock("../plugins/runtime/runtime-web-channel-plugin.js", () => ({ webAuthExists: mocks.webAuthExists, getWebAuthAgeMs: mocks.getWebAuthAgeMs, readWebSelfId: mocks.readWebSelfId, diff --git a/src/auto-reply/reply/commands-approve.ts b/src/auto-reply/reply/commands-approve.ts index 0540109a064..9be27221cdf 100644 --- a/src/auto-reply/reply/commands-approve.ts +++ b/src/auto-reply/reply/commands-approve.ts @@ -1,7 +1,7 @@ import { - isTelegramExecApprovalAuthorizedSender, - isTelegramExecApprovalClientEnabled, -} from "../../../extensions/telegram/api.js"; + getChannelPlugin, + resolveChannelApprovalCapability, +} from "../../channels/plugins/index.js"; import { callGateway } from "../../gateway/call.js"; import { ErrorCodes } from "../../gateway/protocol/index.js"; import { logVerbose } from "../../globals.js"; @@ -77,17 +77,6 @@ function buildResolvedByLabel(params: Parameters[0]): string { return `${channel}:${sender}`; } -function isAuthorizedTelegramExecSender(params: Parameters[0]): boolean { - if (params.command.channel !== "telegram") { - return false; - } - return isTelegramExecApprovalAuthorizedSender({ - cfg: params.cfg, - accountId: params.ctx.AccountId, - senderId: params.command.senderId, - }); -} - function readErrorCode(value: unknown): string | null { return typeof value === "string" && value.trim() ? value : null; } @@ -178,7 +167,21 @@ export const handleApproveCommand: CommandHandler = async (params, allowTextComm } const isPluginId = parsed.id.startsWith("plugin:"); - const telegramExecAuthorizedSender = isAuthorizedTelegramExecSender(params); + const approvalCapability = resolveChannelApprovalCapability( + getChannelPlugin(params.command.channel), + ); + const approveCommandBehavior = approvalCapability?.resolveApproveCommandBehavior?.({ + cfg: params.cfg, + accountId: params.ctx.AccountId, + senderId: params.command.senderId, + approvalKind: isPluginId ? "plugin" : "exec", + }); + if (approveCommandBehavior?.kind === "ignore") { + return { shouldContinue: false }; + } + if (approveCommandBehavior?.kind === "reply") { + return { shouldContinue: false, reply: { text: approveCommandBehavior.text } }; + } const execApprovalAuthorization = resolveApprovalCommandAuthorization({ cfg: params.cfg, channel: params.command.channel, @@ -203,18 +206,6 @@ export const handleApproveCommand: CommandHandler = async (params, allowTextComm return { shouldContinue: false }; } - if ( - params.command.channel === "telegram" && - !isPluginId && - !telegramExecAuthorizedSender && - !isTelegramExecApprovalClientEnabled({ cfg: params.cfg, accountId: params.ctx.AccountId }) - ) { - return { - shouldContinue: false, - reply: { text: "❌ Telegram exec approvals are not enabled for this bot account." }, - }; - } - const missingScope = requireGatewayClientScopeForInternalChannel(params, { label: "/approve", allowedScopes: ["operator.approvals", "operator.admin"], diff --git a/src/auto-reply/reply/commands-session.ts b/src/auto-reply/reply/commands-session.ts index 659e1864870..a0f208e1c6d 100644 --- a/src/auto-reply/reply/commands-session.ts +++ b/src/auto-reply/reply/commands-session.ts @@ -1,4 +1,8 @@ import { resolveFastModeState } from "../../agents/fast-mode.js"; +import { + setChannelConversationBindingIdleTimeoutBySessionKey, + setChannelConversationBindingMaxAgeBySessionKey, +} from "../../channels/plugins/conversation-bindings.js"; import { formatThreadBindingDurationLabel } from "../../channels/thread-bindings-messages.js"; import { parseDurationMs } from "../../cli/parse-duration.js"; import { isRestartEnabled } from "../../config/commands.js"; @@ -7,7 +11,6 @@ import { getSessionBindingService } from "../../infra/outbound/session-binding-s import type { SessionBindingRecord } from "../../infra/outbound/session-binding-service.js"; import { scheduleGatewaySigusr1Restart, triggerOpenClawRestart } from "../../infra/restart.js"; import { loadCostUsageSummary, loadSessionCostSummary } from "../../infra/session-cost-usage.js"; -import { createPluginRuntime } from "../../plugins/runtime/index.js"; import { formatTokenCount, formatUsd } from "../../utils/usage-format.js"; import { parseActivationCommand } from "../group-activation.js"; import { parseSendPolicyCommand } from "../send-policy.js"; @@ -32,12 +35,6 @@ const SESSION_COMMAND_PREFIX = "/session"; const SESSION_DURATION_OFF_VALUES = new Set(["off", "disable", "disabled", "none", "0"]); const SESSION_ACTION_IDLE = "idle"; const SESSION_ACTION_MAX_AGE = "max-age"; -let cachedChannelRuntime: ReturnType["channel"] | undefined; - -function getChannelRuntime() { - cachedChannelRuntime ??= createPluginRuntime().channel; - return cachedChannelRuntime; -} function resolveSessionCommandUsage() { return "Usage: /session idle | /session max-age (example: /session idle 24h)"; @@ -462,20 +459,14 @@ export const handleSessionCommand: CommandHandler = async (params, allowTextComm }) : undefined; const telegramConversationId = onTelegram ? resolveTelegramConversationId(params) : undefined; - const channelRuntime = getChannelRuntime(); - - const discordManager = onDiscord - ? channelRuntime.discord.threadBindings.getManager(accountId) - : null; - if (onDiscord && !discordManager) { - return { - shouldContinue: false, - reply: { text: "⚠️ Discord thread bindings are unavailable for this account." }, - }; - } - const discordBinding = - onDiscord && threadId ? discordManager?.getByThreadId(threadId) : undefined; + onDiscord && threadId + ? sessionBindingService.resolveByConversation({ + channel: "discord", + accountId, + conversationId: threadId, + }) + : null; const telegramBinding = onTelegram && telegramConversationId ? sessionBindingService.resolveByConversation({ @@ -538,39 +529,18 @@ export const handleSessionCommand: CommandHandler = async (params, allowTextComm }; } - const idleTimeoutMs = onDiscord - ? channelRuntime.discord.threadBindings.resolveIdleTimeoutMs({ - record: discordBinding!, - defaultIdleTimeoutMs: discordManager!.getIdleTimeoutMs(), - }) - : resolveSessionBindingDurationMs( - (onMatrix ? matrixBinding : telegramBinding)!, - "idleTimeoutMs", - 24 * 60 * 60 * 1000, - ); - const idleExpiresAt = onDiscord - ? channelRuntime.discord.threadBindings.resolveInactivityExpiresAt({ - record: discordBinding!, - defaultIdleTimeoutMs: discordManager!.getIdleTimeoutMs(), - }) - : idleTimeoutMs > 0 - ? resolveSessionBindingLastActivityAt((onMatrix ? matrixBinding : telegramBinding)!) + - idleTimeoutMs - : undefined; - const maxAgeMs = onDiscord - ? channelRuntime.discord.threadBindings.resolveMaxAgeMs({ - record: discordBinding!, - defaultMaxAgeMs: discordManager!.getMaxAgeMs(), - }) - : resolveSessionBindingDurationMs((onMatrix ? matrixBinding : telegramBinding)!, "maxAgeMs", 0); - const maxAgeExpiresAt = onDiscord - ? channelRuntime.discord.threadBindings.resolveMaxAgeExpiresAt({ - record: discordBinding!, - defaultMaxAgeMs: discordManager!.getMaxAgeMs(), - }) - : maxAgeMs > 0 - ? (onMatrix ? matrixBinding : telegramBinding)!.boundAt + maxAgeMs + const activeBinding = (onDiscord ? discordBinding : onMatrix ? matrixBinding : telegramBinding)!; + const idleTimeoutMs = resolveSessionBindingDurationMs( + activeBinding, + "idleTimeoutMs", + 24 * 60 * 60 * 1000, + ); + const idleExpiresAt = + idleTimeoutMs > 0 + ? resolveSessionBindingLastActivityAt(activeBinding) + idleTimeoutMs : undefined; + const maxAgeMs = resolveSessionBindingDurationMs(activeBinding, "maxAgeMs", 0); + const maxAgeExpiresAt = maxAgeMs > 0 ? activeBinding.boundAt + maxAgeMs : undefined; const durationArgRaw = tokens.slice(1).join(""); if (!durationArgRaw) { @@ -612,9 +582,7 @@ export const handleSessionCommand: CommandHandler = async (params, allowTextComm } const senderId = params.command.senderId?.trim() || ""; - const boundBy = onDiscord - ? discordBinding!.boundBy - : resolveSessionBindingBoundBy((onMatrix ? matrixBinding : telegramBinding)!); + const boundBy = resolveSessionBindingBoundBy(activeBinding); if (boundBy && boundBy !== "system" && senderId && senderId !== boundBy) { return { shouldContinue: false, @@ -638,47 +606,21 @@ export const handleSessionCommand: CommandHandler = async (params, allowTextComm }; } - const updatedBindings = (() => { - if (onDiscord) { - return action === SESSION_ACTION_IDLE - ? channelRuntime.discord.threadBindings.setIdleTimeoutBySessionKey({ - targetSessionKey: discordBinding!.targetSessionKey, - accountId, - idleTimeoutMs: durationMs, - }) - : channelRuntime.discord.threadBindings.setMaxAgeBySessionKey({ - targetSessionKey: discordBinding!.targetSessionKey, - accountId, - maxAgeMs: durationMs, - }); - } - if (onMatrix) { - return action === SESSION_ACTION_IDLE - ? channelRuntime.matrix.threadBindings.setIdleTimeoutBySessionKey({ - targetSessionKey: matrixBinding!.targetSessionKey, - accountId, - idleTimeoutMs: durationMs, - }) - : channelRuntime.matrix.threadBindings.setMaxAgeBySessionKey({ - targetSessionKey: matrixBinding!.targetSessionKey, - accountId, - maxAgeMs: durationMs, - }); - } - return action === SESSION_ACTION_IDLE - ? channelRuntime.threadBindings.setIdleTimeoutBySessionKey({ - channelId: "telegram", - targetSessionKey: telegramBinding!.targetSessionKey, + const channelId = onDiscord ? "discord" : onMatrix ? "matrix" : "telegram"; + const updatedBindings = + action === SESSION_ACTION_IDLE + ? setChannelConversationBindingIdleTimeoutBySessionKey({ + channelId, + targetSessionKey: activeBinding.targetSessionKey, accountId, idleTimeoutMs: durationMs, }) - : channelRuntime.threadBindings.setMaxAgeBySessionKey({ - channelId: "telegram", - targetSessionKey: telegramBinding!.targetSessionKey, + : setChannelConversationBindingMaxAgeBySessionKey({ + channelId, + targetSessionKey: activeBinding.targetSessionKey, accountId, maxAgeMs: durationMs, }); - })(); if (updatedBindings.length === 0) { return { shouldContinue: false, diff --git a/src/auto-reply/reply/commands.test.ts b/src/auto-reply/reply/commands.test.ts index d82eb861c63..71b3dc2199a 100644 --- a/src/auto-reply/reply/commands.test.ts +++ b/src/auto-reply/reply/commands.test.ts @@ -491,6 +491,26 @@ const telegramCommandTestPlugin: ChannelPlugin = { formatAllowFrom: normalizeTelegramAllowFromEntries, }), auth: telegramNativeApprovalAdapter.auth, + approvalCapability: { + resolveApproveCommandBehavior: ({ cfg, accountId, senderId, approvalKind }) => { + if (approvalKind !== "exec") { + return undefined; + } + if (isTelegramExecApprovalClientEnabled({ cfg, accountId })) { + return undefined; + } + if ( + isTelegramExecApprovalAuthorizedSender({ cfg, accountId, senderId }) && + !getTelegramExecApprovalApprovers({ cfg, accountId }).includes(senderId?.trim() ?? "") + ) { + return { kind: "ignore" } as const; + } + return { + kind: "reply", + text: "❌ Telegram exec approvals are not enabled for this bot account.", + } as const; + }, + }, pairing: { idLabel: "telegramUserId", }, diff --git a/src/auto-reply/reply/followup-runner.test.ts b/src/auto-reply/reply/followup-runner.test.ts index fe983fd9a98..a81a1e436b1 100644 --- a/src/auto-reply/reply/followup-runner.test.ts +++ b/src/auto-reply/reply/followup-runner.test.ts @@ -229,6 +229,7 @@ async function loadFreshFollowupRunnerModuleForTest() { acquireSessionWriteLock: vi.fn(async () => ({ release: async () => {}, })), + resolveSessionLockMaxHoldFromTimeout: vi.fn(() => 1), })); vi.doMock("../../agents/pi-embedded.js", () => ({ abortEmbeddedPiRun: vi.fn(async () => false), diff --git a/src/auto-reply/reply/session.test.ts b/src/auto-reply/reply/session.test.ts index ba81f3932aa..bceda16fb64 100644 --- a/src/auto-reply/reply/session.test.ts +++ b/src/auto-reply/reply/session.test.ts @@ -28,6 +28,7 @@ import { initSessionState } from "./session.js"; // Perf: session-store locks are exercised elsewhere; most session tests don't need FS lock files. vi.mock("../../agents/session-write-lock.js", () => ({ acquireSessionWriteLock: async () => ({ release: async () => {} }), + resolveSessionLockMaxHoldFromTimeout: () => 1, })); vi.mock("../../agents/model-catalog.js", () => ({ diff --git a/src/channel-web.ts b/src/channel-web.ts index 0690f779f9d..2a2fc17f82b 100644 --- a/src/channel-web.ts +++ b/src/channel-web.ts @@ -1,12 +1,12 @@ // Barrel exports for the web channel pieces. Splitting the original 900+ line // module keeps responsibilities small and testable. -import { resolveWaWebAuthDir } from "./plugins/runtime/runtime-web-channel-boundary.js"; +import { resolveWebChannelAuthDir } from "./plugins/runtime/runtime-web-channel-plugin.js"; export { HEARTBEAT_PROMPT } from "./auto-reply/heartbeat.js"; export { HEARTBEAT_TOKEN } from "./auto-reply/tokens.js"; export { loadWebMedia, optimizeImageToJpeg } from "./media/web-media.js"; export { - createWaSocket, + createWebChannelSocket as createWaSocket, extractMediaPlaceholder, extractText, formatError, @@ -19,19 +19,19 @@ export { pickWebChannel, resolveHeartbeatRecipients, runWebHeartbeatOnce, - sendMessageWhatsApp, - sendReactionWhatsApp, - waitForWaConnection, + sendWebChannelMessage as sendMessageWhatsApp, + sendWebChannelReaction as sendReactionWhatsApp, + waitForWebChannelConnection as waitForWaConnection, webAuthExists, -} from "./plugins/runtime/runtime-web-channel-boundary.js"; +} from "./plugins/runtime/runtime-web-channel-plugin.js"; // Keep the historic constant surface available, but resolve it through the -// plugin boundary only when a caller actually coerces the value to string. -class LazyWhatsAppAuthDir { +// web-channel plugin boundary only when a caller actually coerces the value to string. +class LazyWebChannelAuthDir { #value: string | null = null; #read(): string { - this.#value ??= resolveWaWebAuthDir(); + this.#value ??= resolveWebChannelAuthDir(); return this.#value; } @@ -48,4 +48,4 @@ class LazyWhatsAppAuthDir { } } -export const WA_WEB_AUTH_DIR = new LazyWhatsAppAuthDir() as unknown as string; +export const WA_WEB_AUTH_DIR = new LazyWebChannelAuthDir() as unknown as string; diff --git a/src/channels/channels-misc.test.ts b/src/channels/channels-misc.test.ts index 076ca85fa85..d1b1bbb022f 100644 --- a/src/channels/channels-misc.test.ts +++ b/src/channels/channels-misc.test.ts @@ -29,15 +29,15 @@ describe("normalizeChatType", () => { describe("WA_WEB_AUTH_DIR", () => { afterEach(() => { - vi.doUnmock("../plugins/runtime/runtime-web-channel-boundary.js"); + vi.doUnmock("../plugins/runtime/runtime-web-channel-plugin.js"); }); it("resolves lazily and caches across the legacy and channels/web entrypoints", async () => { - const resolveWaWebAuthDir = vi.fn(() => "/tmp/openclaw-whatsapp-auth"); + const resolveWebChannelAuthDir = vi.fn(() => "/tmp/openclaw-whatsapp-auth"); vi.resetModules(); - vi.doMock("../plugins/runtime/runtime-web-channel-boundary.js", () => ({ - createWaSocket: vi.fn(), + vi.doMock("../plugins/runtime/runtime-web-channel-plugin.js", () => ({ + createWebChannelSocket: vi.fn(), extractMediaPlaceholder: vi.fn(), extractText: vi.fn(), formatError: vi.fn(), @@ -49,20 +49,20 @@ describe("WA_WEB_AUTH_DIR", () => { monitorWebInbox: vi.fn(), pickWebChannel: vi.fn(), resolveHeartbeatRecipients: vi.fn(), - resolveWaWebAuthDir, + resolveWebChannelAuthDir, runWebHeartbeatOnce: vi.fn(), - sendMessageWhatsApp: vi.fn(), - sendReactionWhatsApp: vi.fn(), - waitForWaConnection: vi.fn(), + sendWebChannelMessage: vi.fn(), + sendWebChannelReaction: vi.fn(), + waitForWebChannelConnection: vi.fn(), webAuthExists: vi.fn(), })); const channelWeb = await import("../channel-web.js"); const webEntry = await import("./web/index.js"); - expect(resolveWaWebAuthDir).not.toHaveBeenCalled(); + expect(resolveWebChannelAuthDir).not.toHaveBeenCalled(); expect(String(channelWeb.WA_WEB_AUTH_DIR)).toBe("/tmp/openclaw-whatsapp-auth"); expect(String(webEntry.WA_WEB_AUTH_DIR)).toBe("/tmp/openclaw-whatsapp-auth"); - expect(resolveWaWebAuthDir).toHaveBeenCalledTimes(1); + expect(resolveWebChannelAuthDir).toHaveBeenCalledTimes(1); }); }); diff --git a/src/channels/plugins/approvals.ts b/src/channels/plugins/approvals.ts index 6c9c69841bc..9eebe87f804 100644 --- a/src/channels/plugins/approvals.ts +++ b/src/channels/plugins/approvals.ts @@ -5,10 +5,12 @@ function buildApprovalCapabilityFromLegacyPlugin( ): ChannelApprovalCapability | undefined { const authorizeActorAction = plugin?.auth?.authorizeActorAction; const getActionAvailabilityState = plugin?.auth?.getActionAvailabilityState; + const resolveApproveCommandBehavior = plugin?.auth?.resolveApproveCommandBehavior; const approvals = plugin?.approvals; if ( !authorizeActorAction && !getActionAvailabilityState && + !resolveApproveCommandBehavior && !approvals?.delivery && !approvals?.render && !approvals?.native @@ -18,6 +20,7 @@ function buildApprovalCapabilityFromLegacyPlugin( return { authorizeActorAction, getActionAvailabilityState, + resolveApproveCommandBehavior, delivery: approvals?.delivery, render: approvals?.render, native: approvals?.native, @@ -39,6 +42,8 @@ export function resolveChannelApprovalCapability( authorizeActorAction: capability.authorizeActorAction ?? legacyCapability.authorizeActorAction, getActionAvailabilityState: capability.getActionAvailabilityState ?? legacyCapability.getActionAvailabilityState, + resolveApproveCommandBehavior: + capability.resolveApproveCommandBehavior ?? legacyCapability.resolveApproveCommandBehavior, delivery: capability.delivery ?? legacyCapability.delivery, render: capability.render ?? legacyCapability.render, native: capability.native ?? legacyCapability.native, diff --git a/src/channels/plugins/types.adapters.ts b/src/channels/plugins/types.adapters.ts index 975628c48ba..9b022e50a41 100644 --- a/src/channels/plugins/types.adapters.ts +++ b/src/channels/plugins/types.adapters.ts @@ -120,6 +120,7 @@ export type ChannelConfigAdapter = { accountId?: string | null; allowFrom: Array; }) => string[]; + hasPersistedAuthState?: (params: { cfg: OpenClawConfig; env?: NodeJS.ProcessEnv }) => boolean; resolveDefaultTo?: (params: { cfg: OpenClawConfig; accountId?: string | null; @@ -415,6 +416,7 @@ export type ChannelAuthAdapter = { accountId?: string | null; action: "approve"; }) => ChannelActionAvailabilityState; + resolveApproveCommandBehavior?: ChannelApprovalCapability["resolveApproveCommandBehavior"]; }; export type ChannelHeartbeatAdapter = { @@ -520,6 +522,11 @@ export type ChannelApprovalDeliveryAdapter = { export type ChannelApprovalKind = "exec" | "plugin"; +export type ChannelApproveCommandBehavior = + | { kind: "allow" } + | { kind: "ignore" } + | { kind: "reply"; text: string }; + export type ChannelApprovalNativeSurface = "origin" | "approver-dm"; export type ChannelApprovalNativeTarget = { @@ -592,6 +599,12 @@ export type ChannelApprovalRenderAdapter = { export type ChannelApprovalCapability = ChannelApprovalAdapter & { authorizeActorAction?: ChannelAuthAdapter["authorizeActorAction"]; getActionAvailabilityState?: ChannelAuthAdapter["getActionAvailabilityState"]; + resolveApproveCommandBehavior?: (params: { + cfg: OpenClawConfig; + accountId?: string | null; + senderId?: string | null; + approvalKind: ChannelApprovalKind; + }) => ChannelApproveCommandBehavior | undefined; }; export type ChannelApprovalAdapter = { diff --git a/src/channels/plugins/types.core.ts b/src/channels/plugins/types.core.ts index f74d438fe96..3cc48eeace9 100644 --- a/src/channels/plugins/types.core.ts +++ b/src/channels/plugins/types.core.ts @@ -397,6 +397,10 @@ export type ChannelThreadingToolContext = { /** Channel-owned messaging helpers for target parsing, routing, and payload shaping. */ export type ChannelMessagingAdapter = { normalizeTarget?: (raw: string) => string | undefined; + normalizeExplicitSessionKey?: (params: { + sessionKey: string; + ctx: MsgContext; + }) => string | undefined; /** * Canonical plugin-owned session conversation grammar. * Use this when the provider encodes thread or scoped-conversation semantics diff --git a/src/channels/read-only-account-inspect.discord.runtime.ts b/src/channels/read-only-account-inspect.discord.runtime.ts deleted file mode 100644 index 5e3fe8fdafd..00000000000 --- a/src/channels/read-only-account-inspect.discord.runtime.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inspectDiscordAccount as inspectDiscordAccountImpl } from "../../extensions/discord/api.js"; - -export type { InspectedDiscordAccount } from "../../extensions/discord/api.js"; - -type InspectDiscordAccount = typeof import("../../extensions/discord/api.js").inspectDiscordAccount; - -export function inspectDiscordAccount( - ...args: Parameters -): ReturnType { - return inspectDiscordAccountImpl(...args); -} diff --git a/src/channels/read-only-account-inspect.slack.runtime.ts b/src/channels/read-only-account-inspect.slack.runtime.ts deleted file mode 100644 index 8e8db46073c..00000000000 --- a/src/channels/read-only-account-inspect.slack.runtime.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inspectSlackAccount as inspectSlackAccountImpl } from "../../extensions/slack/api.js"; - -export type { InspectedSlackAccount } from "../../extensions/slack/api.js"; - -type InspectSlackAccount = typeof import("../../extensions/slack/api.js").inspectSlackAccount; - -export function inspectSlackAccount( - ...args: Parameters -): ReturnType { - return inspectSlackAccountImpl(...args); -} diff --git a/src/cli/deps.test.ts b/src/cli/deps.test.ts index dd071657fe6..12e086d168c 100644 --- a/src/cli/deps.test.ts +++ b/src/cli/deps.test.ts @@ -19,15 +19,6 @@ const sendFns = vi.hoisted(() => ({ imessage: vi.fn(async () => ({ messageId: "i1", chatId: "imessage:1" })), })); -const whatsappBoundaryLoads = vi.hoisted(() => vi.fn()); - -vi.mock("../plugins/runtime/runtime-web-channel-boundary.js", async (importOriginal) => { - whatsappBoundaryLoads(); - return await importOriginal< - typeof import("../plugins/runtime/runtime-web-channel-boundary.js") - >(); -}); - vi.mock("./send-runtime/whatsapp.js", () => { moduleLoads.whatsapp(); return { runtimeSend: { sendMessage: sendFns.whatsapp } }; @@ -112,13 +103,4 @@ describe("createDefaultDeps", () => { expect(moduleLoads.discord).toHaveBeenCalledTimes(1); expect(sendFns.discord).toHaveBeenCalledTimes(2); }); - - it("does not import the whatsapp runtime boundary on deps module load", async () => { - await importFreshModule( - import.meta.url, - "./deps.js?scope=no-whatsapp-runtime-on-import", - ); - - expect(whatsappBoundaryLoads).not.toHaveBeenCalled(); - }); }); diff --git a/src/cli/send-runtime/discord.ts b/src/cli/send-runtime/discord.ts index 5c15549cfae..4452dc61e95 100644 --- a/src/cli/send-runtime/discord.ts +++ b/src/cli/send-runtime/discord.ts @@ -1,9 +1,7 @@ -import { sendMessageDiscord as sendMessageDiscordImpl } from "../../../extensions/discord/runtime-api.js"; +import { createPluginBoundaryRuntimeSend } from "./plugin-boundary-send.js"; -type RuntimeSend = { - sendMessage: typeof import("../../../extensions/discord/runtime-api.js").sendMessageDiscord; -}; - -export const runtimeSend = { - sendMessage: sendMessageDiscordImpl, -} satisfies RuntimeSend; +export const runtimeSend = createPluginBoundaryRuntimeSend({ + pluginId: "discord", + exportName: "sendMessageDiscord", + missingLabel: "Discord plugin runtime", +}); diff --git a/src/cli/send-runtime/plugin-boundary-send.ts b/src/cli/send-runtime/plugin-boundary-send.ts new file mode 100644 index 00000000000..8cd5fbc0b25 --- /dev/null +++ b/src/cli/send-runtime/plugin-boundary-send.ts @@ -0,0 +1,37 @@ +import { createCachedPluginBoundaryModuleLoader } from "../../plugins/runtime/runtime-plugin-boundary.js"; + +type RuntimeSendModule = Record; + +export type RuntimeSend = { + sendMessage: (...args: unknown[]) => Promise; +}; + +function resolveRuntimeExport( + module: RuntimeSendModule | null, + pluginId: string, + exportName: string, +): (...args: unknown[]) => Promise { + const candidate = module?.[exportName]; + if (typeof candidate !== "function") { + throw new Error(`${pluginId} plugin runtime is unavailable: missing export '${exportName}'`); + } + return candidate as (...args: unknown[]) => Promise; +} + +export function createPluginBoundaryRuntimeSend(params: { + pluginId: string; + exportName: string; + missingLabel: string; +}): RuntimeSend { + const loadRuntimeModuleSync = createCachedPluginBoundaryModuleLoader({ + pluginId: params.pluginId, + entryBaseName: "runtime-api", + required: true, + missingLabel: params.missingLabel, + }); + + return { + sendMessage: (...args) => + resolveRuntimeExport(loadRuntimeModuleSync(), params.pluginId, params.exportName)(...args), + }; +} diff --git a/src/cli/send-runtime/signal.ts b/src/cli/send-runtime/signal.ts index 35154a7aa92..4e20c47d8e6 100644 --- a/src/cli/send-runtime/signal.ts +++ b/src/cli/send-runtime/signal.ts @@ -1,9 +1,7 @@ -import { sendMessageSignal as sendMessageSignalImpl } from "../../../extensions/signal/runtime-api.js"; +import { createPluginBoundaryRuntimeSend } from "./plugin-boundary-send.js"; -type RuntimeSend = { - sendMessage: typeof import("../../../extensions/signal/runtime-api.js").sendMessageSignal; -}; - -export const runtimeSend = { - sendMessage: sendMessageSignalImpl, -} satisfies RuntimeSend; +export const runtimeSend = createPluginBoundaryRuntimeSend({ + pluginId: "signal", + exportName: "sendMessageSignal", + missingLabel: "Signal plugin runtime", +}); diff --git a/src/cli/send-runtime/slack.ts b/src/cli/send-runtime/slack.ts index e7d50aefe1f..fd531f2493c 100644 --- a/src/cli/send-runtime/slack.ts +++ b/src/cli/send-runtime/slack.ts @@ -1,9 +1,7 @@ -import { sendMessageSlack as sendMessageSlackImpl } from "../../../extensions/slack/runtime-api.js"; +import { createPluginBoundaryRuntimeSend } from "./plugin-boundary-send.js"; -type RuntimeSend = { - sendMessage: typeof import("../../../extensions/slack/runtime-api.js").sendMessageSlack; -}; - -export const runtimeSend = { - sendMessage: sendMessageSlackImpl, -} satisfies RuntimeSend; +export const runtimeSend = createPluginBoundaryRuntimeSend({ + pluginId: "slack", + exportName: "sendMessageSlack", + missingLabel: "Slack plugin runtime", +}); diff --git a/src/cli/send-runtime/whatsapp.ts b/src/cli/send-runtime/whatsapp.ts index 5dc56b9669f..6c27be2de69 100644 --- a/src/cli/send-runtime/whatsapp.ts +++ b/src/cli/send-runtime/whatsapp.ts @@ -1,9 +1,7 @@ -import { sendMessageWhatsApp as sendMessageWhatsAppImpl } from "../../plugins/runtime/runtime-web-channel-boundary.js"; +import { createPluginBoundaryRuntimeSend } from "./plugin-boundary-send.js"; -type RuntimeSend = { - sendMessage: typeof import("../../plugins/runtime/runtime-web-channel-boundary.js").sendMessageWhatsApp; -}; - -export const runtimeSend = { - sendMessage: sendMessageWhatsAppImpl, -} satisfies RuntimeSend; +export const runtimeSend = createPluginBoundaryRuntimeSend({ + pluginId: "whatsapp", + exportName: "sendMessageWhatsApp", + missingLabel: "WhatsApp plugin runtime", +}); diff --git a/src/commands/health.snapshot.test.ts b/src/commands/health.snapshot.test.ts index edc47ed13ef..9c026188030 100644 --- a/src/commands/health.snapshot.test.ts +++ b/src/commands/health.snapshot.test.ts @@ -41,7 +41,7 @@ async function loadFreshHealthModulesForTest() { recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined), updateLastRoute: vi.fn().mockResolvedValue(undefined), })); - vi.doMock("../plugins/runtime/runtime-web-channel-boundary.js", () => ({ + vi.doMock("../plugins/runtime/runtime-web-channel-plugin.js", () => ({ webAuthExists: vi.fn(async () => true), getWebAuthAgeMs: vi.fn(() => 1234), readWebSelfId: vi.fn(() => ({ e164: null, jid: null })), diff --git a/src/commands/status.test.ts b/src/commands/status.test.ts index 600c3d9be65..89c9c3bf220 100644 --- a/src/commands/status.test.ts +++ b/src/commands/status.test.ts @@ -383,7 +383,7 @@ vi.mock("../channels/plugins/index.js", () => ({ }, ] as unknown, })); -vi.mock("../plugins/runtime/runtime-web-channel-boundary.js", () => ({ +vi.mock("../plugins/runtime/runtime-web-channel-plugin.js", () => ({ webAuthExists: mocks.webAuthExists, getWebAuthAgeMs: mocks.getWebAuthAgeMs, readWebSelfId: mocks.readWebSelfId, diff --git a/src/config/channel-configured.ts b/src/config/channel-configured.ts index 53ef1051256..38d1088c7d5 100644 --- a/src/config/channel-configured.ts +++ b/src/config/channel-configured.ts @@ -1,5 +1,5 @@ -import { hasAnyWhatsAppAuth } from "../../extensions/whatsapp/auth-presence.js"; import { hasMeaningfulChannelConfig } from "../channels/config-presence.js"; +import { getChannelPlugin } from "../channels/plugins/index.js"; import { isRecord } from "../utils.js"; import type { OpenClawConfig } from "./config.js"; @@ -127,17 +127,6 @@ function isStructuredChannelConfigured( return hasMeaningfulChannelConfig(entry); } -function isWhatsAppConfigured(cfg: OpenClawConfig): boolean { - if (hasAnyWhatsAppAuth(cfg)) { - return true; - } - const entry = resolveChannelConfig(cfg, "whatsapp"); - if (!entry) { - return false; - } - return hasMeaningfulChannelConfig(entry); -} - function isGenericChannelConfigured(cfg: OpenClawConfig, channelId: string): boolean { const entry = resolveChannelConfig(cfg, channelId); return hasMeaningfulChannelConfig(entry); @@ -148,8 +137,12 @@ export function isChannelConfigured( channelId: string, env: NodeJS.ProcessEnv = process.env, ): boolean { - if (channelId === "whatsapp") { - return isWhatsAppConfigured(cfg); + const pluginConfigured = getChannelPlugin(channelId)?.config.hasPersistedAuthState?.({ + cfg, + env, + }); + if (pluginConfigured) { + return true; } const spec = STRUCTURED_CHANNEL_CONFIG_SPECS[channelId]; if (spec) { diff --git a/src/config/sessions/explicit-session-key-normalization.test.ts b/src/config/sessions/explicit-session-key-normalization.test.ts index b18ea322805..3cf32846337 100644 --- a/src/config/sessions/explicit-session-key-normalization.test.ts +++ b/src/config/sessions/explicit-session-key-normalization.test.ts @@ -1,5 +1,11 @@ -import { describe, expect, it } from "vitest"; +import { afterEach, beforeEach, describe, expect, it } from "vitest"; import type { MsgContext } from "../../auto-reply/templating.js"; +import type { ChannelPlugin } from "../../channels/plugins/types.js"; +import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../../plugins/runtime.js"; +import { + createChannelTestPluginBase, + createTestRegistry, +} from "../../test-utils/channel-plugins.js"; import { normalizeExplicitSessionKey } from "./explicit-session-key-normalization.js"; function makeCtx(overrides: Partial): MsgContext { @@ -11,6 +17,54 @@ function makeCtx(overrides: Partial): MsgContext { } as MsgContext; } +beforeEach(() => { + const discordPlugin: ChannelPlugin = { + ...createChannelTestPluginBase({ + id: "discord", + label: "Discord", + docsPath: "/channels/discord", + }), + messaging: { + normalizeExplicitSessionKey: ({ sessionKey, ctx }) => { + const normalizedChatType = ctx.ChatType?.trim().toLowerCase(); + let normalized = sessionKey.trim().toLowerCase(); + if (normalizedChatType !== "direct" && normalizedChatType !== "dm") { + return normalized; + } + normalized = normalized.replace(/^(discord:)dm:/, "$1direct:"); + normalized = normalized.replace(/^(agent:[^:]+:discord:)dm:/, "$1direct:"); + const match = normalized.match(/^((?:agent:[^:]+:)?)discord:channel:([^:]+)$/); + if (!match) { + return normalized; + } + const from = (ctx.From ?? "").trim().toLowerCase(); + const senderId = (ctx.SenderId ?? "").trim().toLowerCase(); + const fromDiscordId = + from.startsWith("discord:") && !from.includes(":channel:") && !from.includes(":group:") + ? from.slice("discord:".length) + : ""; + const directId = senderId || fromDiscordId; + return directId && directId === match[2] + ? `${match[1]}discord:direct:${match[2]}` + : normalized; + }, + }, + }; + setActivePluginRegistry( + createTestRegistry([ + { + pluginId: "discord", + plugin: discordPlugin, + source: "test", + }, + ]), + ); +}); + +afterEach(() => { + resetPluginRuntimeStateForTest(); +}); + describe("normalizeExplicitSessionKey", () => { it("dispatches discord keys through the provider normalizer", () => { expect( diff --git a/src/config/sessions/explicit-session-key-normalization.ts b/src/config/sessions/explicit-session-key-normalization.ts index 7b5e80c3a56..3ee37998477 100644 --- a/src/config/sessions/explicit-session-key-normalization.ts +++ b/src/config/sessions/explicit-session-key-normalization.ts @@ -1,50 +1,44 @@ -import { normalizeExplicitDiscordSessionKey } from "../../../extensions/discord/session-key-api.js"; import type { MsgContext } from "../../auto-reply/templating.js"; +import { getChannelPlugin, listChannelPlugins } from "../../channels/plugins/index.js"; +import { normalizeMessageChannel } from "../../utils/message-channel.js"; -type ExplicitSessionKeyNormalizer = (sessionKey: string, ctx: MsgContext) => string; -type ExplicitSessionKeyNormalizerEntry = { - provider: string; - normalize: ExplicitSessionKeyNormalizer; - matches: (params: { - sessionKey: string; - provider?: string; - surface?: string; - from: string; - }) => boolean; -}; - -const EXPLICIT_SESSION_KEY_NORMALIZERS: ExplicitSessionKeyNormalizerEntry[] = [ - { - provider: "discord", - normalize: normalizeExplicitDiscordSessionKey, - matches: ({ sessionKey, provider, surface, from }) => - surface === "discord" || - provider === "discord" || - from.startsWith("discord:") || - sessionKey.startsWith("discord:") || - sessionKey.includes(":discord:"), - }, -]; - -function resolveExplicitSessionKeyNormalizer( +function resolveExplicitSessionKeyNormalizerCandidates( sessionKey: string, ctx: Pick, -): ExplicitSessionKeyNormalizer | undefined { +): string[] { const normalizedProvider = ctx.Provider?.trim().toLowerCase(); const normalizedSurface = ctx.Surface?.trim().toLowerCase(); const normalizedFrom = (ctx.From ?? "").trim().toLowerCase(); - return EXPLICIT_SESSION_KEY_NORMALIZERS.find((entry) => - entry.matches({ - sessionKey, - provider: normalizedProvider, - surface: normalizedSurface, - from: normalizedFrom, - }), - )?.normalize; + const candidates = new Set(); + const maybeAdd = (value?: string | null) => { + const normalized = normalizeMessageChannel(value); + if (normalized) { + candidates.add(normalized); + } + }; + maybeAdd(normalizedSurface); + maybeAdd(normalizedProvider); + maybeAdd(normalizedFrom.split(":", 1)[0]); + for (const plugin of listChannelPlugins()) { + const pluginId = normalizeMessageChannel(plugin.id); + if (!pluginId) { + continue; + } + if (sessionKey.startsWith(`${pluginId}:`) || sessionKey.includes(`:${pluginId}:`)) { + candidates.add(pluginId); + } + } + return [...candidates]; } export function normalizeExplicitSessionKey(sessionKey: string, ctx: MsgContext): string { const normalized = sessionKey.trim().toLowerCase(); - const normalize = resolveExplicitSessionKeyNormalizer(normalized, ctx); - return normalize ? normalize(normalized, ctx) : normalized; + for (const channelId of resolveExplicitSessionKeyNormalizerCandidates(normalized, ctx)) { + const normalize = getChannelPlugin(channelId)?.messaging?.normalizeExplicitSessionKey; + const next = normalize?.({ sessionKey: normalized, ctx }); + if (typeof next === "string" && next.trim()) { + return next.trim().toLowerCase(); + } + } + return normalized; } diff --git a/src/config/sessions/session-key.test.ts b/src/config/sessions/session-key.test.ts index 3bf348d1b76..6f05552f6bc 100644 --- a/src/config/sessions/session-key.test.ts +++ b/src/config/sessions/session-key.test.ts @@ -1,5 +1,11 @@ -import { describe, expect, it } from "vitest"; +import { afterEach, beforeEach, describe, expect, it } from "vitest"; import type { MsgContext } from "../../auto-reply/templating.js"; +import type { ChannelPlugin } from "../../channels/plugins/types.js"; +import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../../plugins/runtime.js"; +import { + createChannelTestPluginBase, + createTestRegistry, +} from "../../test-utils/channel-plugins.js"; import { resolveSessionKey } from "./session-key.js"; function makeCtx(overrides: Partial): MsgContext { @@ -11,6 +17,54 @@ function makeCtx(overrides: Partial): MsgContext { } as MsgContext; } +beforeEach(() => { + const discordPlugin: ChannelPlugin = { + ...createChannelTestPluginBase({ + id: "discord", + label: "Discord", + docsPath: "/channels/discord", + }), + messaging: { + normalizeExplicitSessionKey: ({ sessionKey, ctx }) => { + const normalizedChatType = ctx.ChatType?.trim().toLowerCase(); + let normalized = sessionKey.trim().toLowerCase(); + if (normalizedChatType !== "direct" && normalizedChatType !== "dm") { + return normalized; + } + normalized = normalized.replace(/^(discord:)dm:/, "$1direct:"); + normalized = normalized.replace(/^(agent:[^:]+:discord:)dm:/, "$1direct:"); + const match = normalized.match(/^((?:agent:[^:]+:)?)discord:channel:([^:]+)$/); + if (!match) { + return normalized; + } + const from = (ctx.From ?? "").trim().toLowerCase(); + const senderId = (ctx.SenderId ?? "").trim().toLowerCase(); + const fromDiscordId = + from.startsWith("discord:") && !from.includes(":channel:") && !from.includes(":group:") + ? from.slice("discord:".length) + : ""; + const directId = senderId || fromDiscordId; + return directId && directId === match[2] + ? `${match[1]}discord:direct:${match[2]}` + : normalized; + }, + }, + }; + setActivePluginRegistry( + createTestRegistry([ + { + pluginId: "discord", + plugin: discordPlugin, + source: "test", + }, + ]), + ); +}); + +afterEach(() => { + resetPluginRuntimeStateForTest(); +}); + describe("resolveSessionKey", () => { describe("Discord DM session key normalization", () => { it("passes through correct discord:direct keys unchanged", () => { diff --git a/src/cron/isolated-agent/delivery-target.test.ts b/src/cron/isolated-agent/delivery-target.test.ts index 7ce795f2ba7..de353d9a419 100644 --- a/src/cron/isolated-agent/delivery-target.test.ts +++ b/src/cron/isolated-agent/delivery-target.test.ts @@ -4,10 +4,6 @@ import type { OpenClawConfig } from "../../config/config.js"; import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../../plugins/runtime.js"; import { createOutboundTestPlugin, createTestRegistry } from "../../test-utils/channel-plugins.js"; -const whatsappAccountMocks = vi.hoisted(() => ({ - resolveWhatsAppAccount: vi.fn<() => { allowFrom: string[] }>(() => ({ allowFrom: [] })), -})); - vi.mock("../../config/sessions.js", () => ({ loadSessionStore: vi.fn().mockReturnValue({}), resolveAgentMainSessionKey: vi.fn().mockReturnValue("agent:test:main"), @@ -28,16 +24,11 @@ vi.mock("../../pairing/pairing-store.js", () => ({ readChannelAllowFromStoreSync: vi.fn(() => []), })); -vi.mock("../../../extensions/whatsapp/api.js", () => ({ - resolveWhatsAppAccount: whatsappAccountMocks.resolveWhatsAppAccount, -})); - const mockedModuleIds = [ "../../config/sessions.js", "../../infra/outbound/channel-selection.js", "../../infra/outbound/target-resolver.js", "../../pairing/pairing-store.js", - "../../../extensions/whatsapp/api.js", ]; import { loadSessionStore } from "../../config/sessions.js"; @@ -65,6 +56,22 @@ function createStubOutbound(label: string): ChannelOutboundAdapter { }; } +function createAllowlistAwareStubOutbound(label: string): ChannelOutboundAdapter { + return { + deliveryMode: "gateway", + resolveTarget: ({ to, allowFrom }) => { + const trimmed = typeof to === "string" ? to.trim() : ""; + if (!trimmed) { + return { ok: false, error: new Error(`${label} requires target`) }; + } + if (allowFrom && allowFrom.length > 0 && !allowFrom.includes(trimmed)) { + return { ok: false, error: new Error(`${label} target blocked`) }; + } + return { ok: true, to: trimmed }; + }, + }; +} + beforeEach(() => { resetPluginRuntimeStateForTest(); setActivePluginRegistry( @@ -79,10 +86,18 @@ beforeEach(() => { }, { pluginId: "whatsapp", - plugin: createOutboundTestPlugin({ - id: "whatsapp", - outbound: createStubOutbound("WhatsApp"), - }), + plugin: { + ...createOutboundTestPlugin({ + id: "whatsapp", + outbound: createAllowlistAwareStubOutbound("WhatsApp"), + }), + config: { + listAccountIds: () => [], + resolveAccount: () => ({}), + resolveAllowFrom: ({ cfg }: { cfg: OpenClawConfig }) => + (cfg.channels?.whatsapp as { allowFrom?: string[] } | undefined)?.allowFrom, + }, + }, source: "test", }, ]), @@ -142,10 +157,6 @@ function setLastSessionEntry(params: { }); } -function setWhatsAppAllowFrom(allowFrom: string[]) { - vi.mocked(whatsappAccountMocks.resolveWhatsAppAccount).mockReturnValue({ allowFrom }); -} - function setStoredWhatsAppAllowFrom(allowFrom: string[]) { vi.mocked(readChannelAllowFromStoreSync).mockReturnValue(allowFrom); } @@ -176,10 +187,9 @@ describe("resolveDeliveryTarget", () => { lastChannel: "whatsapp", lastTo: "+15550000099", }); - setWhatsAppAllowFrom([]); setStoredWhatsAppAllowFrom(["+15550000001"]); - const cfg = makeCfg({ bindings: [] }); + const cfg = makeCfg({ bindings: [], channels: { whatsapp: { allowFrom: [] } } }); const result = await resolveLastTarget(cfg); expect(result.channel).toBe("whatsapp"); @@ -192,10 +202,9 @@ describe("resolveDeliveryTarget", () => { lastChannel: "whatsapp", lastTo: "+15550000099", }); - setWhatsAppAllowFrom([]); setStoredWhatsAppAllowFrom(["+15550000001"]); - const cfg = makeCfg({ bindings: [] }); + const cfg = makeCfg({ bindings: [], channels: { whatsapp: { allowFrom: [] } } }); const result = await resolveDeliveryTarget(cfg, AGENT_ID, { channel: "whatsapp", to: "+15550000099", diff --git a/src/cron/isolated-agent/delivery-target.ts b/src/cron/isolated-agent/delivery-target.ts index 78d272f9b25..ab8b32167a4 100644 --- a/src/cron/isolated-agent/delivery-target.ts +++ b/src/cron/isolated-agent/delivery-target.ts @@ -1,5 +1,4 @@ -import { resolveWhatsAppAccount } from "../../../extensions/whatsapp/api.js"; -import { normalizeWhatsAppTarget } from "../../channels/plugins/normalize/whatsapp.js"; +import { getChannelPlugin } from "../../channels/plugins/index.js"; import type { ChannelId } from "../../channels/plugins/types.js"; import type { OpenClawConfig } from "../../config/config.js"; import { @@ -15,6 +14,7 @@ import { resolveSessionDeliveryTarget, } from "../../infra/outbound/targets.js"; import { readChannelAllowFromStoreSync } from "../../pairing/pairing-store.js"; +import { mapAllowFromEntries } from "../../plugin-sdk/channel-config-helpers.js"; import { buildChannelAccountBindings } from "../../routing/bindings.js"; import { normalizeAccountId, normalizeAgentId } from "../../routing/session-key.js"; @@ -152,26 +152,32 @@ export async function resolveDeliveryTarget( }; } - let allowFromOverride: string[] | undefined; - if (channel === "whatsapp") { - const resolvedAccountId = normalizeAccountId(accountId); - const configuredAllowFromRaw = - resolveWhatsAppAccount({ cfg, accountId: resolvedAccountId }).allowFrom ?? []; - const configuredAllowFrom = configuredAllowFromRaw - .map((entry) => String(entry).trim()) - .filter((entry) => entry && entry !== "*") - .map((entry) => normalizeWhatsAppTarget(entry)) - .filter((entry): entry is string => Boolean(entry)); - const storeAllowFrom = readChannelAllowFromStoreSync("whatsapp", process.env, resolvedAccountId) - .map((entry) => normalizeWhatsAppTarget(entry)) - .filter((entry): entry is string => Boolean(entry)); - allowFromOverride = [...new Set([...configuredAllowFrom, ...storeAllowFrom])]; + const channelPlugin = getChannelPlugin(channel); + const resolvedAccountId = normalizeAccountId(accountId); + const configuredAllowFromRaw = channelPlugin?.config.resolveAllowFrom?.({ + cfg, + accountId: resolvedAccountId, + }); + const configuredAllowFrom = configuredAllowFromRaw + ? mapAllowFromEntries(configuredAllowFromRaw) + : []; + const storeAllowFrom = mapAllowFromEntries( + readChannelAllowFromStoreSync(channel, process.env, resolvedAccountId), + ); + const allowFromOverride = [...new Set([...configuredAllowFrom, ...storeAllowFrom])]; + const effectiveAllowFrom = mode === "implicit" ? allowFromOverride : undefined; - if (toCandidate && mode === "implicit" && allowFromOverride.length > 0) { - const normalizedCurrentTarget = normalizeWhatsAppTarget(toCandidate); - if (!normalizedCurrentTarget || !allowFromOverride.includes(normalizedCurrentTarget)) { - toCandidate = allowFromOverride[0]; - } + if (toCandidate && mode === "implicit" && allowFromOverride.length > 0) { + const currentTargetResolution = resolveOutboundTarget({ + channel, + to: toCandidate, + cfg, + accountId, + mode, + allowFrom: effectiveAllowFrom, + }); + if (!currentTargetResolution.ok) { + toCandidate = allowFromOverride[0]; } } @@ -181,7 +187,7 @@ export async function resolveDeliveryTarget( cfg, accountId, mode, - allowFrom: allowFromOverride, + allowFrom: effectiveAllowFrom, }); if (!docked.ok) { return { diff --git a/src/gateway/server-http.ts b/src/gateway/server-http.ts index a91c415596e..c329047f854 100644 --- a/src/gateway/server-http.ts +++ b/src/gateway/server-http.ts @@ -8,7 +8,6 @@ import { import { createServer as createHttpsServer } from "node:https"; import type { TlsOptions } from "node:tls"; import type { WebSocketServer } from "ws"; -import { handleSlackHttpRequest } from "../../extensions/slack/api.js"; import { resolveAgentAvatar } from "../agents/identity-avatar.js"; import { CANVAS_WS_PATH, handleA2uiHttpRequest } from "../canvas-host/a2ui.js"; import type { CanvasHostHandler } from "../canvas-host/server.js"; @@ -325,9 +324,8 @@ export async function runGatewayHttpRequestStages( } catch (err) { // Log and skip the failing stage so subsequent stages (control-ui, // gateway-probes, etc.) remain reachable. A common trigger is a - // bundled-plugin facade that fails to load because an optional - // dependency is missing (e.g. @slack/bolt after the lazy-facade - // refactor). + // plugin-owned route/runtime code can still fail to load when an + // optional dependency is missing. Keep later stages reachable. console.error(`[gateway-http] stage "${stage.name}" threw — skipping:`, err); } } @@ -898,10 +896,6 @@ export function createGatewayHttpServer(opts: { rateLimiter, }), }, - { - name: "slack", - run: () => handleSlackHttpRequest(req, res), - }, ]; if (openResponsesEnabled) { requestStages.push({ diff --git a/src/gateway/server.sessions.gateway-server-sessions-a.test.ts b/src/gateway/server.sessions.gateway-server-sessions-a.test.ts index 6a74af97cc0..c651bf2bfa9 100644 --- a/src/gateway/server.sessions.gateway-server-sessions-a.test.ts +++ b/src/gateway/server.sessions.gateway-server-sessions-a.test.ts @@ -142,21 +142,16 @@ vi.mock("../plugins/hook-runner-global.js", async (importOriginal) => { }; }); -vi.mock("../plugins/runtime/runtime-discord.js", async (importOriginal) => { - const actual = await importOriginal(); +vi.mock("../infra/outbound/session-binding-service.js", async (importOriginal) => { + const actual = + await importOriginal(); return { ...actual, - createRuntimeDiscord: () => { - const runtime = actual.createRuntimeDiscord(); - return { - ...runtime, - threadBindings: { - ...runtime.threadBindings, - unbindBySessionKey: (params: unknown) => - threadBindingMocks.unbindThreadBindingsBySessionKey(params), - }, - }; - }, + getSessionBindingService: () => ({ + ...actual.getSessionBindingService(), + unbind: async (params: unknown) => + threadBindingMocks.unbindThreadBindingsBySessionKey(params), + }), }; }); @@ -1862,9 +1857,7 @@ describe("gateway server sessions", () => { expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledTimes(1); expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledWith({ targetSessionKey: "agent:main:discord:group:dev", - targetKind: "acp", reason: "session-delete", - sendFarewell: true, }); ws.close(); @@ -2022,9 +2015,7 @@ describe("gateway server sessions", () => { expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledTimes(1); expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledWith({ targetSessionKey: "agent:main:subagent:worker", - targetKind: "subagent", reason: "session-delete", - sendFarewell: true, }); ws.close(); @@ -2053,9 +2044,7 @@ describe("gateway server sessions", () => { expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledTimes(1); expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledWith({ targetSessionKey: "agent:main:subagent:worker", - targetKind: "subagent", reason: "session-delete", - sendFarewell: true, }); ws.close(); @@ -2083,9 +2072,7 @@ describe("gateway server sessions", () => { expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledTimes(1); expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledWith({ targetSessionKey: "agent:main:subagent:worker", - targetKind: "subagent", reason: "session-delete", - sendFarewell: true, }); ws.close(); @@ -2140,9 +2127,7 @@ describe("gateway server sessions", () => { expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledTimes(1); expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledWith({ targetSessionKey: "agent:main:main", - targetKind: "acp", reason: "session-reset", - sendFarewell: true, }); ws.close(); @@ -2308,9 +2293,7 @@ describe("gateway server sessions", () => { expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledTimes(1); expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledWith({ targetSessionKey: "agent:main:subagent:worker", - targetKind: "subagent", reason: "session-reset", - sendFarewell: true, }); ws.close(); @@ -2338,9 +2321,7 @@ describe("gateway server sessions", () => { expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledTimes(1); expect(threadBindingMocks.unbindThreadBindingsBySessionKey).toHaveBeenCalledWith({ targetSessionKey: "agent:main:main", - targetKind: "acp", reason: "session-reset", - sendFarewell: true, }); ws.close(); diff --git a/src/gateway/session-reset-service.ts b/src/gateway/session-reset-service.ts index 1970ccf92b2..93e5f61e451 100644 --- a/src/gateway/session-reset-service.ts +++ b/src/gateway/session-reset-service.ts @@ -21,9 +21,9 @@ import { import { resolveSessionFilePath, resolveSessionFilePathOptions } from "../config/sessions/paths.js"; import { logVerbose } from "../globals.js"; import { createInternalHookEvent, triggerInternalHook } from "../hooks/internal-hooks.js"; +import { getSessionBindingService } from "../infra/outbound/session-binding-service.js"; import { closeTrackedBrowserTabsForSessions } from "../plugin-sdk/browser-maintenance.js"; import { getGlobalHookRunner } from "../plugins/hook-runner-global.js"; -import { createPluginRuntime } from "../plugins/runtime/index.js"; import { isSubagentSessionKey, normalizeAgentId, @@ -44,12 +44,6 @@ import { } from "./session-utils.js"; const ACP_RUNTIME_CLEANUP_TIMEOUT_MS = 15_000; -let cachedChannelRuntime: ReturnType["channel"] | undefined; - -function getChannelRuntime() { - cachedChannelRuntime ??= createPluginRuntime().channel; - return cachedChannelRuntime; -} function stripRuntimeModelState(entry?: SessionEntry): SessionEntry | undefined { if (!entry) { @@ -164,12 +158,9 @@ export async function emitSessionUnboundLifecycleEvent(params: { emitHooks?: boolean; }) { const targetKind = isSubagentSessionKey(params.targetSessionKey) ? "subagent" : "acp"; - const channelRuntime = getChannelRuntime(); - channelRuntime.discord.threadBindings.unbindBySessionKey({ + await getSessionBindingService().unbind({ targetSessionKey: params.targetSessionKey, - targetKind, reason: params.reason, - sendFarewell: true, }); if (params.emitHooks === false) { diff --git a/src/gateway/test-helpers.mocks.ts b/src/gateway/test-helpers.mocks.ts index 8495357a9ed..cdfdba15dd9 100644 --- a/src/gateway/test-helpers.mocks.ts +++ b/src/gateway/test-helpers.mocks.ts @@ -821,12 +821,12 @@ vi.mock("../plugins/loader.js", async () => { loadOpenClawPlugins: () => pluginRegistryState.registry, }; }); -vi.mock("../plugins/runtime/runtime-web-channel-boundary.js", () => ({ - sendMessageWhatsApp: (...args: unknown[]) => +vi.mock("../plugins/runtime/runtime-web-channel-plugin.js", () => ({ + sendWebChannelMessage: (...args: unknown[]) => (hoisted.sendWhatsAppMock as (...args: unknown[]) => unknown)(...args), })); -vi.mock("/src/plugins/runtime/runtime-web-channel-boundary.js", () => ({ - sendMessageWhatsApp: (...args: unknown[]) => +vi.mock("/src/plugins/runtime/runtime-web-channel-plugin.js", () => ({ + sendWebChannelMessage: (...args: unknown[]) => (hoisted.sendWhatsAppMock as (...args: unknown[]) => unknown)(...args), })); diff --git a/src/generated/plugin-sdk-facade-type-map.generated.ts b/src/generated/plugin-sdk-facade-type-map.generated.ts index 60ba98e0ebd..5c1ec7eaf87 100644 --- a/src/generated/plugin-sdk-facade-type-map.generated.ts +++ b/src/generated/plugin-sdk-facade-type-map.generated.ts @@ -18,75 +18,6 @@ export interface PluginSdkFacadeTypeMap { }; types: {}; }; - "discord-account": { - module: typeof import("@openclaw/discord/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/discord/api.js"); - }; - }; - types: { - ResolvedDiscordAccount: import("@openclaw/discord/api.js").ResolvedDiscordAccount; - }; - }; - "discord-runtime-surface": { - module: typeof import("@openclaw/discord/runtime-api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/discord/runtime-api.js"); - }; - }; - types: {}; - }; - "discord-session-key": { - module: typeof import("@openclaw/discord/session-key-api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/discord/session-key-api.js"); - }; - }; - types: {}; - }; - "discord-surface": { - module: typeof import("@openclaw/discord/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/discord/api.js"); - }; - }; - types: { - DiscordComponentMessageSpec: import("@openclaw/discord/api.js").DiscordComponentMessageSpec; - DiscordProbe: import("@openclaw/discord/api.js").DiscordProbe; - DiscordSendComponents: import("@openclaw/discord/api.js").DiscordSendComponents; - DiscordSendEmbeds: import("@openclaw/discord/api.js").DiscordSendEmbeds; - DiscordSendResult: import("@openclaw/discord/api.js").DiscordSendResult; - DiscordTokenResolution: import("@openclaw/discord/api.js").DiscordTokenResolution; - InspectedDiscordAccount: import("@openclaw/discord/api.js").InspectedDiscordAccount; - ResolvedDiscordAccount: import("@openclaw/discord/api.js").ResolvedDiscordAccount; - }; - }; - "discord-thread-bindings": { - module: typeof import("@openclaw/discord/runtime-api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/discord/runtime-api.js"); - }; - }; - types: { - ThreadBindingManager: import("@openclaw/discord/runtime-api.js").ThreadBindingManager; - ThreadBindingRecord: import("@openclaw/discord/runtime-api.js").ThreadBindingRecord; - ThreadBindingTargetKind: import("@openclaw/discord/runtime-api.js").ThreadBindingTargetKind; - }; - }; - "discord-timeouts": { - module: typeof import("@openclaw/discord/timeouts.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/discord/timeouts.js"); - }; - }; - types: {}; - }; "anthropic-cli": { module: typeof import("@openclaw/anthropic/api.js"); sourceModules: { @@ -510,30 +441,6 @@ export interface PluginSdkFacadeTypeMap { }; types: {}; }; - "signal-account": { - module: typeof import("@openclaw/signal/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/signal/api.js"); - }; - }; - types: { - ResolvedSignalAccount: import("@openclaw/signal/api.js").ResolvedSignalAccount; - }; - }; - "signal-surface": { - module: typeof import("@openclaw/signal/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/signal/api.js"); - }; - }; - types: { - ResolvedSignalAccount: import("@openclaw/signal/api.js").ResolvedSignalAccount; - SignalProbe: import("@openclaw/signal/api.js").SignalProbe; - SignalSender: import("@openclaw/signal/api.js").SignalSender; - }; - }; "provider-reasoning": { module: typeof import("@openclaw/ollama/api.js"); sourceModules: { @@ -578,50 +485,6 @@ export interface PluginSdkFacadeTypeMap { }; types: {}; }; - "slack-target-parser": { - module: typeof import("@openclaw/slack/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/slack/api.js"); - }; - }; - types: {}; - }; - "slack-account": { - module: typeof import("@openclaw/slack/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/slack/api.js"); - }; - }; - types: { - ResolvedSlackAccount: import("@openclaw/slack/api.js").ResolvedSlackAccount; - }; - }; - "slack-runtime-surface": { - module: typeof import("@openclaw/slack/runtime-api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/slack/runtime-api.js"); - }; - }; - types: { - SlackActionContext: import("@openclaw/slack/runtime-api.js").SlackActionContext; - }; - }; - "slack-surface": { - module: typeof import("@openclaw/slack/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/slack/api.js"); - }; - }; - types: { - InspectedSlackAccount: import("@openclaw/slack/api.js").InspectedSlackAccount; - ResolvedSlackAccount: import("@openclaw/slack/api.js").ResolvedSlackAccount; - SlackProbe: import("@openclaw/slack/api.js").SlackProbe; - }; - }; together: { module: typeof import("@openclaw/together/api.js"); sourceModules: { @@ -640,44 +503,6 @@ export interface PluginSdkFacadeTypeMap { }; types: {}; }; - "telegram-account": { - module: typeof import("@openclaw/telegram/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/telegram/api.js"); - }; - }; - types: { - ResolvedTelegramAccount: import("@openclaw/telegram/api.js").ResolvedTelegramAccount; - }; - }; - "telegram-allow-from": { - module: typeof import("@openclaw/telegram/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/telegram/api.js"); - }; - }; - types: {}; - }; - "telegram-surface": { - module: typeof import("@openclaw/telegram/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/telegram/api.js"); - }; - }; - types: { - InspectedTelegramAccount: import("@openclaw/telegram/api.js").InspectedTelegramAccount; - ProviderInfo: import("@openclaw/telegram/api.js").ProviderInfo; - ResolvedTelegramAccount: import("@openclaw/telegram/api.js").ResolvedTelegramAccount; - StickerMetadata: import("@openclaw/telegram/api.js").StickerMetadata; - TelegramButtonStyle: import("@openclaw/telegram/api.js").TelegramButtonStyle; - TelegramInlineButtons: import("@openclaw/telegram/api.js").TelegramInlineButtons; - TelegramProbe: import("@openclaw/telegram/api.js").TelegramProbe; - TelegramTokenResolution: import("@openclaw/telegram/api.js").TelegramTokenResolution; - }; - }; "vercel-ai-gateway": { module: typeof import("@openclaw/vercel-ai-gateway/api.js"); sourceModules: { @@ -732,32 +557,6 @@ export interface PluginSdkFacadeTypeMap { }; types: {}; }; - "whatsapp-targets": { - module: typeof import("@openclaw/whatsapp/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/whatsapp/api.js"); - }; - }; - types: {}; - }; - "whatsapp-surface": { - module: typeof import("@openclaw/whatsapp/api.js"); - sourceModules: { - source1: { - module: typeof import("@openclaw/whatsapp/api.js"); - }; - source2: { - module: typeof import("@openclaw/whatsapp/constants.js"); - }; - }; - types: { - WebChannelStatus: import("@openclaw/whatsapp/api.js").WebChannelStatus; - WebInboundMessage: import("@openclaw/whatsapp/api.js").WebInboundMessage; - WebListenerCloseReason: import("@openclaw/whatsapp/api.js").WebListenerCloseReason; - WebMonitorTuning: import("@openclaw/whatsapp/api.js").WebMonitorTuning; - }; - }; "zalo-setup": { module: typeof import("@openclaw/zalo/api.js"); sourceModules: { diff --git a/src/infra/tsdown-config.test.ts b/src/infra/tsdown-config.test.ts index f9a49322e1f..54645c7a3e1 100644 --- a/src/infra/tsdown-config.test.ts +++ b/src/infra/tsdown-config.test.ts @@ -47,7 +47,6 @@ describe("tsdown config", () => { "index", "commands/status.summary.runtime", "plugins/provider-runtime.runtime", - "plugins/runtime/runtime-line.contract", "plugins/runtime/index", "plugin-sdk/compat", "plugin-sdk/index", diff --git a/src/library.test.ts b/src/library.test.ts index 68699febe9a..5aeca9413e9 100644 --- a/src/library.test.ts +++ b/src/library.test.ts @@ -10,7 +10,7 @@ const lazyRuntimeSpecifiers = [ "./cli/prompt.js", "./infra/binaries.js", "./process/exec.js", - "./plugins/runtime/runtime-web-channel-boundary.js", + "./plugins/runtime/runtime-web-channel-plugin.js", ] as const; function readLibraryModuleImports() { diff --git a/src/library.ts b/src/library.ts index b5aaf43353f..bbade80b080 100644 --- a/src/library.ts +++ b/src/library.ts @@ -14,7 +14,7 @@ import { handlePortError, PortInUseError, } from "./infra/ports.js"; -import type { monitorWebChannel as monitorWebChannelRuntime } from "./plugins/runtime/runtime-web-channel-boundary.js"; +import type { monitorWebChannel as monitorWebChannelRuntime } from "./plugins/runtime/runtime-web-channel-plugin.js"; import type { runCommandWithTimeout as runCommandWithTimeoutRuntime, runExec as runExecRuntime, @@ -32,8 +32,8 @@ let replyRuntimePromise: Promise let promptRuntimePromise: Promise | null = null; let binariesRuntimePromise: Promise | null = null; let execRuntimePromise: Promise | null = null; -let whatsappRuntimePromise: Promise< - typeof import("./plugins/runtime/runtime-web-channel-boundary.js") +let webChannelRuntimePromise: Promise< + typeof import("./plugins/runtime/runtime-web-channel-plugin.js") > | null = null; function loadReplyRuntime() { @@ -56,9 +56,9 @@ function loadExecRuntime() { return execRuntimePromise; } -function loadWhatsAppRuntime() { - whatsappRuntimePromise ??= import("./plugins/runtime/runtime-web-channel-boundary.js"); - return whatsappRuntimePromise; +function loadWebChannelRuntime() { + webChannelRuntimePromise ??= import("./plugins/runtime/runtime-web-channel-plugin.js"); + return webChannelRuntimePromise; } export const getReplyFromConfig: GetReplyFromConfig = async (...args) => @@ -71,7 +71,7 @@ export const runExec: RunExec = async (...args) => (await loadExecRuntime()).run export const runCommandWithTimeout: RunCommandWithTimeout = async (...args) => (await loadExecRuntime()).runCommandWithTimeout(...args); export const monitorWebChannel: MonitorWebChannel = async (...args) => - (await loadWhatsAppRuntime()).monitorWebChannel(...args); + (await loadWebChannelRuntime()).monitorWebChannel(...args); export { assertWebChannel, diff --git a/src/plugin-activation-boundary.test.ts b/src/plugin-activation-boundary.test.ts index d568ecea38a..62e9c52bc77 100644 --- a/src/plugin-activation-boundary.test.ts +++ b/src/plugin-activation-boundary.test.ts @@ -45,12 +45,6 @@ describe("plugin activation boundary", () => { }> | undefined; let browserAmbientImportsPromise: Promise | undefined; - let discordMaintenancePromise: - | Promise<{ - unbindThreadBindingsBySessionKey: typeof import("./plugin-sdk/discord-maintenance.js").unbindThreadBindingsBySessionKey; - }> - | undefined; - function importAmbientModules() { ambientImportsPromise ??= Promise.all([ import("./agents/cli-session.js"), @@ -110,13 +104,6 @@ describe("plugin activation boundary", () => { return browserAmbientImportsPromise; } - function importDiscordMaintenance() { - discordMaintenancePromise ??= import("./plugin-sdk/discord-maintenance.js").then((module) => ({ - unbindThreadBindingsBySessionKey: module.unbindThreadBindingsBySessionKey, - })); - return discordMaintenancePromise; - } - it("does not load bundled provider plugins on ambient command imports", async () => { await importAmbientModules(); @@ -187,17 +174,16 @@ describe("plugin activation boundary", () => { expect(loadBundledPluginPublicSurfaceModuleSync).not.toHaveBeenCalled(); }); - it("keeps discord cleanup helpers cold when discord is disabled", async () => { - const discord = await importDiscordMaintenance(); + it("keeps generic session-binding cleanup helpers cold when plugins are disabled", async () => { + const { getSessionBindingService } = + await import("./infra/outbound/session-binding-service.js"); - expect( - discord.unbindThreadBindingsBySessionKey({ + await expect( + getSessionBindingService().unbind({ targetSessionKey: "agent:main:test", - targetKind: "acp", reason: "session-reset", - sendFarewell: true, }), - ).toEqual([]); + ).resolves.toEqual([]); expect(loadBundledPluginPublicSurfaceModuleSync).not.toHaveBeenCalled(); }); diff --git a/src/plugin-sdk/approval-delivery-helpers.ts b/src/plugin-sdk/approval-delivery-helpers.ts index e317227c88a..29ec7ea9cd7 100644 --- a/src/plugin-sdk/approval-delivery-helpers.ts +++ b/src/plugin-sdk/approval-delivery-helpers.ts @@ -169,11 +169,13 @@ export function createApproverRestrictedNativeApprovalAdapter( export function createChannelApprovalCapability(params: { authorizeActorAction?: ChannelApprovalCapability["authorizeActorAction"]; getActionAvailabilityState?: ChannelApprovalCapability["getActionAvailabilityState"]; + resolveApproveCommandBehavior?: ChannelApprovalCapability["resolveApproveCommandBehavior"]; approvals?: Pick; }): ChannelApprovalCapability { return { authorizeActorAction: params.authorizeActorAction, getActionAvailabilityState: params.getActionAvailabilityState, + resolveApproveCommandBehavior: params.resolveApproveCommandBehavior, delivery: params.approvals?.delivery, render: params.approvals?.render, native: params.approvals?.native, @@ -184,6 +186,7 @@ export function splitChannelApprovalCapability(capability: ChannelApprovalCapabi auth: { authorizeActorAction?: ChannelApprovalCapability["authorizeActorAction"]; getActionAvailabilityState?: ChannelApprovalCapability["getActionAvailabilityState"]; + resolveApproveCommandBehavior?: ChannelApprovalCapability["resolveApproveCommandBehavior"]; }; delivery: ChannelApprovalCapability["delivery"]; render: ChannelApprovalCapability["render"]; @@ -193,6 +196,7 @@ export function splitChannelApprovalCapability(capability: ChannelApprovalCapabi auth: { authorizeActorAction: capability.authorizeActorAction, getActionAvailabilityState: capability.getActionAvailabilityState, + resolveApproveCommandBehavior: capability.resolveApproveCommandBehavior, }, delivery: capability.delivery, render: capability.render, diff --git a/src/plugin-sdk/discord-maintenance.ts b/src/plugin-sdk/discord-maintenance.ts deleted file mode 100644 index e5085fff0f2..00000000000 --- a/src/plugin-sdk/discord-maintenance.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { tryLoadActivatedBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; - -type DiscordThreadBindingsModule = typeof import("../../extensions/discord/runtime-api.js"); - -export const unbindThreadBindingsBySessionKey: DiscordThreadBindingsModule["unbindThreadBindingsBySessionKey"] = - ((...args) => { - // Session cleanup always attempts Discord thread unbinds, even when Discord is disabled. - // Keep that path a no-op unless the Discord runtime is actually active. - const unbindThreadBindings = tryLoadActivatedBundledPluginPublicSurfaceModuleSync< - Pick - >({ - dirName: "discord", - artifactBasename: "runtime-api.js", - })?.unbindThreadBindingsBySessionKey; - return typeof unbindThreadBindings === "function" ? unbindThreadBindings(...args) : []; - }) as DiscordThreadBindingsModule["unbindThreadBindingsBySessionKey"]; diff --git a/src/plugin-sdk/discord-runtime-surface.ts b/src/plugin-sdk/discord-runtime-surface.ts deleted file mode 100644 index 76bcf501d93..00000000000 --- a/src/plugin-sdk/discord-runtime-surface.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { - createLazyFacadeObjectValue, - loadBundledPluginPublicSurfaceModuleSync, -} from "./facade-runtime.js"; - -type DiscordRuntimeModule = typeof import("../../extensions/discord/runtime-api.js"); - -type DiscordRuntimeSurface = Pick< - DiscordRuntimeModule, - | "auditDiscordChannelPermissions" - | "createThreadDiscord" - | "deleteMessageDiscord" - | "discordMessageActions" - | "editChannelDiscord" - | "editMessageDiscord" - | "getThreadBindingManager" - | "listDiscordDirectoryGroupsLive" - | "listDiscordDirectoryPeersLive" - | "monitorDiscordProvider" - | "pinMessageDiscord" - | "probeDiscord" - | "resolveDiscordChannelAllowlist" - | "resolveDiscordUserAllowlist" - | "resolveThreadBindingIdleTimeoutMs" - | "resolveThreadBindingInactivityExpiresAt" - | "resolveThreadBindingMaxAgeExpiresAt" - | "resolveThreadBindingMaxAgeMs" - | "sendDiscordComponentMessage" - | "sendMessageDiscord" - | "sendPollDiscord" - | "sendTypingDiscord" - | "setThreadBindingIdleTimeoutBySessionKey" - | "setThreadBindingMaxAgeBySessionKey" - | "unbindThreadBindingsBySessionKey" - | "unpinMessageDiscord" ->; - -function loadDiscordRuntimeSurface(): DiscordRuntimeSurface { - return loadBundledPluginPublicSurfaceModuleSync({ - dirName: "discord", - artifactBasename: "runtime-api.js", - }); -} - -export const discordMessageActions: DiscordRuntimeModule["discordMessageActions"] = - createLazyFacadeObjectValue(() => loadDiscordRuntimeSurface().discordMessageActions); - -export const auditDiscordChannelPermissions: DiscordRuntimeModule["auditDiscordChannelPermissions"] = - ((...args) => - loadDiscordRuntimeSurface().auditDiscordChannelPermissions( - ...args, - )) as DiscordRuntimeModule["auditDiscordChannelPermissions"]; - -export const createThreadDiscord: DiscordRuntimeModule["createThreadDiscord"] = ((...args) => - loadDiscordRuntimeSurface().createThreadDiscord( - ...args, - )) as DiscordRuntimeModule["createThreadDiscord"]; - -export const deleteMessageDiscord: DiscordRuntimeModule["deleteMessageDiscord"] = ((...args) => - loadDiscordRuntimeSurface().deleteMessageDiscord( - ...args, - )) as DiscordRuntimeModule["deleteMessageDiscord"]; - -export const editChannelDiscord: DiscordRuntimeModule["editChannelDiscord"] = ((...args) => - loadDiscordRuntimeSurface().editChannelDiscord( - ...args, - )) as DiscordRuntimeModule["editChannelDiscord"]; - -export const editMessageDiscord: DiscordRuntimeModule["editMessageDiscord"] = ((...args) => - loadDiscordRuntimeSurface().editMessageDiscord( - ...args, - )) as DiscordRuntimeModule["editMessageDiscord"]; - -export const getThreadBindingManager: DiscordRuntimeModule["getThreadBindingManager"] = (( - ...args -) => - loadDiscordRuntimeSurface().getThreadBindingManager( - ...args, - )) as DiscordRuntimeModule["getThreadBindingManager"]; - -export const listDiscordDirectoryGroupsLive: DiscordRuntimeModule["listDiscordDirectoryGroupsLive"] = - ((...args) => - loadDiscordRuntimeSurface().listDiscordDirectoryGroupsLive( - ...args, - )) as DiscordRuntimeModule["listDiscordDirectoryGroupsLive"]; - -export const listDiscordDirectoryPeersLive: DiscordRuntimeModule["listDiscordDirectoryPeersLive"] = - ((...args) => - loadDiscordRuntimeSurface().listDiscordDirectoryPeersLive( - ...args, - )) as DiscordRuntimeModule["listDiscordDirectoryPeersLive"]; - -export const monitorDiscordProvider: DiscordRuntimeModule["monitorDiscordProvider"] = ((...args) => - loadDiscordRuntimeSurface().monitorDiscordProvider( - ...args, - )) as DiscordRuntimeModule["monitorDiscordProvider"]; - -export const pinMessageDiscord: DiscordRuntimeModule["pinMessageDiscord"] = ((...args) => - loadDiscordRuntimeSurface().pinMessageDiscord( - ...args, - )) as DiscordRuntimeModule["pinMessageDiscord"]; - -export const probeDiscord: DiscordRuntimeModule["probeDiscord"] = ((...args) => - loadDiscordRuntimeSurface().probeDiscord(...args)) as DiscordRuntimeModule["probeDiscord"]; - -export const resolveDiscordChannelAllowlist: DiscordRuntimeModule["resolveDiscordChannelAllowlist"] = - ((...args) => - loadDiscordRuntimeSurface().resolveDiscordChannelAllowlist( - ...args, - )) as DiscordRuntimeModule["resolveDiscordChannelAllowlist"]; - -export const resolveDiscordUserAllowlist: DiscordRuntimeModule["resolveDiscordUserAllowlist"] = (( - ...args -) => - loadDiscordRuntimeSurface().resolveDiscordUserAllowlist( - ...args, - )) as DiscordRuntimeModule["resolveDiscordUserAllowlist"]; - -export const resolveThreadBindingIdleTimeoutMs: DiscordRuntimeModule["resolveThreadBindingIdleTimeoutMs"] = - ((...args) => - loadDiscordRuntimeSurface().resolveThreadBindingIdleTimeoutMs( - ...args, - )) as DiscordRuntimeModule["resolveThreadBindingIdleTimeoutMs"]; - -export const resolveThreadBindingInactivityExpiresAt: DiscordRuntimeModule["resolveThreadBindingInactivityExpiresAt"] = - ((...args) => - loadDiscordRuntimeSurface().resolveThreadBindingInactivityExpiresAt( - ...args, - )) as DiscordRuntimeModule["resolveThreadBindingInactivityExpiresAt"]; - -export const resolveThreadBindingMaxAgeExpiresAt: DiscordRuntimeModule["resolveThreadBindingMaxAgeExpiresAt"] = - ((...args) => - loadDiscordRuntimeSurface().resolveThreadBindingMaxAgeExpiresAt( - ...args, - )) as DiscordRuntimeModule["resolveThreadBindingMaxAgeExpiresAt"]; - -export const resolveThreadBindingMaxAgeMs: DiscordRuntimeModule["resolveThreadBindingMaxAgeMs"] = (( - ...args -) => - loadDiscordRuntimeSurface().resolveThreadBindingMaxAgeMs( - ...args, - )) as DiscordRuntimeModule["resolveThreadBindingMaxAgeMs"]; - -export const sendDiscordComponentMessage: DiscordRuntimeModule["sendDiscordComponentMessage"] = (( - ...args -) => - loadDiscordRuntimeSurface().sendDiscordComponentMessage( - ...args, - )) as DiscordRuntimeModule["sendDiscordComponentMessage"]; - -export const sendMessageDiscord: DiscordRuntimeModule["sendMessageDiscord"] = ((...args) => - loadDiscordRuntimeSurface().sendMessageDiscord( - ...args, - )) as DiscordRuntimeModule["sendMessageDiscord"]; - -export const sendPollDiscord: DiscordRuntimeModule["sendPollDiscord"] = ((...args) => - loadDiscordRuntimeSurface().sendPollDiscord(...args)) as DiscordRuntimeModule["sendPollDiscord"]; - -export const sendTypingDiscord: DiscordRuntimeModule["sendTypingDiscord"] = ((...args) => - loadDiscordRuntimeSurface().sendTypingDiscord( - ...args, - )) as DiscordRuntimeModule["sendTypingDiscord"]; - -export const setThreadBindingIdleTimeoutBySessionKey: DiscordRuntimeModule["setThreadBindingIdleTimeoutBySessionKey"] = - ((...args) => - loadDiscordRuntimeSurface().setThreadBindingIdleTimeoutBySessionKey( - ...args, - )) as DiscordRuntimeModule["setThreadBindingIdleTimeoutBySessionKey"]; - -export const setThreadBindingMaxAgeBySessionKey: DiscordRuntimeModule["setThreadBindingMaxAgeBySessionKey"] = - ((...args) => - loadDiscordRuntimeSurface().setThreadBindingMaxAgeBySessionKey( - ...args, - )) as DiscordRuntimeModule["setThreadBindingMaxAgeBySessionKey"]; - -export const unbindThreadBindingsBySessionKey: DiscordRuntimeModule["unbindThreadBindingsBySessionKey"] = - ((...args) => - loadDiscordRuntimeSurface().unbindThreadBindingsBySessionKey( - ...args, - )) as DiscordRuntimeModule["unbindThreadBindingsBySessionKey"]; - -export const unpinMessageDiscord: DiscordRuntimeModule["unpinMessageDiscord"] = ((...args) => - loadDiscordRuntimeSurface().unpinMessageDiscord( - ...args, - )) as DiscordRuntimeModule["unpinMessageDiscord"]; diff --git a/src/plugin-sdk/discord-send.ts b/src/plugin-sdk/discord-send.ts deleted file mode 100644 index 5f005327243..00000000000 --- a/src/plugin-sdk/discord-send.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { DiscordSendResult } from "../../extensions/discord/api.js"; -import type { OutboundMediaAccess } from "../media/load-options.js"; -import { attachChannelToResult } from "./channel-send-result.js"; - -type DiscordSendOptionInput = { - replyToId?: string | null; - accountId?: string | null; - silent?: boolean; -}; - -type DiscordSendMediaOptionInput = DiscordSendOptionInput & { - mediaUrl?: string; - mediaAccess?: OutboundMediaAccess; - mediaLocalRoots?: readonly string[]; - mediaReadFile?: (filePath: string) => Promise; -}; - -/** Build the common Discord send options from SDK-level reply payload fields. */ -export function buildDiscordSendOptions(input: DiscordSendOptionInput) { - return { - verbose: false, - replyTo: input.replyToId ?? undefined, - accountId: input.accountId ?? undefined, - silent: input.silent ?? undefined, - }; -} - -/** Extend the base Discord send options with media-specific fields. */ -export function buildDiscordSendMediaOptions(input: DiscordSendMediaOptionInput) { - return { - ...buildDiscordSendOptions(input), - mediaUrl: input.mediaUrl, - mediaAccess: input.mediaAccess, - mediaLocalRoots: input.mediaLocalRoots, - mediaReadFile: input.mediaReadFile, - }; -} - -/** Stamp raw Discord send results with the channel id expected by shared outbound flows. */ -export function tagDiscordChannelResult(result: DiscordSendResult) { - return attachChannelToResult("discord", result); -} diff --git a/src/plugin-sdk/signal-runtime-surface.ts b/src/plugin-sdk/signal-runtime-surface.ts deleted file mode 100644 index 7a6768ffbe2..00000000000 --- a/src/plugin-sdk/signal-runtime-surface.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { - createLazyFacadeObjectValue, - loadBundledPluginPublicSurfaceModuleSync, -} from "./facade-runtime.js"; - -type SignalRuntimeModule = typeof import("../../extensions/signal/runtime-api.js"); - -type SignalRuntimeSurface = Pick< - SignalRuntimeModule, - "monitorSignalProvider" | "probeSignal" | "sendMessageSignal" | "signalMessageActions" ->; - -function loadSignalRuntimeSurface(): SignalRuntimeSurface { - return loadBundledPluginPublicSurfaceModuleSync({ - dirName: "signal", - artifactBasename: "runtime-api.js", - }); -} - -export const signalMessageActions: SignalRuntimeModule["signalMessageActions"] = - createLazyFacadeObjectValue(() => loadSignalRuntimeSurface().signalMessageActions); - -export const monitorSignalProvider: SignalRuntimeModule["monitorSignalProvider"] = ((...args) => - loadSignalRuntimeSurface().monitorSignalProvider( - ...args, - )) as SignalRuntimeModule["monitorSignalProvider"]; - -export const probeSignal: SignalRuntimeModule["probeSignal"] = ((...args) => - loadSignalRuntimeSurface().probeSignal(...args)) as SignalRuntimeModule["probeSignal"]; - -export const sendMessageSignal: SignalRuntimeModule["sendMessageSignal"] = ((...args) => - loadSignalRuntimeSurface().sendMessageSignal( - ...args, - )) as SignalRuntimeModule["sendMessageSignal"]; diff --git a/src/plugin-sdk/slack-runtime-surface.ts b/src/plugin-sdk/slack-runtime-surface.ts deleted file mode 100644 index c49d57766e0..00000000000 --- a/src/plugin-sdk/slack-runtime-surface.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js"; - -type SlackRuntimeModule = typeof import("../../extensions/slack/runtime-api.js"); - -type SlackRuntimeSurface = Pick< - SlackRuntimeModule, - | "handleSlackAction" - | "listSlackDirectoryGroupsLive" - | "listSlackDirectoryPeersLive" - | "monitorSlackProvider" - | "probeSlack" - | "resolveSlackChannelAllowlist" - | "resolveSlackUserAllowlist" - | "sendMessageSlack" ->; - -function loadSlackRuntimeSurface(): SlackRuntimeSurface { - return loadBundledPluginPublicSurfaceModuleSync({ - dirName: "slack", - artifactBasename: "runtime-api.js", - }); -} - -export const handleSlackAction: SlackRuntimeModule["handleSlackAction"] = ((...args) => - loadSlackRuntimeSurface().handleSlackAction(...args)) as SlackRuntimeModule["handleSlackAction"]; - -export const listSlackDirectoryGroupsLive: SlackRuntimeModule["listSlackDirectoryGroupsLive"] = (( - ...args -) => - loadSlackRuntimeSurface().listSlackDirectoryGroupsLive( - ...args, - )) as SlackRuntimeModule["listSlackDirectoryGroupsLive"]; - -export const listSlackDirectoryPeersLive: SlackRuntimeModule["listSlackDirectoryPeersLive"] = (( - ...args -) => - loadSlackRuntimeSurface().listSlackDirectoryPeersLive( - ...args, - )) as SlackRuntimeModule["listSlackDirectoryPeersLive"]; - -export const monitorSlackProvider: SlackRuntimeModule["monitorSlackProvider"] = ((...args) => - loadSlackRuntimeSurface().monitorSlackProvider( - ...args, - )) as SlackRuntimeModule["monitorSlackProvider"]; - -export const probeSlack: SlackRuntimeModule["probeSlack"] = ((...args) => - loadSlackRuntimeSurface().probeSlack(...args)) as SlackRuntimeModule["probeSlack"]; - -export const resolveSlackChannelAllowlist: SlackRuntimeModule["resolveSlackChannelAllowlist"] = (( - ...args -) => - loadSlackRuntimeSurface().resolveSlackChannelAllowlist( - ...args, - )) as SlackRuntimeModule["resolveSlackChannelAllowlist"]; - -export const resolveSlackUserAllowlist: SlackRuntimeModule["resolveSlackUserAllowlist"] = (( - ...args -) => - loadSlackRuntimeSurface().resolveSlackUserAllowlist( - ...args, - )) as SlackRuntimeModule["resolveSlackUserAllowlist"]; - -export const sendMessageSlack: SlackRuntimeModule["sendMessageSlack"] = ((...args) => - loadSlackRuntimeSurface().sendMessageSlack(...args)) as SlackRuntimeModule["sendMessageSlack"]; diff --git a/src/plugins/contracts/plugin-sdk-subpaths.test.ts b/src/plugins/contracts/plugin-sdk-subpaths.test.ts index 4c0d9174045..12e04d7ae94 100644 --- a/src/plugins/contracts/plugin-sdk-subpaths.test.ts +++ b/src/plugins/contracts/plugin-sdk-subpaths.test.ts @@ -375,7 +375,7 @@ describe("plugin-sdk subpath exports", () => { /plugins\/runtime\/runtime-(?:discord|imessage|line|signal|slack|telegram|whatsapp)(?:[-.][^"']*)?\.js/u, exclude: [ "src/plugins/runtime/runtime-plugin-boundary.ts", - "src/plugins/runtime/runtime-web-channel-boundary.ts", + "src/plugins/runtime/runtime-web-channel-plugin.ts", ], excludeFilesMatching: [/\.test\.ts$/u, /\.test-harness\.ts$/u], }); diff --git a/src/plugins/runtime/local-runtime-module.test.ts b/src/plugins/runtime/local-runtime-module.test.ts index 88a8c3d6f7e..e597e93e91d 100644 --- a/src/plugins/runtime/local-runtime-module.test.ts +++ b/src/plugins/runtime/local-runtime-module.test.ts @@ -29,17 +29,17 @@ describe("loadSiblingRuntimeModuleSync", () => { it("loads a sibling runtime module from the caller directory", () => { const root = createTempDir(); const moduleUrl = pathToFileURL( - path.join(root, "src", "plugins", "runtime", "runtime-line.js"), + path.join(root, "src", "plugins", "runtime", "runtime.js"), ).href; writeFile( - path.join(root, "src", "plugins", "runtime", "runtime-line.contract.js"), + path.join(root, "src", "plugins", "runtime", "runtime.contract.js"), "module.exports = { runtimeLine: { source: 'sibling' } };", ); const loaded = loadSiblingRuntimeModuleSync<{ runtimeLine: { source: string } }>({ moduleUrl, - relativeBase: "./runtime-line.contract", + relativeBase: "./runtime.contract", }); expect(loaded.runtimeLine.source).toBe("sibling"); @@ -50,13 +50,13 @@ describe("loadSiblingRuntimeModuleSync", () => { const moduleUrl = pathToFileURL(path.join(root, "dist", "runtime-9DLN_Ai5.js")).href; writeFile( - path.join(root, "dist", "plugins", "runtime", "runtime-line.contract.js"), + path.join(root, "dist", "plugins", "runtime", "runtime.contract.js"), "module.exports = { runtimeLine: { source: 'dist-runtime' } };", ); const loaded = loadSiblingRuntimeModuleSync<{ runtimeLine: { source: string } }>({ moduleUrl, - relativeBase: "./runtime-line.contract", + relativeBase: "./runtime.contract", }); expect(loaded.runtimeLine.source).toBe("dist-runtime"); @@ -69,8 +69,8 @@ describe("loadSiblingRuntimeModuleSync", () => { expect(() => loadSiblingRuntimeModuleSync({ moduleUrl, - relativeBase: "./runtime-line.contract", + relativeBase: "./runtime.contract", }), - ).toThrow("Unable to resolve runtime module ./runtime-line.contract"); + ).toThrow("Unable to resolve runtime module ./runtime.contract"); }); }); diff --git a/src/plugins/runtime/runtime-channel.ts b/src/plugins/runtime/runtime-channel.ts index fd336b35766..b319b65afb8 100644 --- a/src/plugins/runtime/runtime-channel.ts +++ b/src/plugins/runtime/runtime-channel.ts @@ -61,17 +61,7 @@ import { readChannelAllowFromStore, upsertChannelPairingRequest, } from "../../pairing/pairing-store.js"; -import { - setThreadBindingIdleTimeoutBySessionKey, - setThreadBindingMaxAgeBySessionKey, -} from "../../plugin-sdk/discord-runtime-surface.js"; import { buildAgentSessionKey, resolveAgentRoute } from "../../routing/resolve-route.js"; -import { defineCachedValue } from "./runtime-cache.js"; -import { createRuntimeDiscord } from "./runtime-discord.js"; -import { createRuntimeLine } from "./runtime-line.js"; -import { createRuntimeMatrix } from "./runtime-matrix.js"; -import { createRuntimeSignal } from "./runtime-signal.js"; -import { createRuntimeSlack } from "./runtime-slack.js"; import type { PluginRuntime } from "./types.js"; export function createRuntimeChannel(): PluginRuntime["channel"] { @@ -161,63 +151,22 @@ export function createRuntimeChannel(): PluginRuntime["channel"] { loadAdapter: loadChannelOutboundAdapter, }, threadBindings: { - setIdleTimeoutBySessionKey: ({ channelId, targetSessionKey, accountId, idleTimeoutMs }) => { - switch (channelId) { - case "discord": - return setThreadBindingIdleTimeoutBySessionKey({ - targetSessionKey, - accountId, - idleTimeoutMs, - }); - case "matrix": - return setChannelConversationBindingIdleTimeoutBySessionKey({ - channelId, - targetSessionKey, - accountId: accountId ?? "", - idleTimeoutMs, - }); - case "telegram": - return setChannelConversationBindingIdleTimeoutBySessionKey({ - channelId, - targetSessionKey, - accountId, - idleTimeoutMs, - }); - } - }, - setMaxAgeBySessionKey: ({ channelId, targetSessionKey, accountId, maxAgeMs }) => { - switch (channelId) { - case "discord": - return setThreadBindingMaxAgeBySessionKey({ - targetSessionKey, - accountId, - maxAgeMs, - }); - case "matrix": - return setChannelConversationBindingMaxAgeBySessionKey({ - channelId, - targetSessionKey, - accountId: accountId ?? "", - maxAgeMs, - }); - case "telegram": - return setChannelConversationBindingMaxAgeBySessionKey({ - channelId, - targetSessionKey, - accountId, - maxAgeMs, - }); - } - }, + setIdleTimeoutBySessionKey: ({ channelId, targetSessionKey, accountId, idleTimeoutMs }) => + setChannelConversationBindingIdleTimeoutBySessionKey({ + channelId, + targetSessionKey, + accountId, + idleTimeoutMs, + }), + setMaxAgeBySessionKey: ({ channelId, targetSessionKey, accountId, maxAgeMs }) => + setChannelConversationBindingMaxAgeBySessionKey({ + channelId, + targetSessionKey, + accountId, + maxAgeMs, + }), }, - } satisfies Omit & - Partial>; - - defineCachedValue(channelRuntime, "discord", createRuntimeDiscord); - defineCachedValue(channelRuntime, "slack", createRuntimeSlack); - defineCachedValue(channelRuntime, "matrix", createRuntimeMatrix); - defineCachedValue(channelRuntime, "signal", createRuntimeSignal); - defineCachedValue(channelRuntime, "line", createRuntimeLine); + } satisfies PluginRuntime["channel"]; return channelRuntime as PluginRuntime["channel"]; } diff --git a/src/plugins/runtime/runtime-discord-ops.runtime.ts b/src/plugins/runtime/runtime-discord-ops.runtime.ts deleted file mode 100644 index 9afadcbdcb8..00000000000 --- a/src/plugins/runtime/runtime-discord-ops.runtime.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { - auditDiscordChannelPermissions as auditDiscordChannelPermissionsImpl, - listDiscordDirectoryGroupsLive as listDiscordDirectoryGroupsLiveImpl, - listDiscordDirectoryPeersLive as listDiscordDirectoryPeersLiveImpl, - monitorDiscordProvider as monitorDiscordProviderImpl, - probeDiscord as probeDiscordImpl, - resolveDiscordChannelAllowlist as resolveDiscordChannelAllowlistImpl, - resolveDiscordUserAllowlist as resolveDiscordUserAllowlistImpl, - createThreadDiscord as createThreadDiscordImpl, - deleteMessageDiscord as deleteMessageDiscordImpl, - editChannelDiscord as editChannelDiscordImpl, - editMessageDiscord as editMessageDiscordImpl, - pinMessageDiscord as pinMessageDiscordImpl, - sendDiscordComponentMessage as sendDiscordComponentMessageImpl, - sendMessageDiscord as sendMessageDiscordImpl, - sendPollDiscord as sendPollDiscordImpl, - sendTypingDiscord as sendTypingDiscordImpl, - unpinMessageDiscord as unpinMessageDiscordImpl, -} from "../../plugin-sdk/discord-runtime-surface.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -type RuntimeDiscordOps = Pick< - PluginRuntimeChannel["discord"], - | "auditChannelPermissions" - | "listDirectoryGroupsLive" - | "listDirectoryPeersLive" - | "probeDiscord" - | "resolveChannelAllowlist" - | "resolveUserAllowlist" - | "sendComponentMessage" - | "sendMessageDiscord" - | "sendPollDiscord" - | "monitorDiscordProvider" -> & { - typing: Pick; - conversationActions: Pick< - PluginRuntimeChannel["discord"]["conversationActions"], - "editMessage" | "deleteMessage" | "pinMessage" | "unpinMessage" | "createThread" | "editChannel" - >; -}; - -export const runtimeDiscordOps = { - auditChannelPermissions: auditDiscordChannelPermissionsImpl, - listDirectoryGroupsLive: listDiscordDirectoryGroupsLiveImpl, - listDirectoryPeersLive: listDiscordDirectoryPeersLiveImpl, - probeDiscord: probeDiscordImpl, - resolveChannelAllowlist: resolveDiscordChannelAllowlistImpl, - resolveUserAllowlist: resolveDiscordUserAllowlistImpl, - sendComponentMessage: sendDiscordComponentMessageImpl, - sendMessageDiscord: sendMessageDiscordImpl, - sendPollDiscord: sendPollDiscordImpl, - monitorDiscordProvider: monitorDiscordProviderImpl, - typing: { - pulse: sendTypingDiscordImpl, - }, - conversationActions: { - editMessage: editMessageDiscordImpl, - deleteMessage: deleteMessageDiscordImpl, - pinMessage: pinMessageDiscordImpl, - unpinMessage: unpinMessageDiscordImpl, - createThread: createThreadDiscordImpl, - editChannel: editChannelDiscordImpl, - }, -} satisfies RuntimeDiscordOps; diff --git a/src/plugins/runtime/runtime-discord.ts b/src/plugins/runtime/runtime-discord.ts deleted file mode 100644 index 3841a47d2b6..00000000000 --- a/src/plugins/runtime/runtime-discord.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { - discordMessageActions, - getThreadBindingManager, - resolveThreadBindingIdleTimeoutMs, - resolveThreadBindingInactivityExpiresAt, - resolveThreadBindingMaxAgeExpiresAt, - resolveThreadBindingMaxAgeMs, - setThreadBindingIdleTimeoutBySessionKey, - setThreadBindingMaxAgeBySessionKey, - unbindThreadBindingsBySessionKey, -} from "../../plugin-sdk/discord-runtime-surface.js"; -import { - createLazyRuntimeMethodBinder, - createLazyRuntimeSurface, -} from "../../shared/lazy-runtime.js"; -import { createDiscordTypingLease } from "./runtime-discord-typing.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -const loadRuntimeDiscordOps = createLazyRuntimeSurface( - () => import("./runtime-discord-ops.runtime.js"), - ({ runtimeDiscordOps }) => runtimeDiscordOps, -); - -const bindDiscordRuntimeMethod = createLazyRuntimeMethodBinder(loadRuntimeDiscordOps); - -const auditChannelPermissionsLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.auditChannelPermissions, -); -const listDirectoryGroupsLiveLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.listDirectoryGroupsLive, -); -const listDirectoryPeersLiveLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.listDirectoryPeersLive, -); -const probeDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.probeDiscord, -); -const resolveChannelAllowlistLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.resolveChannelAllowlist, -); -const resolveUserAllowlistLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.resolveUserAllowlist, -); -const sendComponentMessageLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.sendComponentMessage, -); -const sendMessageDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.sendMessageDiscord, -); -const sendPollDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.sendPollDiscord, -); -const monitorDiscordProviderLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.monitorDiscordProvider, -); -const sendTypingDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.typing.pulse, -); -const editMessageDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.conversationActions.editMessage, -); -const deleteMessageDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.conversationActions.deleteMessage, -); -const pinMessageDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.conversationActions.pinMessage, -); -const unpinMessageDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.conversationActions.unpinMessage, -); -const createThreadDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.conversationActions.createThread, -); -const editChannelDiscordLazy = bindDiscordRuntimeMethod( - (runtimeDiscordOps) => runtimeDiscordOps.conversationActions.editChannel, -); - -export function createRuntimeDiscord(): PluginRuntimeChannel["discord"] { - return { - messageActions: discordMessageActions, - auditChannelPermissions: auditChannelPermissionsLazy, - listDirectoryGroupsLive: listDirectoryGroupsLiveLazy, - listDirectoryPeersLive: listDirectoryPeersLiveLazy, - probeDiscord: probeDiscordLazy, - resolveChannelAllowlist: resolveChannelAllowlistLazy, - resolveUserAllowlist: resolveUserAllowlistLazy, - sendComponentMessage: sendComponentMessageLazy, - sendMessageDiscord: sendMessageDiscordLazy, - sendPollDiscord: sendPollDiscordLazy, - monitorDiscordProvider: monitorDiscordProviderLazy, - threadBindings: { - getManager: getThreadBindingManager, - resolveIdleTimeoutMs: resolveThreadBindingIdleTimeoutMs, - resolveInactivityExpiresAt: resolveThreadBindingInactivityExpiresAt, - resolveMaxAgeMs: resolveThreadBindingMaxAgeMs, - resolveMaxAgeExpiresAt: resolveThreadBindingMaxAgeExpiresAt, - setIdleTimeoutBySessionKey: setThreadBindingIdleTimeoutBySessionKey, - setMaxAgeBySessionKey: setThreadBindingMaxAgeBySessionKey, - unbindBySessionKey: unbindThreadBindingsBySessionKey, - }, - typing: { - pulse: sendTypingDiscordLazy, - start: async ({ channelId, accountId, cfg, intervalMs }) => - await createDiscordTypingLease({ - channelId, - accountId, - cfg, - intervalMs, - pulse: async ({ channelId, accountId, cfg }) => - void (await sendTypingDiscordLazy(channelId, { accountId, cfg })), - }), - }, - conversationActions: { - editMessage: editMessageDiscordLazy, - deleteMessage: deleteMessageDiscordLazy, - pinMessage: pinMessageDiscordLazy, - unpinMessage: unpinMessageDiscordLazy, - createThread: createThreadDiscordLazy, - editChannel: editChannelDiscordLazy, - }, - }; -} diff --git a/src/plugins/runtime/runtime-line.contract.ts b/src/plugins/runtime/runtime-line.contract.ts deleted file mode 100644 index 3043ad88cb2..00000000000 --- a/src/plugins/runtime/runtime-line.contract.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { - buildTemplateMessageFromPayload, - createQuickReplyItems, - monitorLineProvider, - probeLineBot, - pushFlexMessage, - pushLocationMessage, - pushMessageLine, - pushMessagesLine, - pushTemplateMessage, - pushTextMessageWithQuickReplies, - sendMessageLine, -} from "../../plugin-sdk/line-runtime.js"; -import { - listLineAccountIds, - normalizeAccountId, - resolveDefaultLineAccountId, - resolveLineAccount, -} from "../../plugin-sdk/line.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -export const runtimeLine = { - listLineAccountIds, - resolveDefaultLineAccountId, - resolveLineAccount, - normalizeAccountId, - probeLineBot, - sendMessageLine, - pushMessageLine, - pushMessagesLine, - pushFlexMessage, - pushTemplateMessage, - pushLocationMessage, - pushTextMessageWithQuickReplies, - createQuickReplyItems, - buildTemplateMessageFromPayload, - monitorLineProvider, -} satisfies PluginRuntimeChannel["line"]; diff --git a/src/plugins/runtime/runtime-line.runtime.ts b/src/plugins/runtime/runtime-line.runtime.ts deleted file mode 100644 index 6a16c3c0525..00000000000 --- a/src/plugins/runtime/runtime-line.runtime.ts +++ /dev/null @@ -1,11 +0,0 @@ -export { - monitorLineProvider, - probeLineBot, - pushFlexMessage, - pushLocationMessage, - pushMessageLine, - pushMessagesLine, - pushTemplateMessage, - pushTextMessageWithQuickReplies, - sendMessageLine, -} from "../../plugin-sdk/line-runtime.js"; diff --git a/src/plugins/runtime/runtime-line.ts b/src/plugins/runtime/runtime-line.ts deleted file mode 100644 index 3231494f50d..00000000000 --- a/src/plugins/runtime/runtime-line.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { loadSiblingRuntimeModuleSync } from "./local-runtime-module.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -type RuntimeLineModule = { - runtimeLine: PluginRuntimeChannel["line"]; -}; - -let cachedRuntimeLineModule: RuntimeLineModule | null = null; - -function loadRuntimeLineModule(): RuntimeLineModule { - cachedRuntimeLineModule ??= loadSiblingRuntimeModuleSync({ - moduleUrl: import.meta.url, - relativeBase: "./runtime-line.contract", - }); - return cachedRuntimeLineModule; -} - -export function createRuntimeLine(): PluginRuntimeChannel["line"] { - return { - listLineAccountIds: (...args) => - loadRuntimeLineModule().runtimeLine.listLineAccountIds(...args), - resolveDefaultLineAccountId: (...args) => - loadRuntimeLineModule().runtimeLine.resolveDefaultLineAccountId(...args), - resolveLineAccount: (...args) => - loadRuntimeLineModule().runtimeLine.resolveLineAccount(...args), - normalizeAccountId: (...args) => - loadRuntimeLineModule().runtimeLine.normalizeAccountId(...args), - probeLineBot: (...args) => loadRuntimeLineModule().runtimeLine.probeLineBot(...args), - sendMessageLine: (...args) => loadRuntimeLineModule().runtimeLine.sendMessageLine(...args), - pushMessageLine: (...args) => loadRuntimeLineModule().runtimeLine.pushMessageLine(...args), - pushMessagesLine: (...args) => loadRuntimeLineModule().runtimeLine.pushMessagesLine(...args), - pushFlexMessage: (...args) => loadRuntimeLineModule().runtimeLine.pushFlexMessage(...args), - pushTemplateMessage: (...args) => - loadRuntimeLineModule().runtimeLine.pushTemplateMessage(...args), - pushLocationMessage: (...args) => - loadRuntimeLineModule().runtimeLine.pushLocationMessage(...args), - pushTextMessageWithQuickReplies: (...args) => - loadRuntimeLineModule().runtimeLine.pushTextMessageWithQuickReplies(...args), - createQuickReplyItems: (...args) => - loadRuntimeLineModule().runtimeLine.createQuickReplyItems(...args), - buildTemplateMessageFromPayload: (...args) => - loadRuntimeLineModule().runtimeLine.buildTemplateMessageFromPayload(...args), - monitorLineProvider: (...args) => - loadRuntimeLineModule().runtimeLine.monitorLineProvider(...args), - }; -} diff --git a/src/plugins/runtime/runtime-matrix-boundary.ts b/src/plugins/runtime/runtime-matrix-boundary.ts deleted file mode 100644 index 1d6c5cc821c..00000000000 --- a/src/plugins/runtime/runtime-matrix-boundary.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { createJiti } from "jiti"; -import type { MatrixRuntimeBoundaryModule } from "./runtime-matrix-surface.js"; -import { - loadPluginBoundaryModuleWithJiti, - resolvePluginRuntimeModulePath, - resolvePluginRuntimeRecord, -} from "./runtime-plugin-boundary.js"; - -const MATRIX_PLUGIN_ID = "matrix"; - -type MatrixPluginRecord = { - rootDir?: string; - source: string; -}; - -let cachedModulePath: string | null = null; -let cachedModule: MatrixRuntimeBoundaryModule | null = null; - -const jitiLoaders = new Map>(); - -function resolveMatrixPluginRecord(): MatrixPluginRecord | null { - return resolvePluginRuntimeRecord(MATRIX_PLUGIN_ID) as MatrixPluginRecord | null; -} - -function resolveMatrixRuntimeModulePath(record: MatrixPluginRecord): string | null { - return resolvePluginRuntimeModulePath(record, "runtime-api"); -} - -function loadMatrixModule(): MatrixRuntimeBoundaryModule | null { - const record = resolveMatrixPluginRecord(); - if (!record) { - return null; - } - const modulePath = resolveMatrixRuntimeModulePath(record); - if (!modulePath) { - return null; - } - if (cachedModule && cachedModulePath === modulePath) { - return cachedModule; - } - const loaded = loadPluginBoundaryModuleWithJiti( - modulePath, - jitiLoaders, - ); - cachedModulePath = modulePath; - cachedModule = loaded; - return loaded; -} - -export function setMatrixThreadBindingIdleTimeoutBySessionKey( - ...args: Parameters -): ReturnType { - const fn = loadMatrixModule()?.setMatrixThreadBindingIdleTimeoutBySessionKey; - if (typeof fn !== "function") { - return []; - } - return fn(...args); -} - -export function setMatrixThreadBindingMaxAgeBySessionKey( - ...args: Parameters -): ReturnType { - const fn = loadMatrixModule()?.setMatrixThreadBindingMaxAgeBySessionKey; - if (typeof fn !== "function") { - return []; - } - return fn(...args); -} diff --git a/src/plugins/runtime/runtime-matrix-contract.ts b/src/plugins/runtime/runtime-matrix-contract.ts deleted file mode 100644 index 619dcd5024e..00000000000 --- a/src/plugins/runtime/runtime-matrix-contract.ts +++ /dev/null @@ -1,178 +0,0 @@ -// Narrow plugin-sdk surface for the bundled Matrix plugin. -// Keep this list additive and scoped to the runtime contract only. - -import { createOptionalChannelSetupSurface } from "../../plugin-sdk/channel-setup.js"; - -export { - createActionGate, - jsonResult, - readNumberParam, - readReactionParams, - readStringArrayParam, - readStringParam, -} from "../../agents/tools/common.js"; -export type { ReplyPayload } from "../../auto-reply/types.js"; -export { resolveAckReaction } from "../../agents/identity.js"; -export { - compileAllowlist, - resolveCompiledAllowlistMatch, - resolveAllowlistCandidates, - resolveAllowlistMatchByCandidates, -} from "../../channels/allowlist-match.js"; -export { - addAllowlistUserEntriesFromConfigEntry, - buildAllowlistResolutionSummary, - canonicalizeAllowlistWithResolvedIds, - mergeAllowlist, - patchAllowlistUsersInConfigEntries, - summarizeMapping, -} from "../../channels/allowlists/resolve-utils.js"; -export { ensureConfiguredAcpBindingReady } from "../../acp/persistent-bindings.lifecycle.js"; -export { resolveConfiguredAcpBindingRecord } from "../../acp/persistent-bindings.resolve.js"; -export { resolveControlCommandGate } from "../../channels/command-gating.js"; -export type { NormalizedLocation } from "../../channels/location.js"; -export { formatLocationText, toLocationContext } from "../../channels/location.js"; -export { logInboundDrop, logTypingFailure } from "../../channels/logging.js"; -export type { AllowlistMatch } from "../../channels/plugins/allowlist-match.js"; -export { formatAllowlistMatchMeta } from "../../channels/plugins/allowlist-match.js"; -export { - buildChannelKeyCandidates, - resolveChannelEntryMatch, -} from "../../channels/plugins/channel-config.js"; -export { createAccountListHelpers } from "../../channels/plugins/account-helpers.js"; -export { - deleteAccountFromConfigSection, - setAccountEnabledInConfigSection, -} from "../../channels/plugins/config-helpers.js"; -export { buildChannelConfigSchema } from "../../channels/plugins/config-schema.js"; -export { formatPairingApproveHint } from "../../channels/plugins/helpers.js"; -export { - buildSingleChannelSecretPromptState, - addWildcardAllowFrom, - mergeAllowFromEntries, - promptAccountId, - promptSingleChannelSecretInput, - setTopLevelChannelGroupPolicy, -} from "../../channels/plugins/setup-wizard-helpers.js"; -export { promptChannelAccessConfig } from "../../channels/plugins/setup-group-access.js"; -export { PAIRING_APPROVED_MESSAGE } from "../../channels/plugins/pairing-message.js"; -export { - applyAccountNameToChannelSection, - moveSingleAccountChannelSectionToDefaultAccount, -} from "../../channels/plugins/setup-helpers.js"; -export type { - BaseProbeResult, - ChannelDirectoryEntry, - ChannelGroupContext, - ChannelMessageActionAdapter, - ChannelMessageActionContext, - ChannelMessageActionName, - ChannelMessageToolDiscovery, - ChannelMessageToolSchemaContribution, - ChannelOutboundAdapter, - ChannelResolveKind, - ChannelResolveResult, - ChannelSetupInput, - ChannelToolSend, -} from "../../channels/plugins/types.js"; -export type { ChannelPlugin } from "../../channels/plugins/types.plugin.js"; -export { createReplyPrefixOptions } from "../../channels/reply-prefix.js"; -export { resolveThreadBindingFarewellText } from "../../channels/thread-bindings-messages.js"; -export { - resolveThreadBindingIdleTimeoutMsForChannel, - resolveThreadBindingMaxAgeMsForChannel, -} from "../../channels/thread-bindings-policy.js"; -export { - setMatrixThreadBindingIdleTimeoutBySessionKey, - setMatrixThreadBindingMaxAgeBySessionKey, -} from "../../plugin-sdk/matrix-thread-bindings.js"; -export { createTypingCallbacks } from "../../channels/typing.js"; -export { createChannelReplyPipeline } from "../../plugin-sdk/channel-reply-pipeline.js"; -export type { OpenClawConfig } from "../../config/config.js"; -export { - GROUP_POLICY_BLOCKED_LABEL, - resolveAllowlistProviderRuntimeGroupPolicy, - resolveDefaultGroupPolicy, - warnMissingProviderGroupPolicyFallbackOnce, -} from "../../config/runtime-group-policy.js"; -export type { - DmPolicy, - GroupPolicy, - GroupToolPolicyConfig, - MarkdownTableMode, -} from "../../config/types.js"; -export type { SecretInput } from "../../plugin-sdk/secret-input.js"; -export { - buildSecretInputSchema, - hasConfiguredSecretInput, - normalizeResolvedSecretInputString, - normalizeSecretInputString, -} from "../../plugin-sdk/secret-input.js"; -export { ToolPolicySchema } from "../../config/zod-schema.agent-runtime.js"; -export { MarkdownConfigSchema } from "../../config/zod-schema.core.js"; -export { formatZonedTimestamp } from "../../infra/format-time/format-datetime.js"; -export { fetchWithSsrFGuard } from "../../infra/net/fetch-guard.js"; -export { maybeCreateMatrixMigrationSnapshot } from "../../infra/matrix-migration-snapshot.js"; -export { - getSessionBindingService, - registerSessionBindingAdapter, - unregisterSessionBindingAdapter, -} from "../../infra/outbound/session-binding-service.js"; -export { resolveOutboundSendDep } from "../../infra/outbound/send-deps.js"; -export type { - BindingTargetKind, - SessionBindingRecord, -} from "../../infra/outbound/session-binding-service.js"; -export { isPrivateOrLoopbackHost } from "../../gateway/net.js"; -export { getAgentScopedMediaLocalRoots } from "../../media/local-roots.js"; -export { emptyPluginConfigSchema } from "../config-schema.js"; -export type { PluginRuntime, RuntimeLogger } from "./types.js"; -export type { OpenClawPluginApi } from "../types.js"; -export type { PollInput } from "../../polls.js"; -export { normalizePollInput } from "../../polls.js"; -export { - DEFAULT_ACCOUNT_ID, - normalizeAccountId, - normalizeOptionalAccountId, - resolveAgentIdFromSessionKey, -} from "../../routing/session-key.js"; -export type { RuntimeEnv } from "../../runtime.js"; -export { normalizeStringEntries } from "../../shared/string-normalization.js"; -export { formatDocsLink } from "../../terminal/links.js"; -export { redactSensitiveText } from "../../logging/redact.js"; -export type { WizardPrompter } from "../../wizard/prompts.js"; -export { - evaluateGroupRouteAccessForPolicy, - resolveSenderScopedGroupPolicy, -} from "../../plugin-sdk/group-access.js"; -export { createChannelPairingController } from "../../plugin-sdk/channel-pairing.js"; -export { readJsonFileWithFallback, writeJsonFileAtomically } from "../../plugin-sdk/json-store.js"; -export { formatResolvedUnresolvedNote } from "../../plugin-sdk/resolution-notes.js"; -export { runPluginCommandWithTimeout } from "../../plugin-sdk/run-command.js"; -export { createLoggerBackedRuntime, resolveRuntimeEnv } from "../../plugin-sdk/runtime.js"; -export { dispatchReplyFromConfigWithSettledDispatcher } from "../../plugin-sdk/inbound-reply-dispatch.js"; -export { - buildProbeChannelStatusSummary, - collectStatusIssuesFromLastError, -} from "../../plugin-sdk/status-helpers.js"; -export { - resolveMatrixAccountStorageRoot, - resolveMatrixCredentialsDir, - resolveMatrixCredentialsPath, - resolveMatrixLegacyFlatStoragePaths, -} from "../../plugin-sdk/matrix-helper.js"; -export { getMatrixScopedEnvVarNames } from "../../plugin-sdk/matrix-helper.js"; -export { - requiresExplicitMatrixDefaultAccount, - resolveMatrixDefaultOrOnlyAccountId, -} from "../../plugin-sdk/matrix-helper.js"; - -const matrixSetup = createOptionalChannelSetupSurface({ - channel: "matrix", - label: "Matrix", - npmSpec: "@openclaw/matrix", - docsPath: "/channels/matrix", -}); - -export const matrixSetupWizard = matrixSetup.setupWizard; -export const matrixSetupAdapter = matrixSetup.setupAdapter; diff --git a/src/plugins/runtime/runtime-matrix-surface.ts b/src/plugins/runtime/runtime-matrix-surface.ts deleted file mode 100644 index 33d3d212274..00000000000 --- a/src/plugins/runtime/runtime-matrix-surface.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { SessionBindingRecord } from "../../infra/outbound/session-binding-service.js"; - -export type MatrixThreadBindingIdleTimeoutParams = { - accountId: string; - targetSessionKey: string; - idleTimeoutMs: number; -}; - -export type MatrixThreadBindingMaxAgeParams = { - accountId: string; - targetSessionKey: string; - maxAgeMs: number; -}; - -export type MatrixRuntimeBoundaryModule = { - setMatrixThreadBindingIdleTimeoutBySessionKey: ( - params: MatrixThreadBindingIdleTimeoutParams, - ) => SessionBindingRecord[]; - setMatrixThreadBindingMaxAgeBySessionKey: ( - params: MatrixThreadBindingMaxAgeParams, - ) => SessionBindingRecord[]; -}; diff --git a/src/plugins/runtime/runtime-matrix.ts b/src/plugins/runtime/runtime-matrix.ts deleted file mode 100644 index ac72161f69f..00000000000 --- a/src/plugins/runtime/runtime-matrix.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { - setMatrixThreadBindingIdleTimeoutBySessionKey, - setMatrixThreadBindingMaxAgeBySessionKey, -} from "./runtime-matrix-boundary.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -export function createRuntimeMatrix(): PluginRuntimeChannel["matrix"] { - return { - threadBindings: { - setIdleTimeoutBySessionKey: setMatrixThreadBindingIdleTimeoutBySessionKey, - setMaxAgeBySessionKey: setMatrixThreadBindingMaxAgeBySessionKey, - }, - }; -} diff --git a/src/plugins/runtime/runtime-plugin-boundary.ts b/src/plugins/runtime/runtime-plugin-boundary.ts index bdca0acd37e..d49cadeae13 100644 --- a/src/plugins/runtime/runtime-plugin-boundary.ts +++ b/src/plugins/runtime/runtime-plugin-boundary.ts @@ -16,6 +16,13 @@ type PluginRuntimeRecord = { source: string; }; +type CachedPluginBoundaryLoaderParams = { + pluginId: string; + entryBaseName: string; + required?: boolean; + missingLabel?: string; +}; + export function readPluginBoundaryConfigSafely() { try { return loadConfig(); @@ -104,3 +111,47 @@ export function loadPluginBoundaryModuleWithJiti( ): TModule { return getPluginBoundaryJiti(modulePath, loaders)(modulePath) as TModule; } + +export function createCachedPluginBoundaryModuleLoader( + params: CachedPluginBoundaryLoaderParams, +): () => TModule | null { + let cachedModulePath: string | null = null; + let cachedModule: TModule | null = null; + const loaders = new Map>(); + + return () => { + const missingLabel = params.missingLabel ?? `${params.pluginId} plugin runtime`; + const record = resolvePluginRuntimeRecord( + params.pluginId, + params.required + ? () => { + throw new Error(`${missingLabel} is unavailable: missing plugin '${params.pluginId}'`); + } + : undefined, + ); + if (!record) { + return null; + } + const modulePath = resolvePluginRuntimeModulePath( + record, + params.entryBaseName, + params.required + ? () => { + throw new Error( + `${missingLabel} is unavailable: missing ${params.entryBaseName} for plugin '${params.pluginId}'`, + ); + } + : undefined, + ); + if (!modulePath) { + return null; + } + if (cachedModule && cachedModulePath === modulePath) { + return cachedModule; + } + const loaded = loadPluginBoundaryModuleWithJiti(modulePath, loaders); + cachedModulePath = modulePath; + cachedModule = loaded; + return loaded; + }; +} diff --git a/src/plugins/runtime/runtime-signal.ts b/src/plugins/runtime/runtime-signal.ts deleted file mode 100644 index 3489ecc0b65..00000000000 --- a/src/plugins/runtime/runtime-signal.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { - monitorSignalProvider, - probeSignal, - signalMessageActions, - sendMessageSignal, -} from "../../plugin-sdk/signal-runtime-surface.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -export function createRuntimeSignal(): PluginRuntimeChannel["signal"] { - return { - probeSignal, - sendMessageSignal, - monitorSignalProvider, - messageActions: signalMessageActions, - }; -} diff --git a/src/plugins/runtime/runtime-slack-ops.runtime.ts b/src/plugins/runtime/runtime-slack-ops.runtime.ts deleted file mode 100644 index 33e0c673bf1..00000000000 --- a/src/plugins/runtime/runtime-slack-ops.runtime.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { - listSlackDirectoryGroupsLive as listSlackDirectoryGroupsLiveImpl, - listSlackDirectoryPeersLive as listSlackDirectoryPeersLiveImpl, - monitorSlackProvider as monitorSlackProviderImpl, - probeSlack as probeSlackImpl, - resolveSlackChannelAllowlist as resolveSlackChannelAllowlistImpl, - resolveSlackUserAllowlist as resolveSlackUserAllowlistImpl, - sendMessageSlack as sendMessageSlackImpl, - handleSlackAction as handleSlackActionImpl, -} from "../../plugin-sdk/slack-runtime-surface.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -type RuntimeSlackOps = Pick< - PluginRuntimeChannel["slack"], - | "listDirectoryGroupsLive" - | "listDirectoryPeersLive" - | "probeSlack" - | "resolveChannelAllowlist" - | "resolveUserAllowlist" - | "sendMessageSlack" - | "monitorSlackProvider" - | "handleSlackAction" ->; - -export const runtimeSlackOps = { - listDirectoryGroupsLive: listSlackDirectoryGroupsLiveImpl, - listDirectoryPeersLive: listSlackDirectoryPeersLiveImpl, - probeSlack: probeSlackImpl, - resolveChannelAllowlist: resolveSlackChannelAllowlistImpl, - resolveUserAllowlist: resolveSlackUserAllowlistImpl, - sendMessageSlack: sendMessageSlackImpl, - monitorSlackProvider: monitorSlackProviderImpl, - handleSlackAction: handleSlackActionImpl, -} satisfies RuntimeSlackOps; diff --git a/src/plugins/runtime/runtime-slack.ts b/src/plugins/runtime/runtime-slack.ts deleted file mode 100644 index 9f1cab0f094..00000000000 --- a/src/plugins/runtime/runtime-slack.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { - createLazyRuntimeMethodBinder, - createLazyRuntimeSurface, -} from "../../shared/lazy-runtime.js"; -import type { PluginRuntimeChannel } from "./types-channel.js"; - -const loadRuntimeSlackOps = createLazyRuntimeSurface( - () => import("./runtime-slack-ops.runtime.js"), - ({ runtimeSlackOps }) => runtimeSlackOps, -); - -const bindSlackRuntimeMethod = createLazyRuntimeMethodBinder(loadRuntimeSlackOps); - -const listDirectoryGroupsLiveLazy = bindSlackRuntimeMethod( - (runtimeSlackOps) => runtimeSlackOps.listDirectoryGroupsLive, -); -const listDirectoryPeersLiveLazy = bindSlackRuntimeMethod( - (runtimeSlackOps) => runtimeSlackOps.listDirectoryPeersLive, -); -const probeSlackLazy = bindSlackRuntimeMethod((runtimeSlackOps) => runtimeSlackOps.probeSlack); -const resolveChannelAllowlistLazy = bindSlackRuntimeMethod( - (runtimeSlackOps) => runtimeSlackOps.resolveChannelAllowlist, -); -const resolveUserAllowlistLazy = bindSlackRuntimeMethod( - (runtimeSlackOps) => runtimeSlackOps.resolveUserAllowlist, -); -const sendMessageSlackLazy = bindSlackRuntimeMethod( - (runtimeSlackOps) => runtimeSlackOps.sendMessageSlack, -); -const monitorSlackProviderLazy = bindSlackRuntimeMethod( - (runtimeSlackOps) => runtimeSlackOps.monitorSlackProvider, -); -const handleSlackActionLazy = bindSlackRuntimeMethod( - (runtimeSlackOps) => runtimeSlackOps.handleSlackAction, -); - -export function createRuntimeSlack(): PluginRuntimeChannel["slack"] { - return { - listDirectoryGroupsLive: listDirectoryGroupsLiveLazy, - listDirectoryPeersLive: listDirectoryPeersLiveLazy, - probeSlack: probeSlackLazy, - resolveChannelAllowlist: resolveChannelAllowlistLazy, - resolveUserAllowlist: resolveUserAllowlistLazy, - sendMessageSlack: sendMessageSlackLazy, - monitorSlackProvider: monitorSlackProviderLazy, - handleSlackAction: handleSlackActionLazy, - }; -} diff --git a/src/plugins/runtime/runtime-web-channel-boundary.ts b/src/plugins/runtime/runtime-web-channel-boundary.ts deleted file mode 100644 index 2436256e203..00000000000 --- a/src/plugins/runtime/runtime-web-channel-boundary.ts +++ /dev/null @@ -1,286 +0,0 @@ -import { createJiti } from "jiti"; -type WhatsAppHeavyRuntimeModule = typeof import("@openclaw/whatsapp/runtime-api.js"); -type WhatsAppLightRuntimeModule = typeof import("@openclaw/whatsapp/light-runtime-api.js"); -import { - getDefaultLocalRoots as getDefaultLocalRootsImpl, - loadWebMedia as loadWebMediaImpl, - loadWebMediaRaw as loadWebMediaRawImpl, - optimizeImageToJpeg as optimizeImageToJpegImpl, -} from "../../media/web-media.js"; -import { - loadPluginBoundaryModuleWithJiti, - resolvePluginRuntimeModulePath, - resolvePluginRuntimeRecord, -} from "./runtime-plugin-boundary.js"; - -const WHATSAPP_PLUGIN_ID = "whatsapp"; - -type WhatsAppPluginRecord = { - origin: string; - rootDir?: string; - source: string; -}; - -let cachedHeavyModulePath: string | null = null; -let cachedHeavyModule: WhatsAppHeavyRuntimeModule | null = null; -let cachedLightModulePath: string | null = null; -let cachedLightModule: WhatsAppLightRuntimeModule | null = null; - -const jitiLoaders = new Map>(); - -function resolveWhatsAppPluginRecord(): WhatsAppPluginRecord { - return resolvePluginRuntimeRecord(WHATSAPP_PLUGIN_ID, () => { - throw new Error( - `WhatsApp plugin runtime is unavailable: missing plugin '${WHATSAPP_PLUGIN_ID}'`, - ); - }) as WhatsAppPluginRecord; -} - -function resolveWhatsAppRuntimeModulePath( - record: WhatsAppPluginRecord, - entryBaseName: "light-runtime-api" | "runtime-api", -): string { - const modulePath = resolvePluginRuntimeModulePath(record, entryBaseName, () => { - throw new Error( - `WhatsApp plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WHATSAPP_PLUGIN_ID}'`, - ); - }); - if (!modulePath) { - throw new Error( - `WhatsApp plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WHATSAPP_PLUGIN_ID}'`, - ); - } - return modulePath; -} - -function loadCurrentHeavyModuleSync(): WhatsAppHeavyRuntimeModule { - const modulePath = resolveWhatsAppRuntimeModulePath(resolveWhatsAppPluginRecord(), "runtime-api"); - return loadPluginBoundaryModuleWithJiti(modulePath, jitiLoaders); -} - -function loadWhatsAppLightModule(): WhatsAppLightRuntimeModule { - const modulePath = resolveWhatsAppRuntimeModulePath( - resolveWhatsAppPluginRecord(), - "light-runtime-api", - ); - if (cachedLightModule && cachedLightModulePath === modulePath) { - return cachedLightModule; - } - const loaded = loadPluginBoundaryModuleWithJiti( - modulePath, - jitiLoaders, - ); - cachedLightModulePath = modulePath; - cachedLightModule = loaded; - return loaded; -} - -async function loadWhatsAppHeavyModule(): Promise { - const record = resolveWhatsAppPluginRecord(); - const modulePath = resolveWhatsAppRuntimeModulePath(record, "runtime-api"); - if (cachedHeavyModule && cachedHeavyModulePath === modulePath) { - return cachedHeavyModule; - } - const loaded = loadPluginBoundaryModuleWithJiti( - modulePath, - jitiLoaders, - ); - cachedHeavyModulePath = modulePath; - cachedHeavyModule = loaded; - return loaded; -} - -function getLightExport( - exportName: K, -): NonNullable { - const loaded = loadWhatsAppLightModule(); - const value = loaded[exportName]; - if (value == null) { - throw new Error(`WhatsApp plugin runtime is missing export '${String(exportName)}'`); - } - return value as NonNullable; -} - -async function getHeavyExport( - exportName: K, -): Promise> { - const loaded = await loadWhatsAppHeavyModule(); - const value = loaded[exportName]; - if (value == null) { - throw new Error(`WhatsApp plugin runtime is missing export '${String(exportName)}'`); - } - return value as NonNullable; -} - -export function getActiveWebListener( - ...args: Parameters -): ReturnType { - return getLightExport("getActiveWebListener")(...args); -} - -export function getWebAuthAgeMs( - ...args: Parameters -): ReturnType { - return getLightExport("getWebAuthAgeMs")(...args); -} - -export function logWebSelfId( - ...args: Parameters -): ReturnType { - return getLightExport("logWebSelfId")(...args); -} - -export function loginWeb( - ...args: Parameters -): ReturnType { - return loadWhatsAppHeavyModule().then((loaded) => loaded.loginWeb(...args)); -} - -export function logoutWeb( - ...args: Parameters -): ReturnType { - return getLightExport("logoutWeb")(...args); -} - -export function readWebSelfId( - ...args: Parameters -): ReturnType { - return getLightExport("readWebSelfId")(...args); -} - -export function webAuthExists( - ...args: Parameters -): ReturnType { - return getLightExport("webAuthExists")(...args); -} - -export function sendMessageWhatsApp( - ...args: Parameters -): ReturnType { - return loadWhatsAppHeavyModule().then((loaded) => loaded.sendMessageWhatsApp(...args)); -} - -export function sendPollWhatsApp( - ...args: Parameters -): ReturnType { - return loadWhatsAppHeavyModule().then((loaded) => loaded.sendPollWhatsApp(...args)); -} - -export function sendReactionWhatsApp( - ...args: Parameters -): ReturnType { - return loadWhatsAppHeavyModule().then((loaded) => loaded.sendReactionWhatsApp(...args)); -} - -export function createRuntimeWhatsAppLoginTool( - ...args: Parameters -): ReturnType { - return getLightExport("createWhatsAppLoginTool")(...args); -} - -export function createWaSocket( - ...args: Parameters -): ReturnType { - return loadWhatsAppHeavyModule().then((loaded) => loaded.createWaSocket(...args)); -} - -export function formatError( - ...args: Parameters -): ReturnType { - return getLightExport("formatError")(...args); -} - -export function getStatusCode( - ...args: Parameters -): ReturnType { - return getLightExport("getStatusCode")(...args); -} - -export function pickWebChannel( - ...args: Parameters -): ReturnType { - return getLightExport("pickWebChannel")(...args); -} - -export function resolveWaWebAuthDir(): WhatsAppLightRuntimeModule["WA_WEB_AUTH_DIR"] { - return getLightExport("WA_WEB_AUTH_DIR"); -} - -export async function handleWhatsAppAction( - ...args: Parameters -): ReturnType { - return (await getHeavyExport("handleWhatsAppAction"))(...args); -} - -export async function loadWebMedia( - ...args: Parameters -): ReturnType { - return await loadWebMediaImpl(...args); -} - -export async function loadWebMediaRaw( - ...args: Parameters -): ReturnType { - return await loadWebMediaRawImpl(...args); -} - -export function monitorWebChannel( - ...args: Parameters -): ReturnType { - return loadWhatsAppHeavyModule().then((loaded) => loaded.monitorWebChannel(...args)); -} - -export async function monitorWebInbox( - ...args: Parameters -): ReturnType { - return (await getHeavyExport("monitorWebInbox"))(...args); -} - -export async function optimizeImageToJpeg( - ...args: Parameters -): ReturnType { - return await optimizeImageToJpegImpl(...args); -} - -export async function runWebHeartbeatOnce( - ...args: Parameters -): ReturnType { - return (await getHeavyExport("runWebHeartbeatOnce"))(...args); -} - -export async function startWebLoginWithQr( - ...args: Parameters -): ReturnType { - return (await getHeavyExport("startWebLoginWithQr"))(...args); -} - -export async function waitForWaConnection( - ...args: Parameters -): ReturnType { - return (await getHeavyExport("waitForWaConnection"))(...args); -} - -export async function waitForWebLogin( - ...args: Parameters -): ReturnType { - return (await getHeavyExport("waitForWebLogin"))(...args); -} - -export const extractMediaPlaceholder = ( - ...args: Parameters -) => loadCurrentHeavyModuleSync().extractMediaPlaceholder(...args); - -export const extractText = (...args: Parameters) => - loadCurrentHeavyModuleSync().extractText(...args); - -export function getDefaultLocalRoots( - ...args: Parameters -): ReturnType { - return getDefaultLocalRootsImpl(...args); -} - -export function resolveHeartbeatRecipients( - ...args: Parameters -): ReturnType { - return loadCurrentHeavyModuleSync().resolveHeartbeatRecipients(...args); -} diff --git a/src/plugins/runtime/runtime-web-channel-plugin.ts b/src/plugins/runtime/runtime-web-channel-plugin.ts new file mode 100644 index 00000000000..c3f6f0e3647 --- /dev/null +++ b/src/plugins/runtime/runtime-web-channel-plugin.ts @@ -0,0 +1,289 @@ +import { createJiti } from "jiti"; +type WebChannelHeavyRuntimeModule = typeof import("@openclaw/whatsapp/runtime-api.js"); +type WebChannelLightRuntimeModule = typeof import("@openclaw/whatsapp/light-runtime-api.js"); +import { + getDefaultLocalRoots as getDefaultLocalRootsImpl, + loadWebMedia as loadWebMediaImpl, + loadWebMediaRaw as loadWebMediaRawImpl, + optimizeImageToJpeg as optimizeImageToJpegImpl, +} from "../../media/web-media.js"; +import { + loadPluginBoundaryModuleWithJiti, + resolvePluginRuntimeModulePath, + resolvePluginRuntimeRecord, +} from "./runtime-plugin-boundary.js"; + +const WEB_CHANNEL_PLUGIN_ID = "whatsapp"; + +type WebChannelPluginRecord = { + origin: string; + rootDir?: string; + source: string; +}; + +let cachedHeavyModulePath: string | null = null; +let cachedHeavyModule: WebChannelHeavyRuntimeModule | null = null; +let cachedLightModulePath: string | null = null; +let cachedLightModule: WebChannelLightRuntimeModule | null = null; + +const jitiLoaders = new Map>(); + +function resolveWebChannelPluginRecord(): WebChannelPluginRecord { + return resolvePluginRuntimeRecord(WEB_CHANNEL_PLUGIN_ID, () => { + throw new Error( + `web channel plugin runtime is unavailable: missing plugin '${WEB_CHANNEL_PLUGIN_ID}'`, + ); + }) as WebChannelPluginRecord; +} + +function resolveWebChannelRuntimeModulePath( + record: WebChannelPluginRecord, + entryBaseName: "light-runtime-api" | "runtime-api", +): string { + const modulePath = resolvePluginRuntimeModulePath(record, entryBaseName, () => { + throw new Error( + `web channel plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WEB_CHANNEL_PLUGIN_ID}'`, + ); + }); + if (!modulePath) { + throw new Error( + `web channel plugin runtime is unavailable: missing ${entryBaseName} for plugin '${WEB_CHANNEL_PLUGIN_ID}'`, + ); + } + return modulePath; +} + +function loadCurrentHeavyModuleSync(): WebChannelHeavyRuntimeModule { + const modulePath = resolveWebChannelRuntimeModulePath( + resolveWebChannelPluginRecord(), + "runtime-api", + ); + return loadPluginBoundaryModuleWithJiti(modulePath, jitiLoaders); +} + +function loadWebChannelLightModule(): WebChannelLightRuntimeModule { + const modulePath = resolveWebChannelRuntimeModulePath( + resolveWebChannelPluginRecord(), + "light-runtime-api", + ); + if (cachedLightModule && cachedLightModulePath === modulePath) { + return cachedLightModule; + } + const loaded = loadPluginBoundaryModuleWithJiti( + modulePath, + jitiLoaders, + ); + cachedLightModulePath = modulePath; + cachedLightModule = loaded; + return loaded; +} + +async function loadWebChannelHeavyModule(): Promise { + const record = resolveWebChannelPluginRecord(); + const modulePath = resolveWebChannelRuntimeModulePath(record, "runtime-api"); + if (cachedHeavyModule && cachedHeavyModulePath === modulePath) { + return cachedHeavyModule; + } + const loaded = loadPluginBoundaryModuleWithJiti( + modulePath, + jitiLoaders, + ); + cachedHeavyModulePath = modulePath; + cachedHeavyModule = loaded; + return loaded; +} + +function getLightExport( + exportName: K, +): NonNullable { + const loaded = loadWebChannelLightModule(); + const value = loaded[exportName]; + if (value == null) { + throw new Error(`web channel plugin runtime is missing export '${String(exportName)}'`); + } + return value as NonNullable; +} + +async function getHeavyExport( + exportName: K, +): Promise> { + const loaded = await loadWebChannelHeavyModule(); + const value = loaded[exportName]; + if (value == null) { + throw new Error(`web channel plugin runtime is missing export '${String(exportName)}'`); + } + return value as NonNullable; +} + +export function getActiveWebListener( + ...args: Parameters +): ReturnType { + return getLightExport("getActiveWebListener")(...args); +} + +export function getWebAuthAgeMs( + ...args: Parameters +): ReturnType { + return getLightExport("getWebAuthAgeMs")(...args); +} + +export function logWebSelfId( + ...args: Parameters +): ReturnType { + return getLightExport("logWebSelfId")(...args); +} + +export function loginWeb( + ...args: Parameters +): ReturnType { + return loadWebChannelHeavyModule().then((loaded) => loaded.loginWeb(...args)); +} + +export function logoutWeb( + ...args: Parameters +): ReturnType { + return getLightExport("logoutWeb")(...args); +} + +export function readWebSelfId( + ...args: Parameters +): ReturnType { + return getLightExport("readWebSelfId")(...args); +} + +export function webAuthExists( + ...args: Parameters +): ReturnType { + return getLightExport("webAuthExists")(...args); +} + +export function sendWebChannelMessage( + ...args: Parameters +): ReturnType { + return loadWebChannelHeavyModule().then((loaded) => loaded.sendMessageWhatsApp(...args)); +} + +export function sendWebChannelPoll( + ...args: Parameters +): ReturnType { + return loadWebChannelHeavyModule().then((loaded) => loaded.sendPollWhatsApp(...args)); +} + +export function sendWebChannelReaction( + ...args: Parameters +): ReturnType { + return loadWebChannelHeavyModule().then((loaded) => loaded.sendReactionWhatsApp(...args)); +} + +export function createRuntimeWebChannelLoginTool( + ...args: Parameters +): ReturnType { + return getLightExport("createWhatsAppLoginTool")(...args); +} + +export function createWebChannelSocket( + ...args: Parameters +): ReturnType { + return loadWebChannelHeavyModule().then((loaded) => loaded.createWaSocket(...args)); +} + +export function formatError( + ...args: Parameters +): ReturnType { + return getLightExport("formatError")(...args); +} + +export function getStatusCode( + ...args: Parameters +): ReturnType { + return getLightExport("getStatusCode")(...args); +} + +export function pickWebChannel( + ...args: Parameters +): ReturnType { + return getLightExport("pickWebChannel")(...args); +} + +export function resolveWebChannelAuthDir(): WebChannelLightRuntimeModule["WA_WEB_AUTH_DIR"] { + return getLightExport("WA_WEB_AUTH_DIR"); +} + +export async function handleWebChannelAction( + ...args: Parameters +): ReturnType { + return (await getHeavyExport("handleWhatsAppAction"))(...args); +} + +export async function loadWebMedia( + ...args: Parameters +): ReturnType { + return await loadWebMediaImpl(...args); +} + +export async function loadWebMediaRaw( + ...args: Parameters +): ReturnType { + return await loadWebMediaRawImpl(...args); +} + +export function monitorWebChannel( + ...args: Parameters +): ReturnType { + return loadWebChannelHeavyModule().then((loaded) => loaded.monitorWebChannel(...args)); +} + +export async function monitorWebInbox( + ...args: Parameters +): ReturnType { + return (await getHeavyExport("monitorWebInbox"))(...args); +} + +export async function optimizeImageToJpeg( + ...args: Parameters +): ReturnType { + return await optimizeImageToJpegImpl(...args); +} + +export async function runWebHeartbeatOnce( + ...args: Parameters +): ReturnType { + return (await getHeavyExport("runWebHeartbeatOnce"))(...args); +} + +export async function startWebLoginWithQr( + ...args: Parameters +): ReturnType { + return (await getHeavyExport("startWebLoginWithQr"))(...args); +} + +export async function waitForWebChannelConnection( + ...args: Parameters +): ReturnType { + return (await getHeavyExport("waitForWaConnection"))(...args); +} + +export async function waitForWebLogin( + ...args: Parameters +): ReturnType { + return (await getHeavyExport("waitForWebLogin"))(...args); +} + +export const extractMediaPlaceholder = ( + ...args: Parameters +) => loadCurrentHeavyModuleSync().extractMediaPlaceholder(...args); + +export const extractText = (...args: Parameters) => + loadCurrentHeavyModuleSync().extractText(...args); + +export function getDefaultLocalRoots( + ...args: Parameters +): ReturnType { + return getDefaultLocalRootsImpl(...args); +} + +export function resolveHeartbeatRecipients( + ...args: Parameters +): ReturnType { + return loadCurrentHeavyModuleSync().resolveHeartbeatRecipients(...args); +} diff --git a/src/plugins/runtime/types-channel.ts b/src/plugins/runtime/types-channel.ts index 4450dd8ed81..f8723b0573f 100644 --- a/src/plugins/runtime/types-channel.ts +++ b/src/plugins/runtime/types-channel.ts @@ -1,17 +1,14 @@ /** * Runtime helpers for native channel plugins. * - * This surface exposes core and channel-specific helpers used by bundled - * plugins. Prefer hooks unless you need tight in-process coupling with the - * OpenClaw messaging/runtime stack. + * This surface exposes generic core helpers only. Plugin-owned behavior stays + * inside the owning plugin package instead of hanging off core runtime slots + * like `channel.discord` or `channel.slack`. */ type ReadChannelAllowFromStore = typeof import("../../pairing/pairing-store.js").readChannelAllowFromStore; type UpsertChannelPairingRequest = typeof import("../../pairing/pairing-store.js").upsertChannelPairingRequest; -type DiscordRuntimeSurface = typeof import("../../../extensions/discord/runtime-api.js"); -type DiscordThreadBindings = typeof import("../../../extensions/discord/runtime-api.js"); -type MatrixThreadBindings = typeof import("../../../extensions/matrix/api.js"); type ReadChannelAllowFromStoreForAccount = (params: { channel: Parameters[0]; @@ -110,98 +107,16 @@ export type PluginRuntimeChannel = { }; threadBindings: { setIdleTimeoutBySessionKey: (params: { - channelId: "discord" | "matrix" | "telegram"; + channelId: string; targetSessionKey: string; accountId?: string; idleTimeoutMs: number; }) => RuntimeThreadBindingLifecycleRecord[]; setMaxAgeBySessionKey: (params: { - channelId: "discord" | "matrix" | "telegram"; + channelId: string; targetSessionKey: string; accountId?: string; maxAgeMs: number; }) => RuntimeThreadBindingLifecycleRecord[]; }; - discord: { - messageActions: DiscordRuntimeSurface["discordMessageActions"]; - auditChannelPermissions: DiscordRuntimeSurface["auditDiscordChannelPermissions"]; - listDirectoryGroupsLive: DiscordRuntimeSurface["listDiscordDirectoryGroupsLive"]; - listDirectoryPeersLive: DiscordRuntimeSurface["listDiscordDirectoryPeersLive"]; - probeDiscord: DiscordRuntimeSurface["probeDiscord"]; - resolveChannelAllowlist: DiscordRuntimeSurface["resolveDiscordChannelAllowlist"]; - resolveUserAllowlist: DiscordRuntimeSurface["resolveDiscordUserAllowlist"]; - sendComponentMessage: DiscordRuntimeSurface["sendDiscordComponentMessage"]; - sendMessageDiscord: DiscordRuntimeSurface["sendMessageDiscord"]; - sendPollDiscord: DiscordRuntimeSurface["sendPollDiscord"]; - monitorDiscordProvider: DiscordRuntimeSurface["monitorDiscordProvider"]; - threadBindings: { - getManager: DiscordThreadBindings["getThreadBindingManager"]; - resolveIdleTimeoutMs: DiscordThreadBindings["resolveThreadBindingIdleTimeoutMs"]; - resolveInactivityExpiresAt: DiscordThreadBindings["resolveThreadBindingInactivityExpiresAt"]; - resolveMaxAgeMs: DiscordThreadBindings["resolveThreadBindingMaxAgeMs"]; - resolveMaxAgeExpiresAt: DiscordThreadBindings["resolveThreadBindingMaxAgeExpiresAt"]; - setIdleTimeoutBySessionKey: DiscordThreadBindings["setThreadBindingIdleTimeoutBySessionKey"]; - setMaxAgeBySessionKey: DiscordThreadBindings["setThreadBindingMaxAgeBySessionKey"]; - unbindBySessionKey: DiscordThreadBindings["unbindThreadBindingsBySessionKey"]; - }; - typing: { - pulse: DiscordRuntimeSurface["sendTypingDiscord"]; - start: (params: { - channelId: string; - accountId?: string; - cfg?: ReturnType; - intervalMs?: number; - }) => Promise<{ - refresh: () => Promise; - stop: () => void; - }>; - }; - conversationActions: { - editMessage: DiscordRuntimeSurface["editMessageDiscord"]; - deleteMessage: DiscordRuntimeSurface["deleteMessageDiscord"]; - pinMessage: DiscordRuntimeSurface["pinMessageDiscord"]; - unpinMessage: DiscordRuntimeSurface["unpinMessageDiscord"]; - createThread: DiscordRuntimeSurface["createThreadDiscord"]; - editChannel: DiscordRuntimeSurface["editChannelDiscord"]; - }; - }; - slack: { - listDirectoryGroupsLive: typeof import("../../../extensions/slack/runtime-api.js").listSlackDirectoryGroupsLive; - listDirectoryPeersLive: typeof import("../../../extensions/slack/runtime-api.js").listSlackDirectoryPeersLive; - probeSlack: typeof import("../../../extensions/slack/runtime-api.js").probeSlack; - resolveChannelAllowlist: typeof import("../../../extensions/slack/runtime-api.js").resolveSlackChannelAllowlist; - resolveUserAllowlist: typeof import("../../../extensions/slack/runtime-api.js").resolveSlackUserAllowlist; - sendMessageSlack: typeof import("../../../extensions/slack/runtime-api.js").sendMessageSlack; - monitorSlackProvider: typeof import("../../../extensions/slack/runtime-api.js").monitorSlackProvider; - handleSlackAction: typeof import("../../../extensions/slack/runtime-api.js").handleSlackAction; - }; - matrix: { - threadBindings: { - setIdleTimeoutBySessionKey: MatrixThreadBindings["setMatrixThreadBindingIdleTimeoutBySessionKey"]; - setMaxAgeBySessionKey: MatrixThreadBindings["setMatrixThreadBindingMaxAgeBySessionKey"]; - }; - }; - signal: { - probeSignal: typeof import("../../../extensions/signal/runtime-api.js").probeSignal; - sendMessageSignal: typeof import("../../../extensions/signal/runtime-api.js").sendMessageSignal; - monitorSignalProvider: typeof import("../../../extensions/signal/runtime-api.js").monitorSignalProvider; - messageActions: typeof import("../../../extensions/signal/runtime-api.js").signalMessageActions; - }; - line: { - listLineAccountIds: typeof import("../../plugin-sdk/line.js").listLineAccountIds; - resolveDefaultLineAccountId: typeof import("../../plugin-sdk/line.js").resolveDefaultLineAccountId; - resolveLineAccount: typeof import("../../plugin-sdk/line.js").resolveLineAccount; - normalizeAccountId: typeof import("../../plugin-sdk/line.js").normalizeAccountId; - probeLineBot: typeof import("../../plugin-sdk/line-runtime.js").probeLineBot; - sendMessageLine: typeof import("../../plugin-sdk/line-runtime.js").sendMessageLine; - pushMessageLine: typeof import("../../plugin-sdk/line-runtime.js").pushMessageLine; - pushMessagesLine: typeof import("../../plugin-sdk/line-runtime.js").pushMessagesLine; - pushFlexMessage: typeof import("../../plugin-sdk/line-runtime.js").pushFlexMessage; - pushTemplateMessage: typeof import("../../plugin-sdk/line-runtime.js").pushTemplateMessage; - pushLocationMessage: typeof import("../../plugin-sdk/line-runtime.js").pushLocationMessage; - pushTextMessageWithQuickReplies: typeof import("../../plugin-sdk/line-runtime.js").pushTextMessageWithQuickReplies; - createQuickReplyItems: typeof import("../../plugin-sdk/line-runtime.js").createQuickReplyItems; - buildTemplateMessageFromPayload: typeof import("../../plugin-sdk/line-runtime.js").buildTemplateMessageFromPayload; - monitorLineProvider: typeof import("../../plugin-sdk/line-runtime.js").monitorLineProvider; - }; }; diff --git a/test/helpers/plugins/plugin-runtime-mock.ts b/test/helpers/plugins/plugin-runtime-mock.ts index ba5a96d92d8..a0c04a8875f 100644 --- a/test/helpers/plugins/plugin-runtime-mock.ts +++ b/test/helpers/plugins/plugin-runtime-mock.ts @@ -333,12 +333,7 @@ export function createPluginRuntimeMock(overrides: DeepPartial = setMaxAgeBySessionKey: vi.fn() as unknown as PluginRuntime["channel"]["threadBindings"]["setMaxAgeBySessionKey"], }, - discord: {} as PluginRuntime["channel"]["discord"], activity: {} as PluginRuntime["channel"]["activity"], - line: {} as PluginRuntime["channel"]["line"], - slack: {} as PluginRuntime["channel"]["slack"], - matrix: {} as PluginRuntime["channel"]["matrix"], - signal: {} as PluginRuntime["channel"]["signal"], }, events: { onAgentEvent: vi.fn(() => () => {}) as unknown as PluginRuntime["events"]["onAgentEvent"], diff --git a/tsdown.config.ts b/tsdown.config.ts index 2b052c74c3d..15d37cba952 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -128,7 +128,6 @@ function buildCoreDistEntries(): Record { "agents/pi-model-discovery-runtime": "src/agents/pi-model-discovery-runtime.ts", "commands/status.summary.runtime": "src/commands/status.summary.runtime.ts", "plugins/provider-runtime.runtime": "src/plugins/provider-runtime.runtime.ts", - "plugins/runtime/runtime-line.contract": "src/plugins/runtime/runtime-line.contract.ts", extensionAPI: "src/extensionAPI.ts", "infra/warning-filter": "src/infra/warning-filter.ts", "telegram/audit": bundledPluginFile("telegram", "src/audit.ts"),