diff --git a/CHANGELOG.md b/CHANGELOG.md index c29db34273e..dcef30232ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Docs: https://docs.openclaw.ai - Plugins/startup loading: lazily initialize plugin runtime, split startup-critical plugin SDK imports into `openclaw/plugin-sdk/core` and `openclaw/plugin-sdk/telegram`, and preserve `api.runtime` reflection semantics for plugin compatibility. (#28620) thanks @hmemcpy. - Build/lazy runtime boundaries: replace ineffective dynamic import sites with dedicated lazy runtime boundaries across Slack slash handling, Telegram audit, CLI send deps, memory fallback, and outbound delivery paths while preserving behavior. (#33690) thanks @gumadeiras. - Config/heartbeat legacy-path handling: auto-migrate top-level `heartbeat` into `agents.defaults.heartbeat` (with merge semantics that preserve explicit defaults), and keep startup failures on non-migratable legacy entries in the detailed invalid-config path instead of generic migration-failed errors. (#32706) thanks @xiwan. +- Plugins/SDK subpath parity: add channel-specific plugin SDK subpaths for Discord, Slack, Signal, iMessage, WhatsApp, and LINE; migrate bundled plugin entrypoints to scoped subpaths/core with CI guardrails; and keep `openclaw/plugin-sdk` root import compatibility for existing external plugins. (#33737) thanks @gumadeiras. - Security/auth labels: remove token and API-key snippets from user-facing auth status labels so `/status` and `/models` do not expose credential fragments. (#33262) thanks @cu1ch3n. - Auth/credential semantics: align profile eligibility + probe diagnostics with SecretRef/expiry rules and harden browser download atomic writes. (#33733) thanks @joshavant. - Security/audit denyCommands guidance: suggest likely exact node command IDs for unknown `gateway.nodes.denyCommands` entries so ineffective denylist entries are easier to correct. (#29713) thanks @liquidhorizon88-bot. diff --git a/docs/reference/plugin-sdk-bundled-parity.md b/docs/reference/plugin-sdk-bundled-parity.md new file mode 100644 index 00000000000..638424bd6bc --- /dev/null +++ b/docs/reference/plugin-sdk-bundled-parity.md @@ -0,0 +1,55 @@ +# Plugin SDK bundled parity tracker + +## Phase 0 baseline + +Collected on 2026-03-03 (local dev machine) before this migration wave. + +| scenario | load time ms | rss delta MiB | loaded plugins | +| -------------------------- | -----------: | ------------: | -------------: | +| default-bundled-enable-set | 90004.13 | 1065.53 | 4 | +| telegram-only | 158.80 | 0.00 | 5 | +| discord-only | 56.40 | 0.22 | 5 | +| slack-only | 46.68 | 0.00 | 5 | + +## Phase 3 rerun after migration + +Collected on 2026-03-03 after subpath wiring + bundled entrypoint migration. + +| scenario | load time ms | rss delta MiB | loaded plugins | +| -------------------------- | -----------: | ------------: | -------------: | +| default-bundled-enable-set | 1564.07 | 95.09 | 4 | +| telegram-only | 1539.78 | 33.33 | 5 | +| discord-only | 5341.77 | 17.11 | 5 | +| slack-only | 370.49 | 4.78 | 5 | + +Notes: + +- These local numbers are noisy and order-dependent. +- Keep CI or repeated local medians as the source of truth for hard budgets. + +## Bundled plugin inventory and migration status + +Status legend: + +- `channel-subpath`: imports `openclaw/plugin-sdk/` +- `core-entrypoint`: entrypoint imports `openclaw/plugin-sdk/core` +- `no-sdk-import`: entrypoint does not import plugin-sdk + +`channel-subpath` (7): +`discord`, `imessage`, `line`, `signal`, `slack`, `telegram`, `whatsapp` + +`core-entrypoint` (28): +`acpx`, `bluebubbles`, `copilot-proxy`, `device-pair`, `diagnostics-otel`, `diffs`, `feishu`, +`google-gemini-cli-auth`, `googlechat`, `irc`, `matrix`, `mattermost`, `memory-core`, +`memory-lancedb`, `minimax-portal-auth`, `msteams`, `nextcloud-talk`, `nostr`, `phone-control`, +`qwen-portal-auth`, `synology-chat`, `talk-voice`, `thread-ownership`, `tlon`, `twitch`, +`voice-call`, `zalo`, `zalouser` + +`no-sdk-import` (3): +`llm-task`, `lobster`, `open-prose` + +Deferred (future wave): + +- Non-entrypoint bundled plugin internals that still import monolithic + `openclaw/plugin-sdk` (for example Matrix, Feishu, MSTeams, Zalo, Zalouser, + Twitch, Tlon, and related tests/runtime files). diff --git a/docs/tools/plugin.md b/docs/tools/plugin.md index 90e1f461f4c..f5fd5a34ab6 100644 --- a/docs/tools/plugin.md +++ b/docs/tools/plugin.md @@ -106,6 +106,26 @@ Notes: - Uses core media-understanding audio configuration (`tools.media.audio`) and provider fallback order. - Returns `{ text: undefined }` when no transcription output is produced (for example skipped/unsupported input). +## Plugin SDK import paths + +Use SDK subpaths instead of the monolithic `openclaw/plugin-sdk` import when +authoring plugins: + +- `openclaw/plugin-sdk/core` for generic plugin APIs, provider auth types, and shared helpers. +- `openclaw/plugin-sdk/telegram` for Telegram channel plugins. +- `openclaw/plugin-sdk/discord` for Discord channel plugins. +- `openclaw/plugin-sdk/slack` for Slack channel plugins. +- `openclaw/plugin-sdk/signal` for Signal channel plugins. +- `openclaw/plugin-sdk/imessage` for iMessage channel plugins. +- `openclaw/plugin-sdk/whatsapp` for WhatsApp channel plugins. +- `openclaw/plugin-sdk/line` for LINE channel plugins. + +Compatibility note: + +- `openclaw/plugin-sdk` remains supported for existing external plugins. +- New and migrated bundled plugins should use channel subpaths (or `core`) to + keep startup imports scoped. + ## Discovery & precedence OpenClaw scans, in order: diff --git a/extensions/acpx/index.ts b/extensions/acpx/index.ts index 5f57e396f80..187dbacd765 100644 --- a/extensions/acpx/index.ts +++ b/extensions/acpx/index.ts @@ -1,4 +1,4 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; import { createAcpxPluginConfigSchema } from "./src/config.js"; import { createAcpxRuntimeService } from "./src/service.js"; diff --git a/extensions/bluebubbles/index.ts b/extensions/bluebubbles/index.ts index 92bacb8d51a..15d583bd342 100644 --- a/extensions/bluebubbles/index.ts +++ b/extensions/bluebubbles/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { bluebubblesPlugin } from "./src/channel.js"; import { setBlueBubblesRuntime } from "./src/runtime.js"; diff --git a/extensions/copilot-proxy/index.ts b/extensions/copilot-proxy/index.ts index b14684ab552..990752782e7 100644 --- a/extensions/copilot-proxy/index.ts +++ b/extensions/copilot-proxy/index.ts @@ -3,7 +3,7 @@ import { type OpenClawPluginApi, type ProviderAuthContext, type ProviderAuthResult, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/core"; const DEFAULT_BASE_URL = "http://localhost:3000/v1"; const DEFAULT_API_KEY = "n/a"; diff --git a/extensions/device-pair/notify.ts b/extensions/device-pair/notify.ts index 3430a89cfa4..da43d2dc273 100644 --- a/extensions/device-pair/notify.ts +++ b/extensions/device-pair/notify.ts @@ -1,7 +1,7 @@ import { promises as fs } from "node:fs"; import path from "node:path"; -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { listDevicePairing } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { listDevicePairing } from "openclaw/plugin-sdk/core"; const NOTIFY_STATE_FILE = "device-pair-notify.json"; const NOTIFY_POLL_INTERVAL_MS = 10_000; diff --git a/extensions/diagnostics-otel/index.ts b/extensions/diagnostics-otel/index.ts index 0b9c5318def..4c460a125d8 100644 --- a/extensions/diagnostics-otel/index.ts +++ b/extensions/diagnostics-otel/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { createDiagnosticsOtelService } from "./src/service.js"; const plugin = { diff --git a/extensions/diffs/index.ts b/extensions/diffs/index.ts index 945448656e2..ccd3ef77b5a 100644 --- a/extensions/diffs/index.ts +++ b/extensions/diffs/index.ts @@ -1,6 +1,6 @@ import path from "node:path"; -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/core"; import { diffsPluginConfigSchema, resolveDiffsPluginDefaults, diff --git a/extensions/discord/index.ts b/extensions/discord/index.ts index dcddde67c86..ad441b09bc1 100644 --- a/extensions/discord/index.ts +++ b/extensions/discord/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/discord"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/discord"; import { discordPlugin } from "./src/channel.js"; import { setDiscordRuntime } from "./src/runtime.js"; import { registerDiscordSubagentHooks } from "./src/subagent-hooks.js"; diff --git a/extensions/discord/src/channel.test.ts b/extensions/discord/src/channel.test.ts index b5981e77d93..0a4ead6c3fd 100644 --- a/extensions/discord/src/channel.test.ts +++ b/extensions/discord/src/channel.test.ts @@ -1,4 +1,4 @@ -import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk"; +import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk/discord"; import { describe, expect, it, vi } from "vitest"; import { discordPlugin } from "./channel.js"; import { setDiscordRuntime } from "./runtime.js"; diff --git a/extensions/discord/src/channel.ts b/extensions/discord/src/channel.ts index 3a36a61171d..bfc2b92db74 100644 --- a/extensions/discord/src/channel.ts +++ b/extensions/discord/src/channel.ts @@ -29,7 +29,7 @@ import { type ChannelMessageActionAdapter, type ChannelPlugin, type ResolvedDiscordAccount, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/discord"; import { getDiscordRuntime } from "./runtime.js"; const meta = getChatChannelMeta("discord"); diff --git a/extensions/discord/src/runtime.ts b/extensions/discord/src/runtime.ts index 5c3aa9f3676..506a81085ee 100644 --- a/extensions/discord/src/runtime.ts +++ b/extensions/discord/src/runtime.ts @@ -1,4 +1,4 @@ -import type { PluginRuntime } from "openclaw/plugin-sdk"; +import type { PluginRuntime } from "openclaw/plugin-sdk/discord"; let runtime: PluginRuntime | null = null; diff --git a/extensions/discord/src/subagent-hooks.test.ts b/extensions/discord/src/subagent-hooks.test.ts index f8a139cd56d..d58f07c1314 100644 --- a/extensions/discord/src/subagent-hooks.test.ts +++ b/extensions/discord/src/subagent-hooks.test.ts @@ -1,4 +1,4 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/discord"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { registerDiscordSubagentHooks } from "./subagent-hooks.js"; @@ -35,7 +35,7 @@ const hookMocks = vi.hoisted(() => ({ unbindThreadBindingsBySessionKey: vi.fn(() => []), })); -vi.mock("openclaw/plugin-sdk", () => ({ +vi.mock("openclaw/plugin-sdk/discord", () => ({ resolveDiscordAccount: hookMocks.resolveDiscordAccount, autoBindSpawnedDiscordSubagent: hookMocks.autoBindSpawnedDiscordSubagent, listThreadBindingsBySessionKey: hookMocks.listThreadBindingsBySessionKey, diff --git a/extensions/discord/src/subagent-hooks.ts b/extensions/discord/src/subagent-hooks.ts index 8ecd7873d88..f6e6056538b 100644 --- a/extensions/discord/src/subagent-hooks.ts +++ b/extensions/discord/src/subagent-hooks.ts @@ -1,10 +1,10 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/discord"; import { autoBindSpawnedDiscordSubagent, listThreadBindingsBySessionKey, resolveDiscordAccount, unbindThreadBindingsBySessionKey, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/discord"; function summarizeError(err: unknown): string { if (err instanceof Error) { diff --git a/extensions/feishu/index.ts b/extensions/feishu/index.ts index 5cb75ec6483..62f311262d7 100644 --- a/extensions/feishu/index.ts +++ b/extensions/feishu/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { registerFeishuBitableTools } from "./src/bitable.js"; import { feishuPlugin } from "./src/channel.js"; import { registerFeishuChatTools } from "./src/chat.js"; diff --git a/extensions/google-gemini-cli-auth/index.ts b/extensions/google-gemini-cli-auth/index.ts index 89b7c4d1cfb..254b3994bd5 100644 --- a/extensions/google-gemini-cli-auth/index.ts +++ b/extensions/google-gemini-cli-auth/index.ts @@ -3,7 +3,7 @@ import { emptyPluginConfigSchema, type OpenClawPluginApi, type ProviderAuthContext, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/core"; import { loginGeminiCliOAuth } from "./oauth.js"; const PROVIDER_ID = "google-gemini-cli"; diff --git a/extensions/googlechat/index.ts b/extensions/googlechat/index.ts index c5acead0f61..8bcb1f76e3a 100644 --- a/extensions/googlechat/index.ts +++ b/extensions/googlechat/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { googlechatDock, googlechatPlugin } from "./src/channel.js"; import { setGoogleChatRuntime } from "./src/runtime.js"; diff --git a/extensions/imessage/index.ts b/extensions/imessage/index.ts index 7eb0e80b070..cf0c6b3d8bd 100644 --- a/extensions/imessage/index.ts +++ b/extensions/imessage/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/imessage"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/imessage"; import { imessagePlugin } from "./src/channel.js"; import { setIMessageRuntime } from "./src/runtime.js"; diff --git a/extensions/imessage/src/channel.ts b/extensions/imessage/src/channel.ts index 36963ca981f..994df82c73f 100644 --- a/extensions/imessage/src/channel.ts +++ b/extensions/imessage/src/channel.ts @@ -26,7 +26,7 @@ import { setAccountEnabledInConfigSection, type ChannelPlugin, type ResolvedIMessageAccount, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/imessage"; import { getIMessageRuntime } from "./runtime.js"; const meta = getChatChannelMeta("imessage"); diff --git a/extensions/imessage/src/runtime.ts b/extensions/imessage/src/runtime.ts index ed41c9cb809..866d9c8d380 100644 --- a/extensions/imessage/src/runtime.ts +++ b/extensions/imessage/src/runtime.ts @@ -1,4 +1,4 @@ -import type { PluginRuntime } from "openclaw/plugin-sdk"; +import type { PluginRuntime } from "openclaw/plugin-sdk/imessage"; let runtime: PluginRuntime | null = null; diff --git a/extensions/irc/index.ts b/extensions/irc/index.ts index 2a64cbe8650..6c5e19f16e3 100644 --- a/extensions/irc/index.ts +++ b/extensions/irc/index.ts @@ -1,5 +1,5 @@ -import type { ChannelPlugin, OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { ChannelPlugin, OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { ircPlugin } from "./src/channel.js"; import { setIrcRuntime } from "./src/runtime.js"; diff --git a/extensions/line/index.ts b/extensions/line/index.ts index 3d90029c27b..961baf1f01b 100644 --- a/extensions/line/index.ts +++ b/extensions/line/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/line"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/line"; import { registerLineCardCommand } from "./src/card-command.js"; import { linePlugin } from "./src/channel.js"; import { setLineRuntime } from "./src/runtime.js"; diff --git a/extensions/line/src/card-command.ts b/extensions/line/src/card-command.ts index ff113b75e0a..cc5ec78eeab 100644 --- a/extensions/line/src/card-command.ts +++ b/extensions/line/src/card-command.ts @@ -1,4 +1,4 @@ -import type { LineChannelData, OpenClawPluginApi, ReplyPayload } from "openclaw/plugin-sdk"; +import type { LineChannelData, OpenClawPluginApi, ReplyPayload } from "openclaw/plugin-sdk/line"; import { createActionCard, createImageCard, @@ -7,7 +7,7 @@ import { createReceiptCard, type CardAction, type ListItem, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/line"; const CARD_USAGE = `Usage: /card "title" "body" [options] diff --git a/extensions/line/src/channel.logout.test.ts b/extensions/line/src/channel.logout.test.ts index b11bdc99870..b10d484fbb1 100644 --- a/extensions/line/src/channel.logout.test.ts +++ b/extensions/line/src/channel.logout.test.ts @@ -1,4 +1,4 @@ -import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount } from "openclaw/plugin-sdk"; +import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount } from "openclaw/plugin-sdk/line"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { createRuntimeEnv } from "../../test-utils/runtime-env.js"; import { linePlugin } from "./channel.js"; diff --git a/extensions/line/src/channel.sendPayload.test.ts b/extensions/line/src/channel.sendPayload.test.ts index 3f91f27c51f..e92551538e9 100644 --- a/extensions/line/src/channel.sendPayload.test.ts +++ b/extensions/line/src/channel.sendPayload.test.ts @@ -1,4 +1,4 @@ -import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk"; +import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk/line"; import { describe, expect, it, vi } from "vitest"; import { linePlugin } from "./channel.js"; import { setLineRuntime } from "./runtime.js"; diff --git a/extensions/line/src/channel.startup.test.ts b/extensions/line/src/channel.startup.test.ts index 09722277b17..e4de0f38e3b 100644 --- a/extensions/line/src/channel.startup.test.ts +++ b/extensions/line/src/channel.startup.test.ts @@ -4,7 +4,7 @@ import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/line"; import { describe, expect, it, vi } from "vitest"; import { createRuntimeEnv } from "../../test-utils/runtime-env.js"; import { linePlugin } from "./channel.js"; diff --git a/extensions/line/src/channel.ts b/extensions/line/src/channel.ts index 1c87ad8e2f3..f5a0f9de107 100644 --- a/extensions/line/src/channel.ts +++ b/extensions/line/src/channel.ts @@ -12,7 +12,7 @@ import { type LineConfig, type LineChannelData, type ResolvedLineAccount, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/line"; import { getLineRuntime } from "./runtime.js"; // LINE channel metadata diff --git a/extensions/line/src/runtime.ts b/extensions/line/src/runtime.ts index a352dfccdb8..4f1a4fc121a 100644 --- a/extensions/line/src/runtime.ts +++ b/extensions/line/src/runtime.ts @@ -1,4 +1,4 @@ -import type { PluginRuntime } from "openclaw/plugin-sdk"; +import type { PluginRuntime } from "openclaw/plugin-sdk/line"; let runtime: PluginRuntime | null = null; diff --git a/extensions/matrix/index.ts b/extensions/matrix/index.ts index f86706d53f5..320b256d3a2 100644 --- a/extensions/matrix/index.ts +++ b/extensions/matrix/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { matrixPlugin } from "./src/channel.js"; import { ensureMatrixCryptoRuntime } from "./src/matrix/deps.js"; import { setMatrixRuntime } from "./src/runtime.js"; diff --git a/extensions/mattermost/index.ts b/extensions/mattermost/index.ts index ae32fb61f77..75b28cc1559 100644 --- a/extensions/mattermost/index.ts +++ b/extensions/mattermost/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { mattermostPlugin } from "./src/channel.js"; import { getSlashCommandState, registerSlashCommandRoute } from "./src/mattermost/slash-state.js"; import { setMattermostRuntime } from "./src/runtime.js"; diff --git a/extensions/memory-lancedb/index.ts b/extensions/memory-lancedb/index.ts index f02115b1bf6..cbed48dd9ef 100644 --- a/extensions/memory-lancedb/index.ts +++ b/extensions/memory-lancedb/index.ts @@ -10,7 +10,7 @@ import { randomUUID } from "node:crypto"; import type * as LanceDB from "@lancedb/lancedb"; import { Type } from "@sinclair/typebox"; import OpenAI from "openai"; -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; import { DEFAULT_CAPTURE_MAX_CHARS, MEMORY_CATEGORIES, diff --git a/extensions/minimax-portal-auth/index.ts b/extensions/minimax-portal-auth/index.ts index 51c1b6e1ec1..731404eb867 100644 --- a/extensions/minimax-portal-auth/index.ts +++ b/extensions/minimax-portal-auth/index.ts @@ -3,7 +3,7 @@ import { type OpenClawPluginApi, type ProviderAuthContext, type ProviderAuthResult, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/core"; import { loginMiniMaxPortalOAuth, type MiniMaxRegion } from "./oauth.js"; const PROVIDER_ID = "minimax-portal"; diff --git a/extensions/msteams/index.ts b/extensions/msteams/index.ts index 6bab4723675..9d5fde61d4d 100644 --- a/extensions/msteams/index.ts +++ b/extensions/msteams/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { msteamsPlugin } from "./src/channel.js"; import { setMSTeamsRuntime } from "./src/runtime.js"; diff --git a/extensions/nextcloud-talk/index.ts b/extensions/nextcloud-talk/index.ts index 1dc9c2d646c..92e68fdcfb7 100644 --- a/extensions/nextcloud-talk/index.ts +++ b/extensions/nextcloud-talk/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { nextcloudTalkPlugin } from "./src/channel.js"; import { setNextcloudTalkRuntime } from "./src/runtime.js"; diff --git a/extensions/nostr/index.ts b/extensions/nostr/index.ts index de9c6e2276d..bcebb2fc06a 100644 --- a/extensions/nostr/index.ts +++ b/extensions/nostr/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { nostrPlugin } from "./src/channel.js"; import type { NostrProfile } from "./src/config-schema.js"; import { createNostrProfileHttpHandler } from "./src/nostr-profile-http.js"; diff --git a/extensions/qwen-portal-auth/index.ts b/extensions/qwen-portal-auth/index.ts index 541dd750e1d..6cbbe8dd9c8 100644 --- a/extensions/qwen-portal-auth/index.ts +++ b/extensions/qwen-portal-auth/index.ts @@ -2,7 +2,7 @@ import { emptyPluginConfigSchema, type OpenClawPluginApi, type ProviderAuthContext, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/core"; import { loginQwenPortalOAuth } from "./oauth.js"; const PROVIDER_ID = "qwen-portal"; diff --git a/extensions/signal/index.ts b/extensions/signal/index.ts index e1069e466e2..0a7b988d7f0 100644 --- a/extensions/signal/index.ts +++ b/extensions/signal/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/signal"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/signal"; import { signalPlugin } from "./src/channel.js"; import { setSignalRuntime } from "./src/runtime.js"; diff --git a/extensions/signal/src/channel.ts b/extensions/signal/src/channel.ts index 9a7a9aee13b..44f0bd43294 100644 --- a/extensions/signal/src/channel.ts +++ b/extensions/signal/src/channel.ts @@ -27,7 +27,7 @@ import { type ChannelMessageActionAdapter, type ChannelPlugin, type ResolvedSignalAccount, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/signal"; import { getSignalRuntime } from "./runtime.js"; const signalMessageActions: ChannelMessageActionAdapter = { diff --git a/extensions/signal/src/runtime.ts b/extensions/signal/src/runtime.ts index 8bc1d5e9e8d..21f90071ad8 100644 --- a/extensions/signal/src/runtime.ts +++ b/extensions/signal/src/runtime.ts @@ -1,4 +1,4 @@ -import type { PluginRuntime } from "openclaw/plugin-sdk"; +import type { PluginRuntime } from "openclaw/plugin-sdk/signal"; let runtime: PluginRuntime | null = null; diff --git a/extensions/slack/index.ts b/extensions/slack/index.ts index 6f5945616c7..57d855141be 100644 --- a/extensions/slack/index.ts +++ b/extensions/slack/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/slack"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/slack"; import { slackPlugin } from "./src/channel.js"; import { setSlackRuntime } from "./src/runtime.js"; diff --git a/extensions/slack/src/channel.test.ts b/extensions/slack/src/channel.test.ts index 4e04d6cf3b7..006054f0930 100644 --- a/extensions/slack/src/channel.test.ts +++ b/extensions/slack/src/channel.test.ts @@ -1,4 +1,4 @@ -import type { OpenClawConfig } from "openclaw/plugin-sdk"; +import type { OpenClawConfig } from "openclaw/plugin-sdk/slack"; import { describe, expect, it, vi } from "vitest"; const handleSlackActionMock = vi.fn(); diff --git a/extensions/slack/src/channel.ts b/extensions/slack/src/channel.ts index 6af8b382170..f5b073dc045 100644 --- a/extensions/slack/src/channel.ts +++ b/extensions/slack/src/channel.ts @@ -29,7 +29,7 @@ import { SlackConfigSchema, type ChannelPlugin, type ResolvedSlackAccount, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/slack"; import { getSlackRuntime } from "./runtime.js"; const meta = getChatChannelMeta("slack"); diff --git a/extensions/slack/src/runtime.ts b/extensions/slack/src/runtime.ts index 46777871f1a..02222d2b073 100644 --- a/extensions/slack/src/runtime.ts +++ b/extensions/slack/src/runtime.ts @@ -1,4 +1,4 @@ -import type { PluginRuntime } from "openclaw/plugin-sdk"; +import type { PluginRuntime } from "openclaw/plugin-sdk/slack"; let runtime: PluginRuntime | null = null; diff --git a/extensions/synology-chat/index.ts b/extensions/synology-chat/index.ts index 6b85059761a..87b752bbb33 100644 --- a/extensions/synology-chat/index.ts +++ b/extensions/synology-chat/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { createSynologyChatPlugin } from "./src/channel.js"; import { setSynologyRuntime } from "./src/runtime.js"; diff --git a/extensions/thread-ownership/index.ts b/extensions/thread-ownership/index.ts index 3db1ea94ff4..1960b067f28 100644 --- a/extensions/thread-ownership/index.ts +++ b/extensions/thread-ownership/index.ts @@ -1,4 +1,4 @@ -import type { OpenClawConfig, OpenClawPluginApi } from "openclaw/plugin-sdk"; +import type { OpenClawConfig, OpenClawPluginApi } from "openclaw/plugin-sdk/core"; type ThreadOwnershipConfig = { forwarderUrl?: string; diff --git a/extensions/tlon/index.ts b/extensions/tlon/index.ts index 1cbcd35bc4c..5179c74c61d 100644 --- a/extensions/tlon/index.ts +++ b/extensions/tlon/index.ts @@ -2,8 +2,8 @@ import { spawn } from "node:child_process"; import { existsSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { tlonPlugin } from "./src/channel.js"; import { setTlonRuntime } from "./src/runtime.js"; diff --git a/extensions/twitch/index.ts b/extensions/twitch/index.ts index 992e7f3ea24..7cf7b7f85e8 100644 --- a/extensions/twitch/index.ts +++ b/extensions/twitch/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { twitchPlugin } from "./src/plugin.js"; import { setTwitchRuntime } from "./src/runtime.js"; diff --git a/extensions/voice-call/index.ts b/extensions/voice-call/index.ts index 0aadec4e18b..1e97ec5fac3 100644 --- a/extensions/voice-call/index.ts +++ b/extensions/voice-call/index.ts @@ -1,5 +1,5 @@ import { Type } from "@sinclair/typebox"; -import type { GatewayRequestHandlerOptions, OpenClawPluginApi } from "openclaw/plugin-sdk"; +import type { GatewayRequestHandlerOptions, OpenClawPluginApi } from "openclaw/plugin-sdk/core"; import { registerVoiceCallCli } from "./src/cli.js"; import { VoiceCallConfigSchema, diff --git a/extensions/whatsapp/index.ts b/extensions/whatsapp/index.ts index 1b19ff6775d..9279a2c038d 100644 --- a/extensions/whatsapp/index.ts +++ b/extensions/whatsapp/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/whatsapp"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/whatsapp"; import { whatsappPlugin } from "./src/channel.js"; import { setWhatsAppRuntime } from "./src/runtime.js"; diff --git a/extensions/whatsapp/src/channel.ts b/extensions/whatsapp/src/channel.ts index 67d270d093e..ef36857d899 100644 --- a/extensions/whatsapp/src/channel.ts +++ b/extensions/whatsapp/src/channel.ts @@ -33,7 +33,7 @@ import { type ChannelMessageActionName, type ChannelPlugin, type ResolvedWhatsAppAccount, -} from "openclaw/plugin-sdk"; +} from "openclaw/plugin-sdk/whatsapp"; import { getWhatsAppRuntime } from "./runtime.js"; const meta = getChatChannelMeta("whatsapp"); diff --git a/extensions/whatsapp/src/resolve-target.test.ts b/extensions/whatsapp/src/resolve-target.test.ts index 51bcd15bad3..f779a8e07b6 100644 --- a/extensions/whatsapp/src/resolve-target.test.ts +++ b/extensions/whatsapp/src/resolve-target.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it, vi } from "vitest"; import { installCommonResolveTargetErrorCases } from "../../shared/resolve-target-test-helpers.js"; -vi.mock("openclaw/plugin-sdk", () => ({ +vi.mock("openclaw/plugin-sdk/whatsapp", () => ({ getChatChannelMeta: () => ({ id: "whatsapp", label: "WhatsApp" }), normalizeWhatsAppTarget: (value: string) => { if (value === "invalid-target") return null; diff --git a/extensions/whatsapp/src/runtime.ts b/extensions/whatsapp/src/runtime.ts index 7f79e3ef016..490c7873219 100644 --- a/extensions/whatsapp/src/runtime.ts +++ b/extensions/whatsapp/src/runtime.ts @@ -1,4 +1,4 @@ -import type { PluginRuntime } from "openclaw/plugin-sdk"; +import type { PluginRuntime } from "openclaw/plugin-sdk/whatsapp"; let runtime: PluginRuntime | null = null; diff --git a/extensions/zalo/index.ts b/extensions/zalo/index.ts index 2b8f11b0b1d..ccdc4aaacad 100644 --- a/extensions/zalo/index.ts +++ b/extensions/zalo/index.ts @@ -1,5 +1,5 @@ -import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { zaloDock, zaloPlugin } from "./src/channel.js"; import { setZaloRuntime } from "./src/runtime.js"; diff --git a/extensions/zalouser/index.ts b/extensions/zalouser/index.ts index 0867197b995..6b5d470b85d 100644 --- a/extensions/zalouser/index.ts +++ b/extensions/zalouser/index.ts @@ -1,5 +1,5 @@ -import type { AnyAgentTool, OpenClawPluginApi } from "openclaw/plugin-sdk"; -import { emptyPluginConfigSchema } from "openclaw/plugin-sdk"; +import type { AnyAgentTool, OpenClawPluginApi } from "openclaw/plugin-sdk/core"; +import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/core"; import { zalouserDock, zalouserPlugin } from "./src/channel.js"; import { setZalouserRuntime } from "./src/runtime.js"; import { ZalouserToolSchema, executeZalouserTool } from "./src/tool.js"; diff --git a/package.json b/package.json index 2b58d97c305..4e8c9bbc7e4 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,30 @@ "types": "./dist/plugin-sdk/telegram.d.ts", "default": "./dist/plugin-sdk/telegram.js" }, + "./plugin-sdk/discord": { + "types": "./dist/plugin-sdk/discord.d.ts", + "default": "./dist/plugin-sdk/discord.js" + }, + "./plugin-sdk/slack": { + "types": "./dist/plugin-sdk/slack.d.ts", + "default": "./dist/plugin-sdk/slack.js" + }, + "./plugin-sdk/signal": { + "types": "./dist/plugin-sdk/signal.d.ts", + "default": "./dist/plugin-sdk/signal.js" + }, + "./plugin-sdk/imessage": { + "types": "./dist/plugin-sdk/imessage.d.ts", + "default": "./dist/plugin-sdk/imessage.js" + }, + "./plugin-sdk/whatsapp": { + "types": "./dist/plugin-sdk/whatsapp.d.ts", + "default": "./dist/plugin-sdk/whatsapp.js" + }, + "./plugin-sdk/line": { + "types": "./dist/plugin-sdk/line.d.ts", + "default": "./dist/plugin-sdk/line.js" + }, "./plugin-sdk/account-id": { "types": "./dist/plugin-sdk/account-id.d.ts", "default": "./dist/plugin-sdk/account-id.js" @@ -71,7 +95,7 @@ "build:plugin-sdk:dts": "tsc -p tsconfig.plugin-sdk.dts.json", "build:strict-smoke": "pnpm canvas:a2ui:bundle && tsdown && pnpm build:plugin-sdk:dts", "canvas:a2ui:bundle": "bash scripts/bundle-a2ui.sh", - "check": "pnpm format:check && pnpm tsgo && pnpm lint && pnpm lint:tmp:no-random-messaging && pnpm lint:tmp:channel-agnostic-boundaries && pnpm lint:tmp:no-raw-channel-fetch && pnpm lint:agent:ingress-owner && pnpm lint:plugins:no-register-http-handler && pnpm lint:webhook:no-low-level-body-read && pnpm lint:auth:no-pairing-store-group && pnpm lint:auth:pairing-account-scope && pnpm check:host-env-policy:swift", + "check": "pnpm format:check && pnpm tsgo && pnpm lint && pnpm lint:tmp:no-random-messaging && pnpm lint:tmp:channel-agnostic-boundaries && pnpm lint:tmp:no-raw-channel-fetch && pnpm lint:agent:ingress-owner && pnpm lint:plugins:no-register-http-handler && pnpm lint:plugins:no-monolithic-plugin-sdk-entry-imports && pnpm lint:webhook:no-low-level-body-read && pnpm lint:auth:no-pairing-store-group && pnpm lint:auth:pairing-account-scope && pnpm check:host-env-policy:swift", "check:docs": "pnpm format:docs:check && pnpm lint:docs && pnpm docs:check-links", "check:host-env-policy:swift": "node scripts/generate-host-env-security-policy-swift.mjs --check", "check:loc": "node --import tsx scripts/check-ts-max-loc.ts --max 500", @@ -115,6 +139,7 @@ "lint:docs": "pnpm dlx markdownlint-cli2", "lint:docs:fix": "pnpm dlx markdownlint-cli2 --fix", "lint:fix": "oxlint --type-aware --fix && pnpm format", + "lint:plugins:no-monolithic-plugin-sdk-entry-imports": "node --import tsx scripts/check-no-monolithic-plugin-sdk-entry-imports.ts", "lint:plugins:no-register-http-handler": "node scripts/check-no-register-http-handler.mjs", "lint:swift": "swiftlint lint --config .swiftlint.yml && (cd apps/ios && swiftlint lint --config .swiftlint.yml)", "lint:tmp:channel-agnostic-boundaries": "node scripts/check-channel-agnostic-boundaries.mjs", diff --git a/scripts/check-no-monolithic-plugin-sdk-entry-imports.ts b/scripts/check-no-monolithic-plugin-sdk-entry-imports.ts new file mode 100644 index 00000000000..c960c864f9a --- /dev/null +++ b/scripts/check-no-monolithic-plugin-sdk-entry-imports.ts @@ -0,0 +1,41 @@ +import fs from "node:fs"; +import path from "node:path"; +import { discoverOpenClawPlugins } from "../src/plugins/discovery.js"; + +const ROOT_IMPORT_PATTERN = /\b(?:import|export)\b[\s\S]*?\bfrom\s+["']openclaw\/plugin-sdk["']/g; + +function main() { + const discovery = discoverOpenClawPlugins({}); + const bundledEntryFiles = [ + ...new Set(discovery.candidates.filter((c) => c.origin === "bundled").map((c) => c.source)), + ]; + + const offenders: string[] = []; + for (const entryFile of bundledEntryFiles) { + let content = ""; + try { + content = fs.readFileSync(entryFile, "utf8"); + } catch { + continue; + } + if (ROOT_IMPORT_PATTERN.test(content)) { + offenders.push(entryFile); + } + } + + if (offenders.length > 0) { + console.error("Bundled plugin entrypoints must not import monolithic openclaw/plugin-sdk."); + for (const file of offenders.toSorted()) { + const relative = path.relative(process.cwd(), file) || file; + console.error(`- ${relative}`); + } + console.error("Use openclaw/plugin-sdk/ for channel plugins or /core for others."); + process.exit(1); + } + + console.log( + `OK: bundled entrypoints use scoped plugin-sdk subpaths (${bundledEntryFiles.length} checked).`, + ); +} + +main(); diff --git a/scripts/check-plugin-sdk-exports.mjs b/scripts/check-plugin-sdk-exports.mjs index 51f58b8aa6b..74da33f2d04 100755 --- a/scripts/check-plugin-sdk-exports.mjs +++ b/scripts/check-plugin-sdk-exports.mjs @@ -41,6 +41,18 @@ const exportedNames = exportMatch[1] const exportSet = new Set(exportedNames); +const requiredSubpathEntries = [ + "core", + "telegram", + "discord", + "slack", + "signal", + "imessage", + "whatsapp", + "line", + "account-id", +]; + // Critical functions that channel extension plugins import from openclaw/plugin-sdk. // If any of these are missing, plugins will fail at runtime with: // TypeError: (0 , _pluginSdk.) is not a function @@ -76,6 +88,19 @@ for (const name of requiredExports) { } } +for (const entry of requiredSubpathEntries) { + const jsPath = resolve(__dirname, "..", "dist", "plugin-sdk", `${entry}.js`); + const dtsPath = resolve(__dirname, "..", "dist", "plugin-sdk", `${entry}.d.ts`); + if (!existsSync(jsPath)) { + console.error(`MISSING SUBPATH JS: dist/plugin-sdk/${entry}.js`); + missing += 1; + } + if (!existsSync(dtsPath)) { + console.error(`MISSING SUBPATH DTS: dist/plugin-sdk/${entry}.d.ts`); + missing += 1; + } +} + if (missing > 0) { console.error(`\nERROR: ${missing} required export(s) missing from dist/plugin-sdk/index.js.`); console.error("This will break channel extension plugins at runtime."); diff --git a/scripts/release-check.ts b/scripts/release-check.ts index 03ceff6b94e..d4f302a824b 100755 --- a/scripts/release-check.ts +++ b/scripts/release-check.ts @@ -14,6 +14,22 @@ const requiredPathGroups = [ ["dist/entry.js", "dist/entry.mjs"], "dist/plugin-sdk/index.js", "dist/plugin-sdk/index.d.ts", + "dist/plugin-sdk/core.js", + "dist/plugin-sdk/core.d.ts", + "dist/plugin-sdk/telegram.js", + "dist/plugin-sdk/telegram.d.ts", + "dist/plugin-sdk/discord.js", + "dist/plugin-sdk/discord.d.ts", + "dist/plugin-sdk/slack.js", + "dist/plugin-sdk/slack.d.ts", + "dist/plugin-sdk/signal.js", + "dist/plugin-sdk/signal.d.ts", + "dist/plugin-sdk/imessage.js", + "dist/plugin-sdk/imessage.d.ts", + "dist/plugin-sdk/whatsapp.js", + "dist/plugin-sdk/whatsapp.d.ts", + "dist/plugin-sdk/line.js", + "dist/plugin-sdk/line.d.ts", "dist/build-info.json", ]; const forbiddenPrefixes = ["dist/OpenClaw.app/"]; diff --git a/scripts/write-plugin-sdk-entry-dts.ts b/scripts/write-plugin-sdk-entry-dts.ts index 58cea44ab21..611ec4dfe86 100644 --- a/scripts/write-plugin-sdk-entry-dts.ts +++ b/scripts/write-plugin-sdk-entry-dts.ts @@ -6,7 +6,18 @@ import path from "node:path"; // // Our package export map points subpath `types` at `dist/plugin-sdk/.d.ts`, so we // generate stable entry d.ts files that re-export the real declarations. -const entrypoints = ["index", "core", "telegram", "account-id"] as const; +const entrypoints = [ + "index", + "core", + "telegram", + "discord", + "slack", + "signal", + "imessage", + "whatsapp", + "line", + "account-id", +] as const; for (const entry of entrypoints) { const out = path.join(process.cwd(), `dist/plugin-sdk/${entry}.d.ts`); fs.mkdirSync(path.dirname(out), { recursive: true }); diff --git a/src/plugin-sdk/core.ts b/src/plugin-sdk/core.ts index 97960f925a0..d70ea17738f 100644 --- a/src/plugin-sdk/core.ts +++ b/src/plugin-sdk/core.ts @@ -1,8 +1,17 @@ -export type { OpenClawPluginApi, OpenClawPluginService } from "../plugins/types.js"; +export type { + AnyAgentTool, + OpenClawPluginApi, + OpenClawPluginService, + ProviderAuthContext, + ProviderAuthResult, +} from "../plugins/types.js"; export type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; export type { PluginRuntime } from "../plugins/runtime/types.js"; +export type { OpenClawConfig } from "../config/config.js"; +export type { GatewayRequestHandlerOptions } from "../gateway/server-methods/types.js"; export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; +export { buildOauthProviderAuthResult } from "./provider-auth-result.js"; export { approveDevicePairing, @@ -15,6 +24,7 @@ export { type PluginCommandRunOptions, type PluginCommandRunResult, } from "./run-command.js"; +export { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js"; export { resolveGatewayBindUrl } from "../shared/gateway-bind-url.js"; export type { GatewayBindUrlResult } from "../shared/gateway-bind-url.js"; diff --git a/src/plugin-sdk/discord.ts b/src/plugin-sdk/discord.ts new file mode 100644 index 00000000000..26a7b5c5031 --- /dev/null +++ b/src/plugin-sdk/discord.ts @@ -0,0 +1,60 @@ +export type { ChannelMessageActionAdapter } from "../channels/plugins/types.js"; +export type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; +export type { OpenClawConfig } from "../config/config.js"; +export type { ResolvedDiscordAccount } from "../discord/accounts.js"; +export type { PluginRuntime } from "../plugins/runtime/types.js"; +export type { OpenClawPluginApi } from "../plugins/types.js"; + +export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; + +export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js"; + +export { + applyAccountNameToChannelSection, + migrateBaseNameToDefaultAccount, +} from "../channels/plugins/setup-helpers.js"; +export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; +export { + deleteAccountFromConfigSection, + setAccountEnabledInConfigSection, +} from "../channels/plugins/config-helpers.js"; +export { formatPairingApproveHint } from "../channels/plugins/helpers.js"; +export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js"; + +export { getChatChannelMeta } from "../channels/registry.js"; + +export { + listDiscordAccountIds, + resolveDefaultDiscordAccountId, + resolveDiscordAccount, +} from "../discord/accounts.js"; +export { + listDiscordDirectoryGroupsFromConfig, + listDiscordDirectoryPeersFromConfig, +} from "../channels/plugins/directory-config.js"; +export { + looksLikeDiscordTargetId, + normalizeDiscordMessagingTarget, + normalizeDiscordOutboundTarget, +} from "../channels/plugins/normalize/discord.js"; +export { collectDiscordAuditChannelIds } from "../discord/audit.js"; +export { collectDiscordStatusIssues } from "../channels/plugins/status-issues/discord.js"; + +export { + resolveDefaultGroupPolicy, + resolveOpenProviderRuntimeGroupPolicy, +} from "../config/runtime-group-policy.js"; +export { + resolveDiscordGroupRequireMention, + resolveDiscordGroupToolPolicy, +} from "../channels/plugins/group-mentions.js"; +export { discordOnboardingAdapter } from "../channels/plugins/onboarding/discord.js"; +export { DiscordConfigSchema } from "../config/zod-schema.providers-core.js"; + +export { + autoBindSpawnedDiscordSubagent, + listThreadBindingsBySessionKey, + unbindThreadBindingsBySessionKey, +} from "../discord/monitor/thread-bindings.js"; + +export { buildTokenChannelStatusSummary } from "./status-helpers.js"; diff --git a/src/plugin-sdk/imessage.ts b/src/plugin-sdk/imessage.ts new file mode 100644 index 00000000000..7e31560991d --- /dev/null +++ b/src/plugin-sdk/imessage.ts @@ -0,0 +1,49 @@ +export type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; +export type { ResolvedIMessageAccount } from "../imessage/accounts.js"; +export type { PluginRuntime } from "../plugins/runtime/types.js"; +export type { OpenClawPluginApi } from "../plugins/types.js"; + +export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; + +export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js"; + +export { + applyAccountNameToChannelSection, + migrateBaseNameToDefaultAccount, +} from "../channels/plugins/setup-helpers.js"; +export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; +export { + deleteAccountFromConfigSection, + setAccountEnabledInConfigSection, +} from "../channels/plugins/config-helpers.js"; +export { formatPairingApproveHint } from "../channels/plugins/helpers.js"; +export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js"; + +export { getChatChannelMeta } from "../channels/registry.js"; +export { + listIMessageAccountIds, + resolveDefaultIMessageAccountId, + resolveIMessageAccount, +} from "../imessage/accounts.js"; +export { + formatTrimmedAllowFromEntries, + resolveIMessageConfigAllowFrom, + resolveIMessageConfigDefaultTo, +} from "./channel-config-helpers.js"; +export { + looksLikeIMessageTargetId, + normalizeIMessageMessagingTarget, +} from "../channels/plugins/normalize/imessage.js"; + +export { + resolveAllowlistProviderRuntimeGroupPolicy, + resolveDefaultGroupPolicy, +} from "../config/runtime-group-policy.js"; +export { + resolveIMessageGroupRequireMention, + resolveIMessageGroupToolPolicy, +} from "../channels/plugins/group-mentions.js"; +export { imessageOnboardingAdapter } from "../channels/plugins/onboarding/imessage.js"; +export { IMessageConfigSchema } from "../config/zod-schema.providers-core.js"; + +export { resolveChannelMediaMaxBytes } from "../channels/plugins/media-limits.js"; diff --git a/src/plugin-sdk/line.ts b/src/plugin-sdk/line.ts new file mode 100644 index 00000000000..f7f6a3eeb37 --- /dev/null +++ b/src/plugin-sdk/line.ts @@ -0,0 +1,36 @@ +export type { + ChannelAccountSnapshot, + ChannelGatewayContext, + ChannelStatusIssue, +} from "../channels/plugins/types.js"; +export type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; +export type { OpenClawConfig } from "../config/config.js"; +export type { ReplyPayload } from "../auto-reply/types.js"; +export type { PluginRuntime } from "../plugins/runtime/types.js"; +export type { OpenClawPluginApi } from "../plugins/types.js"; + +export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; + +export { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js"; + +export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; + +export { + resolveAllowlistProviderRuntimeGroupPolicy, + resolveDefaultGroupPolicy, +} from "../config/runtime-group-policy.js"; + +export { buildTokenChannelStatusSummary } from "./status-helpers.js"; + +export { LineConfigSchema } from "../line/config-schema.js"; +export type { LineChannelData, LineConfig, ResolvedLineAccount } from "../line/types.js"; +export { + createActionCard, + createImageCard, + createInfoCard, + createListCard, + createReceiptCard, + type CardAction, + type ListItem, +} from "../line/flex-templates.js"; +export { processLineMessage } from "../line/markdown-to-line.js"; diff --git a/src/plugin-sdk/signal.ts b/src/plugin-sdk/signal.ts new file mode 100644 index 00000000000..d15d35ee1dc --- /dev/null +++ b/src/plugin-sdk/signal.ts @@ -0,0 +1,49 @@ +export type { ChannelMessageActionAdapter } from "../channels/plugins/types.js"; +export type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; +export type { ResolvedSignalAccount } from "../signal/accounts.js"; +export type { PluginRuntime } from "../plugins/runtime/types.js"; +export type { OpenClawPluginApi } from "../plugins/types.js"; + +export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; + +export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js"; + +export { + applyAccountNameToChannelSection, + migrateBaseNameToDefaultAccount, +} from "../channels/plugins/setup-helpers.js"; +export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; +export { + deleteAccountFromConfigSection, + setAccountEnabledInConfigSection, +} from "../channels/plugins/config-helpers.js"; +export { formatPairingApproveHint } from "../channels/plugins/helpers.js"; +export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js"; + +export { getChatChannelMeta } from "../channels/registry.js"; +export { + listSignalAccountIds, + resolveDefaultSignalAccountId, + resolveSignalAccount, +} from "../signal/accounts.js"; +export { + looksLikeSignalTargetId, + normalizeSignalMessagingTarget, +} from "../channels/plugins/normalize/signal.js"; + +export { + resolveAllowlistProviderRuntimeGroupPolicy, + resolveDefaultGroupPolicy, +} from "../config/runtime-group-policy.js"; +export { signalOnboardingAdapter } from "../channels/plugins/onboarding/signal.js"; +export { SignalConfigSchema } from "../config/zod-schema.providers-core.js"; + +export { normalizeE164 } from "../utils.js"; +export { resolveChannelMediaMaxBytes } from "../channels/plugins/media-limits.js"; + +export { + buildBaseAccountStatusSnapshot, + buildBaseChannelStatusSummary, + collectStatusIssuesFromLastError, + createDefaultChannelRuntimeState, +} from "./status-helpers.js"; diff --git a/src/plugin-sdk/slack.ts b/src/plugin-sdk/slack.ts new file mode 100644 index 00000000000..af338f46b70 --- /dev/null +++ b/src/plugin-sdk/slack.ts @@ -0,0 +1,52 @@ +export type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; +export type { OpenClawConfig } from "../config/config.js"; +export type { ResolvedSlackAccount } from "../slack/accounts.js"; +export type { PluginRuntime } from "../plugins/runtime/types.js"; +export type { OpenClawPluginApi } from "../plugins/types.js"; + +export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; + +export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js"; + +export { + applyAccountNameToChannelSection, + migrateBaseNameToDefaultAccount, +} from "../channels/plugins/setup-helpers.js"; +export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; +export { + deleteAccountFromConfigSection, + setAccountEnabledInConfigSection, +} from "../channels/plugins/config-helpers.js"; +export { formatPairingApproveHint } from "../channels/plugins/helpers.js"; +export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js"; + +export { getChatChannelMeta } from "../channels/registry.js"; +export { + listSlackAccountIds, + resolveDefaultSlackAccountId, + resolveSlackAccount, + resolveSlackReplyToMode, +} from "../slack/accounts.js"; +export { + listSlackDirectoryGroupsFromConfig, + listSlackDirectoryPeersFromConfig, +} from "../channels/plugins/directory-config.js"; +export { + looksLikeSlackTargetId, + normalizeSlackMessagingTarget, +} from "../channels/plugins/normalize/slack.js"; +export { extractSlackToolSend, listSlackMessageActions } from "../slack/message-actions.js"; +export { buildSlackThreadingToolContext } from "../slack/threading-tool-context.js"; + +export { + resolveDefaultGroupPolicy, + resolveOpenProviderRuntimeGroupPolicy, +} from "../config/runtime-group-policy.js"; +export { + resolveSlackGroupRequireMention, + resolveSlackGroupToolPolicy, +} from "../channels/plugins/group-mentions.js"; +export { slackOnboardingAdapter } from "../channels/plugins/onboarding/slack.js"; +export { SlackConfigSchema } from "../config/zod-schema.providers-core.js"; + +export { handleSlackMessageAction } from "./slack-message-actions.js"; diff --git a/src/plugin-sdk/subpaths.test.ts b/src/plugin-sdk/subpaths.test.ts new file mode 100644 index 00000000000..80a2d2ffaf1 --- /dev/null +++ b/src/plugin-sdk/subpaths.test.ts @@ -0,0 +1,39 @@ +import * as discordSdk from "openclaw/plugin-sdk/discord"; +import * as imessageSdk from "openclaw/plugin-sdk/imessage"; +import * as lineSdk from "openclaw/plugin-sdk/line"; +import * as signalSdk from "openclaw/plugin-sdk/signal"; +import * as slackSdk from "openclaw/plugin-sdk/slack"; +import * as whatsappSdk from "openclaw/plugin-sdk/whatsapp"; +import { describe, expect, it } from "vitest"; + +describe("plugin-sdk subpath exports", () => { + it("exports Discord helpers", () => { + expect(typeof discordSdk.resolveDiscordAccount).toBe("function"); + expect(typeof discordSdk.discordOnboardingAdapter).toBe("object"); + }); + + it("exports Slack helpers", () => { + expect(typeof slackSdk.resolveSlackAccount).toBe("function"); + expect(typeof slackSdk.handleSlackMessageAction).toBe("function"); + }); + + it("exports Signal helpers", () => { + expect(typeof signalSdk.resolveSignalAccount).toBe("function"); + expect(typeof signalSdk.signalOnboardingAdapter).toBe("object"); + }); + + it("exports iMessage helpers", () => { + expect(typeof imessageSdk.resolveIMessageAccount).toBe("function"); + expect(typeof imessageSdk.imessageOnboardingAdapter).toBe("object"); + }); + + it("exports WhatsApp helpers", () => { + expect(typeof whatsappSdk.resolveWhatsAppAccount).toBe("function"); + expect(typeof whatsappSdk.whatsappOnboardingAdapter).toBe("object"); + }); + + it("exports LINE helpers", () => { + expect(typeof lineSdk.processLineMessage).toBe("function"); + expect(typeof lineSdk.createInfoCard).toBe("function"); + }); +}); diff --git a/src/plugin-sdk/whatsapp.ts b/src/plugin-sdk/whatsapp.ts new file mode 100644 index 00000000000..eaa9a890e8b --- /dev/null +++ b/src/plugin-sdk/whatsapp.ts @@ -0,0 +1,58 @@ +export type { ChannelMessageActionName } from "../channels/plugins/types.js"; +export type { ChannelPlugin } from "../channels/plugins/types.plugin.js"; +export type { ResolvedWhatsAppAccount } from "../web/accounts.js"; +export type { PluginRuntime } from "../plugins/runtime/types.js"; +export type { OpenClawPluginApi } from "../plugins/types.js"; + +export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; + +export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js"; + +export { + applyAccountNameToChannelSection, + migrateBaseNameToDefaultAccount, +} from "../channels/plugins/setup-helpers.js"; +export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js"; +export { formatPairingApproveHint } from "../channels/plugins/helpers.js"; + +export { getChatChannelMeta } from "../channels/registry.js"; +export { + listWhatsAppAccountIds, + resolveDefaultWhatsAppAccountId, + resolveWhatsAppAccount, +} from "../web/accounts.js"; +export { + formatWhatsAppConfigAllowFromEntries, + resolveWhatsAppConfigAllowFrom, + resolveWhatsAppConfigDefaultTo, +} from "./channel-config-helpers.js"; +export { + listWhatsAppDirectoryGroupsFromConfig, + listWhatsAppDirectoryPeersFromConfig, +} from "../channels/plugins/directory-config.js"; +export { + looksLikeWhatsAppTargetId, + normalizeWhatsAppMessagingTarget, +} from "../channels/plugins/normalize/whatsapp.js"; +export { resolveWhatsAppOutboundTarget } from "../whatsapp/resolve-outbound-target.js"; + +export { + resolveAllowlistProviderRuntimeGroupPolicy, + resolveDefaultGroupPolicy, +} from "../config/runtime-group-policy.js"; +export { + resolveWhatsAppGroupRequireMention, + resolveWhatsAppGroupToolPolicy, +} from "../channels/plugins/group-mentions.js"; +export { + resolveWhatsAppGroupIntroHint, + resolveWhatsAppMentionStripPatterns, +} from "../channels/plugins/whatsapp-shared.js"; +export { resolveWhatsAppHeartbeatRecipients } from "../channels/plugins/whatsapp-heartbeat.js"; +export { whatsappOnboardingAdapter } from "../channels/plugins/onboarding/whatsapp.js"; +export { collectWhatsAppStatusIssues } from "../channels/plugins/status-issues/whatsapp.js"; +export { WhatsAppConfigSchema } from "../config/zod-schema.providers-whatsapp.js"; + +export { createActionGate, readStringParam } from "../agents/tools/common.js"; + +export { normalizeE164 } from "../utils.js"; diff --git a/src/plugins/loader.test.ts b/src/plugins/loader.test.ts index 1a002447711..1f9a6ebd5a5 100644 --- a/src/plugins/loader.test.ts +++ b/src/plugins/loader.test.ts @@ -1005,6 +1005,29 @@ describe("loadOpenClawPlugins", () => { expect(record?.status).toBe("loaded"); }); + it("supports legacy plugins importing monolithic plugin-sdk root", () => { + useNoBundledPlugins(); + const plugin = writePlugin({ + id: "legacy-root-import", + filename: "legacy-root-import.cjs", + body: `module.exports = { + id: "legacy-root-import", + configSchema: (require("openclaw/plugin-sdk").emptyPluginConfigSchema)(), + register() {}, +};`, + }); + + const registry = loadRegistryFromSinglePlugin({ + plugin, + pluginConfig: { + allow: ["legacy-root-import"], + }, + }); + + const record = registry.plugins.find((entry) => entry.id === "legacy-root-import"); + expect(record?.status).toBe("loaded"); + }); + it("prefers dist plugin-sdk alias when loader runs from dist", () => { const { root, distFile } = createPluginSdkAliasFixture(); diff --git a/src/plugins/loader.ts b/src/plugins/loader.ts index 6bbdaacd5e0..8df588d6b87 100644 --- a/src/plugins/loader.ts +++ b/src/plugins/loader.ts @@ -100,6 +100,30 @@ const resolvePluginSdkTelegramAlias = (): string | null => { return resolvePluginSdkAliasFile({ srcFile: "telegram.ts", distFile: "telegram.js" }); }; +const resolvePluginSdkDiscordAlias = (): string | null => { + return resolvePluginSdkAliasFile({ srcFile: "discord.ts", distFile: "discord.js" }); +}; + +const resolvePluginSdkSlackAlias = (): string | null => { + return resolvePluginSdkAliasFile({ srcFile: "slack.ts", distFile: "slack.js" }); +}; + +const resolvePluginSdkSignalAlias = (): string | null => { + return resolvePluginSdkAliasFile({ srcFile: "signal.ts", distFile: "signal.js" }); +}; + +const resolvePluginSdkIMessageAlias = (): string | null => { + return resolvePluginSdkAliasFile({ srcFile: "imessage.ts", distFile: "imessage.js" }); +}; + +const resolvePluginSdkWhatsAppAlias = (): string | null => { + return resolvePluginSdkAliasFile({ srcFile: "whatsapp.ts", distFile: "whatsapp.js" }); +}; + +const resolvePluginSdkLineAlias = (): string | null => { + return resolvePluginSdkAliasFile({ srcFile: "line.ts", distFile: "line.js" }); +}; + export const __testing = { resolvePluginSdkAliasFile, }; @@ -478,10 +502,22 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi const pluginSdkAccountIdAlias = resolvePluginSdkAccountIdAlias(); const pluginSdkCoreAlias = resolvePluginSdkCoreAlias(); const pluginSdkTelegramAlias = resolvePluginSdkTelegramAlias(); + const pluginSdkDiscordAlias = resolvePluginSdkDiscordAlias(); + const pluginSdkSlackAlias = resolvePluginSdkSlackAlias(); + const pluginSdkSignalAlias = resolvePluginSdkSignalAlias(); + const pluginSdkIMessageAlias = resolvePluginSdkIMessageAlias(); + const pluginSdkWhatsAppAlias = resolvePluginSdkWhatsAppAlias(); + const pluginSdkLineAlias = resolvePluginSdkLineAlias(); const aliasMap = { ...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}), ...(pluginSdkCoreAlias ? { "openclaw/plugin-sdk/core": pluginSdkCoreAlias } : {}), ...(pluginSdkTelegramAlias ? { "openclaw/plugin-sdk/telegram": pluginSdkTelegramAlias } : {}), + ...(pluginSdkDiscordAlias ? { "openclaw/plugin-sdk/discord": pluginSdkDiscordAlias } : {}), + ...(pluginSdkSlackAlias ? { "openclaw/plugin-sdk/slack": pluginSdkSlackAlias } : {}), + ...(pluginSdkSignalAlias ? { "openclaw/plugin-sdk/signal": pluginSdkSignalAlias } : {}), + ...(pluginSdkIMessageAlias ? { "openclaw/plugin-sdk/imessage": pluginSdkIMessageAlias } : {}), + ...(pluginSdkWhatsAppAlias ? { "openclaw/plugin-sdk/whatsapp": pluginSdkWhatsAppAlias } : {}), + ...(pluginSdkLineAlias ? { "openclaw/plugin-sdk/line": pluginSdkLineAlias } : {}), ...(pluginSdkAccountIdAlias ? { "openclaw/plugin-sdk/account-id": pluginSdkAccountIdAlias } : {}), diff --git a/tsconfig.plugin-sdk.dts.json b/tsconfig.plugin-sdk.dts.json index 4deee810315..3e5be344b80 100644 --- a/tsconfig.plugin-sdk.dts.json +++ b/tsconfig.plugin-sdk.dts.json @@ -14,6 +14,12 @@ "src/plugin-sdk/index.ts", "src/plugin-sdk/core.ts", "src/plugin-sdk/telegram.ts", + "src/plugin-sdk/discord.ts", + "src/plugin-sdk/slack.ts", + "src/plugin-sdk/signal.ts", + "src/plugin-sdk/imessage.ts", + "src/plugin-sdk/whatsapp.ts", + "src/plugin-sdk/line.ts", "src/plugin-sdk/account-id.ts", "src/plugin-sdk/keyed-async-queue.ts", "src/types/**/*.d.ts" diff --git a/tsdown.config.ts b/tsdown.config.ts index 819396b2feb..ef5fd70dbb9 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -69,6 +69,48 @@ export default defineConfig([ fixedExtension: false, platform: "node", }, + { + entry: "src/plugin-sdk/discord.ts", + outDir: "dist/plugin-sdk", + env, + fixedExtension: false, + platform: "node", + }, + { + entry: "src/plugin-sdk/slack.ts", + outDir: "dist/plugin-sdk", + env, + fixedExtension: false, + platform: "node", + }, + { + entry: "src/plugin-sdk/signal.ts", + outDir: "dist/plugin-sdk", + env, + fixedExtension: false, + platform: "node", + }, + { + entry: "src/plugin-sdk/imessage.ts", + outDir: "dist/plugin-sdk", + env, + fixedExtension: false, + platform: "node", + }, + { + entry: "src/plugin-sdk/whatsapp.ts", + outDir: "dist/plugin-sdk", + env, + fixedExtension: false, + platform: "node", + }, + { + entry: "src/plugin-sdk/line.ts", + outDir: "dist/plugin-sdk", + env, + fixedExtension: false, + platform: "node", + }, { entry: "src/plugin-sdk/account-id.ts", outDir: "dist/plugin-sdk", diff --git a/vitest.config.ts b/vitest.config.ts index e95927ae22f..026b1a618f2 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -25,6 +25,30 @@ export default defineConfig({ find: "openclaw/plugin-sdk/telegram", replacement: path.join(repoRoot, "src", "plugin-sdk", "telegram.ts"), }, + { + find: "openclaw/plugin-sdk/discord", + replacement: path.join(repoRoot, "src", "plugin-sdk", "discord.ts"), + }, + { + find: "openclaw/plugin-sdk/slack", + replacement: path.join(repoRoot, "src", "plugin-sdk", "slack.ts"), + }, + { + find: "openclaw/plugin-sdk/signal", + replacement: path.join(repoRoot, "src", "plugin-sdk", "signal.ts"), + }, + { + find: "openclaw/plugin-sdk/imessage", + replacement: path.join(repoRoot, "src", "plugin-sdk", "imessage.ts"), + }, + { + find: "openclaw/plugin-sdk/whatsapp", + replacement: path.join(repoRoot, "src", "plugin-sdk", "whatsapp.ts"), + }, + { + find: "openclaw/plugin-sdk/line", + replacement: path.join(repoRoot, "src", "plugin-sdk", "line.ts"), + }, { find: "openclaw/plugin-sdk/keyed-async-queue", replacement: path.join(repoRoot, "src", "plugin-sdk", "keyed-async-queue.ts"),