文件 I/O
概述
wesgine 的文件 I/O 系统采用三域模型:ArtifactDir(持久产出)、ScratchDir(临时计算)和 HostPaths(宿主路径)。引擎严格管控文件写入边界,确保 Agent 的文件操作在安全范围内进行。
三域模型
┌─────────────────────────────────────────────┐
│ Cell 数据目录 │
│ ├── workspace/{actor}/ ← ArtifactDir │
│ │ └── {agentID}/ (持久产出) │
│ └── .scratch/{runID}/ ← ScratchDir │
│ (临时计算) │
├─────────────────────────────────────────────┤
│ 宿主文件系统 │
│ └── /home/user/project/ ← HostPaths │
│ (用户工作区) │
└─────────────────────────────────────────────┘
ArtifactDir(持久产出)
Agent 执行产生的持久化文件存储在此目录。路径由引擎自动推算:
{CellDataDir}/workspace/{Actor}/{AgentID}/
- 由引擎控制,不从外部传入
- 物理在 Cell 目录下,满足 Cell 隔离和 Export 可移植
- 不出现在系统提示词的"项目"列表中
ScratchDir(临时计算)
Run 执行过程中的临时文件存储在此目录:
{CellDataDir}/.scratch/{RunID}/
- Run 结束后由引擎自动 GC(
os.RemoveAll) - 不包含在 Cell Export 中
- 用于中间计算结果、临时数据处理等
HostPaths(宿主路径)
用户显式授权 Agent 访问的宿主文件系统路径:
- 引擎只验证边界:确认路径在 AllowPaths 范围内
- 引擎不管理:不创建目录(MkdirAll)、不修改权限(Chmod)、不垃圾回收、不包含在 Export 中
PrimaryRoot(主工作上下文)
PrimaryRoot 是 Agent 认知的"主工作上下文"——出现在系统提示词中标记为 active project 的路径。
声明方式:通过 CellSpec.AgentDefaults.Workspace.PrimaryRoot 声明。
Fallback 链:
- 显式声明的 PrimaryRoot
AllowPaths[0](第一个允许路径)- ArtifactDir
PrimaryRoot 必须在 AllowPaths ∪ {ArtifactDir} 范围内。
exec CWD 优先级
Agent 执行命令时的工作目录按以下优先级确定:
- 显式
cwd参数(工具调用时指定) - PrimaryRoot(Agent 主工作上下文)
- ScratchDir
- ArtifactDir
编程场景下 PrimaryRoot 通常是 VS Code 项目根,go build ./... 等命令在项目根执行。
路径安全
写入边界:write / edit / apply_patch 输出必须落入 ArtifactDir 或 HostPaths。禁止写入 /tmp、Scratch、或任何 Cell 外路径。
边界判定:由 internal/pathaccess 包统一判定,基于 DenyPaths(黑名单)和 EnginePaths(引擎保留路径)。
Workspace Handle
Cell 提供 Workspace Handle,与 Memory Handle 对等,提供文件操作 API:
GET /cells/{id}/workspace/files # 文件列表(?actor=&path=&depth=)
GET /cells/{id}/workspace/file # 下载文件(?actor=&path=)
POST /cells/{id}/workspace/upload # 上传文件(?actor=&path=,raw body)
DELETE /cells/{id}/workspace/file # 删除文件(?actor=&path=)
GET /cells/{id}/workspace/stats # 使用统计(?actor=)
POST /cells/{id}/workspace/gc # 触发 GC
DELETE /cells/{id}/workspace/delete-by-prefix # 按前缀批量删除
Cell Export
Cell Export 时的文件包含规则:
| 目录 | 默认行为 | 可配置 |
|---|---|---|
workspace/ | ✅ 包含 | ExportOpts{SkipWorkspace: true} 可排除 |
.scratch/ | ❌ 永不包含 | 不可配置 |
| HostPaths | ❌ 不包含 | 不可配置(不属于 Cell) |
使用示例
// Agent 写入文件到 ArtifactDir(由引擎自动推算路径)
// write(path="report.md", content="...")
// → 实际写入 {CellDataDir}/workspace/alice/agent-legal/report.md
// Agent 读取 HostPaths 中的项目文件
// read(path="/home/user/project/main.go")
// → 引擎验证路径在 AllowPaths 内后允许读取
// Agent 使用 ScratchDir 做临时计算
// write(path=".scratch/{runID}/temp.json", content="...")
// → Run 结束后自动清理
设计原则
- ArtifactDir 归引擎管:路径推算、创建、GC、Export 都由引擎负责
- HostPaths 归用户管:引擎只做边界验证,不做任何管理操作
- ScratchDir 是临时的:Run 级别生命周期,结束即清理
- 安全第一:所有写入路径必须在允许范围内,越界操作被拒绝