architecture-logs-as-bridge.md 7.1 KB

架构:以日志为桥(Logs as Bridge)

一句话总结

OpenCode 是代码编辑器,Python 脚本是干活的,日志是它们之间的事实契约。

OpenCode 永远不碰游戏进程。Python 脚本(CPython 运行时,不是 Bun)可以在任何 Windows 会话里跑游戏、写日志。OpenCode 读日志、改代码、循环往复。

为什么必须这样

物理墙

传奇 cq2.exe 的反作弊 DLL
    │
    ├─ 扫描同 Windows 会话内的所有进程
    │
    └─ 命中 Bun 运行时(JIT 区、NAPI 句柄、HTTP 栈)
       → Segfault at 0x3C
       → OpenCode 闪退

任何跟游戏同会话的进程都有被踩的风险。Bun 特别脆(unmanaged JIT + NAPI), CPython 相对耐打,.NET 工具也基本安全。

我们试过、失败过的方案

方案 失败原因
OpenCode 跟游戏同会话 Bun 段错误
切换 Windows 用户(Plan E) 解决"共存崩溃",但不解决"OpenCode 调试游戏"——跨会话无法 Frida/读内存
WSL2 装 OpenCode 700MB AppxBundle 从国内被限速到 0 字节/分钟
Hyper-V 虚拟机 隔离 OK,但重、配置多;用户没明确选这条路

最后剩下的可行解

让 OpenCode 跟游戏彻底不直接通信,通过日志文件做信息中转:

┌──────────────── Windows 会话(你的开发机)─────────────────┐
│                                                             │
│  ┌────────────┐    写代码     ┌──────────────┐             │
│  │  OpenCode  │ ────────────► │  Python SDK  │             │
│  │  (Bun)     │              │  (CPython)   │             │
│  └──────┬─────┘              └──────┬───────┘             │
│         │                            │                      │
│         │  读 ◄──── JSONL ──── 写    │                      │
│         │            ▲               │                      │
└─────────┼────────────┼───────────────┼──────────────────────┘
          │            │               │
          │            │               │  HTTP / TCP / 进程调用
          │            │               ▼
          │            │      ┌──────────────────┐
          │            │      │   cq2.exe + 反作弊 │
          │            │      │  (任何 Windows 会话)│
          │            │      └──────────────────┘
          │            │
          │   ┌────────┴────────┐
          │   │  D:\传奇\        │
          └──►│  debug_logs\   │
              │  session_*.jsonl│
              └─────────────────┘

OpenCode 在 Administrator 会话读 D:\传奇\debug_logs\session_*.jsonl, Python 脚本在 cq2play 会话(或同会话)跑游戏并写日志。 两个进程通过文件系统解耦。

这个架构能覆盖什么

调试需求 覆盖? 怎么覆盖
看 996box HTTP 登录请求/响应 ✅ log.http_request / log.http_response
看 EnterGameClient 启动协议 ✅ 同上
解析 4 种签名算法 ✅ 写日志的 body_preview 里有明文
看 Lua 文件解密过程 ✅ log.info("decrypted", path=..., size=...)
看 TCP 帧编码 ✅ 写 step("send_frame", hex=..., len=...)
复现失败场景 ✅ 整个 session 一个文件,可 rewind
跨多次跑 diff ✅ 两个 JSONL diff 或 jq 过滤
Frida 注入游戏进程 ❌ 必须同会话、注入到游戏;不在本架构范围
读 cq2.exe 内存 ❌ 同上
实时操控游戏内行为 ❌ 同上

约 80% 的 SDK 开发需求(登录、协议、消息、签名、加密、状态机)都通过日志 覆盖。剩下 20%(运行时 hook/内存读写)必须用 Frida/ReadProcessMemory, 那一块要靠离线逆向 + 协议推断代替。

跟传统"同会话调试"的对比

维度 同会话调试 日志为桥
OpenCode 崩溃风险 100% 0%(不碰游戏)
协议逆向 需要看抓包工具 直接在 SDK 写日志,更精确
跨次对比 困难(要保存抓包) 天然(一个 session 一个文件)
AI 友好度 一般(pcap 二进制) 高(JSONL 是 LLM 训练数据格式)
复现成本 每次手动 跑一次就有完整证据
实时性 强(同步看到) 弱(必须跑完一轮才能看)
覆盖范围 100% 80%

用 20% 的实时性换 0% 的崩溃率 + 100% 的可复现性,对 SDK 开发是值得的。

关键组件

cq2_sdk.debug_log.DebugLogger

单文件、单类、~170 行的 JSONL logger:

  • 每个 session 一个文件:D:\传奇\debug_logs\session_<时间戳>_<6字符>.jsonl
  • 一行一个事件,标准 JSON
  • 4 个核心方法:info / warn / error / log
  • 2 个 HTTP 方法:http_request / http_response(带 req_id 关联)
  • 1 个流程方法:step("login_attempt", ...)
  • 上下文管理器:自动写 session_start / session_end,异常自动落 error
  • 线程安全:每实例一个 threading.Lock

单测 24/24 通过。详见 tests/unit/test_debug_log.py。

日志目录

D:\传奇\debug_logs\
├── session_20260916_103345_a1b2c3.jsonl
├── session_20260916_142017_d4e5f6.jsonl
├── session_20260916_180812_789abc.jsonl
└── ...

每个文件一次完整跑(一次登录、一次启动、一次 13 任务执行)。 不要在一次跑里跨多个 session——会丢失时间序列。

怎么让 OpenCode 读日志

不需要特别配置。直接在 OpenCode 里说:

"读 D:\传奇\debug_logs\ 目录下最新的 session_*.jsonl,看 box_996.py 里的 sign 算法用的是哪一种"

OpenCode 会用 read 工具读文件,grep 过滤 event=http_request, 对比 sign 实现。这个用法才是 OpenCode 的正确打开方式——它是 LLM, 不是反作弊对抗工具。

什么时候该升级架构

如果某天发现:

  • 大量调试时间花在"看协议日志但 SDK 行为还是对不上"上 → 考虑 WSL2 + 实时
  • 需要 Frida hook 游戏 → 必须同会话,准备 Plan E 双用户 + 把 Frida 跑在 cq2play
  • 需要直接读 cq2.exe 内存 → 没办法,只能接受崩溃风险或换独立机器

在那之前,日志为桥就是最佳架构。

相关文档

  • docs/debug-session-workflow.md — 日常怎么用、怎么读日志、怎么加日志
  • docs/two-user-workflow.md — Plan E 双用户切换流程(用于实际玩 cq2 时)
  • src/cq2_sdk/debug_log.py — 实现源码
  • scripts/demo_debug_log.py — 4 种典型用法示例