Merge branch 'master' of http://82.157.175.59:3000/GenarrativeAI/Genarrative
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-05-02 17:57:02 +08:00
47 changed files with 227 additions and 536 deletions

View File

@@ -628,7 +628,7 @@ SpacetimeDB 方向:
4. LLM、OSS、图片生成等外部 I/O 放在 `api-server` / `platform-*` crate 中,再把确定结果写回 SpacetimeDB。
5. 前端调用 reducer 使用生成绑定和对象参数,不编辑生成代码。
6. 涉及表结构修改时同步更新 `migration.rs`
7. 修改后端代码后统一执行 `npm run api-server:maincloud`,并跑对应自动测试。
7. 修改后端代码后统一执行 `npm run api-server`,并跑对应自动测试。
## 9. 最小验收标准

View File

@@ -109,7 +109,7 @@
1. `package.json` 中不存在 `server-node:*``dev:node``m7:api-compare``check:server-node-freeze` 等旧入口。
2. `scripts/` 下不存在 `dev-node.mjs``smoke-server-node.ts``m7-api-compare.ts``smoke-same-origin-stack.ts` 等旧 Node 后端脚本。
3. `package.json``package-lock.json` 中不存在 `express``@types/express``pg``postgres` 依赖。
4. 当前开发入口继续固定为 `npm run dev``npm run dev:web``npm run api-server:maincloud` 与 Rust / SpacetimeDB 相关脚本,不恢复旧 Node 后端切换开关。
4. 当前开发入口继续固定为 `npm run dev``npm run dev:web``npm run api-server` 与 Rust / SpacetimeDB 相关脚本,不恢复旧 Node 后端切换开关。
## 9. Caddy 本地服务入口移除2026-04-26

View File

@@ -255,14 +255,14 @@ node scripts/vite-cli.mjs --port=3000 --host=0.0.0.0
后端代码更新后统一执行:
```bash
npm run api-server:maincloud
npm run api-server
```
执行要求:
- 该命令是后端更新后的默认重启入口,不再使用此前的后端重启命令。
- 重启后必须继续执行与本次后端改动对应的自动测试;涉及 Rust workspace 时优先跑 `server-rs` 下的检查或测试脚本。
- 若本次改动涉及 SpacetimeDB 发布、绑定生成或 Maincloud 联调,按 `spacetimedb-cli` 经验执行,并在验证记录中写清楚实际命令与结果。
- 若本次改动涉及 SpacetimeDB 发布、绑定生成或本地联调,按 `spacetimedb-cli` 经验执行,并在验证记录中写清楚实际命令与结果。
## 14. 一句话总结

View File

@@ -753,7 +753,7 @@ RPG 运行时链:
这些脚本不直接参与玩法,但直接支撑开发、发布、绑定和检查:
### `scripts/api-server-maincloud.mjs`
### `scripts/api-server-dev.mjs`
职责:

View File

