DSH OpenAI Gateway:把 DSH 里的所有模型统一成 OpenAI 接口

前言

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:宿主侧插件在启动时装载,浏览器前半段也只在启动时装配。

典型用法

  1. 侧边栏点「模型网关」,页面顶部显示接口地址(默认 http://127.0.0.1:8787/v1)与 API Key。
  2. 把它当普通 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"}]}'
  1. 模型名直接从页面复制,或在 /v1/models 里查。
  2. 图片照 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
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