deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:khiqwq/dsh-system-proxy
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
DeepSeek Harness(DSH)的出站网络路由插件。它在 DSH 主进程中统一接管 fetch 与可选的 node:http / node:https 请求,根据目标主机及显式调用上下文,在直连、HTTP(S) 代理和 SOCKS4/4a/5/5h 代理之间选择线路;支持直连优先的故障回退、逐跳重定向重新决策、每主机健康记忆,以及内网/云元数据端点的默认保护。
当前版本已实现下述全部能力并通过
npm test(81 项断言 + 真实 Cordis loader 挂载/热重载验证)。
host、provider、plugin 路由;direct、proxy、fallback、block 四种动作;插件加载后:
globalThis.fetch,按规则选择直连或代理 dispatcher;patchNodeHttp: true 时包装 node:http / node:https 的 request 与 get;AsyncLocalStorage 传递显式 provider / plugin 信息;这是进程级全局补丁。同一进程内不应同时加载多个相互竞争的传输包装插件;本插件在还原时只恢复仍指向自身包装器的全局对象,不覆盖后来安装的包装器。
源码仓库:https://github.com/khiqwq/dsh-system-proxy
从源码安装:
git clone https://github.com/khiqwq/dsh-system-proxy.git
cd dsh-system-proxy
npm install
npm test
npm run build
npm run client-test
cd "$env:DSH_HOME\profiles\<name>"
npm install <dsh-system-proxy 源码目录的绝对路径>
# 将 "dsh-system-proxy" 加入 package.json 的 dsh.profile.bundles
发布后可使用:
dsh plugin --profile <name> add dsh-system-proxy
本包声明了 dsh.bundle.patch,安装为 DSH profile bundle 后会提供 system-proxy loader entry。
安装到带有 Settings 服务的 DSH profile 后,插件会以 system-proxy 命名空间注册交互式配置,并通过包内 ./client Web bundle 在 DSH Settings → 插件页面显示可折叠的 系统代理 / System Proxy 配置卡。卡片沿用官方 PluginCard 的紧凑层级、原生 DSH CSS variables、field grid、状态 badge 与 primary/secondary actions;中文 locale 自动显示中文,其他 locale 使用英文 fallback。双语词典由 @deepseek-ai/dsh-client-locale 注册并实时订阅切换。卡片可编辑基础开关、代理 URL、passwordRef 和只写密码;所有输入先保存在浏览器本地草稿中,折叠不会丢失草稿,只有回车或点击 保存并加密 / Save and encrypt 才写入。URL 是普通可见 endpoint 字段并明确拒绝 user:pass@ userinfo;真正的密码输入使用 type=password。命名空间不可用时卡片不会出现;只读状态和保存失败会在卡片内明确显示。保存后插件会串行停止旧传输包装并按最新配置热重装,无需手工编辑 patch 或重启主进程。loader entry 中的 config 作为 base 层:没有用户设置时保持原行为,清除用户覆盖后也会回落到该 base。
代理密码必须优先使用 passwordRef:隐式 default 代理默认使用 DSH_PROXY_PASSWORD(也可改成其他环境变量格式标识符),保存时先写 credential,再写 passwordRef 与其他 settings。保存后密码草稿立即清空,页面重新打开时只通过 credentials.describe() 获取“已配置/未配置”,不会调用 resolve()、回填原文、显示首尾或显示 DPAPI 密文;密码仅通过单向 credentials.set() 提交,绝不会保存到 settings。配套的 dsh-credentials-system 使用 Windows 当前用户绑定的 DPAPI 密文存储,并替换默认的明文 dsh-credentials-local。role("secret") 只负责页面/API 脱敏,本身不等于磁盘加密。
仍可直接使用下面的 cordis.patch.yml 配置;交互式用户层优先于 entry base。
配置位于 profile 的 cordis.patch.yml。以下示例与当前 package schema 一致:proxies 是对象,rules 是数组,默认策略位于 default 对象中。
- id: system-proxy
config:
enabled: true
mode: auto # auto | env | system | manual
url: '' # 旧配置兼容:隐式 default 代理(不要包含 userinfo)
# passwordRef: DSH_PROXY_PASSWORD # 隐式 default 代理的只写 credential 引用
patchNodeHttp: true
protectPrivate: true # 默认直连私网、链路本地和 metadata
healthMaxEntries: 10000 # 每主机健康表上限(LRU 淘汰)
noProxy:
- localhost
- '127.0.0.1'
- '::1'
- api.deepseek.com
only: [] # 旧配置兼容:非空时只代理这里的主机
proxies:
clash-http: http://127.0.0.1:7890
v2ray-socks: socks5h://127.0.0.1:10808
legacy-socks: socks4a://127.0.0.1:1080
os-proxy: { source: system }
# 推荐用 passwordRef 从 DSH credentials 服务解析密码;不能与 password 同时设置
authenticated: { url: http://proxy.example:8080, username: user, passwordRef: DSH_PROXY_OFFICE_PASSWORD }
rules:
- host: [api.deepseek.com]
action: direct
- host: [api.openai.com]
provider: [openai]
action: proxy
proxy: v2ray-socks
- plugin: [some-unreachable-plugin]
action: fallback
proxy: clash-http
directTimeoutMs: 2000
- host: [api.blocked.example]
action: block
default:
strategy: fallback # direct | proxy | fallback
proxy: clash-http
directTimeoutMs: 3000
latencyThresholdMs: 1500
cooldownMs: 60000
methods: [GET, HEAD, OPTIONS, TRACE]
trustRouteHeaders: false
routeHeaderPrefix: x-dsh-route
Cordis loader 只在 EntryOptions 顶层合并。config 一旦出现在后续 patch 中,就会整体替换原 config;rules 或 proxies 使用数组/对象不会产生跨层深合并。
因此,在 profile patch 中增加一条规则时,必须重述要保留的完整 config,包括全部 proxies、rules、default 和兼容键。只写增量字段会丢失其他配置。
mode |
来源 |
|---|---|
auto |
代理环境变量 → OS 系统代理 → 显式 url |
env |
HTTPS_PROXY / HTTP_PROXY / ALL_PROXY(含小写) |
system |
Windows WinINET / macOS scutil |
manual |
仅显式 url |
专用环境变量:
DSH_PROXY_URL:运维级代理 URL 覆盖;DSH_PROXY_MODE:覆盖 mode;DSH_PROXY_DISABLE:任意非空值禁用插件;NO_PROXY / no_proxy:追加直连规则。显式 URL 支持 http://、https://、socks4://、socks4a://、socks5://、socks5h://(SOCKS 默认端口 1080;socks4a 与 socks5h 由代理端解析域名,socks4 与 socks5 本地解析)。
fetch 路径对所有 socks 协议统一使用自定义无状态 connector + undici Agent(connector 模式借鉴 @undicijs/proxy 的 buildSocksProxyConnector,MIT,已在 lib/socks.js 顶部署名):
Agent 按 origin 池隔离——闭合了 GHSA-hm92-r4w5-c3mj 那类 socks 隧道跨 origin 复用串线问题(不使用 undici 内置 Socks5ProxyAgent)。httpSocket 交给 undici 自己的 buildConnector 完成 TLS(ALPN/会话复用与 undici 一致);HTTP 目标直接返回原始 socket。SOCKS4_IPV6_UNSUPPORTED,绝不静默直连。userId/password)传递,可来自 URL user:pass@ 或 username/password 字段;密码错误会明确失败。http(s) 路径由 SocksHttpAgent/SocksHttpsAgent(同一隧道原语)覆盖。规则按数组顺序匹配,首条命中的规则生效:
host:port 等更精确的模式缩小范围。例如 provider 为 openai 且 host 为两个候选之一,才命中这条规则:
- host: [api.openai.com, gateway.example.com]
provider: [openai]
action: proxy
proxy: v2ray-socks
| 动作 | 含义 |
|---|---|
direct |
只直连,不使用代理 |
proxy |
强制使用指定具名代理 |
fallback |
先直连;满足安全条件时在连接前失败或健康记忆触发后改用代理 |
block |
本地拒绝请求(NETWORK_BLOCKED) |
引用不存在或当前不可用的代理名会 fail loud(UNKNOWN_PROXY),不会静默降级直连;source: system|env 当前没有可用代理时,只有未选择该代理的请求可以继续。
全局 fetch 只能可靠看到目标 URL,无法自动判断任意请求来自哪个 Cordis 插件。调用方必须显式使用插件服务:
await ctx.networkRoute.run(
{ provider: 'openai', plugin: 'my-plugin' },
() => fetch('https://api.openai.com/v1/models'),
)
流式响应(SSE)的归属:als.run(meta, () => iterable) 不会让后续迭代保留上下文——next() 在调用方自己的异步上下文里执行,currentRoute() 会丢。对惰性消费的流,用 ctx.networkRoute.iterable(route, stream) 包装:next / return / throw 每次都会在 als.run(route, ...) 内调用,abort(return)与异常(throw)同样保留归属:
const attributed = ctx.networkRoute.iterable(
{ provider: 'openai' },
response.body, // 或任意 async iterable(含 llm/stream 适配器的异步迭代器)
)
for await (const chunk of attributed) { /* currentRoute() 可见 */ }
DSH llm/stream 集成应包装异步迭代器的 next / return / throw 生命周期,使惰性 SSE 消费期间仍保留 provider/model 上下文。
trustRouteHeaders 默认关闭。若开启,可读取 x-dsh-route-provider 与 x-dsh-route-plugin。无论是否信任,这些内部路由控制头都会在发出请求前被自动剥离,不会泄漏给 API 上游(fetch 与 node http(s) 两条路径都已处理)。
自动回退不是普通重试。为避免重复创建 LLM 请求或重复计费:
GET、HEAD、OPTIONS、TRACE 自动换路;POST 默认不重放;onConnect 已发生后的 socket 错误属于不确定状态,默认不重试。延迟阈值使用到响应头的观测值记录 EWMA;连接失败进入有上限的 cooldown。主动健康探测默认关闭,避免插件启动时自行访问外网。
安全默认(protectLocal / protectPrivate,均可关闭)让 localhost、loopback、169.254.0.0/16、云 metadata 端点、RFC1918 内网和 IPv6 ULA(fc00::/7、fe80::/10)一律直连,所以"全部走代理"的配置也不会把内网/metadata 流量交给外部代理。
noProxy 与 NO_PROXY / no_proxy 支持:
*:全部直连;example.com / .example.com / *.example.com:精确或后缀;10.0.0.0/8、fc00::/7:IPv4/IPv6 CIDR;127.0.0.1:8080、example.com:443:host:port(端口必须一致才命中);不要把内网、metadata 或带明文凭据的 HTTP API 交给不受信任的代理。
代理 URL 可以包含凭据,但日志只能显示 http://***@proxy.example:8080。插件不得记录 API Authorization、请求 body 或代理密码。具名代理可设置 passwordRef(环境变量风格标识符,如 DSH_PROXY_OFFICE_PASSWORD),插件通过 DSH credentials.resolve() 在运行时取值,并在该引用更新时重载代理;缺少凭据服务或引用未配置会明确失败。passwordRef 与明文 password 不能同时设置。
实现上,URL 里的凭据(或 username/password 字段)会在解析时剥离:交给 undici ProxyAgent / http(s)-proxy-agent 的 URL 不再含用户信息,认证改由 Proxy-Authorization(undici token、node agent headers 选项)或 SOCKS 握手(userId/password)注入。SOCKS 路径使用插件自研 agent,不做任何 URL 调试输出。npm test 含 DEBUG=* 泄漏测试:stderr 不得出现代理凭据、URL 形式或上游 Bearer token。
残余(依赖固有):明文 HTTP 请求经
http-proxy-agent且进程开启DEBUG=*时,依赖会把该请求的完整请求头(含上游Authorization)dump 到 stderr;https 请求的内层头在 TLS 内不受影响。仍建议不要在包含真实 key 的生产进程里开启通配DEBUG=*。
路由策略对重定向链的每一跳重新计算(redirect: "manual" + 手动跟随):代理请求被 30x 引向内网或 metadata 地址时,下一跳会按规则命中 direct/block,不会继续走外部代理。调用方显式请求 redirect: "manual" 时原样返回 3xx;redirect: "error" 时抛出。默认最多跟随 20 跳。
插件不暴露任何裸 HTTP 状态端点。状态通过两个受控表面提供,返回的都是纯 JSON、只含脱敏信息(代理 URL 用 *** 掩码、健康表按上限采样、无凭据/请求数据/句柄):
systemProxyStatus(总是可用):其他宿主插件可 ctx.get("systemProxyStatus").status()。systemProxyStatus / method status,由 DSH 的 typert 网关作为 Remote 服务。manifest 的 disposer 绑定在插件自身的 fiber 上——热重载时先撤销旧注册再注册,避免重复端点。{
"plugin": "dsh-system-proxy",
"version": "0.2.0",
"enabled": true,
"patchNodeHttp": true,
"proxies": [{ "name": "default", "scheme": "http", "url": "http://***@127.0.0.1:7890" }],
"strategy": "fallback",
"fallback": { "directTimeoutMs": 3000, "latencyThresholdMs": 1500, "cooldownMs": 60000, "methods": ["GET","HEAD","OPTIONS","TRACE"] },
"health": { "api.openai.com": { "ewmaMs": 820.4, "proxyEwmaMs": null, "failures": 0, "coolingDown": false } }
}
fallback 的"延迟阈值"基于到响应头的观测 EWMA 决定后续请求选路;不会在 SSE 已开始后中断线路。healthMaxEntries 可调,LRU 淘汰)。DEBUG=* 时,http-proxy-agent 依赖会 dump 上游请求头(见"凭据与日志安全")。npm install
npm test
覆盖:规则/配置/健康单元测试(含 CIDR、*、host:port、IPv6、健康表上限)、旧版兼容、多代理路由、provider 作用域、路由头剥离、block、fallback 安全重放(GET 重放 / POST 不重放)、socks4/4a/5/5h 在 fetch 与 node http 双路径(含 DNS 语义与 SSE/backpressure/abort)、逐跳重定向、内网与 metadata 默认保护、node (url,cb)/(options,cb)/get 全调用形式、热重载无连接泄漏、dispose 不打断在途请求、ALS 异步迭代器上下文、真实 Cordis loader 挂载与热重载。测试使用本地直连服务器、HTTP CONNECT 代理和 SOCKS 测试服务,不需要访问外部 API。
以下项目已核验真实存在,但解决的是观测、诊断、端点修复或模型层 fallback,不等同于本插件的传输层网络路由:
不引用无法公开验证的 dsh-external/* 地址。
本项目是社区维护的非官方开源插件,与 DeepSeek、DeepSeek Harness 及其关联方不存在隶属、授权、背书或商业合作关系。项目名称及第三方商标仅用于说明兼容对象,其权利归各自权利人所有。
本软件按“原样”(AS IS)提供,不承诺适销性、特定用途适用性、持续可用性、安全性或无错误。代理配置会影响 DSH 主进程的网络流量;错误的路由、凭据或第三方代理可能导致请求失败、信息泄露、额外费用、账号限制或其他损失。使用者应自行审查源码与配置,只使用可信代理,遵守所在地法律、服务条款及网络管理政策,并自行承担部署和使用风险。在法律允许的最大范围内,作者及贡献者不对因使用或无法使用本软件产生的任何索赔、损害或责任负责。若本节与 MIT License 冲突,以 MIT License 英文原文为准。
This is an unofficial, community-maintained open-source plugin. It is not affiliated with, authorized, endorsed, or sponsored by DeepSeek, DeepSeek Harness, or their affiliates. Project names and third-party trademarks are used only to identify compatibility and remain the property of their respective owners.
The software is provided “AS IS,” without warranties of merchantability, fitness for a particular purpose, availability, security, or error-free operation. Proxy configuration affects traffic from the DSH Host process; incorrect routes, credentials, or untrusted proxies may cause failed requests, data exposure, additional charges, account restrictions, or other loss. You are responsible for reviewing the code and configuration, using trusted proxies, complying with applicable law, service terms, and network policies, and accepting all deployment and usage risks. To the maximum extent permitted by law, the authors and contributors are not liable for claims, damages, or other liability arising from use of or inability to use this software. If this section conflicts with the MIT License, the English MIT License text controls.
本项目采用 MIT License。在保留版权声明和许可声明的前提下,你可以使用、复制、修改、合并、发布、分发、再许可及销售本软件副本。MIT License 不提供任何明示或默示担保,完整且具有法律效力的条款以仓库中的 LICENSE 英文原文为准。
This project is licensed under the MIT License. You may use, copy, modify, merge, publish, distribute, sublicense, and sell copies, provided that the copyright and permission notices are retained. The license provides no express or implied warranty. See LICENSE for the complete controlling text.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。