Files
Genarrative/docs/technical/【技术方案】浏览器内AIWeb工程沙箱预览方案-2026-06-13.md
kdletters b4746c24b5 补充AIWeb智能体落地方案
明确 /editor/agent 智能体作为工程改动编排器,通过结构化 patch、校验、snapshot、构建和预览反馈闭环落地。

补充左侧聊天、中间预览、右侧 IDE 的页面布局约束,右侧展开文件内容后隐藏聊天栏。

同步验收清单,明确 MVP 不做 diff 视图并覆盖 agent turn 和布局验收。
2026-06-14 19:34:44 +08:00

13 KiB
Raw Permalink Blame History

浏览器内 AI Web 工程沙箱预览方案

更新时间:2026-06-13

背景

/editor/agent 需要承载一个类似 IDE 的 AI Web 工程编辑器:用户在浏览器里看到文件树、代码编辑、AI 指令输入、构建日志和实时预览,AI 生成的是一个完整 Web 工程。这个工程的构建、依赖安装和运行必须与 Genarrative 主站、当前仓库源码目录、平台密钥和正式业务数据隔离。

第一版不追求“浏览器里完整云 IDE + 任意 npm + HMR + 后端服务”。目标是先跑通一个安全、可恢复、可验收的静态 SPA 预览闭环。

结论

MVP 采用四层结构:

平台编辑器壳 /editor/agent
  -> api-server 控制面
  -> 独立 web-project-runner worker
  -> 独立 preview origin / preview gateway

第一版只支持固定 React / Vite / TypeScript 静态模板、虚拟文件系统、结构化 AI patch、平台固定构建命令、独立 runner 静态构建和独立域 iframe 预览。

MVP 明确不做:

  • 终端 shell。
  • 任意后端服务。
  • 任意端口代理。
  • HMR / 长驻 dev server。
  • 任意 npm 依赖安装。
  • AI 自定义 build shell script。
  • diff 视图。
  • 与主站同源的预览 iframe。
  • 将 AI 生成工程写入当前 Genarrative 仓库源码目录。

分层职责

平台编辑器壳

入口路由固定为 /editor/agent。这一层只负责前端体验:

  • 左侧聊天、中间预览、右侧 IDE 的水平三分布局。
  • AI 指令输入、构建日志、当前项目版本和预览 iframe。
  • 右侧 IDE 默认只显示文件树;展开后显示当前文件内容,并隐藏左侧聊天栏。
  • 保存用户编辑和 AI patch。
  • 订阅构建 job SSE 状态。
  • 在构建成功后切换 iframe 的 previewUrl
  • 构建失败时保留上一版可用预览。

平台编辑器壳不得直接执行用户工程代码,不持有 runner 临时工作区路径,不把平台 access token、用户 cookie、SpacetimeDB 连接信息或 OSS 写权限暴露给预览页。

如果后续接入现有创作链路,入口仍应走 play_flow 主干和 shared-contracts DTO,不在前端壳或 app.rs 中新建平行业务流程。

智能体编排器

/editor/agent 的智能体不是普通聊天页,也不是直接生成整包代码的黑盒。它是“工程改动编排器”,负责把用户意图转成可审计、可校验、可回滚的 Web 工程 patch。

智能体职责:

  • 理解用户自然语言目标,并结合当前 snapshot、文件树、选中文件和最近构建结果形成任务上下文。
  • 输出结构化 patch plan,而不是直接写真实目录或执行 shell。
  • 将 patch plan 提交给 api-server 校验,校验通过后生成新 snapshot。
  • 创建 preview build job,并订阅 job SSE。
  • 读取构建日志、错误摘要和 preview 状态,失败时继续生成修复 patch,成功时推动预览切换。
  • 保留每轮 agent turn 的用户输入、上下文摘要、patch 摘要、校验结果、jobId 和最终状态,便于刷新恢复和审计。

智能体最小闭环:

用户在左侧聊天输入需求
  -> 前端提交 agent turn
  -> api-server 读取当前 snapshot 和允许暴露的上下文
  -> LLM 返回结构化 patch plan
  -> api-server 校验 patch plan
  -> 校验通过后生成新 snapshot
  -> 创建 preview build job
  -> runner 构建
  -> SSE 回传 queued / running / log / succeeded / failed
  -> 成功时中间预览 iframe reload
  -> 失败时智能体基于错误摘要进入下一轮修复

智能体输出只允许以下 patch 操作:

  • create_file
  • update_file
  • delete_file
  • rename_file
  • package_manifest_request

package_manifest_request 只是依赖请求,不是事实源。MVP 中 api-server 必须拒绝或忽略任意新增依赖、生命周期脚本、私有 registry、git: / file: / http: 依赖和 AI 自定义构建命令。

