[pull] main from rmyndharis:main - #116
Merged
Merged
Conversation
The chat-scope check on a read receipt folded both sides through toEngineJid, which reduces @c.us and @s.whatsapp.net to one spelling but returns @lid unchanged. Baileys stores a DM key under the peer's lid once WhatsApp addresses the chat that way, so every stored key for such a chat failed the comparison. The receipt then fell back to a synthesised key that lost the message's real fromMe and participant. Compare in the neutral dialect instead, which resolves a lid to its phone user-part through the session's lid mapping. An unmapped lid still cannot match, so a key belonging to another chat is rejected exactly as before.
A before-hook that stops a dispatch returned the same null as a genuine preflight failure, so the reconciler read a deliberate drop as a loss. It replayed the suppressed event once per sweep until the attempt budget ran out, then marked the row terminally failed and pointed the operator at a delivery-failure row nothing had written. Cancellation is now its own outcome: terminal like a delivery, but recording nothing. A failed replay leaves its outbox row pending on purpose, so every later sweep reached the dead-letter table again. One lost delivery was reported as up to WEBHOOK_RECONCILE_MAX_ATTEMPTS rows and counted that many times in webhook_delivery_failures_total, against a table documented as holding one record per delivery that exhausted its retries. The recorder now skips a delivery it has already recorded, as the inbound reconciler does. That lookup runs on every terminal failure against a table that is never pruned, so it gets a composite index on (webhookId, idempotencyKey).
The note told operators to move the whole `<old root>/plugins` tree when changing the knob. On the default layout that path is PLUGINS_DIR itself, so following the instruction takes the installed plugin packages away from the loader, which the same paragraph says to leave in place. Name the files that actually hold plugin state instead: `registry.json` and each plugin's `<plugin id>/key-*.json`, copied into the new root.
fix(engine): match receipt keys across the lid dialect
fix(webhook): correct outcome accounting on the replay path
…note docs(plugins): correct the PLUGIN_STATE_DIR migration note
A caller could tag participants on send-text and the media sends, but the same array was rejected with "property mentions should not exist" on the routes that carry text just as plainly: reply, edit, send-template and the bulk items. The engines can carry the tags on all of them, so the field was missing from the DTOs rather than from the engines. - replyToMessage and editMessage take an optional mentions list, forwarded by both adapters. Baileys spreads the existing withMentions helper into the content; whatsapp-web.js passes the options bag its library already accepts, and omits it entirely when no tags were asked for so an untagged send keeps its previous call shape. - send-template dispatches through sendText, so it also gained linkPreview. quotedMessageId stays out: docs/06 publishes this route as one that rejects it. - Every bulk item type forwards its own list, audio included. Audio carries no caption, but a mention still tags through contextInfo, which is why the single-send audio route accepts it. - An edit REPLACES the message content, so tags are re-applied rather than preserved: a rewritten body loses the tags unless the list is sent again. - The mentions caps and the 4096 text cap move to shared constants; the effective limits are unchanged. Verified: adapter, service and DTO tests per route, each with a negative control; the DTO cases run through the real production validation pipe, so they exercise the whitelist that produced the 400. Plugin rewrites of the list are asserted on reply and edit, because message:sending is a moderation chokepoint and reading the caller's own body there would send the unredacted tags.
MessageService.reply declared an inline three-field parameter while the controller already handed it a ReplyMessageDto carrying a fourth. The body still reached the sender, because structural typing does not strip excess properties, but the declaration said less than what flowed through and no test covered the entry point itself. A non-REST caller that builds the object against the declared type cannot pass mentions at all. Type it by ReplyMessageDto, matching every sibling forwarder in the class.
…carrying-route feat(message): widen mentions to every text-carrying route
An agent could not tag a participant through the MCP surface, and the failure was silent rather than loud: a tool schema is a plain z.object, so an undeclared `mentions` argument was stripped before the handler ran and the send reported success with the message delivered untagged. The same request over REST tagged correctly. - The text, image, video, audio, document, template and reply tools take the field, forwarding it to the service they already call. - One shared schema takes both caps and the per-entry WID rule from the DTO rather than restating them. A tool handler calls the service directly, so the ValidationPipe never runs and this schema is the only thing between an agent and the engine. An invalid WID is now refused instead of being carried to the adapter. - Not offered on the sticker tool: both adapters build the sticker content without a mention list, so declaring it there would accept the field and drop it, which is the defect this change removes everywhere else. - MessageSendText.text binds to the shared cap constant the file already imports, matching MessageReply.text beside it. Same value, no change in behaviour. The REST/MCP cap-parity spec gains a mentions case, so the two sides cannot drift apart silently.
send-sticker shares SendMediaMessageDto, so the route takes a mentions array, buildMediaInput forwards it, and docs/06 lists send-sticker among the media send routes that accept the field. Both adapters then built the sticker content without a tag list, so the documented capability did nothing on either engine and the caller was told the send succeeded. A sticker carries neither text nor caption, but stickerMessage holds a contextInfo like every other content type, so the tag still reaches the participant. Same reasoning the audio path already records. Baileys spreads the existing withMentions helper into the content; whatsapp-web.js adds the list to the options bag it already passes, and omits the key when none were given so an untagged sticker send keeps its previous call shape.
Same silent drop as mentions, on the other field REST already declares. An agent that supplied a preview had the object stripped by the plain z.object before the handler ran, and the send went out with whatever preview the engine chose on its own. The schema takes all three caps from the DTO rather than restating them, and enforces the title WhatsApp requires: this path calls the service directly, so no ValidationPipe ever sees the object.
fix(engine): apply the mentions a sticker send accepts
feat(mcp): accept mentions on the agent tools
The sticker tool was left without mentions because neither adapter built a tag list for a sticker. That stopped being true one merge earlier: the adapters gained it, and this tool set was authored against the tree before that landed, so the exclusion and its three stated reasons shipped stale. The rationale contradicted itself inside one release: the changelog said the tool withholds the field because the adapters build no tag list, seven lines above an entry saying both adapters now build one. A test locked the drop in place, so it would have resisted the correction. - MessageSendSticker declares and forwards mentions, like the other seven send tools. The route has always accepted the field. - The exclusion test becomes an inclusion test, and the stale reasons in the shared schema docblock and the changelog are gone. - A comment explaining the sticker mimetype rule sits back above the test it explains; a test added last merge had landed between the two.
…-stale-rationale fix(mcp): tag a sticker send, and drop a rationale time made false
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )