完成 Editor Agent Mock Agent P1 收尾

接入 Web Project 契约、SpacetimeDB 表与 api-server 控制面
新增 Mock Agent、静态构建 runner 与独立预览网关
补齐 /editor/agent 前端页面、服务客户端和 SSE 订阅
修复 sandbox 预览资源跨域加载并补充并发保护
接入本地 dev 预览端口漂移与服务身份初始化
更新 P1 技术方案、验收清单和 Hermes 共享记忆
This commit is contained in:
2026-06-16 17:31:25 +08:00
parent 80a382b034
commit 4b09ce3096
404 changed files with 14886 additions and 2497 deletions

View File

@@ -50,7 +50,7 @@ npm install
npm run dev
```
Linux 多用户共享同一台机器开发时,本地 dev 脚本会为当前 Linux 用户分配一个固定端口段并写入系统级注册表 `/var/tmp/genarrative-dev-port-ranges/registry.json`,自动分配从 `10000-10099` 开始,每段 100 个端口,四个 dev 服务依次使用 `start``start + 3`。可用 `GENARRATIVE_DEV_PORT_RANGE``npm run dev -- --port-range` 手动指定端口段用于特殊场景;注册表会阻止不同用户使用相同或重叠段,并让同一用户后续启动继续复用自己已占用的固定段。该机制只在 Linux 生效Windows 仍沿用原有端口探测与漂移逻辑。
Linux 多用户共享同一台机器开发时,本地 dev 脚本会为当前 Linux 用户分配一个固定端口段并写入系统级注册表 `/var/tmp/genarrative-dev-port-ranges/registry.json`,自动分配从 `10000-10099` 开始,每段 100 个端口,主站、api-server、SpacetimeDB、后台和 Web Project preview gateway 依次使用 `start``start + 4`。可用 `GENARRATIVE_DEV_PORT_RANGE``npm run dev -- --port-range` 手动指定端口段用于特殊场景;注册表会阻止不同用户使用相同或重叠段,并让同一用户后续启动继续复用自己已占用的固定段。该机制只在 Linux 生效Windows 仍沿用原有端口探测与漂移逻辑。
本地 `npm run dev``npm run dev:spacetime``npm run dev:api-server` 会在 Rust 子进程环境中绕过项目默认 `sccache` wrapper避免损坏的本机 cache daemon 阻断 `spacetime publish``api-server` 启动;显式设置的非 sccache 自定义 wrapper 会被保留。生产 / Jenkins 构建仍按流水线自身的 sccache 策略执行。
@@ -61,7 +61,7 @@ Linux 多用户共享同一台机器开发时,本地 dev 脚本会为当前 Li
- 主站 Vite
- 后台 Vite
`npm run dev` 和单模块 `dev:*` 命令会更新根目录 `.app/dev-stack.json`,记录四个本地服务的 pid、端口、URL、启动状态和当前命令。该目录只作本机运行态观测不提交 Git。
`npm run dev` 和单模块 `dev:*` 命令会更新根目录 `.app/dev-stack.json`,记录 `spacetime``api-server``web``admin-web``web-project-preview` 的 pid、端口、URL、启动状态和当前命令。该目录只作本机运行态观测不提交 Git。
开启自动刷新:

View File

@@ -2254,3 +2254,11 @@
- 处理:租约持有 `Arc<SpacetimeConnectionPool>` 并实现 `Drop` 统一复位槽位/归还连接;槽位改 `AtomicBool` CAS 抢占,删除自旋循环(持有 permit 必然命中空闲槽位)。任何新的"显式归还"资源在 async 取消语义下都要先想 Drop 兜底。
- 验证:`cargo test -p spacetime-client --manifest-path server-rs/Cargo.toml --lib``dropped_lease_releases_slot_and_permit``acquire_times_out_at_pool_acquire_when_pool_is_busy`)。
- 关联:`server-rs/crates/spacetime-client/src/lib.rs``docs/【后端架构】SpacetimeDB连接池租约Drop兜底与取消安全-2026-06-11.md`
## Web Project preview sandbox 资源响应必须带 CORS
- 现象:`/editor/agent` 的 preview iframe 已切到独立 `http://127.0.0.1:3104/p/<token>/`,但 iframe 内 JS / CSS 模块加载失败,浏览器控制台提示 origin `null` 被 CORS 拦截,按钮点击 smoke 看不到预览内容。
- 原因P1 iframe 按安全边界只允许 `sandbox="allow-scripts"`,不加 `allow-same-origin`;浏览器会把 iframe 文档放进 opaque origin模块脚本和样式再从 preview gateway 加载时需要资源响应显式允许跨域。
- 处理preview gateway 服务 artifact 的成功响应统一带 `Access-Control-Allow-Origin: *`,但仍保留独立 origin、`sandbox="allow-scripts"` 和 CSP `connect-src 'none'`,不要为了修加载问题放宽 iframe sandbox。
- 验证:`cargo test -p api-server web_project --manifest-path server-rs/Cargo.toml`,并用浏览器 smoke 确认 iframe 中计数按钮从 `已点击 0 次` 变为 `已点击 1 次`
- 关联:`server-rs/crates/api-server/src/web_project_preview_gateway.rs``docs/technical/【测试用例】AIWeb工程静态预览MVP验收清单-2026-06-13.md`

