dsh-openai-gateway
Expose DeepSeek Harness (dsh) as an OpenAI-compatible API server — /v1/chat/completions + /v1/models, backed by real agent sessions with tools and workspaces. 把 DeepSeek Harness 暴露为 OpenAI 兼容 API 服务端。
- Stars
- 1
- Language
- JavaScript
- Created
- Aug 23, 2026
- Updated
- Aug 23, 2026
Introduction
dsh-openai-gateway
Expose DeepSeek Harness (dsh) as an OpenAI-compatible API server — POST /v1/chat/completions (stream + non-stream) and GET /v1/models. Every API call is backed by a real agent session with tools and a workspace, so any OpenAI client (SDK, Raycast, scripts, IDE plugins…) can drive your agent by just filling in a base URL and an API key.
把 DeepSeek Harness 暴露为 OpenAI 兼容 API 服务端:每次 API 调用背后是带工具、带工作区的真实 Agent 会话。
工作原理
OpenAI 客户端 ──(可选: 反向代理 /v1)──▶ 插件独立 HTTP 监听 ──▶ dsh Agent 会话
(自带 Bearer 鉴权) (模型+工具+工作区)
dsh 共享 Web 服务器的路由会被登录门插件(如 @xgone/dsh-remote)整体包装,纯 Bearer 的 API 客户端拿不到浏览器会话。因此本插件自建独立监听、鉴权完全自理——API 流量与 Web UI 的登录门互不干扰,可分别暴露。
安装(完整流程)
1. 安装插件
dsh plugin --profile web add github:backrooms-yrc/dsh-openai-gateway#v0.1.1
2. 重启 dsh web
首次新增包需要重启一次:
# 先停掉正在运行的 dsh web,再以你的原参数启动,例如:
dsh web --host 127.0.0.1 --port 41539 --no-open
3. 找到你的端口和 API key
端口:默认 127.0.0.1:41540(这只是本插件的默认值,与 dsh 本身的端口无关,完全可以改)。权威查询方式——监听成功后插件会把实际地址写进状态文件,port: 0(随机端口)场景同样适用:
cat $DSH_HOME/openai-gateway/state.json
# {"host": "127.0.0.1", "port": 41540, "pid": 12345, "startedAt": "..."}
API key:未配置时首次启动自动生成一个,0600 权限落盘:
cat $DSH_HOME/openai-gateway/api-keys.json
# {"keys": ["sk-dsh-..."]}
自检:
curl http://127.0.0.1:41540/healthz
# {"ok":true,"service":"dsh-openai-gateway"}
4. 发起第一次调用
KEY=$(python3 -c "import json;print(json.load(open('$HOME/.dsh/openai-gateway/api-keys.json'))['keys'][0])")
PORT=$(python3 -c "import json;print(json.load(open('$HOME/.dsh/openai-gateway/state.json'))['port'])")
curl http://127.0.0.1:$PORT/v1/chat/completions \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"model":"default","messages":[{"role":"user","content":"你好"}]}'
DSH_HOME默认是~/.dsh;用环境变量DSH_HOME自定义过的以实际为准。
端口说明(重要)
41540是本插件的默认端口,不是 dsh 官方约定。它被占用时插件不会启动 dsh 崩溃,但会记录FATAL: port ... already in use日志,且state.json不会更新、/healthz不通——此时换一个端口即可;- 修改端口(在 profile 的
cordis.patch.yml或$DSH_HOME/cordis.patch.yml中):
- id: openai-gateway
config:
port: 41540 # 改成任意空闲端口;0 = 让操作系统随机分配(实际值见 state.json)
改完重启 dsh web 生效。
会话模型
- 无状态(默认):
messages全量拼为一条 prompt,回合结束即销毁会话,零残留。任何 OpenAI 客户端即插即用。 - 粘性会话(扩展):首次请求带
X-DSH-Session: new头(或 body 扩展字段"dsh_session": "new")创建常驻会话,响应携带dsh_session_id;后续请求带该 id(头或字段均可)复用同一 Agent——只发最新一条 user 消息,工作区与上下文跨请求连续(活体复用,dsh 重启后自动 resume 持久化会话)。
# 第一轮:创建会话并给它一个暗号
curl -X POST http://127.0.0.1:$PORT/v1/chat/completions \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-H "X-DSH-Session: new" \
-d '{"model":"default","messages":[{"role":"user","content":"我的暗号是蓝鲸,记住"}]}'
# → 响应里的 dsh_session_id 记下来
# 第二轮:只发新消息,Agent 记得上一轮
curl -X POST http://127.0.0.1:$PORT/v1/chat/completions \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-H "X-DSH-Session: openai-xxxxxxxx-..." \
-d '{"model":"default","messages":[{"role":"user","content":"我的暗号是什么?"}]}'
客户端接入
任何 OpenAI SDK 只需改 base_url。Python 示例:
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:41540/v1", # 你的端口见 state.json;远程部署换成反代地址
api_key="sk-dsh-...", # 见 api-keys.json
)
resp = client.chat.completions.create(
model="default", # "default" = 跟随 dsh 当前默认模型
messages=[{"role": "user", "content": "你好"}],
)
print(resp.choices[0].message.content)
# 流式 + 推理模型的思考增量(delta.reasoning_content,DeepSeek 风格)
stream = client.chat.completions.create(
model="default", stream=True,
messages=[{"role": "user", "content": "解释一下 SSE"}],
)
for chunk in stream:
delta = chunk.choices[0].delta
if getattr(delta, "reasoning_content", None):
print("[思考]", delta.reasoning_content, end="", flush=True)
if delta.content:
print(delta.content, end="", flush=True)
模型名规则:"default" 跟随 dsh 默认模型;"provider/model" 精确路由(如 deepseek-official/deepseek-v4-flash,完整列表 GET /v1/models);裸模型名会对照 dsh 目录自动匹配供应商。
配置参考
patch 层条目(- id: openai-gateway + config:),未写的键用默认值:
| 键 | 默认 | 说明 |
|---|---|---|
enabled | true | 总开关 |
host | 127.0.0.1 | 只绑回环最安全,对外走反代 |
port | 41540 | 端口;0 = 随机(实际值写入 state.json) |
apiKeys | [] | 留空自动生成并落盘(0600);填数组则只用你给的 |
sessionMode | both | both / stateless(后者拒绝粘性会话请求) |
maxSessions | 16 | 粘性会话簿记上限(LRU) |
timeoutSeconds | 300 | 单轮超时:取消 Agent 并返回 504 |
defaultModel | '' | 请求未指定 model 时的兜底;空 = dsh 默认 |
workspace.cwd | '' | Agent 工作目录;空 = $DSH_HOME/openai-gateway/workspace |
端点
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /v1/chat/completions | 流式/非流式;max_tokens 映射单请求输出上限 |
| GET | /v1/models、/v1/models/:id | 从 dsh 模型目录读取,模型名为 provider/model |
| GET | /healthz | 免鉴权探活 |
响应扩展字段(不破坏标准客户端):dsh_session_id、dsh_tool_calls。工具调用在 SSE 中以注释帧 : dsh tool-call <name> 呈现。
反向代理(nginx,SSE 注意事项)
# 在你的 dsh 站点 server 块里,加在现有 location / 之前(更长前缀优先匹配)
location ^~ /v1/ {
proxy_pass http://127.0.0.1:41540; # 插件端口,以 state.json 为准
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off; # SSE 必须关缓冲,否则流式会被攒包
proxy_read_timeout 3600s; # Agent 单轮可能较长
proxy_send_timeout 3600s;
}
之后客户端用 https://你的域名/v1 作为 base URL,TLS 由 nginx 负责。
故障排查
| 症状 | 原因与处理 |
|---|---|
连接被拒 / /healthz 不通 | 插件没起来:查 state.json 是否有 startedAt;端口被占会记 FATAL: port ... in use,换 port 后重启 |
401 invalid_api_key | key 不对——对照 api-keys.json,或确认配置的 apiKeys 生效(重启) |
404 model_not_found | 模型名写错;GET /v1/models 看完整列表,或直接用 default |
粘性会话 404 session_not_found | 会话 id 不对/已被回收,或 sessionMode: stateless;用 X-DSH-Session: new 重新创建 |
504 timeout | 单轮超过 timeoutSeconds(默认 300s)被取消;调大配置或精简任务 |
| 流式响应一次性全出 | 反代没关缓冲——nginx 加 proxy_buffering off |
已知限制(v0.1)
tool_calls不投影为 OpenAI 工具调用帧(只计数 + SSE 注释);请求体的tools/tool_choice忽略- 无每 key 配额/限速
maxSessions为簿记上限,被逐出簿记的旧 Agent 由 dsh 注册表按自身策略回收
本地开发
git clone https://github.com/backrooms-yrc/dsh-openai-gateway
dsh plugin --profile web add /path/to/dsh-openai-gateway
link 安装不安装 peer 依赖,需自行保证 @deepseek-ai/dsh-agent / dsh-llm / dsh-session / dsh-home-paths / schemastery 可解析(可在插件目录建 node_modules/@deepseek-ai/ 符号链接指向 dsh CLI 的内部副本)。纯 JS 无构建步骤。针对 dsh 0.1.1-rc.2 实现并测试(开发者预览,暂无兼容承诺)。
License
MIT