mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-21 02:34:59 +00:00
plugin-sdk: add channel subpaths and migrate bundled plugins
This commit is contained in:
@@ -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.
|
||||
|
||||
55
docs/reference/plugin-sdk-bundled-parity.md
Normal file
55
docs/reference/plugin-sdk-bundled-parity.md
Normal file
@@ -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/<channel>`
|
||||
- `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).
|
||||
@@ -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:
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/discord";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/imessage";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 <type> "title" "body" [options]
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/line";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/signal";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/slack";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/whatsapp";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
27
package.json
27
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",
|
||||
|
||||
41
scripts/check-no-monolithic-plugin-sdk-entry-imports.ts
Normal file
41
scripts/check-no-monolithic-plugin-sdk-entry-imports.ts
Normal file
@@ -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/<channel> for channel plugins or /core for others.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`OK: bundled entrypoints use scoped plugin-sdk subpaths (${bundledEntryFiles.length} checked).`,
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -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.<name>) 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.");
|
||||
|
||||
@@ -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/"];
|
||||
|
||||
@@ -6,7 +6,18 @@ import path from "node:path";
|
||||
//
|
||||
// Our package export map points subpath `types` at `dist/plugin-sdk/<entry>.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 });
|
||||
|
||||
@@ -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";
|
||||
|
||||
60
src/plugin-sdk/discord.ts
Normal file
60
src/plugin-sdk/discord.ts
Normal file
@@ -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";
|
||||
49
src/plugin-sdk/imessage.ts
Normal file
49
src/plugin-sdk/imessage.ts
Normal file
@@ -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";
|
||||
36
src/plugin-sdk/line.ts
Normal file
36
src/plugin-sdk/line.ts
Normal file
@@ -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";
|
||||
49
src/plugin-sdk/signal.ts
Normal file
49
src/plugin-sdk/signal.ts
Normal file
@@ -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";
|
||||
52
src/plugin-sdk/slack.ts
Normal file
52
src/plugin-sdk/slack.ts
Normal file
@@ -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";
|
||||
39
src/plugin-sdk/subpaths.test.ts
Normal file
39
src/plugin-sdk/subpaths.test.ts
Normal file
@@ -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");
|
||||
});
|
||||
});
|
||||
58
src/plugin-sdk/whatsapp.ts
Normal file
58
src/plugin-sdk/whatsapp.ts
Normal file
@@ -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";
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 }
|
||||
: {}),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"),
|
||||
|
||||
Reference in New Issue
Block a user