OX
OPEN-OX

// docs / architecture

系统架构

基于 Next.js 16 App Router 的全栈 AI 流水线。无需独立后端 — API Routes、AI 编排和前端全部在同一个仓库中。

系统概览

Open-OX Studio 由三个主要层次构成:Next.js 前端(SSR + 客户端状态)、 AI 流水线(服务端编排)、以及外部服务(Supabase、E2B、LLM API)。

浏览器
  └── /studio/[projectId]   ← React 客户端,SSE 消费者
        │
        ├── POST /api/projects      → 创建 DB 记录,返回 projectId
        ├── POST /api/ai            → 启动生成流(SSE)
        ├── POST /api/.../modify    → 启动修改流(SSE)
        └── POST /api/.../preview   → 启动/刷新预览(后端随 OPEN_OX_PREVIEW_BACKEND 分支)

服务端(Next.js API Routes)
  ├── AI 流水线(generate_project / modify_project)
  ├── Supabase(projects 表 + project-files / site-previews Storage)
  └── 预览:OPEN_OX_PREVIEW_BACKEND env → local | storage | e2b
projectId 在 AI 流水线启动之前就已创建。用户可以在生成过程中关闭浏览器, 重新进入时通过 DB 中的增量 buildSteps 恢复进度。

技术栈

层次技术选型理由
框架Next.js 16 App RouterSSR + API Routes 合一,无需独立后端
语言TypeScript 严格模式AI 生成代码的类型安全保障
样式Tailwind CSS v4 + shadcn/uiCSS 变量驱动主题,AI 可直接操作
数据库Supabase (PostgreSQL)托管 Postgres + Storage + 实时订阅
沙箱 / 预览local · Storage · E2B预览后端可选:本地 dev、静态导出+代理、或云端沙箱
LLMOpenAI-compatible API可切换 Gemini / GPT / 任意提供商

为什么用原生 fetch 而非 OpenAI SDK

OpenAI SDK 内部使用 agentkeepalive,默认 socket timeout 为 8 秒。 单次 section 生成调用可达 60 秒,SDK 会强制断连。 原生 fetch 配合 AbortSignal.timeout(300_000) 覆盖所有场景。

const res = await fetch(`${baseURL}/chat/completions`, {
  method: "POST",
  body: JSON.stringify({ model, messages, tools }),
  signal: AbortSignal.timeout(300_000), // 5 min
});

请求流程

从用户输入到上线预览的完整生命周期:

1. 用户输入 prompt → 点击 Build
2. POST /api/projects  → 创建 DB 记录(status=generating)
3. 服务端立即返回 projectId(< 100ms)
4. 浏览器跳转到 /studio/{projectId}
5. 页面检测 status=generating 且 buildSteps 为空
6. 自动触发 POST /api/ai,传入 projectId
7. 服务端运行 AI 流水线,每个步骤完成后:
   a. SSE 事件推送到浏览器(实时显示)
   b. 写入 Supabase(支持断线恢复)
8. status → ready / failed
如果用户在生成过程中关闭标签页,重新打开 /studio/[id] 会启动 3 秒轮询循环,并显示 DB 中已完成的步骤。

API 路由

POST/api/projects创建项目记录,返回 projectId
GET/api/projects项目列表(需登录)。默认返回全员项目;?mine=1 或 folder=uncategorized|… 时仅当前用户并按文件夹筛选
GET/api/projects/[id]按 ID 获取项目(用于轮询)
PATCH/api/projects/[id]重命名、移动文件夹等(仅所有者)
DELETE/api/projects/[id]删除项目及文件(仅所有者)
POST/api/ai启动生成流水线(SSE 流)
POST/api/projects/[id]/modify启动修改 Agent(SSE 流)
POST/api/projects/[id]/preview启动或刷新预览(local/storage/e2b 由环境决定;storage 模式下访客可取得静态 URL)
PUT/api/projects/[id]/preview修改后重建预览
GET/api/models获取可用 LLM 模型列表
GET/api/skills获取可用风格技能列表
RLS:已登录用户可 SELECT 全部 projects 行(便于项目广场按成员浏览);INSERT / UPDATE / DELETE 仍限制为资源所有者。

