dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
A DeepSeek Harness plugin for Windows: writes a self-contained one-click launcher, and refuses to start a second instance when the target port already serves one. / 一个 Windows 专用的 DeepSeek Harness 插件:写入自包含的一键启动器;目标端口已有 Harness 实例时拒绝启动第二个。
English | 中文
随时切换生成的启动器语言 —— /launch --lang zh、/launch --lang en,或 /launch --lang auto 跟随控制台。
一个 Windows 专用的 DeepSeek Harness 插件:在你的桌面写入一个自包含的一键启动器(.bat),
并在目标端口已经有 Harness 实例时拒绝启动第二个实例。
它写出的启动器不会引用本插件。卸载插件后,桌面上的 .bat 照常可用——它就是一个文件,
需要的东西全都写在里面。
插件市场的热挂载只接受纯 insert 的 bundle patch,所以本插件在你点下"安装"的那一刻就已经生效——
启动器也就是这时候出现的。只有桌面上没有启动器时才会创建:已经存在的(不管是你自己写的还是本插件
旧版写的)一律原样保留,因为"插件加载"不是你的决定。想让它安静加载,把 provisionOnLoad 设为 false。
启动器里记录着写它的插件版本。当本插件的新版本加载时发现启动器是旧版写的,就会用当前模板重写这个文件—— 修好的文案、修好的代码页路径就是这样到达桌面的,而不是只停留在仓库里。
重写的是那一个启动器:里面记录的端口、工作区、启动方式、语言、浏览器行为全部沿用,
所以刷新模板永远不会搬动你的设置。改设置仍然是显式的 /launch。把 autoUpdate 设为 false
可以让文件冻结;doctor 仍然会报告它已过期。
有两件事刻意不碰:版本已匹配的启动器,以及版本读不出来的启动器——靠猜是手工修改被覆盖的原因。
另外,启动器每次运行都会用最新的 harness:npx @deepseek-ai/dsh 每次都会解析已发布的版本,
而不是钉死在写文件时的那个版本。
launcher_install 按 Windows 自己的定义解析你的桌面目录(包括被 OneDrive 重定向或本地化的
桌面文件夹),确认该目录可以新建文件,按控制台代码页编码启动器,原子写入,
然后用试运行模式把它真正跑一次,证明它能被解析、能走到自己的逻辑。
自检不通过的启动器会被回滚,不会留在桌面上。
之后每次双击生成的启动器,它都会:
node 能运行、启动命令(npx 或 dsh)有响应;只有第一种情况会启动任何东西。没有任何参数能启动第二个实例。
dsh web 每次启动都会生成进程级的访问令牌,并打印带上它的完整地址;服务器对任何
未认证请求都回答 401 dsh web authentication required。所以实例已经在跑时,直接打开
http://127.0.0.1:3080 看到的是一张 401 页面而不是你的会话——而启动第二个实例本来也会
在绑定端口时失败。端口被占用时,启动器只有两个诚实的选项,本插件选第二个:
告诉你该用哪个地址,然后什么都不启动。
指纹就是那个 401 响应体,所以「这是个 Harness 实例」是检测出来的而不是假设的—— 占用端口的是别的程序时,就会如实报告成别的程序,并附上 PID。
dsh plugin --profile web add dsh-launch-in-one-click
或者直接从仓库安装:
dsh plugin --profile web add github:233fxr-collab/dsh-launch-in-one-click
从你的 profile 里删掉这一行即可卸载。已经生成的启动器照常可用——它们是自包含的。
三个工具,外加一个斜杠命令。
| 工具 | 作用 |
|---|---|
launcher_doctor | 只读诊断。报告 Node、npx、控制台代码页、解析出的桌面目录、它是否可写、目标端口被谁占用、npx 缓存里是哪个 harness 版本、以及已安装启动器的状态。可选地在试运行模式下运行已安装的启动器,或向 registry 查询已发布版本。 |
launcher_install | 写入启动器(原子写入、先备份、自检)。 |
launcher_uninstall | 删除本插件写的启动器以及它的备份。不是它写的文件默认拒绝删除,除非加 force。 |
/launch 用部署默认值安装
/launch doctor 等同于 launcher_doctor 的报告
/launch list 列出本插件放到桌面上的每一个启动器及其设置
/launch --port 3111 换一个端口启动
/launch --lang zh 用中文写入启动器(--lang en | --lang auto)
/launch --name "Work.bat" 指定文件名
/launch --overwrite 覆盖一个不是本插件写的文件
/launch --dry-run 只显示将要写入的内容
--language 是 --lang 的完整写法。切换语言会重写本插件写出的那个启动器(保留带时间戳的备份),
其余部分不变:端口、工作区、启动方式都保持原样。
| 参数 | 作用 |
|---|---|
--port N | 换端口启动 |
--workdir DIR | 换工作区 |
--no-open | 不自动打开浏览器 |
--silent | 不显示控制台窗口启动,过程写进日志 |
--dry-run | 只检查并打印计划,不启动 |
--help | 显示帮助 |
%LOCALAPPDATA%\dsh-launch\launcher.log 记录启动器做过的判断——环境检查、工作区、端口结论、
要执行的命令、退出码——因为控制台窗口一关就什么都看不到了。--silent 完全没有窗口,写的也是它。
失败退出时会打印日志路径。
启动器本身接受 --port N、--workdir DIR、--no-open、--dry-run、--help。
退出码就是启动器的契约:快捷方式包装脚本或计划任务可以直接据此分支, 不需要解析本地化文本。
| 退出码 | 含义 |
|---|---|
| 0 | 服务正常运行并正常退出,或试运行打印了将要执行的命令 |
| 1 | 找不到 node 或启动命令 |
| 2 | 端口上已有 Harness 实例——没有启动任何东西 |
| 3 | 端口被其它程序占用——没有启动任何东西 |
| 4 | 参数非法 |
| 5 | 工作目录不存在或无法进入 |
| 9 | 端口探测没有得出结论 |
| 20 | Harness 自身启动失败,它自己的退出码打印在上面 |
可选,写在 bundle 的 patch 行里:
- id: launch-in-one-click
name: dsh-launch-in-one-click
config:
defaultPort: 3080 # 生成的启动器使用的端口
language: auto # auto | en | zh
runner: npx # npx | dsh
packageSpec: '@deepseek-ai/dsh' # npx 解析的包名
openBrowser: true # 是否让 `dsh web` 自己打开浏览器
provisionOnLoad: true # 加载时创建启动器(仅当桌面没有时)
autoUpdate: true # 用旧版启动器时自动刷新为当前模板
⚠️ 在这里加 config: 行是有代价的。 市场只热挂载纯 id/name insert,所以带配置的 bundle patch
要等下次重启才生效,而不是点完即生效。这也是上面所有默认值都写在代码里而不是这个文件里的原因:
一行配置都不加地安装,启动器照样在你点"安装"的那一刻出现。
%USERPROFILE%\Desktop 解析。指向不存在目录的来源会被跳过,而不是被信任。auto(默认)跟随控制台:支持中文的代码页得到中文,英文控制台得到英文且不产生
任何警告,因为"贴住控制台"本身就是目的,不是回退。显式指定 language: zh 时,即使控制台
打不出中文也会照做——改用 UTF-8 写入并把控制台切过去。|、&、<、>、
^、%、(、) 或 "。cmd.exe 不知道这两个字节是一个字,于是会起一个管道、一次重定向
或一次变量展开。每个文件在写入前都会扫描这种情况。overwrite 时才会替换,并保留带时间戳的备份。force 可以强制刷新。MoveFileEx 会返回 EPERM,
因此重命名带退避重试。npx 与 npx.cmd——Node 会在 npx.cmd 旁边放一个没有扩展名的 POSIX 脚本。
路径解析优先尝试 PATHEXT 里的候选,所以 cmd 根本跑不了的那个脚本永远不会被选中。npm install --legacy-peer-deps # 只有 iconv-lite,其余都是 peer 依赖
npm test
测试共 90 项。其中最有价值的部分会生成启动器,用真实的 cmd.exe 去运行它, 并对着真实的监听者验证——一个会返回 401 指纹的假 Harness 服务、一个无关的 HTTP 服务、 以及一个空闲端口——然后断言退出码。这正是单元测试抓不到的两个缺陷的发现方式: 用裸 LF 结尾写出的文件(cmd 会把整个文件当成一行)和把代码页切换放在第一个多字节字符之后。
test/plugin.test.js 校验插件市场会检查的 manifest 约定,其中包含 peer 版本范围。
那个范围故意写得很长:
>=0.0.1-rc.1 <0.2.0-0 || >=0.1.0-rc.1 <0.2.0-0 || >=0.1.1-rc.1 <0.2.0-0 ||
>=0.1.2-alpha.1 <0.2.0-0 || >=0.1.3-alpha.1 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0
node-semver 只有在范围里某个比较符与该版本的 major.minor.patch 元组完全一致、
且自身也带预发布标签时,才会放行预发布版本。所以看起来宽松的范围——比如
>=0.0.1-rc.1 <0.2.0,甚至 >=0.0.0-0——都会排除掉已发布的每一个 0.1.x 预发布版本,
用户会遇到需要手工绕过的 ERESOLVE。上面这种枚举写法覆盖了每一条已发布的线;
测试会断言本机安装的 harness 版本所在的元组就在其中。
当 harness 的包可以解析时,同一个文件还会用真实的 defineTool 编译器校验每个工具 schema,
否则会报告跳过。
npx 启动方式需要 Node 自带 npx;若设置 runner: dsh,则需要已安装的 dsh 命令。MIT