View File

@@ -13,7 +13,7 @@ metadata:
# Genarrative 本地 dev 启动端口与代理目标串联流程
用于维护 Genarrative 本地开发栈启动脚本,重点覆盖 `npm run dev` 与四个 `dev:*` 单模块命令的端口检查、端口漂移和后续流程目标传递。
用于维护 Genarrative 本地开发栈启动脚本,重点覆盖 `npm run dev` 与四个 `dev:*` 单模块命令的端口检查、端口漂移和后续流程目标传递;完整栈当前包含五个服务端口
## 适用场景
@@ -31,26 +31,27 @@ metadata:
2. Rust `api-server``8082`,健康检查为 `http://127.0.0.1:<api-port>/healthz`
3. SpacetimeDB standalone`3101`,健康检查为 `http://127.0.0.1:<spacetime-port>/v1/ping`
4. 后台 Vite`3102`,后台地址为 `http://127.0.0.1:<admin-web-port>/admin/`
5. Web Project preview gateway`3104`,预览地址由 `api-server` 签发为 `http://127.0.0.1:<web-project-preview-port>/p/<preview-token>/`
端口不可用时,脚本会从优先端口开始向后寻找可用端口。后续流程必须以解析后的实际端口为准,不能继续使用默认端口。
Linux 多用户并发开发时,`GENARRATIVE_DEV_PORT_RANGE``--port-range` 会先向系统级注册表 `/var/tmp/genarrative-dev-port-ranges/registry.json` 申请一个端口段,再把该段映射为 `web = start``api = start + 1``spacetime = start + 2``adminWeb = start + 3`。注册表锁文件是 `/var/tmp/genarrative-dev-port-ranges/registry.lock`,可通过 `GENARRATIVE_DEV_PORT_RANGE_REGISTRY_DIR` 覆盖目录。自动分配从 `10000-10099` 起,每次占用 100 个端口块,后续块按 `10100-10199``10200-10299` 递增;当前口径是“一个用户固定占用一个段,后续启动继续复用这段并在段内漂移”;该注册表只在 Linux 上生效Windows 继续沿用原有端口探测、漂移和复用逻辑,不读系统级注册表。
Linux 多用户并发开发时,`GENARRATIVE_DEV_PORT_RANGE``--port-range` 会先向系统级注册表 `/var/tmp/genarrative-dev-port-ranges/registry.json` 申请一个端口段,再把该段映射为 `web = start``api = start + 1``spacetime = start + 2``adminWeb = start + 3``webProjectPreview = start + 4`。注册表锁文件是 `/var/tmp/genarrative-dev-port-ranges/registry.lock`,可通过 `GENARRATIVE_DEV_PORT_RANGE_REGISTRY_DIR` 覆盖目录。自动分配从 `10000-10099` 起,每次占用 100 个端口块,后续块按 `10100-10199``10200-10299` 递增;当前口径是“一个用户固定占用一个段,后续启动继续复用这段并在段内漂移”;该注册表只在 Linux 上生效Windows 继续沿用原有端口探测、漂移和复用逻辑,不读系统级注册表。
## 实现入口
- `package.json`
- `dev`:执行 `node scripts/dev.mjs`,启动完整四模块
- `dev`:执行 `node scripts/dev.mjs`,启动完整栈的五个服务端口
- `dev:spacetime` / `dev:api-server` / `dev:web` / `dev:admin-web`:执行 `node scripts/dev.mjs <module>`
- `scripts/dev-stack-port-utils.mjs`
- `isPortAvailable(...)`:探测端口是否可监听。
- `findAvailablePort(...)`:从优先端口向后寻找可用端口,`0` 表示申请临时端口。
- `resolveDevStackPorts(...)`:一次性解析 SpacetimeDB、api-server、主站 Vite、后台 Vite 端口,并避免本次解析结果互相冲突。
- `resolveDevStackPorts(...)`:一次性解析 SpacetimeDB、api-server、主站 Vite、后台 Vite、Web Project preview gateway 端口,并避免本次解析结果互相冲突。
- Linux 注册表分配:`reserveLinuxDevPortRange(...)` / `releaseLinuxDevPortRange(...)`,仅在 Linux 上启用系统级端口段登记与用户段复用,自动分配从 `10000-10099` 起。
- CLI 模式:`node scripts/dev-stack-port-utils.mjs resolve-dev-stack spacetime:127.0.0.1:3101 api:127.0.0.1:8082 web:0.0.0.0:3000 adminWeb:127.0.0.1:3102`
- CLI 模式:`node scripts/dev-stack-port-utils.mjs resolve-dev-stack spacetime:127.0.0.1:3101 api:127.0.0.1:8082 web:0.0.0.0:3000 adminWeb:127.0.0.1:3102 webProjectPreview:127.0.0.1:3104`
- `scripts/dev.mjs`
- 解析 CLI 参数后统一计算 client host、端口、`SPACETIME_SERVER``RUST_SERVER_TARGET`
- 完整栈按 SpacetimeDB、publish、api-server、主站 Vite、后台 Vite 顺序启动。
- Linux 下会先申请系统级端口段并把它映射成个 dev 端口;自动分配从 `10000-10099`Windows 则直接沿用原有参数解析与端口漂移逻辑。
- 完整栈按 SpacetimeDB、publish、api-server、主站 Vite、后台 Vite 顺序启动Web Project preview gateway 是 `api-server` 内嵌的独立监听端口
- Linux 下会先申请系统级端口段并把它映射成个 dev 端口;自动分配从 `10000-10099`Windows 则直接沿用原有参数解析与端口漂移逻辑。
- 单模块命令复用同一套参数和 env 解析。
## 必须保持的传递链路
@@ -63,8 +64,9 @@ Linux 多用户并发开发时,`GENARRATIVE_DEV_PORT_RANGE` 或 `--port-range`
4. api-server 健康检查:`wait_for_api_server "${RUST_SERVER_TARGET}/healthz" ...`
5. 主站 Vite`RUST_SERVER_TARGET``GENARRATIVE_RUNTIME_SERVER_TARGET``ADMIN_WEB_TARGET``ADMIN_WEB_PORT``--port=${WEB_PORT}``--host=${WEB_HOST}`
6. 后台 Vite`ADMIN_API_TARGET``GENARRATIVE_API_TARGET``GENARRATIVE_API_PORT``--port=${ADMIN_WEB_PORT}`
7. 控制台日志:`[dev:ports]``[dev] web/admin web/api-server/spacetime` 必须显示最终实际地址
8. Linux 端口段注册`[dev] port-range:` `[dev] port-range-registry:` 只在 Linux 输出Windows 不应依赖系统级注册表
7. Web Project preview gateway`GENARRATIVE_WEB_PROJECT_PREVIEW_HOST``GENARRATIVE_WEB_PROJECT_PREVIEW_PORT``GENARRATIVE_WEB_PROJECT_PREVIEW_PUBLIC_BASE_URL``GENARRATIVE_WEB_PROJECT_PREVIEW_FRAME_ANCESTORS`
8. 控制台日志`[dev:ports]` `[dev] web/admin web/api-server/spacetime` 必须显示最终实际地址
9. Linux 端口段注册:`[dev] port-range:``[dev] port-range-registry:` 只在 Linux 输出Windows 不应依赖系统级注册表。
如果只改了其中一段,通常会出现:浏览器打开的前端可用,但 `/api/*` 代理到旧端口;后台页面可用但后台 API 失败SpacetimeDB 启动在新端口但 publish 仍发往旧端口。
@@ -91,14 +93,15 @@ Linux 多用户并发开发时,`GENARRATIVE_DEV_PORT_RANGE` 或 `--port-range`
node --check scripts/dev.mjs
npm run test -- scripts/dev-stack-port-utils.test.ts
npm run check:encoding
node scripts/dev-stack-port-utils.mjs resolve-dev-stack spacetime:127.0.0.1:0 api:127.0.0.1:0 web:0.0.0.0:0 adminWeb:127.0.0.1:0
npm run test -- scripts/dev.test.ts scripts/dev-stack-port-utils.test.ts --reporter verbose
node scripts/dev-stack-port-utils.mjs resolve-dev-stack spacetime:127.0.0.1:0 api:127.0.0.1:0 web:0.0.0.0:0 adminWeb:127.0.0.1:0 webProjectPreview:127.0.0.1:0
```
端口冲突回归测试建议:
1. 用测试或临时 Node server 占用某个优先端口。
2. 调用 `findAvailablePort`,断言结果大于被占用端口。
3. 调用 `resolveDevStackPorts`,断言个结果互不相同。
3. 调用 `resolveDevStackPorts`,断言个结果互不相同。
4. 如果实际启动完整栈,观察控制台:
- `[dev:ports] ... 不可用,改用 ...`
- `[dev] api-server: http://...:<actual-api-port>`
@@ -121,7 +124,7 @@ node scripts/dev-stack-port-utils.mjs resolve-dev-stack spacetime:127.0.0.1:0 ap
- [ ] 端口工具有测试覆盖端口被占用和多端口互斥解析。
- [ ] Linux 注册表分配、同用户复用固定段并继续漂移、自动分配从 `10000-10099` 起、Windows bypass 都有测试覆盖。
- [ ] `scripts/dev.mjs` 通过 `node --check`
- [ ] `npm run dev` 的 SpacetimeDB、publish、api-server、主站 Vite、后台 Vite 都使用实际端口。
- [ ] `npm run dev` 的 SpacetimeDB、publish、api-server、主站 Vite、后台 Vite、Web Project preview gateway 都使用实际端口。
- [ ] `npm run dev:web` 在主站端口不可用时能切换到可用端口。
- [ ] 文档同步更新 `docs/technical/RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md`
- [ ] 长期踩坑同步更新 `.hermes/shared-memory/pitfalls.md`