智能体不得:

  • 直接写入当前 Genarrative 仓库源码目录。
  • 直接访问 runner 临时工作区。
  • 直接执行 shell、npm script 或任意构建命令。
  • 直接拿平台 access token、用户 cookie、SpacetimeDB 连接、OSS 写权限或 LLM provider 密钥。
  • 绕过 api-server 的路径、依赖、大小、敏感文件和 snapshot 校验。

页面布局

/editor/agent MVP 使用水平三分布局,不做 diff 视图:

┌───────────────┬──────────────────────────────┬────────────────┐
│ 左侧聊天      │ 中间预览                     │ 右侧 IDE       │
│ Agent 对话    │ sandbox iframe + 状态日志    │ 默认文件树     │
└───────────────┴──────────────────────────────┴────────────────┘

布局规则:

  • 左侧聊天承载用户输入、智能体回复、构建状态摘要和失败修复建议。
  • 中间预览始终是主工作区,展示当前 active preview iframe;构建失败时保留上一版 succeeded preview,并在聊天或日志区域展示失败摘要。
  • 右侧 IDE 默认只显示文件树,突出当前工程结构,不默认展示代码内容。
  • 用户展开右侧 IDE 后,右侧显示文件树和当前文件内容,左侧聊天栏隐藏,中间预览与右侧 IDE 形成双栏工作模式。
  • 用户收起右侧文件内容后,恢复左侧聊天 + 中间预览 + 右侧文件树三栏。
  • 文件内容查看用于理解和轻量编辑当前文件,不提供 diff 视图;版本变化通过 agent turn 摘要、snapshot 时间线和构建状态表达。
  • 移动端优先保持预览和聊天可用,右侧 IDE 通过抽屉或分段入口进入;展开文件内容时同样隐藏聊天。

api-server 控制面

控制面只管理权限、快照、任务和状态,不执行 AI 工程代码:

  • 鉴权和项目归属校验。
  • 校验 AI patch 和用户编辑。
  • 保存虚拟文件系统 snapshot。
  • 创建 preview build job。
  • 给 runner 发放最小任务能力。
  • 输出构建日志和状态 SSE。
  • 签发短期 preview URL。
  • 将业务状态通过受控 procedure 或 BFF 更新到正式数据层。

api-server 不把 SpacetimeDB、OSS 写权限、LLM provider、支付、用户 cookie 或平台内部 token 传给 runner。runner 需要读取资产时,只拿只读短期签名 URL 或受控 fixture。

web-project-runner worker

新增独立进程角色,例如 web-project-runner。它可以复用外部生成 worker 的“任务表 + lease + controller + worker”模式,但不应把 Web 工程执行塞进 external_generation_job,避免语义污染。更合适的落点是新增 web_project_runtime_job 或抽象出通用 job 模块。

runner 只做执行面:

  • 拉取指定 snapshot。
  • 展开到独立临时工作区或容器。
  • 使用平台白名单模板依赖。
  • 执行平台固定构建命令。
  • 采集构建日志、资源用量和结果。
  • 上传静态 artifact。

runner 不能反向写平台业务表。业务状态回写必须经过 api-server / SpacetimeDB 的受控入口。

preview gateway 与独立预览域

预览页使用独立 origin,例如:

https://preview-<token>.sandbox.genarrative.world

或者统一域名加不可枚举 token path:

https://sandbox.genarrative.world/p/<previewToken>/

预览域不得与主站同源,不带平台 cookie,不共享主站 localStorage / sessionStorage。主站只通过 sandbox iframe 嵌入预览。

MVP 只服务静态构建产物。HMR、WebSocket 代理和长驻 dev server 后置到单独阶段评审。

MVP 流程

用户在 /editor/agent 输入需求或编辑文件
  -> AI 返回结构化 patch
  -> api-server 校验 patch
  -> 生成 workspace snapshot
  -> 前端 debounce 后创建 preview build job
  -> runner claim job 并构建静态 dist
  -> artifact 上传 artifact store
  -> preview gateway 只读服务 artifact
  -> 前端 SSE 收到 succeeded 后 iframe reload

失败链路:

构建失败 / 超时 / runner 崩溃
  -> job failed / expired
  -> 前端展示错误日志摘要
  -> active preview 保持上一版 succeeded artifact

接口草案

接口归属分成项目控制面和运行时控制面。

POST   /api/creation/web-project/projects
GET    /api/creation/web-project/projects/{projectId}/snapshot
PATCH  /api/creation/web-project/projects/{projectId}/files
POST   /api/creation/web-project/projects/{projectId}/agent-turns
POST   /api/runtime/web-project/projects/{projectId}/preview-builds
GET    /api/runtime/web-project/preview-builds/{jobId}
GET    /api/runtime/web-project/preview-builds/{jobId}/events

