{
  "module": "usage_collector",
  "version": "3.0",
  "purpose": "OpenCode Go 订阅用量采集脚本 — Hybrid v3.0。混合采集：主模式 HTTP + stored cookies（4 个账号同时采集），辅助模式 CDP（仅 Chrome 当前登录账号补充/验证）。从 opencode.ai SSR HTML 解析 rolling/weekly/monthly 用量百分比和倒计时，写入 temp/usage_stats.json。支持 --daemon 持续采集（每 5 分钟）。",
  "ui_location": "Infrastructure tab → OpenCode Go Usage section（通过 dashboard.py 的 /api/usage 和 /api/usage/refresh）",

  "human_help": {
    "title": "OpenCode Go Usage Collector — 用量采集脚本",
    "description": [
      "usage_collector.py 是一个 Python 脚本，从 opencode.ai 的 SSR HTML 中解析 4 个订阅账号的用量数据（5h rolling / weekly / monthly），写入 JSON 缓存供 dashboard 展示。",
      "混合采集模式：① 主模式 — HTTP + stored cookies，可同时采集所有账号（无需 Chrome 登录态切换），快但需要预先提取 cookies ② 辅助模式 — CDP 通过 Chrome tab 获取，只能采集当前登录账号，慢但不需要预先提取 cookies（httpOnly cookies 由浏览器自动携带）。",
      "Cookie 提取：一次性操作 — python extract_cookies.py key1 --workspace-id wrk_XXX → cookies/key1.json。每个账号登录后执行一次。",
      "SSR 解析：主模式用 per-metric regex 解析 HTML 中的 usagePercent + resetInSec（处理嵌套 $R[N]={} 格式）；CDP 辅助模式通过 CDP /eval 执行 JS fetch 获取完整 HTML 并解析。"
    ],
    "usage": [
      "1. 首次配置: 逐个登录 4 个 opencode 账号 → python extract_cookies.py key{N} --workspace-id wrk_XXX",
      "2. 采集: python usage_collector.py（一次性采集全部账号）",
      "3. 守护: python usage_collector.py --daemon（每 5 分钟自动采集）",
      "4. 仅 CDP: python usage_collector.py --cdp-only（仅采集 Chrome 当前登录账号）",
      "5. 打印结果: python usage_collector.py --print",
      "6. Dashboard: GET /api/usage（读缓存）/ POST /api/usage/refresh（触发采集）"
    ],
    "troubleshooting": [
      "如果某账号采集失败: 检查 cookies/{key_id}.json 是否存在且有效 — Session 可能已过期",
      "如果 CDP 模式不可用: 确认 Chrome 以 --remote-debugging-port=9222 启动 + cdp-proxy.mjs (3456) 在运行",
      "如果 SSR 解析失败: opencode.ai 的 SSR hydration 格式可能已变更 — 需要更新 regex",
      "如果 usage_stats.json 为空: 检查脚本是否有文件写入权限 + TEMP_DIR 是否存在",
      "如果采集结果过旧: 检查 --daemon 是否在运行，或手动触发 Refresh"
    ]
  },

  "ai_spec": {
    "apis": [
      {"method": "N/A (CLI)", "path": "python usage_collector.py [--daemon|--cdp-only|--print]", "returns": "写 temp/usage_stats.json + stdout 日志", "note": "CLI 脚本，非 HTTP API"},
      {"method": "CDP call", "path": "localhost:3456/targets + /eval", "returns": "SSR HTML (CDP mode)", "note": "通过 cdp-proxy.mjs 与 Chrome 通信"},
      {"method": "HTTP GET", "path": "https://opencode.ai/workspace/{ws_id}/go", "returns": "SSR HTML (HTTP mode)", "note": "带 Cookie header (从 cookies/{key_id}.json 读取)"}
    ],
    "dependencies": [
      "usage_monitor/accounts.json — 账号 workspace ID × key_id × label 配置 (.gitignore)",
      "usage_monitor/cookies/{key_id}.json — 存储的 cookies (httpOnly auth cookie, .gitignore)",
      "cdp-proxy.mjs (localhost:3456) — Chrome 远程调试代理 (CDP 辅助模式)",
      "Chrome (Windows) with --remote-debugging-port=9222 — 浏览器 + 登录态",
      "Python 3.10+ (stdlib only: urllib, json, re, logging, http.cookiejar)",
      "temp/usage_stats.json — 输出缓存 (dashboard.py 直接读取)",
      "opencode.ai API — 无公开 API，唯一数据来源是 SSR hydration script"
    ],
    "architecture": {
      "flow": "主模式: 遍历 accounts.json → 读取 cookies/{key_id}.json → HTTP GET opencode.ai workspace page → 正则解析 SSR HTML → CDP 辅助: Chrome tab → fetch(location.href) → 解析 → 合并结果 → 写 usage_stats.json",
      "dual_collection": "主模式（HTTP cookies）可同时采所有账号 / CDP 辅助（Chrome browser）仅当前登录账号 / 两种结果合并: CDP 优先，HTTP 补充",
      "regex_parsing": "per-metric regex 匹配 rollingUsage:$R[N]={status,usagePercent,resetInSec} — 处理嵌套 $R[N]={} 而非简单 blob regex",
      "daemon_mode": "每 5 分钟自动采集 — time.sleep(300) 循环",
      "cookie_rotation": "不同账号有独立 cookie 文件 — cookies/key1.json, cookies/key2.json, ... — cookie 文件通过 extract_cookies.py 生成"
    },
    "constraints": [
      "accounts.json 不可提交 git — 已加入 .gitignore",
      "cookies/*.json 不可提交 git — 含 httpOnly auth cookie",
      "采集频率 ≥ 5min — 过密会触发 opencode.ai 风控",
      "不要用 blob regex 解析 SSR — 嵌套 $R[N]={} 会导致 [^}]* 在内层 } 处断",
      "CDP 辅助模式仅在主模式失败或需验证时使用 — 依赖 Chrome 登录态",
      "Cookie 过期后需重新提取 — extract_cookies.py 每个账号执行一次"
    ],
    "must_not": [
      "不要把 accounts.json 或 cookies/*.json 提交到 git",
      "不要在采集脚本中硬编码 workspace ID — 必须从 accounts.json 读取",
      "不要尝试用 Python requests + 提取的 cookies 单独采集 — httpOnly cookies 无法通过 document.cookie 提取",
      "不要用 blob regex 解析 SSR — 用 per-metric regex"
    ],
    "related_modules": [
      {"module": "usage_monitor", "relation": "usage_collector 是 usage_monitor 模块的数据采集层 — 采集结果供 dashboard 的 usage_monitor 展示"},
      {"module": "dashboard", "relation": "dashboard 通过 /api/usage/refresh 触发采集 + /api/usage 读取缓存 + auto-timer 自动触发"},
      {"module": "xmpp_bot", "relation": "xmpp_bot 的 /usage 端点也可触发采集（旧版用法，新版 dashboard 直接 subprocess 调用）"}
    ],
    "tests": [
      {"id": "UC01", "name": "accounts.json 解析正确", "endpoint": "读取 accounts.json → 过滤出有 workspace_id 的记录"},
      {"id": "UC02", "name": "HTTP 主模式采集返回有效数据", "endpoint": "带 cookie 的 HTTP GET → 解析 usagePercent > 0"},
      {"id": "UC03", "name": "CDP 辅助模式在 Chrome 启动时可用", "endpoint": "CDP /targets → 找到 opencode.ai tab"},
      {"id": "UC04", "name": "输出 usage_stats.json 格式正确", "endpoint": "采集后检查 JSON schema: accounts 数组 + last_refresh_iso"},
      {"id": "UC05", "name": "--daemon 模式每 5 分钟采集", "endpoint": "--daemon 启动后连续 2 次采集间隔 ≈ 300s"}
    ],
    "known_issues": [
      "opencode.ai Go 用量目前无公开 API — PR #16513 未上线，数据唯一来源是 SSR hydration script",
      "Cookie 有效期: opencode.ai session cookies 可能随时过期 → session_expired 标记提醒用户重新登录",
      "CDP proxy 依赖: 若 Chrome 关闭或 cdp-proxy.mjs 未运行，CDP 辅助模式将失败",
      "HTML 返回大小: CDP /eval 返回完整 SSR HTML (~16KB)，可用带宽消耗"
    ],
    "related_files": [
      "gateway/scripts/usage_collector.py — 本文件 (742行, v3.0)",
      "gateway/scripts/usage_monitor/accounts.json — 账号配置 (.gitignore)",
      "gateway/scripts/usage_monitor/cookies/{key_id}.json — Cookie 文件 (.gitignore)",
      "gateway/scripts/usage_monitor/extract_cookies.py — Cookie 提取工具",
      "gateway/temp/usage_stats.json — 采集结果缓存",
      "gateway/scripts/specs/usage_collector.json — 本 spec",
      ".opencode/skills/web-access/scripts/cdp-proxy.mjs — CDP proxy (3456)"
    ]
  }
}
