Repository navigation
fix: gaps whatsapp-cli hit — providerRef leak, store-history sync, MCP delete for everyone, stored lookup in connect - #1423
Merged
Merged
Conversation
watch --jsonl, bot watch --jsonl and every answer envelope now drop providerRef/provider_ref at any depth. An adapter keeps there what it needs to fetch a file again: WhatsApp's media path and decryption keys, a MAX bot's token. Every stored read already dropped it through messageItem; live events and raw adapter answers did not. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ne (BUG-271) The attachment upsert took provider_ref from the newer copy, so an edit event or a re-push without keys erased the ones that fetch the file. A null or empty providerRef now keeps the stored value; a new one still replaces it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…BUG-272) services.messages.download passed the chat as typed, a name or an id, straight to the adapter; forward, edit and the other writes resolve it first. It now resolves it the same way, and download --all hands each message's own chat id. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ry (BUG-273) A messenger with history: "store" (WhatsApp) has no server history: messages sync refuses there. Its search messages, stats messages show, rankings top, search conversations and contacts context no longer mount --sync-first, the search help says serve keeps the archive instead of messages sync --all --background, and contacts and chats documents suggest no messages sync step. Over MCP the sync_first arguments are hidden and the search, stats and conversations descriptions drop them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The MCP delete tool only deleted the owner's copy, so a messenger that deletes only for everyone (WhatsApp refuses delete-for-me) could never delete through MCP. for_everyone passes through to the same service and send guard the CLI's --for-everyone uses: the delete permission, the hourly limit and the journal. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…G-275) ReadState now holds markRead alone, so a messenger without forum topics (MAX, WhatsApp) implements ReadState in full instead of Pick<ReadState, "markRead">. markTopicRead is TopicReadState, optional on MessengerAdapter like every other group, and capability() refuses it where absent. chats_mark_read over MCP no longer offers topic where Messenger.topics is false, as the CLI's --topic already did. BREAKING CHANGE: code that reads markTopicRead through the ReadState type must use TopicReadState; implements ReadState and Pick usages compile unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tg, max and wa all have `<tool> <profile> setup`. When the CLI mounts a setup command, a profile with no recorded account is told to link it with setup and then run serve or watch (a store-history messenger), or to log in with setup or run without --offline (one with server history). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…BT-126) ConnectOptions.stored hands an adapter what the local store holds of its own account: message(chatId, id) and newestIncoming(chatId, before?). WhatsApp addresses a message by its sender and whether it is the owner's, so edits, reactions and read receipts look it up first; wa opened a second store handle in its connect to do it. Every connect the shared commands make now passes it over the store the command already has: withServices' own store, and for withMessenger and the MCP session one lazily opened handle shared with what the reads save (connectedFor). A command run through serve borrows serve's connection and its lookup. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… version NEED-1406's skew warning was already there: serve writes its version into the lock beside relay, and the client compares it before relaying (src/cli/program.ts). Nothing tested it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…f fixes Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Task
Fix the cli-core gaps whatsapp-cli (
wa) hit, so wa can drop its workarounds.Why
wa is the first messenger with
history: "store"(WhatsApp has no server history) and the first whose attachments carry decryption keys inproviderRef. Several shared paths assumed a Telegram-shaped messenger.What
watch --jsonl,watch --events --jsonland the botwatch --jsonlprinted the adapter's live event withproviderRef(WhatsApp: media path + decryption keys; MAX bot: token). Now every answer envelope (CLI JSON, JSON lines, pretty, MCP) and the watch lines dropproviderRef/provider_refat any depth (src/cli/provider-refs.ts, applied insealed()/renderAnswer).providerRef(edit event, re-push) keeps the stored value.--sync-firstand its bounds, MCPsync_first, themessages sync --all --backgroundhelp, and themessages syncnext steps in contacts and chats documents are not offered whenhistory: "store".messages_deletetakesfor_everyone, under the same service and guard as--for-everyone.ConnectOptions.stored: a read-onlyStoredMessageslookup (message(chatId, id),newestIncoming(chatId, before?)) over the command's own store handle, given on every shared connect (withServices, withMessenger, MCP session, and so serve's relay).ReadStateismarkReadalone;markTopicReadmoves to the new optionalTopicReadState. MCPchats_mark_readhidestopicwheretopics: false.<tool> <profile> setupfirst when the CLI has a setup command.src/cli/program.ts, lockversion); nothing tested it.Changelog under Unreleased. "Changed — may break callers" covers
ReadState,syncOptions(command, messenger)and download's resolved chat id.Downstream
tg-cli, max-cli, cli-memo: nothing breaks. They have server history, so their sync options and steps stay. Their adapters still compile: tg's class has both read methods, and max uses
Pick<ReadState, "markRead">. max'sdownloadresolves an id too. No downstream code readsprovider_reffrom output.Testing
vitest run: 4925 passed.pnpm ci:quickand the lint are green.--events, stored reads and run logs, and also through CLI and MCP envelopes. BUG-271 has a store round trip. BUG-272, BUG-273 (CLI help and MCP schema and description), BUG-274, BUG-275 and UX-58 each have their own test. DEBT-126 runs a lookup through a real send.🤖 Generated with Claude Code