@openclaw/whatsapp 2026.5.2 → 2026.5.3-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-control-BQ3tCkH8.js +288 -0
- package/dist/account-config-CNQ33oav.js +47 -0
- package/dist/account-ids-DG18xddX.js +5 -0
- package/dist/accounts-BDqgpFEB.js +116 -0
- package/dist/action-runtime-DTGNgG-i.js +74 -0
- package/dist/action-runtime-api.js +2 -0
- package/dist/action-runtime.runtime.js +2 -0
- package/dist/active-listener-N7GFKsuN.js +11 -0
- package/dist/agent-tools-login-DpRxLNRB.js +89 -0
- package/dist/api.js +148 -0
- package/dist/audio-preflight.runtime-Bcdsl_ri.js +7 -0
- package/dist/auth-presence.js +32 -0
- package/dist/auth-store-BjCb50Ry.js +381 -0
- package/dist/channel-DQ-5Xoj9.js +542 -0
- package/dist/channel-config-api.js +2 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel-react-action-Df20qAy9.js +42 -0
- package/dist/channel.runtime-DKXRnA8x.js +55 -0
- package/dist/channel.setup-DOHR2BGp.js +20 -0
- package/dist/command-policy-O8sRnqUV.js +8 -0
- package/dist/config-schema-Dmo66Ubb.js +27 -0
- package/dist/connection-controller-BiHAsTM8.js +596 -0
- package/dist/connection-controller-registry-D_iIGz5m.js +22 -0
- package/dist/constants-DLGCIbfl.js +4 -0
- package/dist/constants.js +2 -0
- package/dist/contract-api.js +19 -0
- package/dist/creds-files-_2V8jzQa.js +19 -0
- package/dist/directory-config-DVs4ffXu.js +37 -0
- package/dist/directory-contract-api.js +2 -0
- package/dist/doctor-A9tXm9Om.js +48 -0
- package/dist/doctor-contract-api.js +10 -0
- package/dist/group-session-contract-B8QBn0I2.js +15 -0
- package/dist/identity-QHAlV7Fu.js +75 -0
- package/dist/index.js +18 -0
- package/dist/legacy-session-surface-api.js +8 -0
- package/dist/legacy-state-migrations-api.js +2 -0
- package/dist/light-runtime-api.js +5 -0
- package/dist/login-DymdrKca.js +52 -0
- package/dist/login-qr-DIS0Iv-7.js +378 -0
- package/dist/login-qr-api.js +2 -0
- package/dist/login-qr-runtime.js +16 -0
- package/dist/monitor-C4Fhg_lD.js +3349 -0
- package/dist/normalize-CWYiGkXw.js +2 -0
- package/dist/normalize-target-BPVHNsM5.js +74 -0
- package/dist/outbound-adapter-BssVnZdz.js +29 -0
- package/dist/outbound-base-Bq1UYEK5.js +119 -0
- package/dist/outbound-media-contract-CGss_QHy.js +163 -0
- package/dist/outbound-payload-test-api.js +2 -0
- package/dist/quoted-message-TENQzyxV.js +108 -0
- package/dist/reaction-level-CRVEVAfi.js +16 -0
- package/dist/reply-resolver.runtime-BRCgoO4C.js +2 -0
- package/dist/resolve-outbound-target-CN-Wo6IY.js +39 -0
- package/dist/rolldown-runtime-RkAeH_Qm.js +27 -0
- package/dist/runtime-6fZ67abR.js +8 -0
- package/dist/runtime-api.js +15 -0
- package/dist/runtime-group-policy-Gp1lQ0at.js +11 -0
- package/dist/secret-contract-api.js +5 -0
- package/dist/security-contract-DqH8JDX6.js +26 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-CIyLFxdZ.js +234 -0
- package/dist/session-contract-B0efQf9P.js +27 -0
- package/dist/session-errors-CSuKZPub.js +63 -0
- package/dist/session.runtime-C1eSE_KK.js +13 -0
- package/dist/setup-core-DZKvpzbH.js +46 -0
- package/dist/setup-entry.js +23 -0
- package/dist/setup-plugin-api.js +2 -0
- package/dist/setup-surface-ieFnIW4g.js +344 -0
- package/dist/shared-D_wzSVar.js +307 -0
- package/dist/state-migrations-DnCdvoYD.js +39 -0
- package/dist/targets.js +2 -0
- package/dist/test-api.js +3 -0
- package/dist/text-runtime-C1zNiZeO.js +116 -0
- package/package.json +14 -6
- package/action-runtime-api.ts +0 -1
- package/action-runtime.runtime.ts +0 -1
- package/api.ts +0 -213
- package/auth-presence.ts +0 -80
- package/channel-config-api.ts +0 -1
- package/channel-plugin-api.ts +0 -3
- package/config-api.ts +0 -4
- package/constants.ts +0 -1
- package/contract-api.ts +0 -29
- package/directory-contract-api.ts +0 -4
- package/doctor-contract-api.ts +0 -8
- package/index.test.ts +0 -13
- package/index.ts +0 -16
- package/legacy-session-surface-api.ts +0 -6
- package/legacy-state-migrations-api.ts +0 -1
- package/light-runtime-api.ts +0 -12
- package/login-qr-api.ts +0 -1
- package/login-qr-runtime.ts +0 -23
- package/outbound-payload-test-api.ts +0 -1
- package/runtime-api.ts +0 -84
- package/secret-contract-api.ts +0 -4
- package/security-contract-api.ts +0 -4
- package/setup-entry.test.ts +0 -21
- package/setup-entry.ts +0 -21
- package/setup-plugin-api.ts +0 -3
- package/src/account-config.ts +0 -77
- package/src/account-ids.ts +0 -13
- package/src/account-types.ts +0 -5
- package/src/accounts.test.ts +0 -182
- package/src/accounts.ts +0 -176
- package/src/accounts.whatsapp-auth.test.ts +0 -59
- package/src/action-runtime-target-auth.ts +0 -27
- package/src/action-runtime.test.ts +0 -330
- package/src/action-runtime.ts +0 -76
- package/src/active-listener.test.ts +0 -65
- package/src/active-listener.ts +0 -17
- package/src/agent-tools-login.test.ts +0 -81
- package/src/agent-tools-login.ts +0 -113
- package/src/approval-auth.test.ts +0 -24
- package/src/approval-auth.ts +0 -27
- package/src/auth-store.runtime.ts +0 -1
- package/src/auth-store.test.ts +0 -311
- package/src/auth-store.ts +0 -502
- package/src/auto-reply/config.runtime.ts +0 -16
- package/src/auto-reply/constants.ts +0 -1
- package/src/auto-reply/deliver-reply.test.ts +0 -843
- package/src/auto-reply/deliver-reply.ts +0 -279
- package/src/auto-reply/loggers.ts +0 -6
- package/src/auto-reply/mentions.ts +0 -131
- package/src/auto-reply/monitor/ack-reaction.test.ts +0 -170
- package/src/auto-reply/monitor/ack-reaction.ts +0 -99
- package/src/auto-reply/monitor/audio-preflight.runtime.ts +0 -9
- package/src/auto-reply/monitor/broadcast.ts +0 -153
- package/src/auto-reply/monitor/commands.ts +0 -19
- package/src/auto-reply/monitor/echo.ts +0 -64
- package/src/auto-reply/monitor/group-activation.runtime.ts +0 -1
- package/src/auto-reply/monitor/group-activation.test.ts +0 -189
- package/src/auto-reply/monitor/group-activation.ts +0 -73
- package/src/auto-reply/monitor/group-gating.audio-preflight.test.ts +0 -103
- package/src/auto-reply/monitor/group-gating.runtime.ts +0 -8
- package/src/auto-reply/monitor/group-gating.ts +0 -217
- package/src/auto-reply/monitor/group-members.test.ts +0 -56
- package/src/auto-reply/monitor/group-members.ts +0 -65
- package/src/auto-reply/monitor/inbound-context.test.ts +0 -97
- package/src/auto-reply/monitor/inbound-context.ts +0 -92
- package/src/auto-reply/monitor/inbound-dispatch.runtime.ts +0 -21
- package/src/auto-reply/monitor/inbound-dispatch.test.ts +0 -895
- package/src/auto-reply/monitor/inbound-dispatch.ts +0 -422
- package/src/auto-reply/monitor/last-route.test.ts +0 -37
- package/src/auto-reply/monitor/last-route.ts +0 -61
- package/src/auto-reply/monitor/message-line.runtime.ts +0 -38
- package/src/auto-reply/monitor/message-line.ts +0 -54
- package/src/auto-reply/monitor/on-message.audio-preflight.test.ts +0 -354
- package/src/auto-reply/monitor/on-message.ts +0 -291
- package/src/auto-reply/monitor/peer.ts +0 -17
- package/src/auto-reply/monitor/process-message.audio-preflight.test.ts +0 -420
- package/src/auto-reply/monitor/process-message.test.ts +0 -355
- package/src/auto-reply/monitor/process-message.ts +0 -531
- package/src/auto-reply/monitor/runtime-api.ts +0 -30
- package/src/auto-reply/monitor-state.test.ts +0 -64
- package/src/auto-reply/monitor-state.ts +0 -106
- package/src/auto-reply/monitor.ts +0 -600
- package/src/auto-reply/reply-resolver.runtime.ts +0 -1
- package/src/auto-reply/types.ts +0 -48
- package/src/auto-reply/util.ts +0 -63
- package/src/auto-reply/web-auto-reply-monitor.test.ts +0 -687
- package/src/auto-reply/web-auto-reply-utils.test.ts +0 -392
- package/src/auto-reply.broadcast-groups.combined.test.ts +0 -246
- package/src/auto-reply.broadcast-groups.test-harness.ts +0 -47
- package/src/auto-reply.impl.ts +0 -6
- package/src/auto-reply.test-harness.ts +0 -421
- package/src/auto-reply.ts +0 -1
- package/src/auto-reply.web-auto-reply.compresses-common-formats-jpeg-cap.test.ts +0 -427
- package/src/auto-reply.web-auto-reply.connection-and-logging.e2e.test.ts +0 -908
- package/src/auto-reply.web-auto-reply.last-route.test.ts +0 -184
- package/src/channel-actions.runtime.ts +0 -7
- package/src/channel-actions.test.ts +0 -216
- package/src/channel-actions.ts +0 -84
- package/src/channel-outbound.test.ts +0 -131
- package/src/channel-outbound.ts +0 -36
- package/src/channel-react-action.runtime.ts +0 -7
- package/src/channel-react-action.test.ts +0 -294
- package/src/channel-react-action.ts +0 -84
- package/src/channel.runtime.ts +0 -117
- package/src/channel.setup.test.ts +0 -461
- package/src/channel.setup.ts +0 -28
- package/src/channel.ts +0 -339
- package/src/command-policy.ts +0 -7
- package/src/config-accessors.test.ts +0 -34
- package/src/config-accessors.ts +0 -22
- package/src/config-schema.test.ts +0 -121
- package/src/config-schema.ts +0 -6
- package/src/config-ui-hints.ts +0 -24
- package/src/connection-controller-registry.test.ts +0 -27
- package/src/connection-controller-registry.ts +0 -49
- package/src/connection-controller.test.ts +0 -282
- package/src/connection-controller.ts +0 -679
- package/src/creds-files.ts +0 -19
- package/src/creds-persistence.ts +0 -102
- package/src/directory-config.test.ts +0 -60
- package/src/directory-config.ts +0 -40
- package/src/directory-contract.test.ts +0 -56
- package/src/doctor-contract.ts +0 -11
- package/src/doctor.test.ts +0 -74
- package/src/doctor.ts +0 -56
- package/src/group-intro.ts +0 -15
- package/src/group-policy.test.ts +0 -36
- package/src/group-policy.ts +0 -40
- package/src/group-session-contract.ts +0 -20
- package/src/group-session-key.test.ts +0 -53
- package/src/group-session-key.ts +0 -41
- package/src/heartbeat.ts +0 -34
- package/src/identity.ts +0 -164
- package/src/inbound/access-control.test-harness.ts +0 -37
- package/src/inbound/access-control.test.ts +0 -375
- package/src/inbound/access-control.ts +0 -237
- package/src/inbound/dedupe.ts +0 -132
- package/src/inbound/extract.test.ts +0 -282
- package/src/inbound/extract.ts +0 -488
- package/src/inbound/lifecycle.ts +0 -39
- package/src/inbound/media.node.test.ts +0 -83
- package/src/inbound/media.ts +0 -102
- package/src/inbound/monitor.ts +0 -890
- package/src/inbound/runtime-api.ts +0 -7
- package/src/inbound/save-media.runtime.ts +0 -1
- package/src/inbound/send-api.test.ts +0 -319
- package/src/inbound/send-api.ts +0 -145
- package/src/inbound/send-result.ts +0 -61
- package/src/inbound/types.ts +0 -106
- package/src/inbound-context.contract.test.ts +0 -32
- package/src/inbound-policy.ts +0 -231
- package/src/inbound.media.test.ts +0 -320
- package/src/inbound.test.ts +0 -290
- package/src/inbound.ts +0 -9
- package/src/login-qr.test.ts +0 -483
- package/src/login-qr.ts +0 -542
- package/src/login.coverage.test.ts +0 -133
- package/src/login.test.ts +0 -89
- package/src/login.ts +0 -70
- package/src/logout.test.ts +0 -162
- package/src/media.test.ts +0 -480
- package/src/media.ts +0 -10
- package/src/monitor-inbox.allows-messages-from-senders-allowfrom-list.test-support.ts +0 -400
- package/src/monitor-inbox.append-upsert.test-support.ts +0 -133
- package/src/monitor-inbox.behavior.test.ts +0 -5
- package/src/monitor-inbox.blocks-messages-from-unauthorized-senders-not-allowfrom.test-support.ts +0 -362
- package/src/monitor-inbox.captures-media-path-image-messages.test-support.ts +0 -306
- package/src/monitor-inbox.streams-inbound-messages.test-support.ts +0 -729
- package/src/monitor-inbox.test-harness.ts +0 -304
- package/src/normalize-target.ts +0 -123
- package/src/normalize.ts +0 -7
- package/src/outbound-adapter.poll.test.ts +0 -62
- package/src/outbound-adapter.sendpayload.test.ts +0 -195
- package/src/outbound-adapter.ts +0 -36
- package/src/outbound-base.test.ts +0 -560
- package/src/outbound-base.ts +0 -244
- package/src/outbound-media-contract.ts +0 -278
- package/src/outbound-media.runtime.ts +0 -36
- package/src/outbound-payload.contract.test.ts +0 -61
- package/src/outbound-send-deps.ts +0 -1
- package/src/outbound-test-support.ts +0 -16
- package/src/pairing-security.test-harness.ts +0 -59
- package/src/qr-image.ts +0 -1
- package/src/qr-terminal.ts +0 -1
- package/src/quoted-message.test.ts +0 -83
- package/src/quoted-message.ts +0 -184
- package/src/reaction-level.test.ts +0 -94
- package/src/reaction-level.ts +0 -21
- package/src/reconnect.test.ts +0 -51
- package/src/reconnect.ts +0 -55
- package/src/resolve-outbound-target.test.ts +0 -288
- package/src/resolve-outbound-target.ts +0 -58
- package/src/resolve-target.test.ts +0 -120
- package/src/runtime-api.ts +0 -59
- package/src/runtime-group-policy.ts +0 -16
- package/src/runtime.ts +0 -9
- package/src/security-contract.ts +0 -47
- package/src/security-fix.ts +0 -71
- package/src/send.test.ts +0 -534
- package/src/send.ts +0 -292
- package/src/session-contract.test.ts +0 -31
- package/src/session-contract.ts +0 -43
- package/src/session-errors.ts +0 -125
- package/src/session-route.test.ts +0 -41
- package/src/session-route.ts +0 -32
- package/src/session.runtime.ts +0 -8
- package/src/session.test.ts +0 -559
- package/src/session.ts +0 -330
- package/src/setup-core.ts +0 -52
- package/src/setup-finalize.ts +0 -446
- package/src/setup-surface.test.ts +0 -367
- package/src/setup-surface.ts +0 -69
- package/src/setup-test-helpers.ts +0 -216
- package/src/shared.ts +0 -291
- package/src/socket-timing.test.ts +0 -49
- package/src/socket-timing.ts +0 -38
- package/src/state-migrations.ts +0 -54
- package/src/status-issues.test.ts +0 -137
- package/src/status-issues.ts +0 -185
- package/src/system-prompt.test.ts +0 -199
- package/src/system-prompt.ts +0 -31
- package/src/targets-runtime.ts +0 -180
- package/src/test-helpers.ts +0 -690
- package/src/text-runtime.test.ts +0 -162
- package/src/text-runtime.ts +0 -11
- package/src/vcard.ts +0 -84
- package/targets.ts +0 -5
- package/test-api.ts +0 -2
- package/tsconfig.json +0 -16
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { handleWhatsAppReactAction } from "./channel-react-action.js";
|
|
3
|
-
import type { OpenClawConfig } from "./runtime-api.js";
|
|
4
|
-
|
|
5
|
-
const hoisted = vi.hoisted(() => ({
|
|
6
|
-
handleWhatsAppAction: vi.fn(async () => ({ content: [{ type: "text", text: '{"ok":true}' }] })),
|
|
7
|
-
}));
|
|
8
|
-
|
|
9
|
-
vi.mock("./channel-react-action.runtime.js", async () => {
|
|
10
|
-
return {
|
|
11
|
-
handleWhatsAppAction: hoisted.handleWhatsAppAction,
|
|
12
|
-
resolveReactionMessageId: ({
|
|
13
|
-
args,
|
|
14
|
-
toolContext,
|
|
15
|
-
}: {
|
|
16
|
-
args: Record<string, unknown>;
|
|
17
|
-
toolContext?: { currentMessageId?: string | number | null };
|
|
18
|
-
}) => args.messageId ?? toolContext?.currentMessageId ?? null,
|
|
19
|
-
readStringOrNumberParam: (params: Record<string, unknown>, key: string) => {
|
|
20
|
-
const value = params[key];
|
|
21
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
22
|
-
return value;
|
|
23
|
-
}
|
|
24
|
-
if (typeof value === "string" && value.trim()) {
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
return undefined;
|
|
28
|
-
},
|
|
29
|
-
isWhatsAppGroupJid: (value?: string | null) => (value ?? "").trim().endsWith("@g.us"),
|
|
30
|
-
normalizeWhatsAppTarget: (value?: string | null) => {
|
|
31
|
-
const raw = (value ?? "").trim();
|
|
32
|
-
if (!raw) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
const stripped = raw.replace(/^whatsapp:/, "");
|
|
36
|
-
if (stripped.endsWith("@g.us")) {
|
|
37
|
-
return stripped;
|
|
38
|
-
}
|
|
39
|
-
return stripped.startsWith("+") ? stripped : `+${stripped.replace(/^\+/, "")}`;
|
|
40
|
-
},
|
|
41
|
-
readStringParam: (
|
|
42
|
-
params: Record<string, unknown>,
|
|
43
|
-
key: string,
|
|
44
|
-
options?: { required?: boolean; allowEmpty?: boolean },
|
|
45
|
-
) => {
|
|
46
|
-
const value = params[key];
|
|
47
|
-
if (value == null) {
|
|
48
|
-
if (options?.required) {
|
|
49
|
-
const err = new Error(`${key} required`);
|
|
50
|
-
err.name = "ToolInputError";
|
|
51
|
-
throw err;
|
|
52
|
-
}
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
const text = typeof value === "string" ? value : "";
|
|
56
|
-
if (!options?.allowEmpty && !text.trim()) {
|
|
57
|
-
if (options?.required) {
|
|
58
|
-
const err = new Error(`${key} required`);
|
|
59
|
-
err.name = "ToolInputError";
|
|
60
|
-
throw err;
|
|
61
|
-
}
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
return text;
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe("whatsapp react action messageId resolution", () => {
|
|
70
|
-
const baseCfg = {
|
|
71
|
-
channels: { whatsapp: { actions: { reactions: true }, allowFrom: ["*"] } },
|
|
72
|
-
} as OpenClawConfig;
|
|
73
|
-
|
|
74
|
-
beforeEach(() => {
|
|
75
|
-
hoisted.handleWhatsAppAction.mockClear();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("uses explicit messageId when provided", async () => {
|
|
79
|
-
await handleWhatsAppReactAction({
|
|
80
|
-
action: "react",
|
|
81
|
-
params: { messageId: "explicit-id", emoji: "👍", to: "+1555" },
|
|
82
|
-
cfg: baseCfg,
|
|
83
|
-
accountId: "default",
|
|
84
|
-
});
|
|
85
|
-
expect(hoisted.handleWhatsAppAction).toHaveBeenCalledWith(
|
|
86
|
-
expect.objectContaining({ messageId: "explicit-id" }),
|
|
87
|
-
baseCfg,
|
|
88
|
-
);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("falls back to toolContext.currentMessageId when messageId omitted", async () => {
|
|
92
|
-
await handleWhatsAppReactAction({
|
|
93
|
-
action: "react",
|
|
94
|
-
params: { emoji: "❤️", to: "+1555" },
|
|
95
|
-
cfg: baseCfg,
|
|
96
|
-
accountId: "default",
|
|
97
|
-
toolContext: {
|
|
98
|
-
currentChannelId: "whatsapp:+1555",
|
|
99
|
-
currentChannelProvider: "whatsapp",
|
|
100
|
-
currentMessageId: "ctx-msg-42",
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
expect(hoisted.handleWhatsAppAction).toHaveBeenCalledWith(
|
|
104
|
-
expect.objectContaining({ messageId: "ctx-msg-42" }),
|
|
105
|
-
baseCfg,
|
|
106
|
-
);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("converts numeric toolContext messageId to string", async () => {
|
|
110
|
-
await handleWhatsAppReactAction({
|
|
111
|
-
action: "react",
|
|
112
|
-
params: { emoji: "🎉", to: "+1555" },
|
|
113
|
-
cfg: baseCfg,
|
|
114
|
-
accountId: "default",
|
|
115
|
-
toolContext: {
|
|
116
|
-
currentChannelId: "whatsapp:+1555",
|
|
117
|
-
currentChannelProvider: "whatsapp",
|
|
118
|
-
currentMessageId: 12345,
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
expect(hoisted.handleWhatsAppAction).toHaveBeenCalledWith(
|
|
122
|
-
expect.objectContaining({ messageId: "12345" }),
|
|
123
|
-
baseCfg,
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("throws ToolInputError when messageId missing and no toolContext", async () => {
|
|
128
|
-
const err = await handleWhatsAppReactAction({
|
|
129
|
-
action: "react",
|
|
130
|
-
params: { emoji: "👍", to: "+1555" },
|
|
131
|
-
cfg: baseCfg,
|
|
132
|
-
accountId: "default",
|
|
133
|
-
}).catch((e: unknown) => e);
|
|
134
|
-
expect(err).toBeInstanceOf(Error);
|
|
135
|
-
expect((err as Error).name).toBe("ToolInputError");
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("skips context fallback when targeting a different chat", async () => {
|
|
139
|
-
const err = await handleWhatsAppReactAction({
|
|
140
|
-
action: "react",
|
|
141
|
-
params: { emoji: "👍", to: "+9999" },
|
|
142
|
-
cfg: baseCfg,
|
|
143
|
-
accountId: "default",
|
|
144
|
-
toolContext: {
|
|
145
|
-
currentChannelId: "whatsapp:+1555",
|
|
146
|
-
currentChannelProvider: "whatsapp",
|
|
147
|
-
currentMessageId: "ctx-msg-42",
|
|
148
|
-
},
|
|
149
|
-
}).catch((e: unknown) => e);
|
|
150
|
-
expect(err).toBeInstanceOf(Error);
|
|
151
|
-
expect((err as Error).name).toBe("ToolInputError");
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it("uses context fallback when target matches current chat", async () => {
|
|
155
|
-
await handleWhatsAppReactAction({
|
|
156
|
-
action: "react",
|
|
157
|
-
params: { emoji: "👍", to: "12345@g.us" },
|
|
158
|
-
cfg: baseCfg,
|
|
159
|
-
accountId: "default",
|
|
160
|
-
requesterSenderId: "123@lid",
|
|
161
|
-
toolContext: {
|
|
162
|
-
currentChannelId: "whatsapp:12345@g.us",
|
|
163
|
-
currentChannelProvider: "whatsapp",
|
|
164
|
-
currentMessageId: "ctx-msg-42",
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
expect(hoisted.handleWhatsAppAction).toHaveBeenCalledWith(
|
|
168
|
-
expect.objectContaining({
|
|
169
|
-
messageId: "ctx-msg-42",
|
|
170
|
-
participant: "123@lid",
|
|
171
|
-
}),
|
|
172
|
-
baseCfg,
|
|
173
|
-
);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("keeps direct-chat reactions without an inferred participant", async () => {
|
|
177
|
-
await handleWhatsAppReactAction({
|
|
178
|
-
action: "react",
|
|
179
|
-
params: { emoji: "👍", to: "+1555" },
|
|
180
|
-
cfg: baseCfg,
|
|
181
|
-
accountId: "default",
|
|
182
|
-
requesterSenderId: "123@lid",
|
|
183
|
-
toolContext: {
|
|
184
|
-
currentChannelId: "whatsapp:+1555",
|
|
185
|
-
currentChannelProvider: "whatsapp",
|
|
186
|
-
currentMessageId: "ctx-msg-42",
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
expect(hoisted.handleWhatsAppAction).toHaveBeenCalledWith(
|
|
190
|
-
expect.objectContaining({
|
|
191
|
-
messageId: "ctx-msg-42",
|
|
192
|
-
participant: undefined,
|
|
193
|
-
}),
|
|
194
|
-
baseCfg,
|
|
195
|
-
);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it("prefers explicit participant over inferred current-message participant", async () => {
|
|
199
|
-
await handleWhatsAppReactAction({
|
|
200
|
-
action: "react",
|
|
201
|
-
params: {
|
|
202
|
-
emoji: "👍",
|
|
203
|
-
to: "12345@g.us",
|
|
204
|
-
participant: "555@s.whatsapp.net",
|
|
205
|
-
},
|
|
206
|
-
cfg: baseCfg,
|
|
207
|
-
accountId: "default",
|
|
208
|
-
requesterSenderId: "123@lid",
|
|
209
|
-
toolContext: {
|
|
210
|
-
currentChannelId: "whatsapp:12345@g.us",
|
|
211
|
-
currentChannelProvider: "whatsapp",
|
|
212
|
-
currentMessageId: "ctx-msg-42",
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
expect(hoisted.handleWhatsAppAction).toHaveBeenCalledWith(
|
|
216
|
-
expect.objectContaining({
|
|
217
|
-
messageId: "ctx-msg-42",
|
|
218
|
-
participant: "555@s.whatsapp.net",
|
|
219
|
-
}),
|
|
220
|
-
baseCfg,
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it("does not reuse the current-chat participant for cross-chat reactions", async () => {
|
|
225
|
-
const err = await handleWhatsAppReactAction({
|
|
226
|
-
action: "react",
|
|
227
|
-
params: { emoji: "👍", to: "99999@g.us" },
|
|
228
|
-
cfg: baseCfg,
|
|
229
|
-
accountId: "default",
|
|
230
|
-
requesterSenderId: "123@lid",
|
|
231
|
-
toolContext: {
|
|
232
|
-
currentChannelId: "whatsapp:12345@g.us",
|
|
233
|
-
currentChannelProvider: "whatsapp",
|
|
234
|
-
currentMessageId: "ctx-msg-42",
|
|
235
|
-
},
|
|
236
|
-
}).catch((e: unknown) => e);
|
|
237
|
-
expect(err).toBeInstanceOf(Error);
|
|
238
|
-
expect((err as Error).name).toBe("ToolInputError");
|
|
239
|
-
expect(hoisted.handleWhatsAppAction).not.toHaveBeenCalled();
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it("does not infer participant when messageId is explicitly provided", async () => {
|
|
243
|
-
await handleWhatsAppReactAction({
|
|
244
|
-
action: "react",
|
|
245
|
-
params: { emoji: "👍", to: "12345@g.us", messageId: "older-msg-7" },
|
|
246
|
-
cfg: baseCfg,
|
|
247
|
-
accountId: "default",
|
|
248
|
-
requesterSenderId: "123@lid",
|
|
249
|
-
toolContext: {
|
|
250
|
-
currentChannelId: "whatsapp:12345@g.us",
|
|
251
|
-
currentChannelProvider: "whatsapp",
|
|
252
|
-
currentMessageId: "ctx-msg-42",
|
|
253
|
-
},
|
|
254
|
-
});
|
|
255
|
-
expect(hoisted.handleWhatsAppAction).toHaveBeenCalledWith(
|
|
256
|
-
expect.objectContaining({
|
|
257
|
-
messageId: "older-msg-7",
|
|
258
|
-
participant: undefined,
|
|
259
|
-
}),
|
|
260
|
-
baseCfg,
|
|
261
|
-
);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("skips context fallback when source is another provider", async () => {
|
|
265
|
-
const err = await handleWhatsAppReactAction({
|
|
266
|
-
action: "react",
|
|
267
|
-
params: { emoji: "👍", to: "+1555" },
|
|
268
|
-
cfg: baseCfg,
|
|
269
|
-
accountId: "default",
|
|
270
|
-
toolContext: {
|
|
271
|
-
currentChannelId: "telegram:-1003841603622",
|
|
272
|
-
currentChannelProvider: "telegram",
|
|
273
|
-
currentMessageId: "tg-msg-99",
|
|
274
|
-
},
|
|
275
|
-
}).catch((e: unknown) => e);
|
|
276
|
-
expect(err).toBeInstanceOf(Error);
|
|
277
|
-
expect((err as Error).name).toBe("ToolInputError");
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
it("skips context fallback when currentChannelId is missing with explicit target", async () => {
|
|
281
|
-
const err = await handleWhatsAppReactAction({
|
|
282
|
-
action: "react",
|
|
283
|
-
params: { emoji: "👍", to: "+1555" },
|
|
284
|
-
cfg: baseCfg,
|
|
285
|
-
accountId: "default",
|
|
286
|
-
toolContext: {
|
|
287
|
-
currentChannelProvider: "whatsapp",
|
|
288
|
-
currentMessageId: "ctx-msg-42",
|
|
289
|
-
},
|
|
290
|
-
}).catch((e: unknown) => e);
|
|
291
|
-
expect(err).toBeInstanceOf(Error);
|
|
292
|
-
expect((err as Error).name).toBe("ToolInputError");
|
|
293
|
-
});
|
|
294
|
-
});
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isWhatsAppGroupJid,
|
|
3
|
-
resolveReactionMessageId,
|
|
4
|
-
handleWhatsAppAction,
|
|
5
|
-
normalizeWhatsAppTarget,
|
|
6
|
-
readStringOrNumberParam,
|
|
7
|
-
readStringParam,
|
|
8
|
-
type OpenClawConfig,
|
|
9
|
-
} from "./channel-react-action.runtime.js";
|
|
10
|
-
|
|
11
|
-
const WHATSAPP_CHANNEL = "whatsapp" as const;
|
|
12
|
-
|
|
13
|
-
export async function handleWhatsAppReactAction(params: {
|
|
14
|
-
action: string;
|
|
15
|
-
params: Record<string, unknown>;
|
|
16
|
-
cfg: OpenClawConfig;
|
|
17
|
-
accountId?: string | null;
|
|
18
|
-
requesterSenderId?: string | null;
|
|
19
|
-
toolContext?: {
|
|
20
|
-
currentChannelId?: string | null;
|
|
21
|
-
currentChannelProvider?: string | null;
|
|
22
|
-
currentMessageId?: string | number | null;
|
|
23
|
-
};
|
|
24
|
-
}) {
|
|
25
|
-
if (params.action !== "react") {
|
|
26
|
-
throw new Error(`Action ${params.action} is not supported for provider ${WHATSAPP_CHANNEL}.`);
|
|
27
|
-
}
|
|
28
|
-
const isWhatsAppSource = params.toolContext?.currentChannelProvider === WHATSAPP_CHANNEL;
|
|
29
|
-
const explicitTarget =
|
|
30
|
-
readStringParam(params.params, "chatJid") ?? readStringParam(params.params, "to");
|
|
31
|
-
const normalizedTarget = explicitTarget ? normalizeWhatsAppTarget(explicitTarget) : null;
|
|
32
|
-
const normalizedCurrent =
|
|
33
|
-
isWhatsAppSource && params.toolContext?.currentChannelId
|
|
34
|
-
? normalizeWhatsAppTarget(params.toolContext.currentChannelId)
|
|
35
|
-
: null;
|
|
36
|
-
const isCrossChat =
|
|
37
|
-
normalizedTarget != null &&
|
|
38
|
-
(normalizedCurrent == null || normalizedTarget !== normalizedCurrent);
|
|
39
|
-
const scopedContext =
|
|
40
|
-
!isWhatsAppSource || isCrossChat || !params.toolContext
|
|
41
|
-
? undefined
|
|
42
|
-
: {
|
|
43
|
-
currentChannelId: params.toolContext.currentChannelId ?? undefined,
|
|
44
|
-
currentChannelProvider: params.toolContext.currentChannelProvider ?? undefined,
|
|
45
|
-
currentMessageId: params.toolContext.currentMessageId ?? undefined,
|
|
46
|
-
};
|
|
47
|
-
const messageIdRaw = resolveReactionMessageId({
|
|
48
|
-
args: params.params,
|
|
49
|
-
toolContext: scopedContext,
|
|
50
|
-
});
|
|
51
|
-
if (messageIdRaw == null) {
|
|
52
|
-
readStringParam(params.params, "messageId", { required: true });
|
|
53
|
-
}
|
|
54
|
-
const messageId = String(messageIdRaw);
|
|
55
|
-
const explicitMessageId = readStringOrNumberParam(params.params, "messageId");
|
|
56
|
-
const emoji = readStringParam(params.params, "emoji", { allowEmpty: true });
|
|
57
|
-
const remove = typeof params.params.remove === "boolean" ? params.params.remove : undefined;
|
|
58
|
-
const explicitParticipant = readStringParam(params.params, "participant");
|
|
59
|
-
const inferredParticipant =
|
|
60
|
-
explicitParticipant ||
|
|
61
|
-
explicitMessageId != null ||
|
|
62
|
-
!isWhatsAppSource ||
|
|
63
|
-
isCrossChat ||
|
|
64
|
-
!isWhatsAppGroupJid(explicitTarget ?? params.toolContext?.currentChannelId ?? "")
|
|
65
|
-
? undefined
|
|
66
|
-
: typeof params.requesterSenderId === "string" && params.requesterSenderId.trim().length > 0
|
|
67
|
-
? params.requesterSenderId.trim()
|
|
68
|
-
: undefined;
|
|
69
|
-
return await handleWhatsAppAction(
|
|
70
|
-
{
|
|
71
|
-
action: "react",
|
|
72
|
-
chatJid:
|
|
73
|
-
readStringParam(params.params, "chatJid") ??
|
|
74
|
-
readStringParam(params.params, "to", { required: true }),
|
|
75
|
-
messageId,
|
|
76
|
-
emoji,
|
|
77
|
-
remove,
|
|
78
|
-
participant: explicitParticipant ?? inferredParticipant,
|
|
79
|
-
accountId: params.accountId ?? undefined,
|
|
80
|
-
fromMe: typeof params.params.fromMe === "boolean" ? params.params.fromMe : undefined,
|
|
81
|
-
},
|
|
82
|
-
params.cfg,
|
|
83
|
-
);
|
|
84
|
-
}
|
package/src/channel.runtime.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
startWebLoginWithQr as startWebLoginWithQrImpl,
|
|
3
|
-
waitForWebLogin as waitForWebLoginImpl,
|
|
4
|
-
} from "../login-qr-runtime.js";
|
|
5
|
-
import { getActiveWebListener as getActiveWebListenerImpl } from "./active-listener.js";
|
|
6
|
-
import {
|
|
7
|
-
getWebAuthAgeMs as getWebAuthAgeMsImpl,
|
|
8
|
-
logWebSelfId as logWebSelfIdImpl,
|
|
9
|
-
logoutWeb as logoutWebImpl,
|
|
10
|
-
readWebAuthSnapshot as readWebAuthSnapshotImpl,
|
|
11
|
-
readWebAuthState as readWebAuthStateImpl,
|
|
12
|
-
readWebAuthExistsBestEffort as readWebAuthExistsBestEffortImpl,
|
|
13
|
-
readWebAuthExistsForDecision as readWebAuthExistsForDecisionImpl,
|
|
14
|
-
readWebAuthSnapshotBestEffort as readWebAuthSnapshotBestEffortImpl,
|
|
15
|
-
readWebSelfId as readWebSelfIdImpl,
|
|
16
|
-
webAuthExists as webAuthExistsImpl,
|
|
17
|
-
} from "./auth-store.js";
|
|
18
|
-
import { monitorWebChannel as monitorWebChannelImpl } from "./auto-reply/monitor.js";
|
|
19
|
-
import { loginWeb as loginWebImpl } from "./login.js";
|
|
20
|
-
import { whatsappSetupWizard as whatsappSetupWizardImpl } from "./setup-surface.js";
|
|
21
|
-
|
|
22
|
-
type GetActiveWebListener = typeof import("./active-listener.js").getActiveWebListener;
|
|
23
|
-
type GetWebAuthAgeMs = typeof import("./auth-store.js").getWebAuthAgeMs;
|
|
24
|
-
type LogWebSelfId = typeof import("./auth-store.js").logWebSelfId;
|
|
25
|
-
type LogoutWeb = typeof import("./auth-store.js").logoutWeb;
|
|
26
|
-
type ReadWebAuthSnapshot = typeof import("./auth-store.js").readWebAuthSnapshot;
|
|
27
|
-
type ReadWebAuthState = typeof import("./auth-store.js").readWebAuthState;
|
|
28
|
-
type ReadWebAuthExistsBestEffort = typeof import("./auth-store.js").readWebAuthExistsBestEffort;
|
|
29
|
-
type ReadWebAuthExistsForDecision = typeof import("./auth-store.js").readWebAuthExistsForDecision;
|
|
30
|
-
type ReadWebAuthSnapshotBestEffort = typeof import("./auth-store.js").readWebAuthSnapshotBestEffort;
|
|
31
|
-
type ReadWebSelfId = typeof import("./auth-store.js").readWebSelfId;
|
|
32
|
-
type WebAuthExists = typeof import("./auth-store.js").webAuthExists;
|
|
33
|
-
type LoginWeb = typeof import("./login.js").loginWeb;
|
|
34
|
-
type StartWebLoginWithQr = typeof import("../login-qr-runtime.js").startWebLoginWithQr;
|
|
35
|
-
type WaitForWebLogin = typeof import("../login-qr-runtime.js").waitForWebLogin;
|
|
36
|
-
type WhatsAppSetupWizard = typeof import("./setup-surface.js").whatsappSetupWizard;
|
|
37
|
-
type MonitorWebChannel = typeof import("./auto-reply/monitor.js").monitorWebChannel;
|
|
38
|
-
|
|
39
|
-
export function getActiveWebListener(
|
|
40
|
-
...args: Parameters<GetActiveWebListener>
|
|
41
|
-
): ReturnType<GetActiveWebListener> {
|
|
42
|
-
return getActiveWebListenerImpl(...args);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function getWebAuthAgeMs(...args: Parameters<GetWebAuthAgeMs>): ReturnType<GetWebAuthAgeMs> {
|
|
46
|
-
return getWebAuthAgeMsImpl(...args);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function logWebSelfId(...args: Parameters<LogWebSelfId>): ReturnType<LogWebSelfId> {
|
|
50
|
-
return logWebSelfIdImpl(...args);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function logoutWeb(...args: Parameters<LogoutWeb>): ReturnType<LogoutWeb> {
|
|
54
|
-
return logoutWebImpl(...args);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function readWebAuthSnapshot(
|
|
58
|
-
...args: Parameters<ReadWebAuthSnapshot>
|
|
59
|
-
): ReturnType<ReadWebAuthSnapshot> {
|
|
60
|
-
return readWebAuthSnapshotImpl(...args);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function readWebAuthState(
|
|
64
|
-
...args: Parameters<ReadWebAuthState>
|
|
65
|
-
): ReturnType<ReadWebAuthState> {
|
|
66
|
-
return readWebAuthStateImpl(...args);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function readWebAuthExistsBestEffort(
|
|
70
|
-
...args: Parameters<ReadWebAuthExistsBestEffort>
|
|
71
|
-
): ReturnType<ReadWebAuthExistsBestEffort> {
|
|
72
|
-
return readWebAuthExistsBestEffortImpl(...args);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function readWebAuthExistsForDecision(
|
|
76
|
-
...args: Parameters<ReadWebAuthExistsForDecision>
|
|
77
|
-
): ReturnType<ReadWebAuthExistsForDecision> {
|
|
78
|
-
return readWebAuthExistsForDecisionImpl(...args);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function readWebAuthSnapshotBestEffort(
|
|
82
|
-
...args: Parameters<ReadWebAuthSnapshotBestEffort>
|
|
83
|
-
): ReturnType<ReadWebAuthSnapshotBestEffort> {
|
|
84
|
-
return readWebAuthSnapshotBestEffortImpl(...args);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function readWebSelfId(...args: Parameters<ReadWebSelfId>): ReturnType<ReadWebSelfId> {
|
|
88
|
-
return readWebSelfIdImpl(...args);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function webAuthExists(...args: Parameters<WebAuthExists>): ReturnType<WebAuthExists> {
|
|
92
|
-
return webAuthExistsImpl(...args);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function loginWeb(...args: Parameters<LoginWeb>): ReturnType<LoginWeb> {
|
|
96
|
-
return loginWebImpl(...args);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export async function startWebLoginWithQr(
|
|
100
|
-
...args: Parameters<StartWebLoginWithQr>
|
|
101
|
-
): ReturnType<StartWebLoginWithQr> {
|
|
102
|
-
return await startWebLoginWithQrImpl(...args);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export async function waitForWebLogin(
|
|
106
|
-
...args: Parameters<WaitForWebLogin>
|
|
107
|
-
): ReturnType<WaitForWebLogin> {
|
|
108
|
-
return await waitForWebLoginImpl(...args);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export const whatsappSetupWizard: WhatsAppSetupWizard = { ...whatsappSetupWizardImpl };
|
|
112
|
-
|
|
113
|
-
export function monitorWebChannel(
|
|
114
|
-
...args: Parameters<MonitorWebChannel>
|
|
115
|
-
): ReturnType<MonitorWebChannel> {
|
|
116
|
-
return monitorWebChannelImpl(...args);
|
|
117
|
-
}
|