hy3-local-gateway
README.md
# CodeBuddy Local Gateway
> 非官方社区项目,与腾讯、CodeBuddy 或各模型官方团队无隶属或关联关系。
这个项目把当前系统用户已经登录的 CodeBuddy 会话复用为两个本地入口,不需要
TokenHub API Key,也不会复制或导出 CodeBuddy 登录凭据:
1. **MCP 桥接**:枚举当前账号可用模型,并把指定模型作为只读推理子 Agent。
2. **OpenAI 兼容反代**:提供动态模型列表和 Chat Completions 文本接口。
`hy3-local-gateway` 是为兼容已有安装保留的包名和命令名;网关已经不再固定使用
Hy3。核心实现在 [src/codebuddy.js](src/codebuddy.js),`ask_hy3` 只是兼容入口。
## 环境要求
- Node.js 20 或更高版本。
- 使用当前系统用户运行过 `codebuddy` 并完成登录。
- CodeBuddy 的 `/model` 菜单中能够看到并使用所需模型。
支持全局安装和源码运行两种方式。无论选择哪一种,都必须先执行对应的 npm 安装
命令,不能跳过安装步骤。
方式一:从 GitHub 全局安装:
```bash
npm install --global github:Embracecactus/hy3-local-gateway
```
安装后会得到一个与源码目录无关的命令:
```bash
hy3-local-gateway --help
```
方式二:克隆源码并安装项目依赖:
```bash
git clone https://github.com/Embracecactus/hy3-local-gateway.git
cd hy3-local-gateway
npm install
```
源码首次运行前必须执行 `npm install`;`package-lock.json` 更新后也应再次执行。跳过
该步骤会因缺少依赖而启动失败。安装完成后可按用途选择一个 npm 启动脚本:
```bash
npm run start:mcp
npm run start:proxy
```
## 功能一:MCP 桥接
MCP Server 通过 stdio 提供三个工具:
- `list_codebuddy_models`:读取当前 CodeBuddy 登录账号可用的模型 ID。
- `ask_codebuddy`:通过 `model` 参数调用任意可用模型,默认使用 `hy3`。
- `ask_hy3`:兼容旧配置的 Hy3 固定入口。
模型在这些入口中不能读取文件、执行命令或修改项目。调用方需要先读取必要上下文,
再把相关代码和任务完整放进 `prompt`。
### 图片支持(多模态)
`ask_codebuddy` 和 `ask_hy3` 支持通过 `images` 参数把图片一起发给支持多模态的模型
(如 Hy3、GLM-5V 等)。`images` 是一个字符串数组,每项可以是:
- **Data URL**(例如 `data:image/png;base64,iVBOR...`);
- **http(s) 图片链接**(由模型后端抓取,仅接受 http/https,URL 最长 8192 字符);
- **本地文件路径**(例如 `/path/to/photo.webp`,由网关读取并转成 base64)。
一次最多传 8 张。示例:
```json
{
"prompt": "请描述这张图片的内容。",
"images": ["/path/to/photo.webp", "data:image/png;base64,iVBOR..."]
}
```
校验与限制:
- 只支持 **JPEG、PNG、GIF、WebP**。不支持的媒体类型、无效的 base64、内容与声明
类型不符的图片会被直接拒绝,并返回包含图片序号和原因的错误(不会静默丢弃后发纯文本)。
- Data URL 和本地图片单张解码后默认不超过 **5 MiB**,可用环境变量
`CODEBUDDY_IMAGE_MAX_BYTES` 调整;一次请求中这两类图片解码后合计默认不超过
**16 MiB**,可用 `CODEBUDDY_IMAGE_TOTAL_MAX_BYTES` 调整。stdio 传输缓冲按总量
上限自动放大,避免大请求在传输层被截断。URL 图片由模型后端抓取,其大小限制
取决于后端,不计入网关的解码总量。
- **本地文件路径默认禁用**(防止模型生成任意路径读取本机文件)。如需启用,设置
`CODEBUDDY_ALLOW_LOCAL_IMAGE_PATHS=1`。启用后仍要求:路径不超过 4096 字符、
必须是常规文件(非目录)、扩展名属于上表、文件内容与扩展名一致(魔数校验)。
如果模型本身不支持图片,SDK 可能会拒绝图片内容,导致整个调用失败(不会自动退回
纯文本),具体取决于模型行为。
Codex 使用全局安装的命令注册:
```bash
codex mcp add codebuddy-local -- hy3-local-gateway mcp
```
使用源码注册时,请先在仓库根目录执行 `npm install`,再运行下面的命令;它会记录
当前源码的绝对路径:
```bash
codex mcp add codebuddy-local -- node "$PWD/src/server.mjs"
```
查看注册状态:
```bash
codex mcp get codebuddy-local
```
重启 Codex 后可以直接请求:
```text
先调用 list_codebuddy_models 获取模型列表,再读取相关代码并调用 ask_codebuddy,
选择 hy3 对必要代码做一次独立审查。
```
原来已经注册为 `hy3-local` 的配置不需要修改,`ask_hy3` 仍然可用。
其他 MCP Host 使用全局命令时采用相同的 stdio 配置:
```json
{
"command": "hy3-local-gateway",
"args": ["mcp"]
}
```
源码方式则将 `command` 设为 `node`,并把参数改成源码中 `src/server.mjs` 的绝对
路径。手动启动或测试:
```bash
hy3-local-gateway mcp
# 源码方式(先执行 npm install)
npm run start:mcp
npm run test:mcp
```
## 功能二:OpenAI Chat Completions 反代
启动:
```bash
hy3-local-gateway proxy
# 源码方式(先执行 npm install)
npm run start:proxy
```
默认连接信息:
```text
Base URL: http://127.0.0.1:8787/v1
API Key: local-placeholder
Default model: hy3
```
默认只监听回环地址,不校验入站 API Key。这里的 `local-placeholder` 只是满足部分
客户端的必填校验,不参与上游 CodeBuddy 认证。CC Switch 中不能留空,必须填写
`local-placeholder` 或实际配置的 `CODEBUDDY_PROXY_TOKEN`。
### 接口
- `GET /health`
- `GET /v1/models`:动态读取当前 CodeBuddy 账号可用模型并缓存 5 分钟。
- `POST /v1/chat/completions`:请求中的 `model` 会原样交给 CodeBuddy。
查看模型:
```bash
curl http://127.0.0.1:8787/v1/models \
-H 'Authorization: Bearer local-placeholder'
```
普通请求:
```bash
curl http://127.0.0.1:8787/v1/chat/completions \
-H 'Authorization: Bearer local-placeholder' \
-H 'Content-Type: application/json' \
--data-binary '{
"model": "hy3",
"messages": [
{"role": "user", "content": "只回复 hello"}
]
}'
```
流式请求:
```bash
curl -N http://127.0.0.1:8787/v1/chat/completions \
-H 'Content-Type: application/json' \
--data-binary '{
"model": "hy3",
"messages": [{"role": "user", "content": "介绍一下你自己"}],
"stream": true,
"stream_options": {"include_usage": true}
}'
```
Python OpenAI SDK:
```python
from openai import OpenAI
client = OpenAI(
api_key="local-placeholder",
base_url="http://127.0.0.1:8787/v1",
)
models = client.models.list()
print([model.id for model in models.data])
response = client.chat.completions.create(
model="hy3",
messages=[{"role": "user", "content": "你好"}],
)
print(response.choices[0].message.content)
```
### CC Switch 读取模型
[CC Switch 的供应商文档](https://github.com/farion1231/cc-switch/blob/main/docs/user-manual/zh/2-providers/2.1-add.md)
会使用配置的 API Key 请求 OpenAI 兼容的 `/v1/models`。先启动本项目的 proxy,
然后在 CC Switch 新增或编辑支持模型获取的自定义供应商:
```text
Endpoint / Base URL: http://127.0.0.1:8787/v1
API Key: local-placeholder
API Format: OpenAI Chat Completions
```
**API Key 是必填项,不能留空。** 默认启动方式下填写 `local-placeholder`;如果启动
proxy 时设置了 `CODEBUDDY_PROXY_TOKEN`,这里必须填写完全相同的值。
点击模型输入框旁的“获取模型”按钮,即可读取本机 CodeBuddy 当前账号的模型列表。
本项目暂不实现 OpenAI Responses API;给 Codex 配置供应商时应选择 Chat Completions
格式,或者使用 CC Switch 提供的本地协议转换功能。
### 反代配置
推荐使用新的 `CODEBUDDY_PROXY_*` 环境变量:
```bash
CODEBUDDY_PROXY_PORT=9000 hy3-local-gateway proxy
# 源码方式
CODEBUDDY_PROXY_PORT=9000 npm run start:proxy
```
设置本地访问令牌:
```bash
CODEBUDDY_PROXY_TOKEN='请换成随机长字符串' hy3-local-gateway proxy
# 源码方式
CODEBUDDY_PROXY_TOKEN='请换成随机长字符串' npm run start:proxy
```
设置令牌后,请求必须携带:
```text
Authorization: Bearer 请换成随机长字符串
```
配置项:
| 环境变量 | 默认值 | 说明 |
| --- | ---: | --- |
| `CODEBUDDY_PROXY_HOST` | `127.0.0.1` | 监听地址 |
| `CODEBUDDY_PROXY_PORT` | `8787` | 监听端口 |
| `CODEBUDDY_PROXY_TOKEN` | 空 | 入站 Bearer Token |
| `CODEBUDDY_PROXY_TIMEOUT_MS` | `300000` | 单次模型调用超时 |
| `CODEBUDDY_PROXY_MAX_BODY_BYTES` | `2097152` | 最大请求体大小 |
| `CODEBUDDY_QUERY_TIMEOUT_MS` | `300000` | MCP 单次模型调用超时 |
| `CODEBUDDY_MODEL_DISCOVERY_TIMEOUT_MS` | `60000` | 模型发现超时 |
| `CODEBUDDY_MODEL_CACHE_TTL_MS` | `300000` | 动态模型缓存时间 |
| `CODEBUDDY_MODELS` | 空 | 可选的逗号分隔静态模型列表 |
旧的 `HY3_PROXY_HOST`、`HY3_PROXY_PORT`、`HY3_PROXY_TOKEN`、
`HY3_PROXY_TIMEOUT_MS` 和 `HY3_PROXY_MAX_BODY_BYTES` 仍兼容;同一配置同时出现时,
`CODEBUDDY_PROXY_*` 优先。
正常情况下不要设置 `CODEBUDDY_MODELS`,网关会读取真实模型列表。只有 CodeBuddy
版本暂不支持动态发现或需要固定暴露模型时,才使用例如:
```bash
CODEBUDDY_MODELS='hy3,另一个模型ID' hy3-local-gateway proxy
# 源码方式
CODEBUDDY_MODELS='hy3,另一个模型ID' npm run start:proxy
```
如果监听地址不是回环地址,程序会强制要求配置 `CODEBUDDY_PROXY_TOKEN`。不建议将
该服务直接暴露到公网。
## 兼容范围与限制
反代实现的是 Chat Completions 的实用子集:
- 支持文本 `system`、`developer`、`user`、`assistant`、`tool` 历史消息。
- 支持普通 JSON 响应。
- 支持 SSE 响应格式,但当前是**缓冲式流式**:等待模型完成后一次发送正文,
不是逐 token 输出。
- 支持 `reasoning_effort` 的 `low`、`medium`、`high`、`xhigh`。
- 支持 `response_format: {"type": "text"}` 和 `json_object`。
- 反代接口仅支持文本消息(图片请走 MCP 入口的 `images` 参数)。
- 不支持外部 `tools` / Function Calling;这类请求会返回明确的 HTTP 400。
- 不提供 OpenAI Responses API。
因此:
- 需要模型作为独立评审或推理子 Agent 时,优先使用 MCP。
- 只需要 OpenAI 兼容文本对话和模型发现的客户端,可以使用本地反代。
- 依赖 Function Calling 的完整编码 Agent,不能把这个反代当成透明底层模型。
## 验证命令
不调用模型、不消耗 CodeBuddy 额度的离线验证:
```bash
npm test
```
使用当前 CodeBuddy 登录实际调用 Hy3:
```bash
npm run test:hy3
```
从系统临时目录验证全局安装,不依赖源码路径:
```bash
npm run test:global:mcp
npm run test:global:models
npm run test:global:chat -- --chat-model=glm-5.1
```
所有真实模型调用都会消耗当前登录 CodeBuddy 账号对应的额度。
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues