dsh-windows-tray 1.0.13 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # dsh-windows-tray
2
2
 
3
- > DeepSeek Harness(dsh)的 Windows 系统托盘管家:**官方鲸鱼状态图标 + Web/TUI 双状态显示 + 一键启停**。
4
- > 纯 PowerShell + WinForms 实现,零依赖、无编译、不改 dsh 源码,卸载即还原。
3
+ > DeepSeek Harness(dsh)的 Windows 托盘管家:**官方鲸鱼状态图标 + Web/TUI 双状态 + 一键启停**。
4
+ > 纯 PowerShell + WinForms,零依赖、无编译、不改 dsh 源码,卸载即还原。
5
+
6
+ > **基础功能公开可用**:他人 `npm i -g dsh-windows-tray` → `dsh-tray install`;**本机自用走源码**:`pwsh -File plugins/dsh-windows-tray/install.ps1 -Auto -NoTrayStart -EnableBackup` + 重启托盘。**备份面默认关闭**(单总开关 `features.backup`,见下「功能开关」节)——包内**不含备份引擎**,启用后若缺引擎会显式显示「未就绪」并给出装法(既不假装能用、也不谎报失败)。⚠ npm 上的 1.0.13 是**引入开关之前**的版本;**源码/落盘 = 1.0.14**;`private: true` 保留到正式发布那一刻(防误发)。
5
7
 
