dsh-windows-tray 1.0.11 → 1.0.12

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
@@ -35,7 +35,7 @@ dsh 默认在终端前台运行 `dsh web`——必须留着一个命令行窗口
35
35
 
36
36
  | 项 | 说明 |
37
37
  | :--- | :--- |
38
- | **dsh 内核** | 适配 `@deepseek-ai/dsh` **v0.1.1-rc.2 系列**(共享核心 `@deepseek-ai/dsh-base` 同版本);dsh 升级不影响托盘 |
38
+ | **dsh 内核** | 适配 `@deepseek-ai/dsh` **v0.1.1-rc.2 ~ 0.1.2-rc.1 系列**;**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
39
  | **Web 服务** | dsh web 默认监听 `127.0.0.1:3088`(即浏览器里的 Web UI)——托盘通过 TCP 探测该端口判断 Web 状态(端口被改时同步修改 `dsh-lib.ps1` 的 `$PORT` 即可) |
40
40
  | **TUI 插件** | 适配 `@deepseek-harness-tui/dsh-tui` **^0.9.2**(通过 dsh-profile `dsh-profile-dsh-tui` 挂载);托盘按进程命令行 `dsh-tui` 检测,与插件版本解耦 |
41
41
  | **Node.js** | ≥ 18(dsh 本体运行所需) |
@@ -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.11' # 托盘版本 (与 npm 包版本同步, 用于日志/排查)
15
+ $TRAY_VERSION = '1.0.12' # 托盘版本 (与 npm 包版本同步, 用于日志/排查)
16
16
  $TRAY_PKG = 'dsh-windows-tray' # npm 包名 (托盘自更新)
17
17
  $TRAY_SCRIPT = Join-Path $PSScriptRoot 'dsh-tray.ps1'
18
18
 
@@ -75,6 +75,15 @@ function Initialize-LogDir {
75
75
  }
76
76
 
77
77
  function Get-WebPid {
78
+ # 优化(1.0.12): netstat 解析优先 (原 Get-NetTCPConnection 在本机 727 进程下 avg 1.3s,
79
+ # 直接拖慢右键菜单转态路径); 解析失败回退 CIM 查询
80
+ try {
81
+ $pids = @()
82
+ foreach ($row in (& netstat -ano -p tcp 2>$null)) {
83
+ if ($row -match ":$PORT\s+\S+\s+LISTENING\s+(\d+)\s*$") { $pids += $Matches[1] }
84
+ }
85
+ if ($pids.Count -gt 0) { return @($pids | Sort-Object -Unique) }
86
+ } catch { }
78
87
  @((Get-NetTCPConnection -LocalPort $PORT -State Listen -ErrorAction SilentlyContinue).OwningProcess | Select-Object -Unique)
79
88
  }
80
89
 
