Files
pikasTech-unidesk/docs/reference/windows-passthrough.md
T
2026-06-03 01:44:46 +00:00

219 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Windows Passthrough Reference
Windows 透传用于让 WSL provider 通过 UniDesk 的 Host SSH / WSL SSH 维护桥调用 Windows 侧工具链、驱动和 skill,同时尽量保持一套可维护的 skill 入口。它的目标不是把 Windows 当成新的 provider,而是让 `ssh <PROVIDER_ID>` 进入 WSL 后,可以稳定触达 Windows `cmd.exe`、PowerShell、Python、Node/npm、Keil、COM 串口和 USB 调试器。
## Architecture
标准链路是:本机或计算节点 CLI 调用 `trans <PROVIDER_ID> ...`main server 的 backend-core 通过 provider-gateway 的既有 WebSocket 把终端流量转给目标 providerprovider-gateway 再用只读挂载的维护私钥连到目标 WSL sshd。进入 WSL 后,Windows-only 工具由 WSL 用户目录下的轻量 wrapper 调用 Windows 可执行文件。
这条链路分三层维护:
- `provider-gateway` 只负责 Host SSH / WSL SSH 维护桥,不直接理解 Keil、串口或业务 skill。
- WSL wrapper 负责路径转换、当前目录转换、Windows 进程启动、UTF-8 输出和 cmd/PowerShell 差异。
- skill wrapper 负责把用户仍然熟悉的 `keil``serial-monitor``board-comm` 命令映射到正确运行侧,避免维护两套互相分叉的 skill。
## UniDesk Win Route
简单 Windows `cmd.exe` 命令不需要依赖节点侧 `win-cmd` wrapper。UniDesk CLI 内置 `win` route
```bash
trans <PROVIDER_ID>:win cmd ver
trans <PROVIDER_ID>:win/c/test cmd cd
trans <PROVIDER_ID>:win skills --limit 20
```
`<PROVIDER_ID>:win` 只定位到 WSL provider 的 Windows host cmd 执行面,后面的 `cmd <command-line>` 才是操作。`<PROVIDER_ID>:win/<drive>/<path>` 使用 slash 语法设置 Windows cwd,例如 `D601:win/c/test` 会在 Windows cmd 内执行 `cd /d "C:\test"`。该入口固定在运行用户命令前设置 `chcp 65001>nul``set "PYTHONUTF8=1"``set "PYTHONIOENCODING=utf-8"`,因此中文 stdout/stderr 和 Python 子进程默认按 UTF-8 处理;环境变量必须使用 cmd 引号写法,避免 `set VAR=1 && ...` 把分隔符前的空格写进变量值。
长期命名只允许 `win`,不允许 `win32``win` route 仍复用 provider-gateway 的 Host SSH / WSL SSH 维护桥抵达目标 WSL provider,但不会依赖 WSL 登录 shell 的 Windows `PATH`,也不再通过节点侧 `win-cmd` wrapper 二次转发。CLI 固定从 `/mnt/c/Windows` 启动 Windows PowerShell UTF-8 launcher,再由 launcher 执行 `C:\Windows\System32\cmd.exe /d /s /c <command-line>`PowerShell 只负责把 Console/Input/OutputEncoding 设为 UTF-8 并保留 cmd 的 exit code,用户命令语义仍属于 Windows `cmd.exe`。需要 Keil、串口、Windows Node/npm 或复杂路径转换时,继续使用下文的 skill/wrapper 入口,直到对应能力被纳入 UniDesk 内置 route。
`<PROVIDER_ID>:win skills` 是 Windows 用户 skill 发现入口,默认读取当前 Windows 用户 `%USERPROFILE%\.agents\skills`,输出 JSON 中包含 `roots``counts` 和每个 skill 的 `name``path``skillFile``description`。需要同时读取 `%USERPROFILE%\.codex\skills` 时使用 `--scope all`;只看 Codex skill 时用 `--scope codex`。该入口用于替代手写 `cmd dir``powershell Get-ChildItem` 或宽泛扫描用户目录。
## Windows Long-Lived Process Detach
`trans <PROVIDER_ID>:win cmd ...``trans <PROVIDER_ID> script -- powershell.exe ...` 适合短命令、只读探测和有界 skill 调用,不适合直接启动 Windows 长驻进程。Windows `cmd start``cmd /c ... &`、PowerShell `Start-Process -PassThru` 或带 stdout/stderr 重定向的子进程,仍可能被 provider-gateway/SSH broker 按子进程树或继承句柄等待;结果是远端进程其实已启动,但 `trans` 会持续占用 provider session,后续 D601/G14 高频调用被 provider session lock 串行排队。
长驻 Windows 进程必须使用明确脱离当前 `trans` 会话的启动模型:
- 优先把启动参数写入节点私有 profile 或 `.cmd`/`.ps1` 文件,再通过 Windows Task Scheduler、Windows Service、NSSM、PM2 Windows service 或同等 supervisor 启动。
- 如果只是临时实验,使用 `schtasks /Create ... /TR "<cmd file>" /SC ONCE ... /F` 后再 `schtasks /Run ...`,并把 stdout/stderr 写入固定日志文件;验证用独立短命令读取 `tasklist``Get-CimInstance Win32_Process`、日志尾部和服务健康。
- 不要在 `D601:win cmd` 内用 `start``Start-Process` 直接启动 `hwlab-gateway`、串口 monitor、Codex app-server、Keil job watcher 等长驻进程;如果误用了并导致 `trans` 卡住,应先停止对应 Windows PID 或本地被卡住的 trans/tran broker 进程,再改为 detached supervisor。
- 启动命令必须避免从 WSL UNC cwd 进入 Windows cmd;长驻进程的 `cwd` 应是 Windows 盘符路径,例如 `F:\Work\HWLAB`,日志也写到同一节点私有 `.state` 或 skill state 目录。
- 长驻进程的验收标准不是“启动命令返回”,而是独立短命令能看到 PID、日志首行、health endpoint 或 cloud-side session/resource/capability 已注册。
该规则尤其适用于 D601 Windows `hwlab-gateway` 连接 G14 HWLAB cloud-api 的场景:gateway 是长期 outbound poll 进程,必须由 detached launcher 或 supervisor 管理;`trans` 只负责创建/更新 launcher、触发启动和读取状态。
## Skill Discovery
先用 UniDesk SSH 透传内置的 skill 发现入口确认目标节点上 WSL 与 Windows 两侧 skill 的实际位置:
```bash
trans <PROVIDER_ID> skills --limit 80
trans <PROVIDER_ID> skills --scope windows --limit 40
bun scripts/cli.ts --main-server-ip <MAIN_SERVER_IP> ssh <PROVIDER_ID> skills --scope wsl --limit 20
```
`ssh <PROVIDER_ID> skills` 输出 JSON,包含 `roots``skills`。WSL provider 会同时扫描 WSL/Linux 的 `~/.agents/skills``~/.codex/skills`,以及 Windows 用户目录下的 `/mnt/c/Users/*/.agents/skills``/mnt/c/Users/*/.codex/skills`。不要用宽泛的 `find /mnt/*` 搜 Windows 盘;Windows 挂载层可能因权限、索引或设备状态导致长时间阻塞。
## Wrapper Contract
WSL 用户的 `~/.local/bin` 是推荐 wrapper 放置位置,并应在 SSH 登录 shell 的 `PATH` 中优先于系统路径。wrapper 名称和职责固定如下:
- `win-powershell <powershell-command>`:用于 Windows 发现、WMI/CIM、注册表、设备和 JSON 输出;应设置 UTF-8 输出,并用 `Set-Location -LiteralPath` 进入 Windows 当前目录。
- `win-cmd <cmd-line>`:用于 `.cmd``.bat` 或必须走 `cmd.exe` 的 legacy 工具;应先写入 Windows 临时 `.cmd` 文件再执行,避免 UNC 当前目录警告和带空格路径引号错误。
- `win-argpath <arg>`:把 `/mnt/<drive>/...` 或存在的 WSL 路径转换为 Windows 路径,其余参数原样返回。
- `win-py <args...>`:调用 Windows `py.exe -3`,并对路径参数做 `/mnt/<drive>``X:\...` 的转换。
- `win-node <args...>`:调用 Windows `node.exe`,适合必须运行在 Windows 设备上下文中的 Node 脚本。
- `win-npm <args...>`:调用 Windows `npm.cmd`;涉及 COM 口、USB 设备或 Windows-only npm 依赖时优先使用它。
- `win-skill-path <skill-name>`:在 Windows `.agents/skills``.codex/skills` 中定位 skill 根目录,供上层 skill wrapper 复用。
`win-cmd` 不应直接从 WSL 默认 UNC cwd 运行 `cmd.exe /C <command>`。稳定做法是选择一个 Windows 可写临时目录,例如 `C:\Temp`,生成 `.cmd` 文件,在脚本中 `chcp 65001``cd /d "<Windows cwd>"`,再执行用户命令。这样可同时处理 `C:\Program Files` 这类带空格路径和 Windows 工具不支持 UNC 当前目录的问题。
## Path And CWD Rules
Windows 可执行文件只能稳定访问 Windows 盘符路径。WSL wrapper 应遵循这些规则:
- 当前目录在 `/mnt/<drive>/...` 下时,自动转换为 `<DRIVE>:\...` 作为 Windows cwd。
- 当前目录不在 `/mnt/<drive>` 下时,默认使用 `C:\Windows`,或由调用者显式设置 `WIN_CWD`
- 参数中存在的 `/mnt/<drive>/...` 路径应转换为 Windows 路径;普通参数、IP、端口、JSON 字符串不应被转换。
- 需要 Windows 工具直接读写的工程仓库应放在 Windows 盘符挂载路径下;WSL 原生 `/home/...` 更适合作为 UniDesk、脚本和临时 Linux 工作区。
- 从 WSL 到 Windows 的搜索优先使用 `win-powershell``ssh <PROVIDER_ID> skills`,再用结构化 `glob`/`find` 缩小到已知目录。
## Skill Compatibility Strategy
不要为 Windows 和 WSL 分别维护两套业务逻辑分叉的 skill。推荐策略是保留一个用户可见命令入口,在 wrapper 中选择正确运行侧:
- `keil`:依赖 Windows Keil、CMSIS-DAP/ST-Link/J-Link 驱动、注册表和工程路径,WSL 入口应调用 Windows 侧 `keil` skill 的 `keil-cli.py`,通常经 `win-py` 执行。
- `serial-monitor`:访问 Windows COM 口时必须运行在 Windows Node/npm 上,WSL 入口应通过 `win-npm --prefix <windows-skill-dir> run cli -- ...` 调用。
- `board-comm`:当前 JSON-RPC over TCP 不依赖 Windows 驱动,可直接用 WSL Python 运行 WSL 侧 skill;只有未来新增 serial transport 时才需要再评估是否切到 Windows 侧。
工程级 wrapper 可以保留 `*-wsl` 别名,例如 `keil-wsl``serial-monitor-wsl``board-comm-wsl`,但用户文档中的正式入口仍应优先写 `keil``serial-monitor``board-comm`,避免让任务 prompt 绑定到某台机器的一次性脚本名。
## Skill Modification And Bootstrap Status
Windows 透传机制不要求修改 WSL skill 的业务代码。标准交付边界应区分三类内容:
- UniDesk 内置能力:`ssh <PROVIDER_ID> skills``apply-patch``glob``py` 等 helper 由 UniDesk CLI 在 SSH 会话启动时注入 `/tmp/unidesk-ssh-tools`,属于开箱即用能力;它们不修改远端 skill 目录。
- 节点 bootstrap`win-cmd``win-powershell``win-py``win-npm``win-skill-path` 以及 `keil``serial-monitor``board-comm` 的 WSL wrapper 属于节点运行环境 bootstrap,通常放在目标 WSL 用户的 `~/.local/bin`;这不是 skill 本身开箱即用的一部分。
- skill 代码:除非明确要把 wrapper 能力合入某个 skill,否则不得为了某台节点直接改 `~/.agents/skills/<skill>``~/.codex/skills/<skill>` 的业务代码;如果确实修改了 skill CLI 或 `SKILL.md`,必须按该 skill 的测试和文档规则独立验收。
因此,判断一个节点是否“开箱即用”时要分别检查:UniDesk CLI 是否支持 `ssh skills`,目标 WSL 是否已有 wrapper bootstrapWindows 侧是否已有 Keil/Node/npm/Python/驱动,目标 skill 是否已有依赖。缺少 wrapper 或 Windows 工具链时,应报告为节点环境未 bootstrap 完成,而不是把它误判成 skill 逻辑失败。
当前推荐不在 wrapper 中自动安装依赖。`serial-monitor` 所需 Windows `node_modules`、Keil pack、pyOCD、USB probe 驱动、COM 驱动等都应由节点 bootstrap 或人工安装完成;wrapper 只负责调用和给出明确错误。这样可以避免 agent 在硬件节点上静默安装版本不明的依赖,导致后续验收不可复现。
## Dependency Bootstrap
Windows 透传依赖分为四类:UniDesk 侧能力、WSL 侧基础环境、Windows 侧工具链、skill 本地依赖。它们应由节点 bootstrap 或人工维护显式安装,不应由业务任务中的 wrapper 静默安装。
### UniDesk And WSL Prerequisites
WSL provider 至少需要:
- WSL sshd 已启动,provider-gateway 容器可用维护私钥免密登录目标 WSL 用户。
- 目标 WSL 用户 `PATH` 包含 `~/.local/bin`,用于放置 `win-*` 与 skill wrapper。
- WSL 内有 `python3``base64``bash``wslpath`UniDesk SSH 注入的 `py``apply-patch``glob``skill-discover` 依赖这些基础命令。
- WSL 可访问 Windows 盘符挂载,例如 `/mnt/c``/mnt/d``/mnt/f`
- 如果 provider-gateway 跑在 Docker Desktop daemon 上,容器到 WSL sshd 的 `host.docker.internal:22` 链路必须可用。
WSL wrapper bootstrap 至少应安装或生成这些脚本:
```bash
mkdir -p ~/.local/bin
# win-cmd, win-powershell, win-argpath, win-py, win-node, win-npm, win-skill-path
# keil, serial-monitor, board-comm wrappers
chmod +x ~/.local/bin/win-* ~/.local/bin/keil ~/.local/bin/serial-monitor ~/.local/bin/board-comm
```
这些 wrapper 属于节点环境,不应提交到 UniDesk 仓库,除非后续专门新增一个受版本管理的 provider bootstrap 脚本。
### Windows Toolchain Prerequisites
Windows 侧至少需要按目标硬件场景安装:
- Python Launcher`py.exe` 可用,且 `py -3` 指向 Python 3。
- Node.js/npm`node.exe``npm.cmd` 可用;涉及 COM 口的 TypeScript skill 应运行在 Windows Node 上。
- Keil MDK`UV4.exe` 可用,Keil Pack 已安装到工程需要的 MCU 系列。
- pyOCDWindows Python 环境中可用 `python -m pyocd`,用于 CMSIS-DAP 探头检测和 pyOCD backend 下载。
- USB 调试器驱动:CMSIS-DAP、DAPLink、ST-Link 或 J-Link 对应驱动可被 Windows 识别。
- 串口驱动:目标板 UART bridge 在 Windows 设备管理器中显示为 `COMx`
- PowerShell:用于 WMI/CIM 设备发现、路径诊断和 Windows 侧环境检查。
推荐的只读检查命令:
```bash
win-powershell "Get-Command py.exe,node.exe,npm.cmd -ErrorAction SilentlyContinue | Select-Object Name,Source | ConvertTo-Json"
win-powershell "Get-CimInstance Win32_SerialPort | Select-Object DeviceID,Name,Description,PNPDeviceID | ConvertTo-Json -Depth 3"
win-cmd "where py && where node && where npm"
```
Keil 与 pyOCD 检查应通过 skill 入口完成:
```bash
keil status
keil list-devices -p <project.uvprojx>
```
### Skill Dependencies
各 skill 的依赖安装边界如下:
- `keil`Windows 侧 `~/.agents/skills/keil` 应已存在 `keil-cli.py``config.json` 与所需 Python 依赖;Windows Python 中必须能导入 pyOCD。Keil pack 和 probe 驱动属于 Windows 工具链依赖,不属于 WSL wrapper 自动安装范围。
- `serial-monitor`Windows 侧 `~/.agents/skills/serial-monitor` 需要已执行过 `npm install`,生成对应 Windows 平台的 `node_modules`。从 WSL 调用时应使用 `win-npm --prefix <windows-skill-dir> run cli -- ...`,不要复用 WSL 的 `node_modules` 去访问 Windows COM 口。
- `board-comm`JSON-RPC over TCP 可直接使用 WSL 侧 `~/.agents/skills/board-comm` 与 WSL Python;如果 `check` 因缺少 pyright 失败,但 `jrpctcp` 正常,不应阻塞硬件通信验证。若未来增加 serial transport,再按运行侧补充 Windows 依赖。
依赖安装必须显式、可复现,并优先在对应 skill 的 `SKILL.md` 或节点 bootstrap 文档中记录。业务任务中如果发现依赖缺失,应输出缺失项、建议安装命令和验证命令,而不是直接静默安装。
### Verification Matrix
节点完成依赖 bootstrap 后,至少运行以下验证:
```bash
trans <PROVIDER_ID> skills --limit 20
trans <PROVIDER_ID> -- 'export PATH="$HOME/.local/bin:$PATH"; command -v win-cmd win-powershell win-py win-npm keil serial-monitor board-comm'
trans <PROVIDER_ID> -- 'export PATH="$HOME/.local/bin:$PATH"; win-py -V; win-npm -v'
trans <PROVIDER_ID> -- 'export PATH="$HOME/.local/bin:$PATH"; keil status'
trans <PROVIDER_ID> -- 'export PATH="$HOME/.local/bin:$PATH"; serial-monitor ports'
trans <PROVIDER_ID> -- 'export PATH="$HOME/.local/bin:$PATH"; board-comm debug build-jrpctcp-request get api'
```
硬件项目级验收还应覆盖真实 `build``program`、串口抓取和 `board-comm jrpctcp get api`。如果只有依赖检查通过但没有真实硬件闭环,不能宣称该工程已完成下载和通信验收。
## Hardware Workflow
Keil/串口/board-comm 的通用顺序如下:
1. `ssh <PROVIDER_ID> skills` 确认 WSL 与 Windows skill 位置。
2. `win-powershell``serial-monitor ports` 确认可见 COM 口。
3. `keil status``keil list-devices -p <project.uvprojx>` 确认 Keil、pyOCD 和 USB probe。
4. `keil build --wait -p <project.uvprojx> -t <target>` 构建。
5. `serial-monitor server start --force``serial-monitor monitor start -p <COMx> -b <baud>` 先打开串口。
6. `keil program --wait ... -u <probe_uid>` 下载并运行。
7. `serial-monitor fetch --session-only --no-dedup -l <N>` 抓取串口证据。
8. `board-comm jrpctcp --host <board_ip> --port <port> get api` 验证主动通信面。
多 probe 同时在线时,`keil program``keil detect` 必须显式传 `-u <probe_uid>`。若 Keil UV4 backend 报缺少 flash/download metadata,可优先用 pyOCD backend 完成下载;是否补齐 UV4 工程下载配置应作为工程维护问题处理,而不是 SSH/Windows 透传问题。
## Code Queue Windows Native Codex
Code Queue 支持在提交任务时选择 `executionMode=windows-native`。该模式用于 D601 这类 WSL ProviderD601 Code Queue 先通过本节点执行环境建立任务运行环境,但容器内不启动 `codex`;容器只运行 stdio relay,连接到 WSL 侧 bridge,再由 bridge 调用 Windows 宿主原生 `codex app-server --listen stdio://`。这样 UniDesk 控制面到 Provider 的临时断连不会直接终止 Windows Codex 进程。
约束:
- 只支持非主 server WSL Provider 和 Codex 模型;`minimax-m3` / `minimax-m2.7` / OpenCode port 不走该模式。
- 工作目录必须在 `/mnt/<drive>/...` 下,供 `win-cmd` 转换为 Windows 盘符 cwdD601 默认提示为 `/mnt/f/Work/ConStart`
- Windows 侧必须已安装 `codex`,且 WSL wrapper `win-cmd` 可用;可用 `trans D601 -- 'export PATH="$HOME/.local/bin:$PATH"; win-cmd "where codex && codex --version"'` 验证。
- 任务 JSON、列表、Trace 摘要和前端卡片必须显示 `executionMode`,便于区分默认容器 Codex 与 Windows 原生 Codex。
## Remote Frontend Limits
`--main-server-ip ... ssh <PROVIDER_ID> <command>` 走 frontend 登录态和 `host.ssh` dispatch,适合短命令和 skill discovery。它不流式转发 stdin,也受 provider-gateway 的 host.ssh command length 限制;`apply-patch``py < stdin`、超长 inline 脚本和需要完整终端流的操作应在 main server 本机 CLI 上执行,或显式走旧 SSH transport。
`ssh <PROVIDER_ID> skills` 在 remote frontend 模式下使用短 inline 发现脚本以避开命令长度限制;如果输出被任务历史截断,应改在 main server 本机 CLI 执行同一命令以获得完整 stdout。
## Safety Rules
- Windows 透传只用于节点诊断、硬件工具链和人工维护,不得作为 provider-gateway 自重建通道;provider-gateway 升级仍必须走 `provider.upgrade mode=schedule`
- 不要把 Windows 透传 wrapper 写入业务仓库根目录;它们属于节点运行环境,应放在 WSL 用户目录或节点私有 bootstrap 脚本中。
- 不要在 wrapper 中静默安装依赖;缺少 `py.exe`、Node/npm、Keil、COM 驱动或 probe 驱动时,应输出明确错误并让节点 bootstrap 修复。
- 不要把 Windows 用户目录、串口日志、Keil 日志、SSH key 或 provider token 提交到 UniDesk 仓库。
- 串口抓取和烧录会影响真实硬件状态;执行前应确认目标 project、target、probe UID、COM 口和 baud rate。