用途与实际影响
这项功能怎样使用
为什么需要它
一条消息的含义可能取决于谁发的、回复哪条、附件是什么,以及当前窗口是不是完整历史。只按关键词抄一句,容易把群成员、本人、系统消息和引用目标混在一起。
举个实际例子
我问“项目群里最后是谁同意周五交付?”工具只翻这个群里够回答问题的一段,把说话人、时间和那句回复指向的原消息一起给我;主号、副号里都有同名群时,它先列候选,绝不蒙一个。
最后我会得到什么
交回这次确实读到的一小段聊天:账号、联系人或群、时间范围、说话人、原回复和附件可用性。若只有小窗口或有遗漏,会说明实际范围,不能当整段历史。
可直接使用
账号和对象唯一,窗口可读,影响问题的发送者、引用和媒体关系都已返回。
需要确认
对象重名、引用目标在窗口外、群成员标签不全或媒体打不开时,保留候选和缺口,并只扩大必要范围。
当前不可用
账号配置、身份承诺、本地消息库、时间索引或输出边界不成立时停止,不换来源补猜。
从哪里开始
说明账号、联系人或群,以及要问的那段微信事实。
需要准备什么
- 微信账号和要看的联系人或群
- 时间、关键词或本人参与线索(如有)
从开始到拿到结果
- 1
系统核对并处理
先从会话变化或本人参与定位小范围,再读足够前后文和原回复,不导出整个账号。
- 2
交付与接续
交回说话人、时间、回复及媒体缺口;对象不唯一或范围不足时停下补线索,不猜是谁。
技术实现与依据
这里保留实现、关键条件、精确入口、历史记录和验证结果。
9月9日来源投影、上下文与候选发现45项及6子测试通过,Doctor成功;真实具名会话未读取关键规则与设计选择
coverage.hasMore 与 continuation 决定是否还需续查;游标固定账号、聊天、时间范围和搜索条件,每次调用仍是独立本地快照,不宣称历史跨页永不变化。
not_found_in_page 不等于请求窗口未命中;末页 not_found_in_remaining_window 只说明剩余范围,存在正文解码缺口时不能说从未说过。
coverage.returnedAllScanned 明确展示是否包含所有扫描消息;关键词附近的小窗口不是完整历史,continuation.purpose 分开继续找命中与普通翻页。
聊天默认从最小窗口开始,不先创建全量档案。
auto 只有唯一匹配时才选择账号;多匹配必须由用户决定。
返回窗口的 self=0 只表示这段没有观察到本人消息,不代表全历史没有。
空窗口仍说明当前会话是否存在更早或更新的本地可见消息。
私聊与群聊引用目标均可按原生server id精确回查;源中缺失或无法读取时仍保留缺口,不保证全部回复都能补回。
只有会改变答案的媒体才需要进一步打开或转写。
本模块用到的名词
- Bounded context(有界上下文)
- 账号、对象、时间和返回数量都明确的一小段消息,不代表远端或本地全历史。
- Sender role(发送者角色)
- self、other、system 或 unknown(未验证);群聊还单独解析成员标签。
- availableHistoryHint
- 窗口为空时说明当前本机是否仍知道更早、更晚或不可读消息存在。
- manifestSha256
- 对本次规范结果计算的整体内容指纹,用于确认回执没有静默变化。
专业定义
先用changes发现当前变化候选,再对明确对象读取有界上下文;可以先筛本人参与,缺少他人回应时再补读。
解决什么
解决错账号、错对象、截断上下文、发送者混淆、小窗口冒充全历史和附件关系丢失。
当前怎样实现
- changes固定discovery.requestedWindow.untilS;按明确primary/secondary/both独立读取当前SessionTable,保留隐藏会话、时间未知项和observed_after_until候选。completeScope只覆盖当前表,historicalChangeDetection明确不检测已消失会话、旧消息补入/撤回、正文或标签修订。
- --self-only在fetch_messages解码前按当前分片发送者方向筛self/unknown(未验证),selectionScope与coverage.senderScope均为self_messages_and_unresolved_senders。v2游标绑定selfOnly,续查不能改变筛选;v1普通游标继续兼容。引用目标按原生ID补取,不把筛选结果当作全群上下文。
- _resolve_contact 在 primary / secondary 槽位中按当前联系人目录解析唯一对象,contact_ambiguous 返回公开安全候选。
- _context_result 校验扫描与返回上限,按 since / until / lookback / around / contains 形成有界窗口。
- _sender_receipt 保留 self、other、system、unknown(未验证) 与群成员标签;文件传输助手只加标签,不改写原生角色。
- 返回 scannedSenderRoleCounts、returnedSenderRoleCounts、selfObservation、availableHistoryHint 与 gaps。
- Canonical JSON(规范 JSON)计算 manifestSha256;超过 512 KiB 直接 context_output_too_large。
- context --byte-limit限制32–512KiB终端JSON,普通continuation负责其余消息;segmentedFields仅是长字段预览,message-part绑定同一显式账号/对象、偏移和whole-text hash(内容指纹)续读。source_changed要求重新context,不能跨版本拼接;便携export-context仍保存选定全文。
执行流程
- 1
读取两个隔离账号槽位的公开安全配置结构。
- 2
解析唯一联系人或群,失败时返回未命中或候选。
- 3
按请求时间与上限读取一个本地快照;--around 优先取最靠近锚点的消息,再按时间排序,续查上界固定但每页快照独立。
- 4
围绕关键词或时间锚点选择最多 80 条。
- 5
补全发送者、回复目标和媒体缺口。
- 6
写出带实际范围与哈希的 JSON,不修改任何源数据。
边界
- 最多扫描 500 条、返回 80 条,默认回看 7 天。
- 不自动把窗口扩大到整个联系人、群或账号。
- 当前设备本地可见范围不等于微信远端全历史。
- changes完整不等于历史变化完整;self-only完整不等于全群上下文完整;精确引用回查仍受本机可读范围约束。
- 不把真实联系人、聊天正文或媒体复制到网页。
失败与恢复
- 多个账号或对象精确匹配
- 返回 contact_ambiguous 候选,等待用户选定,不取第一项。
- 关键词或时间锚点未命中
- 返回明确锚点缺口;只在用户需要时调整窗口。
- 回复目标或媒体不在当前可见范围
- 保留 quote_target_missing / media_not_openable 等 gaps,不伪造正文。
- 消息库缺索引或输出过大
- 停止对应请求,缩小范围或修复源级索引后重试。
真实入口
README.md · context自然语言用途、命令示例与小窗口边界。
wechat_cli.py · _resolve_contact / _context_result唯一对象解析、窗口选择、发送者、回复和结果合同。
wechat_source.py · fetch_messages分片消息读取、内容投影、索引与媒体关系。
tests/test_wechat_cli.py对象歧义、窗口角色、引用目标、媒体缺口和空窗口回归。
如何验证
- test_exact_contact_ambiguity_never_picks_first 验证多匹配不猜。
- test_context_keeps_native_ids_quote_target_and_media_gap 验证消息、引用和媒体缺口。
- test_empty_context_reports_that_older_local_history_exists 验证空窗口不冒充全历史为空。
- 真实可用性仍需用户点名对象后的 context E2E(端到端验证),本次网页刷新未执行。
与其他模块的关系
这是一次性问题的默认入口;需要长期保存时进入“具名增量归档”,需要打开附件时进入“回复与媒体关系”。
