Workspace 管理

Cell 内的文件产出管理,与 Memory 对等的 Handle,涵盖三域模型、API 与路径安全。


Workspace 概念

Workspace 是 Cell 内的文件产出管理系统(INV-IO-05),与 cell.Memory() 对等:

cell.Workspace()  // List / Download / Upload / Delete / Stats / GC
cell.Memory()     // List / Save / Search / Delete / Counts / GC

每个 Cell 拥有独立的 Workspace 目录,物理隔离在 Cell 数据目录下。


三域模型

wesgine 的文件 I/O 分为三个域:

ArtifactDir — 持久产出

{CellDataDir}/workspace/{actor}/
特性说明
计算方式由引擎从 (CellDataDir, Actor, AgentID) 推算
外部传入❌ 不从 AppRunRequest 传入(INV-IO-01)
物理位置Cell 目录下(INV-IO-04)
满足AX-1 隔离 + Export 可移植
系统提示词不出现在"项目"列表中

ScratchDir — 临时计算

{CellDataDir}/.scratch/{runID}/
特性说明
生命周期Run 结束后由引擎 GC(os.RemoveAll)(INV-IO-06)
Export永不包含(INV-IO-08)
用途中间计算结果、临时文件

HostPaths — 宿主路径

由 CellSpec.AllowPaths 声明
特性说明
引擎行为只验证边界(INV-IO-07)
不做MkdirAll、Chmod、GC、Export
用途宿主机的工作目录、项目路径

PrimaryRoot — 主工作上下文

PrimaryRoot 是 Agent 认知的"主工作上下文"——出现在系统提示词标为 active project。

Fallback 链

显式声明 (CellSpec.AgentDefaults.Workspace.PrimaryRoot)
  ↓ 无
AllowPaths[0]
  ↓ 无
ArtifactDir

约束

PrimaryRoot 必须在 AllowPaths ∪ {ArtifactDir} 内。

spec := wesgine.CellSpec{
    AgentDefaults: wesgine.AgentDefaults{
        Workspace: wesgine.WorkspaceDefaults{
            PrimaryRoot: "/home/user/projects/myapp",
        },
    },
    AllowPaths: []string{
        "/home/user/projects/myapp",
        "/home/user/documents",
    },
}

与 Exec CWD 的关系

Exec CWD 优先级(INV-IO-03):

显式 cwd 参数 > PrimaryRoot > ScratchDir > ArtifactDir

编程场景下 PrimaryRoot = VS Code 项目根,go build ./... 等命令在项目根执行。


Workspace API

方法路径说明
GET/workspace/files文件列表
GET/workspace/file下载文件
POST/workspace/upload上传文件
DELETE/workspace/file删除文件
GET/workspace/stats使用统计
POST/workspace/gc触发 GC
DELETE/workspace/delete-by-prefix按前缀批量删除

查询参数

端点参数说明
/workspace/files?actor=&path=&depth=Actor、路径、深度过滤
/workspace/file?actor=&path=指定 Actor 和路径
/workspace/upload?actor=&path=指定上传位置
/workspace/stats?actor=按 Actor 统计
/workspace/delete-by-prefix?actor=&prefix=按前缀批量删除

SDK 调用

// 列出文件
files, err := cell.Workspace().List(ctx, workspace.ListRequest{
    Actor: "alice",
    Path:  "reports/",
    Depth: 2,
})

// 下载
reader, err := cell.Workspace().Download(ctx, "alice", "reports/weekly.pdf")

// 上传
err := cell.Workspace().Upload(ctx, "alice", "reports/daily.md", bodyReader)

// 删除
err := cell.Workspace().Delete(ctx, "alice", "reports/old.pdf")

// 统计
stats, err := cell.Workspace().Stats(ctx, "alice")

// GC
err := cell.Workspace().GC(ctx)

// 批量删除
err := cell.Workspace().DeleteByPrefix(ctx, "alice", "temp/")

Cell Export

Workspace 在 Cell 导出中的行为:

内容默认可配置
workspace/✅ 包含ExportOpts{SkipWorkspace: true} 可排除
.scratch/❌ 永不包含无选项(INV-IO-08)
// 导出(包含 workspace)
reader, err := hyp.Cells().Export(ctx, "dept-legal")

// 导出(排除 workspace)
reader, err := hyp.Cells().Export(ctx, "dept-legal", wesgine.ExportOpts{
    SkipWorkspace: true,
})

路径安全

写入路径约束(INV-IO-02)

write / edit / apply_patch 输出必须落入 ArtifactDir 或 HostPaths。

路径允许?
ArtifactDir 下✅
HostPaths(AllowPaths)下✅
/tmp❌ 禁止
ScratchDir❌ 禁止(write 不应写临时域)
Cell 外路径❌ 禁止

HostPaths 边界(INV-IO-07)

引擎对 HostPaths 的态度是只验边界:

操作是否做
验证路径在 AllowPaths 内✅
MkdirAll❌
Chmod❌
GC❌
Export❌

HostPaths 是宿主机的目录,引擎不管理其生命周期。


目录结构示例

cells/dept-legal/
├── workspace/
│   ├── alice/
│   │   ├── reports/
│   │   │   ├── weekly-2026-09-01.pdf
│   │   │   └── monthly-2026-08.docx
│   │   └── notes/
│   │       └── meeting.md
│   └── bob/
│       └── drafts/
│           └── contract-v2.md
├── .scratch/
│   └── run-abc123/   ← Run 结束后 GC
│       └── temp.json
├── meta.db
├── sessions.db
└── state.db

与 Knowledge 的关系

Workspace 和 Knowledge 是互补的文件管理机制:

特性WorkspaceKnowledge
定位Agent 产出文件知识源文件
操作上传/下载/删除导入/索引/搜索
向量化❌✅(Embedding + 搜索)
按 Actor 隔离✅❌(Cell 级共享)

最佳实践

  1. 不要手动操作 .scratch/:引擎自动管理临时文件
  2. PrimaryRoot 声明清晰:编程场景设为项目根目录
  3. Export 前考虑体积:大量产出文件时用 SkipWorkspace 减小导出体积
  4. 定期 GC:调用 /workspace/gc 清理过期产出
  5. 路径安全意识:Agent 的写入路径受 AllowPaths 约束