fix(web): improve WhatsApp Web listener errors (#612, thanks @YuriNachos)

This commit is contained in:
Peter Steinberger
2026-01-09 22:40:41 +00:00
parent a9f8719cd2
commit a18743eabc
3 changed files with 26 additions and 18 deletions

View File

@@ -36,6 +36,7 @@
- Hooks: default hook agent delivery to true. (#533) — thanks @mcinteerj
- Hooks: normalize hook agent providers (aliases + msteams support).
- WhatsApp: route queued replies to the original sender instead of the bot's own number. (#534) — thanks @mcinteerj
- WhatsApp: improve "no active web listener" errors (include account + relink hint). (#612) — thanks @YuriNachos
- WhatsApp: add broadcast groups for multi-agent replies. (#547) — thanks @pasogott
- WhatsApp: resolve @lid inbound senders via auth-dir mapping fallback + shared resolver. (#365)
- iMessage: isolate group-ish threads by chat_id. (#535) — thanks @mdahmann

View File

@@ -51,6 +51,19 @@ describe("web outbound", () => {
);
});
it("throws a helpful error when no active listener exists", async () => {
setActiveWebListener(null);
await expect(
sendMessageWhatsApp("+1555", "hi", { verbose: false, accountId: "work" }),
).rejects.toThrow(/No active WhatsApp Web listener/);
await expect(
sendMessageWhatsApp("+1555", "hi", { verbose: false, accountId: "work" }),
).rejects.toThrow(/providers login/);
await expect(
sendMessageWhatsApp("+1555", "hi", { verbose: false, accountId: "work" }),
).rejects.toThrow(/account: work/);
});
it("maps audio to PTT with opus mime when ogg", async () => {
const buf = Buffer.from("audio");
loadWebMediaMock.mockResolvedValueOnce({

View File

@@ -13,6 +13,15 @@ const outboundLog = createSubsystemLogger("gateway/providers/whatsapp").child(
"outbound",
);
function requireActiveListener(accountId?: string | null) {
const active = getActiveWebListener(accountId);
if (active) return active;
const id = (accountId ?? "").trim() || "default";
throw new Error(
`No active WhatsApp Web listener (account: ${id}). Start the gateway, then link WhatsApp with: clawdbot providers login --provider whatsapp --account ${id}.`,
);
}
export async function sendMessageWhatsApp(
to: string,
body: string,
@@ -26,12 +35,7 @@ export async function sendMessageWhatsApp(
let text = body;
const correlationId = randomUUID();
const startedAt = Date.now();
const active = getActiveWebListener(options.accountId);
if (!active) {
throw new Error(
"No active gateway listener. Start the gateway before sending messages.",
);
}
const active = requireActiveListener(options.accountId);
const logger = getChildLogger({
module: "web-outbound",
correlationId,
@@ -108,12 +112,7 @@ export async function sendReactionWhatsApp(
},
): Promise<void> {
const correlationId = randomUUID();
const active = getActiveWebListener(options.accountId);
if (!active) {
throw new Error(
"No active gateway listener. Start the gateway before sending reactions.",
);
}
const active = requireActiveListener(options.accountId);
const logger = getChildLogger({
module: "web-outbound",
correlationId,
@@ -149,12 +148,7 @@ export async function sendPollWhatsApp(
): Promise<{ messageId: string; toJid: string }> {
const correlationId = randomUUID();
const startedAt = Date.now();
const active = getActiveWebListener(options.accountId);
if (!active) {
throw new Error(
"No active gateway listener. Start the gateway before sending polls.",
);
}
const active = requireActiveListener(options.accountId);
const logger = getChildLogger({
module: "web-outbound",
correlationId,