6
8
  [![npm](https://img.shields.io/npm/v/dsh-windows-tray?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
7
9
  [![npm downloads](https://img.shields.io/npm/dm/dsh-windows-tray?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
@@ -10,13 +12,24 @@
10
12
 
11
13
  ## 是什么
12
14
 
13
- dsh 默认在终端前台运行 `dsh web`——必须留着一个命令行窗口。本工具把它变成**一个标准的 Windows 托盘应用**:
15
+ dsh 默认在终端前台跑 `dsh web`——必须留一个命令行窗口。本工具把它变成**标准 Windows 托盘应用**:
16
+
17
+ - 🐋 **状态一目了然**:蓝鲸鱼 = Web 运行中;灰鲸鱼 = 未运行(图标由官方 favicon 生成)
18
+ - 📊 **DSH / TUI 双状态**:菜单顶部同屏显示 Web 与 TUI 运行状态(含 PID),互不干扰
19
+ - 🖱️ **零窗口操作**:双击开界面,右键按 DSH/TUI 分组子菜单一键启停,不用碰命令行
20
+ - 👁️ **独立旁观者**:托盘是独立常驻进程,dsh 停止时它仍在(显示未运行 + 一键启动),退出托盘不影响 dsh
21
+ - 🎨 **浅色圆角菜单**:白底/圆角/投影,贴合现代桌面应用审美
22
+
23
+ ## 前置依赖(先读这条)
24
+
25
+ **本包只含托盘本体(UI + 菜单动作),不含备份引擎。** 菜单里的 `备份 ▸` 需要 dsh 侧的引擎 `dsh-backup.mjs`——它由 personal-docs 仓分发,**不随本包发布**。两步(都走源码仓,**不走 npm**):
14
26
 
15
- - 🐋 **状态一目了然**:品牌蓝鲸鱼 = Web 运行中;灰鲸鱼 = 未运行(图标由官方 favicon 渲染生成)
16
- - 📊 **DSH / TUI 双状态**:菜单顶部同屏显示 Web 与 TUI 各自的运行状态(含 PID),互不干扰
17
- - 🖱️ **零窗口操作**:双击开界面,右键通过 DSH / TUI 分组子菜单一键启停,不用再碰命令行
18
- - 👁️ **独立旁观者**:托盘是独立常驻进程,dsh 停止时它依然在(显示未运行 + 一键启动),退出托盘不影响 dsh
19
- - 🎨 **浅色圆角菜单**:白底、圆角、投影阴影,贴合现代桌面应用审美
27
+ 1. 装托盘:`pwsh -File plugins/dsh-windows-tray/install.ps1 -Auto -NoTrayStart`(部署后重启托盘生效)
28
+ 2. 装引擎(一次性;之后随 personal-docs 更新即可):`pwsh -File dsh/config/install.ps1 -Only tools`
29
+
30
+ 只做第 1 步,托盘本体照常可用(Web/TUI 启停、状态、自更新)。**只有「备份」面会显式显示未就绪**:状态行 `备份: 未就绪(缺备份引擎,见 README)⚠`,点「立即备份」弹气泡告知缺什么、怎么补(动作退出码 3)——**不假装成功,也不谎报"备份失败"**。
31
+
32
+ > **定位**:这是作者本人工作流的个人工具(备份对象集、库位置探测、恢复向导都按 personal-docs 约定),发布主要为跨机自用;不承诺开箱适配他人环境。
20
33
 
21
34
  ## 功能特性
22
35
 
@@ -25,22 +38,23 @@ dsh 默认在终端前台运行 `dsh web`——必须留着一个命令行窗口
25
38
  | **图标** | 蓝鲸鱼 = Web 运行中(PID);灰鲸鱼 = 未运行 |
26
39
  | **悬停提示** | `Web UI 运行中 · 127.0.0.1:3080` / `Web UI 未运行 · 右键可启动` |
27
40
  | **双击** | 打开 Web UI(未运行先提示启动) |
28
- | **右键菜单** | 顶部 `Web UI 状态` / `TUI 状态` 双状态行;`Web UI ▸`(打开 Web UI / 启动 / 停止(带确认) / 重启);`TUI ▸`(启动 / 停止);打开日志目录 / `版本信息 ▸`(版本 / 检查更新 / 更新到最新版)/ 退出托盘 |
41
+ | **右键菜单** | 顶部 `Web UI 状态`/`TUI 状态`/**`备份`** 三状态行;`Web UI ▸`(打开/启动/停止(确认)/重启);`TUI ▸`(启动/停止);**`备份 ▸`(立即备份 / 打开备份目录)**——「立即备份」四字即全部文案(括号里的对象清单太长,2026-09-22 用户裁定),动作 = data+runtime+vault 三对象各备一次;打开日志目录/`版本信息 ▸`(版本/检查更新/更新到最新版)/退出托盘 |
42
+ | **备份状态**(1.0.14,**仅当开关开时出现**) | 第三行 `备份: N h 前 ✅/⚠(对象)`:读库内 `status.json`(**只读原始 UTC 时间戳,age 读数时算**),30 s 节流(解析缓存键 = 内容本体,age 每次现算);**显示最旧对象** ⇒ 任一对象陈旧不被掩盖;异常**五文案**:未配置 / 状态文件损坏 / 从未成功 / 时钟异常 ⚠ / **上次失败 N h 前 ⚠(状态停在 M h 前)**(最近一次失败晚于最近一次成功时优先显示)。**「立即备份」有过程与结果反馈**:开始气泡 + 状态行"进行中" + 菜单置灰 + 结束气泡(成功/失败/未启用/未就绪)+ >30 分钟只提示并继续等(**不杀进程、不放开菜单**)。**设计取舍**:只做"可见 + 人工触发",不做空窗告警与自动补跑(托盘只在登录会话内存在)。**库位置不写死盘符**(2026-09-22 改):运行时按 `$env:DSH_BACKUP_STORE` > `<DSH_HOME>\backup-store.txt` > 自动发现已有库解析;都没有 ⇒ 状态行显示「未配置(首次「立即备份」会自动挑盘建库)」。**引擎 = `<DSH_HOME>\tools\dsh-backup.mjs`,来自 personal-docs 仓、不随托盘包分发** ⇒ 新机两步:① 装/更新托盘 ② `personal-docs\dsh\config\install.ps1 -Only tools`;**缺引擎时状态行显式 `备份: 未就绪(缺备份引擎,见 README)⚠`**(不承诺自动建库、不谎报失败)。恢复用引擎的 `recover`(向导)或按 SOP 手工走 |
29
43
  | **菜单智能禁用** | Web 运行中禁用「启动 Web UI」;TUI 运行中禁用「启动 TUI」 |
30
- | **自更新** | 「版本信息 ▸」子菜单(位于退出托盘上方,非日常功能区):查看版本 / 检查更新 / 一键更新到最新版(自动重部署 + 重启托盘) |
44
+ | **自更新** | 「版本信息 ▸」子菜单(在退出托盘上方,非日常功能区):查看版本/检查更新/一键更新(自动重部署+重启托盘)。它对比的是 **npm 源** ⇒ **他人(npm 安装版)**可一键更新;**本机源码版**版本高于 npm 时会提示「以源码为准,升级走 `install.ps1`」,一键更新随之闲置——**它不会把本地降级** |
31
45
  | **状态通知** | Web/TUI 启动与停止瞬间弹系统通知;托盘就绪弹一次提示 |
32
- | **开机自启** | 登录后托盘自动出现 + dsh Web 静默拉起(两个启动文件夹快捷方式,安装时自动创建):「DSH 系统托盘.lnk」→ `dsh-tray.ps1`;「DeepSeek Harness (dsh).lnk」→ `dsh-boot.ps1` |
46
+ | **开机自启** | 登录后托盘自动出现 + dsh Web 静默拉起(两个启动文件夹快捷方式,安装时创建):「DSH 系统托盘.lnk」→ `dsh-tray.ps1`;「DeepSeek Harness (dsh).lnk」→ `dsh-boot.ps1` |
33
47
 
34
48
  ## 适配与依赖
35
49
 
36
50
  | 项 | 说明 |
37
51
  | :--- | :--- |
38
- | **dsh 内核** | **声明**(`package.json` → `dshCompatibility`):`range` = `>=0.1.1-rc.2 <0.2.0`,`testedVersions` = **0.1.1-rc.2 / 0.1.2-rc.1 / 0.1.5-rc.1 / 0.1.5-rc.2**;`install.ps1` 会做**软校验**(不在实测清单→黄字提醒,不阻断)。口径说明:本包是**外部工具**(不 import 任何 `@deepseek-ai` 代码),故不声明 `@deepseek-ai` peerDependencies。适配 `@deepseek-ai/dsh` **v0.1.1-rc.2 起系列**;**rc.1 起引入一次性 launch token 鉴权**(打开 Web UI 必须用启动横幅 `?token=` URL 首次签发持久 cookie)→ **打开/重启 Web UI 需托盘 ≥1.0.11**(自动解析 `web-menu.out.log` 的 token 并探活;无 token/失效回退裸 URL = 向后兼容);1.0.10 及更早在 rc.1+ 上打开的是裸 URL,会看到 `dsh web authentication required` 提示页 |
39
- | **Web 服务** | dsh web 默认监听 `127.0.0.1:3080`(即浏览器里的 Web UI)——托盘通过 TCP 探测该端口判断 Web 状态(端口被改时同步修改 `dsh-lib.ps1` 的 `$PORT` 即可) |
40
- | **TUI 插件** | 适配 `@deepseek-harness-tui/dsh-tui` **^0.9.2(含 0.10.0-beta.4,2026-09-03 实测兼容)**(通过 dsh-profile `dsh-profile-dsh-tui` 挂载);托盘按进程命令行 `dsh-tui` 检测,与插件版本解耦 |
52
+ | **dsh 内核** | **声明**(`package.json` → `dshCompatibility`):`range` = `>=0.1.1-rc.2 <0.2.0`,`testedVersions` = **0.1.1-rc.2 / 0.1.2-rc.1 / 0.1.5-rc.1 / 0.1.5-rc.2**;`install.ps1` 软校验(不在清单→黄字提醒,不阻断)。本包是**外部工具**(不 import `@deepseek-ai` 代码),不声明 peerDependencies。适配 `@deepseek-ai/dsh` **v0.1.1-rc.2 起**;**rc.1 起引入一次性 launch token 鉴权**(打开 Web UI 须用启动横幅 `?token=` URL 首签持久 cookie)→ **打开/重启 Web UI 需托盘 ≥1.0.11**(解析 `web-menu.out.log` 的 token 探活;无 token/失效回退裸 URL);1.0.10 及更早开裸 URL,见 `dsh web authentication required` 页 |
53
+ | **Web 服务** | dsh web 默认监听 `127.0.0.1:3080`(即浏览器里的 Web UI)——托盘用 TCP 探测该端口判断状态(端口改了同步改 `dsh-lib.ps1` 的 `$PORT`) |
54
+ | **TUI 插件** | 适配 `@deepseek-harness-tui/dsh-tui` **^0.9.2(含 0.10.0-beta.4,2026-09-03 实测兼容)**(经 dsh-profile `dsh-profile-dsh-tui` 挂载);托盘按命令行 `dsh-tui` 检测,与插件版本解耦 |
41
55
  | **Node.js** | ≥ 18(dsh 本体运行所需) |
42
56
  | **PowerShell** | 7(托盘常驻进程;缺省回退 Windows PowerShell 5.1) |
43
- | **运行时依赖** | **零 npm 依赖**——纯 PowerShell + WinForms + 系统 API;托盘不修改 dsh、不注入任何内容,纯旁观者 |
57
+ | **运行时依赖** | **零 npm 依赖**——纯 PowerShell + WinForms + 系统 API;不改 dsh、不注入内容,纯旁观者 |
44
58
 
45
59
  ## 界面预览
46
60
 
@@ -48,19 +62,19 @@ dsh 默认在终端前台运行 `dsh web`——必须留着一个命令行窗口
48
62
  | :---: | :---: |
49
63
  | ![running](build/dsh-tray-running-preview.png) | ![stopped](build/dsh-tray-stopped-preview.png) |
50
64
 
51
- > 图标源 = dsh Web 前端官方 favicon(鲸鱼),多尺寸 16~256px;可随时用 `dsh-tray icons` 重新生成。
65
+ > 图标源 = dsh Web 前端官方 favicon(鲸鱼),多尺寸 16~256px;可随时用 `node plugins/dsh-windows-tray/bin/dsh-tray.js icons` 重新生成。
52
66
 
53
67
  ## 快速开始
54
68
 
55
- 前置:Windows 10/11 + [PowerShell 7](https://github.com/PowerShell/PowerShell/releases)(7.x;缺失时自动回退 Windows PowerShell 5.1)+ Node.js **≥ 18** + 已安装 dsh(任意位置)。
69
+ 前置:Windows 10/11 + [PowerShell 7](https://github.com/PowerShell/PowerShell/releases)(缺失回退 Windows PowerShell 5.1)+ Node.js **≥ 18** + dsh(任意位置)。
56
70
 
57
71
  ```powershell
58
- # 1. 全局安装
59
- npm i -g dsh-windows-tray
72
+ # 1. 一键部署(他人:npm i -g dsh-windows-tray + dsh-tray install;本机自用:从源码仓跑这条)
73
+ # 探测 dsh/pwsh/node → 装到 ~\.dsh\launcher → 改写本机路径 → 建开机自启 + 桌面快捷方式
74
+ # -NoTrayStart = 不自动拉起托盘;-EnableBackup = 同时打开备份面(默认关,见「功能开关」)
75
+ pwsh -NoProfile -ExecutionPolicy Bypass -File plugins/dsh-windows-tray/install.ps1 -Auto -NoTrayStart -EnableBackup
60
76
 
61
- # 2. 一键部署(自动探测 dsh/pwsh/node 路径 → 安装到 ~\.dsh\launcher
62
- # → 按本机路径改写配置 → 创建开机自启(托盘 + harness Web)+ 桌面快捷方式 → 启动托盘)
63
- dsh-tray install
77
+ # 2. 唤起托盘(首次;之后随登录自启):桌面「DSH 系统托盘」
64
78
 
65
79
  # 3. 首次使用:把任务栏 ^ 溢出区里的鲸鱼拖到任务栏(一次性,Windows 会记住)
66
80
  ```
@@ -71,32 +85,53 @@ dsh-tray install
71
85
 
72
86
  | 命令 | 作用 |
73
87
  | :--- | :--- |
74
- | `dsh-tray` | 启动托盘(已有实例则提示,不重复启动) |
75
- | `dsh-tray install` | 一键部署 / 重新部署(可透传 `-DshRoot` 等参数) |
76
- | `dsh-tray icons` | 重新生成鲸鱼图标(内置 512px 源图,无需浏览器) |
77
- | `dsh-tray info` | 查看版本 / 安装位置 / 部署状态 |
78
- | `npm up -g dsh-windows-tray` | 命令行更新(更新后建议 `dsh-tray install` 重部署) |
88
+ | `node plugins/dsh-windows-tray/bin/dsh-tray.js` | 启动托盘(已有实例则提示,不重复启动) |
89
+ | `… bin/dsh-tray.js install` | 一键部署 / 重新部署(可透传 `-DshRoot` 等参数);等价且更直接 = `install.ps1 -Auto -NoTrayStart` |
90
+ | `… bin/dsh-tray.js icons` | 重新生成鲸鱼图标(内置 512px 源图,无需浏览器) |
91
+ | `… bin/dsh-tray.js info` | 查看版本 / 安装位置 / 部署状态 |
92
+ | `install.ps1 -Auto -NoTrayStart` | **更新/重部署(2026-09-23 起唯一路径)** |
79
93
 
80
- ## 如何更新
94
+ > ⛔ **仅对本机源码机**:已部署源码版(1.0.14)的机器**别**跑 `npm i -g dsh-windows-tray`——npm 上自 **2026-09-24** 起也是 **1.0.14**(与源码同版,**不再是"降级"风险**),但 npm 安装与源码部署是**两条通道**,混用会让 `dsh-tray` 命令与 `~\.dsh\launcher` 的来源分不清(想走 npm 通道就别再用源码 `install.ps1`);他人首次安装仍走 `npm i -g` → `dsh-tray install`(见上)。本机源码机一律用上表的 `node … bin/dsh-tray.js …` 或 `install.ps1`。
81
95
 
82
- 两种方式任选:
96
+ ## 功能开关(备份面**默认关闭**)
83
97
 
84
- **方式一:托盘一键更新(推荐)**——托盘菜单「版本信息 ▸」→「检查更新」对比 npm 最新版,发现新版后点「更新到最新版」:自动 `npm install -g` → 重新部署(含本机路径改写)→ 自动重启托盘,全程约 1 分钟,失败不影响当前托盘。
98
+ 备份面(第三行状态 + `备份 ▸` 子菜单)是一个**默认关闭**的单开关。关着时菜单里**看不到任何备份痕迹**,动作入口也会拒绝(`exit 4`:不 init、不建库、不写库)。
85
99
 
86
- **方式二:npm 标准流程**——与普通 npm 包一致:
100
+ | 项 | 说明 |
101
+ | :--- | :--- |
102
+ | 开关 | `features.backup`(bool,**默认 false**) |
103
+ | 位置 | **`$DSH_HOME\plugin-config\dsh-windows-tray.json`**(包外 ⇒ 重部署不冲掉;此目录为跨插件统一约定,后续插件沿用) |
104
+ | 启用 | `install.ps1 -EnableBackup` · `node …\bin\dsh-tray.js features --enable backup` · 临时 `$env:DSH_TRAY_BACKUP=1` |
105
+ | 查看 / 关闭 | `… features --list` · `… features --disable backup` |
106
+ | 优先级 | `$env:DSH_TRAY_BACKUP`(临时覆盖、**不落盘**)> 配置文件 > 默认关;**改完需重启托盘** |
107
+ | 异常 | 配置缺失 ⇒ 默认关(**不创建文件**);损坏 / 类型不对 / `version` 高于已知 ⇒ 一律按默认关,**不抛错、不阻断启动** |
108
+
109
+ > ⚠ 开关只管"**显不显示**",**不会**替你装引擎——真要能备份还需引擎在位:`personal-docs\dsh\config\install.ps1 -Only tools`(缺引擎时状态行会显式「未就绪」并给装法)。
110
+ > ⚠ **改开关必须重启托盘**:菜单在**启动时**构建、动作闸**每次现读** ⇒ 只 `--disable` 不重启会出现"菜单还在、点下去弹未启用"的混态(反之 `--enable` 不重启则看不到备份面)。
111
+
112
+ ## 如何更新
113
+
114
+ **两条通道**(谁装的就走谁那条):
87
115
 
88
116
  ```powershell
89
- npm up -g dsh-windows-tray # 拉取最新版
90
- dsh-tray install # 重新部署(自动改写本机路径 + 刷新快捷方式)
91
- dsh-tray # 重启托盘(或右键「退出托盘」后重新登录/双击快捷方式)
117
+ # 他人(npm 安装版):托盘菜单「版本信息 ▸ → 检查更新 → 更新到最新版」,或
118
+ npm up -g dsh-windows-tray ; dsh-tray install
119
+
120
+ # 本机源码版:从源码仓重部署(改完必须重启托盘)
121
+ pwsh -NoProfile -ExecutionPolicy Bypass -File plugins/dsh-windows-tray/install.ps1 -Auto -NoTrayStart -EnableBackup
122
+ # 然后重启托盘(右键「退出托盘」后重新登录 / 双击桌面快捷方式)
92
123
  ```
93
124
 
94
- > 部署目录固定为 `~\.dsh\launcher`,重装/更新都会覆盖旧文件,不会残留;`dsh-tray info` 可查看当前版本与部署状态。
125
+ > ⚠ 两条通道别混:**本机源码版**(1.0.14)若用 `npm up -g` / `dsh-tray install`(npm 上同为 1.0.14,2026-09-24 发布)版本不会变,但部署面来源会换成 npm 版;查本机状态用 `node plugins/dsh-windows-tray/bin/dsh-tray.js info`。
126
+
127
+ > 部署目录固定 `~\.dsh\launcher`,重装/更新覆盖旧文件不残留。
95
128
 
96
129
  ## 卸载
97
130
 
98
131
  ```powershell
99
- npm rm -g dsh-windows-tray # ① 移除 npm 包本体
132
+ # ① 清掉 2026-09-12 那次 npm 发布留下的全局残留(本机 PATH 上那个 1.0.13 的 dsh-tray)
133
+ # 源码安装本身没有"移除 npm 包"这一步;不清也能用,但留着会被误当正身
134
+ npm rm -g dsh-windows-tray
100
135
  # ② 删除快捷方式: 「DSH 系统托盘.lnk」(启动文件夹 + 桌面) + 「DeepSeek Harness (dsh).lnk」(启动文件夹)
101
136
  # ③ 删除部署目录 ~\.dsh\launcher (如与 dsh 控制台共用, 确认无需保留再删)
102
137
  ```
@@ -111,10 +146,10 @@ npm rm -g dsh-windows-tray # ① 移除 npm 包本体
111
146
  └── 单实例 ──► 命名互斥锁 (被强杀遗留的锁自动接管)
112
147
  ```
113
148
 
114
- - **状态检测**:Web 用 TCP 端口探测(物理单实例);TUI 按命令行匹配(多实例安全:全查全杀);TUI 检测 20s 节流,打开菜单时强制刷新
149
+ - **状态检测**:Web 用 TCP 探测(物理单实例);TUI 按命令行匹配(多实例安全,全查全杀);TUI 检测 20s 节流,开菜单强制刷新
115
150
  - **动作隔离**:启动/停止/重启在独立进程执行,托盘 UI 永不卡顿
116
- - **日志**:`~\.dsh\logs\dsh-windows-tray\`(`dsh-tray.log` 状态变化 / `dsh-tray-actions.log` 菜单动作 / `dsh-boot.log` 开机自启)
117
- - **单点配置**:端口/路径等常量集中在 `launcher/dsh-lib.ps1`,安装时按本机自动改写——**包本身与机器无关**
151
+ - **日志**:`~\.dsh\logs\dsh-windows-tray\`(`dsh-tray.log` 状态 / `dsh-tray-actions.log` 菜单动作 / `dsh-boot.log` 开机自启)
152
+ - **单点配置**:端口/路径等常量集中在 `launcher/dsh-lib.ps1`,安装时按本机改写——**包本身与机器无关**
118
153
 
119
154
  ## 配置
120
155
 
@@ -129,13 +164,13 @@ npm rm -g dsh-windows-tray # ① 移除 npm 包本体
129
164
  | 问题 | 处理 |
130
165
  | :--- | :--- |
131
166
  | 任务栏看不到鲸鱼 | 点开 `^` 溢出区,把鲸鱼拖到任务栏(一次性) |
132
- | 停止 Web UI 会关掉浏览器界面 | 对——停止前有确认框;Web 与当前会话在 3080 端口上 |
133
- | 托盘退出了怎么唤回 | 双击桌面「DSH 系统托盘」快捷方式 / 重新登录(开机自启)/ `dsh-tray` |
134
- | 怎么更新到新版 | 托盘菜单「版本信息 ▸ → 更新到最新版」一键完成;或 `npm up -g dsh-windows-tray` + `dsh-tray install`(见「如何更新」) |
167
+ | 停止 Web UI 会关掉浏览器界面 | 对——停止前有确认;Web 与当前会话都在 3080 上 |
168
+ | 托盘退出了怎么唤回 | 双击桌面「DSH 系统托盘」快捷方式(直指 `~\.dsh\launcher\dsh-tray.ps1`)/ 重新登录(开机自启)/ `node plugins/dsh-windows-tray/bin/dsh-tray.js` |
169
+ | 怎么更新到新版 | **他人**(npm 版):菜单「版本信息 ▸ → 检查更新 → 更新到最新版」,或 `npm up -g dsh-windows-tray` + `dsh-tray install`;**本机源码版**:`install.ps1 -Auto -NoTrayStart -EnableBackup` + 重启托盘(见上)。⚠ 两条通道别混(本机用 npm 那条会**降级**) |
135
170
  | 检查更新失败 | 网络或 npm 不可用;托盘继续正常工作,稍后再试 |
136
171
  | dsh 内核升级了,托盘要动吗 | 不用——托盘只探测 3080 端口与 TUI 进程命令行,与内核版本解耦 |
137
- | 想彻底卸载 | `npm rm -g dsh-windows-tray` + 删除「DSH 系统托盘.lnk」与「DeepSeek Harness (dsh).lnk」+ 删除 `~\.dsh\launcher` |
138
- | 开机后 dsh Web 没自动起 | 看 `~\.dsh\logs\dsh-windows-tray\dsh-boot.log`:末行 `boot ok (started)` = 正常;`boot FAILED` 后跟的错误即原因(隐藏窗口下日志是唯一线索),常见是 `~\.dsh\launcher` 被移动/删除 |
172
+ | 想彻底卸载 | 删除「DSH 系统托盘.lnk」与「DeepSeek Harness (dsh).lnk」+ 删除 `~\.dsh\launcher`;若曾用 npm 装过,再 `npm rm -g dsh-windows-tray` 清掉全局残留 |
173
+ | 开机后 dsh Web 没自动起 | 看 `~\.dsh\logs\dsh-windows-tray\dsh-boot.log`:末行 `boot ok (started)` = 正常;`boot FAILED` 后跟的错误即原因(隐藏窗口下日志是唯一线索),常见是 `~\.dsh\launcher` 被移走/删除 |
139
174
 
140
175
  ## 文档
141
176
 
package/bin/dsh-tray.js CHANGED
@@ -5,6 +5,7 @@
5
5
  // dsh-tray install 一键部署到 ~\.dsh\launcher (自动探测路径+快捷方式+启动)
6
6
  // dsh-tray icons 重新生成鲸鱼图标 (build/build-tray-icons.ps1)
7
7
  // dsh-tray info 显示版本/安装位置/pwsh 路径
8
+ // dsh-tray features --list | --enable backup | --disable backup (功能开关,写 plugin-config;默认关)
8
9
  'use strict';
9
10
  const { spawn } = require('child_process');
10
11
  const path = require('path');
@@ -14,6 +15,9 @@ const root = path.join(__dirname, '..');
14
15
  const pkg = require(path.join(root, 'package.json'));
15
16
  const home = process.env.USERPROFILE || process.env.HOME || '';
16
17
  const deployDir = path.join(home, '.dsh', 'launcher');
18
+ // 功能开关/配置跟随 DSH_HOME(与 dsh-lib 的 Get-DshHomeDir 同口径)——写读不一致会让非默认数据目录机器静默失效
19
+ const dataHome = process.env.DSH_HOME || path.join(home, '.dsh');
20
+ const cfgFile = path.join(dataHome, 'plugin-config', 'dsh-windows-tray.json');
17
21
 
18
22
  function findPwsh() {
19
23
  const candidates = [
@@ -57,6 +61,39 @@ switch (cmd) {
57
61
  console.log(`部署状态: ${fs.existsSync(path.join(deployDir, 'dsh-tray.ps1')) ? '已部署' : '未部署 (先运行 dsh-tray install)'}`);
58
62
  break;
59
63
 
64
+ case 'features': {
65
+ // 功能开关(plugin-config 统一模式;单总开关 features.backup,**默认关** —— npm 包不带该文件)
66
+ const arg = process.argv[3] || '--list';
67
+ const target = process.argv[4];
68
+ const readCfg = () => { try { return JSON.parse(fs.readFileSync(cfgFile, 'utf8')); } catch (_) { return null; } };
69
+ if (arg === '--list') {
70
+ const c = readCfg();
71
+ const on = !!(c && c.features && c.features.backup === true);
72
+ console.log(`配置文件: ${cfgFile}${fs.existsSync(cfgFile) ? '' : '(不存在 ⇒ 按默认)'}`);
73
+ console.log(`features.backup = ${on ? '开' : '关'}(来源: ${c ? '配置文件' : '默认'})`);
74
+ break;
75
+ }
76
+ if (arg !== '--enable' && arg !== '--disable') {
77
+ console.error('用法: dsh-tray features --list | --enable backup | --disable backup');
78
+ process.exit(2);
79
+ }
80
+ if (target !== 'backup') {
81
+ console.error(`未知开关: ${target}(本批只支持 backup)`);
82
+ process.exit(2);
83
+ }
84
+ const cfg = readCfg() || {};
85
+ if (!cfg.version) cfg.version = 1;
86
+ cfg.features = cfg.features || {};
87
+ cfg.features.backup = arg === '--enable';
88
+ fs.mkdirSync(path.dirname(cfgFile), { recursive: true });
89
+ const tmp = `${cfgFile}.tmp-${process.pid}`;
90
+ fs.writeFileSync(tmp, `${JSON.stringify(cfg, null, 2)}\n`, 'utf8');
91
+ fs.renameSync(tmp, cfgFile); // 原子写(同目录 rename)
92
+ console.log(`features.backup = ${cfg.features.backup ? '开' : '关'} ⇒ ${cfgFile}`);
93
+ console.log('重启托盘后生效(菜单在启动时构建)');
94
+ break;
95
+ }
96
+
60
97
  case 'run':
61
98
  default: {
62
99
  // 托盘是常驻进程: 优先跑已部署(路径已改写)的副本
@@ -1,7 +1,7 @@
1
- # DSH 系统托盘(Windows)—— npm 包使用手册
1
+ # DSH 系统托盘(Windows)—— 使用手册
2
2
 
3
3
  > 包名: **`dsh-windows-tray`** · 部署位置: `~\.dsh\launcher` · 技术栈: PowerShell 7 + WinForms,零 npm 依赖、纯旁观者、不改 dsh 源码。
4
- > 安装 / 更新 / 卸载全部走 npm 标准流程;开发归档见 [tray-dev-archive.md](tray-dev-archive.md),相关踩坑见 [../../../docs/powershell-pitfalls.md](../../../docs/powershell-pitfalls.md)。
4
+ > **两条通道**:**他人** = `npm i -g dsh-windows-tray` → `dsh-tray install`;**本机自用** = 源码 `plugins/dsh-windows-tray/install.ps1 -Auto -NoTrayStart -EnableBackup`(本册 §一/§四/§五)。**备份面默认关闭**(开关 = `<DSH_HOME>\plugin-config\dsh-windows-tray.json` 的 `features.backup`,详见包 README「功能开关」节)。开发归档见 [tray-dev-archive.md](tray-dev-archive.md),相关踩坑见 powershell-pitfalls.md(**只提名不建链**)。
5
5
  >
6
6
  > **端口(2026-09-07 起)**:本包默认监控/使用端口为 **3080**。
7
7
 
@@ -12,16 +12,18 @@
12
12
  前置:Windows 10/11 + [PowerShell 7](https://github.com/PowerShell/PowerShell/releases)(7.x;缺失时自动回退 Windows PowerShell 5.1)+ Node.js **≥ 18** + 已安装 dsh(任意位置)。
13
13
 
14
14
  ```powershell
15
- # 1. 全局安装
16
- npm i -g dsh-windows-tray
15
+ # 1. 一键部署(他人:npm i -g + dsh-tray install;本机自用:从源码仓跑这条,-EnableBackup 打开备份面)
16
+ # 自动探测 dsh/pwsh/node 路径 → 安装到 ~\.dsh\launcher
17
+ # → 按本机路径改写配置 → 创建开机自启(托盘 + harness Web)+ 桌面快捷方式(-NoTrayStart = 不自动拉起托盘)
18
+ pwsh -NoProfile -ExecutionPolicy Bypass -File plugins/dsh-windows-tray/install.ps1 -Auto -NoTrayStart
17
19
 
18
- # 2. 一键部署:自动探测 dsh/pwsh/node 路径 → 安装到 ~\.dsh\launcher
19
- # → 按本机路径改写配置 → 创建开机自启(托盘 + harness Web)+ 桌面快捷方式 → 启动托盘
20
- dsh-tray install
20
+ # 2. 唤起托盘:桌面「DSH 系统托盘」(之后随登录自启)
21
21
 
22
22
  # 3. 首次使用:把任务栏 ^ 溢出区里的鲸鱼拖到任务栏(一次性,Windows 会记住)
23
23
  ```
24
24
 
25
+ > ⚠️ **落盘口径 = 覆盖式、不自带备份**(本包 `install.ps1` 用 `Copy-Item -Force` 整体覆盖 `~\.dsh\launcher`,**无** `.bak-<时间戳>` 快照)。这点与 `dsh/config/install.ps1` **不同**——后者经 `config/lib/deploy-core.ps1` 逐件留 `.bak-*`(台账"install.ps1 各节自带备份"那句指的是它,2026-09-24 实测澄清)。⇒ **升级/重装前先自行快照**(惯例名 = `~\.dsh\backup-<yyyyMMdd-HHmmss>-tray-align`);**回退 = 取源仓旧 sha 的 `plugins/dsh-windows-tray/launcher/*` 重跑本命令**(`dsh-lib.ps1` 的 6 行本机值由安装器每次重算,快照无需含)。
26
+
25
27
  ### 安装后必做:本机参数探测 → 确认 → 回填(不要信默认值)
26
28
 
27
29
  > **v1.0.2 起 install 已自动完成本节的探测与回填**(探测运行中 web 进程的端口与数据目录 → 展示确认 → 回填全部读取点 + 自动建日志目录)。以下命令仅用于**排查**或手动核对;旧版本(≤1.0.1)部署的机器仍需按此手工适配一次。
@@ -42,10 +44,10 @@ Test-Path "$env:USERPROFILE\.dsh\settings.yaml" # True=默认目录;False=
42
44
 
43
45
  | 命令 | 作用 |
44
46
  | :--- | :--- |
45
- | `dsh-tray` | 启动托盘(已有实例则提示,不重复启动) |
46
- | `dsh-tray install` | 一键部署 / 重新部署(可透传 `-DshRoot` 等参数) |
47
- | `dsh-tray icons` | 重新生成鲸鱼图标(内置 512px 源图,无需浏览器) |
48
- | `dsh-tray info` | 查看版本 / 安装位置 / 部署状态 |
47
+ | `node plugins/dsh-windows-tray/bin/dsh-tray.js` | 启动托盘(已有实例则提示,不重复启动)。裸 `dsh-tray` 走的是**全局 npm 残留(1.0.13)**,源码机请用这个完整形态 |
48
+ | `… bin/dsh-tray.js install` | 一键部署 / 重新部署(可透传 `-DshRoot` 等参数);**等价且更直接的是 `install.ps1 -Auto -NoTrayStart`** |
49
+ | `… bin/dsh-tray.js icons` | 重新生成鲸鱼图标(内置 512px 源图,无需浏览器) |
50
+ | `… bin/dsh-tray.js info` | 查看版本 / 安装位置 / 部署状态 |
49
51
 
50
52
  ## 二、功能一览
51
53
 
@@ -54,7 +56,9 @@ Test-Path "$env:USERPROFILE\.dsh\settings.yaml" # True=默认目录;False=
54
56
  | **图标** | 🐋 品牌蓝鲸鱼 = Web 运行中;灰鲸鱼 = 未运行(官方 favicon 渲染,多尺寸 16~256px) |
55
57
  | **悬停提示** | `Web UI 运行中 · 127.0.0.1:3080` / `Web UI 未运行 · 右键可启动` |
56
58
  | **双击** | 打开 Web UI(未运行时提示先启动) |
57
- | **右键菜单** | 顶部 `Web UI 状态` / `TUI 状态` 双状态行(含 PID);`Web UI ▸`(打开 Web UI / 启动 / 停止(带确认) / 重启);`TUI ▸`(启动 / 停止);打开日志目录 / `版本信息 ▸`(版本 / 检查更新 / 更新到最新版)/ 退出托盘 |
59
+ | **右键菜单** | 顶部 `Web UI 状态` / `TUI 状态` / **`备份`** 三状态行(含 PID / 备份时龄);`Web UI ▸`(打开 Web UI / 启动 / 停止(带确认) / 重启);`TUI ▸`(启动 / 停止);**`备份 ▸`(立即备份 / 打开备份目录)**——「立即备份」四字即全部文案,动作 = data+runtime+vault 三对象各备一次;打开日志目录 / `版本信息 ▸`(版本 / 检查更新 / 更新到最新版)/ 退出托盘 |
60
+ | **备份状态行**(1.0.14) | 第三行显示 `备份: N h 前 ✅/⚠(对象)`,数据源 = `D:\dsh-backups\auto\status.json`(**只读原始 UTC 时间戳、age 读数时算**),30 s 节流刷新(解析结果按文件 `(mtime,size)` 缓存,稳态不重复读盘);**取最旧对象**显示(任一对象陈旧都会露出来)。异常形态:`未配置`(无 status.json)· `状态文件损坏` · `从未成功` · `时钟异常 N h ⚠`(时间在未来)· **`上次失败 N h 前 ⚠(状态停在 M h 前)`**(最近一次失败晚于最近一次成功 ⇒ 备份静默停摆也看得见)。**库位置** = 运行时解析(`$env:DSH_BACKUP_STORE` > `~\.dsh\backup-store.txt` > 自动发现已有库),**不写死盘符**;**引擎** = `~\.dsh\tools\dsh-backup.mjs`(清单/用法见 `dsh/config/tools/README.md`)——**引擎不随托盘包分发**,新机要 ① 装/更新托盘 ② 从 personal-docs 跑 `config\install.ps1 -Only tools`;恢复走引擎 `recover`(向导:还原到中转目录 + 校验 + 打印并入清单,**绝不自动覆盖 HOME**)或按实施记录 §5 手工 SOP |
61
+ | **「立即备份」的反馈**(1.0.14) | 点击后:弹「备份已开始」+ 状态行变 `备份: 进行中…` + 该菜单项**置灰**(备份期间再点只提示"已在运行中",不会重复触发撞 `run.lock`);结束(子进程退出)后弹「备份完成 ✓(N 秒)」或「备份失败(exit=N)—— 详见 `dsh-tray-actions.log`」,并**立即**刷新状态行。超过 30 分钟未结束 ⇒ 提示并恢复菜单项(**不会杀进程**) |
58
62
  | **菜单智能禁用** | Web 运行中禁用「启动 Web UI」;TUI 运行中禁用「启动 TUI」 |
59
63
  | **状态通知** | Web/TUI 启动与停止瞬间弹系统通知;托盘就绪弹一次提示 |
60
64
  | **开机自启** | 登录后托盘自动出现 + dsh Web 静默拉起(两个启动文件夹快捷方式,安装时自动创建):「DSH 系统托盘.lnk」→ `dsh-tray.ps1`;「DeepSeek Harness (dsh).lnk」→ `dsh-boot.ps1`(点源 `dsh-lib.ps1` → `Start-Dsh -OpenBrowser:$false`) |
@@ -64,33 +68,31 @@ Test-Path "$env:USERPROFILE\.dsh\settings.yaml" # True=默认目录;False=
64
68
  ## 三、日常使用
65
69
 
66
70
  1. **自动跟随**:在 dsh 控制台(`~\.dsh\launcher\dsh-control.ps1`)执行 启动/重启 Web 时,托盘会自动拉起(幂等)。
67
- 2. **手动唤起**:双击桌面「DSH 系统托盘」快捷方式;或 `dsh-tray`。
71
+ 2. **手动唤起**:双击桌面「DSH 系统托盘」快捷方式(它直接指向 `~\.dsh\launcher\dsh-tray.ps1`);或源码形态 `node plugins/dsh-windows-tray/bin/dsh-tray.js`(裸 `dsh-tray` 已于 2026-09-23 随全局 npm 残留一并清除)。
68
72
  3. **退出托盘**:右键 → 退出托盘(只退出托盘本身,不影响 dsh;下次登录/双击快捷方式可重新唤起)。
69
73
  4. **取消自启**:删除启动文件夹里的「DSH 系统托盘.lnk」与「DeepSeek Harness (dsh).lnk」(后者只关 dsh Web 的静默自启;托盘仍可从桌面快捷方式/控制台唤起)。
70
74
 
71
75
  ## 四、更新
72
76
 
73
- 两种方式任选:
74
-
75
- **方式一:托盘一键更新(推荐)**——托盘菜单「版本信息 ▸」→「检查更新」对比 npm 最新版,发现新版后点「更新到最新版」:自动 `npm install -g` → 重新部署(含本机路径改写)→ 自动重启托盘,失败不影响当前托盘。
76
-
77
- **方式二:npm 标准流程**:
77
+ **唯一路径 = 从源码仓重部署**:
78
78
 
79
79
  ```powershell
80
- npm up -g dsh-windows-tray # 拉取最新版
81
- dsh-tray install # 重新部署(自动改写本机路径 + 刷新快捷方式)
82
- dsh-tray # 重启托盘
80
+ pwsh -NoProfile -ExecutionPolicy Bypass -File plugins/dsh-windows-tray/install.ps1 -Auto -NoTrayStart
81
+ # 重启托盘:右键「退出托盘」后重新登录 / 双击桌面快捷方式
83
82
  ```
84
83
 
85
- > 部署目录固定为 `~\.dsh\launcher`,重装/更新会覆盖旧文件,不会残留;`dsh-tray info` 可查看当前版本与部署状态。
84
+ - 菜单「检查更新 / 更新到最新版」对比的是 **npm 源** ⇒ **他人(npm 版)**用它更新;**本机源码版**版本高于 npm 时会提示「以源码为准」,一键更新闲置(**不会降级**)。
85
+ - ⛔ **别用 `npm up -g dsh-windows-tray`**(拉不到新版)**或裸 `dsh-tray install`**(解析到全局 npm 残留 1.0.13 ⇒ 覆盖回旧版)。
86
+
87
+ > 部署目录固定为 `~\.dsh\launcher`,重装/更新会覆盖旧文件,不会残留(**覆盖式、不自带备份** —— 快照与回退口径见 §一);`node plugins/dsh-windows-tray/bin/dsh-tray.js info` 可查看当前版本与部署状态。
86
88
  > ⚠️ 更新 = 重新 install,**本机手工适配(端口/数据目录等,见 §六)会被一并覆盖**——更新后按对照表重做并重启托盘,别只看安装输出就收工。
87
89
 
88
90
  ## 五、卸载
89
91
 
90
92
  ```powershell
91
- npm rm -g dsh-windows-tray # 移除 npm 包本体
92
- # 删除三个「DSH 系统托盘.lnk」(启动文件夹 + 桌面)与启动文件夹里的「DeepSeek Harness (dsh).lnk」
93
- # 删除 ~\.dsh\launcher 目录(托盘部署文件;如与 dsh 控制台共用,确认无需保留再删)
93
+ npm rm -g dsh-windows-tray # ① 清掉全局 npm 残留(2026-09-12 发布留下的 1.0.13;源码安装无此步,不清也能用但易被误当正身)
94
+ # ② 删除三个「DSH 系统托盘.lnk」(启动文件夹 + 桌面)与启动文件夹里的「DeepSeek Harness (dsh).lnk」
95
+ # ③ 删除 ~\.dsh\launcher 目录(托盘部署文件;如与 dsh 控制台共用,确认无需保留再删)
94
96
  ```
95
97
 
96
98
  ## 六、配置
@@ -101,33 +103,25 @@ npm rm -g dsh-windows-tray # 移除 npm 包本体
101
103
  | :--- | :--- | :--- | :--- |
102
104
  | 监控端口 | ① `~\.dsh\launcher\dsh-lib.ps1` 顶部 `$PORT`;② `dsh-tray.ps1` 顶部 `param([int]$Port = …)` | `3080` | **两处必须一致**:托盘启动时先点源 lib 再执行 `$PORT = $Port`,**param 默认值会把 lib 改好的端口覆盖回去**(dsh-tray.ps1 第 27 行)——只改 lib 不改 param,托盘仍按默认端口探测 |
103
105
  | dsh 路径 | `dsh-lib.ps1` 顶部 `$DSH_CMD / $NODE / $BIN` | 自动探测 | install 已改写,一般不用动 |
104
- | 数据目录 | `dsh-lib.ps1` `$WORKDIR` + `$env:DSH_HOME` | **不设置** | 不设 DSH_HOME 时 web 默认落 `~\.dsh`——自定义数据目录的机器(如 `D:\dsh`)必须在 lib 里补 `$env:DSH_HOME`,否则托盘/控制台启动的 web 指向空目录 |
105
- | 日志目录 | `dsh-lib.ps1` `$LOG_DIR`(`~\.dsh\logs`) | — | **目录须存在**:不存在时托盘 `Add-Content -ErrorAction SilentlyContinue` 静默吞日志,零日志不是没在记 |
106
+ | 数据目录 | `dsh-lib.ps1` `$WORKDIR` + `$env:DSH_HOME` | **不设置** | 不设 DSH_HOME 时 web 默认落 `~\.dsh`——自定义数据目录的机器(如 `<自定义路径>`)必须在 lib 里补 `$env:DSH_HOME`,否则托盘/控制台启动的 web 指向空目录 |
107
+ | 日志目录 | `dsh-lib.ps1` `$LOG_DIR`(`~\.dsh\logs\dsh-windows-tray`) | — | **目录须存在**:不存在时托盘 `Add-Content -ErrorAction SilentlyContinue` 静默吞日志,零日志不是没在记 |
106
108
  | 图标颜色 | 包内 `build/build-tray-icons.ps1`(运行蓝/停止灰) | `#4176E6` / `#81858C` | — |
107
109
 
108
- > ⚠️ `~\.dsh\launcher` 是部署产物,`dsh-tray install`/更新每次整体覆盖——上表手工适配重装后须重新应用(对照下表逐项核对,别凭记忆)。
109
-
110
- ### 6.1 本机落地对照(跨机器对照用,照此逐项核对)
110
+ > ⚠️ `~\.dsh\launcher` 是部署产物,`install.ps1`/更新每次整体覆盖——上表手工适配重装后须重新应用(对照上表逐项核对,别凭记忆)。
111
111
 
112
- | 项 | 包默认 | 笔记本实际(2026-08-27 实测) | 填充点 |
113
- | :--- | :--- | :--- | :--- |
114
- | Web 端口 | 3080 | **3080** | dsh-lib.ps1 `$PORT` + dsh-tray.ps1 param 默认值(两处) |
115
- | 数据目录 | 不设→`~\.dsh` | **D:\dsh** | dsh-lib.ps1 `$WORKDIR='D:\dsh'` + `$env:DSH_HOME='D:\dsh'` |
116
- | 日志目录 | `~\.dsh\logs`(可能不存在) | 已手动创建 | — |
117
- | 旧控制台 | — | `D:\dsh\launcher\dsh-control.ps1` 与托盘部署并存,端口同为 3080 | 无需合并 |
118
- | 装完验证 | — | `tail ~/.dsh/logs/dsh-tray.log` 应有「托盘启动 (…端口 3080)」;重启 web 应看到「状态: 未运行 → 运行中」翻转 | — |
112
+ > **各机实际值**(某机的端口/数据目录/控制台路径)属装机实录,只进文档仓 `dsh/docs/install-ledger.md`「托盘各机事实」;本册只列包默认值。
119
113
 
120
114
  ## 七、故障排查
121
115
 
122
116
  | 现象 | 处理 |
123
117
  | :--- | :--- |
124
- | web 明明在跑,托盘灰鲸/悬停显示"未运行" | 端口填充点不一致(十有八九是 `dsh-tray.ps1` 的 param 默认值把 lib 改好的端口覆盖回去了)——`tail ~\.dsh\logs\dsh-tray.log` 看「托盘启动」行的实际端口,对照 §六/§6.1 把两处改齐后重启托盘 |
125
- | 托盘零日志 | `~\.dsh\logs` 目录不存在,托盘写日志被静默吞掉——建目录后重启托盘;重启 web 应立即出现状态翻转记录 |
118
+ | web 明明在跑,托盘灰鲸/悬停显示"未运行" | 端口填充点不一致(十有八九是 `dsh-tray.ps1` 的 param 默认值把 lib 改好的端口覆盖回去了)——`tail ~\.dsh\logs\dsh-windows-tray\dsh-tray.log` 看「托盘启动」行的实际端口,对照 §六 把两处改齐后重启托盘 |
119
+ | 托盘零日志 | `~\.dsh\logs\dsh-windows-tray` 目录不存在,托盘写日志被静默吞掉——建目录后重启托盘;重启 web 应立即出现状态翻转记录 |
126
120
  | 任务栏看不到鲸鱼 | 点开 `^` 溢出区查找;若在,拖到任务栏(一次性)。 |
127
- | 托盘图标消失 / 进程死了 | `dsh-tray` 或双击桌面快捷方式重新唤起;托盘退出不影响 dsh。 |
128
- | 动作没反应 | 看 `~\.dsh\logs\dsh-tray-actions.log`(菜单动作)与 `dsh-tray.log`(状态变化)。 |
121
+ | 托盘图标消失 / 进程死了 | 双击桌面「DSH 系统托盘」快捷方式(或 `node plugins/dsh-windows-tray/bin/dsh-tray.js`)重新唤起;托盘退出不影响 dsh。 |
122
+ | 动作没反应 | 看 `~\.dsh\logs\dsh-windows-tray\dsh-tray-actions.log`(菜单动作)与同目录 `dsh-tray.log`(状态变化)。 |
129
123
  | 重复实例 | 命名互斥锁单实例保护(被强杀遗留的锁自动接管),正常不会重复。 |
130
- | 检查更新失败 | 网络或 npm 不可用;托盘继续正常工作,稍后再试。 |
124
+ | 检查更新显示「已是最新」但 npm 上其实有新版 | 本机是**源码版**(版本高于 npm)⇒ 属正常,升级走源码 `install.ps1`(见 §四);若显示"检查失败"则是网络/npm 不可用,不影响托盘。 |
131
125
  | 开机后 dsh Web 没自动起 | 看 `~\.dsh\logs\dsh-windows-tray\dsh-boot.log`:末行 `boot ok (started)` = 正常;`boot FAILED` 后跟的错误即原因(自启是隐藏窗口,日志是唯一线索),常见是 `~\.dsh\launcher` 被移动/删除或 `dsh-boot.ps1` 被手工改名 |
132
126
  | dsh 内核升级了,托盘要动吗 | 不用——托盘只探测 3080 端口与 TUI 进程命令行,与内核版本解耦。 |
133
127
 
package/install.ps1 CHANGED
@@ -1,5 +1,5 @@
1
1
  # install.ps1 —— DSH 系统托盘 一键部署(npm 包内运行;**唯一权威安装器**,无第二份副本)
2
- # 用法: pwsh -NoProfile -ExecutionPolicy Bypass -File .\install.ps1 [-DshRoot <目录>] [-PwshPath <路径>] [-NodePath <路径>] [-Port <端口>] [-DshHome <数据目录>] [-Auto] [-NoTrayStart] [-NoShortcuts]
2
+ # 用法: pwsh -NoProfile -ExecutionPolicy Bypass -File .\install.ps1 [-DshRoot <目录>] [-PwshPath <路径>] [-NodePath <路径>] [-Port <端口>] [-DshHome <数据目录>] [-Auto] [-NoTrayStart] [-NoShortcuts] [-EnableBackup]
3
3
  # 流程: 探测本机路径 -> 探测端口/数据目录并确认 -> 安装到 ~\.dsh\launcher -> 回填全部读取点(含端口两处+DSH_HOME) -> 创建快捷方式 -> 启动托盘
4
4
  # v1.0.2: 端口/数据目录实测探测 + 展示确认 + 回填全部读取点 + 自动创建日志目录 (修: param 默认值覆盖 lib 端口 / DSH_HOME 不设 / 日志目录缺失静默丢日志)
5
5
  # v1.0.3: 停止确认框枚举修复(DefaultButton2→Button2, Win11 .NET 崩溃框根因) + AUMID 通知身份(开始菜单快捷方式+预授权, 气泡不再显示为 PowerShell)
@@ -11,20 +11,28 @@ param(
11
11
  [string]$DshHome, # 数据目录 (含 settings.yaml); 空=自动探测
12
12
  [switch]$Auto, # 非交互: 直接采用探测值不确认 (自更新等隐藏窗口场景)
13
13
  [switch]$NoTrayStart, # 部署后不自动启动托盘
14
- [switch]$NoShortcuts # 不创建快捷方式
14
+ [switch]$NoShortcuts, # 不创建快捷方式
15
+ [switch]$EnableBackup # 部署后写入 plugin-config 开关(**本机自用**;npm 包默认不带 ⇒ 他人装上即关)
15
16
  )
16
17
  $ErrorActionPreference = 'Stop'
17
18
  $pkgRoot = $PSScriptRoot
18
19
  $dst = Join-Path $env:USERPROFILE '.dsh\launcher'
19
20
  $logDir = Join-Path (Join-Path $env:USERPROFILE '.dsh\logs') 'dsh-windows-tray' # 插件专属日志目录 (release-standards §3.1)
21
+ # 功能开关的落点 = **数据目录**(与 launcher/logs 的"安装根"不同口径:配置跟随 DSH_HOME,读侧
22
+ # `dsh-lib:Get-DshHomeDir` 就是这个口径;写读不一致会让非默认数据目录机器开关静默失效,方案审 R1-07)。
23
+ # ⚠ 解析**不在文件头做**——$DshHome 要等交互探测(:139 Confirm-Value)才定稿,见下方写开关处(实现审 R3-04)
20
24
 
21
25
  Write-Host '== DSH 系统托盘 一键部署 ==' -ForegroundColor Cyan
22
26
 
23
27
  # ---- 探测: 实际 Web 端口 (从运行中的 web 进程命令行提取, 不写死默认值) ----
24
28
  function Find-WebPort {
29
+ # 收紧(R2-P3-4 补丁):在 P2-4 三特征基础上再排除 web 工具执行器 runner(命令行携带整段工具文本,
30
+ # 文本里若恰含 bin.js/web/--port 会命中并返回文本里的端口)——runner 恒含 dsh-subprocess-local。
31
+ # 端口提取限定邻接形态 `web --host 127.0.0.1 --port N`(dsh web 启动串),杜绝文本里任意位置提端口。
25
32
  $procs = @(Get-CimInstance Win32_Process -Filter "Name='node.exe'" -ErrorAction SilentlyContinue |
26
- Where-Object { $_.CommandLine -match 'web' -and $_.CommandLine -match '--port' })
33
+ Where-Object { $_.CommandLine -match 'bin\.js' -and $_.CommandLine -match 'web' -and $_.CommandLine -match '--port' -and $_.CommandLine -notmatch 'dsh-subprocess-local' })
27
34
  foreach ($p in $procs) {
35
+ if ($p.CommandLine -match 'web --host 127\.0\.0\.1 --port\s+(\d+)') { return [int]$Matches[1] }
28
36
  if ($p.CommandLine -match '--port\s+(\d+)') { return [int]$Matches[1] }
29
37
  }
30
38
  return $null
@@ -91,19 +99,19 @@ if (-not $PwshPath -or -not (Test-Path $PwshPath)) { throw "未找到 pwsh (Powe
91
99
  # 版本校验: 托盘常驻进程依赖 PowerShell 7.x (5.1 只能降级运行)
92
100
  $pwshVer = & $PwshPath -NoProfile -Command '$PSVersionTable.PSVersion.ToString()' 2>$null
93
101
  if ($pwshVer -notmatch '^7\.') { throw "pwsh 必须是 PowerShell 7.x (检测到: $pwshVer)。请安装 PowerShell 7 或用 -PwshPath 指定。" }
94
- Write-Host "[2/7] pwsh: $PwshPath (v$pwshVer)" -ForegroundColor Green
95
-
96
- # 内核兼容软校验(release-standards §5.5 / package.json dshCompatibility):
97
- # 只提醒不阻断——本包是外部工具,内核超出实测范围时多数功能仍可用(探测/启停与版本解耦)
98
- $tested = @('0.1.1-rc.2', '0.1.2-rc.1', '0.1.5-rc.1', '0.1.5-rc.2')
99
- $corePkg = Join-Path $DshRoot 'node_modules\@deepseek-ai\dsh\package.json'
100
- if (Test-Path $corePkg) {
101
- $coreVer = (Get-Content $corePkg -Raw | ConvertFrom-Json).version
102
- if ($tested -notcontains $coreVer) {
103
- Write-Host "[warn] dsh 内核 $coreVer 不在本包实测清单($($tested -join ' / '))——功能大概率可用,异常请先对照 CHANGELOG 的 dshCompatibility 再报。" -ForegroundColor Yellow
104
- } else {
105
- Write-Host "[2/7] dsh 内核 $coreVer 在实测清单内" -ForegroundColor Green
106
- }
102
+ Write-Host "[2/7] pwsh: $PwshPath (v$pwshVer)" -ForegroundColor Green
103
+
104
+ # 内核兼容软校验(release-standards §5.5 / package.json dshCompatibility):
105
+ # 只提醒不阻断——本包是外部工具,内核超出实测范围时多数功能仍可用(探测/启停与版本解耦)
106
+ $tested = @('0.1.1-rc.2', '0.1.2-rc.1', '0.1.5-rc.1', '0.1.5-rc.2')
107
+ $corePkg = Join-Path $DshRoot 'node_modules\@deepseek-ai\dsh\package.json'
108
+ if (Test-Path $corePkg) {
109
+ $coreVer = (Get-Content $corePkg -Raw | ConvertFrom-Json).version
110
+ if ($tested -notcontains $coreVer) {
111
+ Write-Host "[warn] dsh 内核 $coreVer 不在本包实测清单($($tested -join ' / '))——功能大概率可用,异常请先对照 CHANGELOG 的 dshCompatibility 再报。" -ForegroundColor Yellow
112
+ } else {
113
+ Write-Host "[2/7] dsh 内核 $coreVer 在实测清单内" -ForegroundColor Green
114
+ }
107
115
  }
108
116
 
109
117
  # 3) 探测 node
@@ -163,7 +171,7 @@ $lines = @($lines | Where-Object { $_ -notmatch '^\$env:DSH_HOME\s*=' })
163
171
  $defaultHome = Join-Path $env:USERPROFILE '.dsh'
164
172
  if ($DshHome -ne $defaultHome) {
165
173
  $lines = @($lines | ForEach-Object {
166
- if ($_ -match '^\$WORKDIR') { $_; "`$env:DSH_HOME = '$($DshHome -replace "'", "''")' # 数据目录 (install 回填)" }
174
+ if ($_ -match '^\$WORKDIR') { $_; "`$env:DSH_HOME = '$($DshHome -replace "'", "''")' # 数据目录 (install 回填) # SET-BY-INSTALL-PS1" }
167
175
  else { $_ }
168
176
  })
169
177
  }
@@ -257,6 +265,29 @@ namespace DSH.Shortcut {
257
265
  Write-Host '快捷方式: 开机自启(托盘 + harness) + 桌面 + 开始菜单 已创建 (AUMID=DSH.WindowsTray, 通知已预授权)' -ForegroundColor Green
258
266
  }
259
267
 
268
+ # 功能开关:-EnableBackup 写 plugin-config(本机自用;npm 包默认不带该文件 ⇒ 他人装上即"关")
269
+ if ($EnableBackup) {
270
+ # ⚠ 落点解析必须在**此处**重算:$dataHome(文件头部那次)只看到参数值,而 $DshHome 可能在
271
+ # 上面的交互探测里才定稿(实现审 R3-04)⇒ 旧写法会把开关写到托盘不读的目录(静默失效)
272
+ $switchHome = if ($DshHome) { $DshHome } elseif ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $env:USERPROFILE '.dsh' }
273
+ $cfgDir = Join-Path $switchHome 'plugin-config'
274
+ New-Item -ItemType Directory -Force -Path $cfgDir | Out-Null
275
+ $cfgFile = Join-Path $cfgDir 'dsh-windows-tray.json'
276
+ # 与 bin/dsh-tray.js 的 features 通道**同语义**:**合并**既有配置(不整文件覆写 ⇒ 不丢别的键);
277
+ # 写入用同目录 rename 覆盖(避免半截文件;Windows 上非严格原子 —— 实测 Move-Item -Force 有
278
+ # 50/111,350 次目标缺失窗口,故改用 .NET File.Move(overwrite)(实现审 R3-05))
279
+ $cfg = $null
280
+ if (Test-Path -LiteralPath $cfgFile) { try { $cfg = Get-Content -LiteralPath $cfgFile -Raw | ConvertFrom-Json } catch { $cfg = $null } }
281
+ if (-not $cfg) { $cfg = [pscustomobject]@{ version = 1; features = [pscustomobject]@{ backup = $false } } }
282
+ if ($null -eq $cfg.PSObject.Properties['version']) { $cfg | Add-Member -NotePropertyName version -NotePropertyValue 1 -Force }
283
+ if ($null -eq $cfg.PSObject.Properties['features'] -or -not $cfg.features) { $cfg | Add-Member -NotePropertyName features -NotePropertyValue ([pscustomobject]@{}) -Force }
284
+ $cfg.features | Add-Member -NotePropertyName backup -NotePropertyValue $true -Force
285
+ $tmpFile = Join-Path $cfgDir ('.tmp-' + [guid]::NewGuid().ToString('N').Substring(0, 8) + '.json')
286
+ Set-Content -LiteralPath $tmpFile -Value ($cfg | ConvertTo-Json -Depth 6) -Encoding UTF8
287
+ [System.IO.File]::Move($tmpFile, $cfgFile, $true)
288
+ Write-Host "功能开关: 备份面已启用 ⇒ $cfgFile(重启托盘生效;已有其它键已保留)" -ForegroundColor Green
289
+ }
290
+
260
291
  # 启动托盘
261
292
  if (-not $NoTrayStart) {
262
293
  Start-Process -FilePath $PwshPath -ArgumentList @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-WindowStyle', 'Hidden', '-File', (Join-Path $dst 'dsh-tray.ps1')) -WindowStyle Hidden