dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
两个给 DeepSeek Harness(DSH) 用的本地插件。装上之后:
● ¥18.69,点一下立刻刷新;| 插件 | 你会看到 | 做什么 |
|---|---|---|
dsh-balance-effort | 标题栏 ● ¥xx.xx · 输入框右侧 ⚡ 高 ⌄ | 余额徽标(Host 直连 DeepSeek 余额接口,不把 Key 送到浏览器)+ 推理等级滑块 |
dsh-mobile-access | 左栏「手机访问」 | 内嵌反向代理,手机免登录打开 DSH 界面 |
两个包都是纯本地插件:没有构建步骤、没有第三方依赖,只有 lib/index.js(Host 半)和 lib/client.js(浏览器半)两份源码,直接就是本机正在跑的版本。
⚠️
dsh-mobile-access会把本机 DSH 的完整控制权开给端口上任何设备(等于本机代码执行,且不需要登录)。只在可信局域网里开,用完随手关掉 —— 详见安全说明。
两个插件装法完全一样,以 dsh-balance-effort 为例(把名字换成 dsh-mobile-access 即是另一个)。
# 把仓库里的插件目录整个拷到 DSH 的本地插件目录
Copy-Item -Recurse .\plugins\dsh-balance-effort "$env:USERPROFILE\.dsh\plugins\dsh-balance-effort"
目标路径是 %USERPROFILE%\.dsh\plugins\<包名>,里面应该直接就是 package.json / cordis.patch.yml / lib/。
DSH 按 profile 组合插件,改 %USERPROFILE%\.dsh\profiles\<profile>\package.json(<profile> 通常是 desktop 或 web)两处:
{
"dependencies": {
// ① 加一条 link 依赖,指向你刚放的目录(注意用正斜杠)
"dsh-balance-effort": "link:C:/Users/你的用户名/.dsh/plugins/dsh-balance-effort"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
// ② 把包名追加进 bundles,它才会被真的加载
"dsh-balance-effort"
]
}
}
}
重启后 DSH 会按 link: 依赖在 profiles/<profile>/node_modules/ 里建好链接,并把 lib/client.js 编进页面模块图。重启完直接看界面:
... 同一行);这两个插件互不依赖,可以只装其中一个。
bundles 里的名字、dependencies 的键、package.json 的 name、cordis.patch.yml 里的 id/name,四处必须完全一致。link: 路径写错。 Windows 路径照样用正斜杠;写错的话 node_modules 里不会出现链接。lib/index.js)注册路由发生在启动时,改完必须重启 DSH。lib/client.js 顶层是 window.__ModuleLoader__.load({ id, ... }),id 必须等于包名;改包名时别漏了它。ctx.logger.info,正常启动会各打印一行 serving ... / ready ...。余额 + 推理等级,一个包两个控件。
?force=1 绕过缓存);请求失败 5 秒后自动重试一次。is_available: false · 脉冲 = 加载中。Host 半在 DSH 自己的 webServer 上挂一条只读路由:
GET /dsh-balance/balance[?force=1]
→ { phase, total, granted, toppedUp, currency, isAvailable, updatedLabel, source }
流程是:ctx.credentials.resolve('DEEPSEEK_API_KEY') 拿到 Key → 服务端请求 https://api.deepseek.com/user/balance → 只把数字回给浏览器。安全口径在代码注释里写死了:只接受 GET、不接受任何入参(没法当 SSRF 跳板)、响应 no-store、永不回显 Key。5 秒内的重复请求合并成一次,单次请求 20 秒硬超时。
name),点开是滑轨面板。modelDirectories.select() 写回会话,左上角按钮恢复模型默认档位。reasoning.efforts;换模型时胶囊跟着变。无服务 / 无目录 / 加载中 / 无选择 / 未收录 / 无档位。这是刻意的:注册成功却看不见属于最难查的哑失败。让手机访问只监听 127.0.0.1 的 DSH Web GUI,全程在界面里开关。
用法:左栏底部「手机访问」→ 点开 → 开启 → 面板列出本机所有局域网地址(带网卡名、可复制)→ 手机连同一个 WiFi,浏览器打开任意一条即可,不用输 token、不用配对。
为什么能免登录:DSH 的 /api 信任围栏只认环回或已 trusted 的 authority,并且用 authority 绑定的签名 cookie 认浏览器。插件做两件事:
0.0.0.0:3081 → 转发到 127.0.0.1:<DSH 真实端口>,把每个请求的 Host / Origin 重写成环回 authority,围栏自然放行(不用改 DSH 配置,也不用 --trusted-host);client-connection/browser-session 里的密钥现场签发一张 cookie 注入每个转发请求,所以手机侧不需要任何凭据。普通 HTTP 和 WebSocket 升级(/api/remote.mux 流式通道)都支持,否则手机上会一直转圈。
控制面(挂在 DSH 自己的 webServer 上,只有同源浏览器会调):
GET /dsh-mobile-access/state → { running, dshPort, proxyPort, urls: [{ ifName, address, url }], error }
POST /dsh-mobile-access/start
POST /dsh-mobile-access/stop
几个实现细节:
3081;被占用时 start 会返回 500 并把错误显示在面板上。169.254.x.x 这类链路本地地址(网卡没拿到 DHCP 时出现的占位地址,手机连不上)。dsh-balance-effort:浏览器半只拿得到余额数字。Key 全程留在 Host 进程里,路由无入参、只读。dsh-mobile-access:开启期间,任何能访问该端口的设备都拥有对本机 DSH 的完全控制权(等价于本机代码执行),而且不需要登录。面板上这句警告是常驻的,不是装饰。
bundles 里删掉包名,从 dependencies 里删掉那条 link:;%USERPROFILE%\.dsh\plugins\<包名>;浏览器端注入的样式标签和监听器都跟着 effect 一起回收,不会残留。
MIT —— 见 LICENSE。