mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-30 15:10:22 +00:00
refactor: remove core WhatsApp runtime channel seam
This commit is contained in:
@@ -72,7 +72,6 @@ import { createRuntimeLine } from "./runtime-line.js";
|
||||
import { createRuntimeMatrix } from "./runtime-matrix.js";
|
||||
import { createRuntimeSignal } from "./runtime-signal.js";
|
||||
import { createRuntimeSlack } from "./runtime-slack.js";
|
||||
import { createRuntimeWhatsApp } from "./runtime-whatsapp.js";
|
||||
import type { PluginRuntime } from "./types.js";
|
||||
|
||||
export function createRuntimeChannel(): PluginRuntime["channel"] {
|
||||
@@ -211,22 +210,13 @@ export function createRuntimeChannel(): PluginRuntime["channel"] {
|
||||
}
|
||||
},
|
||||
},
|
||||
} satisfies Omit<
|
||||
PluginRuntime["channel"],
|
||||
"discord" | "slack" | "matrix" | "signal" | "whatsapp" | "line"
|
||||
> &
|
||||
Partial<
|
||||
Pick<
|
||||
PluginRuntime["channel"],
|
||||
"discord" | "slack" | "matrix" | "signal" | "whatsapp" | "line"
|
||||
>
|
||||
>;
|
||||
} satisfies Omit<PluginRuntime["channel"], "discord" | "slack" | "matrix" | "signal" | "line"> &
|
||||
Partial<Pick<PluginRuntime["channel"], "discord" | "slack" | "matrix" | "signal" | "line">>;
|
||||
|
||||
defineCachedValue(channelRuntime, "discord", createRuntimeDiscord);
|
||||
defineCachedValue(channelRuntime, "slack", createRuntimeSlack);
|
||||
defineCachedValue(channelRuntime, "matrix", createRuntimeMatrix);
|
||||
defineCachedValue(channelRuntime, "signal", createRuntimeSignal);
|
||||
defineCachedValue(channelRuntime, "whatsapp", createRuntimeWhatsApp);
|
||||
defineCachedValue(channelRuntime, "line", createRuntimeLine);
|
||||
|
||||
return channelRuntime as PluginRuntime["channel"];
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { createJiti } from "jiti";
|
||||
type WhatsAppHeavyRuntimeModule = typeof import("@openclaw/whatsapp/runtime-api.js");
|
||||
type WhatsAppLightRuntimeModule = typeof import("@openclaw/whatsapp/light-runtime-api.js");
|
||||
import { resolveWhatsAppHeartbeatRecipients } from "../../channels/plugins/whatsapp-heartbeat.js";
|
||||
import {
|
||||
getDefaultLocalRoots as getDefaultLocalRootsImpl,
|
||||
@@ -11,10 +13,6 @@ import {
|
||||
resolvePluginRuntimeModulePath,
|
||||
resolvePluginRuntimeRecord,
|
||||
} from "./runtime-plugin-boundary.js";
|
||||
import type {
|
||||
WhatsAppHeavyRuntimeModule,
|
||||
WhatsAppLightRuntimeModule,
|
||||
} from "./runtime-whatsapp-surface.js";
|
||||
|
||||
const WHATSAPP_PLUGIN_ID = "whatsapp";
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { loginWeb as loginWebImpl } from "./runtime-whatsapp-boundary.js";
|
||||
import type { PluginRuntime } from "./types.js";
|
||||
|
||||
type RuntimeWhatsAppLogin = Pick<PluginRuntime["channel"]["whatsapp"], "loginWeb">;
|
||||
|
||||
export const runtimeWhatsAppLogin = {
|
||||
loginWeb: loginWebImpl,
|
||||
} satisfies RuntimeWhatsAppLogin;
|
||||
@@ -1,15 +0,0 @@
|
||||
import {
|
||||
sendMessageWhatsApp as sendMessageWhatsAppImpl,
|
||||
sendPollWhatsApp as sendPollWhatsAppImpl,
|
||||
} from "./runtime-whatsapp-boundary.js";
|
||||
import type { PluginRuntime } from "./types.js";
|
||||
|
||||
type RuntimeWhatsAppOutbound = Pick<
|
||||
PluginRuntime["channel"]["whatsapp"],
|
||||
"sendMessageWhatsApp" | "sendPollWhatsApp"
|
||||
>;
|
||||
|
||||
export const runtimeWhatsAppOutbound = {
|
||||
sendMessageWhatsApp: sendMessageWhatsAppImpl,
|
||||
sendPollWhatsApp: sendPollWhatsAppImpl,
|
||||
} satisfies RuntimeWhatsAppOutbound;
|
||||
@@ -1,249 +0,0 @@
|
||||
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
|
||||
import type { AnyMessageContent, makeWASocket } from "@whiskeysockets/baileys";
|
||||
import type { NormalizedLocation } from "../../channels/location.js";
|
||||
import type { ChannelAgentTool } from "../../channels/plugins/types.core.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { PollInput } from "../../polls.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import type { WebChannel } from "../../utils.js";
|
||||
|
||||
export type ActiveWebSendOptions = {
|
||||
gifPlayback?: boolean;
|
||||
accountId?: string;
|
||||
fileName?: string;
|
||||
};
|
||||
|
||||
export type ActiveWebListener = {
|
||||
sendMessage: (
|
||||
to: string,
|
||||
text: string,
|
||||
mediaBuffer?: Buffer,
|
||||
mediaType?: string,
|
||||
options?: ActiveWebSendOptions,
|
||||
) => Promise<{ messageId: string }>;
|
||||
sendPoll: (to: string, poll: PollInput) => Promise<{ messageId: string }>;
|
||||
sendReaction: (
|
||||
chatJid: string,
|
||||
messageId: string,
|
||||
emoji: string,
|
||||
fromMe: boolean,
|
||||
participant?: string,
|
||||
) => Promise<void>;
|
||||
sendComposingTo: (to: string) => Promise<void>;
|
||||
close?: () => Promise<void>;
|
||||
};
|
||||
|
||||
export type WebListenerCloseReason = {
|
||||
status?: number;
|
||||
isLoggedOut: boolean;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export type WebInboundMessage = {
|
||||
id?: string;
|
||||
from: string;
|
||||
conversationId: string;
|
||||
to: string;
|
||||
accountId: string;
|
||||
body: string;
|
||||
pushName?: string;
|
||||
timestamp?: number;
|
||||
chatType: "direct" | "group";
|
||||
chatId: string;
|
||||
sender?: unknown;
|
||||
senderJid?: string;
|
||||
senderE164?: string;
|
||||
senderName?: string;
|
||||
replyTo?: unknown;
|
||||
replyToId?: string;
|
||||
replyToBody?: string;
|
||||
replyToSender?: string;
|
||||
replyToSenderJid?: string;
|
||||
replyToSenderE164?: string;
|
||||
groupSubject?: string;
|
||||
groupParticipants?: string[];
|
||||
mentions?: string[];
|
||||
mentionedJids?: string[];
|
||||
self?: unknown;
|
||||
selfJid?: string | null;
|
||||
selfLid?: string | null;
|
||||
selfE164?: string | null;
|
||||
fromMe?: boolean;
|
||||
location?: NormalizedLocation;
|
||||
sendComposing: () => Promise<void>;
|
||||
reply: (text: string) => Promise<void>;
|
||||
sendMedia: (payload: AnyMessageContent) => Promise<void>;
|
||||
mediaPath?: string;
|
||||
mediaType?: string;
|
||||
mediaFileName?: string;
|
||||
mediaUrl?: string;
|
||||
wasMentioned?: boolean;
|
||||
};
|
||||
|
||||
export type WebChannelHealthState =
|
||||
| "starting"
|
||||
| "healthy"
|
||||
| "stale"
|
||||
| "reconnecting"
|
||||
| "conflict"
|
||||
| "logged-out"
|
||||
| "stopped";
|
||||
|
||||
export type WebChannelStatus = {
|
||||
running: boolean;
|
||||
connected: boolean;
|
||||
reconnectAttempts: number;
|
||||
lastConnectedAt?: number | null;
|
||||
lastDisconnect?: {
|
||||
at: number;
|
||||
status?: number;
|
||||
error?: string;
|
||||
loggedOut?: boolean;
|
||||
} | null;
|
||||
lastInboundAt?: number | null;
|
||||
lastMessageAt?: number | null;
|
||||
lastEventAt?: number | null;
|
||||
lastError?: string | null;
|
||||
healthState?: WebChannelHealthState;
|
||||
};
|
||||
|
||||
export type WebMonitorTuning = {
|
||||
reconnect?: Partial<{
|
||||
enabled: boolean;
|
||||
maxAttempts: number;
|
||||
baseDelayMs: number;
|
||||
maxDelayMs: number;
|
||||
}>;
|
||||
heartbeatSeconds?: number;
|
||||
messageTimeoutMs?: number;
|
||||
watchdogCheckMs?: number;
|
||||
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
||||
statusSink?: (status: WebChannelStatus) => void;
|
||||
accountId?: string;
|
||||
debounceMs?: number;
|
||||
};
|
||||
|
||||
export type MonitorWebInboxFactory = (options: {
|
||||
verbose: boolean;
|
||||
accountId: string;
|
||||
authDir: string;
|
||||
onMessage: (msg: WebInboundMessage) => Promise<void>;
|
||||
mediaMaxMb?: number;
|
||||
sendReadReceipts?: boolean;
|
||||
debounceMs?: number;
|
||||
shouldDebounce?: (msg: WebInboundMessage) => boolean;
|
||||
}) => Promise<{
|
||||
closeReason: Promise<WebListenerCloseReason>;
|
||||
stop: () => Promise<void>;
|
||||
}>;
|
||||
|
||||
export type ReplyResolver = (...args: unknown[]) => Promise<unknown>;
|
||||
|
||||
export type WhatsAppWaSocket = ReturnType<typeof makeWASocket>;
|
||||
|
||||
export type WhatsAppLightRuntimeModule = {
|
||||
getActiveWebListener: (accountId?: string | null) => ActiveWebListener | null;
|
||||
getWebAuthAgeMs: (authDir?: string) => number | null;
|
||||
logWebSelfId: (authDir?: string, runtime?: RuntimeEnv, includeChannelPrefix?: boolean) => void;
|
||||
logoutWeb: (params: {
|
||||
authDir?: string;
|
||||
isLegacyAuthDir?: boolean;
|
||||
runtime?: RuntimeEnv;
|
||||
}) => Promise<boolean>;
|
||||
readWebSelfId: (authDir?: string) => {
|
||||
e164: string | null;
|
||||
jid: string | null;
|
||||
lid: string | null;
|
||||
};
|
||||
webAuthExists: (authDir?: string) => Promise<boolean>;
|
||||
createWhatsAppLoginTool: () => ChannelAgentTool;
|
||||
formatError: (err: unknown) => string;
|
||||
getStatusCode: (err: unknown) => number | undefined;
|
||||
pickWebChannel: (pref: WebChannel | "auto", authDir?: string) => Promise<WebChannel>;
|
||||
WA_WEB_AUTH_DIR: string;
|
||||
};
|
||||
|
||||
export type WhatsAppHeavyRuntimeModule = {
|
||||
loginWeb: (
|
||||
verbose: boolean,
|
||||
waitForConnection?: (sock: WhatsAppWaSocket) => Promise<void>,
|
||||
runtime?: RuntimeEnv,
|
||||
accountId?: string,
|
||||
) => Promise<void>;
|
||||
sendMessageWhatsApp: (
|
||||
to: string,
|
||||
body: string,
|
||||
options: {
|
||||
verbose: boolean;
|
||||
cfg?: OpenClawConfig;
|
||||
mediaUrl?: string;
|
||||
mediaLocalRoots?: readonly string[];
|
||||
gifPlayback?: boolean;
|
||||
accountId?: string;
|
||||
},
|
||||
) => Promise<{ messageId: string; toJid: string }>;
|
||||
sendPollWhatsApp: (
|
||||
to: string,
|
||||
poll: PollInput,
|
||||
options: { verbose: boolean; accountId?: string; cfg?: OpenClawConfig },
|
||||
) => Promise<{ messageId: string; toJid: string }>;
|
||||
sendReactionWhatsApp: (
|
||||
chatJid: string,
|
||||
messageId: string,
|
||||
emoji: string,
|
||||
options: {
|
||||
verbose: boolean;
|
||||
fromMe?: boolean;
|
||||
participant?: string;
|
||||
accountId?: string;
|
||||
},
|
||||
) => Promise<void>;
|
||||
createWaSocket: (
|
||||
printQr: boolean,
|
||||
verbose: boolean,
|
||||
opts?: { authDir?: string; onQr?: (qr: string) => void },
|
||||
) => Promise<WhatsAppWaSocket>;
|
||||
handleWhatsAppAction: (
|
||||
params: Record<string, unknown>,
|
||||
cfg: OpenClawConfig,
|
||||
) => Promise<AgentToolResult<unknown>>;
|
||||
monitorWebChannel: (
|
||||
verbose: boolean,
|
||||
listenerFactory?: MonitorWebInboxFactory,
|
||||
keepAlive?: boolean,
|
||||
replyResolver?: ReplyResolver,
|
||||
runtime?: RuntimeEnv,
|
||||
abortSignal?: AbortSignal,
|
||||
tuning?: WebMonitorTuning,
|
||||
) => Promise<void>;
|
||||
monitorWebInbox: MonitorWebInboxFactory;
|
||||
runWebHeartbeatOnce: (opts: {
|
||||
cfg?: OpenClawConfig;
|
||||
to: string;
|
||||
verbose?: boolean;
|
||||
replyResolver?: ReplyResolver;
|
||||
sender?: WhatsAppHeavyRuntimeModule["sendMessageWhatsApp"];
|
||||
sessionId?: string;
|
||||
overrideBody?: string;
|
||||
dryRun?: boolean;
|
||||
}) => Promise<void>;
|
||||
startWebLoginWithQr: (opts?: {
|
||||
verbose?: boolean;
|
||||
timeoutMs?: number;
|
||||
force?: boolean;
|
||||
accountId?: string;
|
||||
runtime?: RuntimeEnv;
|
||||
}) => Promise<{ qrDataUrl?: string; message: string }>;
|
||||
waitForWaConnection: (sock: WhatsAppWaSocket) => Promise<void>;
|
||||
waitForWebLogin: (opts?: {
|
||||
timeoutMs?: number;
|
||||
runtime?: RuntimeEnv;
|
||||
accountId?: string;
|
||||
}) => Promise<{ connected: boolean; message: string }>;
|
||||
extractMediaPlaceholder: (
|
||||
message: unknown,
|
||||
mediaDir: string,
|
||||
verbose?: boolean,
|
||||
) => Promise<string | null>;
|
||||
extractText: (message: unknown) => string;
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
import {
|
||||
createRuntimeWhatsAppLoginTool,
|
||||
getActiveWebListener,
|
||||
getWebAuthAgeMs,
|
||||
handleWhatsAppAction,
|
||||
logWebSelfId,
|
||||
loginWeb,
|
||||
logoutWeb,
|
||||
monitorWebChannel,
|
||||
readWebSelfId,
|
||||
sendMessageWhatsApp,
|
||||
sendPollWhatsApp,
|
||||
startWebLoginWithQr,
|
||||
waitForWebLogin,
|
||||
webAuthExists,
|
||||
} from "./runtime-whatsapp-boundary.js";
|
||||
import type { PluginRuntime } from "./types.js";
|
||||
|
||||
export function createRuntimeWhatsApp(): PluginRuntime["channel"]["whatsapp"] {
|
||||
return {
|
||||
getActiveWebListener,
|
||||
getWebAuthAgeMs,
|
||||
logoutWeb,
|
||||
logWebSelfId,
|
||||
readWebSelfId,
|
||||
webAuthExists,
|
||||
sendMessageWhatsApp,
|
||||
sendPollWhatsApp,
|
||||
loginWeb,
|
||||
startWebLoginWithQr,
|
||||
waitForWebLogin,
|
||||
monitorWebChannel,
|
||||
handleWhatsAppAction,
|
||||
createLoginTool: createRuntimeWhatsAppLoginTool,
|
||||
};
|
||||
}
|
||||
@@ -184,22 +184,6 @@ export type PluginRuntimeChannel = {
|
||||
monitorSignalProvider: typeof import("../../plugin-sdk/signal.js").monitorSignalProvider;
|
||||
messageActions: typeof import("../../plugin-sdk/signal.js").signalMessageActions;
|
||||
};
|
||||
whatsapp: {
|
||||
getActiveWebListener: typeof import("./runtime-whatsapp-boundary.js").getActiveWebListener;
|
||||
getWebAuthAgeMs: typeof import("./runtime-whatsapp-boundary.js").getWebAuthAgeMs;
|
||||
logoutWeb: typeof import("./runtime-whatsapp-boundary.js").logoutWeb;
|
||||
logWebSelfId: typeof import("./runtime-whatsapp-boundary.js").logWebSelfId;
|
||||
readWebSelfId: typeof import("./runtime-whatsapp-boundary.js").readWebSelfId;
|
||||
webAuthExists: typeof import("./runtime-whatsapp-boundary.js").webAuthExists;
|
||||
sendMessageWhatsApp: typeof import("./runtime-whatsapp-boundary.js").sendMessageWhatsApp;
|
||||
sendPollWhatsApp: typeof import("./runtime-whatsapp-boundary.js").sendPollWhatsApp;
|
||||
loginWeb: typeof import("./runtime-whatsapp-boundary.js").loginWeb;
|
||||
startWebLoginWithQr: typeof import("./runtime-whatsapp-boundary.js").startWebLoginWithQr;
|
||||
waitForWebLogin: typeof import("./runtime-whatsapp-boundary.js").waitForWebLogin;
|
||||
monitorWebChannel: typeof import("./runtime-whatsapp-boundary.js").monitorWebChannel;
|
||||
handleWhatsAppAction: typeof import("./runtime-whatsapp-boundary.js").handleWhatsAppAction;
|
||||
createLoginTool: typeof import("./runtime-whatsapp-login-tool.js").createRuntimeWhatsAppLoginTool;
|
||||
};
|
||||
line: {
|
||||
listLineAccountIds: typeof import("../../plugin-sdk/line.js").listLineAccountIds;
|
||||
resolveDefaultLineAccountId: typeof import("../../plugin-sdk/line.js").resolveDefaultLineAccountId;
|
||||
|
||||
Reference in New Issue
Block a user