dsh-router:把 DSH 子智能體接到 sub2api 中繼

前言

在 DeepSeek Harness(DSH)裏啓動子智能體時,常見做法是在 profile 裏寫死 ANTHROPIC_BASE_URL 和 API key。內置的 Claude Code / Codex provider 在構造時就把 env 解析成靜態值;子進程啓動時還會按名字擦除帶 TOKEN、SECRET 等字樣的環境變量。若中繼側要求「每次運行按路由組換一把 relay key」,單靠改配置走不通,需要自己實現 SubagentProvider.start()。

@tokenaissance/dsh-router(維護者 tokenaissance,分類:工作流)把 DSH 的 subagent_router() 接到 sub2api:登錄一次把 grant 放進 ctx.credentials,每次開子智能體時按配置的 groupId 取 relay key(內存緩存 5 分鐘),連同 sub2api 地址注入子進程,再 spawn claude -p … 走 /v1/messages 到上游訂閱賬號池。

這是什麼

一句話:Route DeepSeek Harness subagents through sub2api — sign in once, fetch a route-group key per run, inject it into the child agent.

數據流可以概括爲:

DSH  ──subagent_router()──▶  dsh-router provider
                                  ├─ 取 access token(credentials 裏的 grant 記錄)
                                  ├─ 取路由組 key(內存緩存,5 分鐘)
                                  └─ spawn `claude -p …`
                                        env: ANTHROPIC_BASE_URL=<sub2api>
                                             ANTHROPIC_AUTH_TOKEN=<relay key>

插件以 MIT 許可發佈,npm 包名 @tokenaissance/dsh-router,當前版本 0.1.0。類型按 DSH 倉庫 0.2.2-alpha.2 編寫,與 npm 上 @deepseek-ai/dsh-* 的 0.0.1-rc.1 一代可能存在 API 差異,出樹使用時需對齊 peer 版本並實測子智能體調用。

核心功能(v0.1 已覈實)

能力 狀態
宿主側 provider(Claude Code / stream-json) ✅ v0.1
憑據落 ctx.credentials(grant 記錄)、relay key 僅內存 ✅ v0.1
環境變量令牌引導(開發用) ✅ v0.1
插件頁登錄(plugins.detail.section + @Remote) ⏳ v0.2
Codex(OPENAI_BASE_URL + OPENAI_API_KEY) ⏳ v0.2
任意 ACP agent ⏳ v0.2

安全相關行爲(README 明確說明):登錄 grant 與 relay key 分開存放;取不到 key 則拋錯、不啓動無憑證子進程;stderr 脫敏後落日誌;密碼與 token 不進 profile、不進 prompt。

sub2api 側分組有平臺類型(如 anthropic、openai 等);未綁定分組的 key 在中繼處會 403,因此配置裏的 groupId 實際是必填。Claude Code 形態需選接受 /v1/messages 的組,與 Codex 用的組可能不同。

安裝與啓用

DSH 生態是「一切皆插件」;社區目錄在 skillhub.cn,與 DeepSeek / 幻方無官方從屬關係。安裝前請自行查看源碼與許可證:插件以當前 dsh 進程權限運行。

方式一:DSH 倉庫內開發(推薦聯調)

將包放入 packages/router/dsh-router/,在 DSH 根目錄執行:

pnpm install
pnpm run build

或用腳本鏈接進 DSH 檢出:

node scripts/link-into-dsh.mjs /path/to/deepseek-harness
node scripts/link-into-dsh.mjs /path/to/deepseek-harness --link

之後:

cd /path/to/deepseek-harness && pnpm install && pnpm run build
dsh --profile web --dump-config | grep -A5 subagent-router

方式二:外部插件安裝

官方命令如下:

dsh plugin install /path/to/dsh-router

安裝後通過包內 cordis.patch.yml 插入 subagent-router provider 與 tool-subagent-router 工具。

配置

在 profile 的 cordis.patch.yml 中覆蓋 provider 配置,例如:

- id: subagent-router
  config:
    endpoint: https://sub2api.example.com
    groupId: 12
    model: claude-sonnet-4-5
    permissionMode: dontAsk
字段 默認 說明
endpoint — sub2api origin,必須
groupId — 計費/路由分組,必須;可用 GET /api/v1/groups/available 查看
providerName router ctx.subagents 上的名字
command claude 子進程可執行文件
model 繼承 固定上游模型
permissionMode dontAsk 透傳給子 CLI
keyEnv / baseUrlEnv ANTHROPIC_AUTH_TOKEN / ANTHROPIC_BASE_URL 注入位置
keyTtlMs 5 分鐘 relay key 內存緩存時長
preflight true 先 GET /v1/models 驗 key 再起子進程
bootstrapTokenEnv — 開發用:存放 access token 的環境變量名

上線前建議向 sub2api 部署方確認:GET /api/v1/settings/public 是否開啓 backend mode(會禁用非 admin 面板 API)、登錄是否強制驗證碼、賬號是否啓用 2FA(v0.1 遇驗證碼或 2FA 會報錯,可改用 token 引導)。

典型用法:三步驗證

README 建議順序不要顛倒:先驗 sub2api 與 key,再讓 provider 跑通,最後才做 v0.2 的頁面登錄。

第 1 步:scripts/verify.mjs

與 provider 運行時相同順序走一遍,並可選發真實請求:

SUB2API_ORIGIN=https://sub2api.example.com \
SUB2API_EMAIL=me@example.com SUB2API_PASSWORD=... \
SUB2API_GROUP=12 \
node scripts/verify.mjs

成功會打印應寫入 profile 的配置片段。這步不通,後續配置無效。

第 2 步:bootstrapTokenEnv 跑 subagent_router

export SUB2API_ACCESS_TOKEN=...
- id: subagent-router
  config:
    endpoint: https://sub2api.example.com
    groupId: 12
    bootstrapTokenEnv: SUB2API_ACCESS_TOKEN

SUB2API_ACCESS_TOKEN 可從 verify.mjs --json 輸出取得。

第 3 步

v0.2 計劃把第 2 步中的 token 引導搬到插件詳情頁登錄流程。

適用場景與注意

適合:已在 sub2api 上劃分路由組、希望 DSH 主會話走一套邏輯、子智能體(Claude Code)走中繼並按組計費/限流的團隊或個人。

注意:

  • v0.1 僅 Claude Code 的 print/stream-json;Codex 與任意 ACP agent 在路線圖 v0.2。
  • Node 要求 >=24.9.0;peer 依賴含 @deepseek-ai/cordis、dsh-credentials、dsh-subagent、dsh-subprocess。
  • 與 npm 版 DSH 混用時請釘 peer 並在 pnpm run build 後實測一次 subagent_router。

結尾

dsh-router 解決的是「動態 relay key + sub2api 中繼」與 DSH 子進程環境模型之間的錯位:用自定義 provider 在每次 start() 取 key 並注入,而不是在 profile 裏寫死密鑰。

羽毛球分组比赛记分
小程序二维码

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

小夜