# dsh-codebuddy-auth [English](README.md) | 简体中文 在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH) 里直接使用[腾讯 CodeBuddy](https://www.codebuddy.cn)(IOA)的对话模型:浏览器 OAuth 登录、token 自动续期、模型列表自动同步。登录一次,模型选择器里即可选用 `deepseek-v4-pro`、`glm-5.2`、`kimi-k3-1`、`minimax-m3` 等 craft agent 模型。 ## 工作原理 插件在 `codebuddy` provider 上注册**原生 `ctx.llm` 适配器**,自己持有整条请求链路:浏览器 OAuth、`ctx.credentials` 凭据存储、`/v3/config` 模型发现、自有的 SSE 流式与消息序列化。两套身份,按平面各司其职: | 平面 | 身份 | 原因 | | --- | --- | --- | | 聊天(`POST /v2/chat/completions`) | CLI 客户端(`User-Agent: CLI/2.96.0 CodeBuddy/2.96.0`,极简请求头) | 聊天端点期待 CLI 身份,用它可避开 IDE 身份拦截。 | | 模型发现(`GET /v3/config`) | Craft / VSCode(`X-Agent-Intent: craft` + `X-IDE-*`) | craft 目录是唯一披露每模型推理元数据(`supportedEfforts`、`canDisableThinking`、`defaultEffort`)与精选模型列表的目录;CLI 目录同一端点只返回固定的 `effort` 值。 | 模型目录缓存 5 分钟,可随时 `sync-models` 刷新。 ## 兼容性 已在 DeepSeek Harness 桌面版 **0.2.0-rc.2**(`@deepseek-ai/dsh-llm` 0.2.0-rc.2)上验证。适配器遵循当前宿主契约:tool-call id 经 `ToolCallId` 品牌化(`CallId` 已不存在),工具结果以独立 `role: 'tool'` 消息回放。0.8.2 及更早版本把工具结果序列化成普通 user 文本,任何用到工具的对话都会在第二轮报 `CodeBuddy API error (HTTP 400)`(`11148 tool calls and tool results do not match`)。 ## 安装 DSH 通过官方 `dsh plugin` CLI 安装 profile 插件(它是个精简的 `pnpm` 转发器:安装依赖、把包追加到 profile 的 `dsh.profile.bundles` 层栈、再经包内的 patch 挂载插件——全程无需手动改文件)。 **前置条件**:确保 `pnpm` 在 `PATH` 里,例如用 Homebrew 安装: ```bash brew install pnpm ``` ### 安装插件 ```bash dsh plugin --profile web add github:cainiao1992/dsh-codebuddy-auth ``` 这一条命令即从 GitHub 解析依赖、安装,并自动把插件作为 profile 层激活。 ### 重启 DSH 重启 DSH,安装即完成——插件启动时在 `ctx.llm` 上原生注册 `codebuddy` provider,CodeBuddy 随即出现在模型页(未登录状态)。 ## 登录 可以用 agent 登录,也可以用命令行登录,二选一。 ### 方式一:通过 agent 对 agent 说 **"用 codebuddy 登录"**。agent 调用 `codebuddy` 工具:浏览器打开 IOA 登录页,后台轮询;token 到手后写入凭据并预热模型目录,下一个请求即以 CLI 身份直连聊天端点。 ### 方式二:命令行(headless / 提前引导) ```bash # 直接运行,无 npm 依赖,仅需 Node >= 18: node ~/.dsh/profiles/web/node_modules/dsh-codebuddy-auth/bin/login-flow.mjs # 或经 package.json 的 bin 字段从安装目录本地解析: cd ~/.dsh/profiles/web && pnpm exec codebuddy-login # 不想开浏览器(远程/服务器)加 --no-browser ``` CLI 只写凭据——原生适配器自己持有路由,没有 settings 路由需要管理;`--international` 仅选择登录走的 OAuth 端点。 ## 卸载 ```bash dsh plugin --profile web remove dsh-codebuddy-auth ``` 该命令会移除依赖,并把插件从 profile 层栈中摘除。重启 DSH 即完成卸载。 ## 国际版 插件默认使用**国内版**(`copilot.tencent.com` / `www.codebuddy.cn`)。国际版(`www.codebuddy.ai`)通过挂载行的 `edition: intl` 配置选择: ```yaml # 你的 cordis.patch.yml 挂载行: - id: codebuddy-auth name: dsh-codebuddy-auth edition: intl # 缺省即国内版 ``` 适配器与登录/模型发现随即全部使用 `www.codebuddy.ai` 端点。CLI 的 `--international` 仅为登录选择国际 OAuth 端点。 ## 使用 - **切换模型**:模型选择器里选 CodeBuddy 下的任意模型(如 `deepseek-v4-pro`) - **状态**:"看下 codebuddy 状态" → `codebuddy` 工具 `status` - **续期(全自动,三层)**:① 每次启动时,token 剩余有效期不足 5 分钟(或已过期)即自动续;② 运行中每 30 分钟巡检,剩余不足 1 小时自动续——覆盖 dsh 长期不重启的场景;③ refresh token 失效(改密/吊销)时前两层会失败并留日志,此时说 "刷新 codebuddy" 确认,或重新登录 - **模型更新**:腾讯上新模型后,说 "同步 codebuddy 模型" → `sync-models` - **退出**:"登出 codebuddy" → 清除凭据 ### 推理 每个模型都按 `/v3/config` 报告的**完整真实推理能力**声明,模型选择器里展示该模型实际支持的等级: - **可选等级**(按模型):`supportedEfforts` 原样进选择器——`deepseek-v4-pro` 可选 `low` / `high` / `xhigh`,`hy3` 可选 `low` / `high`,固定等级模型(如 `glm-5.1`)只有 `medium` 一档。线上以 `reasoning_effort: ""` 发送。 - **默认等级**:每模型直接采用 `/v3/config` 报告的 `defaultEffort`(如 glm-5.2 默认 high),选择器里所有已声明等级仍可自由选。 ## 文件 - `lib/index.js` — Cordis 宿主插件(host 组合行)。注册 `codebuddy` provider 与 `codebuddy` 工具,启动时及每 30 分钟自动刷新/同步。 - `lib/codebuddy-adapter.mjs` — 原生 `ctx.llm` 适配器:SSE 流式、消息序列化、推理元数据、错误映射。移植自 [shatyuka/dsh-llm-codebuddy](https://github.com/shatyuka/dsh-llm-codebuddy)(MIT)。 - `lib/codebuddy-core.mjs` — OAuth、JWT 解码、身份头、`/v3/config` 发现;无依赖。 - `bin/login-flow.mjs` — 独立登录 CLI,无 npm 依赖。 - `cordis.patch.yml` — 包内 patch(bundle 消费时的自挂载行)。 ## 排障 **插件管理器显示 `failed to import` / `codebuddy` 工具始终不出现。** 桌面端只给一句摘要;复制一份 profile 冷启动,就能看到真正的导入错误: ```bash cp -R ~/.dsh/profiles/desktop ~/.dsh/profiles/cbprobe dsh --profile cbprobe --no-open # 失败的 entry 及其原因会打到 stderr rm -rf ~/.dsh/profiles/cbprobe ``` 实测过的两种原因: - **dsh 改名了插件用到的 dsh-llm 导出。** dsh 0.2.0-rc.2 把 `CallId` 改名为 `ToolCallId`,插件 ≤0.8.2 在 ESM 链接阶段就失败(`does not provide an export named 'CallId'`),entry 保持未激活。0.8.3 已修复,按下述命令升级即可。 - **profile 里残留的软链接**(早期手动安装遗留)占住了 `~/.dsh/profiles//node_modules` 里的 `@deepseek-ai/*` 名字。检查并删除这类死链即可;DSH 自身会把 installation 作用域的包路由进桌面版 `app.asar` 副本,不需要抽取 asar、也不需要手动软链。 升级(桌面版:先完全退出应用——该 profile 由 Electron 独占管理): ```bash dsh plugin --profile desktop update dsh-codebuddy-auth # 桌面版,退出应用后执行 dsh plugin --profile web update dsh-codebuddy-auth # 其他 profile 随时可执行 ``` git 依赖会被 `pnpm-lock.yaml` 钉住:`pnpm install` 和重复的 `dsh plugin add` 都复用已锁定的 commit;`dsh plugin update `(即 pnpm update)才会把 `github:/` 重新解析到新 HEAD。 不要用裸 `node --input-type=module -e "import('@deepseek-ai/dsh-llm')"` 验证解析——它绕过了 DSH 的模块解析拦截,在 profile 目录里必然失败。上面探针 profile 的冷启动输出才是有效信号。 ## 已知限制(均为实测结论) - `POST /v2/chat/completions` **不校验 User-Agent**,任意 UA 均可;但必须 `stream: true`(非流式返回 `code 11101`)。DSH 的 llm 适配器本来就是流式,无需处理。 - `GET /v3/config`(模型发现)需要 craft / VSCode 身份(`X-Agent-Intent: craft` + `X-IDE-*` 头)才会披露推理元数据;插件自己直接发请求完成。 - CodeBuddy 对每个 craft 模型都报告 `supportsReasoning`。模型按真实推理能力声明(按 `supportedEfforts` 列出等级),因此推理可在模型选择器里直接选用,而非被剥离。 ## License MIT