Files
Hermit/docs/README-windows.md
T
WHC 2a43ae6622
ci / linux (clang) (push) Canceled after 0s
ci / linux (gcc) (push) Canceled after 0s
ci / sanitizers (push) Canceled after 0s
ci / musl (push) Canceled after 0s
ci / macos (push) Canceled after 0s
Windows: official port -- UCRT static build, UTF-8 throughout, Low IL sandbox, ncurses TUI, installer; v0.6.0
Build
  * cross build switches to pkgsCross.ucrt64 (shell-win.nix); curl (Schannel),
    winpthreads and ncurses 6.6 are linked statically, so the release is
    cst-agent.exe + busybox.exe (busybox-w32 Unicode) with no extra DLLs
  * windres embeds a manifest with activeCodePage=UTF-8 and a version resource
  * ncurses 6.6 Windows console driver patches (mouse button state, A_DIM,
    wide-char declarations): scripts/patches/
  * scripts/bootstrap_msys2.sh builds the same release natively in MSYS2
    UCRT64; PR #1's MINGW64 notes now point there
  * vendor/tre-regex (musl's TRE) provides <regex.h> on MinGW

UTF-8
  * paths cross the system call boundary as UTF-16 (*W APIs); console code
    pages set to 65001 and restored on exit; files are read and written in
    binary mode
  * child output that is not valid UTF-8 is decoded from the console, OEM or
    ANSI system code page
  * read_file hides CR; edit_file, apply_patch and write_file keep CRLF line
    endings and a UTF-8 BOM

OS layer and processes
  * os_dir_* and cst_fnmatch replace the POSIX-only directory walks in
    subagent, plugins, skills, undo and fs_tools; realpath / path_under and
    symlink rejection work on Windows
  * every child goes through CreateProcessW with its own environment block
    inside a Job Object, so timeouts and Esc end the whole process tree

Sandbox (auto mode, "auto · lowil")
  * run_shell runs with a restricted Low integrity token; the workspace gets
    an inheritable Low label once, the sandbox TEMP is labeled Low, and the
    credentials file gets a no-read-up label
  * drive roots, the profile and system folders are never labeled
  * network commands still ask, since Low IL does not block the network;
    Access denied and MSYS2's 0xc0000142 offer a rerun outside the sandbox
  * /sandbox lists labeled folders, /sandbox reset-labels restores them

TUI
  * raster console fonts are switched to Consolas / NSimSun while running
  * the home logo falls back to text when the console font lacks U+2580
  * mouse drag copy goes to the Windows clipboard

Distribution
  * scripts/install_windows.ps1 installs a Gitea release into
    %LOCALAPPDATA%\Programs\cst-agent and adds it to the user PATH;
    cst-agent-update.cmd reruns it; scripts/release_windows.sh uploads the
    zip with the token taken from the environment
  * scripts/run_windows.bat is gone; docs/README-windows.md is rewritten

Tests
  * new test_lowil, test_win_utf8 and test_os_dir; tests made portable
    (cst_test_util.h)
  * scripts/win_test.sh and scripts/winvm/ run the suite on English and
    Chinese Windows Server VMs as Administrator, a standard user and a
    Chinese user name: 29/29 on all six
2026-10-06 23:08:14 +08:00

178 lines
8.4 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.
# CST-Agent on Windows
原生 Windows 版:一个静态链接的 `cst-agent.exe`(UCRT,内嵌 UTF-8 清单)加一个
`busybox.exe`(busybox-w32 Unicode 版)作为 shell,不依赖其他 DLL,也不需要管理员权限。
## 安装
在 PowerShell 里(Windows PowerShell 5.1 或 PowerShell 7 都行):
```powershell
irm https://git.whcself.xyz/WHC/CST-agent/raw/branch/main/scripts/install_windows.ps1 | iex
```
脚本从 Gitea Release 下载 `cst-agent-VERSION-windows-x86_64.zip`,校验 `.sha256`,
装到 `%LOCALAPPDATA%\Programs\cst-agent`,并把这个目录加进**用户** PATH。装完新开一个终端:
```bat
cd C:\code\my-project
cst-agent
```
首次启动会让你选 provider 并输入 API key(遮罩输入,按 provider 保存)。
以后升级:
```bat
cst-agent-update :: 最新版
cst-agent-update -Version 0.6.0 :: 指定版本
```
正在运行的 `cst-agent.exe` 不会挡住升级:旧文件会先改名为 `.old`,下次升级时删掉。
安装脚本的参数(下载后用 `powershell -ExecutionPolicy Bypass -File install_windows.ps1 ...` 运行):
| 参数 | 环境变量 | 作用 |
|---|---|---|
| `-Version 0.6.0` | `CST_VERSION` | 指定版本,默认最新 |
| `-Prefix D:\tools\cst` | `CST_PREFIX` | 安装目录 |
| `-Zip FILE` | | 用本地 zip,不联网 |
| `-NoPath` | | 不改用户 PATH |
| | `CST_GITEA` / `CST_REPO` | 换 Gitea 服务器或仓库(默认 `WHC/CST-agent`) |
不想用脚本的话,把 zip 解压到任意目录直接运行 `cst-agent.exe` 也可以。
## 系统要求
- Windows 10 1903(build 18362)及以上、Windows 11、Windows Server 2022 / 2025。
更老的系统不认清单里的 `activeCodePage=UTF-8`,安装脚本会直接拒绝。
- x86_64。Windows 10 1903 起系统自带 UCRT,无需另装运行库。
- 终端:Windows Terminal 或传统控制台(conhost)都行。
## 发行包内容
```
windows-x86_64/
cst-agent.exe # 静态链接:curl(Schannel)、ncurses 6.6、winpthreads
busybox.exe # busybox-w32 Unicode 版,run_shell 用它的 sh
LICENSE.busybox
README.md # 本文件
VERSION
cst-agent-update.cmd # 调用旁边的 install_windows.ps1 升级本目录
install_windows.ps1
```
## 文件位置
| 内容 | 位置 |
|---|---|
| API key(每个 provider 一个) | `%APPDATA%\cst-agent\credentials`,只有当前用户可读,并带“禁止向上读”标签(沙箱内读不到) |
| 上次的 provider、模型、推理强度、确认模式 | `%APPDATA%\cst-agent\settings.json` |
| 沙箱打过标签的目录 | `%APPDATA%\cst-agent\sandbox-labels` |
| 会话、撤销快照、导出 | `<工作区>\.agent\` |
设置了绝对路径的 `XDG_CONFIG_HOME` 时用 `%XDG_CONFIG_HOME%\cst-agent`。
## 编码:全部 UTF-8
- exe 内嵌 `activeCodePage=UTF-8` 清单:进程的 ANSI 代码页就是 65001,命令行参数、
环境变量、文件名都以 UTF-8 进出;内部所有路径在系统调用边界转成 UTF-16(`*W` API)。
- 控制台输入输出代码页在启动时设为 65001,退出时恢复。
- 文件按字节读写,不做换行转换。`read_file` 给模型看的是去掉 `\r` 的文本;`edit_file`、
`apply_patch`、`write_file` 会保持原文件的 CRLF 换行和 UTF-8 BOM。
- 子进程输出:先按 UTF-8 解码;不是合法 UTF-8 时依次尝试控制台代码页、系统 OEM / ANSI
代码页(比如中文系统的 936),转成 UTF-8 再交给模型。
- 中文用户名、中文工作区路径(`C:\Users\测试\项目`)都已在中英文系统上测过。
## 终端界面(TUI)
用的是打过补丁的 ncurses 6.6 Windows 控制台驱动(补丁在
`scripts/patches/ncurses-6.6-win32-console.patch`):
- 中文按两列宽显示,光标位置正确;粘贴多行不会直接发送。
- 鼠标:点击、拖选复制(写入 Windows 剪贴板)、滚轮滚动;`/mouse` 关闭。
- `/copy` 和拖选复制走 Win32 剪贴板 API,不依赖终端的 OSC 52。
- 控制台是点阵字体时(显示不了中文,会变成 `?`),启动时自动换成同字号的 Consolas
(中文系统换成新宋体),退出时换回去。
- 传统控制台不做字形回退:当前字体缺 logo 用的方块字符时(比如中文系统默认的新宋体),
首页改用文字 logo。
## Shell 沙箱:Low 完整性级别
`auto` 确认模式下,`run_shell` 在 Low 完整性级别的受限令牌里运行(界面显示 `auto · lowil`):
- 子进程的令牌去掉了管理员组和特权,完整性级别为 Low(S-1-16-4096),放进 Job Object,
超时或按 Esc 时整个进程树一起结束。
- Low 进程只能写标为 Low 的位置。第一次在某个工作区跑沙箱命令时,CST-Agent 给工作区
加上可继承的 Low 标签(`S:(ML;OICI;NW;;;LW)`),并在输出里提示一次;
记录写进 `sandbox-labels`。沙箱的临时目录是 `%TEMP%\cst-agent-sandbox`(同样标为 Low),
子进程的 `TEMP` / `TMP` 指向这里。
- 不会给盘符根目录、用户目录本身、`%APPDATA%`、`%LOCALAPPDATA%`、`%TEMP%` 本身,
以及 Windows、Program Files、ProgramData 下面的目录打标签:在这些地方启动时,命令不会运行,
界面会问是否在沙箱外重跑。请在项目目录里启动。
- `/sandbox` 列出打过标签的目录;`/sandbox reset-labels` 恢复它们原来的标签。
- 沙箱里可以读、执行用户能访问的文件(凭据文件除外),**不限制联网**。所以像联网的命令
(`curl`、`wget`、`ssh`、`git clone/fetch/pull/push`、`npm install`、`pip install`、
`winget install`、`Invoke-WebRequest` 等)在 `auto` 模式下仍然会弹窗确认。
- 命令像是被拦了(`Access is denied`、`拒绝访问`、`Permission denied` 等)时,会问
“Rerun outside the sandbox?”:`y` 在沙箱外重跑一次,`p` 保存命令前缀规则并重跑,`n` 保留结果。
- MSYS2 / Cygwin 的程序(包括 Git for Windows 自带的 `usr\bin` 工具)在 Low 级别下无法初始化
(`0xc0000142`),同样会触发上面的重跑询问。Git for Windows 的 `git.exe` 本身不受影响。
- `CST_SANDBOX=off` 关闭沙箱(`auto` 退回只读白名单规则);`CST_SANDBOX=lowil` 只用 Low IL。
它防的是误操作写坏工作区以外的文件,不是对抗恶意程序的安全边界。
## 从源码构建
两种方式产物一样:`dist/windows-x86_64/` 和 `dist/cst-agent-VERSION-windows-x86_64.zip`。
第三方依赖(curl、ncurses、busybox-w32)都按固定版本从源码编译、静态链接。
### 在 Linux 上交叉编译
```bash
git clone https://git.whcself.xyz/WHC/CST-agent.git
cd CST-agent
scripts/bootstrap_windows.sh
```
NixOS / 有 Nix 时自动进 `shell-win.nix`(`pkgsCross.ucrt64`);否则需要 UCRT 版的
`x86_64-w64-mingw32-gcc`(带 winpthreads)、cmake、ninja、git、perl。
### 在 Windows 上用 MSYS2 原生编译
装好 [MSYS2](https://www.msys2.org/) 后,打开 **MSYS2 UCRT64** 终端(不是 MINGW64:
MINGW64 链接 msvcrt,UTF-8 清单不起作用):
```bash
pacman -S --needed git
git clone https://git.whcself.xyz/WHC/CST-agent.git
cd CST-agent
scripts/bootstrap_msys2.sh
```
脚本会用 pacman 装 UCRT64 的 gcc / cmake / ninja,编译依赖和 `cst-agent.exe`,跑 ctest
(`CST_SKIP_TESTS=1` 跳过),再打包。
### 测试
`scripts/win_test.sh` 在本机 QEMU 里的 Windows Server 虚拟机(英文 / 中文系统,管理员 /
普通用户 / 中文用户名)上交叉编译后跑全部测试;虚拟机的创建和控制见 `scripts/winvm/`。
### 发布
```bash
GITEA_TOKEN=... scripts/release_windows.sh --build
```
创建(或复用)`vVERSION` Release,上传 zip 和 `.sha256`。token 只从环境变量读取,经 stdin
交给 curl,不会出现在命令行参数、磁盘或输出里。
## 已知限制
- 英文等非中文系统的传统控制台默认用 Consolas,它没有中文字形,中文会显示成方框(列宽仍然正确)。
用 Windows Terminal,或在控制台“属性 → 字体”里选新宋体等中文字体即可。
- 传统控制台里输入表情符号(BMP 以外的字符)可能显示不对;中文输入没问题。
- 通过 SSH / ConPTY 远程运行时,鼠标事件不会转发过来,键盘操作不受影响。
- 很大的工作区第一次打标签要等一会儿(标签要继承到每个文件)。
- 只有 x86_64 发行包。