dsh-router-core 0.1.0

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.
Files changed (42) hide show
  1. package/README.md +151 -0
  2. package/cordis.patch.yml +9 -0
  3. package/lib/client-registry.js +3006 -0
  4. package/lib/client.js +3006 -0
  5. package/lib/index.js +1756 -0
  6. package/lib/types/credential-store.d.ts +15 -0
  7. package/lib/types/index.d.ts +6 -0
  8. package/lib/types/keys.d.ts +39 -0
  9. package/lib/types/llm/adapter.d.ts +31 -0
  10. package/lib/types/router/index.d.ts +73 -0
  11. package/lib/types/router/types.d.ts +80 -0
  12. package/lib/types/shared.d.ts +138 -0
  13. package/lib/types/supplier-config.d.ts +28 -0
  14. package/lib/types/suppliers/contract.d.ts +98 -0
  15. package/lib/types/suppliers/loader.d.ts +41 -0
  16. package/lib/types/suppliers/registry.d.ts +33 -0
  17. package/package.json +86 -0
  18. package/src/client/CombosTab.tsx +458 -0
  19. package/src/client/EndpointTab.tsx +360 -0
  20. package/src/client/Modal.tsx +46 -0
  21. package/src/client/RouterView.tsx +186 -0
  22. package/src/client/SupplierDetail.tsx +943 -0
  23. package/src/client/index.tsx +18 -0
  24. package/src/client/router.css +2096 -0
  25. package/src/client/sidebar-entry.ts +167 -0
  26. package/src/client/workspace-controller.ts +26 -0
  27. package/src/client/workspace-mount.tsx +117 -0
  28. package/src/credential-store.ts +64 -0
  29. package/src/index.ts +468 -0
  30. package/src/keys.ts +143 -0
  31. package/src/llm/adapter.ts +273 -0
  32. package/src/router/index.ts +273 -0
  33. package/src/router/types.ts +85 -0
  34. package/src/shared.ts +152 -0
  35. package/src/supplier-config.ts +144 -0
  36. package/src/suppliers/contract.ts +73 -0
  37. package/src/suppliers/loader.ts +191 -0
  38. package/src/suppliers/nvidia/plugin.ts +268 -0
  39. package/src/suppliers/opencode/plugin.ts +200 -0
  40. package/src/suppliers/openrouter/plugin.ts +282 -0
  41. package/src/suppliers/registry.ts +365 -0
  42. package/src/types.d.ts +45 -0
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # dsh-router
2
+
3
+ **插件版的 9router** —— 不是另开一个网关服务,而是直接作为 DSH 插件嵌进
4
+ DSH web(和「记忆系统」同侧边栏),在 `http://localhost:3080/v1` 上原生暴露
5
+ OpenAI 兼容端点,把请求路由到内部供应商。装好即用,不用多开一个 9router、
6
+ 不用维护第二个端口、不用在网关和 DSH 之间搬配置。
7
+
8
+ ## 为什么更优雅
9
+
10
+ - **零额外进程**:dsh-router 就是 DSH 插件,随 `dsh web` 启停,天然同源
11
+ (`/router/api/*` 无 CORS、面板内嵌侧边栏),不像 9router 要独立跑一个
12
+ Next.js 服务再对接;
13
+ - **供应商即插即拔**:内置供应商(如 opencode / openrouter / nvidia)随插件分发;
14
+ 更多供应商 = 装一个 DSH 插件(`dsh-router-*`)经 cordis service
15
+ `router.suppliers` 注册,面板自动出现、热加载/卸载;也可以放一个自定义
16
+ js 文件到 `~/.dsh/profiles/web/suppliers/` 就注册一个新供应商——
17
+ 无需改核心代码、无需重编译;
18
+ - **模型不内置**:供应商只实现差异化能力(列模型/调上游/登录),模型拉取与
19
+ 缓存由核心统一管,不写死、不过时;
20
+ - **凭证 SQLite 单库**:`auths/credentials.sqlite`,供应商凭证不透明 blob,
21
+ 核心统一生命周期,干净可备份;
22
+ - **复用 9router 思路**:面板布局、组合 fallback、连接池/账号池、API key
23
+ 管理都贴近 9router,但按 DSH「一切皆插件」的方式重组得更轻。
24
+
25
+ > 供应商开发与接入规范见 [`docs/suppliers.md`](docs/suppliers.md)
26
+ > (契约 / 加载顺序 / 模型统一策略 / 内置供应商参考实现)。
27
+
28
+ 左侧边栏「记忆系统」上方有 **路由系统** 入口,点击打开中心栏面板:
29
+
30
+ - **返回会话** — 左侧按钮,关闭面板回到聊天;
31
+ - **供应商** — 供应商卡片(内置 / 插件分组),点击进入详情:
32
+ - **链接池** — 账号列表(冷却/禁用/健康数),支持删除;
33
+ - **加链接** — 按供应商能力弹出不同流程:URL 登录(生成链接 → 浏览器登录 → 回调)、
34
+ API key 弹窗(填名字 + key)、轮询登录(登录后自动取凭证);
35
+ - **可用模型** — 模型列表,逐个启用/禁用 + 自定义模型(通用能力,持久化到
36
+ `data/supplier-config.json`,`/v1/models` 与 chat 只接受启用的模型);
37
+ - **组合** — fallback 链(免费优先),可自定义;
38
+ - **端点与密钥** — 端点核心(无隧道/Tailscale):
39
+ - API 端点 URL(`http://localhost:3080/v1`,可复制);
40
+ - 鉴权设置 `requireApiKey` 开关;
41
+ - API Keys 管理:创建 / 启用切换 / 显示 / 复制 / 删除(持久化到 `data/keys.json`)。
42
+
43
+ ## API 端点(OpenAI 兼容,`:3080/v1`)
44
+
45
+ ```bash
46
+ # 模型列表
47
+ curl http://localhost:3080/v1/models
48
+
49
+ # 对话(流式/非流式)
50
+ curl -X POST http://localhost:3080/v1/chat/completions \
51
+ -H "Content-Type: application/json" \
52
+ -d '{"model":"glm-5.2","messages":[{"role":"user","content":"你好"}],"stream":false}'
53
+ ```
54
+
55
+ 任何支持 OpenAI 兼容 API 的工具(Claude Code、Cline、DSH 设置-模型 等)都可以把
56
+ `baseURL` 指向 `http://localhost:3080/v1`。
57
+
58
+ **鉴权**:默认 `requireApiKey=false`,`/v1/*` 不要求鉴权(本地使用,与 9router 一致)。
59
+ 在「端点与密钥」页开启「要求 API Key」后,请求必须带
60
+ `Authorization: Bearer <库内启用的 Key 或 TW2A_API_KEY>`。
61
+
62
+ ## 面板 API(`/router/api/*`,同源)
63
+
64
+ | 端点 | 方法 | 说明 |
65
+ |---|---|---|
66
+ | `/health` | GET | 供应商列表(含来源/能力) |
67
+ | `/status` | GET | 全部账号(含供应商 id) |
68
+ | `/models` | GET | 合并模型列表(已过滤禁用) |
69
+ | `/combos` | GET | 组合 fallback 链 |
70
+ | `/keys` | GET/POST | 密钥列表(含完整 key)/ 创建 `{name}` → 返回明文一次 |
71
+ | `/keys/toggle` | POST | `{id, isActive}` |
72
+ | `/keys/delete` | POST | `{id}` |
73
+ | `/settings` | GET/PATCH | `{requireApiKey}` |
74
+ | `/suppliers/:id/login` | POST | 生成登录链接 |
75
+ | `/suppliers/:id/login/callback` | POST | `{callbackUrl}` → 加账号 |
76
+ | `/suppliers/:id/models` | GET | 模型 + 启用状态 |
77
+ | `/suppliers/:id/models/toggle` | POST | `{id, enabled}` |
78
+
79
+ ## 架构
80
+
81
+ ```
82
+ 浏览器(client 半)
83
+ └─ 侧边栏「路由系统」+ 中心栏面板(RouterView, 含返回会话按钮)
84
+ ├─ RouterView tab: 供应商 / 组合 / 端点与密钥
85
+ ├─ SupplierDetail 供应商详情:链接池 + 加链接 + 可用模型
86
+ ├─ EndpointTab 端点 URL + requireApiKey + 密钥管理
87
+ └─ fetch /router/api/* (同源,无 CORS)
88
+ └─ host 半(src/index.ts)
89
+ ├─ /v1/models + /v1/chat/completions (OpenAI 兼容, KeysStore 鉴权)
90
+ ├─ KeysStore(src/keys.ts) 密钥库 + requireApiKey
91
+ └─ Router(路由器) → suppliers[]
92
+ ├─ OpenCodeSupplier(lib/suppliers/opencode.js) 无账号免费直连
93
+ ├─ OpenRouterSupplier(lib/suppliers/openrouter.js) API key 账号
94
+ └─ NvidiaSupplier(lib/suppliers/nvidia.js) API key 账号
95
+ └─ 外部插件供应商(经 router.suppliers service 注册)
96
+ ```
97
+
98
+ - **供应商抽象**:可插拔 js 模块只提供**差异化能力**(`status/listModels/getAlias/chatCompletions`
99
+ + 可选登录/签到/测模型);**通用能力**(连接池排序/策略、模型启用/自定义、别名、凭证)
100
+ 由核心统一管。
101
+ - **供应商加载**(三来源,见 [`docs/suppliers.md`](docs/suppliers.md)):
102
+ 1. 内置:`lib/suppliers/*.js`(随插件分发,如 opencode)
103
+ 2. 用户:`~/.dsh/profiles/web/suppliers/*.js`
104
+ 3. 外部插件:其他 DSH 插件通过 cordis service `router.suppliers`
105
+ (值为 `{ [supplierId]: (env) => SupplierModule }`)暴露供应商,
106
+ dsh-router `ctx.inject(['router.suppliers'])` 延迟加载。
107
+ - **模型统一策略**:插件不内置、不缓存模型;`listModels` 每次从上游拉取,
108
+ 缓存由核心按 60s TTL 统一管(`/suppliers/:id/models`),`/v1/models` 保持实时。
109
+ - **凭证存储**:SQLite 单库 `{authDir}/credentials.sqlite`(表 `credentials(supplier, uid, data)`,
110
+ 凭证为供应商不透明 JSON blob)。
111
+ - **/v1/\* 鉴权**:由 `KeysStore.requireApiKey` 控制。关闭 → 不鉴权;
112
+ 开启 → Bearer 必须是「库内启用的 key」或 `TW2A_API_KEY` env。
113
+
114
+ ## 环境变量
115
+
116
+ | 变量 | 默认 | 说明 |
117
+ |---|---|---|
118
+ | `TW2A_AUTH_DIR` | `<dataDir>/auths` | 凭证目录(dsh-router 核心统一管,`credentials.sqlite` SQLite 库) |
119
+ | `TW2A_STATE_FILE` | `data/state.json` | 状态持久化(同目录放 keys.json / combos.json / supplier-config.json) |
120
+ | `TW2A_API_KEY` | 空 | /v1 Bearer 鉴权(与库内 key 等效) |
121
+
122
+ ## 构建
123
+
124
+ ```bash
125
+ pnpm install
126
+ pnpm build # lib/index.js(host) + lib/client.js / lib/client-registry.js(browser)
127
+ pnpm typecheck
128
+ ```
129
+
130
+ ## 挂载
131
+
132
+ 1. `~/.dsh/profiles/web/package.json` 的 `dsh.profile.bundles` 加 `"dsh-router"`,
133
+ `dependencies` 加 `"dsh-router-core": "link:/Users/carvin/Desktop/dsh-plugins/dsh-router"`;
134
+ 2. `cd ~/.dsh/profiles/web && pnpm install`;
135
+ 3. 重启 `dsh web`。
136
+
137
+ > 发布版:`npm i dsh-router-core`(见 [npm](https://www.npmjs.com/package/dsh-router-core))。
138
+
139
+ ## 前提
140
+
141
+ - 凭证由 dsh-router 核心统一管(SQLite 库 `<dataDir>/auths/credentials.sqlite`);
142
+ - 供应商接入与开发见 [`docs/suppliers.md`](docs/suppliers.md);
143
+ - 重启 DSH 后 `/v1/*` 即生效;面板管理账号、模型与密钥。
144
+
145
+ ## 致谢
146
+
147
+ 感谢以下项目给的灵感:
148
+
149
+ - [decolua/9router](https://github.com/decolua/9router) —— 本地 AI 路由网关,面板/组合/连接池/凭证等思路的来源;
150
+ - [deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) —— DSH「一切皆插件」的宿主框架;
151
+ - [omdsh-dev/dsh-mnemon](https://github.com/omdsh-dev/dsh-mnemon) —— DSH 插件形态与侧边栏入口的参考。
@@ -0,0 +1,9 @@
1
+ # dsh-router bundle patch
2
+ #
3
+ # Mounts dsh-router into the DSH cordis bundle stack. dsh-router adds a
4
+ # 路由系统 (Routing System) sidebar entry beside dsh-mnemon's 记忆系统; its
5
+ # host half serves /router/api/* (OpenAI-compatible /v1/* routing).
6
+ # No dependency on other plugins.
7
+ - insert:
8
+ - id: dsh-router
9
+ name: 'dsh-router'