From 152d17930297f547f92e7541c50f90a4cb7a5469 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Wed, 18 Mar 2026 11:13:19 -0700 Subject: [PATCH] Plugin SDK: add public WhatsApp runtime subpaths --- package.json | 8 +++ scripts/lib/plugin-sdk-entrypoints.json | 2 + src/plugin-sdk/subpaths.test.ts | 11 ++++ src/plugin-sdk/whatsapp-action-runtime.ts | 1 + src/plugin-sdk/whatsapp-login-qr.ts | 1 + src/plugin-sdk/whatsapp.ts | 3 + .../runtime/runtime-whatsapp-login-tool.ts | 2 +- .../runtime/runtime-whatsapp-login.runtime.ts | 2 +- .../runtime-whatsapp-outbound.runtime.ts | 2 +- src/plugins/runtime/runtime-whatsapp.ts | 17 +++--- src/plugins/runtime/types-channel.ts | 24 ++++---- ...n-extension-import-boundary-inventory.json | 56 ------------------- 12 files changed, 49 insertions(+), 80 deletions(-) create mode 100644 src/plugin-sdk/whatsapp-action-runtime.ts create mode 100644 src/plugin-sdk/whatsapp-login-qr.ts diff --git a/package.json b/package.json index 5b7887dcef4..d28200d336f 100644 --- a/package.json +++ b/package.json @@ -210,6 +210,14 @@ "types": "./dist/plugin-sdk/whatsapp.d.ts", "default": "./dist/plugin-sdk/whatsapp.js" }, + "./plugin-sdk/whatsapp-action-runtime": { + "types": "./dist/plugin-sdk/whatsapp-action-runtime.d.ts", + "default": "./dist/plugin-sdk/whatsapp-action-runtime.js" + }, + "./plugin-sdk/whatsapp-login-qr": { + "types": "./dist/plugin-sdk/whatsapp-login-qr.d.ts", + "default": "./dist/plugin-sdk/whatsapp-login-qr.js" + }, "./plugin-sdk/whatsapp-core": { "types": "./dist/plugin-sdk/whatsapp-core.d.ts", "default": "./dist/plugin-sdk/whatsapp-core.js" diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index e55bea9d053..e0d707523a8 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -42,6 +42,8 @@ "imessage", "imessage-core", "whatsapp", + "whatsapp-action-runtime", + "whatsapp-login-qr", "whatsapp-core", "line", "line-core", diff --git a/src/plugin-sdk/subpaths.test.ts b/src/plugin-sdk/subpaths.test.ts index 93ad61651e0..2f4a30ae5ce 100644 --- a/src/plugin-sdk/subpaths.test.ts +++ b/src/plugin-sdk/subpaths.test.ts @@ -29,6 +29,8 @@ import * as telegramSdk from "openclaw/plugin-sdk/telegram"; import * as testingSdk from "openclaw/plugin-sdk/testing"; import * as voiceCallSdk from "openclaw/plugin-sdk/voice-call"; import * as whatsappSdk from "openclaw/plugin-sdk/whatsapp"; +import * as whatsappActionRuntimeSdk from "openclaw/plugin-sdk/whatsapp-action-runtime"; +import * as whatsappLoginQrSdk from "openclaw/plugin-sdk/whatsapp-login-qr"; import { describe, expect, expectTypeOf, it } from "vitest"; import type { ChannelMessageActionContext } from "../channels/plugins/types.js"; import type { PluginRuntime } from "../plugins/runtime/types.js"; @@ -297,6 +299,15 @@ describe("plugin-sdk subpath exports", () => { expect("resolveWhatsAppMentionStripPatterns" in whatsappSdk).toBe(false); }); + it("exports WhatsApp QR login helpers from the dedicated subpath", () => { + expect(typeof whatsappLoginQrSdk.startWebLoginWithQr).toBe("function"); + expect(typeof whatsappLoginQrSdk.waitForWebLogin).toBe("function"); + }); + + it("exports WhatsApp action runtime helpers from the dedicated subpath", () => { + expect(typeof whatsappActionRuntimeSdk.handleWhatsAppAction).toBe("function"); + }); + it("exports Feishu helpers", async () => { expect(typeof feishuSdk.feishuSetupWizard).toBe("object"); expect(typeof feishuSdk.feishuSetupAdapter).toBe("object"); diff --git a/src/plugin-sdk/whatsapp-action-runtime.ts b/src/plugin-sdk/whatsapp-action-runtime.ts new file mode 100644 index 00000000000..87e7a29e437 --- /dev/null +++ b/src/plugin-sdk/whatsapp-action-runtime.ts @@ -0,0 +1 @@ +export { handleWhatsAppAction } from "../../extensions/whatsapp/action-runtime-api.js"; diff --git a/src/plugin-sdk/whatsapp-login-qr.ts b/src/plugin-sdk/whatsapp-login-qr.ts new file mode 100644 index 00000000000..bde71742811 --- /dev/null +++ b/src/plugin-sdk/whatsapp-login-qr.ts @@ -0,0 +1 @@ +export { startWebLoginWithQr, waitForWebLogin } from "../../extensions/whatsapp/login-qr-api.js"; diff --git a/src/plugin-sdk/whatsapp.ts b/src/plugin-sdk/whatsapp.ts index 3e16da46d80..d5182f9004c 100644 --- a/src/plugin-sdk/whatsapp.ts +++ b/src/plugin-sdk/whatsapp.ts @@ -71,10 +71,13 @@ export { resolveWhatsAppAccount, } from "../../extensions/whatsapp/api.js"; export { + getActiveWebListener, + getWebAuthAgeMs, WA_WEB_AUTH_DIR, logWebSelfId, logoutWeb, pickWebChannel, + readWebSelfId, webAuthExists, } from "../../extensions/whatsapp/runtime-api.js"; export { diff --git a/src/plugins/runtime/runtime-whatsapp-login-tool.ts b/src/plugins/runtime/runtime-whatsapp-login-tool.ts index 094e47c9a1d..33c2355cda1 100644 --- a/src/plugins/runtime/runtime-whatsapp-login-tool.ts +++ b/src/plugins/runtime/runtime-whatsapp-login-tool.ts @@ -1 +1 @@ -export { createWhatsAppLoginTool as createRuntimeWhatsAppLoginTool } from "../../../extensions/whatsapp/runtime-api.js"; +export { createWhatsAppLoginTool as createRuntimeWhatsAppLoginTool } from "openclaw/plugin-sdk/whatsapp"; diff --git a/src/plugins/runtime/runtime-whatsapp-login.runtime.ts b/src/plugins/runtime/runtime-whatsapp-login.runtime.ts index baef795d478..c0e89600bde 100644 --- a/src/plugins/runtime/runtime-whatsapp-login.runtime.ts +++ b/src/plugins/runtime/runtime-whatsapp-login.runtime.ts @@ -1,4 +1,4 @@ -import { loginWeb as loginWebImpl } from "../../../extensions/whatsapp/runtime-api.js"; +import { loginWeb as loginWebImpl } from "openclaw/plugin-sdk/whatsapp"; import type { PluginRuntime } from "./types.js"; type RuntimeWhatsAppLogin = Pick; diff --git a/src/plugins/runtime/runtime-whatsapp-outbound.runtime.ts b/src/plugins/runtime/runtime-whatsapp-outbound.runtime.ts index 91fcba6fd39..c213afe141e 100644 --- a/src/plugins/runtime/runtime-whatsapp-outbound.runtime.ts +++ b/src/plugins/runtime/runtime-whatsapp-outbound.runtime.ts @@ -1,7 +1,7 @@ import { sendMessageWhatsApp as sendMessageWhatsAppImpl, sendPollWhatsApp as sendPollWhatsAppImpl, -} from "../../../extensions/whatsapp/runtime-api.js"; +} from "openclaw/plugin-sdk/whatsapp"; import type { PluginRuntime } from "./types.js"; type RuntimeWhatsAppOutbound = Pick< diff --git a/src/plugins/runtime/runtime-whatsapp.ts b/src/plugins/runtime/runtime-whatsapp.ts index 796bc80bb5a..ca266581d21 100644 --- a/src/plugins/runtime/runtime-whatsapp.ts +++ b/src/plugins/runtime/runtime-whatsapp.ts @@ -1,11 +1,11 @@ -import { getActiveWebListener } from "../../../extensions/whatsapp/runtime-api.js"; +import { getActiveWebListener } from "openclaw/plugin-sdk/whatsapp"; import { getWebAuthAgeMs, - logoutWeb, logWebSelfId, + logoutWeb, readWebSelfId, webAuthExists, -} from "../../../extensions/whatsapp/runtime-api.js"; +} from "openclaw/plugin-sdk/whatsapp"; import { createLazyRuntimeMethodBinder, createLazyRuntimeSurface, @@ -63,16 +63,15 @@ const handleWhatsAppActionLazy: PluginRuntime["channel"]["whatsapp"]["handleWhat return handleWhatsAppAction(...args); }; -let webLoginQrPromise: Promise< - typeof import("../../../extensions/whatsapp/login-qr-api.js") -> | null = null; +let webLoginQrPromise: Promise | null = + null; let webChannelPromise: Promise | null = null; let whatsappActionsPromise: Promise< - typeof import("../../../extensions/whatsapp/action-runtime-api.js") + typeof import("openclaw/plugin-sdk/whatsapp-action-runtime") > | null = null; function loadWebLoginQr() { - webLoginQrPromise ??= import("../../../extensions/whatsapp/login-qr-api.js"); + webLoginQrPromise ??= import("openclaw/plugin-sdk/whatsapp-login-qr"); return webLoginQrPromise; } @@ -82,7 +81,7 @@ function loadWebChannel() { } function loadWhatsAppActions() { - whatsappActionsPromise ??= import("../../../extensions/whatsapp/action-runtime-api.js"); + whatsappActionsPromise ??= import("openclaw/plugin-sdk/whatsapp-action-runtime"); return whatsappActionsPromise; } diff --git a/src/plugins/runtime/types-channel.ts b/src/plugins/runtime/types-channel.ts index 7b53a0e0025..b5f9a8e8e7a 100644 --- a/src/plugins/runtime/types-channel.ts +++ b/src/plugins/runtime/types-channel.ts @@ -205,19 +205,19 @@ export type PluginRuntimeChannel = { sendMessageIMessage: typeof import("../../../extensions/imessage/runtime-api.js").sendMessageIMessage; }; whatsapp: { - getActiveWebListener: typeof import("../../../extensions/whatsapp/runtime-api.js").getActiveWebListener; - getWebAuthAgeMs: typeof import("../../../extensions/whatsapp/runtime-api.js").getWebAuthAgeMs; - logoutWeb: typeof import("../../../extensions/whatsapp/runtime-api.js").logoutWeb; - logWebSelfId: typeof import("../../../extensions/whatsapp/runtime-api.js").logWebSelfId; - readWebSelfId: typeof import("../../../extensions/whatsapp/runtime-api.js").readWebSelfId; - webAuthExists: typeof import("../../../extensions/whatsapp/runtime-api.js").webAuthExists; - sendMessageWhatsApp: typeof import("../../../extensions/whatsapp/runtime-api.js").sendMessageWhatsApp; - sendPollWhatsApp: typeof import("../../../extensions/whatsapp/runtime-api.js").sendPollWhatsApp; - loginWeb: typeof import("../../../extensions/whatsapp/runtime-api.js").loginWeb; - startWebLoginWithQr: typeof import("../../../extensions/whatsapp/login-qr-api.js").startWebLoginWithQr; - waitForWebLogin: typeof import("../../../extensions/whatsapp/login-qr-api.js").waitForWebLogin; + getActiveWebListener: typeof import("openclaw/plugin-sdk/whatsapp").getActiveWebListener; + getWebAuthAgeMs: typeof import("openclaw/plugin-sdk/whatsapp").getWebAuthAgeMs; + logoutWeb: typeof import("openclaw/plugin-sdk/whatsapp").logoutWeb; + logWebSelfId: typeof import("openclaw/plugin-sdk/whatsapp").logWebSelfId; + readWebSelfId: typeof import("openclaw/plugin-sdk/whatsapp").readWebSelfId; + webAuthExists: typeof import("openclaw/plugin-sdk/whatsapp").webAuthExists; + sendMessageWhatsApp: typeof import("openclaw/plugin-sdk/whatsapp").sendMessageWhatsApp; + sendPollWhatsApp: typeof import("openclaw/plugin-sdk/whatsapp").sendPollWhatsApp; + loginWeb: typeof import("openclaw/plugin-sdk/whatsapp").loginWeb; + startWebLoginWithQr: typeof import("openclaw/plugin-sdk/whatsapp-login-qr").startWebLoginWithQr; + waitForWebLogin: typeof import("openclaw/plugin-sdk/whatsapp-login-qr").waitForWebLogin; monitorWebChannel: typeof import("../../channels/web/index.js").monitorWebChannel; - handleWhatsAppAction: typeof import("../../../extensions/whatsapp/action-runtime-api.js").handleWhatsAppAction; + handleWhatsAppAction: typeof import("openclaw/plugin-sdk/whatsapp-action-runtime").handleWhatsAppAction; createLoginTool: typeof import("./runtime-whatsapp-login-tool.js").createRuntimeWhatsAppLoginTool; }; line: { diff --git a/test/fixtures/plugin-extension-import-boundary-inventory.json b/test/fixtures/plugin-extension-import-boundary-inventory.json index a91dc57c85e..740e9b6226f 100644 --- a/test/fixtures/plugin-extension-import-boundary-inventory.json +++ b/test/fixtures/plugin-extension-import-boundary-inventory.json @@ -94,61 +94,5 @@ "specifier": "../../extensions/zai/model-definitions.js", "resolvedPath": "extensions/zai/model-definitions.js", "reason": "imports extension-owned file from src/plugins" - }, - { - "file": "src/plugins/runtime/runtime-whatsapp-login-tool.ts", - "line": 1, - "kind": "export", - "specifier": "../../../extensions/whatsapp/runtime-api.js", - "resolvedPath": "extensions/whatsapp/runtime-api.js", - "reason": "re-exports extension-owned file from src/plugins" - }, - { - "file": "src/plugins/runtime/runtime-whatsapp-login.runtime.ts", - "line": 1, - "kind": "import", - "specifier": "../../../extensions/whatsapp/runtime-api.js", - "resolvedPath": "extensions/whatsapp/runtime-api.js", - "reason": "imports extension-owned file from src/plugins" - }, - { - "file": "src/plugins/runtime/runtime-whatsapp-outbound.runtime.ts", - "line": 4, - "kind": "import", - "specifier": "../../../extensions/whatsapp/runtime-api.js", - "resolvedPath": "extensions/whatsapp/runtime-api.js", - "reason": "imports extension-owned file from src/plugins" - }, - { - "file": "src/plugins/runtime/runtime-whatsapp.ts", - "line": 1, - "kind": "import", - "specifier": "../../../extensions/whatsapp/runtime-api.js", - "resolvedPath": "extensions/whatsapp/runtime-api.js", - "reason": "imports extension-owned file from src/plugins" - }, - { - "file": "src/plugins/runtime/runtime-whatsapp.ts", - "line": 8, - "kind": "import", - "specifier": "../../../extensions/whatsapp/runtime-api.js", - "resolvedPath": "extensions/whatsapp/runtime-api.js", - "reason": "imports extension-owned file from src/plugins" - }, - { - "file": "src/plugins/runtime/runtime-whatsapp.ts", - "line": 75, - "kind": "dynamic-import", - "specifier": "../../../extensions/whatsapp/login-qr-api.js", - "resolvedPath": "extensions/whatsapp/login-qr-api.js", - "reason": "dynamically imports extension-owned file from src/plugins" - }, - { - "file": "src/plugins/runtime/runtime-whatsapp.ts", - "line": 85, - "kind": "dynamic-import", - "specifier": "../../../extensions/whatsapp/action-runtime-api.js", - "resolvedPath": "extensions/whatsapp/action-runtime-api.js", - "reason": "dynamically imports extension-owned file from src/plugins" } ]