需要时自动拉起代理内核,空闲后自动关闭
29/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add xfgil/dsh-proxy-on-demand该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(308 字)↓
DSH 按需代理插件:需要时才拉起 mihomo 内核,用完空闲自动关闭 —— 平时不占端口、不留后台进程。首次运行自动下载内核(约 61MB),内置设置界面可填订阅或一键导入本机 FlClash 配置。内核与 Windows 系统代理是两枚独立开关:内核只绑 127.0.0.1,起停不改变你的网络环境;动系统代理前先备份原值,关的时候逐字段精确还原(连绕过列表都一字不动),别人占着时只报告不抢。自带节点面板:列分组、列节点、切换后回读确认、一键测延迟。检测到全屏游戏只是不启用代理;检测到 FlClash 等其它代理已在运行就静默让路。On-demand proxy for DeepSeek Harness.
README
由 DeepSeek 最新模型翻译生成dsh-proxy-on-demand
需要时才拉起代理内核,用完自动关。平时不占端口、不留后台进程、不碰你的系统代理。
给智能体用的工具,不是给人用的客户端 —— 内核用 7899(避开 FlClash 的 7890),本机已有代理在跑时直接借道,一个进程都不起。
| dsh-proxy-on-demand — 按需代理,用完自动关(本仓库) |
| dsh-hot-reloader — 改完插件源码不用重启 |
| dsh-session-clock — 按会话授时与空闲间隔 |
| dsh-second-opinion — 卡住时把问题交给另一个独立会话,要一份第二意见 |
| dsh-onebot-companion — QQ 通道一体化:出站沉默守卫 / 行为规则 / 对话节奏 / 人设 / 语音 |
[!IMPORTANT]
首次运行会自动联网下载内核。 本插件不含内核二进制,第一次要用时会从 mihomo 的官方 GitHub Release 自动下载 mihomo-windows-amd64(约 61MB)到插件目录下的 runtime/,之后离线可用。
不需要你手动装任何东西;删掉 runtime/ 即可完全清除,磁盘上不留残余。
不想自动下载就在配置里设 autoDownload: false 并自行放好内核。
细节见下载说明。
[!
展开完整文档(README 剩余 1 节)
dsh-proxy-on-demand
需要时才拉起代理内核,用完自动关。平时不占端口、不留后台进程、不碰你的系统代理。
给智能体用的工具,不是给人用的客户端 —— 内核用 7899(避开 FlClash 的 7890),本机已有代理在跑时直接借道,一个进程都不起。
| dsh-proxy-on-demand — 按需代理,用完自动关(本仓库) |
| dsh-hot-reloader — 改完插件源码不用重启 |
| dsh-session-clock — 按会话授时与空闲间隔 |
| dsh-second-opinion — 卡住时把问题交给另一个独立会话,要一份第二意见 |
| dsh-onebot-companion — QQ 通道一体化:出站沉默守卫 / 行为规则 / 对话节奏 / 人设 / 语音 |
[!IMPORTANT]
首次运行会自动联网下载内核。 本插件不含内核二进制,第一次要用时会从 mihomo 的官方 GitHub Release 自动下载 mihomo-windows-amd64(约 61MB)到插件目录下的 runtime/,之后离线可用。
不需要你手动装任何东西;删掉 runtime/ 即可完全清除,磁盘上不留残余。
不想自动下载就在配置里设 autoDownload: false 并自行放好内核。
细节见下载说明。
[!WARNING]
自用工具,请自行评估风险。 本插件按「原样」提供,不附带任何明示或默示担保。
代理内核、节点与订阅的来源及合法性由使用者自行负责;请遵守你所在地的法律法规与所使用服务的条款。作者不对使用本软件造成的任何直接或间接后果承担责任。
目录
- 这是什么
- 它到底解决了什么问题
- 环境要求
- 安装
- 使用
- 设置界面
- 借道已有代理
- 配置
- HTTP 接口
- 它是怎么做到的
- 下载说明
- 上游程序
- 已知限制
- 免责声明
- License
这是什么
dsh-proxy-on-demand 是一个 DeepSeek Harness(DSH)插件,给智能体一个随叫随到、用完就走的代理。
定位是「给智能体用的工具」,不是「给人用的客户端」。 它没有托盘图标、不抢系统代理、不替你做「现在该不该上网」的决定。设置页存在,是因为你要往里填节点(订阅 / 从 FlClash 导入 / 手动粘贴)—— 填完就可以忘了它。
它把 mihomo(Clash Meta 内核)包进插件里:
- 需要时自动拉起 —— 第一次要用的时候自己下载内核、准备配置、启动进程。
- 空闲后自动关闭 —— 默认 2 分钟没人用就杀掉内核、清掉状态文件。
- 不跟 FlClash 抢端口 —— 内核用 7899,故意避开 FlClash/Clash 系默认的 7890;管理 API 从 19090 起、DNS 从 15353 起,再各自找空闲端口(也避开了 FlClashCore 惯例的 9090 和它会占的 1053)。所以你那边 FlClash 该开就开,不受影响。
- 永不碰系统代理 —— 插件只把内核绑在 127.0.0.1 上,一个字节都不写 Windows 系统代理注册表。要不要让流量走代理,由你自己(HTTP_PROXY、或你自己的代理软件)决定。
- 本机已有代理就直接借道 —— 你已经开着 FlClash 之类的时候,插件复用它的出口,自己一个进程都不起(见借道已有代理)。
- 自带节点面板 —— 内核是自己起的时候,可以在设置页列分组、列节点、切节点(切完回读确认)、一键测延迟。
它到底解决了什么问题
用 Clash 系客户端(Clash Verge、FlClash、ClashX…)的人都有这个体验:
要用一下代理 → 打开客户端 → 等它起内核、拉订阅 → 用完 → 忘了关 → 它一直挂在托盘里,占着 7890,开着系统代理
对脚本、CI、爬虫、偶尔抓一次墙外数据这类场景,这个模型是反的:代理只在几秒钟里被需要,却要一直养着一个常驻进程。
这个插件把模型倒过来:代理是函数的调用栈,不是常驻服务。
dsh-proxy -- curl.exe -sS https://api.github.com/repos/MetaCubeX/mihomo
内核按需启动 → 命令跑完 → 空闲超时后内核自动退出
在 DSH 里,智能体需要抓墙外内容时直接调 POST /dsh-proxy/fetch,插件会顺手准备出口(本机已有代理就借道,否则起内核)、抓完续一次租约,用完自己关。
留下的是:HTTP 接口、命令行、内核按需起停,以及配置来源那一小块设置页(订阅 / 从 FlClash 导入 / 手动粘贴)—— 没有它你就没法往里填节点。
为什么不用 FlClash 的内核
FlClash 自带的 FlClashCore.exe 不是标准 mihomo,而是 GUI 专用的 IPC 从属进程。它的 main() 长这样:
func main() {
args := os.Args
if len(args) <= 1 { os.Exit(1) }
go exitOnTermination()
startServer(args[1]) // args[1] 是管道名
}
func startServer(arg string) {
dialed, err := dial(arg) // 连不上就 panic if err != nil { panic(err.Error()) } }
配置全部由界面经 IPC 下发,无法脱离 GUI 独立启动(实测 FlClashCore.exe -v 会 panic: dial unix -v,因为它把 -v 当成了管道名)。所以本插件用上游标准内核。
环境要求
- Node.js ≥ 22
- DeepSeek Harness 0.2.0-rc.2(Electron 44.0.0)—— 开发与验证所用的版本;作为插件运行需要它。命令行部分(dsh-proxy)可脱离宿主独立使用。
- 一份 Clash/mihomo 配置,来源三选一:
- 订阅链接
- 本机 FlClash 的 config.yaml(自动导入并修正路径)
- 手动粘贴
安装
dsh plugin --profile <你的profile> add link:<本目录绝对路径>
例如:
dsh plugin --profile desktop add link:D:/path/to/plugins/dsh-proxy-on-demand
从 npm 安装(如果你是用发布版):
dsh plugin --profile <你的profile> add dsh-proxy-on-demand
装完之后,profile 清单(dsh.profile.bundles)会被自动更新。
⚠ 对「宿主正在运行时才装的新插件」:光改清单不够,需要再关开一次这个 bundle。
宿主不会为运行中新加入的 bundle 自动挂载 —— HMR 只 reconcile 已经存在于 loader 树里的 entry。实测:清单写好了、node_modules 链接也建了,但 plugin_manager list_plugins 里就是没有这个包,HTTP 端点 404。此时把它关掉再打开(plugin_manager set_bundle {target, enabled:false} → 再 enabled:true,两次都会返回 {"changed":true,"application":"applied"}),宿主侧端点立刻 200、客户端界面同时注册进 slot 树。不需要重启宿主。
反过来,如果插件目录/链接在宿主启动之前就存在,宿主启动时会一并加载,就不必这一步。
手工安装(不走 CLI)也可以:在 profile 的 package.json 里加 "dsh-proxy-on-demand": "link:D:/path/to/plugins/dsh-proxy-on-demand",并在 dsh.profile.bundles 数组里补上 "dsh-proxy-on-demand";然后在 profile 的 node_modules 下建一个指向插件目录的链接(mklink /J 或符号链接均可)。
使用
在 DSH 里
装上之后,设置 → 按需代理(设置侧栏里独立的一页,不是「设置 → 插件」里的卡片)会出现完整界面(见下节)。也可以用 HTTP 接口:
curl -X POST http://127.0.0.1:19387/dsh-proxy/fetch \
-H 'content-type: application/json' \
-d '{"url":"https://api.github.com/repos/MetaCubeX/mihomo/releases/latest"}'
命令行
插件自带 dsh-proxy 命令,不依赖宿主进程,宿主没起来也能用:
dsh-proxy status # 看状态(含出口端口、有没有在借道) dsh-proxy prepare # 下载内核 + 准备配置(顺手把 7890 / 1053 挪开) dsh-proxy import-flclash # 从本机 FlClash 导入配置 dsh-proxy peers # 看本机有没有可借道的代理 dsh-proxy start # 启动内核(或借道),守着直到空闲自动关 dsh-proxy stop # 立刻关掉(只关自己起的) dsh-proxy -- <命令> [参数...] # 带着代理跑一条命令
status 长这样(本机 FlClash 开着的时候):
运行时目录 : D:\Plugins\dsh-proxy-on-demand\runtime 端口 : 7899 空闲自动关 : 120 秒内核状态 : 未运行剩余计时 : - 借道探测 : 可以借 127.0.0.1:7890(自己的内核不必起)配置 : 143 个节点,482 条规则
端口 是插件自己内核的端口,借道探测 是「真要用的时候能不能借到」。
status 只探端口、不起内核(约 2ms)—— 看一眼状态不该顺手拉起一个进程。
内核真跑起来时还会多一行 出口端口,那才是 -- <cmd> 实际会用到的那个。
常用的是最后一种:
dsh-proxy -- git clone https://github.com/some/repo
dsh-proxy --idle 0 -- curl.exe -sS https://api.ipify.org # 跑完立刻关 dsh-proxy --idle 600 -- npm install # 空闲 10 分钟才关 dsh-proxy --no-borrow -- curl.exe -sS https://api.ipify.org # 不用本机已有的代理,坚持起自己的内核
它给子进程注入:
| 变量 | 值 |
| HTTP_PROXY / HTTPS_PROXY / ALL_PROXY | http://127.0.0.1:<出口端口> |
| NO_PROXY | localhost,127.0.0.1,::1,192.168.,10.,172.16.* |
NO_PROXY 很重要 —— 否则连本机服务(比如 DSH 自己的 19387)也会被绕进代理。
注意出口端口是运行期现算的:本机已有代理在跑时,它是借来的那个端口(多半是 7890),否则才是插件自己的 7899。CLI 不会想当然用设置里的端口 —— 那会指向一个没人监听的端口。
设置界面
装上插件后,设置侧栏里会多出一页「按需代理」,从上到下是:
状态 — 一眼看内核在不在跑,旁边一枚代理内核开关:
| 显示 | 含义 |
| 内核运行中 | 插件自己起的 mihomo 正在跑,显示 PID 与出口端口,非常驻时还显示「距离自动关还剩几秒」 |
| 端口被占用 | 7899 上已经有别的程序在听 —— 插件不起内核,直接用那个(见借道已有代理) |
| 内核未运行 | 还没起过,下次用到会自动拉起。本机已有代理在跑时也是这个 badge —— 状态行里会写明「未启动(借道中)」并给出实际出口端口 |
借道时开关会置灰:不需要启动自己的内核,点了也没意义。借道情况下也不显示倒计时 —— 那个内核不是我们的,它的寿命我们既不知道也不该管。每 4 秒自动刷新。
节点配置 — 三种填节点的方式:
| 方式 | 说明 |
| 订阅地址 | 粘贴后点「拉取订阅」,插件下载并改写成相对路径 |
| 从 FlClash 导入 | 读本机 FlClash 的 config.yaml,自动把规则文件的绝对路径改成相对路径 |
| 手动粘贴 | 直接贴一份 Clash/mihomo YAML |
节点面板 — 内核在跑时列出当前分组里的节点,每行左名右延迟,● 标出正在用的那个。顶部一个测延迟按钮触发整组测速;列表单页固定 8 行、超出滚动。
这里刻意没有分组下拉框:分组全平铺在滚动列表里,你自己滚。测速也是只留「测延迟」一种——「测连通性」因为实测只有极少数节点能通过(那次只有香港),判据价值低、又容易被误读成「网络坏了」,已经删掉。
测速目标是分组自己配的 url:(通常机场给的是 gstatic/generate_204);分组没配(多数手选分组都没配)就回落到一个国内可达的 generate_204。插件不替你改写配置文件里的目标。
为什么不是「让内核用分组自己的 url」就完事? mihomo 的 Selector 分组没有重写 URLTest(),不带 url 参数调延迟接口时它把空串原样传下去 → urlToMetadata("") 判 "scheme not Support" → 组里每个成员都失败,接口 4ms 内回 504 all proxies timeout。而面板点「测延迟」操作的正是第一个 Selector。所以现在由插件自己解析目标并始终带上:分组有自己的 testUrl 就用它,没有就用兜底的 generate_204。自动组(URLTest/Fallback/LoadBalance)会忽略传进来的 url、仍用自己的,因此这样做对它们无害。
借道时节点面板用不了,这是正常的。 列节点、切节点全走 mihomo 的管理 API,而管理 API 的地址与 secret 是插件给自己内核配的;借来的那个内核是别人的,secret 不同、地址也不同。这种时候插件会老老实实说「借道中」,不会假装能切。
参数 — 代理端口、空闲多久自动关(秒)、启用插件、首次是否自动导入 FlClash 配置、内核常驻。改完立即生效。
端口默认 7899,故意不是 7890 —— 那是 FlClash / Clash 系的默认端口,撞在一起会把对方的内核顶掉。端口改动需要重启内核才生效:把「代理内核」开关关掉再打开。
界面走插件自己的 HTTP 端点 + 直接读写状态文件,不依赖 DSH 的 settings 服务。
借道已有代理
如果你机器上已经有别的代理在跑(FlClash、Clash Verge、v2rayN……),本插件直接借道它的出口,自己一个进程都不起、不抢端口、不碰你的设置。别的代理退出后,插件下次要用时才自己起内核。
判据只有一条 —— 本地有没有东西在监听常见代理端口。不看进程名,也不要求对方是哪个软件:换成任何代理软件都自动适用,不需要维护「谁是代理」的名单,也不会因为某个软件不在名单里而漏判。代价是覆盖不到两种情况 —— 代理软件开着但还没开始监听端口,以及 TUN 模式不监听端口。这两种情况下插件会照常起自己的内核(借道没借到),但不会去动对方。
只看端口,不认软件
| 探的端口 | 18 个:7890-7893(Clash/mihomo)、7897/7898(Clash Verge Rev)、10808-10810(v2rayN/xray)、1080/1081(SOCKS 惯例)、2080/2081(sing-box)、20171/20172(Clash Verge 旧版)、8889(Clash for Windows)、8118(privoxy)、9910 |
| 成本 | 并发探完约 2–3ms(loopback 上的连接拒绝是瞬时的) |
| 优先级 | 按名单顺序,不按端口号排序 —— 7890 排第一,也就是「FlClash 优先」 |
借道结果有 3 秒缓存:一轮里连续几次抓取只会探一次端口。探端口用 net.createConnection,不起外部进程 —— 后者(netstat 之类)单次要 100–300ms,而这里并发探 18 个端口总共 1–2ms。
必须排除自己的内核
上表不含 7899 —— 那是本插件自己的端口。这不是小事:如果把它列进候选,在「自己的内核刚被杀、端口还没被系统释放」那一瞬间,插件会把自己借给自己,然后发现出口其实不存在。
所以名单里坚决不写自己的端口,而不是靠「判断这个监听是不是我」来绕 —— 后者在端口复用的情况下并不可靠。
端口被占时复用
借道只在准备自己起内核时才发生。走一遍 ensureRunning():
自己的内核已经在跑?──────是──> 续租返回(不探测、不动任何东西) │否找得到可借道的代理?──────是──> 记下出口端口,本插件不起内核 │否自己的 7899 被别人占着?──是──> 就用它(同样不起内核) │否才 core.start() 起自己的内核
借道时不写租约:那个内核是别人家的,我们没资格替它改寿命。空闲守护也会跳过 —— 别人的进程不归我们关。
命令行 bash dsh-proxy peers # 看借道检测结果:哪个端口可以借、判定用时 dsh-proxy peers --json # 同样的东西,JSON 形式 dsh-proxy --no-borrow -- cmd # 本次不用别人的,坚持起自己的内核
借道是正常状态,不是错误:这时候没有退出码、也不会被拦。
配置
插件自己的设置存在 <插件>/runtime/settings.state: json { "enabled": true, "port": 7899, "idleMs": 120000, "subscriptionUrl": "", "autoImportFlClash": true, "configSource": "flclash", "lastSyncAt": 1760000000000, "lastSyncNote": "已从 FlClash 导入(143 个节点 / 482 条规则)", "resident": false }
port 默认 7899,故意不是 7890(见借道已有代理)。
resident 默认 false —— 也就是本插件原本的行为「用完了自己关掉」,把它打开才是常驻(不因空闲自动关闭,随 DSH 一起退出)。
读设置时按上面这些键做白名单过滤,旧版本遗留的死键(比如早期接管系统代理用的 systemProxy)留在文件里也不会被读进来。
runtime/ 目录(已被 .gitignore 排除)里放的是运行期产物:
| 文件 | 作用 |
| mihomo.exe | 内核(首次用时自动下载) |
| config.yaml | 喂给内核的配置 |
| providers/rules/ | rule-provider 规则文件 |
| settings.state | 上面那份用户设置 |
| core.pid | 当前内核 PID(只用来杀自己启动的那个) |
| lease.state | 租约,记录「用到什么时候为止」 |
| busy.state | 忙锁,记录「哪条长命令正在用」(按 PID 判存活) |
| core.log | 内核日志 |
为什么状态文件是 .state 而不是 .json?
宿主会盯着插件目录,而它的插件监视器只看 .json(用 21 种扩展名实测的矩阵:.state/.log/.txt/.dat/.lock/.yaml/.pid… 全都不触发,只有 .json 触发,子目录里的 .json 同样触发)。一触发就是一次完整的热重载:先 dispose 旧实例,再 apply 新实例。
所以只要状态文件叫 .json,每写一次盘就重建一次插件,写了一半的状态会被另一个实例读走。换成 .state 之后热重载根本不会发生,这条竞态从根上消失。旧版本留下的 .json 会在启动时自动迁移(migrateStateFiles()),迁移完就删掉。
HTTP 接口
全部只监听 loopback(127.0.0.1 / ::1),非本机请求返回 403。
| 方法 | 路径 | 作用 |
| GET | /dsh-proxy/status | 状态:内核是否在跑、PID、出口端口 exitPort、是否借道 borrowed、剩余秒数 |
| GET | /dsh-proxy/settings | 读设置 + 当前配置概况 |
| POST | /dsh-proxy/settings | 写设置 |
| GET | /dsh-proxy/proxies | 列出分组与节点(加 ?fake=1 连信息伪节点一起列) |
| POST | /dsh-proxy/proxies/select | {"group":"...","node":"..."} 切换节点,回读确认 |
| POST | /dsh-proxy/proxies/test | {"group":"...","timeoutMs":3000} 测延迟 |
| POST | /dsh-proxy/proxies/connectivity | {"node":"..."} 或 {"nodes":[...]} 真的以该节点为出口发一次请求(只有接口,界面上没有按钮 —— 判据价值低、容易误读成「网络坏了」) |
| POST | /dsh-proxy/prepare | 下载内核 + 准备配置 |
| POST | /dsh-proxy/start | 启动内核(本机已有代理时改为借道,返回里带 borrowed: true) |
| POST | /dsh-proxy/stop | 关闭内核(只关自己起的,借来的不动) |
| POST | /dsh-proxy/renew | 续期空闲计时 |
| POST | /dsh-proxy/config/from-subscription | {"url":"..."} 拉订阅 |
| POST | /dsh-proxy/config/import-flclash | 从本机 FlClash 导入 |
| POST | /dsh-proxy/config/manual | {"text":"..."} 手动写配置 |
| GET | /dsh-proxy/config/example | 取一份模板 |
| POST | /dsh-proxy/fetch | {"url":"https://..."} 经代理抓一次 |
| GET | /dsh-proxy/peers | 借道检测状态(加 ?force=1 绕过缓存) |
| POST | /dsh-proxy/peers/clear-cache | 让借道检测缓存失效,强制重新探测 |
没有系统代理端点,也没有游戏端点。 所有端点都只在 loopback 上监听,而且没有「被拦下 → 409」这条路径:借道是正常状态,最坏情况也只是自己多起一个内核,代理始终可用。请求出错时统一回 500。
/fetch 必须用 exitPort(),不是设置里的端口。 借道时出口是借来的那个(多半是 7890),照设置里的 7899 发请求会打到一个没人监听的端口上。返回体里带着 via(实际用的 127.0.0.1:<端口>)与 borrowed(这一发是不是走的别人的代理),排查时看这两个字段。
/fetch 会带上 User-Agent。 GitHub 的 REST API 对所有请求强制要求 UA,不带一律回 403(Request forbidden by administrative rules...)—— 不是限流。而 /fetch 最常见的用途恰恰就是抓 api.github.com(上面那个 curl 示例就是),所以它固定带 dsh-proxy-on-demand (+https://github.com/xfgil/dsh-proxy-on-demand)。
它是怎么做到的
空闲自动关:租约 + 守护
任何一次使用 ──renew()──> 写 lease.state { deadline: now + idleMs } │ 守护定时器(每 15s)───────────┘ 走的是借道?──是──> 直接返回(不写租约、也永不「关」别人的内核) │否有命令正持忙锁?──是──> 绝不关(busy.state,按 PID 判定存活) │否 deadline 到期?──否──> 继续睡 │是 └─> 内核是我们起的?──否──> 只删租约,不碰进程 │是 └─> 杀 core.pid 里的那个 PID,删 pid/lease/busy 文件
四个刻意的设计:
1. 只杀自己启动的 PID。 状态文件里记着 core.pid,绝不按进程名扫杀 —— 否则会误杀用户自己开的 FlClash 或其他 mihomo。
2. 端口被占时不抢。 如果自己的端口已经被别的程序监听,插件不启动内核,只标记一下后照常可用,也不会在空闲时去关那个不属于自己的进程。更常见的情况是借道:别人的代理在 7890 上跑着,插件连自己的端口都不碰。
3. 长命令期间持忙锁。 dsh-proxy -- <命令> 跑起来时会写 busy.state(内容是自己的 PID)并持续续租。只要锁在,checkIdle() 一律不动内核 —— 否则一条比 idleMs 更久的命令(比如 npm install、git clone)会在跑到一半时被自己的守护掐断,表现为 ConnectionReset。持有者进程若已消失,锁按 PID 自动失效,不会永久卡住。
4. 命令行守到最后。 守护定时器是 unref() 的(不阻止 Node 退出)。所以 dsh-proxy start 与 dsh-proxy -- <命令> 都会一直守着,直到内核真的被自动关掉才返回 —— 否则命令一跑完就退出,没人执行「到期杀内核」那一步,内核会一直挂着,正是本插件要消灭的情况。(借道时不守:没有自己的内核要守,也没人需要关,dsh-proxy start 打完一行提示就直接返回。)
借道插在哪
借道探测只在起核路径上跑,不影响已在运行的内核:
POST /start ─┐
POST /fetch ─┼─> ensureAndStart() ─> core.ensureRunning()
CLI -- cmd ─┘ │
自己的内核已在跑?──是──> 续租返回(不探测) │否找到可借道的代理?──是──> 用它的出口,本插件不起内核 │否自己的端口被别人占?──是──> 就用它,同样不起内核 │否
core.start() ← 唯一的起核分支
借道判定用闭包回调注入 core,不是让 core.js 直接 import peers.js —— 这样 core.js 只管进程生命周期,探测规则留在上层,也能被单独测试: js // lib/index.js:宿主侧直接借,交给 core 决定什么时候问
const borrowFn = async ({ ownPort } = {}) => findBorrowableProxy({
ownPort: Number.isInteger(ownPort) ? ownPort : user.port,
});
// bin/dsh-proxy.mjs:命令行多一层开关(--no-borrow 干脆传 null 把这条路径关掉)
const borrowPort = opts.noBorrow ? null : ({ ownAlive } = {}) => findBorrowableProxy({
ownPort: port,
force: ownAlive !== true,
});
ownPort 必须由 core 现算再传下去 —— 上层(index.js)拿不到「这个端口上的监听是不是我自己」这个判断依据。探测失败时回调返回 null,core 就当「没人可借」自己起内核:宁可多起一个内核,也不要因为探测代码出问题就让代理彻底不可用。
配置路径:两个必踩的坑坑 1 — SAFE_PATHS 沙盒。 mihomo 只允许访问 -d 目录内的相对路径。FlClash 的配置里 rule-provider 写的是绝对路径,直接启动会:
Parse config error: path is not subpath of home directory or SAFE_PATHS:
C:\Users\<user>\AppData\Roaming\com.follow\clash\profiles\...\rules\59aaf94a...
allowed paths: [D:\path\to\plugins\dsh-proxy-on-demand\runtime]
修法:把规则文件拷进 runtime/providers/rules/,路径改写成 providers/rules/<hash>。
坑 2 — YAML 里是双反斜杠。 文件里写作 C:\\Users\\暝\\...。如果按单反斜杠写 -replace,会静默不匹配 —— 而且此时再查「还剩几个单反斜杠」同样返回 0,造成「已经改好了」的假象。必须按字面的双反斜杠匹配: js const SEP = '\\\\\\\\?'; // 一个或两个字面反斜杠都认
下载说明
本插件唯一的联网下载行为是获取代理内核,没有别的下载。
| 下什么 | mihomo-windows-amd64 二进制(上游标准 mihomo 内核,不是 FlClash 的定制版) |
| 多大 | 约 61MB(实测版本 v1.19.32) |
| 从哪下 | MetaCubeX/mihomo 的官方 GitHub Release,默认取 /releases/latest;可用配置项 kernelVersion 固定某个版本 |
| 落到哪 | <插件目录>/runtime/mihomo.exe |
| 什么时候下 | 第一次真正需要用到代理时(prepare / start / fetch / -- <命令>)。不会在你装插件的时候偷偷下 |
| 怎么跳过 | 配置里设 autoDownload: false,并自己把内核放到 runtime/mihomo.exe。此后插件不会发起任何下载 |
| 怎么清掉 | 直接删 <插件目录>/runtime/ —— 内核、配置、规则、状态文件全在里面,删完磁盘上不留残余 |
镜像回退。 直连 github.com 的 Release 下载在国内会挂死(TCP 连得上、请求发得出去、响应永远不来),而不是快速失败。所以插件按顺序尝试多个源,每个源有 12 秒首字节超时,超时就换下一个:
| 顺序 | 源 |
| 1 | 直连 github.com |
| 2 | https://gh-proxy.com/ |
| 3 | https://ghproxy.net/ |
| 4 | https://ghfast.top/ |
下载完成后在本地解压(zip),只取其中的 mihomo.exe。之后离线可用,不会再联网。
除下载内核外,插件自身不主动连接外网 —— 抓取网页是你让它做的(/fetch 或 -- <命令>),不是它自己发起的。借道探测只连 127.0.0.1。
上游程序
本插件不含代理内核,只负责按需拉起和关掉它。真正的代理能力来自上游:
| 项目 | mihomo(即 Clash.Meta 内核) |
| 版权 | © MetaCubeX 及 mihomo 贡献者 |
| 授权 | GPL-3.0(独立于本仓库的 MIT) |
| 本插件与它的关系 | 仅在其官方 GitHub Release 下载 mihomo-windows-amd64 二进制,不修改、不重新打包、不静态链接;以独立进程方式调用 |
| 实测版本 | v1.19.32(Mihomo Meta v1.19.32 windows amd64 with go1.26.8),约 61MB |
| 版本策略 | 默认取 /releases/latest;可用配置项 kernelVersion 固定版本 |
上游程序的许可证、行为与安全性由上游项目负责。若你要分发本插件,请注意下载 GPL-3.0 程序与再分发它是两回事:本仓库只做前者。
已知限制
- Windows 优先。 内核资产名目前写死 mihomo-windows-amd64。换平台需要改 lib/index.js 的 prepareKernel()。
- 首次要联网下内核(约 61MB)。下好之后缓存在 runtime/,之后离线可用。见下载说明。
- 自己的端口(默认 7899)被占时不自启。 这是刻意的:宁可复用那个已经开着的代理,也不去抢端口。
- 借道时节点面板与切节点不可用。 列节点、切节点走的是 mihomo 管理 API,而借来的内核是别人的,controller 地址与 secret 都对不上。这时候界面会显示「借道中」并置灰内核开关,不会假装能操作。想切节点就先让别的代理退掉,或者用 --no-borrow 让插件起自己的内核。
- 借道检测只看端口,不看软件身份。 这是刻意的(见借道已有代理)。覆盖不到「代理软件开着但还没监听端口」和「TUN 模式不监听端口」两种情况;这种情况下插件会照常起自己那个 7899 的内核(借道没借到),代价是多一个进程,不会去动对方。
- settings.state 与 config.yaml 分开存。 换订阅不会丢你的开关和端口设置,但反过来,手动改 config.yaml 不会同步进界面显示的「节点数」以外的字段。
- 只测过 Windows 10/11 x64 + DSH 0.2.0-rc.2。
- 不替你判断「现在该不该用代理」。 打游戏时、别的代理在跑时,插件都不会拒绝工作 —— 最坏情况是自己多起一个内核。这个判断还给你自己。
- 永不改系统代理。 面板上没有系统代理开关,插件也不写注册表。要让流量走代理,请自己设 HTTP_PROXY,或者用你自己的代理客户端。
免责声明
这是作者自用的工具,请自行评估风险后再用。
- 本软件按「原样」(AS IS)提供,不附带任何明示或默示的担保,包括但不限于适销性、特定用途适用性与不侵权担保。
- 作者不对因使用或无法使用本软件而产生的任何直接、间接、偶然、特殊或后果性损害承担责任。
- 代理内核、节点与订阅的来源及合法性由使用者自行负责。 本插件只是把 mihomo 拉起来又关掉,它不提供、不内置、不分发任何节点或订阅。
- 请遵守你所在地的法律法规,以及你所使用服务的使用条款。
- 内核来自上游官方 Release,作者不对上游二进制的行为或安全性作任何保证。
License
本插件自身代码:MIT
其中下载并调用的上游内核 mihomo 版权归 MetaCubeX 及贡献者所有,以 GPL-3.0 授权 —— 详见 LICENSE 末尾说明。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
xfgil/dsh-proxy-on-demand
需要时自动拉起代理内核,空闲后自动关闭
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,270已汉化DSH
70.8
这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。