Runtime: narrow WhatsApp login tool surface

This commit is contained in:
Vincent Koc
2026-03-16 21:36:22 -07:00
parent 5572e6965a
commit 38bc364aed
3 changed files with 74 additions and 3 deletions

View File

@@ -0,0 +1,71 @@
import { Type } from "@sinclair/typebox";
import type { ChannelAgentTool } from "openclaw/plugin-sdk/channel-runtime";
export function createRuntimeWhatsAppLoginTool(): ChannelAgentTool {
return {
label: "WhatsApp Login",
name: "whatsapp_login",
ownerOnly: true,
description: "Generate a WhatsApp QR code for linking, or wait for the scan to complete.",
parameters: Type.Object({
action: Type.Unsafe<"start" | "wait">({
type: "string",
enum: ["start", "wait"],
}),
timeoutMs: Type.Optional(Type.Number()),
force: Type.Optional(Type.Boolean()),
}),
execute: async (_toolCallId, args) => {
const { startWebLoginWithQr, waitForWebLogin } =
await import("../../../extensions/whatsapp/src/login-qr.js");
const action = (args as { action?: string })?.action ?? "start";
if (action === "wait") {
const result = await waitForWebLogin({
timeoutMs:
typeof (args as { timeoutMs?: unknown }).timeoutMs === "number"
? (args as { timeoutMs?: number }).timeoutMs
: undefined,
});
return {
content: [{ type: "text", text: result.message }],
details: { connected: result.connected },
};
}
const result = await startWebLoginWithQr({
timeoutMs:
typeof (args as { timeoutMs?: unknown }).timeoutMs === "number"
? (args as { timeoutMs?: number }).timeoutMs
: undefined,
force:
typeof (args as { force?: unknown }).force === "boolean"
? (args as { force?: boolean }).force
: false,
});
if (!result.qrDataUrl) {
return {
content: [
{
type: "text",
text: result.message,
},
],
details: { qr: false },
};
}
const text = [
result.message,
"",
"Open WhatsApp -> Linked Devices and scan:",
"",
`![whatsapp-qr](${result.qrDataUrl})`,
].join("\n");
return {
content: [{ type: "text", text }],
details: { qr: true },
};
},
};
}

View File

@@ -6,7 +6,7 @@ import {
readWebSelfId,
webAuthExists,
} from "../../../extensions/whatsapp/src/auth-store.js";
import { createWhatsAppLoginTool } from "../../channels/plugins/agent-tools/whatsapp-login.js";
import { createRuntimeWhatsAppLoginTool } from "./runtime-whatsapp-login-tool.js";
import type { PluginRuntime } from "./types.js";
const sendMessageWhatsAppLazy: PluginRuntime["channel"]["whatsapp"]["sendMessageWhatsApp"] = async (
@@ -106,6 +106,6 @@ export function createRuntimeWhatsApp(): PluginRuntime["channel"]["whatsapp"] {
waitForWebLogin: waitForWebLoginLazy,
monitorWebChannel: monitorWebChannelLazy,
handleWhatsAppAction: handleWhatsAppActionLazy,
createLoginTool: createWhatsAppLoginTool,
createLoginTool: createRuntimeWhatsAppLoginTool,
};
}

View File

@@ -211,7 +211,7 @@ export type PluginRuntimeChannel = {
waitForWebLogin: typeof import("../../../extensions/whatsapp/src/login-qr.js").waitForWebLogin;
monitorWebChannel: typeof import("../../channels/web/index.js").monitorWebChannel;
handleWhatsAppAction: typeof import("../../agents/tools/whatsapp-actions.js").handleWhatsAppAction;
createLoginTool: typeof import("../../channels/plugins/agent-tools/whatsapp-login.js").createWhatsAppLoginTool;
createLoginTool: typeof import("./runtime-whatsapp-login-tool.js").createRuntimeWhatsAppLoginTool;
};
line: {
listLineAccountIds: typeof import("../../line/accounts.js").listLineAccountIds;