feat: restore ID-only quoted messages with a local SQLite cache - #283
Merged
6 commits merged intoSep 8, 2026
Merged
6 commits merged into
6 commits merged into
Conversation
added 5 commits
September 2, 2026 16:21
8 tasks
# Conflicts: # src/channel.ts # src/messaging/error-notice.ts # src/messaging/inbound.test.ts # src/messaging/process-message.ts
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.
Summary
ref_msg.svr_id.node:sqliteis unavailable.Motivation
Newer WeChat clients may omit the quoted message body and send only its server message ID. Without local reconstruction, text quotes lose their context and attachment quotes degrade to placeholders such as
[文件], leaving the agent unable to identify or read the referenced content.This change preserves the quote experience for existing plugin users despite that client-side protocol change.
Implementation
message_id,msg_id, andsvr_idlosslessly as strings to avoid JavaScript integer precision loss.media/inbound/workspace hint so file/PDF tools can read the attachment when automatic extraction fails.Retention and compatibility
The cache is enabled by default with these bounded defaults:
The limits and
enabledflag are configurable underchannels.openclaw-weixin.quoteCache. Ifnode:sqliteis unavailable or the database cannot be opened, quote caching is disabled without an in-memory fallback. Cache failures never interrupt normal message delivery.Messages that predate cache initialization cannot be reconstructed and return an explicit cache-miss placeholder.
Change size
The PR adds 2,331 lines and removes 56 lines across 26 files. The additions break down as follows:
The two largest files are the self-contained SQLite/media lifecycle implementation (
quote-store.ts, 649 lines) and its focused tests (quote-store.test.ts, 516 lines). The store covers schema initialization, account/conversation isolation, legacy-path migration, retention, count and byte-budget eviction, orphan cleanup, account deletion, and compatibility fallback.Validation
Automated
2645786ab5f866bc3ca96775f032dd6e9adc53d7npm run typechecknpm test: 29 test files and 452 tests passedManual local end-to-end evidence
The following excerpts are from one local OpenClaw session on 2026-09-02 (Asia/Shanghai). User/account identifiers, filenames, full local paths, and server message IDs are redacted; timestamps, MIME type, byte size, tool result, and behavior are preserved.
1. ID-only text quote was reconstructed from SQLite
This proves the agent received the stored quoted body rather than only the quote marker/ID.
2. Quoted PDF metadata and its managed file were retained
3. The agent used the supplied path and reached the quoted file
This demonstrates the intended fallback: WeChat still supplies
[文件]as the display body, while the plugin restores the actual attachment metadata/path and the agent can access that file with a tool.The local runtime package was installed at 15:32:43. Its quote-critical sources (
quote-store.ts,inbound.ts,send.ts,api.ts, config/types/media/partial-quote processing) match this PR HEAD byte-for-byte. Itschannel.tsadditionally contained the unrelated local PR #269 outbound-route change, so this log is reported as manual runtime evidence rather than an exact-head CI artifact. SQLitePRAGMA integrity_checkreturnedokafter the run.