# 参数说明 本文基于当前代码实现整理,目的是给后续编写转发程序时提供一份可直接对照的参数参考。 涉及的主要代码位置: - [src/direct-chat.ts](src/direct-chat.ts) — 直连 `copilot.tencent.com` 的请求构造 - [src/server.ts](src/server.ts) — 本地转发服务入口 - [src/protocols.ts](src/protocols.ts) — OpenAI / Anthropic 协议适配 - [src/prompt.ts](src/prompt.ts) — prompt 拼接规则 - [src/config.ts](src/config.ts) — 服务端环境变量和账号加载 - [src/codebuddy.ts](src/codebuddy.ts) — Agent SDK session 参数 --- ## 1. 总览 当前仓库里有两条主要链路: ### 1.1 直连远端链路 入口:`npm run chat:direct` 对应代码: - [package.json:7](package.json#L7) - [src/direct-chat.ts](src/direct-chat.ts) 这条链路直接请求: - `https://copilot.tencent.com/v2/chat/completions` 它需要你构造: 1. HTTP 请求头 2. JSON 请求体 3. system prompt 4. user message 包装内容 5. CLI 上下文注入内容 这部分最适合后续做“远端转发 / 伪装成官方客户端”的参考。 ### 1.2 本地代理链路 入口:`npm run start` 对应代码: - [package.json:8](package.json#L8) - [src/server.ts](src/server.ts) 这条链路提供本地兼容接口: - `POST /v1/chat/completions` - `POST /chat/completions` - `POST /v1/messages` 它本身不直接拼远端 HTTP 头,而是把请求转成 prompt 后交给 Agent SDK。 --- ## 2. 直连远端链路需要的参数 以下内容来自 [src/direct-chat.ts:19-220](src/direct-chat.ts#L19-L220)。 ## 2.1 目标地址 ### `CODEBUDDY_DIRECT_ENDPOINT` - 作用:远端接口地址 - 默认值:`https://copilot.tencent.com/v2/chat/completions` - 代码位置:[src/direct-chat.ts:19](src/direct-chat.ts#L19) - 是否必需:否 如果你后续写转发程序要直接打官方接口,这个值就是默认目标地址。 --- ## 2.2 模型参数 ### `CODEBUDDY_MODEL` - 作用:请求体中的 `model` - 默认值:`minimax-m2.7` - 代码位置:[src/direct-chat.ts:20](src/direct-chat.ts#L20) - 是否必需:否 请求体中实际发送: ```json { "model": "minimax-m2.7" } ``` --- ## 2.3 鉴权参数 ### `CODEBUDDY_API_KEY` - 作用:远端请求鉴权主凭证 - 代码位置:[src/direct-chat.ts:21](src/direct-chat.ts#L21)、[src/direct-chat.ts:162-177](src/direct-chat.ts#L162-L177) - 是否必需:是(除非从文件读取) 它会被同时用于这些 header: - `authorization: Bearer ` - `x-api-key: ` - `x-user-id: anonymous_` ### `CODEBUDDY_APIKEY_FILE` - 作用:当环境变量没有设置 `CODEBUDDY_API_KEY` 时,从文件读取 key - 默认值:`apikey` - 代码位置:[src/direct-chat.ts:166](src/direct-chat.ts#L166) - 是否必需:否 读取规则: - 逐行读取 - 去掉空白 - 跳过 `#` 注释行 - 取第一条有效内容 如果环境变量和文件都没有,会报错: - `Missing API key. Set CODEBUDDY_API_KEY or create apikey.` --- ## 2.4 system prompt 相关参数 ### `CODEBUDDY_DISABLE_SYSTEM_PROMPT` - 作用:关闭 system prompt 注入 - 生效条件:值为 `1` - 代码位置:[src/direct-chat.ts:179-180](src/direct-chat.ts#L179-L180) - 是否必需:否 ### `CODEBUDDY_SYSTEM_PROMPT` - 作用:直接通过环境变量传入 system prompt - 代码位置:[src/direct-chat.ts:182-183](src/direct-chat.ts#L182-L183) - 是否必需:否 - 优先级:高于文件 ### `CODEBUDDY_SYSTEM_PROMPT_FILE` - 作用:从文件读取 system prompt - 默认值:`captures/codebuddy-system-prompt.txt` - 代码位置:[src/direct-chat.ts:185-187](src/direct-chat.ts#L185-L187) - 是否必需:否 ### system prompt 注入规则 代码位置:[src/direct-chat.ts:107-109](src/direct-chat.ts#L107-L109) 如果存在 system prompt,请求体里的 `messages` 会变成: ```json [ { "role": "system", "content": "...system prompt..." }, ...history ] ``` 否则直接发送历史消息。 --- ## 2.5 user message 包装参数 ### `CODEBUDDY_DISABLE_USER_QUERY_WRAP` - 作用:关闭 `...` 包装 - 生效条件:值为 `1` - 代码位置:[src/direct-chat.ts:111-117](src/direct-chat.ts#L111-L117) - 是否必需:否 注意:当前实现里这个开关不只是去掉 `` 标签。因为 `buildUserContent()` 在该开关为 `1` 时会直接返回原始字符串,所以也会同时跳过 `cliUserContextBlocks` 注入。 也就是说: - 默认模式:`user.content` 是 `text` block 数组,包含 CLI 上下文和 `` - `CODEBUDDY_DISABLE_USER_QUERY_WRAP=1`:`user.content` 退化为纯字符串,不包含 CLI 上下文 默认情况下,用户输入不会直接以纯字符串发送,而是被包装成: ```json [ ...cliUserContextBlocks, { "type": "text", "text": "用户输入" } ] ``` 也就是说默认 user message 的 `content` 是一个数组,而不是纯字符串。 如果关闭包装,则发送原始字符串: ```json { "role": "user", "content": "用户原始输入" } ``` --- ## 2.6 CLI 上下文注入参数 ### `CODEBUDDY_DISABLE_CLI_USER_CONTEXT` - 作用:关闭从抓包文件中提取 CLI 上下文并注入 user message - 生效条件:值为 `1` - 代码位置:[src/direct-chat.ts:190-191](src/direct-chat.ts#L190-L191) - 是否必需:否 ### `CODEBUDDY_CLI_CAPTURE_FILE` - 作用:指定抓包文件,用来抽取 user message 中的上下文块 - 默认值:`captures/codebuddy-chat-completion-full.redacted.json` - 代码位置:[src/direct-chat.ts:193-194](src/direct-chat.ts#L193-L194) - 是否必需:否 ### CLI 上下文提取规则 代码位置:[src/direct-chat.ts:196-209](src/direct-chat.ts#L196-L209) 程序会: 1. 读取抓包 JSON 2. 找到 `request_body.messages` 里第一条 `role === "user"` 的消息 3. 仅保留 `content` 数组中的 `type === "text"` 块 4. 过滤掉含有 `` 的块 5. 剩余部分作为 `cliUserContextBlocks` 也就是说,这些上下文块本质上用于模拟官方客户端注入的: - memory - system-reminder - IDE context - 其他包装文本 这部分是当前直连效果接近官方 chat-completion 的关键参数来源。 当前抓包里 `user.content` 实际是 3 段 `text` block: 1. memory / system-reminder 2. IDE / system-reminder 3. `真实用户输入` 后续不同 CLI 版本、目录状态或配置下,前面的上下文 block 数量可能变化。因此转发程序不应该写死为 2 个上下文 block,而应该按当前逻辑处理为: ```text 0..N 个 CLI context blocks + 1 个 block ``` --- ## 2.7 采样 / 推理相关参数 这些字段直接写进远端请求体。 ### `CODEBUDDY_TEMPERATURE` - 作用:请求体中的 `temperature` - 默认值:`1` - 代码位置:[src/direct-chat.ts:72](src/direct-chat.ts#L72) ### `CODEBUDDY_MAX_TOKENS` - 作用:请求体中的 `max_tokens` - 默认值:`48000` - 代码位置:[src/direct-chat.ts:73](src/direct-chat.ts#L73) ### `CODEBUDDY_REASONING_EFFORT` - 作用:请求体中的 `reasoning_effort` - 默认值:`medium` - 代码位置:[src/direct-chat.ts:74](src/direct-chat.ts#L74) ### `CODEBUDDY_VERBOSITY` - 作用:请求体中的 `verbosity` - 默认值:`high` - 代码位置:[src/direct-chat.ts:75](src/direct-chat.ts#L75) ### `CODEBUDDY_REASONING_SUMMARY` - 作用:请求体中的 `reasoning_summary` - 默认值:`auto` - 代码位置:[src/direct-chat.ts:76](src/direct-chat.ts#L76) --- ## 2.8 远端请求体完整结构 代码位置:[src/direct-chat.ts:63-77](src/direct-chat.ts#L63-L77) 当前程序实际发送的 JSON 结构为: ```json { "model": "minimax-m2.7", "messages": [ { "role": "system", "content": "..." }, { "role": "user", "content": [ { "type": "text", "text": "...context block 1..." }, { "type": "text", "text": "...context block 2..." }, { "type": "text", "text": "..." } ] } ], "stream": true, "stream_options": { "include_usage": true }, "temperature": 1, "max_tokens": 48000, "reasoning_effort": "medium", "verbosity": "high", "reasoning_summary": "auto" } ``` 其中固定发送的字段有: - `model` - `messages` - `stream: true` - `stream_options.include_usage: true` - `temperature` - `max_tokens` - `reasoning_effort` - `verbosity` - `reasoning_summary` --- ## 2.9 远端请求头完整结构 代码位置:[src/direct-chat.ts:130-159](src/direct-chat.ts#L130-L159) 当前程序会发送以下 headers: | Header | 来源 | 说明 | |---|---|---| | `content-type` | 固定 | `application/json` | | `content-encoding` | 固定 | `gzip` | | `accept` | 固定 | `application/json` | | `x-requested-with` | 固定 | `XMLHttpRequest` | | `authorization` | `CODEBUDDY_API_KEY` | Bearer 鉴权 | | `x-api-key` | `CODEBUDDY_API_KEY` | 额外鉴权头 | | `x-conversation-id` | 随机 UUID | 会话 ID | | `x-conversation-request-id` | 随机 hex | 请求 ID | | `x-conversation-message-id` | 随机 hex | 消息 ID | | `x-agent-intent` | 固定 | `craft` | | `x-ide-type` | 固定 | `CLI` | | `x-ide-name` | 固定 | `CLI` | | `x-ide-version` | 固定 | `2.93.3` | | `user-agent` | `CODEBUDDY_USER_AGENT` 或默认值 | 模拟客户端 UA | | `x-trace-id` | 随机 hex | trace id | | `x-request-id` | 与 `x-trace-id` 相同 | request id | | `b3` | 由 traceId + spanId 组成 | b3 tracing | | `x-b3-traceid` | traceId | tracing | | `x-b3-parentspanid` | 固定空串 | tracing | | `x-b3-spanid` | spanId | tracing | | `x-b3-sampled` | 固定 | `1` | | `x-codebuddy-request` | 固定 | `1` | | `x-user-id` | apiKey 后 8 位 | 匿名用户标识 | | `x-product` | 固定 | `SaaS` | 补充:代码中会设置 `x-b3-parentspanid: ""`,但在最终抓包中这个空 header 可能被客户端或中间层丢弃,因此抓包里不一定能看到它。这个字段不是核心鉴权字段;如果后续要严格复刻官方 CLI,可以单独测试是否需要保留。 ### `CODEBUDDY_USER_AGENT` - 作用:覆盖 `user-agent` - 默认值: ```text CLI/2.93.3 CodeBuddy/2.93.3 CodeBuddy Agent SDK/0.3.28 (Node.js/25.2.1) CodeBuddy Code/2.93.3 ``` - 代码位置:[src/direct-chat.ts:147-148](src/direct-chat.ts#L147-L148) --- ## 3. 本地代理服务需要的参数 以下内容来自 [src/config.ts](src/config.ts)、[src/server.ts](src/server.ts)、[src/codebuddy.ts](src/codebuddy.ts)。 ## 3.1 服务监听参数 ### `PORT` - 作用:本地 HTTP 服务监听端口 - 默认值:`8787` - 代码位置:[src/config.ts:38](src/config.ts#L38) - 是否必需:否 ### `PROXY_API_KEY` - 作用:本地代理服务的访问鉴权 - 代码位置:[src/config.ts:39](src/config.ts#L39)、[src/server.ts:98-102](src/server.ts#L98-L102) - 是否必需:否 如果设置了该值,客户端调用本地代理时必须带: ```http Authorization: Bearer ``` --- ## 3.2 本地代理支持的接口 代码位置:[src/server.ts:29-49](src/server.ts#L29-L49) ### OpenAI 风格 - `POST /v1/chat/completions` - `POST /chat/completions` ### Anthropic 风格 - `POST /v1/messages` ### 其他接口 - `GET /health` - `GET /debug/memory` - `GET /v1/models` --- ## 3.3 本地代理可接受的 OpenAI 请求参数 定义位置:[src/protocols.ts:5-9](src/protocols.ts#L5-L9) 当前代码真正使用的只有: | 字段 | 是否必需 | 说明 | |---|---|---| | `model` | 否 | 请求模型名 | | `messages` | 否 | 消息数组 | | `stream` | 否 | 是否流式输出 | ### prompt 拼接规则 代码位置: - [src/server.ts:66-77](src/server.ts#L66-L77) - [src/protocols.ts:18-20](src/protocols.ts#L18-L20) - [src/prompt.ts:6-10](src/prompt.ts#L6-L10) OpenAI 风格请求会被转成: ```text ROLE: content ROLE: content ``` 也就是把每条 message 变成: - `SYSTEM:` - `USER:` - `ASSISTANT:` 再按文本拼接。 --- ## 3.4 本地代理可接受的 Anthropic 请求参数 定义位置:[src/protocols.ts:11-16](src/protocols.ts#L11-L16) 当前代码真正使用的只有: | 字段 | 是否必需 | 说明 | |---|---|---| | `model` | 否 | 请求模型名 | | `system` | 否 | system prompt | | `messages` | 否 | 消息数组 | | `stream` | 否 | 是否流式输出 | ### prompt 拼接规则 代码位置: - [src/server.ts:80-91](src/server.ts#L80-L91) - [src/protocols.ts:22-24](src/protocols.ts#L22-L24) - [src/prompt.ts:13-18](src/prompt.ts#L13-L18) Anthropic 风格请求会被转成: ```text SYSTEM: ... USER: ... ASSISTANT: ... ``` 如果 `system` 为空,则不加 `SYSTEM:` 段。 --- ## 3.5 content 到纯文本的转换规则 代码位置:[src/prompt.ts:21-38](src/prompt.ts#L21-L38) `contentToText()` 支持: 1. `string` 2. `Array` 3. `object` 处理规则: ### 如果是字符串 直接返回。 ### 如果是数组 逐项处理: - 如果项本身是字符串,直接保留 - 如果项是对象,优先取 `text` - 否则尝试取 `content` - 最终用换行拼接 ### 如果是对象 只尝试取 `text` ### 这意味着 你的 OpenAI / Anthropic 转发层如果传入类似: ```json [ { "type": "text", "text": "hello" }, { "type": "text", "text": "world" } ] ``` 最终会变成: ```text hello world ``` --- ## 4. 本地代理服务的环境变量 ## 4.1 模型和权限相关 ### `CODEBUDDY_MODEL` - 作用:本地代理默认模型 - 代码位置:[src/config.ts:40](src/config.ts#L40) - 是否必需:否 如果请求体里没带 `model`,则用它。 ### `CODEBUDDY_PASS_REQUEST_MODEL` - 作用:是否把客户端请求中的 `model` 透传给 SDK session - 生效条件:值为 `1` - 代码位置:[src/config.ts:41](src/config.ts#L41)、[src/server.ts:94-95](src/server.ts#L94-L95) - 默认值:关闭 如果不开启,则请求里的 `model` 不会真正影响底层 SDK,只用于返回值展示。 ### `CODEBUDDY_PERMISSION_MODE` - 作用:创建 Agent SDK session 时的权限模式 - 默认值:`bypassPermissions` - 代码位置:[src/config.ts:42](src/config.ts#L42)、[src/codebuddy.ts:85-89](src/codebuddy.ts#L85-L89) 允许值: - `default` - `acceptEdits` - `bypassPermissions` - `plan` - `delegate` - `dontAsk` --- ## 4.2 账号加载参数 代码位置:[src/config.ts:48-76](src/config.ts#L48-L76) 账号加载优先级如下: 1. `CODEBUDDY_ACCOUNTS_JSON` 2. `CODEBUDDY_API_KEY` / `CODEBUDDY_AUTH_TOKEN` 3. `CODEBUDDY_APIKEY_FILE` 如果全部都没有,会报错。 ### `CODEBUDDY_ACCOUNTS_JSON` - 作用:通过 JSON 传入多个账号 - 代码位置:[src/config.ts:49](src/config.ts#L49) - 是否必需:否 支持两种格式: ```json [ { "id": "a1", "apiKey": "xxx", "authToken": "yyy", "internetEnvironment": "zzz", "configDir": "/path/to/dir" } ] ``` 或: ```json { "accounts": [ { "id": "a1", "apiKey": "xxx" } ] } ``` ### `CODEBUDDY_API_KEY` - 作用:单账号 API Key - 代码位置:[src/config.ts:52-58](src/config.ts#L52-L58) ### `CODEBUDDY_AUTH_TOKEN` - 作用:单账号 Auth Token - 代码位置:[src/config.ts:52-58](src/config.ts#L52-L58) ### `CODEBUDDY_INTERNET_ENVIRONMENT` - 作用:账号附带的网络环境参数 - 代码位置:[src/config.ts:57](src/config.ts#L57) ### `CODEBUDDY_APIKEY_FILE` - 作用:凭证文件路径 - 默认值:`apikey` - 代码位置:[src/config.ts:61](src/config.ts#L61) ### `CODEBUDDY_TOKEN_KIND` - 作用:当凭证文件是“裸 token 列表”时,指定这些行应被当成 `api_key` 还是 `auth_token` - 可选值:`api_key` / `auth_token` - 默认值:`api_key` - 代码位置:[src/config.ts:70](src/config.ts#L70) --- ## 4.3 账号对象字段 定义位置:[src/config.ts:4-10](src/config.ts#L4-L10) 单个账号支持这些字段: | 字段 | 说明 | |---|---| | `id` | 账号标识 | | `apiKey` | API Key | | `authToken` | Auth Token | | `internetEnvironment` | 网络环境标识 | | `configDir` | 单账号配置目录 | ### `configDir` 默认规则 代码位置:[src/config.ts:108-118](src/config.ts#L108-L118) 如果未显式提供,默认会创建: ```text /.codebuddy-accounts/ ``` --- ## 5. Agent SDK session 实际使用的参数 代码位置:[src/codebuddy.ts:83-98](src/codebuddy.ts#L83-L98) 创建 session 时,实际传入: | 参数 | 来源 | |---|---| | `cwd` | `process.cwd()` | | `model` | `requestedModel || app.model` | | `permissionMode` | `CODEBUDDY_PERMISSION_MODE` | | `includePartialMessages` | 固定 `true` | | `settingSources` | 固定 `[]` | | `env.CODEBUDDY_API_KEY` | 账号配置 | | `env.CODEBUDDY_AUTH_TOKEN` | 账号配置 | | `env.CODEBUDDY_INTERNET_ENVIRONMENT` | 账号配置 | | `env.CODEBUDDY_CONFIG_DIR` | 账号配置 | 这意味着后续如果你写的是“本地代理 -> Agent SDK -> CodeBuddy”的转发,不需要手工拼远端 HTTP headers,但需要把账号参数和 session 参数配对好。 --- ## 6. 返回格式参数 以下来自 [src/protocols.ts](src/protocols.ts)。 ## 6.1 OpenAI 非流式响应 代码位置:[src/protocols.ts:26-35](src/protocols.ts#L26-L35) 固定结构: ```json { "id": "chatcmpl-...", "object": "chat.completion", "created": 1234567890, "model": "...", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 } } ``` --- ## 6.2 OpenAI 流式响应 代码位置:[src/protocols.ts:37-54](src/protocols.ts#L37-L54) 每个 SSE chunk 结构: ```json { "id": "chatcmpl-...", "object": "chat.completion.chunk", "created": 1234567890, "model": "...", "choices": [ { "index": 0, "delta": { "content": "..." }, "finish_reason": null } ] } ``` 结束时输出: ```text data: [DONE] ``` --- ## 6.3 Anthropic 非流式响应 代码位置:[src/protocols.ts:56-67](src/protocols.ts#L56-L67) 固定结构: ```json { "id": "msg_xxx", "type": "message", "role": "assistant", "model": "...", "content": [ { "type": "text", "text": "..." } ], "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 0, "output_tokens": 0 } } ``` --- ## 6.4 Anthropic 流式响应 代码位置:[src/protocols.ts:69-86](src/protocols.ts#L69-L86) 事件顺序固定为: 1. `message_start` 2. `content_block_start` 3. 多次 `content_block_delta` 4. `content_block_stop` 5. `message_delta` 6. `message_stop` --- ## 7. 后续写转发程序时最关键的参数 如果目标是“尽可能复刻当前 direct-chat 效果”,最关键的是下面这些: ### 必需参数 | 参数 | 原因 | |---|---| | `CODEBUDDY_API_KEY` | 远端鉴权必须有 | | `authorization` / `x-api-key` | 远端请求头必须有 | | `model` | 请求体核心字段 | | `messages` | 请求体核心字段 | | `stream` | 当前实现固定启用 | | `stream_options.include_usage` | 当前实现固定启用 | ### 高影响参数 | 参数 | 原因 | |---|---| | system prompt | 决定基础行为 | | `cliUserContextBlocks` | 决定是否接近官方 chat-completion 行为 | | `` 包装 | 决定用户问题在 prompt 中的结构 | | `reasoning_effort` | 影响推理风格 | | `verbosity` | 影响输出密度 | | `reasoning_summary` | 影响返回行为 | | `max_tokens` | 影响可输出长度 | | `temperature` | 影响稳定性与发散度 | ### 容易忽略但建议保留的请求头 | Header | 原因 | |---|---| | `x-conversation-id` | 会话标识 | | `x-conversation-request-id` | 请求标识 | | `x-conversation-message-id` | 消息标识 | | `user-agent` | 客户端指纹的一部分 | | `x-ide-type` / `x-ide-name` / `x-ide-version` | 客户端环境标识 | | `x-trace-id` / `x-request-id` / `b3` | tracing 相关 | | `x-codebuddy-request` | 客户端标识 | | `x-product` | 产品标识 | --- ## 8. 建议的最小转发模板 如果你后续单独写一个远端转发器,建议最少保证下面这些字段齐全: ### 请求头最小集合 ```json { "content-type": "application/json", "content-encoding": "gzip", "accept": "application/json", "authorization": "Bearer ", "x-api-key": "", "x-conversation-id": "", "x-conversation-request-id": "", "x-conversation-message-id": "", "x-agent-intent": "craft", "x-ide-type": "CLI", "x-ide-name": "CLI", "x-ide-version": "2.93.3", "user-agent": "", "x-trace-id": "", "x-request-id": "", "b3": "--1-", "x-b3-traceid": "", "x-b3-spanid": "", "x-b3-sampled": "1", "x-codebuddy-request": "1", "x-user-id": "anonymous_", "x-product": "SaaS" } ``` ### 请求体最小集合 ```json { "model": "minimax-m2.7", "messages": [ { "role": "system", "content": "..." }, { "role": "user", "content": [ { "type": "text", "text": "...context 1..." }, { "type": "text", "text": "...context 2..." }, { "type": "text", "text": "..." } ] } ], "stream": true, "stream_options": { "include_usage": true }, "temperature": 1, "max_tokens": 48000, "reasoning_effort": "medium", "verbosity": "high", "reasoning_summary": "auto" } ``` --- ## 9. 一句话结论 如果后续目标是“写一个效果尽量接近官方 chat-completion 的转发器”,真正不能少的不是只有 system prompt,而是这四层一起保留: 1. `system prompt` 2. `cliUserContextBlocks` 3. `` 包装 4. 一整套近似官方的 headers 和请求体参数