@wendongfly/myhi 1.3.121 → 1.3.128

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
@@ -32,6 +32,16 @@ npm install -g @wendongfly/myhi
32
32
 
33
33
  需要 Node.js >= 18。
34
34
 
35
+ > **新版 npm 注意**:若看到 `npm warn allow-scripts`(新版 npm 默认拦包的安装脚本),说明 `node-pty` 的原生模块脚本被跳过、终端可能受影响。加参数放行即可:
36
+ > ```bash
37
+ > npm install -g @wendongfly/myhi --allow-scripts=@wendongfly/myhi,node-pty
38
+ > ```
39
+ > 或本机一次性放行:`npm config set allow-scripts=@wendongfly/myhi,node-pty --location=user`。用下面的 Windows 安装器则已自动处理,无需手动加。
40
+
41
+ ### Windows 傻瓜安装(给普通员工,免命令行)
42
+
43
+ 不想让员工碰终端?用 `installer/` 里的一键安装:右键 **`Install-myhi.bat` → 以管理员身份运行**,它会自动装 Node(缺则 winget 装)、装/更新 myhi、**注册计划任务实现开机登录自启(脱离会话、无黑窗、普通权限)**、放行防火墙、建桌面「myhi 控制台」快捷方式。装完开机登录即自动后台运行,员工只管点桌面图标用。详见 [`installer/README.md`](installer/README.md)。
44
+
35
45
  ## 快速开始
36
46
 
