# 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