# codebuddy2api
**Repository Path**: frankliao/codebuddy2api
## Basic Information
- **Project Name**: codebuddy2api
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-08-18
- **Last Updated**: 2026-10-10
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# workbuddy2api
把 **WorkBuddy / CodeBuddy(腾讯代码助手)** 的桌面端登录态,转成你本机可直接使用的 **OpenAI / Anthropic 兼容 API**。
适用场景:
- 用 **Codex CLI** 走 `/v1/responses`
- 用 **Claude Code / CC Switch** 走 `/v1/messages`
- 用 **Cherry Studio / ZCode / LobeChat / NextChat / Open WebUI** 走 `/v1/chat/completions`
[English](#english) · [中文](#中文)
---
## 中文
### 这是什么
`workbuddy2api` 是一个本地协议转换器。它会读取你已经登录好的 WorkBuddy / CodeBuddy 桌面端凭据,转发到腾讯后端 `copilot.tencent.com`,然后在本地暴露这些接口:
- `POST /v1/chat/completions`
- `POST /v1/responses`
- `POST /v1/messages`
- `GET /v1/models`
- `GET /health`
它不负责登录,不模拟桌面端,也不替你执行工具。它只做三件事:
1. 读取本机登录态并注入鉴权头
2. 在 OpenAI / Anthropic 协议和腾讯后端协议之间转换
3. 保留多轮消息、工具调用及思考内容,并提供可选的运行时提示脱敏
> 命名说明:项目对外名称现在叫 `workbuddy2api`。代码里仍保留部分历史命名,比如 `codebuddy2openai`、`CODEBUDDY2OPENAI_*`,目的是兼容旧配置和环境变量。
> 另外,GitHub 仓库路径当前也可能仍沿用 `codebuddy2openai`,这是仓库路径与项目展示名尚未完全统一,不影响使用。
### 你能用它做什么
- 把 WorkBuddy 订阅复用到 OpenAI 兼容客户端
- 让 Codex CLI 直接接腾讯后端,而不是只接 OpenAI 官方
- 让 Claude Code 通过 CC Switch 复用 WorkBuddy 支持的模型
- 保留原生 `tools` / `tool_calls` / 流式 SSE / 多轮工具调用
### 当前支持
| 客户端 / 协议 | 接口 | 当前状态 |
|------|------|------|
| OpenAI Chat Completions | `/v1/chat/completions` | 已支持 |
| OpenAI Responses | `/v1/responses` | 已支持,适配 Codex CLI |
| Anthropic Messages | `/v1/messages` | 已支持,适配 Claude Code / CC Switch |
| OpenAI Models | `/v1/models` | 已支持,动态探测实际可用模型(缓存 10 分钟,失败回退静态列表) |
| Health Check | `/health` | 已支持 |
---
## 3 分钟上手
### 1. 前置条件
你需要先满足这 3 个条件:
1. 本机已经安装并登录 **WorkBuddy / CodeBuddy** 桌面端
2. 本机有 **Python 3.8+**
3. 已安装 `requirements.txt` 中的依赖(本地 token 计数使用 `transformers` 和 `jinja2`,不需要模型权重或 PyTorch)
默认会在这些位置寻找登录态:
- macOS: `~/Library/Application Support/CodeBuddyExtension/Data/Public/auth/*.info`
- Windows: `%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\*.info`
- Linux: `~/.local/share/CodeBuddyExtension/Data/Public/auth/*.info`
转换器只接受企业版认证:文件必须同时包含非空的 `account.enterpriseId`
和企业专属 `auth.domain`(域名包含 `.copilot.`)。如果目录中同时存在个人版
和企业版登录态,只会在企业版文件中选择非历史快照且修改时间最新的一份,
不会回退使用个人版认证;如果找不到符合条件的企业认证,服务将拒绝启动,
`--skip-check` 也不会绕过该限制。
### 2. 安装依赖
推荐用 `uv`:
```bash
git clone https://github.com/ShouZhuo0413/codebuddy2openai.git workbuddy2api
cd workbuddy2api
uv venv
uv pip install -r requirements.txt
```
也可以用虚拟环境:
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
> 注意:无论是启动服务,还是执行 `python converter.py --help`,都必须先装依赖。
### 3. 启动
最常用的启动方式:
```bash
uv run converter.py --desensitize --log converter.log
```
或:
```bash
python converter.py --desensitize --log converter.log
```
看到监听 `http://127.0.0.1:8787` 就说明已经起来了。
### 4. 快速自检
```bash
curl http://127.0.0.1:8787/health
curl http://127.0.0.1:8787/v1/models
```
如果这两条能通,说明本地服务、登录态、基本路由都没问题。
`/health` 默认只返回服务状态、企业认证是否可用和 Token 是否过期,
不会暴露认证文件路径、用户标识、昵称或企业名称。
---
## 客户端接入
### Codex CLI
这是当前最推荐的接法。Codex CLI 走的是 `/v1/responses`,而不是 `/v1/chat/completions`。
推荐启动命令:
```bash
uv run converter.py --desensitize --log converter.log
```
把下面配置合并到 `~/.codex/config.toml`:
```toml
[model_providers.workbuddy]
name = "WorkBuddy (via local converter)"
base_url = "http://127.0.0.1:8787/v1"
wire_api = "responses"
env_key = "CODEBUDDY2OPENAI_KEY"
[profiles.workbuddy]
model = "glm-5.2"
model_provider = "workbuddy"
```
设置一个占位环境变量:
```bash
export CODEBUDDY2OPENAI_KEY=any-value
```
启动:
```bash
codex --profile workbuddy "你的任务描述"
```
补充说明:
- 推荐保留 `--desensitize`
- `/v1/responses` 保留完整历史、工具参数和工具结果,不再按消息数强制压缩
- 每次请求请携带完整 `input`;当前不保存 Responses 会话,使用 `previous_response_id` 会返回 400
- 如果你想尽量保留原始 system prompt,可试 `--desensitize --no-compact`
- `--desensitize --no-compact` 下若仍命中审核,当前实现会自动退回紧凑模式重试一次
### Claude Code / CC Switch
Claude Code 不走 OpenAI 协议,而是走 Anthropic Messages。
推荐启动命令:
```bash
uv run converter.py --desensitize --log converter.log
```
在 CC Switch 里配置:
```json
{
"DeepSeek-V4-Pro": {
"base_url": "http://127.0.0.1:8787/v1/messages",
"api_key": "",
"model": "deepseek-v4-pro"
}
}
```
注意:
- 模型名必须填写腾讯后端支持的真实模型名
- 不做 Anthropic 模型名到腾讯模型名的自动映射
- Claude Code 场景强烈建议开启 `--desensitize`
### 其他 OpenAI 兼容客户端
适用于:
- Cherry Studio
- ZCode
- LobeChat
- NextChat
- Open WebUI
- 自己写的 OpenAI SDK 客户端
配置方式:
- Base URL: `http://127.0.0.1:8787/v1`
- API Key: 留空,或填你启动时设置的 `--api-key`
- 模型名: `glm-5.2` / `deepseek-v4-pro` / `kimi-k2.7` / `auto` 等
---
## 常用命令
### 基本启动
```bash
python converter.py
python converter.py --desensitize
python converter.py --desensitize --log converter.log
python converter.py --api-key mysecret
python converter.py --port 9000
```
### 命令行参数
| 参数 | 默认值 | 说明 |
|------|------|------|
| `--host` | `127.0.0.1` | 监听地址 |
| `--port` | `8787` | 监听端口 |
| `--api-key` | 无 | 给本地客户端加一层鉴权 |
| `--log` | 无 | 记录摘要日志;默认不保存提示词、源码、工具参数或思考正文 |
| `--log-payloads` | 关 | 显式记录完整请求、响应和原始 SSE;仅建议临时排障使用 |
| `--log-max-mb` | `10` | 单个日志文件的轮转大小(MB) |
| `--log-backup-count` | `3` | 保留的历史日志数量;加上当前文件最多共 4 个 |
| `--reasoning-effort` | `off` | 为未指定档位的请求注入 `low/medium/high`;全局 `off` 表示不注入,沿用上游默认 |
| `--reasoning-effort-map` | `reasoning_effort.json` | 按模型设置默认档位,优先于全局值;映射中的 `off` 会明确发送给上游 |
| `--desensitize` | 关 | 压缩运行时提示、去掉 tool description、零宽脱敏高风险关键词 |
| `--no-compact` | 关 | 配合 `--desensitize` 使用,保留更完整的原始 system prompt |
| `--count-tokens-path` | 无 | 已确认可用的 CodeBuddy 同源计数路径,优先于本地 tokenizer |
| `--tokenizer-map` | 无 | JSON 文件:精确模型 ID → tokenizer 仓库或本地目录,补充/覆盖内置映射 |
| `--skip-check` | 否 | 跳过启动预检 |
### 流式结束日志
三个流式接口在响应生命周期结束时统一记录一次摘要。`outcome` 区分 `completed`、`client_disconnected`、`upstream_error`、`content_filtered`、`incomplete`、`cancelled` 和 `internal_error`。收到 `[DONE]` 后不再等待上游 HTTP 连接 EOF。
`client_disconnected` 只表示客户端关闭了连接,可能发生在客户端已经收到结果之后,不等于模型生成失败。结合 `upstream_done`、`finish` 和 `tokens` 判断上游进度;提前断开时 `tokens=?` 表示尚未收到 usage,不代表用量为零。
`cleanup=ok` 表示清理未报告错误;`timeout`、`cancelled` 或异常类型表示清理未正常完成。连接关闭使用取消保护并设置 5 秒超时,HTTPX 自动 EOF 清理和 Responses 重试连接也经过同一保护。日志仍默认只记录摘要;`--log-payloads` 才记录正文。进程被强制终止或日志磁盘不可写时,无法保证落盘。
### 思考模式与长对话
- 显式请求档位优先于模型默认值和全局默认值,每一轮独立处理,不按对话次数降低档位。
- Chat 使用 `reasoning_effort`,Responses 使用 `reasoning.effort`;`xhigh` 转成 `high`、`minimal` 转成 `low`、`none/no_think` 转成 `off`。其他非空档位原样交给上游判断。
- Anthropic 的 `thinking.type=enabled/adaptive` 默认对应 `high`;提供正整数预算时,`<=2048` 对应 `low`、`<=8192` 对应 `medium`,其余对应 `high`。这是档位近似映射,不保证严格的 token 预算。
- `thinking.type=disabled` 明确发送 `off`,不会被服务端默认 `high` 覆盖。上游是否支持关闭思考,仍取决于所选模型。
- 三种接口均保留上游返回的思考内容。Responses 通过 reasoning summary 事件和输出项返回,Anthropic 通过 thinking 块返回;客户端回传这些历史项时会恢复 assistant 的 `reasoning`。
- Chat 上游没有 Anthropic 的加密签名,thinking 块中的 `signature` 为空,仅支持经本转换器回传;不会伪造官方签名或解密其他服务的历史项。
- 如需避免客户端漏传档位造成变化,可设置 `--reasoning-effort high`,或在 `reasoning_effort.json` 中指定实际使用的模型 ID。模型映射是默认值配置,不是动态模型能力发现。
- 长历史不再被转换器静默截断,因此请求可能触及上游上下文限制。请由客户端显式管理上下文;`--desensitize` 仍可能压缩运行时说明和工具描述。
- `/v1/messages/count_tokens` 优先使用配置的上游计数接口,不可用时使用模型专属 tokenizer,详见下节。
事件格式参考:[OpenAI Responses 流事件](https://developers.openai.com/api/reference/resources/responses/streaming-events)、[Anthropic 流事件](https://platform.claude.com/docs/en/build-with-claude/streaming)。
### Token 计数
`POST /v1/messages/count_tokens` 要求明确的 `model` 和非空 `messages`。计数与 `/v1/messages` 共用协议转换、思考档位注入和脱敏处理,包含转换后的 system、历史消息和 tools,不再使用“字节数 / 3”。
1. 如果设置了 `--count-tokens-path /已确认的路径`,先使用当前企业 CodeBuddy 凭据调用该路径。接口需接收转换后的 **Chat JSON**(去掉 `stream` 和 `stream_options`),返回 `{"input_tokens": 非负整数}`。只允许同源绝对路径,不跟随重定向。返回 404/405/501 时回退;鉴权、限流、网络错误、5xx 和无效响应直接报错,避免掩盖故障。
2. 未设置路径或接口不支持时,按精确模型 ID 查找对应 tokenizer,用 `apply_chat_template(tokenize=True, add_generation_prompt=True)` 计数。支持工具的模板会纳入工具 schema、工具调用和结果;思考档位传给模板的 `reasoning_effort` / `enable_thinking`,历史思考按模板规则处理。
3. 两种方式均不可用时明确返回错误:未匹配模型、模板不支持请求内容为 **501**,tokenizer 文件下载/加载不可用为 **503**。不回退到字符估算,不将 Claude、GLM、DeepSeek 混用同一个分词器。
2026-10-10 在当前企业后端验证 `/v2/messages/count_tokens`、`/v1/messages/count_tokens`、`/v2/chat/completions/count_tokens` 均返回 404,已安装的 CodeBuddy CLI 使用本地粗估。**尚未确认可用的上游计数接口,因此默认不设置计数路径**;这不代表其他企业部署一定没有该能力。不要将生成接口配置为计数接口。
内置映射:
| CodeBuddy 模型 ID | 官方 tokenizer | 限制 |
|---|---|---|
| `glm-4.7` | `zai-org/GLM-4.7` | 文本、工具与可读思考,按公开聊天模板处理 |
| `deepseek-v3-0324` | `deepseek-ai/DeepSeek-V3-0324` | 公开模板未编码工具定义;带 `tools` 时返回 501 |
模型别名必须对应实际模型版本。`auto` 无法提前确定分词器;`deepseek-v4.1-flash` 等未匹配模型、无公开 tokenizer 的闭源模型也不会套用相似名称的 tokenizer。可用以下 JSON 给已有官方 tokenizer 的模型补充映射;本地目录应包含通过 `save_pretrained()` 保存的 tokenizer 文件和聊天模板:
```json
{
"glm-4.7": "/data/tokenizers/glm-4.7"
}
```
```bash
python converter.py --tokenizer-map tokenizer_map.json
```
首次使用内置映射会从 Hugging Face 下载 tokenizer 文件,随后使用磁盘缓存与进程内缓存;不会下载模型权重、上传对话或执行仓库自定义 Python 代码。离线环境可在联网环境预下载后复制目录:
```python
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("zai-org/GLM-4.7", trust_remote_code=False)
tokenizer.save_pretrained("./tokenizers/glm-4.7")
```
Docker 部署需要挂载 tokenizer 目录及映射 JSON,并在 `command` 中添加 `--tokenizer-map /data/tokenizer_map.json`;也可挂载 Hugging Face 缓存目录以复用在线下载结果。
成功响应保持 `{"input_tokens": N}` 格式,通过 `X-Token-Count-Source: upstream` 或 `tokenizer` 标记来源。**本地结果仍可能与上游实际 usage 不同**:企业网关的隐藏提示词、模板修改、自动路由、审核重试的再次压缩等无法在本地复现。当前 Chat 适配器不能完整转换图片、文档或加密思考,因此计数遇到这些内容会返回 501,避免静默漏算;不要把这个数当成精确账单或绝对上下文保证。依赖 count_tokens 自动压缩上下文的客户端需能处理计数不可用的错误。
参考:[Hugging Face 聊天模板](https://huggingface.co/docs/transformers/en/chat_templating)、[GLM-4.7 官方模型文件](https://huggingface.co/zai-org/GLM-4.7/tree/main)、[DeepSeek V3-0324 官方模板](https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/main/tokenizer_config.json)。
### curl 示例
```bash
curl http://127.0.0.1:8787/v1/models
curl http://127.0.0.1:8787/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"glm-5.2","messages":[{"role":"user","content":"你好"}]}'
curl -N http://127.0.0.1:8787/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"glm-5.2","stream":true,"messages":[{"role":"user","content":"数1到5"}]}'
```
---
## 日志与排障
### 推荐启动方式
```bash
uv run converter.py --desensitize --log converter.log
```
### 日志里能看到什么
每次请求都会带一个唯一 ID。默认摘要日志只记录:
- 请求类型、模型、消息数、工具数
- 响应耗时、结束原因、Token 数、工具调用名称
- 最终发送的 `reasoning_effort`(`upstream-default` 表示未注入)
- HTTP / 网络错误摘要
- `⚠️内容审核拦截`
日志默认按 10 MB 轮转并保留 3 份历史文件。只有临时排障确实需要查看
请求正文或原始 SSE 时,才显式开启:
```bash
python converter.py --desensitize --log converter.log --log-payloads
```
完整正文日志可能包含提示词、源码、工具参数和模型思考内容,排障完成后应关闭该选项。
排查思考模式变化时,先比较相邻请求的模型与 `reasoning_effort`,再检查上游是否返回思考内容。
### 最常见问题
#### 找不到登录文件
说明桌面端没登录,或者登录目录不在默认路径。先确认桌面端已经真正完成登录。
#### 401
分两种:
- 本地 401:你启用了 `--api-key`,但客户端没带同一个 key
- 后端 401:腾讯 token 失效,尝试重新打开桌面端登录
#### 响应慢
先换快一点的模型,比如 `deepseek-v4-flash`。
#### 被“敏感内容”拦截
这是腾讯后端的内容审核,不一定是用户问题本身敏感,很多时候是 agent runtime 文本触发的,比如:
- `DoS`
- `exploit`
- `credential`
- `sandbox`
- `escalation`
- 竞争品牌词
- tool description 中的安全术语
建议排查顺序:
1. 开 `--log`
2. 看同一请求 ID 下的 `REQUEST BODY` 或 `RESPONSES → CHAT BODY`
3. 如果是 Codex CLI,检查请求消息数和最终发送的 `reasoning_effort`
4. 开 `--desensitize`
5. 如果还不稳,再尝试 `--desensitize --no-compact`
---
## Docker 部署
如果你更习惯用 Docker,可以直接用。
前提是把宿主机登录态目录挂进去,因为容器里拿不到桌面端 auth 文件。
### docker compose
先改 `docker-compose.yml` 里的 auth 挂载路径,再执行:
```bash
docker compose up -d --build
```
### docker run
```bash
docker build -t workbuddy2api .
docker run -d --name workbuddy2api -p 8787:8787 \
-v ~/Library/Application Support/CodeBuddyExtension/Data/Public/auth:/data/auth:ro \
-e CODEBUDDY_AUTH_DIR=/data/auth \
workbuddy2api
```
### 相关环境变量
| 变量 | 说明 |
|------|------|
| `CODEBUDDY_AUTH_DIR` | 指定登录态目录 |
| `CODEBUDDY2OPENAI_KEY` | 本地 API Key |
| `CODEBUDDY2OPENAI_LOG` | 日志路径 |
---
## 模型列表
当前内置默认模型列表:
`glm-5.2`、`glm-5.1`、`glm-5v-turbo`、`kimi-k2.7`、`kimi-k2.6`、`kimi-k2.5`、`deepseek-v4-pro`、`deepseek-v4-flash`、`minimax-m3-pay`、`hy3-preview-agent`、`auto`
具体能不能用,取决于你的 WorkBuddy / CodeBuddy 订阅。
---
## 项目结构
```text
workbuddy2api/
├── converter.py
├── responses_adapter.py
├── anthropic_adapter.py
├── desensitize.py
├── codex-codebuddy.example.toml
├── test_responses_adapter.py
├── test_anthropic_adapter.py
├── test_reasoning.py
├── README.md
└── LICENSE
```
各文件作用:
- `converter.py`: 主入口,FastAPI 服务
- `responses_adapter.py`: OpenAI Responses ↔ Chat 适配
- `anthropic_adapter.py`: Anthropic Messages ↔ Chat 适配
- `desensitize.py`: 运行时文本压缩与零宽脱敏
---
## 致谢
本项目基于 [HanHan666666/codebuddy2openai](https://github.com/HanHan666666/codebuddy2openai) 的思路演进而来,感谢原作者的开源贡献。
## 免责声明
本项目仅用于个人学习与研究。与腾讯、WorkBuddy、CodeBuddy、OpenAI、Anthropic 无官方关联。请仅在你合法拥有订阅的前提下使用,并自行承担风险。
## 开源协议
[MIT](./LICENSE)
---
## English
`workbuddy2api` exposes your already logged-in **WorkBuddy / CodeBuddy** desktop session as local **OpenAI- and Anthropic-compatible APIs**.
Supported endpoints:
- `POST /v1/chat/completions`
- `POST /v1/responses`
- `POST /v1/messages`
- `GET /v1/models`
- `GET /health`
Recommended use cases:
- **Codex CLI** via `/v1/responses`
- **Claude Code / CC Switch** via `/v1/messages`
- **Cherry Studio / ZCode / LobeChat / Open WebUI** via `/v1/chat/completions`
### Quick Start
```bash
git clone https://github.com/ShouZhuo0413/codebuddy2openai.git workbuddy2api
cd workbuddy2api
uv venv
uv pip install -r requirements.txt
uv run converter.py --desensitize --log converter.log
```
Then verify:
```bash
curl http://127.0.0.1:8787/health
curl http://127.0.0.1:8787/v1/models
```
### Codex CLI
Use `/v1/responses` and keep `--desensitize` enabled.
```toml
[model_providers.workbuddy]
name = "WorkBuddy (via local converter)"
base_url = "http://127.0.0.1:8787/v1"
wire_api = "responses"
env_key = "CODEBUDDY2OPENAI_KEY"
[profiles.workbuddy]
model = "glm-5.2"
model_provider = "workbuddy"
```
Run:
```bash
export CODEBUDDY2OPENAI_KEY=any-value
codex --profile workbuddy "your task"
```
### Claude Code / CC Switch
Use `/v1/messages`:
```json
{
"DeepSeek-V4-Pro": {
"base_url": "http://127.0.0.1:8787/v1/messages",
"api_key": "",
"model": "deepseek-v4-pro"
}
}
```
### Notes
- `--desensitize` is recommended for both Codex CLI and Claude Code
- `/v1/responses` preserves full history and tool payloads; send the full `input` on every request (`previous_response_id` is unsupported)
- `--desensitize --no-compact` preserves more of the original system prompt
- if that still gets review-blocked, `/v1/responses` will retry once in compact mode
### CLI Options
```bash
python converter.py [--host HOST] [--port PORT] [--api-key KEY] [--log PATH]
[--log-payloads] [--log-max-mb MB] [--log-backup-count N]
[--reasoning-effort off|low|medium|high] [--desensitize] [--skip-check]
```
### Disclaimer
For personal learning and research only. Not affiliated with Tencent, WorkBuddy, CodeBuddy, OpenAI, or Anthropic.
---
Keywords: codebuddy to openai · codebuddy2openai · workbuddy api proxy · workbuddy openai adapter · codex cli workbuddy · claude code workbuddy · tencent code assistant openai compatible api