前言¶
DeepSeek Harness(DSH)采用「一切皆插件」的架构,一个宿主可以挂载多个 provider 插件,各自负责与上游对话。在本地开发或集成时,通常会面临一个问题:如何把这些分散的模型入口,统一成一套固定的 OpenAI 兼容 API,方便外部项目调用、脚本测试或直接接入前端。
DSH OpenAI Gateway 正是为此设计的一个 bundle 插件。它在本地回环上监听一个固定端口,把所有已注册 provider 的模型按 provider/model 的形式暴露为 OpenAI 兼容接口。同时,它在 DSH 左侧边栏加入一个「模型网关」页面,用于查看地址与密钥、改端口、换密钥以及逐个复制模型 ID。
它是什么¶
DSH OpenAI Gateway 是一个独立的 DSH bundle 插件,维护者为 pigman18。它本身不做任何按厂商重写的转发逻辑,而是把 OpenAI 形状的请求转发给宿主的 ctx.llm 服务,由各自 provider 的 adapter 原地处理。因此,任何把 provider 注册进 ctx.llm 的插件都会自动出现在网关里,无需额外适配。
核心功能¶
- 一个入口,全部模型:
/v1/models返回所有 provider 的所有模型,ID 为provider/model。例如workbuddy/deepseek-v4.1-flash、opencode2dsh/deepseek-v4.1-flash-free、local/qwen3.5:4b。当某个裸模型名只被一个 provider 提供时也接受;多个 provider 撞名时明确报错并列出候选。 - 端口固化:默认监听
127.0.0.1:8787,与 DSH 界面端口无关。若端口被占用,网关会自动落到系统分配的随机端口继续服务,页面会标明「随机(8787 被占用)」。 - 密钥固化:首次启动生成
sk-dsh-…并写入$DSH_HOME/openai-gateway/settings.json(权限 0600),重启后不变。页面上的「生成」按钮可换新(两步确认,旧钥立即失效)。 - 侧边栏模型网关页:打开即见接口地址、密钥(打码/显示/复制)、端口(可直接改,回车生效),以及按 provider 折叠分组的完整模型清单。每个模型 ID 一个复制按钮,每组可整组复制,也可一键复制全部。
- 流式与非流式都支持:
"stream": true返回标准 SSE(data: …逐帧,[DONE]收尾),非流式返回完整chat.completion。 - 工具调用:
tools正常转发,结果以tool_calls返回,arguments的分片会被拼装完整,finish_reason为tool_calls;tool消息按其tool_call_id回到对应调用。 - 图片与文件:支持
image_url/input_image与file/input_file。图片由网关抓取并存进宿主的附件库(ctx.attachments),模型拿到的是持久化的图片块。文件中能当文本读的直接内联成文本([attached file: name]+ 内容,2 MiB 以内、UTF-8 且无 NUL 字节),其余存进附件库并作为file块交给模型。 - 推理内容与用量:模型产出思考时以
reasoning_content单独返回;usage映射为prompt_tokens/completion_tokens/total_tokens,有 reasoning / cache 细分时一并带上。 reasoning_effort按目标模型真实档位映射:映射到该模型自己声明的档位集合;不支持的档位降到最接近的或直接丢弃,不会因此拒掉整个请求。- 对
stop被拒的上游自动降级:某些 adapter 不接受stop时会先返回UNSUPPORTED_OPTION;网关识别后去掉stop重试一次,而不是把请求判死。 - 浏览器直连:
/v1/*自带 CORS 预检(OPTIONS无需鉴权即答 204),前端项目可以把它当普通 OpenAI 端点用。 - 只绑回环:仅监听
127.0.0.1,不是网络服务。页面用的控制接口还额外要求同源、POST与 JSON Content-Type。
安装与启用¶
从 GitHub 安装:
dsh plugin --profile <profile> add github:pigman18/dsh-openai-gateway
开发时直接链本地目录:
dsh plugin --profile <profile> add link:/path/to/dsh-openai-gateway
安装或更新后重启 DSH:宿主侧插件在启动时装载,浏览器前半段也只在启动时装配。
典型用法¶
- 侧边栏点「模型网关」,页面顶部显示接口地址(默认
http://127.0.0.1:8787/v1)与 API Key。 - 把它当普通 OpenAI 端点填进任意客户端:
curl http://127.0.0.1:8787/v1/chat/completions \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"model":"workbuddy/deepseek-v4.1-flash","messages":[{"role":"user","content":"hi"}]}'
- 模型名直接从页面复制,或在
/v1/models里查。 - 图片照 OpenAI 的写法内联即可(
data:URL 或http(s)图片地址都行):
{
"model": "workbuddy/glm-5.3-flash",
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "这张图里是什么?" },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,iVBORw0KGgo…" } }
]
}
]
}
文件同理,用 {"type":"file","file":{"filename":"notes.txt","file_data":"data:text/plain;base64,…"}}。
配置¶
bundle 行上可选配置(键名与默认值):
| 键 | 默认 | 含义 |
|---|---|---|
enabled |
true |
false 时插件空转:页面显示未启用,/v1/* 返回 503 |
port |
已存值 / 8787 |
首选监听端口,显式值优先于已存值 |
apiKey |
已存值 | 固定密钥,优先于已存值 |
bodyLimitBytes |
8388608 |
请求体上限 |
catalogTtlMs |
60000 |
/v1/models 缓存时长 |
retryMaxRetries |
5 |
瞬时失败(RATE_LIMIT/SERVER/TIMEOUT/TRANSPORT/EMPTY_RESPONSE)的重试次数,与宿主 llm-retry 默认一致 |
retryInitialDelayMs |
500 |
退避起始间隔 |
retryMaxDelayMs |
10000 |
退避上限;上游给出的重置点超过它就按「请稍后再来」直接失败 |
silentFlushMs |
10000 |
流式响应静默多久后提交响应头并开始保活 |
keepAliveMs |
15000 |
保活 : keep-alive 注释的间隔 |
maxInputTokens |
0(关) |
估算输入超过它就回 413 CONTEXT_WINDOW_EXCEEDED;0 时改用模型声明的 contextWindow(provider 没声明就不拦) |
maxMessages |
0(关) |
历史超过这么多条就丢弃最早的若干条,且保证保留部分从 user 开始 |
适用场景与注意¶
适合在本地开发环境、脚本测试或需要统一 OpenAI 兼容接口的场景中使用。插件以当前 dsh 进程权限运行,安装前应检查源码与许可证。
短结尾¶
DSH OpenAI Gateway 把 DSH 里分散的 provider 模型统一成一个固定的 OpenAI 兼容端点,端口与密钥持久化,重启不变。左侧边栏提供可视化的模型网关页面,方便查看地址、密钥与模型 ID。
- 目录页:https://www.skillhub.cn/plugins/pigman18/dsh-openai-gateway
- GitHub:https://github.com/pigman18/dsh-openai-gateway