前端栈
Vite React shadcn 拆分源码;构建可输出 HTML/CSS/JS,Host 兼容待验
Owner 已拍板的目标架构(2026-11-07),脚手架尚未落地。 开发采用 Vite + React,共享组件统一使用 shadcn 的 Base UI 变体,组件与逻辑拆分维护;构建可输出分开的 HTML/CSS/JS,按需 chunk 或懒加载。单文件只是可选打包策略,并非已证 Host 硬限制。首轮只做独立 host-hello,不从视频编辑器抽壳。判断层与第二 App 见 Decisions 架构 与 OpenRouter Decisions 契约。ai-video-editor 是历史测试基线,不迁移、不维护,不列入后续 React 迁移目标。
约定与证据边界
Host 文档描述通过 iframe 的 srcdoc 加载 HTML,并在业务脚本前注入 window.frevana;页面不直接访问 Electron、preload 或 Node.js。共享发生在源码与构建期:每个 App 携带自身所需的构建资源,SkillPack 必须自包含,运行时不依赖 monorepo、软链接或开发机 node_modules。自包含不等于所有资源必须内联。
| 状态 | 依据与范围 |
|---|---|
| 原始约定 | 原始 AGENTS.md 将 app.html 约定为单文件 HTML,并要求在其中维护界面代码。这是原项目维护约定,不是已验证的 Host 加载能力上限;当前新方案改为拆分源码维护与构建产物集合交付,原始资料保留原样。 |
| Host 文档描述 | docs/app-html-host-api-architecture.md 描述 iframe.srcdoc、业务脚本前的 shim 注入及 app.getRootPath(): Promise<string>,背景也使用单文件 HTML 的说法。这是文档证据,本轮未读取 Host 实现或重做运行实验,不能据此断言外置资源被禁止。 |
| 已证实:仓库记录 | 系统架构与交付闭环记录文本基线、P0-02 和文件级 P0-03;历史单文件交付实验及回退仅在各自演练范围内成立。 |
| 此前内联推断:已纠正 | 此前由缺少静态服务或基址保证推导“默认全部内联、禁止 chunk”,证据不足。iframe 通常可以通过外置 link/script 加载资源,srcdoc 本身不推出禁止;这也不能反向证明当前 Host 已支持这些资源。媒体专用协议不能证明任意静态资源可用。 |
| 未验证 | workspace、共享包、构建资源与 React/Base UI 在真实 Host 中的兼容性均未落地验收;清单、Job、skills 加载与 U02/U07 的历史缺口仍保留。 |
| 未知 | 实际 sandbox/CSP、资源 URL 基址解析与静态服务兼容、模块和动态 import 支持、HTML 大小上限及跨机器安装升级协议;需读取实现或受控验证,不凭浏览器开发页推导。本轮不执行 Host 验证。 |
资料路径相对仓库外原始资料根 ../agent-app/agent-app/;它是设计依据,不是运行依赖。本文压缩方案原稿并按 Owner 新指示更新范围,不将原稿中的迁移建议视为待办。
目标源码与共享边界
| 目标路径 | 职责与依赖限制 |
|---|---|
根 package.json / package-lock.json | 私有 npm workspaces,纳入 packages/*、apps/*/web;根脚本驱动构建工具。 |
packages/ui/ | @frevana/ui:按需维护 shadcn Base UI 组件源码、tokens、样式与显式 exports;首轮只有 Button。不含 Job、鉴权、文件规则或 Host 操作,不依赖 SDK。 |
packages/host-sdk/ | @frevana/host-sdk:本仓消费者的类型与薄适配层,不依赖 React,不自称官方 SDK,不重做 IPC、不内置生产 mock。 |
apps/<id>/web/ | 独立包、index.html、Vite/TS 配置、src/;业务组件、结果 schema 与状态归 App。首轮新增目标为 apps/host-hello/web/。 |
tooling/app-build/ | 显式入口映射、公共配置、构建产物集合、资源清单检查和凭据;单文件打包仅为可选策略;不写本机运行目录。 |
.build/<app-id>/ | 将来加入忽略规则的临时输出,不作为交付目录。 |
apps/<id>/skillpack/ 内的 UI 产物与资源清单 | 构建型 App 的经审查 HTML/CSS/JS 等产物集合,随基线入库;手写 UI 的权威源为 web/,不手改产物。历史测试基线保持原样。 |
依赖方向为 App → ui / host-sdk;两个共享包互不依赖 App。shadcn 统一 Base UI,不混用 Radix 变体;components.json 别名与 exports 对齐,Vite 客户端设 rsc: false,Tailwind 扫描包含 ui 与 App,tokens 可由 App 覆盖。不预建 hooks/core 大包,第二个真实消费者出现后再抽象。
首轮采用 npm workspaces。根与子包均 private,内部依赖用与本地版本匹配的普通版本范围,由 npm 链接;不照抄 workspace:*,检查解析结果没有回落外部 registry。一个安装边界只有一个锁文件;锁定 Node/npm/工具版本,CI 用 npm ci。App 显式声明 React/ReactDOM,ui 使用 React peer 约束,检查只解析到一份兼容 React。docs-site 保持独立安装与现有锁文件,不纳入首轮 workspace。pnpm、Turbo、Nx、Lerna 均非本轮前提。
构建产物集合与资源清单交付契约
- 输出自包含。 构建可输出分开的 HTML、CSS、JS 和必要资产,资源清单列出入口、文件相对路径与引用关系。允许配套 assets,不依赖 CDN、localhost 或开发机路径。技能脚本、模型和外部运行时仍须另行声明、携带或提供可复现安装校验,前端自包含不代表技能已可运行。
- 按需拆包。 Vite 可以按需生成 chunk,使用动态 import / React.lazy 懒加载;不因 srcdoc 一概禁止。具体资源 URL、模块、CSS、Worker/WASM 等加载方式须分别核验当前 Host 的基址、静态服务、sandbox/CSP 兼容性。
base: './'也不能单独证明 Host 可加载。单文件插件或受控内联仅是可选打包策略,无须预设单文件组装工具;采用时仍需检查完整资源图与兼容性。 - 保留文档描述的注入顺序。 输出完整 doctype/head/body,业务脚本在挂载节点之后,为 Host 文档描述的 head 前部 shim 注入保留位置。保留必要的
FREVANA_APP_DIRECTIVE原始注释,内联时安全处理脚本闭合标签,不覆盖window.frevana,生产产物排除 dev mock;实际加载兼容仍待验。 - 检查最终产物集合。 检查 script src、stylesheet/modulepreload、CSS url/@import、JS import 和资源图,确保引用与清单一致,无漏带 chunk。对最终产物做浏览器 srcdoc 冒烟并观察资源请求、样式和懒加载路径;浏览器通过不等于当前 Host 支持。Host 兼容需另读实现或受控验证,不将“无资源请求”设为通用门槛。
- 可追溯、可复现。 凭据记录 App ID、源提交/脏工作树摘要、锁摘要、工具版本、每个产物的 SHA 与字节数及资源清单。同环境两次构建比较整个产物集合与清单,时间戳放凭据;source map 不交付,不带密钥或开发机路径。共享包变化按受影响 App 各自重建、审查与验收,不静默更新运行实例。
- 安全提升。 构建只写
.build/<id>/,不得将会清目录的 outDir 指向 SkillPack。通过检查后按审查过的资源清单逐文件提升 HTML/CSS/JS 等产物,备份并记录新增、替换与待删除旧资源;旧资源删除须单独审查,不整目录覆盖或镜像删除。普通 build 不自动交付。app:build/app:check/app:stage只是未来命令约定,当前不存在。
提升后的产物继续走限定文件交付:核对身份和漂移、逐文件备份与 SHA、清单白名单、Host 验收及按清单回退。data/、app-files/、artifacts、会话、缓存、身份与备份不覆盖、不镜像删除;视图回退不等于状态回退。registry 和本机映射职责不变,不获得新的加载或分发能力。
Host SDK 与 Vibe Editing 冲突
SDK 首轮只包装 window.frevana.app.getRootPath():运行时检测方法存在,保留接收者调用,校验返回非空字符串,缺能力或 reject 在页面明确展示。hello 是演示名称,不存在据此发明的 frevana.hello() API。开发 mock 必须显式标记且从生产排除,mock 成功不计入 Host 验收。
后续接口按已核对资料逐项补充,保留 files.read 对象返回值、取消 null、Promise reject;未知数据从 unknown 校验,业务 schema 留在 App。副作用需清理,隐藏/卸载停止轮询,写入或运行 Agent 由用户动作触发,避免 StrictMode 重复 effect 触发业务请求。持久化继续走 Host 项目级存储和 app-files,不打入 bundle。
暂停 Vibe Editing 仍有效,冲突未解决。 Agent 改写 HTML marker 会与 React 管理的 DOM、编译产物及下次构建冲突,不能自动反编译回 TSX。交付前发现目标 SHA 漂移必须停止审查。未来如重启编辑,需另验“固定视图消费结构化数据”或“React 不管理的独立编辑区”契约;若实际流程仍强制改写 bundle,该 App 暂不采用 React。仅写“请勿编辑”不能证明兼容。
以下情况否决交付:未经证据确认就宣称当前 Host 支持或禁止外置资源;运行时加载 CDN/localhost/开发机依赖;任意 marker 改写 bundle 或自动双向同步;整目录覆盖或覆盖状态;把构建成功、文本入库或缺模型的基线宣称为完整发布验收。
首轮 P0:独立 host-hello
实现阶段建立最小 workspace、两个共享包和 apps/host-hello/web。页面只含一个来自 @frevana/ui 的 Button 和状态区,点击经 SDK 调用 getRootPath,显示调用前、等待、成功及真实返回值、缺 Host、失败状态。不配置 Job,不借用 video-editor 配置或运行实例;如缺合适的隔离实例或创建流程,先核验合法入口,不发明清单字段。
| 门槛 | 必须留下的证据 |
|---|---|
| 安装与共享消费 | 干净检出 npm ci、类型检查与构建通过;实际导入两个共享包,依赖图确认 React/Base UI 打入产物。 |
| 产物集合与复现 | HTML/CSS/JS、配套资产与资源清单完整,两次构建逐文件 SHA 一致,记录实际体积;不虚构 Host 上限。 |
| 浏览器兼容 | 最终产物集合 srcdoc 冒烟,样式、点击、资源解析、按需 chunk/懒加载及错误分支按实际使用范围检查;只计浏览器证据。 |
| 真实 Host | 同一资源清单与逐文件 SHA 的产物在隔离本机实例打开,按钮取得真实运行根;记录 Host 版本、打开方式、实际 sandbox/CSP、URL 基址与资源加载证据,生产无 mock;当前均待验。 |
| 交付与回退 | 白名单覆盖构建产物集合与资源清单,逐文件核对摘要,恢复被替换文件并撤回本轮新增文件后重开;不整目录覆盖,状态抽检单独记录范围。 |
本次只写文档,不实现脚手架或执行 App 验收。 构建证明与真实 Host 通过分开登记,缺 Host 证据不能关闭完整 P0。不做 video-editor 迁移或维护,不碰其 Job/skills/状态;不做 HTML→TSX 回收、Host 改造、云端发布、跨机器安装升级、业务状态迁移或大型编排平台。P0 之后另选真实小页面验证复用;video-editor 不在候选中。