dsh-router-core 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CARVIN
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,4 +1,18 @@
1
- # dsh-router
1
+ <h1 align="center">dsh-router</h1>
2
+
3
+ <p align="center">DeepSeek Harness 的 OpenAI 兼容路由插件</p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/dsh-router-core"><img src="https://img.shields.io/npm/v/dsh-router-core?style=flat-square&logo=npm&label=npm" alt="npm version"></a>
7
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-10b981?style=flat-square" alt="MIT license"></a>
8
+ </p>
9
+
10
+ <p align="center">
11
+ <a href="#快速安装">快速安装</a> ·
12
+ <a href="#面板设置--路由">面板</a> ·
13
+ <a href="#api-端点openai-兼容3080v1">API 端点</a> ·
14
+ <a href="docs/suppliers.md">供应商开发</a>
15
+ </p>
2
16
 
3
17
  **插件版的 9router** —— 不是另开一个网关服务,而是直接作为 DSH 插件嵌进 DSH web,
4
18
  在 `http://localhost:3080/v1` 上原生暴露 OpenAI 兼容端点,把请求路由到内部供应商。
@@ -7,30 +21,44 @@
7
21
 
8
22
  ![设置 → 路由 面板:概览(用量看板)、供应商、组合、端点与密钥](docs/screenshot.png)
9
23
 
10
- ## 为什么更优雅
11
-
12
- - **零额外进程**:dsh-router 就是 DSH 插件,随 `dsh web` 启停,天然同源
13
- (`/router/api/*` 无 CORS、面板嵌在设置里),不像 9router 要独立跑一个
14
- Next.js 服务再对接;
15
- - **供应商即插即拔**:内置供应商(如 opencode / openrouter / nvidia)随插件分发;
16
- 更多供应商 = 装一个 DSH 插件(`dsh-router-*`)经 cordis service
17
- `router.suppliers` 注册,面板自动出现、热加载/卸载;也可以放一个自定义
18
- js 文件到 `~/.dsh/profiles/web/suppliers/` 就注册一个新供应商——
19
- 无需改核心代码、无需重编译;
20
- - **模型不内置**:供应商只实现差异化能力(列模型/调上游/登录),模型拉取与
21
- 缓存由核心统一管,不写死、不过时;
22
- - **策略只写一次**:组合回退、账号池(选号/冷却/禁用/连续错误累计)、响应写入、
23
- 凭证存储、模型管理都由核心提供。供应商 js 只对**单个账号**调一次上游并报告
24
- 成败,不自己遍历账号、不维护冷却表——否则每个插件都会长出一份互相不一致的
25
- 实现,而核心也就无从判断「该不该换号」;
26
- - **凭证 SQLite 单库**:`auths/credentials.sqlite`,供应商凭证不透明 blob,
27
- 核心统一生命周期,干净可备份;
28
- - **复用 9router 思路**:面板布局、组合 fallback、连接池/账号池、API key
29
- 管理都贴近 9router,但按 DSH「一切皆插件」的方式重组得更轻。
24
+ ## 快速安装
25
+
26
+ 需要支持 `dsh plugin` profile 插件机制的 DeepSeek Harness、Node.js `>= 20`,以及 `web` profile。
27
+
28
+ ```bash
29
+ dsh plugin --profile web add dsh-router-core
30
+ ```
31
+
32
+ 然后**重启 `dsh web`**。打开设置面板,左侧导航「模型」下面会出现 **路由**。
33
+
34
+ > 更多供应商:DSH 插件形态的供应商各自发 npm 包,同样
35
+ > `dsh plugin --profile web add <包名>` 即可;供应商接入与开发见
36
+ > [`docs/suppliers.md`](docs/suppliers.md)。
37
+ >
38
+ > 本地开发版:不用 npm,直接 `dependencies` 加
39
+ > `"dsh-router-core": "link:/path/to/dsh-router"` 指向本地仓库。
30
40
 
