from pathlib import Path import hashlib import json import shutil root = Path('C:/wechat_rpa') audit = Path(__file__).resolve().parent target = root / 'protocol_engine.py' before = target.read_bytes() text = before.decode('utf-8') old = "def session_key(account,conversation):return hashlib.blake2b((account+'\\0'+conversation).encode(),digest_size=40).hexdigest()" new = '''def _is_text_message(message): try:return int(message.get('content_type') or 0) in (0,1,2) except (TypeError,ValueError):return False def _unanswered_requires_manual(context): # A text caption after an image/voice is still a media question. Only inspect # the unanswered batch: media already handled by a human must not block later text. for message in reversed((context or {}).get('messages') or []): if message.get('is_self'):break if not _is_text_message(message):return True return False ''' + old assert text.count(old) == 1 text = text.replace(old, new) old = " self._save()\n def _save(self):" new = """ # A restart must preserve the same pause as an unknown live send result. self.needs_attention=any(s.get('account')==self.account and s.get('send_state')=='uncertain' for s in self._pending.values()) self._save() def _save(self):""" assert text.count(old) == 1 text = text.replace(old,new) old = """ if int(state.get('content_type') or 0) not in (0,1,2): self._stage(key,'error','此消息类型需要人工处理','当前协议版只自动处理文本消息');return if not state.get('reply_text'): self._stage(key,'generating','根据当前会话生成回复') context=self.db.get_conversation_context_by_id(self.account,state['conv_id'],limit=100) """ new = """ context=self.db.get_conversation_context_by_id(self.account,state['conv_id'],limit=100) if not _is_text_message(state) or _unanswered_requires_manual(context): with self._lock:state.update(reply_text='',staged_reply_text='',approved=False,awaiting_review=False) self._stage(key,'error','此消息类型需要人工处理','当前未回复消息包含图片、语音或其他非文本内容,协议版需人工处理');return if not state.get('reply_text'): self._stage(key,'generating','根据当前会话生成回复') """ assert text.count(old) == 1 text = text.replace(old,new) backup = root / 'backups/recognition-audit-20260916' backup.mkdir(parents=True,exist_ok=True) save = backup / target.name assert not save.exists(), f'Backup already exists: {save}' save.write_bytes(before) target.write_text(text,encoding='utf-8') shutil.copy2(audit/'test_protocol_audit_boundaries.py', root/'test_protocol_audit_boundaries.py') result = {'target':str(target),'backup':str(save), 'before_sha256':hashlib.sha256(before).hexdigest(), 'after_sha256':hashlib.sha256(target.read_bytes()).hexdigest(), 'added_test':str(root/'test_protocol_audit_boundaries.py')} (audit/'protocol-fix-manifest.json').write_text(json.dumps(result,indent=2),encoding='utf-8') print(json.dumps(result))