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
178 lines
8.4 KiB
Markdown
178 lines
8.4 KiB
Markdown
# 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 发行包。
|