37
47
  ```bash
@@ -0,0 +1,17 @@
1
+ @echo off
2
+ chcp 65001 >nul
3
+ title myhi installer (headless)
4
+ rem Headless / always-on mode: starts at boot, no logon required. For servers / always-on PCs.
5
+ rem For an employee's own PC use Install-myhi.bat instead (starts at logon).
6
+ rem "am_admin" marker prevents an infinite UAC loop if "net session" misdetects admin rights.
7
+ if "%~1"=="am_admin" goto :run
8
+ net session >nul 2>&1
9
+ if %errorlevel%==0 goto :run
10
+ echo [myhi] Requesting administrator (UAC)...
11
+ powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -ArgumentList 'am_admin' -Verb RunAs"
12
+ exit /b
13
+ :run
14
+ powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0install-myhi.ps1" -Headless
15
+ echo.
16
+ echo Done. You can close this window.
17
+ pause
@@ -0,0 +1,15 @@
1
+ @echo off
2
+ chcp 65001 >nul
3
+ title myhi installer
4
+ rem "am_admin" marker prevents an infinite UAC loop if "net session" misdetects admin rights.
5
+ if "%~1"=="am_admin" goto :run
6
+ net session >nul 2>&1
7
+ if %errorlevel%==0 goto :run
8
+ echo [myhi] Requesting administrator (UAC)...
9
+ powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -ArgumentList 'am_admin' -Verb RunAs"
10
+ exit /b
11
+ :run
12
+ powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0install-myhi.ps1"
13
+ echo.
14
+ echo Done. You can close this window.
15
+ pause
@@ -0,0 +1,85 @@
1
+ # myhi Windows 傻瓜安装(让员工省心)
2
+
3
+ 给普通员工用的一键安装:**双击一个文件,装好后开机登录自动在后台运行,全程不用开终端、不用敲命令**。
4
+
5
+ ## 员工怎么用
6
+
7
+ 1. 把整个 `installer` 文件夹拷到员工电脑(或发压缩包)。
8
+ 2. 按场景右键选一个 `.bat` → **以管理员身份运行**(会弹 UAC,点「是」):
9
+ - **`Install-myhi.bat`** —— **员工自己的电脑**(登录后用):登录时自动后台运行。
10
+ - **`Install-myhi-headless.bat`** —— **常驻/常开机器(服务器)**:**开机即运行,无论是否登录**(用 S4U,免密码、非提权)。
11
+ 3. 等它自动完成(没装 Node 会自动装、装/更新 myhi、设自启、放行防火墙、建快捷方式)。
12
+ 4. 桌面出现 **「myhi 控制台」** 图标,双击打开 `https://localhost:12300`(首次有自签证书警告,点「高级 → 继续前往」)。首次登录密码见 `%USERPROFILE%\.myhi\password`。
13
+
14
+ 之后 myhi **自动在后台运行**(登录模式=登录后;常驻模式=开机即起),员工只管点桌面图标用,或用手机/平板在同一局域网访问。
15
+
16
+ 卸载:右键 **`Uninstall-myhi.bat` → 以管理员身份运行**(撤销自启/防火墙/快捷方式;保留 myhi 本体与数据)。
17
+
18
+ ## 批量部署很多新电脑(一次配好、台台开箱即用)
19
+
20
+ 安装器已经把**依赖一起装了**:Node(缺则 winget 装)+ **Claude CLI**(AI 引擎)+ myhi。要让新机**连 AI 都免配、开箱即用**,管理员只需在部署包里预置一份网关配置:
21
+
22
+ 1. 把 `installer/gateway.json.example` 复制成 **`gateway.json`**,填入你的 AI 网关 `baseUrl` 和 `apiKey`,放在 installer 文件夹里。
23
+ 2. 把整个文件夹(含 `gateway.json`)打包发到各新机。
24
+ 3. 每台机右键 `Install-myhi.bat`(或 `Install-myhi-headless.bat`)以管理员运行 → 自动装好 node/claude/myhi + **把 gateway.json 部署到 `~/.myhi/`** → AI 直接能用。
25
+
26
+ > 🔒 `gateway.json` 含密钥,已被 `.gitignore` 忽略、**绝不进 git**;只在你的部署包/各机本地之间流转。不预置也行——那样各机装完需在 `~/.myhi/gateway.json` 手动填 `{"baseUrl":"...","apiKey":"..."}`(或在网页里配)后 AI 才可用。
27
+
28
+ > 还没做的(可后续加):预置登录密码、预置密钥库 `secrets.json`。需要的话告诉我。
29
+
30
+ ## 升级怎么做
31
+
32
+ myhi 有两条升级路径,都不需要员工敲命令:
33
+
34
+ 1. **网页点「更新」**(最省事):仪表盘每 10 分钟查新版,有新版会显示横幅,员工点一下 → daemon 自动 `npm i -g @latest` 并重启。⚠️ **Windows 注意**:升级时正在跑的 server 子进程可能锁着 `node-pty` 的 `pty.node`,导致 npm 覆盖 EBUSY 而升级不生效(会继续跑旧版)。遇到这种情况用下面第 2 条。
35
+ 2. **重新跑一次安装器(推荐、最可靠)**:重新右键跑对应的 `Install-*.bat`。安装器是**幂等**的——它会**先停掉 myhi 释放 `pty.node` → `npm i -g @latest` → 重新起**,专门绕开了 EBUSY。所以在 Windows 上「**再跑一次安装器 = 干净升级**」。
36
+
37
+ > 运维批量升级:各机 `npm i -g @wendongfly/myhi@latest` 后重启(Linux `systemctl restart myhi`;Windows 计划任务模式先停 daemon 再由计划任务/手动拉起)。
38
+
39
+ ## 它到底做了什么(管理员/运维看)
40
+
41
+ `install-myhi.ps1`:
42
+
43
+ 1. **Node**:没有就 `winget install OpenJS.NodeJS.LTS` 自动装;已有则用现成的。
44
+ 2. **myhi**:`npm i -g @wendongfly/myhi@latest --allow-scripts=@wendongfly/myhi,node-pty`(放行 node-pty 原生模块)。
45
+ 3. **Claude CLI**(myhi 的 AI 引擎):`npm i -g @anthropic-ai/claude-code@latest`(加 `-SkipClaude` 可跳过)。
46
+ 4. **隐藏启动器**:生成 `~/.myhi/myhi-launch.vbs`,用 `WScript.Shell.Run(cmd, 0, False)` **窗口隐藏**启动 `node bin/daemon.js`(无黑窗)。
47
+ 5. **AI 网关配置**:若安装包目录随附 `gateway.json`(管理员预置),复制到 `~/.myhi/gateway.json`,AI 开箱即用。
48
+ 6. **开机自启 = 计划任务**(Windows 上的「systemd 等价物」):`myhi-autostart`,**当前用户身份 + `RunLevel Limited`(非提权) + 脱离创建者会话**;触发方式按模式:默认「登录触发」,`-Headless` 则「开机触发 + S4U(无论是否登录)」。同时解决开机自启、登出/重启后存活、终端为普通权限(安全)。
49
+ 7. **防火墙**:放行 TCP 12300/12301(Private/Domain),局域网手机平板可访问。
50
+ 8. **快捷方式**:桌面 + 开始菜单 `myhi 控制台.url → https://localhost:12300`。
51
+ 9. **立即启动**一次。
52
+
53
+ **升级**照旧走网页里的「更新」横幅(daemon 内建 `npm i -g @latest` + 重启,见 `bin/daemon.js`),员工点一下即可,无需碰命令行。
54
+
55
+ ## 关键设计取舍
56
+
57
+ - **为什么用计划任务不用 Windows 服务**:Windows 服务默认以 `SYSTEM` 跑 → myhi 开的每个终端都会是 SYSTEM 最高权限,是严重提权面;且服务账户的 `~` 与员工登录账户不同,`~/.myhi` 配置对不上。计划任务「登录触发 + 当前用户 + 非提权」天然规避这两点,且脱离会话(正是我们远程运维时被迫用 WMI 解决的那个「登出即死」问题)。
58
+ - **谁该是管理员**:注册计划任务/防火墙需要管理员。若员工是**自己电脑的本地管理员**(最常见),`Install-myhi.bat` 提权后 `$env:USERNAME` 仍是员工本人,自启身份正确。若员工是标准用户、UAC 里输入的是**另一个管理员账户**,则自启会挂到那个管理员账户名下——这种环境请改用「以员工账户运行」的方式(或手工建计划任务时指定员工为 principal)。
59
+
60
+ ## 已实测
61
+
62
+ 已在一台真实 Windows 客户机(Win10 + Node 16 + nvm)端到端跑通:Node 检测→停旧释放 `pty.node`→npm 装/更新→隐藏启动器→计划任务注册(Ready)→防火墙→快捷方式→启动,`https://localhost:12300` 返回 302。安装器对重复运行/升级(myhi 已在跑)也做了处理:**先停 myhi 释放 `pty.node` 再 npm**,避免升级时 EBUSY。
63
+
64
+ ## 手动 npm 安装的注意(新版 npm)
65
+
66
+ 若不用安装器、直接 `npm i -g @wendongfly/myhi`,**新版 npm 默认拦截包的安装脚本**(`allow-scripts` 安全特性),会看到 `npm warn allow-scripts` 提示——此时 `node-pty` 的原生模块 `pty.node`(终端核心)没被正确放置,**myhi 终端会起不来**。解决:加 `--allow-scripts` 放行:
67
+
68
+ ```
69
+ npm i -g @wendongfly/myhi --allow-scripts=@wendongfly/myhi,node-pty
70
+ ```
71
+
72
+ (安装器 `install-myhi.ps1` 已自动带这个参数,用安装器不必手动加。)验证:打开 myhi 网页开一个「Shell/终端」会话,能敲命令即正常。
73
+
74
+ ## 局限(当前 MVP)
75
+
76
+ - 仍需要机器能访问 npm(装/升级 myhi)。
77
+ - 计划任务在**登录时**启动一次;若 daemon 中途自己挂了,要到下次登录才拉起(daemon 内部已有 server 崩溃自恢复,daemon 本身很稳)。后续可加一个带重复间隔的看护任务。
78
+ - **触发器是「登录时」**:适合「员工登录后用自己电脑」的场景。若是**无人交互登录的常驻/headless 机器**(重启后没人登录),登录触发不会发生 → 不会自动起;那种机器该用「无论是否登录都运行」的服务模式(但需权衡 SYSTEM 权限/账户密码)。
79
+ - Node <18 只会 EBADENGINE 警告不阻断(实测 16 能跑),但建议尽量 18+。
80
+
81
+ ## 后续可演进(阶段二/三,非本 MVP)
82
+
83
+ - **免装 Node**:随包附 portable `node.exe`(或 Node SEA 打成单 exe),连「装 Node」这道坎也去掉。难点是 `node-pty` 原生模块 `pty.node` 要随包带上。
84
+ - **正式安装包**:用 **Inno Setup** 把上面这套 + portable node 打成一个 `myhi-setup.exe` 安装向导(比 .bat 更友好、可加图标/许可/卸载入口)。
85
+ - **系统托盘小程序**:托盘图标右键「显示地址+二维码 / 启停 / 检查更新 / 打开面板」,日常操作全图形化(不建议上 Electron,太重)。
@@ -0,0 +1,15 @@
1
+ @echo off
2
+ chcp 65001 >nul
3
+ title myhi uninstaller
4
+ rem "am_admin" marker prevents an infinite UAC loop if "net session" misdetects admin rights.
5
+ if "%~1"=="am_admin" goto :run
6
+ net session >nul 2>&1
7
+ if %errorlevel%==0 goto :run
8
+ echo [myhi] Requesting administrator (UAC)...
9
+ powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -ArgumentList 'am_admin' -Verb RunAs"
10
+ exit /b
11
+ :run
12
+ powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0uninstall-myhi.ps1"
13
+ echo.
14
+ echo Done. You can close this window.
15
+ pause
@@ -0,0 +1,6 @@
1
+ {
2
+ "_说明": "AI 大模型网关配置模板。批量部署时:复制本文件为 gateway.json、填入真实 baseUrl/apiKey,放在 installer 文件夹里,安装器会自动部署到每台机器的 ~/.myhi/gateway.json,AI 开箱即用。",
3
+ "_安全": "gateway.json 含密钥,已被 .gitignore 忽略、绝不进 git;只在你的部署包/本机之间流转。",
4
+ "baseUrl": "https://你的AI网关地址",
5
+ "apiKey": "sk-你的密钥"
6
+ }
@@ -0,0 +1,158 @@
1
+ # myhi Windows 傻瓜安装器(阶段一:让员工省心)
2
+ # 作用:把 myhi 装成「开机登录自动后台运行」,员工全程不碰终端。
3
+ # 1) 没装 Node 就用 winget 自动装;2) npm 装/更新 myhi 全局包;
4
+ # 3) 生成隐藏启动器(VBS,无黑窗);4) 注册计划任务(登录触发/当前用户/非提权/脱离会话);
5
+ # 5) 防火墙放行 12300/12301(局域网手机平板可访问);6) 建桌面/开始菜单快捷方式;7) 立即启动。
6
+ # 需以管理员运行(Install-myhi.bat 会自动提权)。
7
+ #Requires -Version 5
8
+ # -Headless:开机即运行(无论是否登录,用 S4U 免密码);不加则默认「登录时运行」(员工电脑场景)。
9
+ # -SkipClaude:不安装 Claude CLI(默认会装,myhi 的 AI 引擎)。
10
+ param([switch]$Headless, [switch]$SkipClaude)
11
+
12
+ $ErrorActionPreference = 'Stop'
13
+ $Port = 12300
14
+ $TaskName = 'myhi-autostart'
15
+
16
+ function Info($m){ Write-Host "[myhi] $m" -ForegroundColor Cyan }
17
+ function Ok($m) { Write-Host "[OK] $m" -ForegroundColor Green }
18
+ function Warn($m){ Write-Host "[!] $m" -ForegroundColor Yellow }
19
+
20
+ try {
21
+ # ---------- 1) Node ----------
22
+ $node = Get-Command node -ErrorAction SilentlyContinue
23
+ if (-not $node) {
24
+ Warn "未检测到 Node.js,尝试用 winget 自动安装 LTS..."
25
+ if (Get-Command winget -ErrorAction SilentlyContinue) {
26
+ # 临时设 Continue:winget 的 stderr 在 ErrorActionPreference=Stop 下会被误判为致命错误
27
+ $eaW = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
28
+ winget install -e --id OpenJS.NodeJS.LTS --accept-source-agreements --accept-package-agreements
29
+ $ErrorActionPreference = $eaW
30
+ $env:Path = [Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [Environment]::GetEnvironmentVariable('Path','User')
31
+ $node = Get-Command node -ErrorAction SilentlyContinue
32
+ }
33
+ if (-not $node) { throw "无法自动安装 Node.js。请先手动装 Node 18+(https://nodejs.org/),再重新运行本安装程序。" }
34
+ }
35
+ $nodeExe = $node.Source
36
+ Ok "Node: $(& $nodeExe -v) ($nodeExe)"
37
+
38
+ # ---------- 2) myhi 全局包 ----------
39
+ # 若本机已在跑 myhi,daemon 会锁住 node-pty 的 pty.node → npm 覆盖时 EBUSY。先停再装。
40
+ # 整段临时设 Continue:taskkill/npm 等【原生命令】的 stderr 在 ErrorActionPreference=Stop
41
+ # 下会被 PS5.1 包成 ErrorRecord 误当致命错误("进程不存在"/EBADENGINE 都会中断安装)。
42
+ $eaPrev = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
43
+ Info "停止可能在运行的 myhi(释放 pty.node,避免升级 EBUSY)..."
44
+ $pidFile = Join-Path $env:USERPROFILE '.myhi\daemon.pid'
45
+ if (Test-Path $pidFile) {
46
+ $dpid = (Get-Content $pidFile -Raw).Trim()
47
+ if ($dpid) { taskkill /PID $dpid /T /F 2>$null | Out-Null }
48
+ }
49
+ # 兜底:按命令行特征杀掉残留 myhi 的 node 进程(不会误伤本安装脚本——它是 powershell.exe)
50
+ Get-CimInstance Win32_Process -Filter "Name='node.exe'" -ErrorAction SilentlyContinue |
51
+ Where-Object { $_.CommandLine -match 'myhi' } |
52
+ ForEach-Object { taskkill /PID $_.ProcessId /T /F 2>$null | Out-Null }
53
+ # 清 npm 上次 EBUSY/ENOTEMPTY 残留的 .myhi-<hash> 临时目录
54
+ $npmRoot0 = (npm.cmd root -g 2>$null | Select-Object -Last 1)
55
+ if ($npmRoot0) { Get-ChildItem (Join-Path $npmRoot0.ToString().Trim() '@wendongfly') -Filter '.myhi-*' -Directory -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
56
+ Start-Sleep -Seconds 2
57
+
58
+ Info "安装/更新 myhi(npm i -g @wendongfly/myhi@latest,稍候)..."
59
+ # 新版 npm 默认拦「包安装脚本」(allow-scripts 安全特性),而 node-pty 靠其安装脚本放置原生
60
+ # pty.node(终端核心)、@wendongfly/myhi 靠 postinstall chmod。带 --allow-scripts 放行这两个包;
61
+ # 老版本 npm 不认此值只当普通 config、脚本本就默认执行,两种 npm 都 OK。
62
+ npm.cmd i -g '@wendongfly/myhi@latest' --allow-scripts=@wendongfly/myhi,node-pty
63
+ $npmExit = $LASTEXITCODE
64
+ if ($npmExit -ne 0) {
65
+ # 万一某 npm 版本因这个 flag 报错,退回普通安装(老 npm 默认就跑脚本)
66
+ npm.cmd i -g '@wendongfly/myhi@latest'
67
+ $npmExit = $LASTEXITCODE
68
+ }
69
+ $npmRoot = (npm.cmd root -g | Select-Object -Last 1).ToString().Trim()
70
+ $ErrorActionPreference = $eaPrev
71
+ if ($npmExit -ne 0) { throw "npm 安装失败 (exit $npmExit)。若是 EBUSY,多为 myhi 仍在运行占用 pty.node,请关掉后重试。" }
72
+
73
+ # ---------- 2b) Claude Code CLI(myhi 的 AI 引擎,@anthropic-ai/claude-code)----------
74
+ if (-not $SkipClaude) {
75
+ Info "安装/更新 Claude CLI(npm i -g @anthropic-ai/claude-code@latest,稍候)..."
76
+ $eaC = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
77
+ npm.cmd i -g '@anthropic-ai/claude-code@latest' --allow-scripts=@anthropic-ai/claude-code
78
+ if ($LASTEXITCODE -ne 0) { npm.cmd i -g '@anthropic-ai/claude-code@latest' }
79
+ $claudeExit = $LASTEXITCODE
80
+ $ErrorActionPreference = $eaC
81
+ # 不因 claude 装失败而中断整体部署(可事后手动补)
82
+ if ($claudeExit -eq 0) { Ok "Claude CLI 已安装" }
83
+ else { Warn "Claude CLI 安装失败(exit $claudeExit),可稍后手动:npm i -g @anthropic-ai/claude-code" }
84
+ }
85
+ $pkgDir = Join-Path $npmRoot '@wendongfly\myhi'
86
+ $daemon = Join-Path $pkgDir 'bin\daemon.js'
87
+ if (-not (Test-Path $daemon)) { throw "未找到 myhi 安装目录:$daemon" }
88
+ Ok "myhi: $(& $nodeExe (Join-Path $pkgDir 'bin\myhi.js') -v)"
89
+
90
+ # ---------- 3) 隐藏启动器(无黑窗)----------
91
+ $cfgDir = Join-Path $env:USERPROFILE '.myhi'
92
+ New-Item -ItemType Directory -Force -Path $cfgDir | Out-Null
93
+ $vbs = Join-Path $cfgDir 'myhi-launch.vbs'
94
+ $runCmd = '"' + $nodeExe + '" "' + $daemon + '"' # 带引号,含空格路径安全
95
+ $vbsArg = $runCmd -replace '"', '""' # VBS 字符串里的 " 要写成 ""
96
+ $vbsBody = "' myhi 安装器生成:窗口隐藏(0)+不等待(False) 启动 daemon`r`n" +
97
+ "CreateObject(""WScript.Shell"").Run """ + $vbsArg + """, 0, False"
98
+ # VBS 用系统 ANSI 编码存,兼容中文用户名路径
99
+ [IO.File]::WriteAllText($vbs, $vbsBody, [Text.Encoding]::Default)
100
+ Ok "启动器:$vbs"
101
+
102
+ # 部署 AI 网关配置:若安装包目录随附 gateway.json(管理员预置,含 baseUrl/apiKey),复制到 ~/.myhi。
103
+ # 这样批量部署时 AI 开箱即用;此文件含密钥,只留本机、绝不进 git(见 installer/README 的批量部署)。
104
+ $gwSrc = Join-Path $PSScriptRoot 'gateway.json'
105
+ if (Test-Path $gwSrc) {
106
+ Copy-Item $gwSrc (Join-Path $cfgDir 'gateway.json') -Force
107
+ Ok "已部署 AI 网关配置(gateway.json → ~/.myhi,AI 开箱即用)"
108
+ } else {
109
+ Warn "未随附 gateway.json:AI 需部署后在 ~/.myhi/gateway.json 填 {\"baseUrl\":...,\"apiKey\":...} 才能用(见 README)"
110
+ }
111
+
112
+ # ---------- 4) 计划任务:登录触发 / 当前用户 / 非提权 / 脱离会话 ----------
113
+ # 用当前用户身份 + RunLevel Limited:myhi 里开的终端就是普通员工权限,不是管理员,避免提权面。
114
+ # 用规范账户名(机器名\用户 或 域\用户),Windows 能正确映射到 SID;
115
+ # 直接拼 $env:USERDOMAIN\$env:USERNAME 在某些环境(如 SSH 会话)会报"账户名与安全标识无映射"。
116
+ $me = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
117
+ $action = New-ScheduledTaskAction -Execute 'wscript.exe' -Argument ('"' + $vbs + '"')
118
+ $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit ([TimeSpan]::Zero)
119
+ if ($Headless) {
120
+ # 常驻/无人登录:开机即以该用户身份后台跑(S4U 免密码、不需要交互登录)。RunLevel Limited 保持非提权。
121
+ $trigger = New-ScheduledTaskTrigger -AtStartup
122
+ $principal = New-ScheduledTaskPrincipal -UserId $me -LogonType S4U -RunLevel Limited
123
+ $modeDesc = "开机即运行(无论是否登录)"
124
+ } else {
125
+ # 员工电脑:登录时在其会话里后台跑。
126
+ $trigger = New-ScheduledTaskTrigger -AtLogOn -User $me
127
+ $principal = New-ScheduledTaskPrincipal -UserId $me -LogonType Interactive -RunLevel Limited
128
+ $modeDesc = "登录时运行"
129
+ }
130
+ Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null
131
+ Ok "开机自启已设置(计划任务 $TaskName:$modeDesc,普通权限)"
132
+
133
+ # ---------- 5) 防火墙 ----------
134
+ foreach ($p in @(12300, 12301)) {
135
+ $rn = "myhi TCP $p"
136
+ Get-NetFirewallRule -DisplayName $rn -ErrorAction SilentlyContinue | Remove-NetFirewallRule -ErrorAction SilentlyContinue
137
+ New-NetFirewallRule -DisplayName $rn -Direction Inbound -Action Allow -Protocol TCP -LocalPort $p -Profile Private,Domain | Out-Null
138
+ }
139
+ Ok "防火墙已放行 12300/12301(局域网手机/平板可访问)"
140
+
141
+ # ---------- 6) 快捷方式 ----------
142
+ $url = "https://localhost:$Port"
143
+ foreach ($dir in @([Environment]::GetFolderPath('Desktop'), (Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs'))) {
144
+ if (Test-Path $dir) { Set-Content -Path (Join-Path $dir 'myhi 控制台.url') -Value "[InternetShortcut]`r`nURL=$url" -Encoding ASCII }
145
+ }
146
+ Ok "快捷方式:myhi 控制台 → $url"
147
+
148
+ # ---------- 7) 立即启动 ----------
149
+ Start-ScheduledTask -TaskName $TaskName
150
+ Start-Sleep -Seconds 6
151
+ Write-Host ""
152
+ Info "访问地址:$url (首次有自签证书警告,点『高级 → 继续前往』即可)"
153
+ Info "默认密码见:$cfgDir\password"
154
+ Ok "安装完成!以后开机登录自动运行,无需再开终端或敲命令。"
155
+ } catch {
156
+ Warn "安装失败:$($_.Exception.Message)"
157
+ exit 1
158
+ }
@@ -0,0 +1,39 @@
1
+ # myhi Windows 卸载器:撤销 install-myhi.ps1 的所有设置(保留 myhi 本体与 ~/.myhi 数据)。
2
+ #Requires -Version 5
3
+ $ErrorActionPreference = 'Continue'
4
+ $TaskName = 'myhi-autostart'
5
+ function Ok($m){ Write-Host "[OK] $m" -ForegroundColor Green }
6
+ function Info($m){ Write-Host "[myhi] $m" -ForegroundColor Cyan }
7
+
8
+ # 1) 停并删计划任务
9
+ try {
10
+ if (Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue) {
11
+ Stop-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
12
+ Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
13
+ Ok "已删除开机自启计划任务"
14
+ }
15
+ } catch {}
16
+
17
+ # 2) 停掉正在跑的 daemon
18
+ try {
19
+ $pidFile = Join-Path $env:USERPROFILE '.myhi\daemon.pid'
20
+ if (Test-Path $pidFile) {
21
+ $dpid = (Get-Content $pidFile -Raw).Trim()
22
+ if ($dpid) { & taskkill /PID $dpid /T /F 2>$null | Out-Null; Ok "已停止 daemon (PID $dpid)" }
23
+ }
24
+ } catch {}
25
+
26
+ # 3) 删防火墙规则
27
+ foreach ($p in @(12300, 12301)) {
28
+ Get-NetFirewallRule -DisplayName "myhi TCP $p" -ErrorAction SilentlyContinue | Remove-NetFirewallRule -ErrorAction SilentlyContinue
29
+ }
30
+ Ok "已移除防火墙规则"
31
+
32
+ # 4) 删快捷方式 + 启动器
33
+ foreach ($dir in @([Environment]::GetFolderPath('Desktop'), (Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs'))) {
34
+ Remove-Item (Join-Path $dir 'myhi 控制台.url') -Force -ErrorAction SilentlyContinue
35
+ }
36
+ Remove-Item (Join-Path $env:USERPROFILE '.myhi\myhi-launch.vbs') -Force -ErrorAction SilentlyContinue
37
+ Ok "已删除快捷方式与启动器"
38
+
39
+ Info "卸载完成。myhi 全局包与 ~/.myhi 配置仍保留;如需彻底清除:npm uninstall -g @wendongfly/myhi + 删 %USERPROFILE%\.myhi"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wendongfly/myhi",
3
- "version": "1.3.121",
3
+ "version": "1.3.128",
4
4
  "description": "Web-based terminal sharing with chat UI — control your terminal from phone via LAN/Tailscale",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,7 +9,8 @@
9
9
  },
10
10
  "files": [
11
11
  "bin/",
12
- "dist/"
12
+ "dist/",
13
+ "installer/"
13
14
  ],
14
15
  "scripts": {
15
16
  "start": "node dist/index.js",