41
+ ## 它解决什么问题
42
+
43
+ | 能力 | 说明 |
44
+ |---|---|
45
+ | 零额外进程 | 就是 DSH 插件,随 `dsh web` 启停,天然同源(`/router/api/*` 无 CORS、面板嵌在设置里)。 |
46
+ | 供应商即插即拔 | 内置供应商随插件分发;更多供应商 = 装一个 DSH 插件(`dsh-router-*`)或放一个 js 文件到 `~/.dsh/profiles/web/suppliers/`。 |
47
+ | 模型不内置 | 供应商只实现差异化能力,模型拉取与缓存由核心统一管,不写死、不过时。 |
48
+ | 策略只写一次 | 组合回退、账号池(选号/冷却/禁用/连续错误累计)、响应写入、凭证存储、模型管理都由核心提供。供应商 js 只对**单个账号**调一次上游并报告成败,不自己遍历账号、不维护冷却表——否则每个插件都会长出一份互相不一致的实现,而核心也就无从判断「该不该换号」。 |
49
+ | 凭证单库 | `auths/credentials.sqlite`,供应商凭证不透明 blob,核心统一生命周期,干净可备份。 |
50
+ | 组合即模型 | 建好的组合自动带出为 DSH 模型目录里的 `router` provider 选项,设置 → 模型直接选组合名即可。 |
51
+ | 用量可观测 | 面板概览看板:周期切换、汇总卡、趋势折线、Top 榜、最近请求。 |
52
+
53
+ > 面板布局、组合 fallback、连接池/账号池、API key 管理都贴近
54
+ > [9router](https://github.com/decolua/9router),但按 DSH「一切皆插件」的方式
55
+ > 重组得更轻。
56
+ >
31
57
  > 供应商开发与接入规范见 [`docs/suppliers.md`](docs/suppliers.md)
32
58
  > (契约 / 加载顺序 / 模型统一策略 / 内置供应商参考实现)。
33
59
 
60
+ ## 面板(设置 → 路由)
61
+
34
62
  面板挂在 **设置 → 路由**(官方 `settings.section` 座位,排在「模型」下面):
35
63
 
36
64
  - **概览** — 用量看板(默认页):
@@ -162,32 +190,14 @@ curl -X POST http://localhost:3080/v1/chat/completions \
162
190
  | `TW2A_STATE_FILE` | `data/state.json` | 状态持久化(同目录放 keys.json / combos.json / supplier-config.json) |
163
191
  | `TW2A_API_KEY` | 空 | /v1 Bearer 鉴权(与库内 key 等效) |
164
192
 
165
- ## 构建
166
-
167
- ```bash
168
- pnpm install
169
- pnpm build # lib/index.js(host) + lib/client.js / lib/client-registry.js(browser)
170
- pnpm typecheck
171
- ```
172
-
173
- ## 安装(DSH)
174
-
175
- 用 dsh CLI 装到 profile(web 是 DSH 插件宿主):
176
-
177
- ```bash
178
- dsh plugin --profile web add dsh-router-core
179
- ```
193
+ ## 与 DSH 的边界
180
194
 
181
- 该命令会在 profile 里 `pnpm add`,并自动把 `dsh-router-core` 加入
182
- `dsh.profile.bundles`(包声明了 `dsh.bundle.patch`,即 `cordis.patch.yml`)。
183
-
184
- 然后**重启 `dsh web`**。打开设置面板,左侧导航「模型」下面会出现 **路由**。
185
-
186
- > 更多供应商:DSH 插件形态的供应商各自发 npm 包,同样 `dsh plugin --profile web add <包名>`
187
- > 即可;供应商接入与开发见 [`docs/suppliers.md`](docs/suppliers.md)。
188
- >
189
- > 本地开发版:不用 npm,直接 `dependencies` 加
190
- > `"dsh-router-core": "link:/path/to/dsh-router"` 指向本地仓库。
195
+ - dsh-router 复用 DSH 的 Web Server 与设置面板座位,不启动第二个应用或代理系统。
196
+ - 供应商 js 不改 DSH 的 prompt、工具 schema 或权限;它只负责「把上游协议翻译成
197
+ OpenAI 形态」,路由/回退/存储归核心。
198
+ - 数据分两处:`data/` 下的状态与用量 JSON(删了只是没统计了),以及
199
+ `auths/credentials.sqlite`(删了要重新登录所有供应商)。
200
+ - 内置 patch 仅支持 DSH 的 `web` profile。
191
201
 
192
202
  ## 前提
193
203
 
@@ -195,6 +205,18 @@ dsh plugin --profile web add dsh-router-core
195
205
  - 供应商接入与开发见 [`docs/suppliers.md`](docs/suppliers.md);
196
206
  - 重启 DSH 后 `/v1/*` 即生效;面板管理账号、模型与密钥。
197
207
 
208
+ ## 开发
209
+
210
+ ```bash
211
+ pnpm install
212
+ pnpm build # lib/index.js(host) + lib/client.js / lib/client-registry.js(browser)
213
+ pnpm typecheck
214
+ pnpm test # node --test "src/**/*.test.ts"
215
+ ```
216
+
217
+ 需要一个供应商最小实现作参考时,看 [`examples/suppliers/echo.js`](examples/suppliers/echo.js);
218
+ 完整契约、加载顺序与模型策略见 [`docs/suppliers.md`](docs/suppliers.md)。
219
+
198
220
  ## 致谢
199
221
 
200
222
  感谢以下项目给的灵感:
@@ -202,3 +224,7 @@ dsh plugin --profile web add dsh-router-core
202
224
  - [decolua/9router](https://github.com/decolua/9router) —— 本地 AI 路由网关,面板/组合/连接池/凭证等思路的来源;
203
225
  - [deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) —— DSH「一切皆插件」的宿主框架;
204
226
  - [omdsh-dev/dsh-mnemon](https://github.com/omdsh-dev/dsh-mnemon) —— DSH 插件形态与侧边栏入口的参考。
227
+
228
+ ## 许可证
229
+
230
+ [MIT](LICENSE)
Binary file
@@ -607,7 +607,10 @@ window.__ModuleLoader__.load({
607
607
  children: supplier.icon !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
608
608
  className: "dshr-providerImg",
609
609
  src: supplier.icon,
610
- alt: ""
610
+ alt: "",
611
+ onError: (e) => {
612
+ e.currentTarget.style.display = "none";
613
+ }
611
614
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon$4, {
612
615
  d: I$4.link,
613
616
  size: 22
@@ -3376,7 +3379,10 @@ window.__ModuleLoader__.load({
3376
3379
  children: [supplier.icon !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
3377
3380
  className: "dshr-supplierIcon",
3378
3381
  src: supplier.icon,
3379
- alt: ""
3382
+ alt: "",
3383
+ onError: (e) => {
3384
+ e.currentTarget.style.display = "none";
3385
+ }
3380
3386
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3381
3387
  className: "dshr-supplierName",
3382
3388
  children: supplier.name
package/lib/client.js CHANGED
@@ -607,7 +607,10 @@ window.__ModuleLoader__.load({
607
607
  children: supplier.icon !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
608
608
  className: "dshr-providerImg",
609
609
  src: supplier.icon,
610
- alt: ""
610
+ alt: "",
611
+ onError: (e) => {
612
+ e.currentTarget.style.display = "none";
613
+ }
611
614
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon$4, {
612
615
  d: I$4.link,
613
616
  size: 22
@@ -3376,7 +3379,10 @@ window.__ModuleLoader__.load({
3376
3379
  children: [supplier.icon !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
3377
3380
  className: "dshr-supplierIcon",
3378
3381
  src: supplier.icon,
3379
- alt: ""
3382
+ alt: "",
3383
+ onError: (e) => {
3384
+ e.currentTarget.style.display = "none";
3385
+ }
3380
3386
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3381
3387
  className: "dshr-supplierName",
3382
3388
  children: supplier.name
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-router-core",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "DSH plugin: a simplified 9router (AI routing gateway). Adds a 路由系统 (Routing System) sidebar entry beside 记忆系统; the panel shows suppliers, account pool, combos, and endpoint/API keys.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -103,7 +103,15 @@ export function RouterView({ onBack }: RouterViewProps): JSX.Element {
103
103
  <section key={supplier.id} className="dshr-supplierCard" onClick={() => setDetailSupplier(supplier)}>
104
104
  <div className="dshr-supplierRow">
105
105
  {supplier.icon !== undefined && (
106
- <img className="dshr-supplierIcon" src={supplier.icon} alt="" />
106
+ <img
107
+ className="dshr-supplierIcon"
108
+ src={supplier.icon}
109
+ alt=""
110
+ // 加载失败就藏起来(别留碎图)。图标不是关键信息,
111
+ // 旁边有供应商名字。历史上的坑:icon 曾是
112
+ // http://localhost:20128/... 这种外链,9router 没跑就全是坏图。
113
+ onError={(e) => { e.currentTarget.style.display = 'none' }}
114
+ />
107
115
  )}
108
116
  <div className="dshr-supplierName">{supplier.name}</div>
109
117
  </div>
@@ -560,7 +560,15 @@ export function SupplierDetail({ supplier, accounts, statusLoading, onBack, onRe
560
560
  <div className="dshr-providerTitleRow">
561
561
  <div className="dshr-providerIcon">
562
562
  {supplier.icon !== undefined
563
- ? <img className="dshr-providerImg" src={supplier.icon} alt="" />
563
+ ? (
564
+ <img
565
+ className="dshr-providerImg"
566
+ src={supplier.icon}
567
+ alt=""
568
+ // 同上:失败就藏,露出备用图标位置(不显示碎图)
569
+ onError={(e) => { e.currentTarget.style.display = 'none' }}
570
+ />
571
+ )
564
572
  : <Icon d={I.link} size={22} />}
565
573
  </div>
566
574
  <div className="dshr-providerMeta">
@@ -22,8 +22,14 @@ import type { SupplierEnv, SupplierModule } from '../contract.ts'
22
22
  export const id = 'nvidia'
23
23
  export const name = 'NVIDIA NIM'
24
24
  export const priority = 20 // 同 9Router:免费直连(opencode=0)之后
25
- /** 面板图标(9router 提供的 logo)。 */
26
- export const icon = 'http://localhost:20128/providers/nvidia.png'
25
+ /**
26
+ * 面板图标(NVIDIA 官方 logo,128×128 PNG,base64 内联)。
27
+ *
28
+ * **必须内联,不能放网络 URL**:之前是 `http://localhost:20128/...`(9router
29
+ * 的端口),9router 没跑时就是一张坏图 —— 面板图标不该依赖另一个服务活着,
30
+ * 更不该依赖特定端口。跟 opencode / openrouter / traework 的做法保持一致。
31
+ */
32
+ export const icon = 'data:image/png;base64,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'
27
33
 
28
34
  const BASE = 'https://integrate.api.nvidia.com/v1'
29
35
  const MODELS_URL = `${BASE}/models`