# 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/`。 ### 发布 CI:推 `main` 或 `v*` tag 且 `windows-cross` 成功后,自动把 zip / `.sha256` 发到 Gitea Release `vVERSION`(版本来自 `include/cst_version.h`;同名资源替换)。仓库 Secrets 可设 `RELEASE_TOKEN`(`write:repository`),没有则用 Actions 自带 token。 本地: ```bash GITEA_TOKEN=... scripts/release_windows.sh --build ``` 创建(或复用)`vVERSION` Release,上传 zip 和 `.sha256`。token 只从环境变量读取,经 stdin 交给 curl,不会出现在命令行参数、磁盘或输出里。发版前先 bump `cst_version.h`;推 `vX.Y.Z` tag 时必须与头文件一致。 ## 已知限制 - 英文等非中文系统的传统控制台默认用 Consolas,它没有中文字形,中文会显示成方框(列宽仍然正确)。 用 Windows Terminal,或在控制台“属性 → 字体”里选新宋体等中文字体即可。 - 传统控制台里输入表情符号(BMP 以外的字符)可能显示不对;中文输入没问题。 - 通过 SSH / ConPTY 远程运行时,鼠标事件不会转发过来,键盘操作不受影响。 - 很大的工作区第一次打标签要等一会儿(标签要继承到每个文件)。 - 只有 x86_64 发行包。