From 8a731c1ef77bd5dc0f5e15f057f3bb078ce25ab5 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 25 Apr 2026 22:18:54 +0100 Subject: [PATCH] perf(plugin-sdk): add narrow outbound send deps entry --- docs/plugins/sdk-migration.md | 1 + docs/plugins/sdk-subpaths.md | 1 + extensions/discord/src/outbound-adapter.ts | 6 ++---- extensions/discord/src/outbound-payload.contract.test.ts | 2 +- extensions/discord/src/outbound-send-context.ts | 5 ++--- extensions/imessage/src/channel.runtime.ts | 2 +- extensions/imessage/src/imessage.test-plugin.ts | 2 +- extensions/matrix/src/runtime-api.ts | 2 +- extensions/msteams/src/outbound.ts | 2 +- extensions/signal/src/channel.ts | 2 +- extensions/slack/src/channel.ts | 2 +- extensions/slack/src/outbound-adapter.ts | 6 ++---- extensions/slack/src/outbound-payload.test-harness.ts | 2 +- extensions/telegram/src/channel.ts | 2 +- extensions/telegram/src/outbound-adapter.ts | 4 ++-- extensions/whatsapp/src/outbound-base.ts | 3 ++- extensions/whatsapp/src/outbound-payload.contract.test.ts | 2 +- extensions/zalo/src/outbound-payload.contract.test.ts | 2 +- extensions/zalouser/src/channel.sendpayload.test.ts | 2 +- package.json | 4 ++++ scripts/lib/plugin-sdk-entrypoints.json | 1 + src/plugin-sdk/outbound-send-deps.ts | 6 ++++++ 22 files changed, 35 insertions(+), 26 deletions(-) create mode 100644 src/plugin-sdk/outbound-send-deps.ts diff --git a/docs/plugins/sdk-migration.md b/docs/plugins/sdk-migration.md index bbf6cca7268..8569cf0e5c2 100644 --- a/docs/plugins/sdk-migration.md +++ b/docs/plugins/sdk-migration.md @@ -262,6 +262,7 @@ releases. | `plugin-sdk/inbound-reply-dispatch` | Inbound reply helpers | Shared record-and-dispatch helpers | | `plugin-sdk/messaging-targets` | Messaging target parsing | Target parsing/matching helpers | | `plugin-sdk/outbound-media` | Outbound media helpers | Shared outbound media loading | + | `plugin-sdk/outbound-send-deps` | Outbound send dependency helpers | Lightweight `resolveOutboundSendDep` lookup without importing the full outbound runtime | | `plugin-sdk/outbound-runtime` | Outbound runtime helpers | Outbound delivery, identity/send delegate, session, formatting, and payload planning helpers | | `plugin-sdk/thread-bindings-runtime` | Thread-binding helpers | Thread-binding lifecycle and adapter helpers | | `plugin-sdk/agent-media-payload` | Legacy media payload helpers | Agent media payload builder for legacy field layouts | diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index 1d5a0762a21..9b0a17a2dd3 100644 --- a/docs/plugins/sdk-subpaths.md +++ b/docs/plugins/sdk-subpaths.md @@ -50,6 +50,7 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview) | `plugin-sdk/inbound-reply-dispatch` | Shared inbound record-and-dispatch helpers | | `plugin-sdk/messaging-targets` | Target parsing/matching helpers | | `plugin-sdk/outbound-media` | Shared outbound media loading helpers | + | `plugin-sdk/outbound-send-deps` | Lightweight outbound send dependency lookup for channel adapters | | `plugin-sdk/outbound-runtime` | Outbound delivery, identity, send delegate, session, formatting, and payload planning helpers | | `plugin-sdk/poll-runtime` | Narrow poll normalization helpers | | `plugin-sdk/thread-bindings-runtime` | Thread-binding lifecycle and adapter helpers | diff --git a/extensions/discord/src/outbound-adapter.ts b/extensions/discord/src/outbound-adapter.ts index 2fbfa704c0d..51acf26d09f 100644 --- a/extensions/discord/src/outbound-adapter.ts +++ b/extensions/discord/src/outbound-adapter.ts @@ -3,10 +3,8 @@ import { createAttachedChannelResultAdapter, } from "openclaw/plugin-sdk/channel-send-result"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { - resolveOutboundSendDep, - type OutboundIdentity, -} from "openclaw/plugin-sdk/outbound-runtime"; +import type { OutboundIdentity } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import { normalizeOptionalString, normalizeOptionalStringifiedId, diff --git a/extensions/discord/src/outbound-payload.contract.test.ts b/extensions/discord/src/outbound-payload.contract.test.ts index 39157a61a33..a6349938103 100644 --- a/extensions/discord/src/outbound-payload.contract.test.ts +++ b/extensions/discord/src/outbound-payload.contract.test.ts @@ -2,7 +2,7 @@ import { installChannelOutboundPayloadContractSuite, primeChannelOutboundSendMock, type OutboundPayloadHarnessParams, -} from "openclaw/plugin-sdk/testing"; +} from "openclaw/plugin-sdk/channel-contract-testing"; import { describe, vi } from "vitest"; import { discordOutbound } from "./outbound-adapter.js"; diff --git a/extensions/discord/src/outbound-send-context.ts b/extensions/discord/src/outbound-send-context.ts index 519357f901b..d5098ca55fb 100644 --- a/extensions/discord/src/outbound-send-context.ts +++ b/extensions/discord/src/outbound-send-context.ts @@ -1,10 +1,9 @@ import type { OpenClawConfig, ReplyToMode } from "openclaw/plugin-sdk/config-runtime"; +import { createReplyToFanout, type ReplyToResolution } from "openclaw/plugin-sdk/outbound-runtime"; import { - createReplyToFanout, resolveOutboundSendDep, - type ReplyToResolution, type OutboundSendDeps, -} from "openclaw/plugin-sdk/outbound-runtime"; +} from "openclaw/plugin-sdk/outbound-send-deps"; import { normalizeOptionalStringifiedId } from "openclaw/plugin-sdk/text-runtime"; import { withDiscordDeliveryRetry } from "./delivery-retry.js"; diff --git a/extensions/imessage/src/channel.runtime.ts b/extensions/imessage/src/channel.runtime.ts index 6630ed5f8ca..ef4746088ff 100644 --- a/extensions/imessage/src/channel.runtime.ts +++ b/extensions/imessage/src/channel.runtime.ts @@ -1,4 +1,4 @@ -import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import type { ResolvedIMessageAccount } from "./accounts.js"; import { PAIRING_APPROVED_MESSAGE, resolveChannelMediaMaxBytes } from "./channel-api.js"; import type { ChannelPlugin } from "./channel-api.js"; diff --git a/extensions/imessage/src/imessage.test-plugin.ts b/extensions/imessage/src/imessage.test-plugin.ts index 5187106de35..8d4a5434751 100644 --- a/extensions/imessage/src/imessage.test-plugin.ts +++ b/extensions/imessage/src/imessage.test-plugin.ts @@ -1,6 +1,6 @@ import type { ChannelOutboundAdapter } from "openclaw/plugin-sdk/channel-contract"; import type { ChannelPlugin } from "openclaw/plugin-sdk/core"; -import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import { collectStatusIssuesFromLastError } from "openclaw/plugin-sdk/status-helpers"; import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime"; diff --git a/extensions/matrix/src/runtime-api.ts b/extensions/matrix/src/runtime-api.ts index 3113179bac3..0db659215fb 100644 --- a/extensions/matrix/src/runtime-api.ts +++ b/extensions/matrix/src/runtime-api.ts @@ -87,7 +87,7 @@ export { resolveThreadBindingIdleTimeoutMsForChannel, resolveThreadBindingMaxAgeMsForChannel, } from "openclaw/plugin-sdk/conversation-runtime"; -export { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; +export { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; export { resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing"; export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking"; export { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline"; diff --git a/extensions/msteams/src/outbound.ts b/extensions/msteams/src/outbound.ts index 2ecfbd5cc31..953206ec6e6 100644 --- a/extensions/msteams/src/outbound.ts +++ b/extensions/msteams/src/outbound.ts @@ -1,5 +1,5 @@ import { createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result"; -import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import { chunkTextForOutbound, type ChannelOutboundAdapter } from "../runtime-api.js"; import { createMSTeamsPollStoreFs } from "./polls.js"; import { sendMessageMSTeams, sendPollMSTeams } from "./send.js"; diff --git a/extensions/signal/src/channel.ts b/extensions/signal/src/channel.ts index 33c76530cec..2cf6bfc161c 100644 --- a/extensions/signal/src/channel.ts +++ b/extensions/signal/src/channel.ts @@ -9,7 +9,7 @@ import { import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status"; import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime"; import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime"; -import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import { chunkText, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking"; import { buildOutboundBaseSessionKey, type RoutePeer } from "openclaw/plugin-sdk/routing"; import { diff --git a/extensions/slack/src/channel.ts b/extensions/slack/src/channel.ts index 382a3b601e7..7be4621e20c 100644 --- a/extensions/slack/src/channel.ts +++ b/extensions/slack/src/channel.ts @@ -14,7 +14,7 @@ import { createRuntimeDirectoryLiveAdapter, } from "openclaw/plugin-sdk/directory-runtime"; import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; -import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import { buildOutboundBaseSessionKey, type RoutePeer } from "openclaw/plugin-sdk/routing"; import { createComputedAccountStatusAdapter, diff --git a/extensions/slack/src/outbound-adapter.ts b/extensions/slack/src/outbound-adapter.ts index d002b60329f..e5298767ecc 100644 --- a/extensions/slack/src/outbound-adapter.ts +++ b/extensions/slack/src/outbound-adapter.ts @@ -8,10 +8,8 @@ import { type InteractiveReply, type MessagePresentation, } from "openclaw/plugin-sdk/interactive-runtime"; -import { - resolveOutboundSendDep, - type OutboundIdentity, -} from "openclaw/plugin-sdk/outbound-runtime"; +import type { OutboundIdentity } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import { resolvePayloadMediaUrls, sendPayloadMediaSequenceAndFinalize, diff --git a/extensions/slack/src/outbound-payload.test-harness.ts b/extensions/slack/src/outbound-payload.test-harness.ts index 157bdcd9346..8a22a793e69 100644 --- a/extensions/slack/src/outbound-payload.test-harness.ts +++ b/extensions/slack/src/outbound-payload.test-harness.ts @@ -1,5 +1,5 @@ +import { primeChannelOutboundSendMock } from "openclaw/plugin-sdk/channel-contract-testing"; import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime"; -import { primeChannelOutboundSendMock } from "openclaw/plugin-sdk/testing"; import { vi, type Mock } from "vitest"; import { slackOutbound } from "./outbound-adapter.js"; diff --git a/extensions/telegram/src/channel.ts b/extensions/telegram/src/channel.ts index 81931e0c3cd..05489131eb3 100644 --- a/extensions/telegram/src/channel.ts +++ b/extensions/telegram/src/channel.ts @@ -25,7 +25,7 @@ import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime"; import { resolveOutboundSendDep, type OutboundSendDeps, -} from "openclaw/plugin-sdk/outbound-runtime"; +} from "openclaw/plugin-sdk/outbound-send-deps"; import { type RoutePeer } from "openclaw/plugin-sdk/routing"; import { createComputedAccountStatusAdapter, diff --git a/extensions/telegram/src/outbound-adapter.ts b/extensions/telegram/src/outbound-adapter.ts index ac8f4405ad2..4fb8d0395cd 100644 --- a/extensions/telegram/src/outbound-adapter.ts +++ b/extensions/telegram/src/outbound-adapter.ts @@ -8,11 +8,11 @@ import { renderMessagePresentationFallbackText, resolveInteractiveTextFallback, } from "openclaw/plugin-sdk/interactive-runtime"; +import { sanitizeForPlainText } from "openclaw/plugin-sdk/outbound-runtime"; import { resolveOutboundSendDep, - sanitizeForPlainText, type OutboundSendDeps, -} from "openclaw/plugin-sdk/outbound-runtime"; +} from "openclaw/plugin-sdk/outbound-send-deps"; import { resolvePayloadMediaUrls, sendPayloadMediaSequenceOrFallback, diff --git a/extensions/whatsapp/src/outbound-base.ts b/extensions/whatsapp/src/outbound-base.ts index 5741afd7df9..f3705d91fd1 100644 --- a/extensions/whatsapp/src/outbound-base.ts +++ b/extensions/whatsapp/src/outbound-base.ts @@ -9,7 +9,8 @@ import { type ChannelOutboundAdapter, } from "openclaw/plugin-sdk/channel-send-result"; import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime"; -import { resolveOutboundSendDep, sanitizeForPlainText } from "openclaw/plugin-sdk/outbound-runtime"; +import { sanitizeForPlainText } from "openclaw/plugin-sdk/outbound-runtime"; +import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps"; import { sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload"; import { normalizeWhatsAppOutboundPayload, diff --git a/extensions/whatsapp/src/outbound-payload.contract.test.ts b/extensions/whatsapp/src/outbound-payload.contract.test.ts index 559a1fd14e1..48ce7b8abf8 100644 --- a/extensions/whatsapp/src/outbound-payload.contract.test.ts +++ b/extensions/whatsapp/src/outbound-payload.contract.test.ts @@ -2,7 +2,7 @@ import { installChannelOutboundPayloadContractSuite, primeChannelOutboundSendMock, type OutboundPayloadHarnessParams, -} from "openclaw/plugin-sdk/testing"; +} from "openclaw/plugin-sdk/channel-contract-testing"; import { describe, expect, it, vi } from "vitest"; import { whatsappOutbound } from "./outbound-adapter.js"; diff --git a/extensions/zalo/src/outbound-payload.contract.test.ts b/extensions/zalo/src/outbound-payload.contract.test.ts index 8367c38d1b7..424c0d68a06 100644 --- a/extensions/zalo/src/outbound-payload.contract.test.ts +++ b/extensions/zalo/src/outbound-payload.contract.test.ts @@ -2,7 +2,7 @@ import { installChannelOutboundPayloadContractSuite, primeChannelOutboundSendMock, type OutboundPayloadHarnessParams, -} from "openclaw/plugin-sdk/testing"; +} from "openclaw/plugin-sdk/channel-contract-testing"; import { describe, vi } from "vitest"; import { zaloPlugin } from "./channel.js"; diff --git a/extensions/zalouser/src/channel.sendpayload.test.ts b/extensions/zalouser/src/channel.sendpayload.test.ts index 1407ecb5418..efb179b4860 100644 --- a/extensions/zalouser/src/channel.sendpayload.test.ts +++ b/extensions/zalouser/src/channel.sendpayload.test.ts @@ -2,7 +2,7 @@ import { installChannelOutboundPayloadContractSuite, primeChannelOutboundSendMock, type OutboundPayloadHarnessParams, -} from "openclaw/plugin-sdk/testing"; +} from "openclaw/plugin-sdk/channel-contract-testing"; import { beforeEach, describe, expect, it, vi } from "vitest"; import "./accounts.test-mocks.js"; import "./zalo-js.test-mocks.js"; diff --git a/package.json b/package.json index 7355ed59f0c..f6f5c139e67 100644 --- a/package.json +++ b/package.json @@ -238,6 +238,10 @@ "types": "./dist/plugin-sdk/outbound-media.d.ts", "default": "./dist/plugin-sdk/outbound-media.js" }, + "./plugin-sdk/outbound-send-deps": { + "types": "./dist/plugin-sdk/outbound-send-deps.d.ts", + "default": "./dist/plugin-sdk/outbound-send-deps.js" + }, "./plugin-sdk/outbound-runtime": { "types": "./dist/plugin-sdk/outbound-runtime.d.ts", "default": "./dist/plugin-sdk/outbound-runtime.js" diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index 959973a80b0..a6ab71c473d 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -45,6 +45,7 @@ "channel-runtime", "interactive-runtime", "outbound-media", + "outbound-send-deps", "outbound-runtime", "poll-runtime", "infra-runtime", diff --git a/src/plugin-sdk/outbound-send-deps.ts b/src/plugin-sdk/outbound-send-deps.ts new file mode 100644 index 00000000000..8148c6bf6b6 --- /dev/null +++ b/src/plugin-sdk/outbound-send-deps.ts @@ -0,0 +1,6 @@ +export { + resolveLegacyOutboundSendDepKeys, + resolveOutboundSendDep, + type OutboundSendDeps, + type ResolveOutboundSendDepOptions, +} from "../infra/outbound/send-deps.js";