@tr1v3r/dsh-proxy

toolstested: passnpmMIT

Hot-switches in-process DSH fetch traffic among direct, manual HTTP(S)/SOCKS5 proxy, and ambient system-proxy modes, with no-proxy rules and optional proxy-environment export for newly spawned child processes.

下载量 / Downloads
1,263
依赖体积 / node_modules
2.96 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add @tr1v3r/dsh-proxy

Sandbox test results

StageResult
1 install✓
2 list✓
3 mount✓
4 boot—

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

dsh-proxy — DSH 运行时可切换出站代理

English readme: [README.md](README.md)。

![npm](https://www.npmjs.com/package/@tr1v3r/dsh-proxy)

![license](LICENSE)

![DSH Market](https://dsh.market/)

@tr1v3r/dsh-proxy 是 DeepSeek Harness 插件,把进程内所有出站请求——

LLM 提供方、web_search / web_fetch、streamable-http MCP——经由

HTTP(S) CONNECT 或 SOCKS5 代理转发,并且支持运行时随时开关、随时换代理:

可以在 Web「设置 → 通用 → 网络代理」中操作,也可以编辑 profile 的

cordis.patch.yml 中的 dsh-proxy 条目(热加载),全程零重启。

上面的动图展示路由引擎,安装后可运行 node scripts/demo.mjs 复现。

工作原理

DSH 与 pi-ai 的请求都走 globalThis.fetch,而它读取的是 undici 的全局

dispatcher 槽位(Symbol.for('undici.globalDispatcher.1'))。本插件接管该槽位:

  • http(s):// 代理 → EnvHttpProxyAgent(https 走 CONNECT 隧道)
  • socks5:// 代理 → undici 内置 Socks5ProxyAgent(支持 URL 内鉴权;

socks5h:// / socks:// 自动归一;域名在代理端远程解析)

  • noProxy 规则 → 两条路径统一走 RoutingDispatcher 分流,HTTP 与 SOCKS

语义完全一致(undici 风格:裸条目匹配主机及点边界子域;host:port 锁定

端口; 全部直连;前导点 / . 前缀视同裸条目等价写法)。manual 模式

下 dispatcher 刻意忽略环境变量里的 NO_PROXY/HTTP_PROXY——导出的 env

只引导子进程,进程内路由完全由 profile 条目配置决定;system 模式则相反,

跟随环境代理——HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY,环境变量

缺失时再回退到 macOS 系统设置里的网络代理(scutil --proxy)——每次分节

应用时重新探测一次,而非持续轮询)

exportEnv: true(默认)时,切换还会同步导出

HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY 到 dsh 进程环境——切换后

新拉起的子进程(bash 工具里的 curl/git、stdio MCP server)跟着走同一

代理。启动时由你自己设置的环境变量绝不会被覆盖;禁用/卸载时全部还原。回环直连开启

(默认)时,导出的 NO_PROXY 还会并入回环默认集(localhost,127.0.0.1,::1,与你的

规则去重合并);bypassLoopback: false 时按你自己的列表原样导出。

被替换下来的旧 dispatcher 先优雅关闭、30 秒后强制销毁,确保切换真正切断

旧的 keep-alive 连接。在途请求同样只有这 30 秒宽限(RETIRE_DESTROY_MS):

切换后仍持续超过约 30 秒的流式响应,会在旧 dispatcher 的 socket 被强制销毁时

被中断。

凭据安全

代理 URL 中内嵌的 user:pass@ 凭据以明文存放在磁盘上——profile 的

cordis.patch.yml 与 settings 持久化中——仅靠文件权限保护。默认

exportEnv: true 时,凭据还会随 HTTP(S)_PROXY 环境变量写入 dsh 进程,

切换后拉起的子进程都会携带(同一用户可通过 ps -E 或

/proc/<PID>/environ 看到;其他用户通常需要 root 等特权才能读取,

具体取决于平台权限设置,并非所有同机用户都可见)。为此不引入新的配置项;凭据敏感的场景,

建议让 dsh-proxy 指向本机免鉴权的代理入口(例如 http://127.0.0.1:7890,

由它再对接需要鉴权的上游),而不是把 user:pass@ 写进 URL。

安装

在目标 profile 目录(~/.config/dsh/profiles/<name>/):

1. package.json 加依赖与 bundle(合并进现有 dsh.profile.bundles 列表):

   {
     "dependencies": {
       "@tr1v3r/dsh-proxy": "^0.2.5"
     },
     "dsh": {
       "profile": {
         "bundles": ["@deepseek-ai/dsh-base", "@tr1v3r/dsh-proxy"]
       }
     }
   }

2. 安装:

   dsh plugin --profile <name> install --no-frozen-lockfile

3. 重启一次 dsh 挂载插件;此后再无需重启——切换全在 settings 里。

使用

Web 主界面侧栏底部(设置上方)只有「代理状态」图标;悬浮、聚焦或打开菜单可查看

当前选择的模式,并在直连、跟随系统和手动代理之间切换。它与设置页共用同一个配置条目,外部编辑

profile 的 cordis.patch.yml 后也会同步更新;悬浮提示中的手动代理地址会隐藏用户名和密码。

「跟随系统」表示已选择的模式,不保证系统探测到了可用代理;实际出口以 DSH

日志为准。没有有效代理地址时,快捷菜单不会启用手动模式。要编辑地址、直连规则

或子进程开关,请打开「设置 → 通用 → 网络代理」。

Web profile 也可打开「设置 → 通用 → 网络代理」:从下拉列表选择直连、跟随系统或手动代理,

选择后立即生效,无需「应用」按钮。手动模式可填写 HTTP(S)/SOCKS5 URL、直连地址

(每行一个)和子进程环境变量开关;URL 与直连地址失焦后保存,开关切换后立即保存,

无效 URL 不写入文件。图形界面写入同一个 dsh-proxy 配置条目,文件配置仍然完整保留:

直接编辑 profile 的 cordis.patch.yml 会热加载并同步到图形界面;并发修改由修订号保护,

避免覆盖新值。

下拉菜单提供三种出站模式:

也可以在 ~/.config/dsh/profiles/<name>/cordis.patch.yml 添加如下条目

(热加载,立即生效);如果文件已有条目,就追加到现有 YAML 列表中;已有

dsh-proxy 条目时直接修改该条目。mode 可在

direct(直连)、system(跟随系统)、manual(手动)间切换:

- id: dsh-proxy
  config:
    mode: manual                           # direct | system | manual
    proxy: socks5://127.0.0.1:1080         # 仅 manual——http://…、https://…、
                                           # socks5://user:pass@host:1080、socks5h://…
    noProxy:                               # 仅 manual——可选分流规则
      - localhost
      - .internal.example
      - registry.corp:443
    bypassLoopback: true                   # manual 与 system 均生效——本地回环默认直连
                                           # (false 可改为走代理)
    exportEnv: true                        # 仅 manual——同步设置子进程的 HTTP(S)_PROXY

mode · 行为

direct · 直连,不走任何代理(等价于旧的 enabled: false)。

system · 跟随主机代理,每次分节应用时探测一次:读取 HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY 环境变量;环境变量缺失时,在 macOS 上再读取系统设置里的网络代理(scutil --proxy)。是保存时探测、非持续轮询;Windows 注册表、Linux 桌面与 PAC 暂未覆盖。忽略 proxy/noProxy/exportEnv。

manual · 走 proxy URL,可用 noProxy 分流(等价于旧的 enabled: true)。

enabled: true/false 仍作为旧写法兼容——未设置 mode 时分别映射到

manual/direct:

- id: dsh-proxy
  config:
    enabled: true                          # ≡ mode: manual
    proxy: http://127.0.0.1:7890

每次保存立即重路由。插件会记录每次切换:

dsh-proxy: routing global fetch via socks5://***@127.0.0.1:1080, noProxy 3 rule(s)
dsh-proxy: following system proxy (http://127.0.0.1:7890, noProxy 3 rule(s))
dsh-proxy: direct (mode: direct)

(日志中代理 URL 的用户名密码会打码。system 模式只读环境/系统代理,

不会回写这些环境变量。)

已应用路由快照

通用设置中的代理卡片通过可选、已认证的 Connection Fetch 路由,读取 Host

最近应用的默认路由:所选模式、来源、分别脱敏的 HTTP/HTTPS 端点、绕过策略、

代次及稳定的应用/回退代码。保存完成不等于 Host 已应用该版本,必要时手动刷新。

不支持此能力或断连时显示“状态不可用”,不影响原有设置及快捷切换。

快照不是连接健康检查或逐请求追踪。direct 恢复原始 dispatcher(可能被其他插件

配置),不保证物理直连;system 展示上次实际安装结果,不重新探测环境/系统。

NO_PROXY 和回环策略仍可能让个别请求绕过代理。此功能不发送任意 URL 探针或

提供方请求,也不传递凭据或完整代理 URL。提供方连接诊断仍延期,等待适配器给出

明确的有效目标与安全契约。

开启回环绕过时,导出的 NO_PROXY 只对去除首尾空白后完全相同的条目去重,保留

用户拼写和顺序,并补齐缺失的标准默认值:localhost、127.0.0.1、::1。

大小写、尾点和 IPv6 方括号变体各自保留,例如 127.0.0.1. 不能挤掉

127.0.0.1,[::1] 不能挤掉 ::1。外部客户端不一定遵循进程内的 hostname

匹配规则(curl 对上述 IP 变体的处理就不同),也不假定各客户端对 localhost

变体的解释等价。后缀/通配符/端口规则及其他地址不做规范化。

bypassLoopback: false 仍按原用户列表导出,不注入默认值也不去重,具体含义由

子进程客户端自行解释。进程内更广泛的回环识别逻辑保持不变。

覆盖范围

流量 · 是否代理

pi-ai 各提供方(zai-coding-cn、自定义 openai 兼容路由……) · ✅

dsh-llm-deepseek(deepseek-official) · ✅

web_search / web_fetch · ✅

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::9,最后更新 2026-10-04

Links

GitHub · Homepage · npm

Same category