输入触发器系统

HeroPrompt 输入框支持多种触发器,在文本任意位置通过特殊字符激活。 选中后以彩色 chip 形式注入,提交时各 chip 的 payload 合并到请求体。

触发符功能提交字段
/风格模板选择(如 /glassmorphism)styleGuide
@引用已有项目作为设计参考referenceProjectId
#约束标签(#暗色主题 #极简 #中文)prompt 追加
URL粘贴 URL 自动提取为参考referenceUrl
图片粘贴截图作为视觉参考imageBase64

架构

app/hooks/usePromptTriggers.ts   — 统一触发器 hook(检测 / @ # + 光标位置)
app/components/ui/TriggerMenu.tsx — 浮层下拉菜单(按类型显示不同颜色前缀)
app/components/ui/PromptChips.tsx — 注入的标签展示(含图片缩略图)
app/components/ui/QuickTemplates.tsx — 快捷模板 pills

触发检测基于光标位置:从光标往前搜索最近的触发字符, 触发字符必须在行首或空格后,且到光标之间不含空格。 这允许用户在文本中间任意位置触发菜单。

Modify Agent

生成后的迭代修改由 Modify Agent 处理 — 一个受 Claude Code 启发的开放式 Agent 循环。 Agent 在单次循环中完成搜索、阅读、编辑和验证。

工具列表

read_filesearch_codelist_diredit_filewrite_filerun_buildexec_shellthinkrevert_file

4-Phase 工作流

Phase 1: ORIENT  — search_code + list_dir,建立全局理解
Phase 2: READ    — 只读 1-2 个最相关文件,形成修改计划
Phase 3: EDIT    — edit_file 精确替换,最小改动
Phase 4: VERIFY  — run_build 验证编译

安全机制

Must read before edit — edit_file 前必须先 read_file,防止盲改。Loop Detection — 连续 4 次操作同一文件时注入策略转换提示。Tool Result Budget — 单条结果上限 30K 字符。Context 压缩 — 基于相关性,热文件保留完整,冷文件压缩。

数据持久化

projects 表

字段类型说明
idtext PK{timestamp}_{slug} — URL 可读,全局唯一
user_iduuid FK所属用户(auth.users)
owner_usernametext创建时写入的展示名,用于全员列表按成员分组
folder_iduuid FK?单层文件夹(project_folders),可空
statusenumgenerating / ready / failed
blueprintjsonbanalyze 步骤输出的完整 ProjectBlueprint
build_stepsjsonb[]增量写入 — 每步完成后立即持久化
modification_historyjsonb[]每次修改的完整记录(含 diff)
sandbox_idtextE2B 沙箱 ID(用于重连)
verification_statusenumpassed / failed(next build 结果)

源码持久化在 Storage 桶 project-files;静态预览产物在 site-previews(由 /site-previews/… 代理访问)。 本地丢失时从 project-files 恢复到 sites/ 后再构建预览。

关键工程决策

projectId 在 AI 启动前创建

支持断线恢复、可分享 URL、以及无需重新输入 prompt 的重试。

buildSteps 增量持久化

每个步骤完成后立即写入 DB。用户中途关闭页面后重新进入,看到的是真实进度而非空白。

Blueprint normalize 层

asProjectBlueprint() 对每个字段做 normalize 并提供 fallback。LLM 输出不一致时不会导致流水线崩溃。

静态预览默认走 Storage(本地开发)

配置 Service Role 与 NEXT_PUBLIC_SITE_URL 且未指定 OPEN_OX_PREVIEW_BACKEND 时,本地默认与生产一致使用静态导出 + 代理,避免 Dev Server 与 CSP 差异。