|
|
15 godzin temu | |
|---|---|---|
| .gitignore | 1 dzień temu | |
| LICENSE | 4 miesięcy temu | |
| README.md | 15 godzin temu | |
| autostart_windows.go | 1 dzień temu | |
| build.ps1 | 15 godzin temu | |
| config.go | 1 dzień temu | |
| deadcode_test.go | 15 godzin temu | |
| go.mod | 1 dzień temu | |
| go.sum | 4 miesięcy temu | |
| icon.ico | 4 miesięcy temu | |
| logger.go | 1 dzień temu | |
| main.go | 16 godzin temu | |
| npm.go | 1 dzień temu | |
| probe.go | 1 dzień temu | |
| proc_windows.go | 15 godzin temu | |
| supervisor.go | 16 godzin temu | |
| tray.go | 15 godzin temu | |
| updater.go | 16 godzin temu | |
| util.go | 1 dzień temu | |
| util_test.go | 1 dzień temu |
DeepSeek Harness Web 版桌面包装(Windows 系统托盘 + 守护进程)。
把 dsh web 变成常驻托盘应用:全程隐藏终端、异常自动重启、一键开机自启、一键更新。
开机自启为静默启动:不弹终端、不打开浏览器。需要时从托盘菜单"打开 Web 界面"(自动带 token,直接进入已认证界面)。
node <dsh>/lib/bin.js web --no-open 直接启动(无 shell 包装),子进程使用 CREATE_NO_WINDOW + HideWindowautostart on|off(写 HKCU Run 键,无需管理员权限)npm install -g @deepseek-ai/dsh@latest --allow-scripts=...,先停服务再更新(避免 Windows 上 native 模块文件占用导致安装失败),无论成败都恢复原有运行状态;可开启定期后台更新(常驻单例循环:关闭仅暂停计时,再次开启立即恢复)dsh web 输出的访问地址;菜单标题只显示 origin,token 只存内存token=***;打开 URL/路径不经 shell 解析(rundll32 / explorer)Local 命名互斥体(普通用户可创建,避免 Global 权限失败导致失效)getlantern/systray、golang.org/x/sys),单文件分发约 5 MB.\build.ps1 # 一键:格式检查 + go vet + go test + 构建
分步执行:
gofmt -l . # 格式检查(应无输出)
go vet ./... # 静态检查
go test ./... # 单元测试
go build -trimpath -ldflags "-H:windowsgui -s -w" -o deepseek-tray.exe .
| 命令 | 说明 |
|---|---|
deepseek-tray.exe |
托盘模式(默认) |
deepseek-tray.exe --silent |
静默托盘(开机自启使用,无窗口、不打开浏览器) |
deepseek-tray.exe daemon |
无 UI 守护模式(支持优雅退出信号,适合注册为 Windows 服务) |
deepseek-tray.exe status |
状态查询(同时写日志) |
deepseek-tray.exe autostart [on\|off] |
查看/设置开机自启 |
deepseek-tray.exe version |
版本号 |
CLI 子命令在真实终端中输出(通过
AttachConsole);无终端场景可从日志回溯。
nssm install DeepSeekTray "C:\path\to\deepseek-tray.exe" daemon
nssm start DeepSeekTray
设计取舍:菜单与提示均不显示访问地址。 原因:地址(含 token)很长,一旦放进菜单标题就会撑宽整个菜单,视觉不协调;而
getlantern/systray在 Windows 上又不支持菜单项悬停提示(只有图标 tooltip 有效)。 因此访问地址只用于两处:点击「打开 Web 界面」直接打开、以及写入日志便于排查。 需要原始地址时,可在日志中查看(token 已脱敏)或从浏览器地址栏获取。
位置:%APPDATA%\deepseek-tray\config.json(首次运行自动生成,原子写入)
{
"webPort": 3080,
"webHost": "127.0.0.1",
"nodePath": "",
"dshBinJs": "",
"autoStart": false,
"autoUpdate": false,
"updateIntervalHours": 24,
"restartDelaySeconds": 5
}
| 字段 | 说明 |
|---|---|
webPort / webHost |
dsh web 监听端口与地址(默认 3080 / 127.0.0.1) |
nodePath / dshBinJs |
留空自动探测(node + npm root -g 下的 dsh 入口) |
autoStart |
开机自启(与托盘勾选同步) |
autoUpdate / updateIntervalHours |
定期后台更新开关与间隔 |
restartDelaySeconds |
重启退避的基准延迟(按失败次数指数放大,封顶 2 分钟) |
修改配置文件后需重启程序生效。
| 文件 | 职责 |
|---|---|
main.go |
入口与 CLI 子命令(托盘 / daemon / status / autostart) |
supervisor.go |
守护核心:端口预检、隐藏启动、退避重启、状态快照 |
probe.go |
环境探测:node 路径、dsh 入口、已装版本(带缓存与串行化) |
updater.go |
更新与定期更新循环 |
tray.go |
托盘菜单与交互 |
config.go / logger.go / npm.go / util.go |
配置、日志、npm 调用、纯工具 |
*_windows.go |
Win32 细节(隐藏窗口、进程树终止、单实例、控制台附加) |
util_test.go |
单元测试 |
%APPDATA%\deepseek-tray\logs\tray-YYYYMMDD.log(按天轮转;含 dsh web 的 stdout/stderr;token 已脱敏)
go test)| 测试 | 覆盖 |
|---|---|
| TestRedact | token 脱敏(多 token / 终止符 / 无 token / 空串) |
| TestExtractHTTPURL | URL 提取与误报拒绝(httpx) |
| TestShortURL / TestHumanDuration | 展示格式化 |
| TestConfigNormalized | 配置越界回退默认值 |
| TestIsPortOpen | 真实监听端口的探测 |
| TestBackoff | 退避序列与封顶(此测试发现并修复了上限未生效问题) |
| TestLoggerRotate | 日志按天轮转 |
| TestConfigRoundTrip | 配置首次生成 / 保存重载 / BOM 容忍 / 损坏回退(隔离到临时目录) |
| TestSetAutoUpdatePersists | 线程安全 setter 同时更新内存与磁盘 |
| TestSupervisorLifecycle | 守护状态机:启动 / 自动重启 / 停止 |
| 维度 | 验证项 | 结果 | 证据形式 |
|---|---|---|---|
| 可靠性 | 隐藏终端 | daemon / dsh web 的顶层窗口句柄为 0 | 进程属性测量 |
| 可靠性 | 自动重启 | 假命令下观测到 启动 6 / 退出 4 / 重启 4 | 日志计数 |
| 可靠性 | 单实例 | 第二个实例立即退出并记录 | 日志 |
| 可靠性 | 启动/停止竞态 | 已处理(停止请求落在启动窗口时终止该进程) | 仅代码审查;窗口毫秒级,未确定性复现 |
| 健壮性 | 端口被占用 | 不启动冲突进程,退避 6s→12s→24s | 日志时间戳 |
| 健壮性 | 配置损坏 / UTF-8 BOM | 回退默认值 / 正确读取 | 单元测试 + CLI |
| 安全性 | 日志 token | 输出 token=***(真实值仅存内存) |
日志 |
| 安全性 | 打开 URL/路径 | 不经 shell(ShellExecuteW) | 探针测试通过 |
| 可靠性 | 打开日志/配置 | 窗口正常显示(不再被 SW_HIDE 隐藏) | 探针调用成功(目视确认由用户完成) |
| 效率 | status 查询 / 二进制 | 0.4 秒 / 约 5.2 MB | 计时与文件大小 |
复现方式:
build.ps1跑单元测试;上表运行时项可用--port 3099与假命令分别复现。未标注"实测"的行为代码审查结论。
npm install -g @deepseek-ai/dsh@latest --allow-scripts='@deepseek-ai/dsh-subprocess-local,koffi,node-pty,@google/genai,protobufjs'node 在 PATH 中firstLine 改用 ASCII 码 10,避免转义写法歧义MenuItem.SetTooltip 是空操作),改为把完整地址放进托盘图标 tooltip(地址置于首行,规避 128 字符上限截断),并新增「复制 Web 地址」(临时文件 + clip.exe,文本不经 shell 解析)build.ps1 一键构建Local 互斥体 + 日志脱敏 + 原子配置 + autostart 子命令dsh web 托盘守护(旧版余额查询功能归档于 legacy-v1 标签)见 LICENSE。