deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
中文 | English
DSH(DeepSeek Harness)远程 Web 启动 + 用户名/密码认证插件。
⚠️ 版本跟进声明:本项目只跟进官方 dsh 的正式发布通道(
nextdist-tag),不跟进alpha预览通道(当前基线:dsh 0.2.0-rc.1,依赖 5 个@deepseek-ai/dsh-*已 bump 到^0.2.0-rc.1;适配审查与观察哨见docs/upgrade-dsh-0.2.0-playbook.md)。

原版 @deepseek-ai/dsh-web-app/startup 出于安全考虑硬拒绝 --host 0.0.0.0;本插件替换它,并配一个带登录/注册页的认证插件,让 dsh web 可以在局域网(或任何非回环接口)上安全暴露浏览器界面。
--host 0.0.0.0 可用,替代原版启动器的硬性拒绝;--host ::(或任意 IPv6 字面量,如 ::1、fd00::1)同样可用(#35;非规范拼写自动规范化,带 zone 的(%eth0)与 IPv4-mapped(::ffff:a.b.c.d)写法拒绝)。纯 IPv6 网络下 0.0.0.0 只绑 IPv4、界面不可达;:: 在 Linux 默认双栈(net.ipv6.bindv6only=0),同时监听 IPv6 与 IPv4-mapped,比 0.0.0.0 覆盖更全;bindv6only=1 的系统上 :: 仅 IPv6。prefers-color-scheme)。Host 头都是回环时才免认证。所以本机浏览器直接访问 http://127.0.0.1:<端口>/ 无需注册或登录;局域网客户端、以及反向代理转发来的请求(Host 是公网域名)一律需要会话。免登录不等于已登录:本机没有会话 cookie,认证页显示的是「管理员账号」而不是「当前登录」,也不会给出退出登录入口(没有会话可退)。Retry-After。本机(真回环且未开启「本机登录校验」)豁免全局退避,避免攻击者借此把管理员锁在自己机器外面。dsh_sid,默认 14 天有效、可在设置面板调节(3–180 天档位),HttpOnly + SameSite=Lax)。/api/* 及第三方插件的 RPC 路由,除 /api/auth/* 与 /login)必须携带有效会话,否则返回 401/拒绝握手。crypto.randomUUID polyfill —— 非安全上下文下该 API 缺失,会导致所有 RPC 失败。dsh-auth-* 签名 cookie),/api 与 index.html 一律要求携带、连回环都不豁免(本机也得先换 token URL)。本插件为已通过自己认证(dsh_sid 会话,或 TCP 对端 + Host 双回环的本地请求)的访问者自动补发该 cookie:页面导航经一次 200 跳板(meta refresh 回原路径)即带上、登录响应直接下发(不用 3xx:重定向响应里新设的 cookie 不会带给重定向目标,补发会被逐跳重放成 ERR_TOO_MANY_REDIRECTS),全程无需接触启动打印的 token URL——「账号/密码 + 可撤销会话」仍是唯一认证入口,上游 cookie 只是通过上游闸门的凭据。本插件是一个 DSH bundle(package.json 的 dsh.bundle.patch 声明了随包分发的 cordis.patch.yml)。用 dsh plugin 安装后,包会被加入 profile 的 dsh.profile.bundles,补丁层自动生效,无需手动编辑任何配置文件。
# 方式一:从源码安装
git clone <仓库地址>
cd dsh-web-startup-auth
npm install # 安装构建依赖(typescript 等)
npm run build # 编译 src/ 到 lib/(插件运行时加载 lib/ 下的产物)
dsh plugin --profile web add .
# 方式二:从 npm registry 安装(已装过旧版本时执行同一条命令即可升级)
dsh plugin --profile web add dsh-web-startup-auth@latest
dsh plugin是 pnpm 转发器,--profile <name>必填;add .会把当前目录以link:方式装进 profile。
版本范围:本插件声明支持 dsh
>=0.1.7-rc.1、不支持0.3.0起的版本线(含其预发布版)。运行中的 dsh 超出范围时,dsh 会跳过本 bundle 并打印原因——这是刻意的 fail-loud:宁可不加载,也不在未适配验证过的 dsh minor 版本线上静默运行。注意粒度是 minor 线:同一条线内的后续版本(含 rc 等预发布)会照常加载,每出一条新 minor 线要先完成适配再考虑放宽范围。确需强行启用可走 profile 的 version exemption(插件管理器文档)。
启动:
dsh web --host 0.0.0.0
# 纯 IPv6 网络(或想同时覆盖 IPv6):
dsh web --host :: --port 8080
安装时已自动应用补丁,无需再用
--patch叠加——重复叠加会把插件再插入一遍,导致重复。
http://<主机IP>:<端口>/(在本机则用 http://127.0.0.1:<端口>/,无需登录)。IPv6 地址在 URL 中必须加方括号:http://[<IPv6地址>]:<端口>/。注意:--host :: 启动时终端只打印回环 URL(上游的 LAN 地址推导只枚举 IPv4),局域网 IPv6 地址请用上面的形式手动拼接;打印的回环 URL 固定是 http://127.0.0.1:<端口>/(上游硬编码),bindv6only=1 的系统上 :: 是纯 IPv6 套接字、它不通,本机请用 http://[::1]:<端口>/。/login,显示"设置管理员账号密码"注册表单。/api/auth/logout 清除会话 cookie)。如果需要在本地设置账号密码(本机默认免登录,界面不会自动跳登录页):
http://127.0.0.1:<端口>/login —— 未注册时该页直接显示注册表单。注册后本机仍免登录;想让本机也要登录,到认证 → 登录要求打开「本机登录校验」(需先有账号)。开关打开后本机也要走 /login(页面会立即跳过去),登录后认证页才会显示「当前登录」和退出登录入口。
凭据与会话密钥保存在 $DSH_HOME/web-auth.json($DSH_HOME 未设置时即 ~/.dsh/web-auth.json,与 dsh 自身数据同目录;可用环境变量 DSH_WEB_AUTH_FILE 覆盖整个路径):
sessionMaxAgeDays,默认 14)也存在这个文件里,可在设置面板调节;调整只对新签发的会话生效。dsh --profile web auth-reset,交互式设置新密码(或 dsh --profile web auth-reset --password <新密码> 非交互)。重置会轮换会话密钥,所有已登录的浏览器都需要重新登录一次。dsh --profile web auth-reset --username <新用户名>(可与 --password 同用)。同样轮换会话密钥。用户名在注册/登录/修改时统一剥除 C0 控制字符(0x00–0x1F)与 DEL(0x7F)——旧版本若已把含 DEL 的用户名原样存盘,用它即可修复。$DSH_HOME/web-auth.json,默认 ~/.dsh/web-auth.json)并重启,即可重新注册。这只影响登录状态——已登录的浏览器需要再登录一次,不会删除任何会话记录或历史数据(它们存在 ~/.dsh/sessions/ 等位置,与本文件无关)。auth-reset 不能用来首次创建账号:它要求已有凭据,否则报「尚未注册管理员账号,无需重置」。首次只能用上面的注册页。如果您在寻找开箱即用的专为 Agent 时代研发的 IDE,推荐您使用 Omniterm
crypto.scryptSync,无第三方依赖。dsh_sid 是自包含签名 cookie,/api/auth/logout 只清除浏览器一侧的 cookie。cookie 一旦泄露(如明文 HTTP 下被嗅探),在有效期内无法单独吊销(上限即设置面板所选的会话有效期档位)。例外:dsh --profile web auth-reset、设置面板的「修改密码」与「修改用户名」都会轮换会话密钥,一次性让所有已登录的浏览器重新登录(操作者自己的当前会话由服务端重新签发,保持登录)。/api/auth/login、/api/auth/change-password 与 /api/auth/change-username(旧密码/当前密码错误同样计次)。如需更严格防护请在反向代理层增加通用限速。connection/request 扩展点上的会话闸门。两层互为保险:上游接口变化导致其中一层失效时,另一层仍保证只有可撤销的会话(或真本机回环)能访问 API——30 天不可单独吊销的上游原生 cookie 永远不能单独作为 API 凭据。$DSH_HOME/web-auth.json(默认 ~/.dsh/web-auth.json;含密码哈希与会话签名密钥)以 0600 保存,目录以 0700 创建;插件启动时会自动修复旧版本遗留的过宽权限。--trusted-host:该参数仅为与原版 CLI 兼容而保留透传,不参与本插件认证判断——远程客户端一律需要有效会话,不存在"受信主机免登录"。127.0.0.1,由代理做 SSL 卸载并转发。此时代理必须转发真实 Host(nginx 默认即为 proxy_set_header Host $host;,配上 --trusted-host <域名> 让 DSH 自身的 Host 围栏放行);认证通过后插件按请求的真实 Host(公网域名)补发上游原生浏览器 cookie,上游闸门据此放行。反之,若代理把 Host 写死成 127.0.0.1,插件会认为请求来自本机从而放行全部流量、不做认证——不要这样配置。X-Forwarded-For 不被采信(客户端可伪造),信任判定只看 TCP 对端地址与 Host。connection.isLoopback,远程浏览器下的 settings mirror 走内存模式、插件配置卡片与 Models 页不可用;本插件当时通过 webServer.tapIndex 注入脚本在 connection 激活瞬间把该标志覆盖为恒 true。0.1.2 上游引入真实 cookie 认证后能进 UI,但 settings mirror 仍按同一标志判定——LAN 浏览器依旧得到从不读 host 的 memory mirror,设置面板的 Models(提供方目录)会报 "settings are unavailable in this browser"。直接恢复旧的 getter 覆盖会破坏 web boot(A/B 实测 26 个前端插件 pending),因此 0.1.2 起改用注入 window.__DSH_TRANSPORT__ = { ownsHost: true }:connection client 构造时据此把 isLoopback 报为 true(api/rpc 字段缺省时安全回退,且不重写 cordis 服务),LAN 与回环浏览器的全部设置面(含 Models)都正常渲染。当前保留的浏览器侧 shim:该 transport hook 与 crypto.randomUUID polyfill(明文 HTTP 非安全上下文所需)。npm install
npm run typecheck # tsc --noEmit
npm test # vitest
npm run build # tsc -p tsconfig.json + tsdown,产物输出到 lib/
tsc 编译 node 侧源码(src/*.ts)与类型声明到 lib/、lib/types/。tsdown 把前端插件(src/client/index.tsx)打包成浏览器 bundle lib/client.js(window.__ModuleLoader__.load 注册格式)。改前端代码后必须重新构建,profile 里 link: 安装会自动加载新产物。@deepseek-ai/dsh-client-* 包只用于类型与构建,运行时由 DSH 前端模块表提供。CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。