@@ -259,7 +259,7 @@ export interface ProfileInviteCodeAdminResponse {
`tableStats` 中单表失败必须展示 `errorMessage`不能让整页变成空白。SpacetimeDB private 表或当前身份不可见的表在 `/sql` 下可能返回 `no such table` / `marked private`后台服务必须将这类错误归一为“不可统计private 或当前身份不可见)”,避免把预期的访问边界展示成原始 HTTP 400 故障。
线上如果大量表都显示“不可统计private 或当前身份不可见)”,优先检查 `api-server` 启动环境中的 `GENARRATIVE_SPACETIME_TOKEN` / `GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN` 是否存在且属于目标库 owner。Jenkins 覆盖发布包时必须保留部署目录已有运行 token只带迁移 token 不能让后台概览读取 private 表。
线上如果大量表都显示“不可统计private 或当前身份不可见)”,优先检查 `api-server` 启动环境中的 `GENARRATIVE_SPACETIME_TOKEN` 是否存在且属于目标库 owner。Jenkins 覆盖发布包时必须保留部署目录已有运行 token只带迁移 token 不能让后台概览读取 private 表。
### 4.6 API 调试 contract
@@ -380,7 +380,7 @@ export interface ProfileInviteCodeAdminResponse {
### 7.1 本地联调
1. 启动后端:`npm run api-server:maincloud`
1. 启动后端:`npm run api-server`
2. 启动后台前端:在 `apps/admin-web` 执行 `npm run dev`
3. 后台 dev server 通过 Vite proxy 转发 `/admin/api``ADMIN_API_TARGET`;未配置时默认 `http://127.0.0.1:3100`
4. 若使用非 3100 端口,在仓库根目录 `.env.local` 设置 `ADMIN_API_TARGET=http://127.0.0.1:<api-server-port>`,并重启后台前端 dev server。
@@ -437,7 +437,7 @@ export interface ProfileInviteCodeAdminResponse {
- 后续接入根 workspace 后,补充后台工程 build/typecheck 脚本。
3. 后端:
- 继续保留 `cargo test -p api-server --manifest-path server-rs/Cargo.toml admin`
- 修改后端管理 API 后必须运行 `npm run api-server:maincloud` 并手动验证 `/admin` 为 404、`/admin/api/login` 可用。
- 修改后端管理 API 后必须运行 `npm run api-server` 并手动验证 `/admin` 为 404、`/admin/api/login` 可用。
## 9. 后续扩展边界

View File

@@ -11,7 +11,7 @@
## 2. 根因
### 2.1 Maincloud 目标库挂起
### 2.1 远端目标库挂起
CLI 直接查询 `xushi-p4wfr` 返回:
@@ -20,7 +20,7 @@ Error: database is suspended
HTTP status server error (503 Service Unavailable)
```
这说明 `maincloud.spacetimedb.com` 入口在线,但具体数据库 `xushi-p4wfr` 当前不可订阅、不可查 schema、不可执行 SQL。所有依赖该库的 procedure 都会失败。
这说明远端 SpacetimeDB 入口在线,但具体数据库 `xushi-p4wfr` 当前不可订阅、不可查 schema、不可执行 SQL。所有依赖该库的 procedure 都会失败。
### 2.2 认证快照同步被当成硬失败
@@ -64,7 +64,7 @@ HTTP status server error (503 Service Unavailable)
## 4. 本地可跑链路
Maincloud `xushi-p4wfr` 挂起期间,抓大鹅本地体验应使用本地 SpacetimeDB
远端 `xushi-p4wfr` 挂起期间,抓大鹅本地体验应使用本地 SpacetimeDB
```powershell
spacetime --root-dir=server-rs/.spacetimedb/local start --edition standalone --listen-addr 127.0.0.1:3101
@@ -75,10 +75,10 @@ spacetime --root-dir=server-rs/.spacetimedb/local publish xushi-p4wfr --server h
再让 Rust API 指向本地库:
```powershell
$env:GENARRATIVE_SPACETIME_MAINCLOUD_SERVER_URL="http://127.0.0.1:3101"
$env:GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE="xushi-p4wfr"
$env:GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN=""
npm run api-server:maincloud
$env:GENARRATIVE_SPACETIME_SERVER_URL="http://127.0.0.1:3101"
$env:GENARRATIVE_SPACETIME_DATABASE="xushi-p4wfr"
$env:GENARRATIVE_SPACETIME_TOKEN=""
npm run api-server
```
最后重启前端:
@@ -96,10 +96,10 @@ npm run dev:web
1. `GET http://127.0.0.1:3000/api/auth/login-options` 返回 `["phone","password"]`
2. `GET http://127.0.0.1:3000/api/runtime/match3d/gallery` 返回 `{"items":[]}`,不再返回 SpacetimeDB 503。
3. 未登录请求 `POST http://127.0.0.1:3000/api/creation/match3d/sessions` 返回 `401`,说明同源请求已进入 Rust 鉴权层,不再被 Vite `404`
4. 隔离端口指向挂起的 Maincloud 并使用 mock 短信时,手机号验证码登录返回 `200` 和 token日志只记录“认证快照写入 SpacetimeDB 失败,当前认证流程继续”。
4. 隔离端口指向挂起的远端库并使用 mock 短信时,手机号验证码登录返回 `200` 和 token日志只记录“认证快照写入 SpacetimeDB 失败,当前认证流程继续”。
## 6. 后续
1. Maincloud `xushi-p4wfr` 仍需恢复数据库挂起状态,否则正式云端玩法 procedure 仍不可用。
1. 远端 `xushi-p4wfr` 仍需恢复数据库挂起状态,否则对应玩法 procedure 仍不可用。
2. 本地开发如只为体验抓大鹅,可继续使用本地 SpacetimeDB 链路。
3. 认证快照同步失败会影响进程重启后的端恢复完整性,需要在 Maincloud 恢复后重新完成一次成功同步。
3. 认证快照同步失败会影响进程重启后的端恢复完整性,需要在目标库恢复后重新完成一次成功同步。

View File

@@ -7,7 +7,7 @@
但当前链路仍暴露出两个直接体验问题:
1. 前端草稿进度页仍把大鱼吃小鱼展示成单个 `compile` 步骤,用户会感觉“整个生成过程只有一步,而且一直卡在第一步”。
2. 前端在打开大鱼草稿或结果页时,会通过 `GET /api/runtime/big-fish/agent/sessions/:sessionId` 拉取完整会话;当 Maincloud 上游偶发抖动时Rust `spacetime-client` 统一 10 秒超时会直接映射成 `502`,用户会看到反复报错。
2. 前端在打开大鱼草稿或结果页时,会通过 `GET /api/runtime/big-fish/agent/sessions/:sessionId` 拉取完整会话;当 SpacetimeDB 上游偶发抖动时Rust `spacetime-client` 统一 10 秒超时会直接映射成 `502`,用户会看到反复报错。
## 修复口径
@@ -39,7 +39,7 @@
这样可以覆盖两类常见情况:
1. Maincloud 连接偶发抖动,第一次 procedure 超时但第二次马上恢复。
1. SpacetimeDB 连接偶发抖动,第一次 procedure 超时但第二次马上恢复。
2. 用户打开草稿页时碰到短暂断链,不再被立即判定成稳定的坏网关故障。
## 落地范围

View File

@@ -16,7 +16,7 @@
1. 构建产物目录统一使用 `build/<版本号>/`
2. 默认使用 Jenkins `BUILD_NUMBER` 作为版本号,避免依赖时间戳;如有需要也允许显式传 `BUILD_VERSION`
3. `构建``构建并部署``checkout scm` 后、实际构建前必须执行 `git reset --hard HEAD``git clean -fd`,避免固定源码目录内的 Git 变更和未跟踪文件影响发布包;不使用 `-x`,避免删除 `node_modules/` 等忽略目录后与 `RUN_NPM_CI=false` 冲突。
3. 所有使用仓库源码的 Jenkins 流水线在实际执行脚本前必须执行 `git reset --hard HEAD`,避免固定源码目录内的 Git 变更影响本次构建、部署或迁移操作;其中 `构建``构建并部署` 在实际构建前还必须执行 `git clean -fd` 清理未跟踪文件,不使用 `-x`,避免删除 `node_modules/` 等忽略目录后与 `RUN_NPM_CI=false` 冲突。
4. `构建并部署` 可选填写 `COMMIT_HASH`。留空时使用 Jenkins SCM 当前检出的提交;填写时只能是 7 到 40 位十六进制 commit hash流水线会先按 SCM checkout 得到仓库,再尽量拉取 `origin` 全部分支引用、解析该 hash 并 detached checkout 到对应 commit 后构建。
5. `部署` 流水线允许人工启动;没有上游触发 cause 时按人工部署处理,不再直接失败。
6. `部署` 流水线仅在存在上游触发 cause 时校验上游作业名与传入的 `EXPECTED_UPSTREAM_JOB` 一致;如配置了环境变量 `GENARRATIVE_ALLOWED_UPSTREAM_JOB`,还必须与该值一致。
@@ -84,7 +84,8 @@ jenkins/Jenkinsfile.deploy
1. 读取触发原因;人工启动时跳过上游门禁,上游触发时同时兼容 `BuildUpstreamCause` 与经典 `UpstreamCause` 并继续校验上游作业名。
2. 校验 `BUILD_VERSION``SOURCE_WORKSPACE_ROOT``DEPLOY_DIRECTORY` 非空。
3. 执行:
3. `SOURCE_WORKSPACE_ROOT` 内执行 `git reset --hard HEAD`,确保部署脚本和构建产物选择不受本地改动影响。
4. 执行:
```bash
scripts/jenkins-deploy-release.sh \
@@ -100,7 +101,7 @@ scripts/jenkins-deploy-release.sh \
脚本语义:
1. 若部署目录已有旧版本且存在 `stop.sh`,先执行旧版本 `stop.sh`
2. 覆盖前如果旧部署目录存在 `migration-bootstrap-secret.txt`,先复制到 `deploy-state/migration-bootstrap-secret.previous.txt`,供新版本 `start.sh` 在 schema 冲突自动迁移时授权导出旧库。该文件属于 Jenkins 部署状态,不放入 `run/`,避免 `sudo` 启停脚本生成的 root 私有运行目录阻断后续部署写入。
2. 覆盖前如果旧部署目录存在 `migration-bootstrap-secret.txt`,先复制到 `deploy-state/migration-bootstrap-secret.previous.txt`,供新版本 `start.sh` 在 schema 冲突自动迁移时授权导出旧库。该文件属于 Jenkins 部署状态,不放入 `run/`,避免 `sudo` 启停脚本生成的 root 私有运行目录阻断后续部署写入;如果后续部署失败,部署脚本必须把该快照复制回部署目录根下的 `migration-bootstrap-secret.txt`,避免当前仍在运行的数据库丢失对应迁移引导密钥
3. 只删除发布产物白名单中的旧文件,例如 `web/``api-server``spacetime_module.wasm``migration-bootstrap-secret.txt``scripts/``.env*``start.sh``stop.sh``web-server.mjs``README.md`
4. 将指定版本目录中的同名发布产物复制到部署目录;文件产物使用普通复制,`web/``scripts/` 等目录产物必须递归复制。
5.`WEB_PORT``MIGRATE_ON_CONFLICT``MIGRATION_DIRECTORY` 写入部署目录 `.env.local`,确保通过 sudo 执行 `start.sh` 时仍能读取 Jenkins 参数;启动前读取 `.env``.env.local` 中最终的 `GENARRATIVE_SPACETIME_DATABASE`,打印并校验其符合 SpacetimeDB 数据库名规则。Jenkins 参数 `MIGRATION_EXPORT_TOKEN` / `MIGRATION_IMPORT_TOKEN` 会分别写入 `GENARRATIVE_SPACETIME_MIGRATION_EXPORT_TOKEN` / `GENARRATIVE_SPACETIME_MIGRATION_IMPORT_TOKEN`;如果参数为空,部署目录已有同名变量时会尽量保留。
@@ -109,7 +110,7 @@ scripts/jenkins-deploy-release.sh \
如果 `RUN_DEPLOY_HOOKS_WITH_SUDO=true`,旧版本 `stop.sh` 和新版本 `start.sh` 会改为 `sudo -n` 调用;这要求 Jenkins 运行用户提前配置免密 sudo否则部署会直接失败不会进入交互式密码提示。
这样可以满足“发布文件直接覆盖”的要求,同时保留部署目录里像 `.spacetimedb/``logs/``run/``deploy-state/``database-migrations/` 这类运行态目录,不会因为部署被整体删除。`run/` 只承载 pid 等启停运行状态;`deploy-state/` 承载 Jenkins 覆盖部署前保存的旧迁移引导密钥,必须由 Jenkins 用户保持可写。发布白名单内的 `.env``.env.local` 会先以构建产物中的文件为准;部署脚本会在启动 hook 前移除这些环境文件中的 UTF-8 BOM 与 CRLF并把 Jenkins 部署参数 `WEB_PORT` 写入 `.env.local``GENARRATIVE_WEB_PORT`,把 `MIGRATE_ON_CONFLICT` 写入 `GENARRATIVE_SPACETIME_MIGRATE_ON_CONFLICT`,把 `MIGRATION_DIRECTORY` 写入 `GENARRATIVE_SPACETIME_MIGRATION_DIR`,并在启动前输出最终 `GENARRATIVE_SPACETIME_DATABASE`,避免 `start.sh` 在 Bash 下把首行变量名误解析成命令,也避免端口、数据库名和迁移配置只停留在上游构建阶段。`start.sh` 会先执行 Ubuntu 专用 `sync_ubuntu_spacetime_install`,优先从 `/usr/.local/share/spacetime/bin/<version>/spacetimedb-cli``$HOME/.local/share/spacetime/bin/<version>/spacetimedb-cli` 同步到部署目录 `.spacetimedb/bin/current/spacetimedb-cli`,后续启动、探活和 root-dir 占用判定都使用部署目录内 `.spacetimedb/`,且不再额外设置 `--data-dir`,避免 Jenkins 机器全局 `spacetime login` 变化影响本地库更新;如遇 `403 Forbidden`,按 `SPACETIMEDB_START_SH_PUBLISH_403_IDENTITY_FIX_2026-04-26.md` 排查数据库所有者与 CLI 身份。
这样可以满足“发布文件直接覆盖”的要求,同时保留部署目录里像 `.spacetimedb/``logs/``run/``deploy-state/``database-migrations/` 这类运行态目录,不会因为部署被整体删除。`run/` 只承载 pid 等启停运行状态;`deploy-state/` 承载 Jenkins 覆盖部署前保存的旧迁移引导密钥,必须由 Jenkins 用户保持可写,并在部署失败时作为恢复源写回根目录 `migration-bootstrap-secret.txt`。发布白名单内的 `.env``.env.local` 会先以构建产物中的文件为准;部署脚本会在启动 hook 前移除这些环境文件中的 UTF-8 BOM 与 CRLF并把 Jenkins 部署参数 `WEB_PORT` 写入 `.env.local``GENARRATIVE_WEB_PORT`,把 `MIGRATE_ON_CONFLICT` 写入 `GENARRATIVE_SPACETIME_MIGRATE_ON_CONFLICT`,把 `MIGRATION_DIRECTORY` 写入 `GENARRATIVE_SPACETIME_MIGRATION_DIR`,并在启动前输出最终 `GENARRATIVE_SPACETIME_DATABASE`,避免 `start.sh` 在 Bash 下把首行变量名误解析成命令,也避免端口、数据库名和迁移配置只停留在上游构建阶段。`start.sh` 会先执行 Ubuntu 专用 `sync_ubuntu_spacetime_install`,优先从 `/usr/.local/share/spacetime/bin/<version>/spacetimedb-cli``$HOME/.local/share/spacetime/bin/<version>/spacetimedb-cli` 同步到部署目录 `.spacetimedb/bin/current/spacetimedb-cli`,后续启动、探活和 root-dir 占用判定都使用部署目录内 `.spacetimedb/`,且不再额外设置 `--data-dir`,避免 Jenkins 机器全局 `spacetime login` 变化影响本地库更新;如遇 `403 Forbidden`,按 `SPACETIMEDB_START_SH_PUBLISH_403_IDENTITY_FIX_2026-04-26.md` 排查数据库所有者与 CLI 身份。
### 4.3 构建并部署

View File

@@ -39,7 +39,7 @@ Genarrative-Database-Export
关键参数:
1. `DATABASE`:目标 SpacetimeDB 数据库名;留空时读取仓库环境变量。
2. `SERVER`SpacetimeDB server 别名,默认 `maincloud`
2. `SERVER`SpacetimeDB server 别名,默认 `dev`
3. `SERVER_URL`:显式服务地址;填写后优先于 `SERVER`
4. `DEPLOY_DIRECTORY`:固定部署目录,默认 `/var/lib/jenkins/deploy/Genarrative`
5. `ROOT_DIR`:可选,透传给 `spacetime --root-dir`;为空时使用 `<DEPLOY_DIRECTORY>/.spacetimedb`
@@ -86,11 +86,12 @@ Genarrative-Database-Import
2. `INCREMENTAL``REPLACE_EXISTING` 互斥Jenkinsfile 会在执行前阻止同时启用。
3. Jenkinsfile 不打印 token生产环境应通过 Jenkins 凭据或目标机器环境变量传入敏感值。
4. 如果不传 `TOKEN`,导入脚本会创建临时 Web API identity并调用迁移授权/撤销 procedure 收敛权限窗口。
5. 如果日志出现 `SpacetimeDB HTTP 413: Failed to buffer the request body: length limit exceeded`,优先把 `CHUNK_SIZE` 调低到 `262144` 或更小后重跑。该参数只降低单次 HTTP body不改变导入表范围
5. 导入导出流水线在调用仓库内迁移脚本前都会执行 `git reset --hard HEAD`,确保固定源码目录中的本地改动不会影响本次迁移操作
6. 如果日志出现 `SpacetimeDB HTTP 413: Failed to buffer the request body: length limit exceeded`,优先把 `CHUNK_SIZE` 调低到 `262144` 或更小后重跑。该参数只降低单次 HTTP body不改变导入表范围。
## 5. 本地部署测试参数
`Genarrative-Build-And-Deploy` 增加以下本地发布包参数,便于在 Jenkins 中测试本地 SpacetimeDB,不依赖 Maincloud
`Genarrative-Build-And-Deploy` 增加以下本地发布包参数,便于在 Jenkins 中测试本地 SpacetimeDB
1. `DATABASE`:发布包默认数据库名,默认 `genarrative-pipeline-local-test`。SpacetimeDB CLI 当前要求数据库名匹配 `^[a-z0-9]+(-[a-z0-9]+)*$`,只能使用小写字母、数字,并用单个短横线分隔;不要使用大写字母、点号、下划线、首尾短横线或连续短横线。
2. `API_PORT`:发布包内 api-server 端口,默认 `8082`
@@ -106,7 +107,7 @@ SERVER_URL=http://127.0.0.1:3101
DEPLOY_DIRECTORY=/var/lib/jenkins/deploy/Genarrative
```
这样脚本会自动使用 `/var/lib/jenkins/deploy/Genarrative/.spacetimedb` 作为 `spacetime --root-dir`,避免回退到 Jenkins 用户全局 CLI 登录态,也避免误连 Maincloud
这样脚本会自动使用 `/var/lib/jenkins/deploy/Genarrative/.spacetimedb` 作为 `spacetime --root-dir`,避免回退到 Jenkins 用户全局 CLI 登录态,也避免误连非本地目标
## 6. 文件清单

View File

@@ -39,8 +39,6 @@
- protocol: `/responses`
- web_search: 开启时映射为 `tools: [{ "type": "web_search", "max_keyword": 3 }]`
联网搜索是模板创作的增强能力,不是 Agent 对话主链的硬依赖。若上游 Responses SSE 返回 `ToolNotOpen` 或“账号未开通 web search”类错误`creation_agent_llm_turn` 必须使用同一 system/user prompt 自动降级为无联网搜索重试一次;只有重试仍失败时才向玩法层返回“生成失败”。这样 RPG Agent、大鱼 Agent、拼图 Agent 都能在未开通搜索插件的环境中继续完成基础 JSON turn。
覆盖入口:
1. `creation_agent_llm_turn.rs`
@@ -76,7 +74,6 @@ Responses 非流式解析优先读取 `output_text`,再兼容 `output[].conten
1. RPG 运行时 LLM 请求在代码层显式带 `doubao-seed-character-251128`
2. 创作模板 LLM 请求在代码层显式带 `deepseek-v3-2-251201` 与 Responses 协议。
3. `platform-llm` 单测覆盖 Responses 非流式、Responses SSE、Responses web_search tools 请求体。
4. `api-server` 单测覆盖创作 Agent 对 `ToolNotOpen` / 未开通 web search 错误的识别,确保可触发无搜索重试
5. `cargo test -p platform-llm --manifest-path server-rs/Cargo.toml` 通过。
6. `cargo test -p api-server creation_agent_llm_turn --manifest-path server-rs/Cargo.toml` 通过。
7. 修改后按项目约束使用 `npm run api-server:maincloud` 重新启动后端,并执行相应自动测试。
4. `cargo test -p platform-llm --manifest-path server-rs/Cargo.toml` 通过
5. `cargo test -p api-server creation_agent_llm_turn --manifest-path server-rs/Cargo.toml` 通过。
6. 修改后按项目约束使用 `npm run api-server` 重新启动后端,并执行相应自动测试。

View File

@@ -2,7 +2,7 @@
日期:`2026-04-22`
归档说明:截至 `2026-04-26`Rust 迁移已完成,旧 `server-node/` 已删除M7 阶段性预检包装入口已移除。后续长期检查统一使用 `server-rs/scripts/check.ps1``server-rs/scripts/smoke.ps1``server-rs/scripts/oss-smoke.ps1``npm run api-server:maincloud`
归档说明:截至 `2026-04-26`Rust 迁移已完成,旧 `server-node/` 已删除M7 阶段性预检包装入口已移除。后续长期检查统一使用 `server-rs/scripts/check.ps1``server-rs/scripts/smoke.ps1``server-rs/scripts/oss-smoke.ps1``npm run api-server`
## 1. 文档目标

View File

@@ -784,7 +784,7 @@ B3 当前落地状态:
1. 创作到发布到试玩主链通过。
2. 运行态点击、入槽、三消、失败、胜利通过。
3. 移动端视口检查通过。
4. `npm run api-server:maincloud` 通过。
4. `npm run api-server` 通过。
5. 对应测试与 `npm run check:encoding` 通过。
---
@@ -820,7 +820,7 @@ npm run check:encoding -- docs/technical/MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IM
```powershell
cargo test -p module-match3d
cargo test -p shared-contracts
npm run api-server:maincloud
npm run api-server
npm run check:encoding
```

View File

@@ -110,4 +110,4 @@ server-rs/crates/module-match3d
1. `cargo test -p module-match3d` 通过。
2. `cargo test -p shared-contracts match3d` 通过。
3. `npm run check:encoding` 覆盖新增中文文档和新增源码。
4. 本阶段不要求运行 `npm run api-server:maincloud`因为未修改后端运行服务入口、SpacetimeDB 表或 `api-server` facade。
4. 本阶段不要求运行 `npm run api-server`因为未修改后端运行服务入口、SpacetimeDB 表或 `api-server` facade。

View File

@@ -143,4 +143,4 @@ npm run check:encoding
3. 不把 Match3D 公开广场并入更复杂的推荐、排行和运营榜单策略。
4. 不删除 `/match3d` 本地 playground它作为开发调试入口继续保留。
5. 全量 `npm run typecheck` 曾存在非 Match3D 既有阻塞,本轮以 Q1 定向测试和后端定向检查作为集成验收口径。
6. Maincloud 运行态仍依赖当前 SpacetimeDB 环境稳定性;如 `npm run api-server:maincloud` 现场遇到订阅 HTTP 500应按 Maincloud/SpacetimeDB 联调链路单独排查。
6. 运行态仍依赖当前 SpacetimeDB 环境稳定性;如 `npm run api-server` 现场遇到订阅 HTTP 500应按本地 SpacetimeDB 联调链路单独排查。

View File

@@ -119,10 +119,10 @@ cargo check -p spacetime-client --manifest-path server-rs\Cargo.toml
cargo check -p api-server --manifest-path server-rs\Cargo.toml
cargo test -p shared-contracts match3d --manifest-path server-rs\Cargo.toml
npm run check:encoding
npm run api-server:maincloud
npm run api-server
```
`api-server:maincloud` 是修改后端后的必跑项;如果本地缺少 Maincloud 环境或 SpacetimeDB 发布态不一致,需要在最终结果里明确说明。
`api-server` 是修改后端后的必跑项;如果本地 SpacetimeDB 发布态不一致,需要在最终结果里明确说明。
## 7. 后续接入点

View File

@@ -128,4 +128,4 @@
- Rust/module-runtime覆盖公共码、唯一码、私有码、失败场景、流水来源和余额累加。
- Axum覆盖用户鉴权、管理员鉴权、runtime error 到 400 的映射和兼容路径。
- 前端:覆盖入口替换、独立 modal、成功刷新余额和失败展示后端 message。
- 验证命令:`cargo test`、目标前端测试、`npm run api-server:maincloud``npm run check:encoding`
- 验证命令:`cargo test`、目标前端测试、`npm run api-server``npm run check:encoding`

View File

@@ -13,11 +13,10 @@
3. 初始表单输入自动保存到 session 的 `draft_json``puzzle_work_profile` 投影。保存字段只包含 `workTitle``workDescription``pictureDescription`、可推断标签和一个 `generationStatus = idle` 的默认关卡草稿设置阶段默认关卡名称必须为空不得写入“第一关”“第1关”或作品名称作为默认值。参考图只保存在当前前端会话内不落入 SpacetimeDB。
4. 玩家在生成草稿前退出,再次从创作中心点击这条拼图草稿时,必须恢复到填表页,并回填之前自动保存的作品名称、作品描述和画面描述;只有执行 `compile_puzzle_draft` 且生成结果页草稿后,草稿入口才进入结果页。
5. 表单自动保存走 `save_puzzle_form_draft` action不消耗光点不生成图片不改变 `stage = collecting_anchors`;生成草稿按钮仍单独触发 `compile_puzzle_draft` 并进入进度页。
6. 生成草稿按钮文本右侧固定展示 `消耗2光点`,实际扣费由后端 `compile_puzzle_draft` 统一预扣,前端不自行判断余额
7. 点击拼图入口始终创建新草稿,不复用上一次未完成 session恢复旧草稿只通过“我的创作”中的草稿卡进入
8. 若 Maincloud 仍运行旧 wasm,缺少 `save_puzzle_form_draft` procedure前端提交生成或生成失败页重试时不得继续复用空 `seedText` 的表单 session必须用当前表单 payload 新建带真实 seed 的 session 再执行 `compile_puzzle_draft`
9. api-server 也要兼容旧 wasm`save_puzzle_form_draft` 缺失时,自动保存 action 降级返回当前 session`compile_puzzle_draft` 前置保存缺失且当前 session 为空 seed 时,创建一条带表单 seed 的替代 session 后继续编译,避免再次暴露 `No such procedure`
10. 正式修复仍是发布最新 SpacetimeDB wasm。当前 Maincloud `xushi-p4wfr` 的迁移操作员表为空,但旧库引导密钥来自旧 wasm本次临时生成的新引导密钥无法授权导出迁移需使用已有迁移操作员 token 或数据库 owner 重新授权后发布;禁止为绕过冲突直接清库,除非明确接受数据丢失。
6. 点击拼图入口始终创建新草稿,不复用上一次未完成 session恢复旧草稿只通过“我的创作”中的草稿卡进入
7. 若运行中的旧 wasm 缺少 `save_puzzle_form_draft` procedure前端提交生成或生成失败页重试时不得继续复用空 `seedText` 的表单 session必须用当前表单 payload 新建带真实 seed 的 session 再执行 `compile_puzzle_draft`
8. api-server 也要兼容旧 wasm`save_puzzle_form_draft` 缺失时,自动保存 action 降级返回当前 session`compile_puzzle_draft` 前置保存缺失且当前 session 为空 seed 时,创建一条带表单 seed 的替代 session 后继续编译,避免再次暴露 `No such procedure`
9. 正式修复仍是发布最新 SpacetimeDB wasm。如果目标库的迁移操作员表为空但旧库引导密钥来自旧 wasm本次临时生成的新引导密钥无法授权导出迁移需使用已有迁移操作员 token 或数据库 owner 重新授权后发布;禁止为绕过冲突直接清库,除非明确接受数据丢失
1. 作品名称为必填字段,保存到 `workTitle`,兼容写入旧 `seedText`,同时作为作品级 `workTitle` 的真相源。
2. 作品描述为必填字段,保存到 `workDescription`,作为作品详情页、作品列表和发布资料中的 `summary` 真相源。
@@ -97,8 +96,6 @@
6. api-server 处理 `generate_puzzle_images` 时,若 action 带有 `levelsJson`,必须用这份关卡快照覆盖本次生成的草稿关卡视图后再定位 `levelId`。若请求明确传入 `levelId` 但关卡列表中不存在该关卡,必须返回错误,不得静默回退第一关。
7. 历史拼图素材入口只在已有正式图的 `画面图` 区域右下角展示,不再放在 `画面描述` 输入区;本地上传参考图入口仍保留在画面描述输入区右下角。
8. 历史拼图素材列表必须由服务端按当前登录账号过滤,只返回 `asset_kind = puzzle_cover_image``owner_user_id = 当前账号` 的资产;不得依赖前端过滤,也不得展示其他账号素材。
9. 关卡详情“生成画面 / 重新生成画面”按钮文本右侧展示 `消耗2光点`;点击后弹出消耗确认弹窗,确认后才调用 `generate_puzzle_images`
10. 确认开始生成后,关卡详情底部生图按钮位置切换为 30 秒进度条,标注 `预计剩余 xx 秒`,用于覆盖 APIMart 生图常见等待时间;接口提前结束或失败时由父级 busy/error 状态接管。
画面描述区域不再展示候选图实际 prompt 或“请生成一张适合……”之类内部提示词模块。参考图入口保留在画面描述编辑区域内,便于重新生成时继续带入。结果页编辑关卡画面描述时只同步该关卡 `pictureDescription`;作品描述只在作品信息 Tab 编辑,作品详情页不得再回退使用画面描述。
@@ -108,5 +105,5 @@
2. 点击确认后进入拼图草稿生成进度页,并自动完成草稿编译、首图生成、正式图选择。
3. 首图生成请求使用玩家画面描述作为 prompt上传参考图时走图生图作品详情页展示玩家作品描述。
4. 结果页包含“拼图关卡”和“作品信息”两个 Tab关卡列表默认至少一关支持新增、删除和进入关卡详情。
5. 关卡详情页支持生成或重新生成画面;生图前确认消耗 `2` 光点,确认后展示 30 秒预计剩余进度条;已有正式图后显示吸底“关卡测试”入口。
5. 关卡详情页支持生成或重新生成画面;已有正式图后显示吸底“关卡测试”入口。
6. 发布、作品测试、自动保存作品名称、作品描述、作品标签和关卡列表仍可用。

View File

@@ -28,4 +28,4 @@
1. `npm run check:encoding`
2. `cargo check -p api-server --manifest-path server-rs/Cargo.toml`
3. `npm run api-server:maincloud` 重启后,点击拼图结果页“生成或更换图片”,候选图应能写回并正常展示。
3. `npm run api-server` 重启后,点击拼图结果页“生成或更换图片”,候选图应能写回并正常展示。

View File

@@ -4,15 +4,11 @@
## 文档列表
- [WORK_PUBLISH_SHARE_PANEL_2026-05-02.md](./WORK_PUBLISH_SHARE_PANEL_2026-05-02.md):记录作品发布完成后“分享给朋友”面板的标题、分享文本、复制按钮、微信/QQ/抖音渠道 icon 与四类作品发布链路接入口径。
- [PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md](./PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md):冻结当前对外中文命名,产品展示名统一为“百梦”,消费单位为“光点”,公开账号标识为“百梦号”,创作侧称谓为“百梦主”。
- [PUBLIC_WORK_DETAIL_OWNED_EDIT_ACTION_2026-05-02.md](./PUBLIC_WORK_DETAIL_OWNED_EDIT_ACTION_2026-05-02.md):记录公开作品详情页按 `ownerUserId` 识别本人作品,将左下角“作品改造”切换为“作品编辑”并恢复原草稿而不复制新作品的规则。
- [NEW_WORK_ENTRY_CONFIG_2026-05-01.md](./NEW_WORK_ENTRY_CONFIG_2026-05-01.md):记录新建作品入口开放状态、隐藏状态和展示文案统一收口到 `src/config/newWorkEntryConfig.ts` 的配置规则。
- [PUZZLE_APIMART_IMAGE_MODEL_ROUTING_2026-05-01.md](./PUZZLE_APIMART_IMAGE_MODEL_ROUTING_2026-05-01.md):记录拼图图片生成接入 APIMart `gpt-image-2``gemini-3.1-flash-image-preview`,以及画面描述框内模型切换与后端路由边界。
- [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md):冻结 SpacetimeDB 表结构变更约束、自动迁移可接受范围、冲突后的系统行为,以及保留旧数据的增量迁移流程;凡涉及 `spacetime publish`、表字段调整或 `migration.rs` 对齐时优先参考。
- [SPACETIMEDB_CLOUD_CONFIG_REMOVAL_2026-05-02.md](./SPACETIMEDB_CLOUD_CONFIG_REMOVAL_2026-05-02.md):记录旧云端 SpacetimeDB 配置、发布脚本和默认文档口径的移除结果,冻结后续仅使用本地或显式 `SERVER_URL` 的运维规则。
- [SPACETIMEDB_LOCAL_REPLICA_IDENTITY_MISMATCH_FIX_2026-04-30.md](./SPACETIMEDB_LOCAL_REPLICA_IDENTITY_MISMATCH_FIX_2026-04-30.md):记录本地 standalone 启动时报 `mismatched database identity` 的 root-dir/replica 数据残留根因、备份重建步骤和脚本诊断口径。
- [AUTH_SNAPSHOT_AND_MATCH3D_LOCAL_DEV_FIX_2026-05-01.md](./AUTH_SNAPSHOT_AND_MATCH3D_LOCAL_DEV_FIX_2026-05-01.md):记录 Maincloud `xushi-p4wfr` 挂起导致认证快照同步和抓大鹅创作失败的根因、认证同步非阻断修复、`/api/creation` Vite 代理补齐和本地 SpacetimeDB 可跑链路。
- [RPG_FOUNDATION_DRAFT_LLM_SEARCH_FALLBACK_2026-05-01.md](./RPG_FOUNDATION_DRAFT_LLM_SEARCH_FALLBACK_2026-05-01.md):记录 RPG foundation draft 分批 LLM 生成遇到 `ToolNotOpen` 或搜索增强超时时,按配置启用搜索并自动降级为无搜索重试的修复口径。
- [AUTH_SNAPSHOT_AND_MATCH3D_LOCAL_DEV_FIX_2026-05-01.md](./AUTH_SNAPSHOT_AND_MATCH3D_LOCAL_DEV_FIX_2026-05-01.md):记录远端库挂起导致认证快照同步和抓大鹅创作失败的根因、认证同步非阻断修复、`/api/creation` Vite 代理补齐和本地 SpacetimeDB 可跑链路。
- [LLM_MODEL_ROUTING_RPG_AND_CREATION_2026-04-30.md](./LLM_MODEL_ROUTING_RPG_AND_CREATION_2026-04-30.md):冻结 RPG 运行时剧情推理使用 `doubao-seed-character-251128``/chat/completions`,以及所有模板创作大模型推理使用 `deepseek-v3-2-251201``/responses`
- [PROFILE_INVITE_CODE_REGISTRATION_AND_ADMIN_2026-04-30.md](./PROFILE_INVITE_CODE_REGISTRATION_AND_ADMIN_2026-04-30.md):冻结邀请码从“我的 Tab 填写”迁到注册环节的前后端边界、`profile_invite_code.metadata_json` 表结构扩展、管理员邀请码虚拟主体和奖励规则。
- [MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md](./MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md):冻结抓大鹅 Match3D 首版 demo 的独立玩法域、表与 procedure、HTTP facade、前端即时反馈/后端权威确认协议,以及可并行开发包。
@@ -30,7 +26,7 @@
- [RPG_CREATION_RESULT_VIEW_BACKEND_TRUTH_MIGRATION_2026-04-28.md](./RPG_CREATION_RESULT_VIEW_BACKEND_TRUTH_MIGRATION_2026-04-28.md):冻结 RPG 创作结果页保存、Agent session/result preview 真相优先级和结果页入口裁决迁移到后端 result-view 的落地边界。
- [RPG_CREATION_PROFILE_GENERATION_BACKEND_MIGRATION_2026-04-28.md](./RPG_CREATION_PROFILE_GENERATION_BACKEND_MIGRATION_2026-04-28.md):记录 RPG 创作 profile 生成移除非浏览器 legacy AI 回退,统一通过 `server-rs``/api/runtime/custom-world/profile` 生成世界底稿。
- [CREATION_PUBLIC_GALLERY_AND_AGENT_RESTORE_GUARD_FIX_2026-04-28.md](./CREATION_PUBLIC_GALLERY_AND_AGENT_RESTORE_GUARD_FIX_2026-04-28.md):记录 RPG Agent 旧 URL 恢复指针必须有本机用户归属才读取受保护 session以及 Big Fish 公开广场读取失败按空广场降级的修复口径。
- [BIG_FISH_DRAFT_PROGRESS_AND_SESSION_TIMEOUT_GUARD_FIX_2026-04-28.md](./BIG_FISH_DRAFT_PROGRESS_AND_SESSION_TIMEOUT_GUARD_FIX_2026-04-28.md):记录大鱼吃小鱼草稿进度页从单步 compile 改为多阶段感知展示,以及大鱼会话读取在 Maincloud 抖动时增加短重试与超时语义收口的修复口径。
- [BIG_FISH_DRAFT_PROGRESS_AND_SESSION_TIMEOUT_GUARD_FIX_2026-04-28.md](./BIG_FISH_DRAFT_PROGRESS_AND_SESSION_TIMEOUT_GUARD_FIX_2026-04-28.md):记录大鱼吃小鱼草稿进度页从单步 compile 改为多阶段感知展示,以及大鱼会话读取在 SpacetimeDB 抖动时增加短重试与超时语义收口的修复口径。
- [BIG_FISH_PROMPT_MODULE_EXTRACTION_2026-04-28.md](./BIG_FISH_PROMPT_MODULE_EXTRACTION_2026-04-28.md):记录大鱼吃小鱼草稿生成、生图、动作三类提示词从业务脚本中抽离到独立 `prompt/big_fish.rs` 模块的边界与职责划分。
- [BIG_FISH_MAIN_IMAGE_TRANSPARENT_BACKGROUND_ALIGNMENT_2026-04-28.md](./BIG_FISH_MAIN_IMAGE_TRANSPARENT_BACKGROUND_ALIGNMENT_2026-04-28.md):记录大鱼吃小鱼等级主图与动作关键帧正式图在 Rust 后端复用 RPG 角色主图透明背景 alpha 后处理的对齐口径,并明确场地背景不走该处理。
- [PUZZLE_IMAGE_AND_FRONTEND_RULES_ALIGNMENT_2026-04-29.md](./PUZZLE_IMAGE_AND_FRONTEND_RULES_ALIGNMENT_2026-04-29.md):记录拼图生成图片回到 1:1运行时拖动、交换、合并与拆分由前端即时裁决以及移动端棋盘贴近屏幕边缘的落地边界。
@@ -38,7 +34,6 @@
- [PUZZLE_LEADERBOARD_FRONTEND_LEVEL_AND_RPG_COMING_SOON_2026-04-30.md](./PUZZLE_LEADERBOARD_FRONTEND_LEVEL_AND_RPG_COMING_SOON_2026-04-30.md):记录拼图第二关排行榜提交以前端当前关卡为准、不被 SpacetimeDB 旧 run 快照误杀,以及 RPG 创作入口改为敬请期待的落地边界。
- [PUZZLE_NEXT_LEVEL_AND_SIMILAR_WORK_HANDOFF_2026-04-30.md](./PUZZLE_NEXT_LEVEL_AND_SIMILAR_WORK_HANDOFF_2026-04-30.md):记录拼图通关后优先同作品下一关、无下一关时按 RPG/build 标签语义相似度返回三个候选作品,并在跨作品时只切换到候选作品第 1 张图、运行时关卡序号继续累进的落地规则。
- [PUZZLE_FAILURE_EXTENSION_AND_SAVE_ARCHIVE_2026-05-01.md](./PUZZLE_FAILURE_EXTENSION_AND_SAVE_ARCHIVE_2026-05-01.md):记录拼图失败后重新开始/付费续时,以及进入作品与过关后同步存档页投影的落地规则。
- [PUZZLE_RUNTIME_FIRST_EXIT_REMODEL_PROMPT_2026-05-02.md](./PUZZLE_RUNTIME_FIRST_EXIT_REMODEL_PROMPT_2026-05-02.md):记录拼图运行态首次点击左上返回时弹出作品改造引导,并复用现有拼图 remix 进入结果页改造草稿的交互边界。
- [PUZZLE_RUNTIME_TIMER_AND_PROPS_2026-04-29.md](./PUZZLE_RUNTIME_TIMER_AND_PROPS_2026-04-29.md)记录拼图关卡切割、倒计时、失败态和三个运行时道具的统一规则2026-05-01 起关卡切割与限时按第 1-10 关配置,并从第 11 关按第 5-10 关六关循环。
- [RPG_SCENE_ACT_PREVIEW_BOOTSTRAP_FIX_2026-04-30.md](./RPG_SCENE_ACT_PREVIEW_BOOTSTRAP_FIX_2026-04-30.md):记录编辑器幕预览卡在“正在载入这一幕”时的启动态根因,收口预览本地运行态装配与禁持久化首段 story 注入。
- [PUZZLE_RESULT_AUTOSAVE_AND_TAG_GATE_FIX_2026-04-28.md](./PUZZLE_RESULT_AUTOSAVE_AND_TAG_GATE_FIX_2026-04-28.md):记录拼图结果页名称与标签编辑自动保存、发布门槛统一到 `3~6` 标签,以及前端发布校验不再被旧 session blocker 卡死的修复口径。
@@ -51,7 +46,7 @@
- [SPACETIMEDB_TABLE_CATALOG.md](./SPACETIMEDB_TABLE_CATALOG.md):持续维护当前 SpacetimeDB 表目录,按领域说明每张表的作用、字段结构、索引和常用 `spacetime sql` 查询模板。
- [RPG_OPENING_SCENE_ACT_IMAGE_PRESENTATION_SYNC_2026-04-26.md](./RPG_OPENING_SCENE_ACT_IMAGE_PRESENTATION_SYNC_2026-04-26.md):记录开局场景与普通场景复用同一场景展示解析服务,修复列表幕缩略图和详情幕背景预览图片不一致的问题。
- [FRONTEND_FIRST_LOAD_PERFORMANCE_FIX_2026-04-26.md](./FRONTEND_FIRST_LOAD_PERFORMANCE_FIX_2026-04-26.md):记录网站启动后首次加载约三分钟的前端根因,收口 `RouteImageReadyGate` 首屏图片门控和 Vite dev server 无关文件监听范围。
- [RPG_WORK_DELETE_SPACETIMEDB_PROCEDURE_EXPORT_FIX_2026-04-25.md](./RPG_WORK_DELETE_SPACETIMEDB_PROCEDURE_EXPORT_FIX_2026-04-25.md):记录 RPG 作品删除时报 `No such procedure` 的根因,补齐 `delete_custom_world_agent_session` 在有效 SpacetimeDB 模块入口中的导出,并要求发布后核验 Maincloud schema。
- [RPG_WORK_DELETE_SPACETIMEDB_PROCEDURE_EXPORT_FIX_2026-04-25.md](./RPG_WORK_DELETE_SPACETIMEDB_PROCEDURE_EXPORT_FIX_2026-04-25.md):记录 RPG 作品删除时报 `No such procedure` 的根因,补齐 `delete_custom_world_agent_session` 在有效 SpacetimeDB 模块入口中的导出,并要求发布后核验 schema。
- [CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md](./CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md):冻结当前后端唯一落地口径,明确新功能以 `server-rs + Axum + SpacetimeDB` 为准,旧 `server-node` / Express / PostgreSQL 与 Go 方向只允许作为迁移参考。
- [RPG_DRAFT_GENERATION_CONTINUE_AND_ETA_FIX_2026-04-25.md](./RPG_DRAFT_GENERATION_CONTINUE_AND_ETA_FIX_2026-04-25.md):记录世界草稿生成失败/中断后进度不再误到 `100%`、主按钮改为“继续生成草稿”并复用已保存底稿续跑,以及按阶段耗时模型估算预计等待时间的修复口径。
- [RUNTIME_NPC_CHAT_LLM_MIGRATION_2026-04-25.md](./RUNTIME_NPC_CHAT_LLM_MIGRATION_2026-04-25.md):冻结运行时 NPC 聊天从 Rust 确定性兜底迁到 `platform-llm` 的边界,要求旧 Node 聊天提示词原样迁移,覆盖回复、建议、好感变化与限轮收束。

View File

@@ -48,4 +48,4 @@ Agent 路由保持原有 submit/finalize 分工:
3. `cargo test -p api-server runtime_chat`
4. `cargo test -p api-server creation_agent_llm_turn`
5. `node scripts/check-encoding.mjs docs/technical/RPG_AND_AGENT_CHAT_TRUE_SSE_STREAMING_2026-04-26.md server-rs/crates/api-server/src/runtime_chat.rs server-rs/crates/api-server/src/custom_world.rs server-rs/crates/api-server/src/big_fish.rs docs/technical/README.md`
6. 修改后端代码后,使用 `npm run api-server:maincloud` 重启后端。
6. 修改后端代码后,使用 `npm run api-server` 重启后端。

View File

@@ -10,7 +10,7 @@
2. `GET /api/runtime/custom-world-gallery`
3. 个人看板、浏览历史、存档等私有数据
其中 `custom-world-library` 通过 `api-server -> spacetime-client -> list_custom_world_profiles procedure` 读取当前用户作品。旧实现把每个作品的完整 `profile_payload_json` 一并返回给首页列表,而首页卡片只需要标题、摘要、封面、状态和计数字段。用户作品较多或 Maincloud 连接抖动时,这个 procedure 容易超过 `spacetime-client` 固定 `10s` 等待窗口,最终由 Axum 映射成 `502 Bad Gateway`,前端控制台显示 `SpacetimeDB procedure 调用超时`
其中 `custom-world-library` 通过 `api-server -> spacetime-client -> list_custom_world_profiles procedure` 读取当前用户作品。旧实现把每个作品的完整 `profile_payload_json` 一并返回给首页列表,而首页卡片只需要标题、摘要、封面、状态和计数字段。用户作品较多或 SpacetimeDB 连接抖动时,这个 procedure 容易超过 `spacetime-client` 固定 `10s` 等待窗口,最终由 Axum 映射成 `502 Bad Gateway`,前端控制台显示 `SpacetimeDB procedure 调用超时`
## 2. 修复口径
@@ -19,8 +19,8 @@
1. `list_custom_world_profiles` 仍保持旧 procedure 名称和返回 envelope避免本轮重新生成 bindings。
2. 列表返回的 `profile_payload_json` 改为轻量摘要 JSON只包含首页卡片和标签兜底需要的少量字段。
3. 单条详情、发布、下架、编辑继续使用完整 profile snapshot确保进入详情或结果页时仍有完整世界数据。
4. `spacetime-client` 的 procedure 等待窗口从硬编码 `10s` 改为可配置,Maincloud 默认使用更宽的窗口吸收连接冷启动与短时抖动。
5. Axum 的 `GET /api/runtime/custom-world-library` 首屏接口改走已有 `custom-world/works` 轻量读模型,并在用户点击详情/编辑时再调用 owner-only detail 接口取完整 profile避免 Maincloud wasm 尚未发布轻量 profile procedure 时首页继续命中重 procedure。
4. `spacetime-client` 的 procedure 等待窗口从硬编码 `10s` 改为可配置,用更宽的窗口吸收连接冷启动与短时抖动。
5. Axum 的 `GET /api/runtime/custom-world-library` 首屏接口改走已有 `custom-world/works` 轻量读模型,并在用户点击详情/编辑时再调用 owner-only detail 接口取完整 profile避免 wasm 尚未发布轻量 profile procedure 时首页继续命中重 procedure。
## 3. 轻量 profile JSON 字段
@@ -47,4 +47,4 @@
3. `cargo check -p spacetime-client` 通过。
4. `cargo check -p api-server` 通过。
5. `npm run check:encoding` 通过。
6. 修改后按项目约束使用 `npm run api-server:maincloud` 重启后端。
6. 修改后按项目约束使用 `npm run api-server` 重启后端。

View File

@@ -83,7 +83,7 @@
6. 修改后执行:
- Rust 相关测试。
- TypeScript 相关测试。
- `npm run api-server:maincloud`
- `npm run api-server`
## 5. 本次实现结果

View File

@@ -91,7 +91,7 @@ server-rs/crates/api-server/src/prompt/rpg/
1. `npm run check:encoding`
2. `npm run test -- src/services/ai.test.ts src/hooks/rpg-runtime-story/storyResponseOptions.test.ts`
3. `cargo check -p api-server`
4. `npm run api-server:maincloud`
4. `npm run api-server`
## 后续编辑约定

View File

@@ -81,7 +81,7 @@ npm run typecheck -- --pretty false
npm run check:encoding
```
局部测试、局部 ESLint、全量类型检查与编码检查均通过。后端代码未在本次任务中修改因此未执行 `npm run api-server:maincloud`
局部测试、局部 ESLint、全量类型检查与编码检查均通过。后端代码未在本次任务中修改因此未执行 `npm run api-server`
## 2026-04-27 第二轮复查修正
@@ -123,7 +123,7 @@ npm test -- --run src/data/sceneEncounterPreviews.test.ts src/hooks/rpg-runtime-
npx eslint src/data/sceneEncounterPreviews.ts src/data/sceneEncounterPreviews.test.ts src/services/customWorldSceneActRuntime.ts src/hooks/rpg-runtime-story/storyChoiceRuntime.ts src/hooks/rpg-runtime-story/storyChoiceRuntime.test.ts src/hooks/rpg-runtime-story/uiTypes.ts src/components/rpg-runtime-panels/RpgAdventurePanelOverlays.tsx
```
以上局部测试与局部 ESLint 已通过。后端代码未在本轮修改中触碰,因此不需要执行 `npm run api-server:maincloud`
以上局部测试与局部 ESLint 已通过。后端代码未在本轮修改中触碰,因此不需要执行 `npm run api-server`
## 2026-04-27 第三轮复查修正
@@ -149,7 +149,7 @@ npx eslint src/hooks/rpg-session/useRpgSessionBootstrap.ts src/hooks/useGameFlow
npm run typecheck -- --pretty false
```
以上局部测试、局部 ESLint 与全量类型检查已通过。后端代码未在本轮修改中触碰,因此仍不需要执行 `npm run api-server:maincloud`
以上局部测试、局部 ESLint 与全量类型检查已通过。后端代码未在本轮修改中触碰,因此仍不需要执行 `npm run api-server`
## 2026-04-27 第四轮复查修正
@@ -183,7 +183,7 @@ npm run typecheck -- --pretty false
npm run check:encoding
```
以上相关测试、局部 ESLint、全量类型检查与编码检查均通过。后端代码未在本轮修改中触碰因此未执行 `npm run api-server:maincloud`
以上相关测试、局部 ESLint、全量类型检查与编码检查均通过。后端代码未在本轮修改中触碰因此未执行 `npm run api-server`
## 2026-04-27 第五轮误导链路闭口
@@ -232,4 +232,4 @@ npx eslint src/hooks/rpg-session/useRpgSessionBootstrap.ts src/hooks/useGameFlow
npm run typecheck -- --pretty false
```
以上测试、ESLint 与类型检查已通过。后端代码未在本轮修改中触碰,因此仍不需要执行 `npm run api-server:maincloud`
以上测试、ESLint 与类型检查已通过。后端代码未在本轮修改中触碰,因此仍不需要执行 `npm run api-server`

View File

@@ -4,15 +4,15 @@
创作页或作品详情删除 RPG 作品时报 `No such procedure`
本次核对 Maincloud `xushi-p4wfr` schema 后确认:
本次核对 `xushi-p4wfr` schema 后确认:
1. 已发布 / 作品库 profile 删除依赖 `delete_custom_world_profile_and_return`
2. 草稿作品删除依赖 `delete_custom_world_agent_session`
3. 本地 Rust client 绑定里存在 `delete_custom_world_agent_session`,但 Maincloud schema 中没有该 procedure。
3. 本地 Rust client 绑定里存在 `delete_custom_world_agent_session`,但目标 schema 中没有该 procedure。
## 根因
`server-rs/crates/spacetime-module/src/custom_world/mod.rs` 中有一份草稿删除实现,但当前有效发布入口仍是 `server-rs/crates/spacetime-module/src/lib.rs` 中的 custom world 实现。`lib.rs` 未导出 `delete_custom_world_agent_session`,导致发布到 Maincloud 的模块 schema 缺少该 procedure。
`server-rs/crates/spacetime-module/src/custom_world/mod.rs` 中有一份草稿删除实现,但当前有效发布入口仍是 `server-rs/crates/spacetime-module/src/lib.rs` 中的 custom world 实现。`lib.rs` 未导出 `delete_custom_world_agent_session`,导致发布的模块 schema 缺少该 procedure。
## 落地口径
@@ -31,7 +31,7 @@
1. `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`
2. `npm run check:encoding`
3. `npm run spacetime:publish:maincloud`
4. 发布后用 `spacetime describe xushi-p4wfr --server maincloud --json` 确认 schema 包含:
3. 发布最新 SpacetimeDB wasm。
4. 发布后用 `spacetime describe xushi-p4wfr --server <目标服务> --json` 确认 schema 包含:
- `delete_custom_world_profile_and_return`
- `delete_custom_world_agent_session`

View File

@@ -112,9 +112,9 @@ npm run dev:rust:logs -- --follow
2. 仅供测试断言使用的辅助函数使用 `#[cfg(test)]` 限定,避免进入 `cargo run -p api-server` 的普通二进制编译。
3. 已无调用入口且无迁移价值的映射函数直接删除;如果后续新增同类 SpacetimeDB 记录映射,再按实际调用路径补回,避免提前保留死代码。
Maincloud API 重启补充:
api-server 单独重启补充:
1. `npm run api-server:maincloud` 会先读取 `.env``.env.local``GENARRATIVE_SPACETIME_MAINCLOUD_*` 映射为 `api-server` 使用 `GENARRATIVE_SPACETIME_*`,再运行 `cargo run -p api-server --manifest-path server-rs/Cargo.toml`
1. `npm run api-server` 会先读取 `.env``.env.local`,使用 `GENARRATIVE_SPACETIME_*` 启动 `cargo run -p api-server --manifest-path server-rs/Cargo.toml`
2. Windows 下脚本会尽力停止本仓库 `server-rs/target/debug/api-server.exe` 对应的旧进程,避免 cargo 重新编译时 exe 被占用。
3. 旧进程已经退出或清理过程中出现瞬时等待失败时,不应阻断新的 `api-server` 启动;脚本只记录清理失败并继续启动。
@@ -191,7 +191,7 @@ cd build/<timestamp>
./stop.sh
```
如果后续通过 Jenkins 的部署脚本把发布包覆盖到固定部署目录,部署阶段默认只替换 `web/``api-server``spacetime_module.wasm``migration-bootstrap-secret.txt``scripts/``.env*``start.sh``stop.sh``web-server.mjs``README.md` 等发布产物;后台管理前端位于 `web/admin/`,随 `web/` 一并覆盖。文件产物使用普通复制,`web/``scripts/` 等目录产物递归复制,不会删除部署目录中的 `.spacetimedb/``logs/``run/``deploy-state/``database-migrations/` 这类运行态目录。Jenkins 覆盖 `.env.local` 时会保留目标部署目录已有的 `GENARRATIVE_SPACETIME_TOKEN` / `GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN`,避免后台表统计在部署后失去读取 private 表所需的 owner 身份。
如果后续通过 Jenkins 的部署脚本把发布包覆盖到固定部署目录,部署阶段默认只替换 `web/``api-server``spacetime_module.wasm``migration-bootstrap-secret.txt``scripts/``.env*``start.sh``stop.sh``web-server.mjs``README.md` 等发布产物;后台管理前端位于 `web/admin/`,随 `web/` 一并覆盖。文件产物使用普通复制,`web/``scripts/` 等目录产物递归复制,不会删除部署目录中的 `.spacetimedb/``logs/``run/``deploy-state/``database-migrations/` 这类运行态目录。Jenkins 覆盖 `.env.local` 时会保留目标部署目录已有的 `GENARRATIVE_SPACETIME_TOKEN`,避免后台表统计在部署后失去读取 private 表所需的 owner 身份。
安全边界:

View File

@@ -0,0 +1,42 @@
# SpacetimeDB 云端配置移除记录
日期:`2026-05-02`
## 1. 目标
当前项目不再使用旧云端 SpacetimeDB 目标仓库内不再保留云端专用配置、脚本入口和文档默认口径。后续开发、迁移、Jenkins 流水线与后台验证均以本地或显式传入的 SpacetimeDB 服务为准。
## 2. 入口调整
1. 根工程后端单独启动入口统一为:
```bash
npm run api-server
```
2. 该入口读取 `.env``.env.local` 与当前进程环境中的 `GENARRATIVE_SPACETIME_*`,默认服务地址回落到 `http://127.0.0.1:3101`
3. 已移除旧云端发布入口和脚本。SpacetimeDB 模块发布继续通过本地联调脚本、发布包 `start.sh` 或显式 `spacetime publish --server <server-url>` 执行。
## 3. 环境变量口径
`api-server`、迁移脚本和 Jenkins 部署脚本只使用以下运行变量:
```text
GENARRATIVE_SPACETIME_SERVER_URL
GENARRATIVE_SPACETIME_DATABASE
GENARRATIVE_SPACETIME_TOKEN
```
旧云端专用变量不再作为兼容回退读取。需要连接其它 SpacetimeDB 服务时,必须显式设置 `GENARRATIVE_SPACETIME_SERVER_URL` 或在脚本参数中传入 `--server-url`
## 4. 迁移脚本口径
1. `scripts/spacetime-migration-common.mjs` 默认 server 为本地 `dev`,解析到 `http://127.0.0.1:3101`
2. 授权、撤销、导出等 CLI 调用会显式传 `-s`,避免落回机器上的 SpacetimeDB CLI 默认服务。
3. Jenkins 数据库导入导出流水线默认 `SERVER=dev`,需要操作其它目标时必须显式填写 `SERVER_URL`
## 5. 后续约束
1. 新增 SpacetimeDB 运维脚本时,不允许把云端服务写成默认值。
2. 文档中的验证命令统一使用 `npm run api-server`
3. 如果某次任务需要连接非本地 SpacetimeDB必须在文档和验证记录中写清楚实际 `SERVER_URL`、数据库名和 root-dir。

View File

@@ -13,7 +13,7 @@ SpacetimeDB reducer 必须保持确定性,不能访问文件系统和网络。
procedure 不再访问 HTTP 文件桥,也不接收部署机本地文件路径。这样可以避开 SpacetimeDB 对 private/special-purpose 地址的 HTTP 访问限制,并避免把 private 表内容通过临时 HTTP 服务转发。
SpacetimeDB Wasm 运行环境不支持 `std::time::SystemTime::now()`procedure 或 reducer 内需要当前时间时必须使用 `ctx.timestamp`。如果共享 crate 同时服务前端/本地纯逻辑与 SpacetimeDB 模块,应提供 `*_at(now_ms)` 或显式时间参数版本SpacetimeDB 模块只调用注入时间的函数,避免发布后在 maincloud 触发 `time not implemented on this platform` panic。
SpacetimeDB Wasm 运行环境不支持 `std::time::SystemTime::now()`procedure 或 reducer 内需要当前时间时必须使用 `ctx.timestamp`。如果共享 crate 同时服务前端/本地纯逻辑与 SpacetimeDB 模块,应提供 `*_at(now_ms)` 或显式时间参数版本SpacetimeDB 模块只调用注入时间的函数,避免发布后触发 `time not implemented on this platform` panic。
`spacetime login show --token` 输出的是 CLI 登录 token不是 HTTP `/v1/database/.../call` 所需的数据库连接 token。导入脚本如果没有显式传 `--token`,会自动调用 `POST /v1/identity` 获取 Web API token迁移时不要把 CLI token 传给 `--token`
@@ -41,17 +41,13 @@ SpacetimeDB Wasm 运行环境不支持 `std::time::SystemTime::now()`procedur
运维流程:
```bash
npm run spacetime:publish:maincloud -- --database <database>
# 控制台会输出:
# [spacetime:maincloud] 迁移引导密钥: <本次发布随机密钥>
```
本地开发发布时,`npm run dev:rust` 会在发布模块前输出本次随机生成的迁移引导密钥。发布包部署时,`npm run deploy:rust:remote` 会把同一份密钥写入发布包根目录的 `migration-bootstrap-secret.txt`,目标服务器执行 `./start.sh` 发布 wasm 时也会再次显示该密钥。
发布完成后,在同一台机器上用当前 `spacetime login` 身份授权操作员:
```bash
node scripts/spacetime-authorize-migration-operator.mjs \
--server maincloud \
--server dev \
--database xushi-p4wfr \
--bootstrap-secret <本次发布随机密钥> \
--operator-identity <identity-hex> \
@@ -62,7 +58,7 @@ node scripts/spacetime-authorize-migration-operator.mjs \
```bash
node scripts/spacetime-revoke-migration-operator.mjs \
--server maincloud \
--server dev \
--database xushi-p4wfr \
--operator-identity <identity-hex>
```
@@ -71,9 +67,8 @@ node scripts/spacetime-revoke-migration-operator.mjs \
### 发布脚本密钥行为
当前所有会构建或发布 `spacetime-module` 的脚本默认都会生成并显示迁移引导密钥:
当前会构建或发布 `spacetime-module` 的脚本默认都会生成并显示迁移引导密钥:
- `npm run spacetime:publish:maincloud`:在本机 `cargo build` 前生成密钥,控制台输出 `[spacetime:maincloud] 迁移引导密钥: ...`
- `npm run dev:rust`:在本地 `spacetime publish --module-path` 前生成密钥,控制台输出 `[dev:rust] 迁移引导密钥: ...`
- `npm run deploy:rust:remote`:在构建发布包 wasm 前生成密钥,控制台输出 `[deploy:rust] 迁移引导密钥: ...`,并把同一份密钥写入发布包根目录的 `migration-bootstrap-secret.txt`。服务器执行 `./start.sh` 发布 wasm 时也会再次显示该文件里的密钥。
@@ -145,11 +140,11 @@ Node 导入脚本默认在文件超过 `524288` bytes 时使用分片导入;
### 发布冲突自动迁移
`npm run spacetime:publish:maincloud` 默认采用冲突感知发布:
Ubuntu 发布包的 `start.sh` 默认采用冲突感知发布:
1. 先不清库发布新 wasm。
2. 如果发布成功,流程结束。
3. 如果发布失败且输出可判定为 schema 冲突,脚本自动导出旧库迁移 JSON 到 `tmp/spacetime-migrations/maincloud/<database>/<timestamp>.json`
3. 如果发布失败且输出可判定为 schema 冲突,脚本自动导出旧库迁移 JSON 到 `database-migrations/<database>/<timestamp>.json``GENARRATIVE_SPACETIME_MIGRATION_DIR` 指定目录
4. 导出成功后执行清库发布新 wasm。
5. 新 wasm 发布成功后,把第 3 步导出的 JSON 自动导入回灌。
@@ -159,15 +154,11 @@ SpacetimeDB 2.1 对 schema 冲突的报错文案可能不再包含 `schema confl
任一阶段失败都会中止流程,并保留已经导出的迁移 JSON。非 schema 冲突的发布失败不会进入迁移流程。
```bash
npm run spacetime:publish:maincloud -- --database xushi-p4wfr
```
可选参数:
- `--no-migrate-on-conflict`:禁用冲突自动迁移,只保留原始发布失败。
- `--migration-dir <dir>`:指定迁移 JSON 输出目录。
- `--clear-database`:显式清库发布;该模式代表人工确认清库,不触发自动迁移。
- `GENARRATIVE_SPACETIME_MIGRATE_ON_CONFLICT=false`:禁用冲突自动迁移,只保留原始发布失败。
- `GENARRATIVE_SPACETIME_MIGRATION_DIR=<dir>`:指定迁移 JSON 输出目录。
- `./start.sh --clear-database`:显式清库发布;该模式代表人工确认清库,不触发自动迁移。
冲突自动迁移需要发布脚本本次生成的 `GENARRATIVE_SPACETIME_MIGRATION_BOOTSTRAP_SECRET`。因此不要和 `--no-migration-bootstrap-secret` 同时使用。
@@ -237,7 +228,7 @@ node scripts/spacetime-export-migration-json.mjs \
```bash
node scripts/spacetime-authorize-migration-operator.mjs \
--server maincloud \
--server dev \
--database xushi-p4wfr \
--bootstrap-secret <服务器目标库发布时输出的随机密钥> \
--operator-identity <服务器 spacetime login show 中的 identity> \
@@ -248,7 +239,7 @@ node scripts/spacetime-authorize-migration-operator.mjs \
```bash
node scripts/spacetime-import-migration-json.mjs \
--server maincloud \
--server dev \
--database xushi-p4wfr \
--bootstrap-secret <服务器目标库发布时输出的随机密钥> \
--in tmp/spacetime-migrations/source-2026-04-27.json
@@ -258,7 +249,7 @@ node scripts/spacetime-import-migration-json.mjs \
```bash
node scripts/spacetime-import-migration-json.mjs \
--server maincloud \
--server dev \
--database xushi-p4wfr \
--bootstrap-secret <服务器目标库发布时输出的随机密钥> \
--in tmp/spacetime-migrations/source-2026-04-27.json \
@@ -298,7 +289,7 @@ node scripts/spacetime-export-migration-json.mjs \
--include ai_task,ai_task_stage,ai_text_chunk,ai_result_reference
```
`--server` 支持 `dev``local``maincloud`,也可以直接传 SpacetimeDB 服务器 URL。导出、授权、撤销默认走 `spacetime call`,使用当前机器的 CLI 登录态;导入默认走 Web API request body避免大 JSON 触发命令行长度限制。数据库名可通过 `--database``GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE``GENARRATIVE_SPACETIME_DATABASE` 提供。
`--server` 支持 `dev``local`,也可以直接传 SpacetimeDB 服务器 URL。导出、授权、撤销默认走 `spacetime call`,使用当前机器的 CLI 登录态;导入默认走 Web API request body避免大 JSON 触发命令行长度限制。数据库名可通过 `--database``GENARRATIVE_SPACETIME_DATABASE` 提供。
授权脚本额外支持:
@@ -319,7 +310,7 @@ node scripts/spacetime-export-migration-json.mjs \
- 拼图:`puzzle_agent_session``puzzle_agent_message``puzzle_work_profile``puzzle_runtime_run`
- 大鱼:`big_fish_creation_session``big_fish_agent_message``big_fish_asset_slot`
`big_fish_runtime_run` 当前运行态已由前端本地运行服务承接,不再加入迁移白名单;但 maincloud 旧库仍可能存在该表。为避免热升级被 “Removing the table big_fish_runtime_run requires a manual migration” 阻断,模块发布期可以保留兼容空壳表,后续确认旧数据可丢弃后再走正式删除表迁移。
`big_fish_runtime_run` 当前运行态已由前端本地运行服务承接,不再加入迁移白名单;但旧库仍可能存在该表。为避免热升级被 “Removing the table big_fish_runtime_run requires a manual migration” 阻断,模块发布期可以保留兼容空壳表,后续确认旧数据可丢弃后再走正式删除表迁移。
后续新增 SpacetimeDB 表时,必须同步把表加入迁移白名单与本文档。

View File

@@ -16,7 +16,7 @@ error starting database: failed to init replica 1 for <new-database-identity>: m
2. `replica 1` 的持久化数据仍带有旧库 `c20037fcfaac4e5c4b1f492f026a4f6119a98f56319b77f21ef021ededf8b7ae`
3. SpacetimeDB 因同一个副本目录中 identity 不一致而拒绝继续启动。
这不是 Rust 编译错误,也不是 `api-server:maincloud` 的 token 错误。只要错误来自 `server-rs/.spacetimedb/local/.../spacetime-standalone.log`,优先按本地 root-dir 数据目录污染处理。
这不是 Rust 编译错误,也不是 `api-server` 的 token 错误。只要错误来自 `server-rs/.spacetimedb/local/.../spacetime-standalone.log`,优先按本地 root-dir 数据目录污染处理。
## 2. 根因
@@ -37,7 +37,7 @@ server-rs/.spacetimedb/local
1. 不在脚本里默认删除 `.spacetimedb` 数据,避免误删本地开发数据。
2. 如果只是本地开发库且数据可丢弃,优先备份后重建 `data` 目录。
3. 如果数据必须保留,不要清理目录;应改回创建旧库时使用的 database/root-dir或先导出迁移数据。
4. Maincloud 发布与本地 standalone root-dir 是两条链路;不要通过切回 `server-node` 或 PostgreSQL 绕过。
4. 本地 standalone root-dir 与其它部署目标是两条链路;不要通过切回 `server-node` 或 PostgreSQL 绕过。
## 4. 本地可丢弃数据时的修复
@@ -77,7 +77,7 @@ npm run dev:rust
1. 用旧库对应的 database/root-dir 重新启动。
2. 使用迁移导出脚本导出旧数据,再清理本地 root-dir 并导入到新库。
3. 如目标其实是 Maincloud改用 `npm run api-server:maincloud` 连接云端,避免误启动本地 standalone。
3. 如目标其实是其它已运行的 SpacetimeDB 服务,改用 `GENARRATIVE_SPACETIME_SERVER_URL` 指向该服务,避免误启动本地 standalone。
## 6. 脚本诊断

View File

@@ -1,63 +0,0 @@
# SpacetimeDB Maincloud 发布与 api-server 适配方案
## 目标
新增一条明确的 npm 命令链,用于把 `server-rs/crates/spacetime-module` 发布到 SpacetimeDB Maincloud并让 `api-server` 可以使用同一套 Maincloud 数据库配置启动。
## 环境变量约定
Maincloud 发布不复用本地 `spacetime.local.json`,避免误把本地开发库名发布到云端。需要显式提供:
| 变量 | 用途 |
| -------------------------------------------- | ------------------------------------------------------------ |
| `GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE` | Maincloud 数据库名,发布脚本优先读取 |
| `GENARRATIVE_SPACETIME_MAINCLOUD_SERVER_URL` | Maincloud 服务地址,默认 `https://maincloud.spacetimedb.com` |
| `GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN` | `api-server` 连接 Maincloud 时使用的 token |
兼容 `api-server` 现有变量:
| 变量 | 用途 |
| ---------------------------------- | --------------------------- |
| `GENARRATIVE_SPACETIME_SERVER_URL` | `api-server` 实际连接地址 |
| `GENARRATIVE_SPACETIME_DATABASE` | `api-server` 实际连接数据库 |
| `GENARRATIVE_SPACETIME_TOKEN` | `api-server` 实际连接 token |
## npm 命令
```bash
npm run spacetime:publish:maincloud
```
执行内容:
1. 使用 `cargo build -p spacetime-module --target wasm32-unknown-unknown --release` 构建 wasm。
2. 使用 `spacetime publish <database> --server maincloud --bin-path <wasm> --yes` 发布到 Maincloud。
3. 发布前输出目标数据库名和 server便于在 Jenkins 或手工日志中确认实际发布目标。
4. 输出 `api-server` 需要的 Maincloud 环境变量,便于部署进程复用。
如需 schema 冲突时清库发布:
```bash
npm run spacetime:publish:maincloud -- --clear-database
```
## api-server 启动
```bash
npm run api-server:maincloud
```
执行内容:
1.`.env``.env.local` 读取默认环境。
2.`GENARRATIVE_SPACETIME_MAINCLOUD_*` 映射为 `api-server` 已支持的 `GENARRATIVE_SPACETIME_*`
3. 在 Windows 启动前检查 `server-rs/target/debug/api-server.exe` 对应的旧进程;如果旧进程仍在运行,先停止它,避免 Rust 编译阶段覆盖 exe 时出现 `failed to remove file ... 拒绝访问。 (os error 5)`
4. 启动 `cargo run -p api-server --manifest-path server-rs/Cargo.toml`
## 设计约束
- Maincloud 数据库名必须显式配置,不能默认读取本地 `spacetime.local.json`
- Maincloud 数据库名必须匹配 `^[a-z0-9]+(-[a-z0-9]+)*$`,只能使用小写字母、数字,并用单个短横线分隔;否则 `spacetime publish` 会报 `invalid characters in database name`
- 发布脚本只处理 SpacetimeDB 模块发布,不启动本地 SpacetimeDB。
- `api-server` 继续通过 `SpacetimeClientConfig``server_url / database / token` 连接数据库,不在前端增加逻辑。
- Windows 进程清理只能匹配本仓库 `server-rs/target/debug/api-server.exe` 的完整路径,不能按进程名泛化清理,避免影响其他 Rust 服务。

View File

@@ -20,7 +20,7 @@ SpacetimeDB 的数据库更新权限绑定到创建或被授权的身份。只
1. 部署机上执行 `start.sh` 的用户切换过 `spacetime login` 身份。
2. 固定部署目录保留了旧 `.spacetimedb/`,但当前 CLI 身份不是旧数据库创建者。
3. `GENARRATIVE_SPACETIME_SERVER_URL` 指向 Maincloud,而当前 CLI 身份不是该 Maincloud 数据库的所有者或授权成员。
3. `GENARRATIVE_SPACETIME_SERVER_URL` 指向其它 SpacetimeDB 服务,而当前 CLI 身份不是该数据库的所有者或授权成员。
4. `.env.local` 中的 `GENARRATIVE_SPACETIME_DATABASE` 指向了另一个环境的数据库名或数据库 identity。
## 3. 落地修复
@@ -62,7 +62,7 @@ mv .spacetimedb ".spacetimedb.backup.$(date +%Y%m%d-%H%M%S)"
2. 找到创建该数据库的 SpacetimeDB 身份。
3. 用该身份对应的 CLI root 执行发布,或在 SpacetimeDB 侧补授权后再发布。
如果目标是 Maincloud
如果目标是其它 SpacetimeDB 服务
1. 执行 `spacetime login show` 确认当前身份。
2. 确认该身份对 `GENARRATIVE_SPACETIME_DATABASE` 有更新权限。