← Open Source
ardeyouxipianyi

workbuddy2api-hub

WorkBuddy 国际国内多账号反代网关,支持 Codex / Claude Code / DSH与标准 OpenAI 客户端。

InfrastructureObservabilityGatewayPython
Open on GitHub
Momentum
+93stars in 24 hours+11.2%
927
Stars
208
Forks
+326
This week
21
Contributors
Created 2026-09-12 · Updated 2026-10-11 · #158 today
Top developers
README

WorkBuddy2API-Hub — 国际版、国内版多账号网关中枢

Version 1.6.20 Python OpenAI API Dual Realm License Vibe Coding

把腾讯 www.workbuddy.ai(国际版)与 codebuddy.cn(国内版)的原生服务封装成标准 OpenAI 兼容接口(Chat Completions / Responses)与原生 Anthropic Messages 接口,并补齐多账号调度与运维能力:

  • 开箱即用:绿色包自带精简 Python,双击脚本即启;
  • 双区域独立路由:国际版 / 国内版各自配置与调度,看板一键切换,状态落盘;
  • 三协议:Chat Completions、Responses API(Codex)、原生 Anthropic Messages(Claude Code / Anthropic SDK);
  • 模型目录对齐官方桌面端:剔除补全通道与专线变体,能力与规格按桌面端宣告,上游新模型无需发版即进 /v1/models;
  • 设备指纹隔离 (derive_id):以账号 UID 稳定派生机器码与会话标识,同一账号不漂移、不同账号互不关联;
  • 账号接入:看板点链接走浏览器 OAuth;Windows 上还能直接从运行中的桌面客户端导入(加密 token 就地解密);
  • 每日自动化:国内版签到 / 成长与积分任务 / 猫猫旅行;国际版每日活跃打卡(真跑完网页会话);后台调度器按 09:00 & 21:00、22:00、01:00 排程;
  • 限额护栏:保留积分 · 每日 Token · 每日积分 · 按模型 Token 四条账号级护栏,单账号独立计数,本地 0 点解封(默认全部关闭);
  • OpenRouter 价估算:把 token 折算成等价花费(人民币 / 美元可切),逐条请求可悬停查看定价来源;
  • 多 Key 与出口绑定:每个 Key 可固定走国际版或国内版、可限定模型,用量按 Key 归属;
  • Web 看板:指标卡片、模型性能与用量大表、请求流水、账号与任务管理一屏可查。

⚡ Vibe Coding 产物:本项目为 100% Vibe Coding 协同产物——人类开发者提出架构与业务意图,AI 助手端到端完成逆向分析、链路调度、WAF 指纹脱敏与界面编写。


一、快速启动

1. 本机运行

Windows 双击 start-wb-proxy.bat,保持窗口运行;macOS 双击 start-wb-proxy.command(首次被 Gatekeeper 拦截时右键 →「打开」确认一次),或在终端执行 ./start-wb-proxy.sh [端口](默认 8788)。

启动后:API 地址 http://127.0.0.1:8788/v1,Web 看板 http://127.0.0.1:8788/。首次启动还没有账号,打开看板点「+ 添加账号 (OAuth)」完成授权即自动入库。

zip 解压后若提示权限不足,先执行一次:chmod +x start-wb-proxy.sh start-wb-proxy.command start-wb-proxy-lan.sh start-wb-proxy-lan.command allow-firewall.command

2. 面板访问密码

看板需要面板访问密码(默认 admin),它与 API Key 相互独立:密码只用于打开看板,可在「设置」页修改(或启动时 --panel-password 指定),以 PBKDF2-SHA256 摘要存于 accounts/settings.json(不存明文),登录态只留在浏览器会话里。