@@ -160,10 +169,12 @@ function Start-Tui {
160
169
 
161
170
  # TUI 进程树: 外壳 pwsh(-NoExit) → cmd(dsh.cmd) → node(bin.js), 三层命令行都含 dsh-tui
162
171
  # 按进程名白名单过滤, 防止误杀命令行里恰好含 dsh-tui 的其他程序 (如 WindowsTerminal.exe 本体)
172
+ # 优化(1.0.12): WQL 先按 Name 窄集 (原全量枚举会拉全部进程的 CommandLine);
173
+ # ⚠️ 本机实测任何 Win32_Process 查询固定 ~450-570ms (WinRM 不可用, DCOM/持久会话均无效)——
174
+ # **调用方 (托盘状态刷新) 必须在 ThreadJob 里异步跑, 禁止在 UI/菜单路径同步调用** (见 dsh-tray.ps1)
163
175
  function Get-TuiTree {
164
- Get-CimInstance Win32_Process -ErrorAction SilentlyContinue | Where-Object {
165
- $_.ProcessId -ne $PID -and $_.CommandLine -and
166
- $_.CommandLine -match 'dsh-tui' -and $_.Name -match '^(node|cmd|pwsh|powershell)\.exe$'
176
+ Get-CimInstance Win32_Process -Filter "Name='node.exe' OR Name='cmd.exe' OR Name='pwsh.exe' OR Name='powershell.exe'" -ErrorAction SilentlyContinue | Where-Object {
177
+ $_.ProcessId -ne $PID -and $_.CommandLine -and $_.CommandLine -match 'dsh-tui'
167
178
  }
168
179
  }
169
180
 
@@ -342,8 +353,7 @@ function Show-Status {
342
353
  # ---- 系统托盘 ----
343
354
 
344
355
  function Get-TrayProcesses {
345
- Get-CimInstance Win32_Process -ErrorAction SilentlyContinue | Where-Object {
346
- ($_.Name -eq 'pwsh.exe' -or $_.Name -eq 'powershell.exe') -and
356
+ Get-CimInstance Win32_Process -Filter "Name='pwsh.exe' OR Name='powershell.exe'" -ErrorAction SilentlyContinue | Where-Object {
347
357
  $_.CommandLine -and $_.CommandLine -match 'dsh-tray\.ps1' -and
348
358
  $_.ProcessId -ne $PID
349
359
  }
@@ -354,31 +354,66 @@ $script:prevState = $null # $null=初始; $true=运行; $false=停止
354
354
  $script:prevTui = $null # TUI 状态 ($null=初始; $true=运行; $false=停止)
355
355
  $script:firstRun = $true # 首次刷新只设图标, 不弹变化通知
356
356
  $script:lastTuiCheck = 0 # TUI 检测节流 (常规 20s 一次, 打开菜单时强制)
357
+ $script:tuiJob = $null # 运行中的 TUI 检测任务 (1.0.12 异步化)
358
+ $script:tuiRefreshQueued = $false # 任务在跑期间又到期/强制刷新 → 完成后立即再刷
359
+
360
+ # ThreadJob 异步化 (1.0.12): 本机实测任何 Win32_Process WMI 查询固定 ~450-570ms
361
+ # (WinRM 不可用, WSMAN/DCOM 持久会话均无效) —— 若在菜单 Opening / 状态 tick 同步跑,
362
+ # 右键菜单会被 WinForms 卡住 (Opening 未返回不渲染)。TUI 检测改为后台任务,
363
+ # 结果由 2s 定时器在 UI 线程回收应用; ThreadJob 模块缺失时降级同步 (旧行为)。
364
+ Import-Module Microsoft.PowerShell.ThreadJob -ErrorAction SilentlyContinue
365
+ $script:threadJobOk = $null -ne (Get-Command Start-ThreadJob -ErrorAction SilentlyContinue)
366
+
367
+ function Apply-TuiStatus {
368
+ param([object[]]$tuiProcs)
369
+ $tuiRunning = $tuiProcs.Count -gt 0
370
+ if ($tuiRunning) {
371
+ $itemTuiStatus.Text = "TUI 状态: 运行中 (PID $(($tuiProcs.ProcessId) -join ','))"
372
+ } else {
373
+ $itemTuiStatus.Text = 'TUI 状态: 未运行'
374
+ }
375
+ if ($tuiRunning -ne $script:prevTui) {
376
+ $script:prevTui = $tuiRunning
377
+ $itemTuiStart.Enabled = -not $tuiRunning
378
+ $itemTuiStop.Enabled = $tuiRunning
379
+ if ($tuiRunning) {
380
+ Log "TUI: 运行中 (PID $(($tuiProcs.ProcessId) -join ','))"
381
+ } else {
382
+ Log 'TUI: 未运行'
383
+ }
384
+ }
385
+ }
357
386
 
358
387
  function Update-State {
359
388
  param([switch]$ForceTui)
360
389
  try {
361
- # TUI 状态独立检测 (不随 Web 状态提前返回); WMI 查询节流, 减少周期开销
362
- if ($ForceTui -or ([Environment]::TickCount - $script:lastTuiCheck) -gt 20000) {
363
- $script:lastTuiCheck = [Environment]::TickCount
364
- $tuiProcs = @(Get-TuiProcesses)
365
- $tuiRunning = $tuiProcs.Count -gt 0
366
- if ($tuiRunning) {
367
- $itemTuiStatus.Text = "TUI 状态: 运行中 (PID $(($tuiProcs.ProcessId) -join ','))"
368
- } else {
369
- $itemTuiStatus.Text = 'TUI 状态: 未运行'
390
+ # --- TUI 检测: 异步, 绝不阻塞 UI —— 先回收已完成任务, 再按需排程 ---
391
+ if ($script:threadJobOk) {
392
+ if ($script:tuiJob -and $script:tuiJob.State -ne 'Running') {
393
+ $tuiProcs = @(Receive-Job -Job $script:tuiJob -ErrorAction SilentlyContinue)
394
+ Remove-Job $script:tuiJob -Force -ErrorAction SilentlyContinue
395
+ $script:tuiJob = $null
396
+ $script:lastTuiCheck = [Environment]::TickCount
397
+ Apply-TuiStatus $tuiProcs
398
+ if ($script:tuiRefreshQueued) { $script:tuiRefreshQueued = $false; $script:lastTuiCheck = 0 }
370
399
  }
371
- if ($tuiRunning -ne $script:prevTui) {
372
- $script:prevTui = $tuiRunning
373
- $itemTuiStart.Enabled = -not $tuiRunning
374
- $itemTuiStop.Enabled = $tuiRunning
375
- if ($tuiRunning) {
376
- Log "TUI: 运行中 (PID $(($tuiProcs.ProcessId) -join ','))"
400
+ if ($ForceTui -or (([Environment]::TickCount - $script:lastTuiCheck) -gt 20000)) {
401
+ if (-not $script:tuiJob) {
402
+ $libPath = Join-Path $PSScriptRoot 'dsh-lib.ps1'
403
+ $script:tuiJob = Start-ThreadJob -ScriptBlock {
404
+ param($lib)
405
+ . $lib
406
+ @(Get-TuiProcesses)
407
+ } -ArgumentList $libPath
377
408
  } else {
378
- Log 'TUI: 未运行'
409
+ $script:tuiRefreshQueued = $true
379
410
  }
380
411
  }
412
+ } elseif ($ForceTui -or (([Environment]::TickCount - $script:lastTuiCheck) -gt 20000)) {
413
+ $script:lastTuiCheck = [Environment]::TickCount
414
+ Apply-TuiStatus (@(Get-TuiProcesses))
381
415
  }
416
+ # --- Web 状态: Test-Port ~11ms + 转态才查 PID (netstat ~42ms), 保持在 UI 线程 ---
382
417
  $running = Test-Port $PORT
383
418
  if ($running -eq $script:prevState -and -not $script:firstRun) { return } # 无变化
384
419
  $script:prevState = $running
@@ -426,5 +461,6 @@ $timer.Dispose()
426
461
  $menu.Dispose()
427
462
  $iconRun.Dispose(); $iconStop.Dispose()
428
463
  try { $mutex.ReleaseMutex() } catch { }
464
+ try { if ($script:tuiJob) { Remove-Job $script:tuiJob -Force -ErrorAction SilentlyContinue; $script:tuiJob = $null } } catch { }
429
465
  Log '托盘已退出'
430
466
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-windows-tray",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "DSH (DeepSeek Harness) Windows 系统托盘: 蓝/灰鲸鱼状态图标 + Web/TUI 一键启停控制。纯 PowerShell + WinForms, 零依赖。",
5
5
  "license": "MIT",
6
6
  "author": "jankin_lv",