/events 复用现有 src/services/sseStream.ts 的 SSE 传输层口径。事件类型建议包括:

  • queued
  • running
  • log
  • succeeded
  • failed
  • cancelled
  • expired
  • stale

前端刷新恢复时,先读取项目 active snapshot 和 active preview,再按未终态 job 继续订阅 SSE。

agent-turns 的请求建议包含:

  • projectId
  • baseSnapshotId
  • message
  • selectedFilePath
  • visibleFilePaths
  • recentBuildJobId

agent-turns 的响应建议包含:

  • turnId
  • status
  • assistantMessage
  • patchSummary
  • validationErrors[]
  • snapshotId
  • buildJobId

当 patch 校验失败时,不生成 snapshot,不创建 build job,只返回可展示的校验错误和智能体修正建议。

虚拟文件系统

平台内的“文件系统”是虚拟工作区,不是真实目录长期挂载。

snapshot manifest 建议包含:

  • projectId
  • snapshotId
  • parentSnapshotId
  • ownerUserId
  • templateKey
  • files[]
  • createdAt
  • createdBy
  • patchSummary

文件项建议包含:

  • path
  • contentDigest
  • sizeBytes
  • mediaType
  • encoding
  • executable=false

路径必须 fail-closed

  • 只允许相对路径。
  • 拒绝绝对路径。
  • 拒绝 ..
  • 拒绝符号链接。
  • 拒绝超深目录。
  • 拒绝超大文件。
  • 拒绝隐藏敏感文件名,例如 .env.npmrc.ssh.git
  • MVP 只支持文本源码和少量静态资源。

文件内容小文本可以按 digest 存对象;大一点的 snapshot 可打包成 tar / zip artifact 放受控 artifact store。图片、音频等大资产继续走现有资产链路,不让 AI 工程随意内嵌大 Data URL。

依赖和构建

MVP 只支持平台预置模板依赖:

  • React
  • Vite
  • TypeScript
  • 平台已审核的 UI / 工具依赖子集

package.json 在 MVP 中不是事实源。AI 可以提出 manifest patch,但 api-server 会重写或忽略危险字段。构建命令由平台固定,例如:

npm ci --ignore-scripts
npm exec vite build

第一版应禁止:

  • preinstall / install / postinstall
  • git: / file: / http: 依赖。
  • 私有 registry。
  • native build。
  • 二进制下载型包。
  • AI 自定义 shell script。

后续若要开放依赖,必须进入“受控依赖白名单”和“隔离依赖解析服务”阶段,不混入 MVP。

预览状态机

draft snapshot
  -> build queued
  -> build running
  -> build succeeded
  -> build failed
  -> build cancelled
  -> build expired
  -> build stale

状态规则:

  • 新 snapshot 触发新 build 时,旧 running build 应取消或标记 stale。
  • 只有当前 active snapshot 的 succeeded job 可以成为 active preview。
  • failed / cancelled / expired / stale 不能覆盖 active preview。
  • 回滚是切回历史 snapshot 并复用对应 immutable artifact,或重新构建该 snapshot。
  • 不允许复用 runner 临时目录作为回滚来源。

后续阶段

Phase 0:文档和威胁模型

补齐技术方案、威胁模型和验收清单,明确 MVP 不可做能力、安全门禁、状态机和 QA 口径。

Phase 1:静态模板预览纵切

完成 /editor/agent 编辑器壳、固定模板、虚拟文件系统、AI patch 保存、runner 静态构建、artifact 服务和 iframe reload。

Phase 2:持久任务和恢复

引入 web_project_runtime_job,按 lease / controller / worker 模式实现任务队列、取消、stale、刷新恢复和日志 SSE。

Phase 3:受控依赖安装

支持白名单依赖、lockfile 固化、依赖层缓存、安装失败可读错误、依赖封禁和审计。

Phase 4:实时体验增强

在安全评审后再做长驻 dev server、HMR、WebSocket 代理、端口租约和空闲回收。

Phase 5:作品化发布

将通过安全门禁的 Web project 接入平台作品类型。发布必须重新构建 immutable artifact,不直接提升临时预览 artifact。

与现有系统的关系

  • 前端 SSE 读取复用 src/services/sseStream.ts
  • 后端 job 模式参考外部生成 worker 的 lease / controller 经验,但使用新的 Web 工程 runtime 语义。
  • /editor/agent 是第一版用户入口,不新增重复 IDE 页面。
  • 业务真相仍通过 server-rs + SpacetimeDB 受控写入,前端和 runner 都不能绕过控制面。