dsh-windows-tray 1.0.9 → 1.0.11

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 jankin_lv
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 jankin_lv
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,146 +1,146 @@
1
- # dsh-windows-tray
2
-
3
- > DeepSeek Harness(dsh)的 Windows 系统托盘管家:**官方鲸鱼状态图标 + Web/TUI 双状态显示 + 一键启停**。
4
- > 纯 PowerShell + WinForms 实现,零依赖、无编译、不改 dsh 源码,卸载即还原。
5
-
6
- [![npm](https://img.shields.io/npm/v/dsh-windows-tray?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
7
- [![npm downloads](https://img.shields.io/npm/dm/dsh-windows-tray?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
8
- [![Platform](https://img.shields.io/badge/platform-Windows%2010%2F11-blue?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
9
- [![License](https://img.shields.io/npm/l/dsh-windows-tray?style=flat-square)](https://github.com/)
10
-
11
- ## 是什么
12
-
13
- dsh 默认在终端前台运行 `dsh web`——必须留着一个命令行窗口。本工具把它变成**一个标准的 Windows 托盘应用**:
14
-
15
- - 🐋 **状态一目了然**:品牌蓝鲸鱼 = Web 运行中;灰鲸鱼 = 未运行(图标由官方 favicon 渲染生成)
16
- - 📊 **DSH / TUI 双状态**:菜单顶部同屏显示 Web 与 TUI 各自的运行状态(含 PID),互不干扰
17
- - 🖱️ **零窗口操作**:双击开界面,右键通过 DSH / TUI 分组子菜单一键启停,不用再碰命令行
18
- - 👁️ **独立旁观者**:托盘是独立常驻进程,dsh 停止时它依然在(显示未运行 + 一键启动),退出托盘不影响 dsh
19
- - 🎨 **浅色圆角菜单**:白底、圆角、投影阴影,贴合现代桌面应用审美
20
-
21
- ## 功能特性
22
-
23
- | 交互 | 行为 |
24
- | :--- | :--- |
25
- | **图标** | 蓝鲸鱼 = Web 运行中(PID);灰鲸鱼 = 未运行 |
26
- | **悬停提示** | `Web UI 运行中 · 127.0.0.1:3088` / `Web UI 未运行 · 右键可启动` |
27
- | **双击** | 打开 Web UI(未运行先提示启动) |
28
- | **右键菜单** | 顶部 `Web UI 状态` / `TUI 状态` 双状态行;`Web UI ▸`(打开 Web UI / 启动 / 停止(带确认) / 重启);`TUI ▸`(启动 / 停止);打开日志目录 / `版本信息 ▸`(版本 / 检查更新 / 更新到最新版)/ 退出托盘 |
29
- | **菜单智能禁用** | Web 运行中禁用「启动 Web UI」;TUI 运行中禁用「启动 TUI」 |
30
- | **自更新** | 「版本信息 ▸」子菜单(位于退出托盘上方,非日常功能区):查看版本 / 检查更新 / 一键更新到最新版(自动重部署 + 重启托盘) |
31
- | **状态通知** | Web/TUI 启动与停止瞬间弹系统通知;托盘就绪弹一次提示 |
32
- | **开机自启** | 登录后托盘自动出现(启动文件夹快捷方式,安装时自动创建) |
33
-
34
- ## 适配与依赖
35
-
36
- | 项 | 说明 |
37
- | :--- | :--- |
38
- | **dsh 内核** | 适配 `@deepseek-ai/dsh` **v0.1.1-rc.2 系列**(共享核心 `@deepseek-ai/dsh-base` 同版本);dsh 升级不影响托盘 |
39
- | **Web 服务** | dsh web 默认监听 `127.0.0.1:3088`(即浏览器里的 Web UI)——托盘通过 TCP 探测该端口判断 Web 状态(端口被改时同步修改 `dsh-lib.ps1` 的 `$PORT` 即可) |
40
- | **TUI 插件** | 适配 `@deepseek-harness-tui/dsh-tui` **^0.9.2**(通过 dsh-profile `dsh-profile-dsh-tui` 挂载);托盘按进程命令行 `dsh-tui` 检测,与插件版本解耦 |
41
- | **Node.js** | ≥ 18(dsh 本体运行所需) |
42
- | **PowerShell** | 7(托盘常驻进程;缺省回退 Windows PowerShell 5.1) |
43
- | **运行时依赖** | **零 npm 依赖**——纯 PowerShell + WinForms + 系统 API;托盘不修改 dsh、不注入任何内容,纯旁观者 |
44
-
45
- ## 界面预览
46
-
47
- | 运行中(品牌蓝 `#4176E6`) | 未运行(中性灰 `#81858C`) |
48
- | :---: | :---: |
49
- | ![running](build/dsh-tray-running-preview.png) | ![stopped](build/dsh-tray-stopped-preview.png) |
50
-
51
- > 图标源 = dsh Web 前端官方 favicon(鲸鱼),多尺寸 16~256px;可随时用 `dsh-tray icons` 重新生成。
52
-
53
- ## 快速开始
54
-
55
- 前置:Windows 10/11 + [PowerShell 7](https://github.com/PowerShell/PowerShell/releases)(7.x;缺失时自动回退 Windows PowerShell 5.1)+ Node.js **≥ 18** + 已安装 dsh(任意位置)。
56
-
57
- ```powershell
58
- # 1. 全局安装
59
- npm i -g dsh-windows-tray
60
-
61
- # 2. 一键部署(自动探测 dsh/pwsh/node 路径 → 安装到 ~\.dsh\launcher
62
- # → 按本机路径改写配置 → 创建开机自启+桌面快捷方式 → 启动托盘)
63
- dsh-tray install
64
-
65
- # 3. 首次使用:把任务栏 ^ 溢出区里的鲸鱼拖到任务栏(一次性,Windows 会记住)
66
- ```
67
-
68
- 部署完成后即可双击鲸鱼打开 Web UI,右键管理一切。
69
-
70
- ## 常用命令
71
-
72
- | 命令 | 作用 |
73
- | :--- | :--- |
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` 重部署) |
79
-
80
- ## 如何更新
81
-
82
- 两种方式任选:
83
-
84
- **方式一:托盘一键更新(推荐)**——托盘菜单「版本信息 ▸」→「检查更新」对比 npm 最新版,发现新版后点「更新到最新版」:自动 `npm install -g` → 重新部署(含本机路径改写)→ 自动重启托盘,全程约 1 分钟,失败不影响当前托盘。
85
-
86
- **方式二:npm 标准流程**——与普通 npm 包一致:
87
-
88
- ```powershell
89
- npm up -g dsh-windows-tray # 拉取最新版
90
- dsh-tray install # 重新部署(自动改写本机路径 + 刷新快捷方式)
91
- dsh-tray # 重启托盘(或右键「退出托盘」后重新登录/双击快捷方式)
92
- ```
93
-
94
- > 部署目录固定为 `~\.dsh\launcher`,重装/更新都会覆盖旧文件,不会残留;`dsh-tray info` 可查看当前版本与部署状态。
95
-
96
- ## 卸载
97
-
98
- ```powershell
99
- npm rm -g dsh-windows-tray # ① 移除 npm 包本体
100
- # ② 删除快捷方式: 启动文件夹 + 桌面 各一个「DSH 系统托盘.lnk」
101
- # ③ 删除部署目录 ~\.dsh\launcher (如与 dsh 控制台共用, 确认无需保留再删)
102
- ```
103
-
104
- ## 工作原理
105
-
106
- ```
107
- 托盘(pwsh 常驻) ──2s 轮询──► 127.0.0.1:3088 (Web UI 端口)
108
- │ └──────────────► node 进程命令行含 'dsh-tui' (TUI 进程)
109
- ├── 菜单动作 ──► dsh-actions.ps1 (独立隐藏进程, 不卡 UI)
110
- ├── 自更新 ──► dsh-update.ps1 (npm 安装→重部署→重启)
111
- └── 单实例 ──► 命名互斥锁 (被强杀遗留的锁自动接管)
112
- ```
113
-
114
- - **状态检测**:Web 用 TCP 端口探测(物理单实例);TUI 按命令行匹配(多实例安全:全查全杀);TUI 检测 20s 节流,打开菜单时强制刷新
115
- - **动作隔离**:启动/停止/重启在独立进程执行,托盘 UI 永不卡顿
116
- - **日志**:`~\.dsh\logs\dsh-tray.log`(状态变化)+ `dsh-tray-actions.log`(动作)
117
- - **单点配置**:端口/路径等常量集中在 `launcher/dsh-lib.ps1`,安装时按本机自动改写——**包本身与机器无关**
118
-
119
- ## 配置
120
-
121
- | 项 | 位置 | 默认 |
122
- | :--- | :--- | :--- |
123
- | 监控端口 | `~\.dsh\launcher\dsh-lib.ps1` 顶部 `$PORT` | `3088` |
124
- | dsh 路径 | 同上(安装时自动改写) | 自动探测 |
125
- | 图标颜色 | `build/build-tray-icons.ps1`(运行蓝/停止灰) | `#4176E6` / `#81858C` |
126
-
127
- ## 常见问题
128
-
129
- | 问题 | 处理 |
130
- | :--- | :--- |
131
- | 任务栏看不到鲸鱼 | 点开 `^` 溢出区,把鲸鱼拖到任务栏(一次性) |
132
- | 停止 Web UI 会关掉浏览器界面 | 对——停止前有确认框;Web 与当前会话在 3088 端口上 |
133
- | 托盘退出了怎么唤回 | 双击桌面「DSH 系统托盘」快捷方式 / 重新登录(开机自启)/ `dsh-tray` |
134
- | 怎么更新到新版 | 托盘菜单「版本信息 ▸ → 更新到最新版」一键完成;或 `npm up -g dsh-windows-tray` + `dsh-tray install`(见「如何更新」) |
135
- | 检查更新失败 | 网络或 npm 不可用;托盘继续正常工作,稍后再试 |
136
- | dsh 内核升级了,托盘要动吗 | 不用——托盘只探测 3088 端口与 TUI 进程命令行,与内核版本解耦 |
137
- | 想彻底卸载 | `npm rm -g dsh-windows-tray` + 删除两个「DSH 系统托盘.lnk」+ 删除 `~\.dsh\launcher` |
138
-
139
- ## 文档
140
-
141
- - `docs/system-tray-guide.md` — 使用手册(安装部署 / 功能一览 / 更新 / 卸载 / 故障排查)
142
- - `docs/tray-dev-archive.md` — 开发归档(架构决策与历史记录)
143
-
144
- ## 许可
145
-
146
- MIT
1
+ # dsh-windows-tray
2
+
3
+ > DeepSeek Harness(dsh)的 Windows 系统托盘管家:**官方鲸鱼状态图标 + Web/TUI 双状态显示 + 一键启停**。
4
+ > 纯 PowerShell + WinForms 实现,零依赖、无编译、不改 dsh 源码,卸载即还原。
5
+
6
+ [![npm](https://img.shields.io/npm/v/dsh-windows-tray?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
7
+ [![npm downloads](https://img.shields.io/npm/dm/dsh-windows-tray?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
8
+ [![Platform](https://img.shields.io/badge/platform-Windows%2010%2F11-blue?style=flat-square)](https://www.npmjs.com/package/dsh-windows-tray)
9
+ [![License](https://img.shields.io/npm/l/dsh-windows-tray?style=flat-square)](https://github.com/)
10
+
11
+ ## 是什么
12
+
13
+ dsh 默认在终端前台运行 `dsh web`——必须留着一个命令行窗口。本工具把它变成**一个标准的 Windows 托盘应用**:
14
+
15
+ - 🐋 **状态一目了然**:品牌蓝鲸鱼 = Web 运行中;灰鲸鱼 = 未运行(图标由官方 favicon 渲染生成)
16
+ - 📊 **DSH / TUI 双状态**:菜单顶部同屏显示 Web 与 TUI 各自的运行状态(含 PID),互不干扰
17
+ - 🖱️ **零窗口操作**:双击开界面,右键通过 DSH / TUI 分组子菜单一键启停,不用再碰命令行
18
+ - 👁️ **独立旁观者**:托盘是独立常驻进程,dsh 停止时它依然在(显示未运行 + 一键启动),退出托盘不影响 dsh
19
+ - 🎨 **浅色圆角菜单**:白底、圆角、投影阴影,贴合现代桌面应用审美
20
+
21
+ ## 功能特性
22
+
23
+ | 交互 | 行为 |
24
+ | :--- | :--- |
25
+ | **图标** | 蓝鲸鱼 = Web 运行中(PID);灰鲸鱼 = 未运行 |
26
+ | **悬停提示** | `Web UI 运行中 · 127.0.0.1:3088` / `Web UI 未运行 · 右键可启动` |
27
+ | **双击** | 打开 Web UI(未运行先提示启动) |
28
+ | **右键菜单** | 顶部 `Web UI 状态` / `TUI 状态` 双状态行;`Web UI ▸`(打开 Web UI / 启动 / 停止(带确认) / 重启);`TUI ▸`(启动 / 停止);打开日志目录 / `版本信息 ▸`(版本 / 检查更新 / 更新到最新版)/ 退出托盘 |
29
+ | **菜单智能禁用** | Web 运行中禁用「启动 Web UI」;TUI 运行中禁用「启动 TUI」 |
30
+ | **自更新** | 「版本信息 ▸」子菜单(位于退出托盘上方,非日常功能区):查看版本 / 检查更新 / 一键更新到最新版(自动重部署 + 重启托盘) |
31
+ | **状态通知** | Web/TUI 启动与停止瞬间弹系统通知;托盘就绪弹一次提示 |
32
+ | **开机自启** | 登录后托盘自动出现(启动文件夹快捷方式,安装时自动创建) |
33
+
34
+ ## 适配与依赖
35
+
36
+ | 项 | 说明 |
37
+ | :--- | :--- |
38
+ | **dsh 内核** | 适配 `@deepseek-ai/dsh` **v0.1.1-rc.2 系列**(共享核心 `@deepseek-ai/dsh-base` 同版本);dsh 升级不影响托盘 |
39
+ | **Web 服务** | dsh web 默认监听 `127.0.0.1:3088`(即浏览器里的 Web UI)——托盘通过 TCP 探测该端口判断 Web 状态(端口被改时同步修改 `dsh-lib.ps1` 的 `$PORT` 即可) |
40
+ | **TUI 插件** | 适配 `@deepseek-harness-tui/dsh-tui` **^0.9.2**(通过 dsh-profile `dsh-profile-dsh-tui` 挂载);托盘按进程命令行 `dsh-tui` 检测,与插件版本解耦 |
41
+ | **Node.js** | ≥ 18(dsh 本体运行所需) |
42
+ | **PowerShell** | 7(托盘常驻进程;缺省回退 Windows PowerShell 5.1) |
43
+ | **运行时依赖** | **零 npm 依赖**——纯 PowerShell + WinForms + 系统 API;托盘不修改 dsh、不注入任何内容,纯旁观者 |
44
+
45
+ ## 界面预览
46
+
47
+ | 运行中(品牌蓝 `#4176E6`) | 未运行(中性灰 `#81858C`) |
48
+ | :---: | :---: |
49
+ | ![running](build/dsh-tray-running-preview.png) | ![stopped](build/dsh-tray-stopped-preview.png) |
50
+
51
+ > 图标源 = dsh Web 前端官方 favicon(鲸鱼),多尺寸 16~256px;可随时用 `dsh-tray icons` 重新生成。
52
+
53
+ ## 快速开始
54
+
55
+ 前置:Windows 10/11 + [PowerShell 7](https://github.com/PowerShell/PowerShell/releases)(7.x;缺失时自动回退 Windows PowerShell 5.1)+ Node.js **≥ 18** + 已安装 dsh(任意位置)。
56
+
57
+ ```powershell
58
+ # 1. 全局安装
59
+ npm i -g dsh-windows-tray
60
+
61
+ # 2. 一键部署(自动探测 dsh/pwsh/node 路径 → 安装到 ~\.dsh\launcher
62
+ # → 按本机路径改写配置 → 创建开机自启+桌面快捷方式 → 启动托盘)
63
+ dsh-tray install
64
+
65
+ # 3. 首次使用:把任务栏 ^ 溢出区里的鲸鱼拖到任务栏(一次性,Windows 会记住)
66
+ ```
67
+
68
+ 部署完成后即可双击鲸鱼打开 Web UI,右键管理一切。
69
+
70
+ ## 常用命令
71
+
72
+ | 命令 | 作用 |
73
+ | :--- | :--- |
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` 重部署) |
79
+
80
+ ## 如何更新
81
+
82
+ 两种方式任选:
83
+
84
+ **方式一:托盘一键更新(推荐)**——托盘菜单「版本信息 ▸」→「检查更新」对比 npm 最新版,发现新版后点「更新到最新版」:自动 `npm install -g` → 重新部署(含本机路径改写)→ 自动重启托盘,全程约 1 分钟,失败不影响当前托盘。
85
+
86
+ **方式二:npm 标准流程**——与普通 npm 包一致:
87
+
88
+ ```powershell
89
+ npm up -g dsh-windows-tray # 拉取最新版
90
+ dsh-tray install # 重新部署(自动改写本机路径 + 刷新快捷方式)
91
+ dsh-tray # 重启托盘(或右键「退出托盘」后重新登录/双击快捷方式)
92
+ ```
93
+
94
+ > 部署目录固定为 `~\.dsh\launcher`,重装/更新都会覆盖旧文件,不会残留;`dsh-tray info` 可查看当前版本与部署状态。
95
+
96
+ ## 卸载
97
+
98
+ ```powershell
99
+ npm rm -g dsh-windows-tray # ① 移除 npm 包本体
100
+ # ② 删除快捷方式: 启动文件夹 + 桌面 各一个「DSH 系统托盘.lnk」
101
+ # ③ 删除部署目录 ~\.dsh\launcher (如与 dsh 控制台共用, 确认无需保留再删)
102
+ ```
103
+
104
+ ## 工作原理
105
+
106
+ ```
107
+ 托盘(pwsh 常驻) ──2s 轮询──► 127.0.0.1:3088 (Web UI 端口)
108
+ │ └──────────────► node 进程命令行含 'dsh-tui' (TUI 进程)
109
+ ├── 菜单动作 ──► dsh-actions.ps1 (独立隐藏进程, 不卡 UI)
110
+ ├── 自更新 ──► dsh-update.ps1 (npm 安装→重部署→重启)
111
+ └── 单实例 ──► 命名互斥锁 (被强杀遗留的锁自动接管)
112
+ ```
113
+
114
+ - **状态检测**:Web 用 TCP 端口探测(物理单实例);TUI 按命令行匹配(多实例安全:全查全杀);TUI 检测 20s 节流,打开菜单时强制刷新
115
+ - **动作隔离**:启动/停止/重启在独立进程执行,托盘 UI 永不卡顿
116
+ - **日志**:`~\.dsh\logs\dsh-tray.log`(状态变化)+ `dsh-tray-actions.log`(动作)
117
+ - **单点配置**:端口/路径等常量集中在 `launcher/dsh-lib.ps1`,安装时按本机自动改写——**包本身与机器无关**
118
+
119
+ ## 配置
120
+
121
+ | 项 | 位置 | 默认 |
122
+ | :--- | :--- | :--- |
123
+ | 监控端口 | `~\.dsh\launcher\dsh-lib.ps1` 顶部 `$PORT` | `3088` |
124
+ | dsh 路径 | 同上(安装时自动改写) | 自动探测 |
125
+ | 图标颜色 | `build/build-tray-icons.ps1`(运行蓝/停止灰) | `#4176E6` / `#81858C` |
126
+
127
+ ## 常见问题
128
+
129
+ | 问题 | 处理 |
130
+ | :--- | :--- |
131
+ | 任务栏看不到鲸鱼 | 点开 `^` 溢出区,把鲸鱼拖到任务栏(一次性) |
132
+ | 停止 Web UI 会关掉浏览器界面 | 对——停止前有确认框;Web 与当前会话在 3088 端口上 |
133
+ | 托盘退出了怎么唤回 | 双击桌面「DSH 系统托盘」快捷方式 / 重新登录(开机自启)/ `dsh-tray` |
134
+ | 怎么更新到新版 | 托盘菜单「版本信息 ▸ → 更新到最新版」一键完成;或 `npm up -g dsh-windows-tray` + `dsh-tray install`(见「如何更新」) |
135
+ | 检查更新失败 | 网络或 npm 不可用;托盘继续正常工作,稍后再试 |
136
+ | dsh 内核升级了,托盘要动吗 | 不用——托盘只探测 3088 端口与 TUI 进程命令行,与内核版本解耦 |
137
+ | 想彻底卸载 | `npm rm -g dsh-windows-tray` + 删除两个「DSH 系统托盘.lnk」+ 删除 `~\.dsh\launcher` |
138
+
139
+ ## 文档
140
+
141
+ - `docs/system-tray-guide.md` — 使用手册(安装部署 / 功能一览 / 更新 / 卸载 / 故障排查)
142
+ - `docs/tray-dev-archive.md` — 开发归档(架构决策与历史记录)
143
+
144
+ ## 许可
145
+
146
+ MIT
@@ -1,9 +1,9 @@
1
- <!DOCTYPE html><html><head><meta charset='utf-8'><style>html,body{margin:0;padding:0;background:#ffffff;overflow:hidden}</style></head><body><svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 50 50" fill="none">
2
- <style>
3
- @media (prefers-color-scheme: dark) {
4
- path { fill: #fff; }
5
- }
6
- </style>
7
- <path id="path" d="M48.8354 10.0479C48.3232 9.79199 48.1025 10.2798 47.8032 10.5278C47.7007 10.6079 47.6143 10.7119 47.5273 10.8076C46.7793 11.624 45.9048 12.1597 44.7622 12.0957C43.0923 12 41.666 12.5356 40.4058 13.8398C40.1377 12.2319 39.2476 11.272 37.8926 10.6558C37.1836 10.3359 36.4668 10.0156 35.9702 9.31982C35.6235 8.82373 35.5293 8.27197 35.356 7.72754C35.2456 7.3999 35.1353 7.06396 34.7651 7.00781C34.3633 6.94385 34.2056 7.2876 34.0479 7.57568C33.418 8.75195 33.1733 10.0479 33.1973 11.3599C33.2524 14.312 34.4736 16.6641 36.8999 18.3359C37.1758 18.5278 37.2466 18.7197 37.1597 19C36.9946 19.5757 36.7974 20.1357 36.624 20.7119C36.5137 21.0801 36.3486 21.1597 35.9624 21C34.6309 20.4321 33.481 19.5918 32.4644 18.5757C30.7393 16.8721 29.1792 14.9917 27.2334 13.52C26.7764 13.1758 26.3193 12.856 25.8467 12.5518C23.8618 10.584 26.1069 8.96777 26.627 8.77588C27.1704 8.57568 26.8159 7.8877 25.0591 7.896C23.3022 7.90381 21.6953 8.50391 19.647 9.30371C19.3477 9.42383 19.0322 9.51172 18.7095 9.58398C16.8501 9.22363 14.9199 9.14355 12.9033 9.37598C9.10596 9.80762 6.07275 11.6396 3.84326 14.7681C1.16455 18.5278 0.53418 22.7998 1.30664 27.2559C2.11768 31.9521 4.46582 35.8398 8.07373 38.8799C11.8159 42.0322 16.1255 43.5762 21.041 43.2803C24.0269 43.104 27.3516 42.6963 31.1016 39.4561C32.0469 39.936 33.0396 40.1279 34.686 40.272C35.9546 40.3921 37.1758 40.208 38.1211 40.0078C39.6021 39.688 39.4995 38.2881 38.9639 38.0322C34.623 35.9678 35.5762 36.8081 34.71 36.1279C36.9155 33.4639 40.2402 30.6958 41.54 21.728C41.6426 21.0161 41.5557 20.5679 41.54 19.9917C41.5322 19.6396 41.6108 19.5039 42.0049 19.4639C43.0923 19.3359 44.1479 19.0317 45.1167 18.4878C47.9292 16.9199 49.064 14.3438 49.3315 11.2559C49.3711 10.7837 49.3237 10.2959 48.8354 10.0479ZM24.3262 37.8398C20.1196 34.4639 18.0791 33.3521 17.2358 33.3999C16.4482 33.4482 16.5898 34.3682 16.7632 34.9678C16.9443 35.5601 17.1812 35.9683 17.5117 36.4878C17.7402 36.832 17.8979 37.3442 17.2832 37.728C15.9282 38.584 13.5728 37.4399 13.4624 37.3838C10.7207 35.7358 8.42822 33.5601 6.81348 30.584C5.25342 27.7197 4.34766 24.6479 4.19775 21.3677C4.1582 20.5757 4.38672 20.2959 5.15869 20.1519C6.17529 19.96 7.22314 19.9199 8.23926 20.0718C12.5327 20.7119 16.1885 22.6719 19.2529 25.7759C21.002 27.5439 22.3252 29.6558 23.6885 31.7202C25.1377 33.9121 26.6978 36 28.6831 37.7119C29.3843 38.312 29.9434 38.7681 30.479 39.104C28.8643 39.2881 26.1699 39.3281 24.3262 37.8398ZM26.3433 24.6001C26.3433 24.248 26.6191 23.9678 26.9658 23.9678C27.0444 23.9678 27.1152 23.9839 27.1782 24.0078C27.2651 24.04 27.3438 24.0879 27.4067 24.1602C27.5171 24.272 27.5801 24.4321 27.5801 24.6001C27.5801 24.9521 27.3042 25.2319 26.9575 25.2319C26.6108 25.2319 26.3433 24.9521 26.3433 24.6001ZM32.6064 27.8799C32.2046 28.0479 31.8027 28.1919 31.4165 28.208C30.8179 28.2397 30.1641 27.9922 29.8096 27.688C29.2583 27.2158 28.8643 26.9521 28.6987 26.1279C28.6279 25.7759 28.6675 25.2319 28.7305 24.9199C28.8721 24.248 28.7144 23.8159 28.2495 23.4238C27.8716 23.104 27.3911 23.0161 26.8633 23.0161C26.666 23.0161 26.4849 22.9277 26.3511 22.856C26.1304 22.7441 25.9492 22.4639 26.1226 22.1201C26.1777 22.0078 26.4458 21.7358 26.5088 21.688C27.2256 21.272 28.0527 21.4077 28.8169 21.7197C29.5259 22.0161 30.0615 22.5601 30.834 23.3281C31.6216 24.2559 31.7632 24.5117 32.2124 25.208C32.5669 25.752 32.8901 26.312 33.1104 26.9521C33.2446 27.3521 33.0713 27.6802 32.6064 27.8799Z" fill="#000" fill-opacity="1.000000" fill-rule="nonzero"/>
8
- </svg>
1
+ <!DOCTYPE html><html><head><meta charset='utf-8'><style>html,body{margin:0;padding:0;background:#ffffff;overflow:hidden}</style></head><body><svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 50 50" fill="none">
2
+ <style>
3
+ @media (prefers-color-scheme: dark) {
4
+ path { fill: #fff; }
5
+ }
6
+ </style>
7
+ <path id="path" d="M48.8354 10.0479C48.3232 9.79199 48.1025 10.2798 47.8032 10.5278C47.7007 10.6079 47.6143 10.7119 47.5273 10.8076C46.7793 11.624 45.9048 12.1597 44.7622 12.0957C43.0923 12 41.666 12.5356 40.4058 13.8398C40.1377 12.2319 39.2476 11.272 37.8926 10.6558C37.1836 10.3359 36.4668 10.0156 35.9702 9.31982C35.6235 8.82373 35.5293 8.27197 35.356 7.72754C35.2456 7.3999 35.1353 7.06396 34.7651 7.00781C34.3633 6.94385 34.2056 7.2876 34.0479 7.57568C33.418 8.75195 33.1733 10.0479 33.1973 11.3599C33.2524 14.312 34.4736 16.6641 36.8999 18.3359C37.1758 18.5278 37.2466 18.7197 37.1597 19C36.9946 19.5757 36.7974 20.1357 36.624 20.7119C36.5137 21.0801 36.3486 21.1597 35.9624 21C34.6309 20.4321 33.481 19.5918 32.4644 18.5757C30.7393 16.8721 29.1792 14.9917 27.2334 13.52C26.7764 13.1758 26.3193 12.856 25.8467 12.5518C23.8618 10.584 26.1069 8.96777 26.627 8.77588C27.1704 8.57568 26.8159 7.8877 25.0591 7.896C23.3022 7.90381 21.6953 8.50391 19.647 9.30371C19.3477 9.42383 19.0322 9.51172 18.7095 9.58398C16.8501 9.22363 14.9199 9.14355 12.9033 9.37598C9.10596 9.80762 6.07275 11.6396 3.84326 14.7681C1.16455 18.5278 0.53418 22.7998 1.30664 27.2559C2.11768 31.9521 4.46582 35.8398 8.07373 38.8799C11.8159 42.0322 16.1255 43.5762 21.041 43.2803C24.0269 43.104 27.3516 42.6963 31.1016 39.4561C32.0469 39.936 33.0396 40.1279 34.686 40.272C35.9546 40.3921 37.1758 40.208 38.1211 40.0078C39.6021 39.688 39.4995 38.2881 38.9639 38.0322C34.623 35.9678 35.5762 36.8081 34.71 36.1279C36.9155 33.4639 40.2402 30.6958 41.54 21.728C41.6426 21.0161 41.5557 20.5679 41.54 19.9917C41.5322 19.6396 41.6108 19.5039 42.0049 19.4639C43.0923 19.3359 44.1479 19.0317 45.1167 18.4878C47.9292 16.9199 49.064 14.3438 49.3315 11.2559C49.3711 10.7837 49.3237 10.2959 48.8354 10.0479ZM24.3262 37.8398C20.1196 34.4639 18.0791 33.3521 17.2358 33.3999C16.4482 33.4482 16.5898 34.3682 16.7632 34.9678C16.9443 35.5601 17.1812 35.9683 17.5117 36.4878C17.7402 36.832 17.8979 37.3442 17.2832 37.728C15.9282 38.584 13.5728 37.4399 13.4624 37.3838C10.7207 35.7358 8.42822 33.5601 6.81348 30.584C5.25342 27.7197 4.34766 24.6479 4.19775 21.3677C4.1582 20.5757 4.38672 20.2959 5.15869 20.1519C6.17529 19.96 7.22314 19.9199 8.23926 20.0718C12.5327 20.7119 16.1885 22.6719 19.2529 25.7759C21.002 27.5439 22.3252 29.6558 23.6885 31.7202C25.1377 33.9121 26.6978 36 28.6831 37.7119C29.3843 38.312 29.9434 38.7681 30.479 39.104C28.8643 39.2881 26.1699 39.3281 24.3262 37.8398ZM26.3433 24.6001C26.3433 24.248 26.6191 23.9678 26.9658 23.9678C27.0444 23.9678 27.1152 23.9839 27.1782 24.0078C27.2651 24.04 27.3438 24.0879 27.4067 24.1602C27.5171 24.272 27.5801 24.4321 27.5801 24.6001C27.5801 24.9521 27.3042 25.2319 26.9575 25.2319C26.6108 25.2319 26.3433 24.9521 26.3433 24.6001ZM32.6064 27.8799C32.2046 28.0479 31.8027 28.1919 31.4165 28.208C30.8179 28.2397 30.1641 27.9922 29.8096 27.688C29.2583 27.2158 28.8643 26.9521 28.6987 26.1279C28.6279 25.7759 28.6675 25.2319 28.7305 24.9199C28.8721 24.248 28.7144 23.8159 28.2495 23.4238C27.8716 23.104 27.3911 23.0161 26.8633 23.0161C26.666 23.0161 26.4849 22.9277 26.3511 22.856C26.1304 22.7441 25.9492 22.4639 26.1226 22.1201C26.1777 22.0078 26.4458 21.7358 26.5088 21.688C27.2256 21.272 28.0527 21.4077 28.8169 21.7197C29.5259 22.0161 30.0615 22.5601 30.834 23.3281C31.6216 24.2559 31.7632 24.5117 32.2124 25.208C32.5669 25.752 32.8901 26.312 33.1104 26.9521C33.2446 27.3521 33.0713 27.6802 32.6064 27.8799Z" fill="#000" fill-opacity="1.000000" fill-rule="nonzero"/>
8
+ </svg>
9
9
  </body></html>
@@ -1,133 +1,133 @@
1
- # DSH 系统托盘(Windows)—— npm 包使用手册
2
-
3
- > 包名: **`dsh-windows-tray`** · 部署位置: `~\.dsh\launcher` · 技术栈: PowerShell 7 + WinForms,零 npm 依赖、纯旁观者、不改 dsh 源码。
4
- > 安装 / 更新 / 卸载全部走 npm 标准流程;开发归档见 [tray-dev-archive.md](tray-dev-archive.md),相关踩坑见 [powershell-pitfalls.md](powershell-pitfalls.md)。
5
-
6
- ---
7
-
8
- ## 一、安装与部署
9
-
10
- 前置:Windows 10/11 + [PowerShell 7](https://github.com/PowerShell/PowerShell/releases)(7.x;缺失时自动回退 Windows PowerShell 5.1)+ Node.js **≥ 18** + 已安装 dsh(任意位置)。
11
-
12
- ```powershell
13
- # 1. 全局安装
14
- npm i -g dsh-windows-tray
15
-
16
- # 2. 一键部署:自动探测 dsh/pwsh/node 路径 → 安装到 ~\.dsh\launcher
17
- # → 按本机路径改写配置 → 创建开机自启 + 桌面快捷方式 → 启动托盘
18
- dsh-tray install
19
-
20
- # 3. 首次使用:把任务栏 ^ 溢出区里的鲸鱼拖到任务栏(一次性,Windows 会记住)
21
- ```
22
-
23
- ### 安装后必做:本机参数探测 → 确认 → 回填(不要信默认值)
24
-
25
- install 只自动改写 dsh/pwsh/node **路径**;**端口、数据目录按包默认值写入且不改**。与本机实际不一致时,症状是托盘永远灰鲸(探测错端口)或托盘/控制台启动的 web 落到空数据目录。先实测,人工确认数值,再回填到 §六 列出的**全部**填充点(只改一处会被另一处覆盖):
26
-
27
- ```powershell
28
- # 实际 Web 端口:看运行中的 web 进程命令行(没在跑就看本机控制台/启动脚本里的启动命令)
29
- Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
30
- Where-Object { $_.CommandLine -like '*web*' } |
31
- ForEach-Object { $_.CommandLine } # 输出里找 --port NNNN 与 --host
32
-
33
- # 实际数据目录:找带 settings.yaml + skins/ + profiles/ 的目录(默认 ~\.dsh,自定义部署不在那)
34
- Test-Path "$env:USERPROFILE\.dsh\settings.yaml" # True=默认目录;False=自定义 DSH_HOME,必须回填
35
- ```
36
-
37
- 常用命令:
38
-
39
- | 命令 | 作用 |
40
- | :--- | :--- |
41
- | `dsh-tray` | 启动托盘(已有实例则提示,不重复启动) |
42
- | `dsh-tray install` | 一键部署 / 重新部署(可透传 `-DshRoot` 等参数) |
43
- | `dsh-tray icons` | 重新生成鲸鱼图标(内置 512px 源图,无需浏览器) |
44
- | `dsh-tray info` | 查看版本 / 安装位置 / 部署状态 |
45
-
46
- ## 二、功能一览
47
-
48
- | 交互 | 行为 |
49
- | :--- | :--- |
50
- | **图标** | 🐋 品牌蓝鲸鱼 = Web 运行中;灰鲸鱼 = 未运行(官方 favicon 渲染,多尺寸 16~256px) |
51
- | **悬停提示** | `Web UI 运行中 · 127.0.0.1:3088` / `Web UI 未运行 · 右键可启动` |
52
- | **双击** | 打开 Web UI(未运行时提示先启动) |
53
- | **右键菜单** | 顶部 `Web UI 状态` / `TUI 状态` 双状态行(含 PID);`Web UI ▸`(打开 Web UI / 启动 / 停止(带确认) / 重启);`TUI ▸`(启动 / 停止);打开日志目录 / `版本信息 ▸`(版本 / 检查更新 / 更新到最新版)/ 退出托盘 |
54
- | **菜单智能禁用** | Web 运行中禁用「启动 Web UI」;TUI 运行中禁用「启动 TUI」 |
55
- | **状态通知** | Web/TUI 启动与停止瞬间弹系统通知;托盘就绪弹一次提示 |
56
- | **开机自启** | 登录后托盘自动出现(启动文件夹快捷方式,安装时自动创建) |
57
-
58
- 托盘每 2 秒探测一次 `127.0.0.1:3088`(TCP 连接,500ms 超时,开销可忽略);菜单动作在独立隐藏进程执行,托盘 UI 永不卡顿。
59
-
60
- ## 三、日常使用
61
-
62
- 1. **自动跟随**:在 dsh 控制台(`~\.dsh\launcher\dsh-control.ps1`)执行 启动/重启 Web 时,托盘会自动拉起(幂等)。
63
- 2. **手动唤起**:双击桌面「DSH 系统托盘」快捷方式;或 `dsh-tray`。
64
- 3. **退出托盘**:右键 → 退出托盘(只退出托盘本身,不影响 dsh;下次登录/双击快捷方式可重新唤起)。
65
- 4. **取消自启**:删除启动文件夹里的「DSH 系统托盘.lnk」。
66
-
67
- ## 四、更新
68
-
69
- 两种方式任选:
70
-
71
- **方式一:托盘一键更新(推荐)**——托盘菜单「版本信息 ▸」→「检查更新」对比 npm 最新版,发现新版后点「更新到最新版」:自动 `npm install -g` → 重新部署(含本机路径改写)→ 自动重启托盘,失败不影响当前托盘。
72
-
73
- **方式二:npm 标准流程**:
74
-
75
- ```powershell
76
- npm up -g dsh-windows-tray # 拉取最新版
77
- dsh-tray install # 重新部署(自动改写本机路径 + 刷新快捷方式)
78
- dsh-tray # 重启托盘
79
- ```
80
-
81
- > 部署目录固定为 `~\.dsh\launcher`,重装/更新会覆盖旧文件,不会残留;`dsh-tray info` 可查看当前版本与部署状态。
82
- > ⚠️ 更新 = 重新 install,**本机手工适配(端口/数据目录等,见 §六)会被一并覆盖**——更新后按对照表重做并重启托盘,别只看安装输出就收工。
83
-
84
- ## 五、卸载
85
-
86
- ```powershell
87
- npm rm -g dsh-windows-tray # 移除 npm 包本体
88
- # 删除两个「DSH 系统托盘.lnk」(启动文件夹 + 桌面)
89
- # 删除 ~\.dsh\launcher 目录(托盘部署文件;如与 dsh 控制台共用,确认无需保留再删)
90
- ```
91
-
92
- ## 六、配置
93
-
94
- > **先探测实际值再回填,不要照抄默认列**(探测命令见 §一"安装后必做")。同一参数可能有多个填充点,缺改一处就被另一处覆盖。
95
-
96
- | 项 | 位置 | 包默认 | 说明 |
97
- | :--- | :--- | :--- | :--- |
98
- | 监控端口 | ① `~\.dsh\launcher\dsh-lib.ps1` 顶部 `$PORT`;② `dsh-tray.ps1` 顶部 `param([int]$Port = …)` | `3088` | **两处必须一致**:托盘启动时先点源 lib 再执行 `$PORT = $Port`,**param 默认值会把 lib 改好的端口覆盖回去**(dsh-tray.ps1 第 27 行)——只改 lib 不改 param,托盘仍按默认端口探测 |
99
- | dsh 路径 | `dsh-lib.ps1` 顶部 `$DSH_CMD / $NODE / $BIN` | 自动探测 | install 已改写,一般不用动 |
100
- | 数据目录 | `dsh-lib.ps1` `$WORKDIR` + `$env:DSH_HOME` | **不设置** | 不设 DSH_HOME 时 web 默认落 `~\.dsh`——自定义数据目录的机器(如 `D:\dsh`)必须在 lib 里补 `$env:DSH_HOME`,否则托盘/控制台启动的 web 指向空目录 |
101
- | 日志目录 | `dsh-lib.ps1` `$LOG_DIR`(`~\.dsh\logs`) | — | **目录须存在**:不存在时托盘 `Add-Content -ErrorAction SilentlyContinue` 静默吞日志,零日志不是没在记 |
102
- | 图标颜色 | 包内 `build/build-tray-icons.ps1`(运行蓝/停止灰) | `#4176E6` / `#81858C` | — |
103
-
104
- > ⚠️ `~\.dsh\launcher` 是部署产物,`dsh-tray install`/更新每次整体覆盖——上表手工适配重装后须重新应用(对照下表逐项核对,别凭记忆)。
105
-
106
- ### 6.1 本机落地对照(跨机器对照用,照此逐项核对)
107
-
108
- | 项 | 包默认 | 笔记本实际(2026-08-27 实测) | 填充点 |
109
- | :--- | :--- | :--- | :--- |
110
- | Web 端口 | 3088 | **3080** | dsh-lib.ps1 `$PORT` + dsh-tray.ps1 param 默认值(两处) |
111
- | 数据目录 | 不设→`~\.dsh` | **D:\dsh** | dsh-lib.ps1 `$WORKDIR='D:\dsh'` + `$env:DSH_HOME='D:\dsh'` |
112
- | 日志目录 | `~\.dsh\logs`(可能不存在) | 已手动创建 | — |
113
- | 旧控制台 | — | `D:\dsh\launcher\dsh-control.ps1` 与托盘部署并存,端口同为 3080 | 无需合并 |
114
- | 装完验证 | — | `tail ~/.dsh/logs/dsh-tray.log` 应有「托盘启动 (…端口 3080)」;重启 web 应看到「状态: 未运行 → 运行中」翻转 | — |
115
-
116
- ## 七、故障排查
117
-
118
- | 现象 | 处理 |
119
- | :--- | :--- |
120
- | web 明明在跑,托盘灰鲸/悬停显示"未运行" | 端口填充点不一致(十有八九是 `dsh-tray.ps1` 的 param 默认值把 lib 改好的端口覆盖回去了)——`tail ~\.dsh\logs\dsh-tray.log` 看「托盘启动」行的实际端口,对照 §六/§6.1 把两处改齐后重启托盘 |
121
- | 托盘零日志 | `~\.dsh\logs` 目录不存在,托盘写日志被静默吞掉——建目录后重启托盘;重启 web 应立即出现状态翻转记录 |
122
- | 任务栏看不到鲸鱼 | 点开 `^` 溢出区查找;若在,拖到任务栏(一次性)。 |
123
- | 托盘图标消失 / 进程死了 | `dsh-tray` 或双击桌面快捷方式重新唤起;托盘退出不影响 dsh。 |
124
- | 动作没反应 | 看 `~\.dsh\logs\dsh-tray-actions.log`(菜单动作)与 `dsh-tray.log`(状态变化)。 |
125
- | 重复实例 | 命名互斥锁单实例保护(被强杀遗留的锁自动接管),正常不会重复。 |
126
- | 检查更新失败 | 网络或 npm 不可用;托盘继续正常工作,稍后再试。 |
127
- | dsh 内核升级了,托盘要动吗 | 不用——托盘只探测 3088 端口与 TUI 进程命令行,与内核版本解耦。 |
128
-
129
- ## 八、已知边界
130
-
131
- - 通知弹窗受 Windows「通知设置/专注助手」控制,被系统屏蔽时图标与菜单不受影响。
132
- - 托盘进程是 `pwsh`,`taskkill /T` 杀进程树会连托盘一起结束(下次登录/快捷方式/控制台操作时恢复)。
133
- - 端口探测只区分 运行/停止:3088 被其他程序占用时会误判"运行中"。
1
+ # DSH 系统托盘(Windows)—— npm 包使用手册
2
+
3
+ > 包名: **`dsh-windows-tray`** · 部署位置: `~\.dsh\launcher` · 技术栈: PowerShell 7 + WinForms,零 npm 依赖、纯旁观者、不改 dsh 源码。
4
+ > 安装 / 更新 / 卸载全部走 npm 标准流程;开发归档见 [tray-dev-archive.md](tray-dev-archive.md),相关踩坑见 [powershell-pitfalls.md](powershell-pitfalls.md)。
5
+
6
+ ---
7
+
8
+ ## 一、安装与部署
9
+
10
+ 前置:Windows 10/11 + [PowerShell 7](https://github.com/PowerShell/PowerShell/releases)(7.x;缺失时自动回退 Windows PowerShell 5.1)+ Node.js **≥ 18** + 已安装 dsh(任意位置)。
11
+
12
+ ```powershell
13
+ # 1. 全局安装
14
+ npm i -g dsh-windows-tray
15
+
16
+ # 2. 一键部署:自动探测 dsh/pwsh/node 路径 → 安装到 ~\.dsh\launcher
17
+ # → 按本机路径改写配置 → 创建开机自启 + 桌面快捷方式 → 启动托盘
18
+ dsh-tray install
19
+
20
+ # 3. 首次使用:把任务栏 ^ 溢出区里的鲸鱼拖到任务栏(一次性,Windows 会记住)
21
+ ```
22
+
23
+ ### 安装后必做:本机参数探测 → 确认 → 回填(不要信默认值)
24
+
25
+ install 只自动改写 dsh/pwsh/node **路径**;**端口、数据目录按包默认值写入且不改**。与本机实际不一致时,症状是托盘永远灰鲸(探测错端口)或托盘/控制台启动的 web 落到空数据目录。先实测,人工确认数值,再回填到 §六 列出的**全部**填充点(只改一处会被另一处覆盖):
26
+
27
+ ```powershell
28
+ # 实际 Web 端口:看运行中的 web 进程命令行(没在跑就看本机控制台/启动脚本里的启动命令)
29
+ Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
30
+ Where-Object { $_.CommandLine -like '*web*' } |
31
+ ForEach-Object { $_.CommandLine } # 输出里找 --port NNNN 与 --host
32
+
33
+ # 实际数据目录:找带 settings.yaml + skins/ + profiles/ 的目录(默认 ~\.dsh,自定义部署不在那)
34
+ Test-Path "$env:USERPROFILE\.dsh\settings.yaml" # True=默认目录;False=自定义 DSH_HOME,必须回填
35
+ ```
36
+
37
+ 常用命令:
38
+
39
+ | 命令 | 作用 |
40
+ | :--- | :--- |
41
+ | `dsh-tray` | 启动托盘(已有实例则提示,不重复启动) |
42
+ | `dsh-tray install` | 一键部署 / 重新部署(可透传 `-DshRoot` 等参数) |
43
+ | `dsh-tray icons` | 重新生成鲸鱼图标(内置 512px 源图,无需浏览器) |
44
+ | `dsh-tray info` | 查看版本 / 安装位置 / 部署状态 |
45
+
46
+ ## 二、功能一览
47
+
48
+ | 交互 | 行为 |
49
+ | :--- | :--- |
50
+ | **图标** | 🐋 品牌蓝鲸鱼 = Web 运行中;灰鲸鱼 = 未运行(官方 favicon 渲染,多尺寸 16~256px) |
51
+ | **悬停提示** | `Web UI 运行中 · 127.0.0.1:3088` / `Web UI 未运行 · 右键可启动` |
52
+ | **双击** | 打开 Web UI(未运行时提示先启动) |
53
+ | **右键菜单** | 顶部 `Web UI 状态` / `TUI 状态` 双状态行(含 PID);`Web UI ▸`(打开 Web UI / 启动 / 停止(带确认) / 重启);`TUI ▸`(启动 / 停止);打开日志目录 / `版本信息 ▸`(版本 / 检查更新 / 更新到最新版)/ 退出托盘 |
54
+ | **菜单智能禁用** | Web 运行中禁用「启动 Web UI」;TUI 运行中禁用「启动 TUI」 |
55
+ | **状态通知** | Web/TUI 启动与停止瞬间弹系统通知;托盘就绪弹一次提示 |
56
+ | **开机自启** | 登录后托盘自动出现(启动文件夹快捷方式,安装时自动创建) |
57
+
58
+ 托盘每 2 秒探测一次 `127.0.0.1:3088`(TCP 连接,500ms 超时,开销可忽略);菜单动作在独立隐藏进程执行,托盘 UI 永不卡顿。
59
+
60
+ ## 三、日常使用
61
+
62
+ 1. **自动跟随**:在 dsh 控制台(`~\.dsh\launcher\dsh-control.ps1`)执行 启动/重启 Web 时,托盘会自动拉起(幂等)。
63
+ 2. **手动唤起**:双击桌面「DSH 系统托盘」快捷方式;或 `dsh-tray`。
64
+ 3. **退出托盘**:右键 → 退出托盘(只退出托盘本身,不影响 dsh;下次登录/双击快捷方式可重新唤起)。
65
+ 4. **取消自启**:删除启动文件夹里的「DSH 系统托盘.lnk」。
66
+
67
+ ## 四、更新
68
+
69
+ 两种方式任选:
70
+
71
+ **方式一:托盘一键更新(推荐)**——托盘菜单「版本信息 ▸」→「检查更新」对比 npm 最新版,发现新版后点「更新到最新版」:自动 `npm install -g` → 重新部署(含本机路径改写)→ 自动重启托盘,失败不影响当前托盘。
72
+
73
+ **方式二:npm 标准流程**:
74
+
75
+ ```powershell
76
+ npm up -g dsh-windows-tray # 拉取最新版
77
+ dsh-tray install # 重新部署(自动改写本机路径 + 刷新快捷方式)
78
+ dsh-tray # 重启托盘
79
+ ```
80
+
81
+ > 部署目录固定为 `~\.dsh\launcher`,重装/更新会覆盖旧文件,不会残留;`dsh-tray info` 可查看当前版本与部署状态。
82
+ > ⚠️ 更新 = 重新 install,**本机手工适配(端口/数据目录等,见 §六)会被一并覆盖**——更新后按对照表重做并重启托盘,别只看安装输出就收工。
83
+
84
+ ## 五、卸载
85
+
86
+ ```powershell
87
+ npm rm -g dsh-windows-tray # 移除 npm 包本体
88
+ # 删除两个「DSH 系统托盘.lnk」(启动文件夹 + 桌面)
89
+ # 删除 ~\.dsh\launcher 目录(托盘部署文件;如与 dsh 控制台共用,确认无需保留再删)
90
+ ```
91
+
92
+ ## 六、配置
93
+
94
+ > **先探测实际值再回填,不要照抄默认列**(探测命令见 §一"安装后必做")。同一参数可能有多个填充点,缺改一处就被另一处覆盖。
95
+
96
+ | 项 | 位置 | 包默认 | 说明 |
97
+ | :--- | :--- | :--- | :--- |
98
+ | 监控端口 | ① `~\.dsh\launcher\dsh-lib.ps1` 顶部 `$PORT`;② `dsh-tray.ps1` 顶部 `param([int]$Port = …)` | `3088` | **两处必须一致**:托盘启动时先点源 lib 再执行 `$PORT = $Port`,**param 默认值会把 lib 改好的端口覆盖回去**(dsh-tray.ps1 第 27 行)——只改 lib 不改 param,托盘仍按默认端口探测 |
99
+ | dsh 路径 | `dsh-lib.ps1` 顶部 `$DSH_CMD / $NODE / $BIN` | 自动探测 | install 已改写,一般不用动 |
100
+ | 数据目录 | `dsh-lib.ps1` `$WORKDIR` + `$env:DSH_HOME` | **不设置** | 不设 DSH_HOME 时 web 默认落 `~\.dsh`——自定义数据目录的机器(如 `D:\dsh`)必须在 lib 里补 `$env:DSH_HOME`,否则托盘/控制台启动的 web 指向空目录 |
101
+ | 日志目录 | `dsh-lib.ps1` `$LOG_DIR`(`~\.dsh\logs`) | — | **目录须存在**:不存在时托盘 `Add-Content -ErrorAction SilentlyContinue` 静默吞日志,零日志不是没在记 |
102
+ | 图标颜色 | 包内 `build/build-tray-icons.ps1`(运行蓝/停止灰) | `#4176E6` / `#81858C` | — |
103
+
104
+ > ⚠️ `~\.dsh\launcher` 是部署产物,`dsh-tray install`/更新每次整体覆盖——上表手工适配重装后须重新应用(对照下表逐项核对,别凭记忆)。
105
+
106
+ ### 6.1 本机落地对照(跨机器对照用,照此逐项核对)
107
+
108
+ | 项 | 包默认 | 笔记本实际(2026-08-27 实测) | 填充点 |
109
+ | :--- | :--- | :--- | :--- |
110
+ | Web 端口 | 3088 | **3080** | dsh-lib.ps1 `$PORT` + dsh-tray.ps1 param 默认值(两处) |
111
+ | 数据目录 | 不设→`~\.dsh` | **D:\dsh** | dsh-lib.ps1 `$WORKDIR='D:\dsh'` + `$env:DSH_HOME='D:\dsh'` |
112
+ | 日志目录 | `~\.dsh\logs`(可能不存在) | 已手动创建 | — |
113
+ | 旧控制台 | — | `D:\dsh\launcher\dsh-control.ps1` 与托盘部署并存,端口同为 3080 | 无需合并 |
114
+ | 装完验证 | — | `tail ~/.dsh/logs/dsh-tray.log` 应有「托盘启动 (…端口 3080)」;重启 web 应看到「状态: 未运行 → 运行中」翻转 | — |
115
+
116
+ ## 七、故障排查
117
+
118
+ | 现象 | 处理 |
119
+ | :--- | :--- |
120
+ | web 明明在跑,托盘灰鲸/悬停显示"未运行" | 端口填充点不一致(十有八九是 `dsh-tray.ps1` 的 param 默认值把 lib 改好的端口覆盖回去了)——`tail ~\.dsh\logs\dsh-tray.log` 看「托盘启动」行的实际端口,对照 §六/§6.1 把两处改齐后重启托盘 |
121
+ | 托盘零日志 | `~\.dsh\logs` 目录不存在,托盘写日志被静默吞掉——建目录后重启托盘;重启 web 应立即出现状态翻转记录 |
122
+ | 任务栏看不到鲸鱼 | 点开 `^` 溢出区查找;若在,拖到任务栏(一次性)。 |
123
+ | 托盘图标消失 / 进程死了 | `dsh-tray` 或双击桌面快捷方式重新唤起;托盘退出不影响 dsh。 |
124
+ | 动作没反应 | 看 `~\.dsh\logs\dsh-tray-actions.log`(菜单动作)与 `dsh-tray.log`(状态变化)。 |
125
+ | 重复实例 | 命名互斥锁单实例保护(被强杀遗留的锁自动接管),正常不会重复。 |
126
+ | 检查更新失败 | 网络或 npm 不可用;托盘继续正常工作,稍后再试。 |
127
+ | dsh 内核升级了,托盘要动吗 | 不用——托盘只探测 3088 端口与 TUI 进程命令行,与内核版本解耦。 |
128
+
129
+ ## 八、已知边界
130
+
131
+ - 通知弹窗受 Windows「通知设置/专注助手」控制,被系统屏蔽时图标与菜单不受影响。
132
+ - 托盘进程是 `pwsh`,`taskkill /T` 杀进程树会连托盘一起结束(下次登录/快捷方式/控制台操作时恢复)。
133
+ - 端口探测只区分 运行/停止:3088 被其他程序占用时会误判"运行中"。
@@ -1,57 +1,57 @@
1
- # 系统托盘开发归档(v1.0.0 · 2026-08-27)
2
-
3
- > 托盘已发布为 npm 包 **`dsh-windows-tray`**,日常安装 / 使用 / 更新 / 卸载见 [system-tray-guide.md](system-tray-guide.md)。
4
- > 本文仅归档开发期的**架构决策与历史记录**(源码细节、文件清单不再维护);通用踩坑已归入 [powershell-pitfalls.md](powershell-pitfalls.md)。
5
-
6
- ---
7
-
8
- ## 1. 架构决策(仍生效)
9
-
10
- | 决策 | 理由 |
11
- | :--- | :--- |
12
- | **独立常驻进程**(不嵌入 dsh) | 需求是"看到未启动状态"——进程内嵌图标会随 dsh 消失;旁观者进程才能表达 运行/停止 两态,且能重启已死的 dsh |
13
- | **端口探测**(每 2s TCP 连 127.0.0.1:3088,500ms 超时) | 不持有进程句柄;dsh 重启 PID 变化也不误判;对 dsh 实现零依赖 |
14
- | **动作独立进程**(隐藏执行) | 菜单动作(含 taskkill、等待轮询)不阻塞托盘 UI 线程 |
15
- | **静态 .ico 图标资源** | 不依赖 dsh 运行时接口;缺失时 `New-FallbackIcon` 画纯色圆点兜底 |
16
- | **命名互斥锁单实例** | 替代 WMI 扫描,无竞态;被强杀遗留的锁自动接管(AbandonedMutexException) |
17
- | **TUI 单实例锁**(仅启动侧) | 防连点误开多窗口;检测/停止侧本就支持多实例(全查全杀);物理上 TUI 可多开,放开只需移除启动锁 |
18
-
19
- 进程模型:
20
-
21
- ```
22
- 托盘(pwsh) ──2s 轮询──► 端口 3088 (dsh web)
23
- │ └──────────────► node 进程命令行含 'dsh-tui' (TUI)
24
- ├── 菜单动作 ──► 独立隐藏进程 (带日志)
25
- └── 自更新 ──► npm install -g → 重部署 → 重启托盘
26
- ```
27
-
28
- ## 2. 图标渲染管线(摘要)
29
-
30
- 官方 `favicon.svg`(鲸鱼)→ 浏览器渲染 512px → PowerShell 逐像素"亮度转透明度 + 填充目标色" → 多尺寸 ICO(16/24/32/48/64/256)。运行态品牌蓝 `#4176E6`,停止态中性灰 `#81858C`。源图与脚本已内置 npm 包 `build/`,`dsh-tray icons` 可随时再生成。
31
-
32
- ## 3. 社区借鉴(发布前调研)
33
-
34
- npm 上两个同思路项目(`dsh-tray`、`dsh-tray-launcher`,均一周内发布),落地到本项目:
35
-
36
- - **命名互斥锁单实例**(替代 WMI 扫描,无竞态)
37
- - **浅色圆角菜单**(白底 + 圆角 hover + 细分隔线 + P/Invoke 圆角窗口 + CS_DROPSHADOW 投影,主/子菜单通用)
38
- - **菜单打开时强制刷新** TUI 状态(`add_Opening`),平时 TUI 检测 20s 节流
39
- - **停止 DSH 前 MessageBox 确认**、**版本烙印**(启动日志显示 v1.0.0,npm 安装版优先读 package.json)
40
-
41
- 不照搬的差异化设计:**旁观者架构**(退出托盘不影响 dsh)、**2s 端口轮询状态图标**、**TUI 启停集成 / 官方鲸鱼图标 / 控制台共享公共库**。
42
-
43
- ## 4. 需求变更决策记录
44
-
45
- | 时间 | 需求 | 决策 |
46
- | :--- | :--- | :--- |
47
- | 2026-08-27 | 托盘内 npm 自更新 | 曾按"更新应由 npm 标准流程承担"移除 → 用户决定恢复("更新加回去吧")→ 菜单「版本信息 ▸」(位于退出托盘上方,非日常功能区)提供 检查更新 / 一键更新;README 同时保留 npm CLI 路径 |
48
- | 2026-08-27 | 菜单太长 | DSH / TUI 收进子菜单(借鉴更新子菜单收纳思路) |
49
- | 2026-08-27 | 只显示 dsh 状态 | 顶部双状态行:`DSH 状态: …` / `TUI 状态: …`(独立检测、互不干扰) |
50
- | 2026-08-27 | 一级/二级菜单间隔大 | 根因:箭头预留撑宽父项 + 事件闭包 $null(详见 powershell-pitfalls §1.1 / §4.2) |
51
-
52
- ## 5. 已知边界
53
-
54
- 1. 3088 被其他程序占用时托盘误判"运行中"(属端口问题,与托盘无关)
55
- 2. 二态检测:只区分 运行/停止,无法区分"忙/卡死"(可扩展 HTTP 探测做三态)
56
- 3. TUI 单实例是策略而非物理限制(见 §1 决策表)
57
- 4. 单实例互斥锁在极端竞态下仍有极小双启动概率(影响可忽略)
1
+ # 系统托盘开发归档(v1.0.0 · 2026-08-27)
2
+
3
+ > 托盘已发布为 npm 包 **`dsh-windows-tray`**,日常安装 / 使用 / 更新 / 卸载见 [system-tray-guide.md](system-tray-guide.md)。
4
+ > 本文仅归档开发期的**架构决策与历史记录**(源码细节、文件清单不再维护);通用踩坑已归入 [powershell-pitfalls.md](powershell-pitfalls.md)。
5
+
6
+ ---
7
+
8
+ ## 1. 架构决策(仍生效)
9
+
10
+ | 决策 | 理由 |
11
+ | :--- | :--- |
12
+ | **独立常驻进程**(不嵌入 dsh) | 需求是"看到未启动状态"——进程内嵌图标会随 dsh 消失;旁观者进程才能表达 运行/停止 两态,且能重启已死的 dsh |
13
+ | **端口探测**(每 2s TCP 连 127.0.0.1:3088,500ms 超时) | 不持有进程句柄;dsh 重启 PID 变化也不误判;对 dsh 实现零依赖 |
14
+ | **动作独立进程**(隐藏执行) | 菜单动作(含 taskkill、等待轮询)不阻塞托盘 UI 线程 |
15
+ | **静态 .ico 图标资源** | 不依赖 dsh 运行时接口;缺失时 `New-FallbackIcon` 画纯色圆点兜底 |
16
+ | **命名互斥锁单实例** | 替代 WMI 扫描,无竞态;被强杀遗留的锁自动接管(AbandonedMutexException) |
17
+ | **TUI 单实例锁**(仅启动侧) | 防连点误开多窗口;检测/停止侧本就支持多实例(全查全杀);物理上 TUI 可多开,放开只需移除启动锁 |
18
+
19
+ 进程模型:
20
+
21
+ ```
22
+ 托盘(pwsh) ──2s 轮询──► 端口 3088 (dsh web)
23
+ │ └──────────────► node 进程命令行含 'dsh-tui' (TUI)
24
+ ├── 菜单动作 ──► 独立隐藏进程 (带日志)
25
+ └── 自更新 ──► npm install -g → 重部署 → 重启托盘
26
+ ```
27
+
28
+ ## 2. 图标渲染管线(摘要)
29
+
30
+ 官方 `favicon.svg`(鲸鱼)→ 浏览器渲染 512px → PowerShell 逐像素"亮度转透明度 + 填充目标色" → 多尺寸 ICO(16/24/32/48/64/256)。运行态品牌蓝 `#4176E6`,停止态中性灰 `#81858C`。源图与脚本已内置 npm 包 `build/`,`dsh-tray icons` 可随时再生成。
31
+
32
+ ## 3. 社区借鉴(发布前调研)
33
+
34
+ npm 上两个同思路项目(`dsh-tray`、`dsh-tray-launcher`,均一周内发布),落地到本项目:
35
+
36
+ - **命名互斥锁单实例**(替代 WMI 扫描,无竞态)
37
+ - **浅色圆角菜单**(白底 + 圆角 hover + 细分隔线 + P/Invoke 圆角窗口 + CS_DROPSHADOW 投影,主/子菜单通用)
38
+ - **菜单打开时强制刷新** TUI 状态(`add_Opening`),平时 TUI 检测 20s 节流
39
+ - **停止 DSH 前 MessageBox 确认**、**版本烙印**(启动日志显示 v1.0.0,npm 安装版优先读 package.json)
40
+
41
+ 不照搬的差异化设计:**旁观者架构**(退出托盘不影响 dsh)、**2s 端口轮询状态图标**、**TUI 启停集成 / 官方鲸鱼图标 / 控制台共享公共库**。
42
+
43
+ ## 4. 需求变更决策记录
44
+
45
+ | 时间 | 需求 | 决策 |
46
+ | :--- | :--- | :--- |
47
+ | 2026-08-27 | 托盘内 npm 自更新 | 曾按"更新应由 npm 标准流程承担"移除 → 用户决定恢复("更新加回去吧")→ 菜单「版本信息 ▸」(位于退出托盘上方,非日常功能区)提供 检查更新 / 一键更新;README 同时保留 npm CLI 路径 |
48
+ | 2026-08-27 | 菜单太长 | DSH / TUI 收进子菜单(借鉴更新子菜单收纳思路) |
49
+ | 2026-08-27 | 只显示 dsh 状态 | 顶部双状态行:`DSH 状态: …` / `TUI 状态: …`(独立检测、互不干扰) |
50
+ | 2026-08-27 | 一级/二级菜单间隔大 | 根因:箭头预留撑宽父项 + 事件闭包 $null(详见 powershell-pitfalls §1.1 / §4.2) |
51
+
52
+ ## 5. 已知边界
53
+
54
+ 1. 3088 被其他程序占用时托盘误判"运行中"(属端口问题,与托盘无关)
55
+ 2. 二态检测:只区分 运行/停止,无法区分"忙/卡死"(可扩展 HTTP 探测做三态)
56
+ 3. TUI 单实例是策略而非物理限制(见 §1 决策表)
57
+ 4. 单实例互斥锁在极端竞态下仍有极小双启动概率(影响可忽略)
@@ -12,7 +12,7 @@ $URL = "http://127.0.0.1:$PORT"
12
12
  $LOG_DIR = Join-Path (Join-Path $env:USERPROFILE '.dsh\logs') 'dsh-windows-tray' # 本插件专属日志目录 (logs\<插件名>\, 边界规则见 release-standards §3.1)
13
13
  $WT = "$env:LOCALAPPDATA\Microsoft\WindowsApps\wt.exe"
14
14
  $PWSH = 'D:\Program Files (x86)\PowerShell-7.6.4\pwsh.exe'
15
- $TRAY_VERSION = '1.0.9' # 托盘版本 (与 npm 包版本同步, 用于日志/排查)
15
+ $TRAY_VERSION = '1.0.11' # 托盘版本 (与 npm 包版本同步, 用于日志/排查)
16
16
  $TRAY_PKG = 'dsh-windows-tray' # npm 包名 (托盘自更新)
17
17
  $TRAY_SCRIPT = Join-Path $PSScriptRoot 'dsh-tray.ps1'
18
18
 
@@ -208,9 +208,71 @@ function Stop-Tui {
208
208
  }
209
209
 
210
210
  # ---- 打开 Web UI: 智能复用已有标签页 (UIA), 任何失败降级为新开 (最坏=旧行为) ----
211
- $WEB_TITLE_PREFIX = 'DeepSeek Harness' # dsh web 页面 <title> 前缀 (标题可能带 Edge 的 睡眠/内存 后缀)
211
+ # 匹配用包含而非前缀: dsh web 是 SPA, 打开会话页时 <title> 被改写为「会话名 — DeepSeek Harness」
212
+ # (dsh-client-ui-renderer: document.title = `${title} — ${productTitle}`),
213
+ # 前缀匹配对这类标签必然失败→每次都降级新开 (1.0.9 实测缺陷)。包含匹配同时覆盖
214
+ # 「DeepSeek Harness」(首页/无标题会话) 与「会话名 — DeepSeek Harness」两种形态;
215
+ # Edge 睡眠/内存后缀 (「- 睡眠 - 内存使用率 - xx MB」) 不受影响。
216
+ $WEB_TITLE_PREFIX = 'DeepSeek Harness' # dsh web 页面 <title> 关键标识 (含匹配, 见上)
212
217
  $BROWSER_PROGID_MAP = @{ 'MSEdgeHTM' = 'msedge'; 'ChromeHTML' = 'chrome' } # Chromium ProgId → 进程名; 查不到=降级新开
213
218
 
219
+ # ---- dsh 0.1.2+ 一次性 launch token 鉴权 (1.0.11) ----
220
+ # rc.1 起 dsh web 每次启动生成随机 launch token, 横幅打印 「dsh web: http://127.0.0.1:<port>/?token=...」;
221
+ # 该 URL 首次访问签发持久签名 cookie (跨重启有效), 此后裸 URL 才可直访——因此托盘打开 Web UI
222
+ # 必须用带 token 的 URL (或命中已授权标签页)。
223
+ # 向后兼容: 旧版 dsh 无 token 行 / token 失效 → 全部回退裸 URL (行为同 1.0.10 及以前)。
224
+ $WEB_TOKEN_LOG = Join-Path $LOG_DIR 'web-menu.out.log' # 与 Start-Dsh 的重定向输出同文件 (每 boot 覆写)
225
+
226
+ # 解析启动日志中的 launch token URL (最后一条命中; 纯读, 网络探活在 Get-WebLaunchUrl 里做)
227
+ function Parse-WebLaunchTokenUrl {
228
+ param([string]$LogPath = $WEB_TOKEN_LOG)
229
+ if (-not (Test-Path $LogPath)) { return '' }
230
+ $found = ''
231
+ foreach ($line in (Get-Content -LiteralPath $LogPath -ErrorAction SilentlyContinue)) {
232
+ if ($line -match '(https?://\S*\?token=[A-Za-z0-9_-]+)') { $found = $Matches[1] }
233
+ }
234
+ return $found
235
+ }
236
+
237
+ # 探活: token URL 对无 cookie 请求应 303 (签发 Set-Cookie 后重定向到净 URL); 39x/200 均算有效。
238
+ # 用 HttpWebRequest 不自动跟随重定向; 401 (token 过期/被拒) 或网络异常 → 无效
239
+ function Test-WebLaunchUrl {
240
+ param([string]$Url)
241
+ foreach ($u in @($Url)) {
242
+ try {
243
+ $req = [System.Net.HttpWebRequest]::Create($u)
244
+ $req.AllowAutoRedirect = $false
245
+ $req.Timeout = 3000
246
+ $resp = $req.GetResponse()
247
+ $code = [int]$resp.StatusCode
248
+ $resp.Close()
249
+ if ($code -ge 200 -and $code -lt 400) { return $true }
250
+ } catch {
251
+ $resp = $_.Exception.Response
252
+ if ($null -ne $resp) {
253
+ $code = [int]$resp.StatusCode
254
+ $resp.Close()
255
+ if ($code -ge 200 -and $code -lt 400) { return $true }
256
+ }
257
+ }
258
+ }
259
+ return $false
260
+ }
261
+
262
+ # 决定打开哪个 URL: 日志有 token 且探活有效 → 带 token URL; 否则裸 URL (旧版 dsh 直访 200)
263
+ function Get-WebLaunchUrl {
264
+ param(
265
+ [string]$Fallback = $URL,
266
+ [string]$LogPath = $WEB_TOKEN_LOG,
267
+ [switch]$SkipProbe # 单测注入: 跳过网络探活, 只测解析与回退逻辑
268
+ )
269
+ $tokenUrl = Parse-WebLaunchTokenUrl -LogPath $LogPath
270
+ if ($tokenUrl -ne '') {
271
+ if ($SkipProbe -or (Test-WebLaunchUrl -Url $tokenUrl)) { return $tokenUrl }
272
+ }
273
+ return $Fallback
274
+ }
275
+
214
276
  function Open-DshWeb {
215
277
  param([string]$Url = $URL)
216
278
  try {
@@ -237,7 +299,7 @@ namespace DSH {
237
299
  if ((Get-Process -Id $win.Current.ProcessId -ErrorAction SilentlyContinue).ProcessName -ne $procName) { continue }
238
300
  $tabCond = New-Object System.Windows.Automation.PropertyCondition([System.Windows.Automation.AutomationElement]::ControlTypeProperty, [System.Windows.Automation.ControlType]::TabItem)
239
301
  foreach ($tab in $win.FindAll('Descendants', $tabCond)) {
240
- if (-not ($tab.Current.Name -like "$WEB_TITLE_PREFIX*")) { continue }
302
+ if (-not ($tab.Current.Name -like "*${WEB_TITLE_PREFIX}*")) { continue }
241
303
  # 命中已打开的 DSH Web 标签页: 切换过去并激活窗口
242
304
  ([System.Windows.Automation.SelectionItemPattern]$tab.GetCurrentPattern([System.Windows.Automation.SelectionItemPattern]::Pattern)).Select()
243
305
  $hwnd = [IntPtr]$win.Current.NativeWindowHandle
@@ -251,7 +313,9 @@ namespace DSH {
251
313
  } catch {
252
314
  Write-Host "[web] 切换检测不可用($($_.Exception.Message)), 新开" -ForegroundColor DarkGray
253
315
  }
254
- Start-Process $Url
316
+ $openUrl = Get-WebLaunchUrl -Fallback $Url
317
+ Write-Host "[web] 打开: $openUrl" -ForegroundColor DarkGray
318
+ Start-Process $openUrl
255
319
  }
256
320
 
257
321
  function Show-Status {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-windows-tray",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "DSH (DeepSeek Harness) Windows 系统托盘: 蓝/灰鲸鱼状态图标 + Web/TUI 一键启停控制。纯 PowerShell + WinForms, 零依赖。",
5
5
  "license": "MIT",
6
6
  "author": "jankin_lv",