89 lines
4.5 KiB
Python
89 lines
4.5 KiB
Python
from pathlib import Path
|
|
import shutil
|
|
|
|
ROOTS = [Path('C:/wechat_rpa'), Path('C:/kefu/wechat_rpa')]
|
|
|
|
|
|
def replace_once(source, before, after):
|
|
assert source.count(before) == 1, (before[:100], source.count(before))
|
|
return source.replace(before, after)
|
|
|
|
|
|
for root in ROOTS:
|
|
target = root / 'wechat_bot.py'
|
|
original = target.read_bytes()
|
|
source = original.decode('utf-8').replace('\r\n', '\n')
|
|
source = replace_once(source,
|
|
' value.get("confirmed_unread", False)\n or str(value.get("send_state") or "")\n',
|
|
' value.get("confirmed_unread", False)\n or value.get("awaiting_review", False)\n or value.get("review_approved", False)\n or str(value.get("stage") or "") == "manual_review"\n or str(value.get("send_state") or "")\n')
|
|
marker = ' "awaiting_review": bool(value.get("awaiting_review", False)),\n'
|
|
assert source.count(marker) == 2
|
|
source = source.replace(marker, marker + ''' "review_reason": str(value.get("review_reason") or "")[:500],
|
|
"review_origin": str(value.get("review_origin") or "")[:16],
|
|
"review_approved": bool(value.get("review_approved", False)),
|
|
"review_approved_at": value.get("review_approved_at", 0.0),
|
|
"judge_risk": str(value.get("judge_risk") or "")[:32],
|
|
"judge_reason": str(value.get("judge_reason") or "")[:500],
|
|
''')
|
|
source = replace_once(source,
|
|
' if send_baseline_blocks is not None:\n',
|
|
''' # Older clients discarded review reasons. Treat an unclassified
|
|
# restored draft as still requiring a decision, never as permission
|
|
# to send merely because the global mode is now automatic.
|
|
if state["awaiting_review"] or (
|
|
state["stage"] == "manual_review" and not state["review_approved"]
|
|
):
|
|
state["awaiting_review"] = True
|
|
state["stage"] = "manual_review"
|
|
if not state["review_reason"] and state["review_origin"] != "global":
|
|
legacy_detail = str(value.get("stage_detail") or "")
|
|
state["review_reason"] = (
|
|
legacy_detail[:500]
|
|
if "命中审核规则" in legacy_detail or "裁判" in legacy_detail
|
|
else "历史审核原因未保存,请人工核对本条草稿"
|
|
)
|
|
if send_baseline_blocks is not None:
|
|
''')
|
|
source = replace_once(source,
|
|
''' if self._reply_awaiting_review(fp):
|
|
self._set_task_stage(
|
|
fp,
|
|
"manual_review",
|
|
detail="AI 回复已填入输入框,等待人工核对并发送",
|
|
)
|
|
self._log_queue_event(fp, "待审核", "回复草稿已填入企业微信输入框")
|
|
return
|
|
''',
|
|
''' if self._reply_awaiting_review(fp):
|
|
state = self._pending_reply_state(fp) or {}
|
|
reason = str(state.get("review_reason") or "").strip()
|
|
detail = (
|
|
f"{reason},已停止自动发送,等待人工核对并发送"
|
|
if reason else "AI 回复已填入输入框,等待人工核对并发送"
|
|
)
|
|
self._set_task_stage(fp, "manual_review", detail=detail)
|
|
self._log_queue_event(fp, "待审核", detail)
|
|
return
|
|
''')
|
|
source = replace_once(source,
|
|
' state.pop("review_reason", None)\n',
|
|
''' state.pop("review_reason", None)
|
|
state.pop("review_origin", None)
|
|
state.pop("judge_risk", None)
|
|
state.pop("judge_reason", None)
|
|
state.pop("judge_score", None)
|
|
state.pop("model_chosen", None)
|
|
state.pop("model_candidates", None)
|
|
''')
|
|
source = replace_once(source,
|
|
' pending_state["review_reason"] = rule_reason\n',
|
|
' pending_state["review_reason"] = rule_reason\n'
|
|
' pending_state["review_origin"] = "global" if blanket_review else "rule"\n')
|
|
backup = root / 'backups/review-visibility-20260916'
|
|
backup.mkdir(parents=True, exist_ok=True)
|
|
assert not (backup / target.name).exists(), 'Backup already exists; inspect before rerun'
|
|
shutil.copy2(target, backup / target.name)
|
|
newline = '\r\n' if b'\r\n' in original else '\n'
|
|
target.write_bytes(source.replace('\n', newline).encode('utf-8'))
|
|
print(root, 'patched visual review persistence and reasons')
|