本机 / 受信局域网自用可带 ?pwd=面板密码 免手输直接进面板(如 http://127.0.0.1:8788/?pwd=admin);公网暴露时不要用——密码会留在浏览器历史与反向代理日志里。注意它和局域网共享的 ?key= 不同:?key= 只把 API Key 存给 /v1 用,不会自动登录面板。首次登录后请立即改掉默认密码。

3. 局域网共享

  • Windows 双击 start-wb-proxy-lan.bat;macOS 双击 start-wb-proxy-lan.command,或 ./start-wb-proxy-lan.sh [端口] [Key];
  • Base URL http://<本机局域网IP>:8788/v1;带密钥直达面板 http://:8788/?key=生成的Key;
  • API Key:首次启动生成高强度随机 Key,写入 accounts/settings.json 并打印在终端,重启复用;也可用第二个参数指定自己的 Key;
  • macOS 防火墙:首次监听端口时选「允许」;macOS 15+ 还要在「系统设置 → 隐私与安全性 → 本地网络」允许终端,./allow-firewall.command 可查看状态并加白。

4. 多 API Key 与出口绑定

「设置」页可管理多个 Key,每个 Key 独立出口——不同客户端各用各的 Key,国内外流量互不干扰:

  • 生成 / 绑定:填名称点「生成随机 Key」;可固定走 🌐 国际版或 🇨🇳 国内版,不绑定则跟随看板顶部的全局出口开关;
  • 模型限制:可填允许的模型(如 deepseek*、gpt-6-astra,支持 *,逗号分隔),留空不限;不在列表里的请求本机直接返回 400,不送达上游、不消耗额度;
  • 区域自检:Key 绑定的出口与模型不匹配时(如国际版 Key 调国内独占的 deepseek-v4-pro)直接返回可读 400,而不是上游晦涩的 WAF 报错;
  • 启停 / 删除:可单独启停;删除后密钥立即失效,条目以只读形式留在「设置」页的「已删除」折叠区,历史用量仍显示它的名字;
  • 用量归因:「数据看板」页按 Key 列出请求数、Token、缓存命中、积分与模型分布,口径与账号表一致;
  • 防冲突:面板保存过 Key 后,启动参数里的 --api-key 自动失效。

5. Docker 部署

预编译双架构镜像(linux/amd64、linux/arm64)发布在 GHCR 与 Docker Hub,无需克隆代码、无需本地编译:

方式一:一键脚本(推荐)

# 官方源(可直连 GitHub 环境):
curl -fsSL https://raw.githubusercontent.com/ardeyouxipianyi/workbuddy2api-hub/main/quick-deploy.sh | bash

# 国内网络 / NAS 加速(Connection reset 时用):
curl -fsSL https://gh-proxy.com/https://raw.githubusercontent.com/ardeyouxipianyi/workbuddy2api-hub/main/quick-deploy.sh | sudo bash

NAS(如飞牛 fnOS)普通用户没有 Docker 权限时,把结尾的 bash 换成 sudo bash。再次运行同一条命令即平滑升级,账号与用量数据不受影响。

方式二:NAS / 面板单文件 Compose

在 NAS 或面板的 Compose 界面新建项目并粘贴以下内容保存启动,无需拉取源码:

services:
  wb-proxy:
    image: ghcr.io/ardeyouxipianyi/workbuddy2api-hub:latest   # 或 ardeyouxipianyi/workbuddy2api-hub:latest
    container_name: wb-proxy
    restart: unless-stopped
    ports:
      - "8788:8788"          # 左侧宿主端口可自选;右侧必须与下面的 PORT 一致
    environment:
      - HOST=0.0.0.0
      - PORT=8788
      # - API_KEY=your_secret_key   # 留空则自动生成并打印在启动日志
      - TZ=Asia/Shanghai
    volumes:
      - ./accounts:/app/accounts    # 账号凭证与配置(更新/重建容器不丢)
      - ./usage:/app/usage          # 用量流水日志(更新/重建容器不丢)

更新:面板里点「拉取最新镜像并重启」,或 docker compose pull && docker compose up -d。

方式三:Watchtower 自动静默更新

docker run -d --name wb-proxy-watchtower --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtower:latest --interval 86400 --cleanup wb-proxy

补充与排错

  • 持久化:./accounts 与 ./usage 由宿主机挂载,更新或重建容器都不丢数据;
  • docker run 快捷启动:
    docker run -d --name wb-proxy --restart unless-stopped -p 8788:8788 \
      -v $(pwd)/accounts:/app/accounts -v $(pwd)/usage:/app/usage \
      ghcr.io/ardeyouxipianyi/workbuddy2api-hub:latest
    
  • 鉴权:容器以 --lan 启动,无显式 API_KEY 时自动生成 Key 写入 ./accounts/settings.json 并打印在日志里:docker compose logs wb-proxy | grep -i "api key";
  • 镜像名要带 registry:写成 ardeyouxipianyi/workbuddy2api-hub 会去 Docker Hub 找并报 pull access denied,正确写法是 ghcr.io/ardeyouxipianyi/workbuddy2api-hub:latest(GHCR 公开包,拉取无需登录);
  • 目录权限:默认以 root(0:0)运行;想以宿主用户跑就设 PUID / PGID(或 --user $(id -u):$(id -g)),并确保两个挂载目录对该 uid 可写;
  • 健康检查:镜像自带 HEALTHCHECK(每 30s 探一次 /health),docker ps 的 STATUS 列会显示 healthy / unhealthy;
  • 源码构建:docker compose -f docker-compose.build.yml up -d --build。

6. 测试

python tests/run_all.py            # 全部套件
python tests/run_all.py realm      # 只跑名字里含 realm 的
  • 129 个套件:93 个 Python + 36 个 JS;JS 需要 PATH 上有 node,缺失时会跳过并提示。
  • tests/_mobile_check.py 是独立的 Playwright 手机/桌面布局检查器(需自行安装 Playwright),按需手动运行,不在上面的套件集里。
  • CI(.github/workflows/tests.yml)跑同一条命令:Ubuntu 上 python 3.9 与 3.12(3.9 是本项目声称的最低版本),Windows 上 python 3.12;推送 v* tag 时额外断言 tag == 源码版本(-ci 演练 tag 豁免)。

二、核心特性

1. 模型列表对齐官方桌面端

对官方本地配置清单(50+ 底层模型)做清洗:剔除行内补全专用模型(codewise-*、completion-gf、hunyuan-3b/7b 等)与多云专线变体(*-volc、*-lkeap 等),严格对齐官方 Windows 桌面端,并宣告每个模型的上下文窗口、单次最大输出、视觉支持、工具调用与推理档位。

  • 🌐 国际版(17 个):hy4-preview-f、hy3、deepseek-v4.1-flash、gpt-6-astra、gpt-5.6-sol、gpt-5.6-terra、gpt-5.6-luna、gpt-5.5、gpt-5.4、grok-4.7、gemini-3.5-flash、glm-5.3-flash、glm-5.3、glm-5.2、kimi-k3、kimi-k2.6、kimi-k2.8-preview
  • 🇨🇳 国内版(14 个):hy4-preview-f、hy3、deepseek-v4.1-flash、deepseek-v4-pro、glm-5.3、glm-5.3-flash、glm-5.2、glm-5.1、glm-5v-turbo、minimax-m3、kimi-k3-1、kimi-k2.8-preview、kimi-k2.7、kimi-k2.6

清单与上游 GET /v3/config 的 agents[cli].models 保持同步(接口不可用时依次回落到桌面端缓存文件、内置快照);过滤规则:去掉 5 个档位别名与 auto、去掉 -sg / -x 变体、同名的只留 0.00 倍率那一档。上游新上架的模型无需发版即出现在 /v1/models。

同名模型(如 deepseek-v4.1-flash)暂未实现跨国内 / 国际账号的混合轮询:两个区域作为独立出口分别配置与调度,请求只走当前所选网关。这是出站指纹对齐与账号防风控的取舍,待长期实测确认稳定后再补。

2. 设备指纹隔离(derive_id)

国际版与国内版共用同一套算法内核:以账号 UID 结合固定业务盐值单向哈希派生机器码与会话标识——同一账号每次出站都来自同一台虚拟设备(不随机漂移),不同账号之间彼此独立(阻断跨账号关联风控)。

3. 国内版自动化

  • 每日签到:一键完成国内版打卡领积分;
  • 自动连续打卡与连登管家:每日定时为国内版账号上报轻量会话事件(复刻客户端 chat_request_send),点亮官方成长中心连登天数与热力墙;自动闭环检查昨日漏签(有补签卡则自动补签保连登)、领取新手礼包/补偿、兑换 7d/14d/28d 连登档位奖励,并自动抽完抽奖次数;
  • 成长任务与积分任务:自动批量接取未接任务,构造规范行为事件上报点亮(画布创建、灵感案例、模板使用、模型体验、多轮对话等 14 项),并自动领奖入账;
  • 猫猫日常:自动检查旅行状态,在家自动派出、归来自动领奖。

4. 后台常驻调度器

常驻后台,按固定整点执行自动化运维排程:

  • 每日 09:00 & 21:00:国内版账号自动签到、对话活跃上报(点亮连登)与猫猫旅行闭环;国际版账号执行每日活跃打卡(领官方每日 30/50 积分福利);
  • 每日 22:00:集中扫描全库账号,Token 剩余寿命不足 2 小时自动调用 Refresh Token 保活;
  • 每日 01:00:深夜时段执行夜猫子任务;
  • 看板顶部另有「立即巡检保活」与「每日活跃打卡 (国际版)」可随时手动触发。

5. 限额护栏(设置 → 账号限额)

四条账号级护栏放在同一张表里,每行一条、每列一个作用域:

护栏 作用
保留积分 账号余额低于该值时不再接单,避免余额被用尽后触发上游的提醒短信
每日 Token 限额 账号当日消耗的 token 达到该值时暂停接单,请求自动切到其他账号
每日积分限额 账号当日消费的积分达到该值后只服务免费模型,需要花积分的模型自动切号
按模型每日 Token 限额 账号在单个模型上当日消耗的 token 达到该值时只禁该模型,同账号其他模型照常
  • 全局默认 + 可选分版本:每条护栏的「全局默认」同时作用于国际版与国内版;勾上「分别设置国际版 / 国内版」后可单独设值,某版本留空即继承全局(占位符会写出继承到的数字),取消勾选再保存等于清回继承。
  • 每条填 0 表示关闭(默认值);四条都按本地时间 0 点解封,只在请求路径生效(定时任务不受影响),且都是单账号独立计数。
  • 免费 / 付费以各出口自己的模型目录为准,未知模型按付费处理;账号行会显示对应徽章与 模型 · N tok 达限 标记。
  • 某个出口的全部账号都达额时,该出口的请求返回 429(文案说明本地 0 点恢复,Retry-After 指向 0 点)。
  • 存储:accounts/settings.json 里的一组 limits 映射({"global": …, "intl": …, "cn": …},null 表示继承全局);旧版写在外层的四个扁平键会在第一次读取时自动折入。

6. OpenRouter 价估算(等价 token 花费)

把每条请求的 token 消耗按 OpenRouter 公布的模型价折算成等价金额,回答「这些 token 放在 OpenRouter 上值多少钱」——与账号实际扣除的积分是两个口径,看板里并列显示:

  • 总开关(「设置 → 模型价格估算」,默认开启):关掉后价格列、「API 等价花费」卡片、取价控件与未定价清单一起隐藏,后端也不再取价与折算;重新打开会立刻抓一次价并补算关闭期间的请求(历史日志一个字不改,金额始终是读时算的)。
  • 计价口径:输入按缓存命中 / 未命中两档单价拆分,输出单独单价,乘 token 数再按汇率折算;输出的 token 数取上游 completion_tokens(已包含推理 token,不另计)。按条件定价的模型(按输入长度或按 UTC 时段)按每条请求取最紧的那一档。
  • 定价来源:OpenRouter 模型目录的模型级公布价(对应它默认路由的那家 provider)。每份价格按内容存成一条「定价策略」,每条请求只记引用了哪条策略,所以之后调价不会改写历史数字;wb_pricing.py 另内嵌一份快照作出厂价。
  • 刷新:「设置 → 定价刷新」默认每 5 分钟一次(填 0 关闭);只有价格真的变了才写策略与时间轴,价格不动时每轮只是一次 HTTP GET。面板可看当前生效策略、上次 / 下次取价时间与失败原因,也能点「立即取价」。
  • 新增模型自动取价:候选清单 = 内置目录 ∪ 网关实时目录,上游新上架的名字 5 分钟内进入取价;两次取价之间就被调用也会按需补价(请求路径不发网络请求)。匹配顺序:面板手填覆盖 → 人工覆盖表 → 同名唯一命中 → 变体后缀继承(剥 -lkeap / -taiji / -volc / -sg 等,仍要求唯一命中),继承可在设置里整体关掉。
  • 未定价可见:/pricing 列出未定价模型及分类(别名 / OpenRouter 无对应 / 剥后缀后无唯一基准)与相似候选(仅建议,不自动采用),可在「设置 → 定价刷新」为某条手填 OpenRouter id 并登记(写 pricing-overrides.json,不改源码,登记后立即取价)。
  • 展示位置:数据看板「API 等价花费」卡片、各账号用量透视与模型性能表最后一列、网关页「估算价格」卡片、最近请求最后一列(悬停可看完整定价链:三档原始单价、汇率、匹配证据、策略 id 与补算标记 *)。
  • 人民币 / 美元一键切换(记在浏览器本地);快照覆盖不到的模型显示 —,不猜数字。

7. 本地网络工具(可选,默认关闭)

Codex App 这类客户端会在 Responses 请求里声明 web_search / web_fetch,而上游没有对应的执行器——声明送上去只会拿到一句 unsupported call。打开「设置 → 本地网络工具」后,网关把那份声明换成自己的同名 function,拦下模型的调用并在本地执行(搜索走 DuckDuckGo HTML 版,抓页面抓模型给出的 URL),再把结果喂回模型,最多代跑 3 轮(WB_MAX_WEB_ROUNDS 可调,上限 8);搜索过程会作为 web_search_call 卡片事件与 url_citation 引用回到客户端。

  • 关闭时(默认)声明原样透传,客户端自己声明的搜索工具照常拿到调用;
  • 打开后网关会主动出网抓取模型给出的 URL(只挡字面私网地址),且每轮代跑都会多跑一次上游、多消耗该账号额度;国内网络下 DuckDuckGo 可能连不上,那时模型拿到的是错误文本;
  • 只影响声明了这两个工具的客户端,普通 /v1/chat/completions 客户端不经过这条路径。

8. 智能体一键配置

看板「智能体配置」页可检测本机已装的 AI 客户端,一键把它们的配置指向本网关,改前自动备份、随时字节级还原:

客户端 写入位置 协议
Claude Code ~/.claude/settings.json 原生 Anthropic Messages(自动剥 /v1 后缀)
Codex CLI ~/.codex/config.toml、~/.codex/auth.json Responses API
OpenCode ~/.config/opencode/opencode.json OpenAI 兼容(@ai-sdk/openai-compatible)
DSH (DeepSeek Harness) ~/.dsh/settings.yaml、~/.dsh/.credentials.yaml OpenAI 兼容
Crush (Charm Crush) ~/.config/crush/crush.json OpenAI 兼容
ZCode ~/.zcode/v2/provider_config.json OpenAI 兼容(openai-chat-completions;配置前先退出 ZCode,运行中它会重写该文件)

用法:打开看板 →「智能体配置」→ 选 API Key(支持全局默认或绑定特定出口的多 Key)、默认模型与网关地址 → 在检测到的客户端卡片上点「一键配置」;随时可点「一键还原」。

  • 非侵入:纯标准库实现的文本级 YAML / TOML / JSON / .env 编辑器,只增量插入或更新 wb-proxy 那段,绝不重排或抹掉用户的注释、缩进与其他 provider 配置;
  • 可回滚:写入前自动备份到 accounts/agent-backups/<客户端ID>/(每文件保留最新 10 份),首次接入的原件永久保留;多文件客户端(DSH、Codex)两阶段写入,任一文件失败立即回退;
  • 还原:byte-exact 回到首次接入前,网关新建的文件会被清理;若之后手动改过配置,看板会提示「检测到外部修改」,还原仍会覆盖回原件;
  • 密钥安全:API Key 只写进客户端自己的本地配置目录(权限仅限当前系统用户),单文件超过 8MB 拒绝编辑。

在另一台机器上接入(远程 / 非本机):看板的一键配置运行在网关进程里,改的是网关所在机器的配置目录——所以它只在网关本机、且用 127.0.0.1 打开看板时可用(远程访问、容器 / OpenWrt 部署下按设计隐藏入口)。客户端装在别的电脑(网关跑在服务器 / NAS / 路由器上)时,改用自带的配置器 CLI:它在客户端所在的机器上运行,写本机配置、只通过 HTTP 从网关取模型表:

# 1. 取配置器(网关直接提供该文件;也可从仓库 / 绿色包复制 wb_agents.py)
curl -fsSL http://<网关地址>:8788/agents/cli -o wb_agents.py

# 2. 一条命令接入(需要 Python 3.9+,Key 在「设置」页生成)
python wb_agents.py list                                   # 本机装了哪些客户端
python wb_agents.py apply --client codex --base-url http://<网关地址>:8788/v1 --key sk-xxxx
python wb_agents.py restore --client codex                 # 随时字节级还原
  • 支持 claude-code / codex / opencode / dsh / crush / zcode 六个客户端,与看板共用同一套写入、备份与还原逻辑(plan() 同时驱动 --dry-run 与真实写入);
  • 默认带 Key 请求一次 GET /v1/models:既为 OpenCode / DSH / Crush / ZCode 填入模型表,也顺带验证 Key(401 = Key 被拒);网关不可达或想完全离线时加 --no-models;
  • 状态与备份存在该机器自己的 ~/.wb-agent-config/(可用 --state-dir 覆盖),每台机器一份,restore 只对执行过 apply 的机器有效;
  • --dry-run 只打印将要写入的内容、不落盘;Key 也可用环境变量 WB_PROXY_API_KEY 传入。

模块内部设计与新增客户端的方法见 docs/CONTRIBUTING-智能体配置.md。

9. 剩余用量估算(数据看板 → 剩余用量估算)

上游按 24 小时窗口给「账号 × 模型」配额(用满时 429 / code 6004 会带上重置墙钟),但从不告诉你这个窗口的预算是多少。看板新增的「剩余用量估算」区块把它反推出来:

  • 预算 = 撞线账号窗口用量的平均:账号撞线(收到带重置时刻的 429)的那一刻,它在该模型上「自窗口起点以来的成功用量」就是预算的一个样本;按区域聚合、先按账号平均再跨账号平均。样本在 429 处理的那一刻就记进 usage/limit-events.jsonl(重试循环里只有最后一个账号会留下带归属的 429 用量行,光靠日志会漏掉大部分撞线),历史日志里带账号的 429 行作为补充,两者按「账号 + 模型 + 重置时刻」去重。
  • 已用从每个账号自己的重置时刻起算:窗口起点取该账号该模型最近一次重置时刻;重置时刻在未来的组合(正在冷却)剩余记 0 并显示恢复时间。
  • 没有撞线记录的组合标「按 24h 估算」:窗口起点未知时按最近 24 小时用量统计——窗口起点必然落在最近 24h 内,所以这是剩余量的下界(偏保守,不会高估)。
  • 接口 GET /usage/remaining(需面板会话)返回 budgets(每个区域 × 模型的预算均值 / 区间 / 样本数)与 rows(每个账号 × 模型:已用、预算、剩余、窗口起点、是否冷却、是否估算),区块只读不写,不参与请求路径(唯一的请求路径接触点是撞线时记一行事件)。
  • 查询侧不做重复计算:每个「账号 × 模型」的用量缓冲是时间戳 + 累计和两个列表(窗口求和 = 两次二分 + 一次相减,O(log n),内存约 16 字节/行),载荷再挂一个短 TTL(WB_REMAINING_TTL,默认 15 秒)并支持 ETag / If-None-Match:面板 5 秒一轮的轮询在 TTL 内直接拿上次算好的载荷(连日志尾部都不再扫),带条件请求时回 304。实测(2 万行缓冲):单次重建 ~0.7ms(旧版逐行重算 ~1.8ms)、轮询一分钟 2.9ms(旧版 21.5ms)、缓冲内存 321KB(旧版 2.3MB)。

10. 积分获取历史(数据看板 → 积分获取历史)

「积分扣减历史」看的是花掉的部分,这一块补上进账的部分:上游对每个账号返回一份积分包清单(每日活跃奖励的 Bonus Pack、免费套餐、活动包…),每个包带面额、发放时间与到期时间。区块把全部账号的包摊平成一张表、新的在前:

  • 列:时间(发放)/ 账号 / 区域 / 名称 / 来源 / 积分 / 剩余 / 到期 / 状态;
  • 状态按「过期 > 用完 > 在扣减 > 可用」归类:生效中(上游标了 in_usage,当前正从它扣减)、可用、已用完、已过期;no_expiry 的包显示「不过期」;
  • 来源:上游自带的发放原因原样显示(如「Buddy 加油站签到」「成长计划奖励」「官方活动发放」);国际版的 Bonus Pack 30/50 没有原因字段,按官方规则推断为「每日活跃奖励」(悬停里注明这是推断)。我们自己的签到 / 每日活跃记录也会按时间关联上去(取发放前 2 小时内最近的一次尝试,带成功 / 失败),悬停即可对上「本机动作:每日签到 10-10 00:07 成功」——一次发放到底由哪次动作带来,一眼可见;
  • 摘要行给出笔数、合计面额、合计剩余与快照时刻。接口 GET /accounts/credits/grants 只读内存里的积分快照、不发上游请求——数字的新鲜度取决于最近一次「一键刷新积分」(签到与每日活跃打卡也会顺带刷新它),所以要看最新的包先点账号页那个按钮。

三、账号添加与管理

打开看板 http://127.0.0.1:8788/,在「账号」区域操作。若上游对某账号的单个模型返回 429,账号行会显示受限模型与预计恢复时间(浏览器本地时间),该账号仍可用于其他模型;模型冷却只在当前进程内保留,重启清空。

方式一:浏览器 OAuth 授权(推荐,免客户端)

  1. 点「+ 添加账号 (OAuth)」;
  2. 选择要登录的区域(国际版 / 国内版),点弹出的官方授权链接并在浏览器完成登录;
  3. 程序自动检测回调,账号自动加入账号池,无需手动复制凭证。

方式二:从本机桌面客户端导入(仅 Windows)

  1. 让 WorkBuddy 桌面客户端保持运行并已登录(网关要从它的进程内存里取解码密钥,这一步不能省);
  2. 看板点「扫描桌面客户端账号」,弹窗列出本机已登录的国际版 / 国内版账号;
  3. 若提示凭据已加密,先点弹窗里的「回收密钥」(只读,实测 1 秒内完成),再点账号行的「导入」。

关于加密凭据:桌面客户端从 2026-09-24 起把 accessToken / refreshToken 存成 $wbEncrypted 信封,网关按客户端 packages/at-rest-crypto 的同一套方案(AES-256-GCM + WB-AAD 帧头)就地解密,导入的仍是可直接使用的 token;解码密钥编译在客户端原生模块里、磁盘上没有明文,只能从正在运行的桌面端进程内存里找回(只读 OpenProcess(PROCESS_VM_READ) + ReadProcessMemory,不向客户端写任何东西),密钥只留在网关进程内存、不落盘不写日志。提示权限不足时,以管理员身份启动网关再试一次。Docker / Linux / macOS 下请用方式一。


四、客户端配置与接入

  • API 接口地址 (Base URL):http://127.0.0.1:8788/v1(局域网为 http://<局域网IP>:8788/v1)
  • API Key:本机单机模式(未配置 Key 且未开 LAN)可留空或填任意字符;已在看板配置 Key 或 LAN 模式,请用看板「设置」页里绑好出口的 Key;
  • 模型名称:填 /v1/models 里列出的任意官方对齐模型 ID(如 deepseek-v4.1-flash、gpt-6-astra、glm-5.3)。

Codex CLI / Claude Code(Responses API)

export OPENAI_BASE_URL="http://127.0.0.1:8788/v1"
export OPENAI_API_KEY="你在看板设置中添加并绑定的API_Key"

Claude Code / Anthropic SDK(原生 Anthropic Messages API)

export ANTHROPIC_BASE_URL="http://127.0.0.1:8788"
export ANTHROPIC_API_KEY="你在看板设置中添加并绑定的API_Key"

网关原生实现 /v1/messages(流式与非流式):system(字符串或文本块数组)、text / image / document / tool_use / tool_result 内容块双向转换,tools + tool_choice、stop_sequences、metadata.user_id、thinking / output_config.effort 全部映射到上游;流式输出是原生事件序列(message_start → content_block_start / content_block_delta → content_block_stop → message_delta → message_stop);鉴权接受 x-api-key 或 Authorization: Bearer,错误一律用 Anthropic 的错误信封。

边界:服务端工具(web_search 等)上游不支持,会被丢弃并在 system 里注明,不会伪造调用;thinking / redacted_thinking 块不回放(上游不提供可验证签名);top_k、cache_control、context_management 与 betas 忽略;/v1/messages/count_tokens 返回的是网关的 CJK 感知估算值(与用量统计同一套估算器),不是官方分词器的精确值。


五、看板与接口一览

访问 http://127.0.0.1:8788/ 使用集成看板:顶部页签默认是「网关与账号 / 数据看板 / 智能体配置 / 设置 / 运行日志」,每个主页面左侧有一条按页面区块现场生成的导航(点击直达、滚动高亮、地址栏带锚点,可收起成窄轨)。

账号多起来之后(国际版十几个),账号列表与「当前禁用」总览会把网关页挤下去。设置页的「账号独立成一个页签」默认关闭,账号区就留在「网关与账号」页(位置与拆分前一致);打开后它们和签到记录一起成为独立的「账号」页:添加 / 导入 / 导出、启用停用、凭证与积分刷新、代理出口绑定都在那里,顶部页签变成「网关 / 账号 / 数据看板 / 智能体配置 / 设置 / 运行日志」。页内的「签到与活跃记录」读 GET /activity/history,可按区间 / 任务 / 结果 / 账号筛选(筛选在服务端做),一行一次真实尝试,列出 时间 · 账号 · 区域 · 任务 · 来源 · 结果 · 说明,最新在前;超过一页时用「加载更多」往下翻,上限 1000 行——「这个账号昨天到底签成了没有」不用再去调度器日志里翻。

「数据看板」页顶部可切换统计口径:今日 / 本周 / 本月 / 全部历史 / 自定义(本周自周一零点起算、本月自 1 号零点起算,任一侧留空表示不限),切换后 KPI 卡片、账号用量透视表与模型性能表一起切到同一窗口。

方法 路径 说明
GET / Web 用量与任务监控看板
POST /v1/chat/completions 标准 Chat Completions 接口
POST /v1/responses Responses API 协议接口
POST /v1/messages 原生 Anthropic Messages 协议接口(流式 / 非流式,x-api-key 或 Authorization 鉴权)
POST /v1/messages/count_tokens Anthropic 计数接口(CJK 感知估算值,非官方分词器)
GET /v1/models 官方对齐模型列表(含能力与规格宣告)
GET /pricing 定价状态:当前生效策略、上次/下次取价时间、未定价清单(分类 + 候选)
POST /pricing/refresh 立即取一次价(需面板会话)
POST /pricing/mapping 手填 / 清除「模型 → OpenRouter id」运行期映射,随后自动取价(需面板会话)
GET /agents 客户端探测概览、支持的模型清单及网关连接地址
GET /agents/cli 智能体配置器源码(供远程机器直接 curl 取用,免面板鉴权;与仓库内 wb_agents.py 逐字节一致)
POST /agents/apply 一键写入客户端配置并备份原件(需面板会话)
POST /agents/restore 一键还原客户端至首次配置前的状态(需面板会话)
GET /tasks 国内版成长任务、连续打卡与猫猫日常状态
POST /tasks/run 触发国内成长任务全自动点亮与领奖
POST /tasks/travel 触发猫猫日常旅行(派出 / 领奖)
GET /scheduler 定时调度器运行状态与排程日志
POST /scheduler/trigger 手动立即执行后台巡检保活
GET /activity/history 账号每日活动历史:签到与每日活跃的每一次真实尝试(range / uid / task / result / limit,最新在前)

| GET | /accounts/credits/grants | 积分获取历史:各账号积分包(发放时间 / 面额 / 剩余 / 到期 / 状态),只读内存快照、不发上游请求 | | GET | /usage/remaining | 剩余用量估算:每个账号 × 模型在当前 24h 窗口的已用 / 预算 / 剩余(预算取撞线账号的平均用量;需面板会话) |


六、版本更新记录 (Changelog)

Unreleased

  • 账号手动权重与备注(#289):账号表新增「权重」列(下拉 1-10,默认 1)——权重 >1 的账号优先于一切自动偏好接单,多个高权重账号之间按权重平滑加权分流量(nginx 同款算法,谁也不独占),它们都不可用时照旧落回自动偏好与轮询;全部为 1(默认)时分派与从前完全一致。另有账号备注(点「+ 备注」编辑,空串清除,上限 200 字),纯展示、不参与调度,随凭证档持久化;账号列表排序改为「有备注置顶 → 权重高在前 → 同权重启用在前」。新增 tests/_test_manual_weight.py、tests/_test_account_note.py、tests/_test_account_weight.js。

  • 修复「一次请求给同一个账号重复记账」(issue #271):重试轮在遇到传输类失败后会清空 tried 整池重轮,于是同一个账号会被再挑一遍、再记一笔 fails/degrade_count。池子越空重轮越频繁,一个刚抖了一下的账号因此可能一次请求就被推过熔断阈值(两次抖动触发 3 次硬失败的断路,而不是三次)。现在一次请求对一个账号最多记一笔:open_upstream() 用 charged 集合记住这一轮已经记过账的账号,重轮再挑到它时不再重复计数(note_error() 的冷却语义不变)。

    • tests/_test_pool_backoff.py 新增 RetryRoundChargeTests:钉住传输类与 502 两种失败下「一次请求只记一笔」,以及这道护栏不跨请求(第二个请求仍然照记,否则会掩盖真正在失败的账号)。
  • 新增「出口级瞬时失败退避」(默认关,issue #271):账号级熔断把「连续 3 次硬失败」记在账号头上(30 分钟起、翻倍到 6 小时)。当失败来自出口 / 链路的瞬时抖动而不是账号本身时,这个口径会把一次抖动记到每个共享该出口的账号头上——现场实测 4 小时 196 次 URLError 陆续熔断 13 个账号(最长窗口约 3 小时),期间池子几乎空掉。打开 egress_backoff_enabled 后,传输类失败与 502/503/504 不再喂账号的 fails / degrade_count,改记在出口上:同一个出口的账号共用一个计数器,退避降到秒级(1 秒起、翻倍、封顶 15 秒、带抖动),任一次成功即清零。出口身份用 wb_upstream_pool.egress_key()——与连接池键同一口径 (scheme, host, port, 代理串),并把「配了代理但命中系统旁路」折叠成直连,所以「直连」本来就是一个共享出口。500 仍留给账号(可能是与凭证相关的真实故障,需要再看一眼);401/403/429 各走原有路径。单次请求的睡眠封顶 5 秒(EGRESS_SLEEP_MAX),共享计数器仍让并发请求一起变慢。

    • 开关缺失键读作关:它改变的是派发路径上的失败归账与退避尺度,老安装保持原样(传输错误仍喂账号熔断)。
    • 新增 wb_egress.py 与 tests/_test_egress_backoff.py:钉住出口身份与池键同口径、旁路折叠、秒级阶梯与封顶、共享计数器、成功清零、静默窗口重开阶梯,以及开关开 / 关两种口径下账号计数的差异(含 500 仍记账号)。
    • release/portable_runtime.py 的 REQUIRED_FILES 补 Lib/random.py(wb_egress 用它做退避抖动);release/portable.txt 加 wb_egress.py。
  • 数据看板:token 紧凑单位、缓存 token、总计花费、延迟自动单位(#287):两张 token 卡的大数字与输入/输出/思考明细改为紧凑单位(fmtCompact:<1 万精确千分位,≥1 万 K、≥100 万 M、≥10 亿 B,小数位随量级收缩、尾零去掉);明细行新增「缓存」一段,缓存命中率卡副行带缓存 token 数;「API 等价花费」卡副行给出总计(全部历史);KPI 的平均首字延迟 / 平均耗时与最近请求表的耗时 / 首字列改用自动单位;账号透视表与 Key 表的 token 列同步。新增 tests/_test_token_units.js。

  • 数据看板:剩余积分分「总剩余 / 可用」两个维度(#286):区域卡片的大数字保持「总剩余」(全部账号之和,含停用账号),副行新增「可用 N」——只算启用且未触发保留积分 / 日限额 / 积分限额护栏的账号(与旁边的 N/M 账号计数同一个口径)。没有积分数据时两个维度都显示 —,不会把可用误显示成 0。新增 tests/_test_credits_dimensions.js。

  • 修复:上游风控限制 403(code 11140)不再被当成内容审核(#288):账号被上游限制时(正文「账号存在异常行为,已被限制使用」/「restricted due to unusual activity」),原先落进内容审核分支——降级提示词重试一次后就把错误透传给客户端,被限制的账号既不冷却也继续被选用,同一条对话被一次次打死。现在按账号级限制处理:冷却该账号 2 小时并轮到下一个账号,上游解封后自愈;池里只剩一个账号时仍把限制原因交给客户端。内容审核 403 的降级路径不变。顺带把重试循环的 5xx 从固定清单(500/502/503/504)放宽为一切 >= 500——上游自定义的 550 这类原先会直接甩回客户端,现在按瞬时故障轮转。新增 tests/_test_restricted_403.py(6 项)。

  • 修复:remaining 的 checkpoint 从来没能被采纳(写者/校验者口径矛盾):折叠侧按日志顺序追加,而 at 取的是请求完成时刻——多线程下会回退几毫秒(本机日志有一对 4.96ms,路由器自己写出的 checkpoint 里有一对 0.47ms),加载侧却要求每个 (账号 × 模型) 的 at 严格单调,一处乱序就整份拒绝:每次重启 /usage/remaining 都退回从零冷扫(真机实测 3.05~4.5s)。现在折叠侧按 at 有序插入(只在乱序时才付 O(n) 挪动,pair 通常几十~几百条;顺序追加仍是 O(1)),加载侧对旧版(日志顺序)缓冲做一次稳定排序并重建累计和/base((at, 增量) 配对不变、已裁剪的死前缀物理丢弃、base 记绝对值),形状校验不再要求有序。同一处乱序在窗口求和上的连带错误一并修掉:_range_sum/_range_sum_open 的二分前提恢复后,乱序日志下的窗口和等于「按排序后重算」的值(旧版会少算、甚至算成 0)。新增 tests/_test_remaining_checkpoint_order.py(12 项:乱序日志的折叠与窗口和、乱序/旧版 checkpoint 的重启采纳与逐字节对拍、截断与同尺寸重写仍然作废、两个独立进程的冷折 vs 采纳对拍)。

  • 修复「网页通道打卡」在认证代理下必然 407:账号绑定带 user/pwd 的代理槽时,网页通道那一步固定失败并回 OSError: Tunnel connection failed: 407 Proxy Authentication Required,而桌面通道与面板「出口 IP 测试」都正常。原因是 wb_webagent.AcpChannel._connect() 用裸 http.client + set_tunnel() 直连代理,只传了 host/port:urllib.request.ProxyHandler 会替 urlopen 那条路径把 URL 里的凭据转成 Proxy-Authorization: Basic ...,而 set_tunnel() 不带这个头——于是同一个代理 URL 在两条通道上行为不一致。

    • 现在 _connect() 走 _proxy_parts() 解析代理 URL,把 Proxy-Authorization 显式塞进 CONNECT(取值口径与 ProxyHandler.proxy_open 一致:先 unquote 再 base64),两种写法都认:http://user:pass@host:port 与无 scheme 的 user:pass@host:port(后者此前连 host/port 都会被 urlparse 误判成 scheme,一并修正);没填凭据时不发该头,免认证代理行为不变。
    • 新增 tests/_test_web_agent.py 的 ProxyTunnelTests:钉住两种 URL 形态的解析、转义字符与 urllib 同口径、无凭据不发头、隧道确实带上该头,以及直连时不走隧道。
  • 修复「网页腿失败也写 lastDailyChat,当天积分静默丢掉」:_daily_chat_upstream() 在桌面腿成功后立刻写 lastDailyChat,而网页腿(唯一计入官方「每日活跃」的那条)失败也照写;于是当天后续巡检 can_daily_chat() 直接跳过该账号,那天的 30/50 积分既不到账也不再重试,面板还显示「成功」。现在只有网页腿成功(或 web=False、没开网页通道)才写盘,失败时留到下一个巡检周期重试。

    • tests/_test_daily_chat.py 补三条:网页腿失败不写盘且 can_daily_chat() 仍为真、网页腿成功写盘、web=False 维持原语义。
  • 新增「配置器 CLI」:客户端不在网关机器上也能一条命令接入(#280):看板的一键配置运行在网关进程里,只在网关本机、用 127.0.0.1 打开看板时可用(远程访问与容器 / OpenWrt 部署按设计拒绝),网关跑在服务器 / NAS / 路由器上时,客户端装在别的电脑就用不上。现在 wb_agents.py 同时是可执行的配置器——list / status / apply / restore,在客户端所在的机器本地写配置(与看板共用同一套写入、备份、还原逻辑),只通过 HTTP 从网关取模型表;网关侧新增 GET /agents/cli 下发该脚本(免面板鉴权,正文与仓库内 wb_agents.py 逐字节一致、不含机密)。--dry-run 与真实写入共用同一条 plan() 生成路径;Key 走 --key → WB_PROXY_API_KEY → 交互提示,提示仅在 stdin 与 stdout 都是终端时出现(避免没有控制台的进程里 getpass 永久阻塞)。

    • 顺手修「apply → apply → restore 把自产文件当原件还原」:按内容哈希判定归属——仍逐字节等于我们最后写入的 → restore 删除;被用户手改过 → 备份并恢复用户版本。此前含 API Key 的 .credentials.yaml 会留在磁盘上,与文档承诺相悖。
    • release/portable_runtime.py 的 REQUIRED_FILES 补 Lib/getpass.py(新增 import 后裁剪运行时缺该模块);README 套件计数 119 → 120。
  • 账号工具栏新增「一键切换所有出站身份」(#254):一次把全部账号(含另一个版本)的出站身份切到下一个——WB → VSC → CLI → 循环。按钮上直接显示当前身分,各账号不一致时显示「混合」,此时点一下统一成 WB。服务端 /accounts/product 本来就支持不带 uid 的全量切换(面板此前只有单账号的行内按钮,以及 429 时的自动换身分),这次补的是入口与提示;切完当场落盘,重启不丢。

    • tests/_test_product_switch.py(新套件):钉住全量 / 按区域 / 单账号三条分支、非法身分被拒、落盘后重启仍在、重复切换不报变更;
    • tests/_test_accounts_page.js:钉住按钮位置、轮转顺序与「不带 uid」的提交形状,并在假 DOM 里真跑一遍。
  • 补一道「冲突标记」门禁:仓库里已经三次把解冲突的残留提交进 main(#131 专门清过一次 dashboard 的,README 又在 #243/#245 那批合并里带进 12~15 行),此前没有任何测试盯它——Python 文件会直接 SyntaxError,HTML/JS 则是静默坏掉,回滚检查还会把「合并时顺手整理掉这些行」算成弄丢 main 的改动(#245 那次报红就是这个)。tests/_test_release_engineering.py 新增 RepoHygieneTests:扫全树(跳过运行时数据与打包产物目录),任一行以 <<<<<<< / >>>>>>> / ||||||| 开头即失败。

  • 智能体一键配置新增 ZCode 客户端:把网关作为 wb-proxy provider 写进 ZCode 的活配置 ~/.zcode/v2/provider_config.json(providerConfigRules.providerRules + providerOrder)。规则按稳定 providerId 定位,重复 apply 更新同一条而非堆叠;其余 provider、它们的顺序与 modelConfigRules 逐字节保留。模型表来自 GET /v1/models,写成 personalModelIds + modelOrder。该文件由 ZCode 应用自己持有、运行中会被重写——卡片文案与文档都提示「配置前先退出 ZCode」。

    • tests/_test_agents.py 扩到 126 项:zcode 形状断言 + 「重复 apply 不堆叠 / 其他 provider 与 modelConfigRules 逐字节保留 / 还原字节级」。

已发布版本的完整记录(v1.4.5 ~ v1.6.20,含每版的 PR 归属)见 docs/CHANGELOG.md。

七、致谢与引用声明 (Credits & References)

协议兼容、风控规避与任务链路设计过程中,参考并吸纳了以下开源项目的经验与逆向成果:

PR 贡献者(v1.4.5 之前的改动未进上方更新记录,这里一并列出):

  • @ddddd-ren:用量日志倒序检索与看板防堆叠(PR #14)、原子写入与并发竞争修复(PR #13)、账号池 JSON 导出导入(PR #5);
  • @wylftw0314-glitch:Responses API custom 工具协议双向转译(PR #12);
  • @shuishuipingan:成长任务领取竞态与专家/团队事件 id 去重、猫猫旅行派出修复、夜猫子任务接入调度器、启动端口误判(PR #21)、按模型冷却限流(PR #22)、任务接取强化与轮询加速(PR #27)、网络抖动重试与 403 直通(PR #28)、HTTP 连接同步(PR #30);
  • @ayeaaaa:按账号绑定出口代理槽(PR #26)、DeepSeek reasoning_content 回填(PR #36)、看板移动端布局(PR #37);
  • @t-789:macOS 启动脚本与防火墙助手(PR #31);
  • @Cekxri:Codex App namespace 工具支持(PR #33);
  • @wiggins-kong:API Key 行 id 唯一化(PR #40)、Docker 镜像缺少运行时模块(PR #41);
  • @Pro-XK:看板积分消耗与账号昵称(PR #45);
  • @teddyli18000:单模型限流可视化(PR #50)、/health 鉴权状态修正(PR #52);
  • @LuFering:Docker 部署下的 Linux 桌面凭据挂载说明(PR #55);
  • @zhangzm0:tool_choice="none" 保留工具声明(PR #57)。

八、免责声明 (Disclaimer)

  1. 本项目为非官方自托管网关,仅供技术研究、逆向协议学习与个人合法授权账号在私有环境测试使用。
  2. 本项目不提供任何账号及额度。请严格遵守官方服务条款,禁止用于任何商业转售、恶意并发或违规滥用。