← 返回列表
需源码安装
🐾 deepseek-harness-lan
暂不能直接安装(需源码编译或环境不满足):仓库缺少 package.json,无法用 dsh 插件安装命令安装。 · 最近上游提交 2026/9/6 · 已提供中文文档
Run DeepSeek Harness Web UI on your home LAN — 4 minimal patches + one-click apply/revert scripts | 让 DeepSeek Harness 的 Web UI 在局域网跑起来
综合分
33
GitHub 分
33
用户评分
—
★ Stars
6
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add oitsukiii/deepseek-harness-lan仓库缺少 package.json,无法用 dsh 插件安装命令安装,改用 GitHub 源安装
数据截至 2026/9/17(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查需源码安装
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包deepseek-harness-lan(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明
仓库缺少 package.json,无法用 dsh 插件安装命令安装
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/18 17:00:38
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
🐾 deepseek-harness-lan
Run DeepSeek Harness Web UI on your home LAN — bind a specific IP, trust it, and open it from any device.
让 DeepSeek Harness 的 Web UI 在局域网里跑起来——从 Windows / 手机 / 平板直接打开。
License
dsh
built-with
🎯 目标版本:dsh 0.1.2-rc.1(commit a66e470204) —— 补丁基于该版本编写并验证,其他版本可能失效(详见 🧩 兼容性)。
📑 目录
- 📖 这是什么
- ✨ 特性
- 🚀 快速开始
- 🔀 备选方案:不改源码(SSH 隧道)
- 🧠 技术原理
- 🔒 安全须知(务必阅读)
- 🧩 兼容性
- 🗺️ 版本兼容矩阵
- ❓ FAQ
- 🧩 补丁文件一览
- 🤝 贡献
- 🎉 致谢
- 📜 License
📖 这是什么
dsh 的 Web UI 官方只允许本机(localhost)访问。--host 0.0.0.0 直接报错:
error: --host 0.0.0.0 is intentionally not supported yet for safety:
it would expose remote code execution to the network; use 127.0.0.1 instead
这是有意为之的安全设计——dsh 的 Web UI 背后是一个能执行任意命令的 agent,官方不想让它裸奔到网络。
但家里/办公室的局域网,想在 Windows、手机、平板上打开 dsh 怎么办?本仓库提供 3 个最小补丁 + 一键脚本,让你绑定指定局域网 IP 安全运行 dsh Web UI。
✨ 特性
- 🔧 3 个最小 diff,只改必要源码,不引入额外依赖(原 4 处 LAN 改动中有 2 处已被上游 0.1.2-rc.1 采纳:--trusted-host CLI + rpc-host.ts 里的 trustedHosts 围栏,因此这些文件不再需要打补丁)
- 📦 一键打补丁 / 一键还原(apply.sh / revert.sh),自动检测、防重复应用
- 🧩 不破坏官方安全模型:0.0.0.0 通配符仍被拒绝;--trusted-host 显式信任机制保留
- 🧪 已在 dsh 0.1.2-rc.1 验证:完整 pnpm run build、页面加载、API 调用、特权接口全通过
- 🪄 自动补全 build 依赖(unrun),pnpm run build 不会莫名失败
🚀 快速开始
从零到跑通(共 6 步)
核心顺序一句话:先装好 dsh 源码,再跑 apply.sh 打补丁——apply.sh 是打补丁工具,不是 dsh 安装器。
① 准备环境
- Node.js ≥ 24(node -v 验证)
- pnpm(pnpm -v 验证)
- git
- 🪟 Windows 用户:bash 脚本请在 Git Bash 或 WSL 中运行;dsh 源码本身跨平台
② 获取 dsh 源码
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
⚠️ 必须是 git clone 的源码,不能用 npm install 装的成品包——补丁要改源码文件。
⚠️ 不要用 --depth 1 浅克隆(后面固定版本需要完整历史)。
当前 master 分支即目标版本 0.1.2-rc.1(commit a66e470204)。若日后上游已前进(apply.sh 会提示版本不匹配),先固定版本再继续:
git checkout a66e470204
pnpm install
③ 克隆 deepseek-harness-lan 并打补丁
git clone https://github.com/oitsukiii/deepseek-harness-lan.git
cd deepseek-harness-lan
./apply.sh /path/to/deepseek-harness
apply.sh 自动完成:版本校验 → 检查能否干净应用 → 打补丁 → 补装构建依赖 unrun。看到 ✓ 补丁应用完成 即成功。
💡 目录无关:deepseek-harness-lan 和 deepseek-harness 可以放在任意目录(任意组合)——脚本自动定位自身 patch、按参数定位 dsh 仓库,无硬编码路径。三种运行方式任选:传 dsh 路径参数、cd 到 dsh 目录再跑、或把 deepseek-harness-lan 放在 dsh 旁边。
④ 重新构建前端
cd /path/to/deepseek-harness
pnpm run build
randomUUID polyfill 在 web 产物里,必须重新构建才生效。
⑤ 启动并绑定局域网 IP
pnpm dsh web --host 192.168.1.100 --trusted-host 192.168.1.100
把 192.168.1.100 换成你的局域网 IP(ip addr 或路由器后台查看)。
⑥ 访问与验证
在其他设备(Windows / 手机 / 平板)浏览器打开:
http://192.168.1.100:3080
⚠️ 若之前打开过,请 Ctrl + F5 强制刷新(浏览器可能缓存旧 JS)。
验证清单:
- [ ] 页面正常加载,标题 "DeepSeek Harness"
- [ ] 配置模型 API 不报 403 / crypto.randomUUID is not a function
- [ ] 局域网其他设备也能打开
还原(可选)
./revert.sh /path/to/deepseek-harness
一键移除补丁,之后可正常 git pull 更新 dsh。
🔀 备选方案:不改源码(SSH 隧道)
如果你不想改 dsh 源码(想保持官方原样、官方升级零维护),SSH 隧道是唯一干净的局域网访问方式——零补丁,三道闸天然全通。
原理(为什么不用打补丁)
dsh 的信任检查(browser-trust)看的是请求的 Host 头,不是来源 IP(DNS rebinding 防御);而 crypto.randomUUID 只在 secure context(HTTPS 或 localhost)可用。SSH 隧道让浏览器始终以 127.0.0.1 访问 dsh,于是:
| 三道闸 | SSH 隧道下 | 为什么 |
|---|---|---|
| 闸 1(CLI/schema) | ✅ 不触发 | dsh 监听 127.0.0.1 = 官方默认值,无需改动 |
| 闸 2(browser-trust) | ✅ 含特权接口 | Host 头 = 127.0.0.1 → loopback 豁免(原版特权接口也只放行 loopback) |
| 闸 3(randomUUID) | ✅ 可用 | 127.0.0.1 属于 secure context,浏览器原生提供 |
步骤
1. 按官方原样启动 dsh(不打补丁,监听 127.0.0.1:3080)
cd /path/to/deepseek-harness
pnpm dsh web
在需要访问的电脑上开隧道(Windows 10/11 自带 OpenSSH):
ssh -N -L 3080:127.0.0.1:3080 @
浏览器打开:
http://127.0.0.1:3080
配置 API、特权接口、全部功能均可正常使用。
对比
| 方案 | 改源码 | 电脑 | 手机/平板 | 官方升级 |
|---|---|---|---|---|
| SSH 隧道(本方案) | ❌ 零改动 | ✅ | ⚠️ 每台设备配隧道 | 直接 git pull,无感 |
| deepseek-harness-lan 补丁(主方案) | ✅ 4 处最小 diff | ✅ | ✅ 直接开网址 | 需重新打补丁 |
为什么 nginx 反代不行
反代(无论 HTTP 还是 HTTPS)后 Host 头变成局域网 IP,而原版特权接口(settings.describe、llm.providers 等——配置模型 API 必需)是 isTrustedApiRequest(request, []) 强制只放行 loopback,所以配置 API 那步必然 403。SSH 隧道是唯一"不改源码且功能完整"的路径;想全设备直接开网址访问,就用主方案的补丁。
🧠 技术原理
dsh 官方阻止局域网访问,一共有 三道闸。本项目的 3 个补丁逐个击破:
闸 1:CLI 拒绝 0.0.0.0,schema 只认两个字面量
现象:--host 0.0.0.0 直接报错;想绑具体 IP(如 192.168.1.100)也会启动失败:
ValidationError: invalid config:
- $.host expected "127.0.0.1" | "0.0.0.0" but got "192.168.1.100" (at host)
原因(两层限制):
| 层 | 位置 | 限制 |
|---|---|---|
| CLI 层 | packages/bundle/web-app/src/startup.ts | options.host === '0.0.0.0' 时 program.error() 拒绝启动 |
| Schema 层 | packages/host/webserver/src/index.ts | zod 校验 z.union([z.const('127.0.0.1'), z.const('0.0.0.0')]),类型定义也只允许这两个值 |
补丁(packages/host/webserver/src/index.ts,放宽 schema):
- host: '127.0.0.1' | '0.0.0.0' // 类型
+ host: string
- host: z.union([z.const('127.0.0.1'), z.const('0.0.0.0')]).required() // zod
+ host: z.string().required()
📌 0.1.2-rc.1 说明:CLI 层(startup.ts)的 --host 0.0.0.0 拒绝逻辑上游仍保留,但无需再补——它只拒绝通配符,不影响绑定具体局域网 IP;该文件不再出现在补丁中。
设计取舍:0.0.0.0 通配符绑定所有网卡(包括公网/WG),危险;绑定具体 IP 只暴露一个网卡,可控。所以只放开具体 IP,通配符继续拒绝。
闸 2:/api 的 browser-trust 围栏(403)
现象:页面能打开,但所有 /api/ 请求返回 HTTP 403,例如:
加载提供方目录失败: transport failure for /api/llm.providers: HTTP 403
原因:dsh 的 /api 网关前有一道 browser-trust fence(防 DNS rebinding / 跨站攻击),packages/client/connection/src/index.ts 里:
// 信任列表:只有绑 0.0.0.0 时才自动采集所有局域网 IP
// 绑具体 IP 时列表为空 → 非 localhost 请求全 403
const lanAddresses = bindHost === ALL_INTERFACES_HOST ? collectLanIps() : []
return { lanAddresses, trustedHosts: [...lanAddresses, ...extra] }
另外,特权方法(settings.、credentials.、agentPreset. 等)用的是空信任列表检查——意味着即使加了 --trusted-host,这些接口依然只放行 localhost:
if (PRIVILEGED_METHODS.has(method) && !isTrustedApiRequest(request, [])) {
return new Response('forbidden', { status: 403 })
}
补丁:0.1.2-rc.1 起无需补丁——本闸已被上游采纳。packages/client/connection/src/rpc-host.ts 现检查 this.trustedHosts(由 CLI 的 --trusted-host 配置)而非空列表,因此 --trusted-host 已对特权接口生效。本仓库因此不再修改 packages/client/connection/src/index.ts;补丁文件只覆盖其余 3 个文件。
设计取舍(上游采纳后的语义):--trusted-host(管理员显式配置的信任入口)对特权接口生效。不传 --trusted-host 时行为不变,仍只放行 localhost——官方安全语义原样保留。
闸 3:crypto.randomUUID is not a function
现象:配置 API 时报错:
加载提供方目录失败: crypto.randomUUID is not a function
原因:浏览器 Web Crypto API 的 crypto.randomUUID() 只在 secure context(HTTPS 或 localhost)可用。用 http://192.168.1.100:3080(局域网明文 HTTP)访问时,这个函数不存在。
补丁(apps/web/src/main.ts,Web 入口最前面):
// crypto.randomUUID 仅 secure context 可用;HTTP 局域网环境补一个 UUIDv4 实现
if (typeof globalThis.crypto === 'object' && typeof globalThis.crypto.randomUUID !== 'function') {
try {
globalThis.crypto.randomUUID = () =>
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0
const v = c === 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
} catch { /* crypto 只读环境则保持原样 / }
}
💡 UUID 只用于本地标识(附件草稿、会话 id 等),不涉及安全校验,polyfill 无安全风险。
🔒 安全须知(务必阅读)
- ⚠️ 这个界面能执行任意命令。打补丁后,局域网内任何设备都能访问并控制你的 agent。
- ✅ 只应在信任的家庭/办公网络使用。
- ❌ 不要把 3080 端口映射到公网(port forwarding / DMZ)。
- ❌ 不要用 --host 0.0.0.0(补丁后依然被拒绝,这是有意保留的防线)。
- 💡 进阶:可以在 dsh 前面再套一层带认证的反向代理(如 nginx Basic Auth)。
- 🔐 --trusted-host 是官方 browser-trust 机制的显式信任入口,请只填你自己的局域网 IP。
🧩 兼容性
本补丁针对 dsh 0.1.2-rc.1(commit a66e470204)编写并验证。
✅ 上游说明(0.1.2-rc.1):原 4 处 LAN 改动中有 2 处已被上游采纳——CLI 现已支持 --trusted-host,packages/client/connection/src/rpc-host.ts 检查 this.trustedHosts 而非空列表——因此当前补丁集精简为 3 个文件:
1. packages/host/webserver/src/index.ts — 把绑定 host 的 schema 从两个字面量(127.0.0.1/0.0.0.0)放宽为 string(支持局域网 IP);
2. apps/web/src/main.ts — 明文 HTTP 局域网场景下的 crypto.randomUUID polyfill;
3. packages/client/tsdown.client.ts — REPOSITORY_ROOT 改用 process.cwd() 而非 import.meta.url(修复 tsdown 用 unrun 编译此 preset 到 node_modules/.unrun 时的工作区 manifest 查找,否则会报 no packages//*/package.json declares the name …)。
⚠️ 上游已知构建怪癖(0.1.2-rc.1):干净 checkout 上跑完整 pnpm run build 可能报 Cannot find entry: ["lib/types/{index,invariant,startup}.js"](归因于 @deepseek-ai/dsh-root)。原因:旧版 dsh 遗留目录(如 packages/client/runtime、packages/host/apiproxy)已被上游删除,但 git checkout 不会清掉它们——因为里面只有被忽略的文件(node_modules)。修复:删除遗留目录(先用 git clean -ndx 列出,再删除),然后重新构建。
- 验证链路:补丁可干净应用(git apply --check)→ 完整 pnpm run build 成功 → Web UI 页面加载 → /api 接口调用 → 特权接口(settings.describe 等)全通过。
- dsh 上游迭代很快,其他版本大概率会失效:
- 源码上下文变化时,apply.sh 的 git apply --check 会检查失败并安全中止,不会弄脏你的仓库(这是保护机制,不是 bug)。
- 适配新版本:
1. 在新版本上运行 apply.sh,失败后记录冲突文件;
2. 对照 🧠 技术原理 的"三道闸"思路手工适配;
3. 欢迎把适配后的 patch 提 PR 回本仓库。
- 还原:revert.sh 一键还原,之后可正常 git pull 更新 dsh。
🗺️ 版本兼容矩阵
一份补丁对应一个 dsh 版本线;更早/不同的版本可能 git apply --check 失败(这正是安全机制——失败即中止,不会弄脏你的仓库)。
| dsh 版本 | dsh 发布时间 | 我该用哪个补丁? |
|---|---|---|
| 0.0.1-rc.1(npm) | 2026-08-10 | — |
| 0.0.1-rc.2(npm) | 2026-08-11 | — |
| 0.0.1-rc.5(npm) | 2026-08-12 | — |
| 0.1.0-rc.2(npm) | 2026-08-13 | — |
| 0.1.0-rc.3(npm) | 2026-08-13 | — |
| 0.1.0-rc.6(npm) | 2026-08-13 | — |
| 0.1.0-rc.7(release) | 2026-08-17 | v0.1.1 |
| 0.1.0-rc.8(release) | 2026-08-19 | v0.2.0 |
| 0.1.1-rc.1(release) | 2026-08-21 | v0.2.0 |
| 0.1.1-rc.2(release) | 2026-08-21 | v0.2.0 |
| 0.1.2-rc.1(release) | 2026-08-29 | v0.3.0 ⭐ 当前(3 文件补丁;4 处 LAN 改动已有 2 处进入上游) |
💡 经验法则:rc.8 及以后的版本用当前补丁即可;rc.7 及更早需要用旧补丁或直接升级。早期版本(0.0.1-rc.x、0.1.0-rc.2/3/6)是公开发布 3 天内的过渡版本,不应有人还在使用。
❓ FAQ
Q: 手机上能访问吗?
A: 能。只要手机连同一个局域网,浏览器打开 http://:3080 即可。
Q: 打补丁后 dsh 官方更新怎么办?
A: apply.sh 会先 git apply --check,上游代码变了会检查失败并中止,不会弄脏你的仓库。还原用 revert.sh,然后正常 git pull 更新即可。
Q: 为什么不用 Docker 跑?
A: dsh 官方提供的是 Node.js / npm 包,无官方 Docker 镜像;本项目只改源码,直接沿用官方安装方式最稳。
Q: 这个补丁会被官方接受吗?
A: 官方有意禁了通配符绑定,短期内不太可能放开;但绑定具体 IP + 显式信任的思路,可以给官方提 issue 讨论。
🧩 补丁文件一览
| 文件 | 解决 |
|---|---|
| patches/deepseek-harness-lan.patch | 全部 4 处改动的统一 diff(git apply 直接用) |
🤝 贡献
- Bug / 兼容性问题:开 issue,附 dsh 版本号 + 报错信息
- 新平台 / 新版本适配:提 PR,更新补丁并在对应版本验证
- 上游 dsh 更新后失效:欢迎提交更新后的 patch
🎉 致谢
- DeepSeek Harness —— 优秀的 agent 框架("Everything is a Plugin")
- 本项目由 DeepSeek V4 Flash 驱动开发(排查 → 定位 → 打补丁 → 脚本化 → 文档全流程)
📜 License
MIT License — 与 DeepSeek Harness 官方无关的非官方社区项目,仅供学习与自用参考。扫码进群