Merge branch 'master' into codex/ddd
This commit is contained in:
@@ -44,8 +44,8 @@ spacetime generate --lang typescript|csharp|rust|unrealcpp --out-dir ./bindings
|
||||
### Publishing & Deployment
|
||||
|
||||
```bash
|
||||
# Publish to Maincloud (default)
|
||||
spacetime publish my-database --yes
|
||||
# Publish to an explicit server
|
||||
spacetime publish my-database --server http://127.0.0.1:3101 --yes
|
||||
|
||||
# Publish to local server
|
||||
spacetime publish my-database --server local --yes
|
||||
@@ -133,8 +133,8 @@ spacetime logout
|
||||
|
||||
| Name | URL | Description |
|
||||
|------|-----|-------------|
|
||||
| `maincloud` | `https://maincloud.spacetimedb.com` | Production cloud (default) |
|
||||
| `local` | `http://127.0.0.1:3000` | Local development server |
|
||||
| `dev` | `http://127.0.0.1:3101` | Genarrative local development server |
|
||||
|
||||
## Common Workflows
|
||||
|
||||
@@ -224,6 +224,6 @@ rustup target add wasm32-unknown-unknown
|
||||
## Notes
|
||||
|
||||
- Many commands are marked UNSTABLE and may change
|
||||
- Default server is `maincloud` unless configured otherwise
|
||||
- Genarrative scripts should pass `--server` or `--server-url` explicitly instead of relying on the CLI default
|
||||
- Use `--yes` flag in scripts to avoid interactive prompts
|
||||
- Dev mode watches files and auto-rebuilds on changes
|
||||
|
||||
@@ -119,6 +119,11 @@ RPG_LLM_WEB_SEARCH_ENABLED="true"
|
||||
DASHSCOPE_BASE_URL="https://dashscope.aliyuncs.com/api/v1"
|
||||
DASHSCOPE_API_KEY="YOUR_DASHSCOPE_API_KEY"
|
||||
|
||||
# Server-side APIMart image generation config for optional puzzle image models.
|
||||
APIMART_BASE_URL="https://api.apimart.ai/v1"
|
||||
APIMART_API_KEY="YOUR_APIMART_API_KEY"
|
||||
APIMART_IMAGE_REQUEST_TIMEOUT_MS="180000"
|
||||
|
||||
# 阿里云 OSS 配置。
|
||||
# Rust `server-rs` 的 `api-server` 会优先从 `.env` / `.env.local` 读取这些变量,
|
||||
# 用于签发浏览器 PostObject 直传票据,并保持 `/generated-*` 旧路径习惯。
|
||||
|
||||
+1
-5
@@ -54,11 +54,7 @@ GENARRATIVE_SPACETIME_SERVER_URL="http://127.0.0.1:3101"
|
||||
GENARRATIVE_SPACETIME_DATABASE="xushi-p4wfr"
|
||||
GENARRATIVE_SPACETIME_TOKEN=""
|
||||
|
||||
GENARRATIVE_SPACETIME_MAINCLOUD_SERVER_URL="https://maincloud.spacetimedb.com"
|
||||
GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE="xushi-p4wfr"
|
||||
GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN=""
|
||||
|
||||
# admin
|
||||
GENARRATIVE_ADMIN_USERNAME=admin
|
||||
GENARRATIVE_ADMIN_PASSWORD=123456
|
||||
ADMIN_API_TARGET=http://127.0.0.1:8082
|
||||
ADMIN_API_TARGET=http://127.0.0.1:8082
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
- 后端路线固定为 `server-rs + Axum + SpacetimeDB`。旧 `server-node`、Express、PostgreSQL 不再作为兼容目标;历史实现只能作为迁移参考,若旧文档与 DDD 约束冲突,先修正文档和方案再编码。
|
||||
- DDD 分层边界按总纲执行:领域规则沉到 `module-*`,SpacetimeDB 表和事务编排留在 `spacetime-module`,后端访问 SpacetimeDB 统一经 `spacetime-client` facade,HTTP/SSE/BFF 留在 `api-server`,外部副作用留在 `platform-*`,前后端 DTO 留在 `shared-contracts`。
|
||||
- 前端只做表现、交互和临时 UI 状态,不承接正式业务真相,不绕过后端投影或后端 API 直接实现业务规则。
|
||||
- 修改后端代码后,按对应 DDD 文档中的验收命令执行测试;涉及 API smoke 时继续使用 `npm run api-server:maincloud` 验证并确认 `/healthz`。
|
||||
- 修改后端代码后,按对应 DDD 文档中的验收命令执行测试;涉及 API smoke 时使用 `npm run api-server` 重新拉起后端并执行相应自动测试,同时确认 `/healthz`。
|
||||
- 凡是涉及 SpacetimeDB 的设计、实现、脚本、调试、前端绑定接入,统一显式使用以下 skill 作为执行依据:
|
||||
- [$spacetimedb-cli](.codex\\skills\\spacetimedb-cli\\SKILL.md)
|
||||
- [$spacetimedb-rust](.codex\\skills\\spacetimedb-rust\\SKILL.md)
|
||||
@@ -36,6 +36,8 @@
|
||||
- 涉及 `crates/spacetime-module` 的表、reducer、view、Rust API 使用时,按 `spacetimedb-rust` 与 `spacetimedb-concepts` 执行。
|
||||
- 涉及前端或 Node 侧的 SpacetimeDB TypeScript SDK、订阅、绑定使用时,按 `spacetimedb-typescript` 与 `spacetimedb-concepts` 执行。
|
||||
- 若仓库内旧实现或旧文档与这些 skill 冲突,先修正文档和方案,再继续编码。
|
||||
- 修改后端代码后,必须使用 `npm run api-server` 自动重新运行后端,并执行相应自动测试;不要再使用旧的后端重启命令。
|
||||
- 数据库表结构更改后,需要对齐migration.rs
|
||||
|
||||
## 文档图谱
|
||||
|
||||
|
||||
@@ -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. 最小验收标准
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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. 一句话总结
|
||||
|
||||
|
||||
@@ -493,12 +493,15 @@ interface CustomWorldCoverProfile {
|
||||
第一版必须有:
|
||||
|
||||
1. `进入世界`
|
||||
2. `删除作品`
|
||||
|
||||
可选:
|
||||
|
||||
1. `查看作品`
|
||||
2. `基于此作品继续创作`
|
||||
|
||||
`删除作品` 必须放在已发布卡片主操作的左侧,并在创作页内弹出二次确认面板后再执行删除。
|
||||
|
||||
第一版不强制做“基于已发布作品继续创作”,避免先把发布后再开草稿链带复杂。
|
||||
|
||||
---
|
||||
@@ -884,7 +887,7 @@ type SelectionStage =
|
||||
|
||||
1. 不做完整 Agent 工作区
|
||||
2. 不做世界底稿生成
|
||||
3. 不做作品删除确认流
|
||||
3. 不做独立的作品删除管理后台,删除确认统一收口在创作页内完成
|
||||
4. 不做作品搜索排序高级功能
|
||||
5. 不做发布世界管理后台
|
||||
6. 不做已发布作品的二次派生创作
|
||||
@@ -901,9 +904,10 @@ type SelectionStage =
|
||||
2. 创作页面能同时展示草稿和已发布作品。
|
||||
3. 草稿作品可以继续创作。
|
||||
4. 已发布作品可以进入世界。
|
||||
5. 新建作品入口可以正确创建 Agent session 并跳转到创作工作区。
|
||||
6. 页面在移动端首屏可用,信息层级清楚。
|
||||
7. 草稿与已发布作品都通过后端聚合接口返回,前端不自己拼数据来源。
|
||||
5. 已发布作品卡的删除按钮位于主操作左侧,点击后先弹出创作页内的二次确认面板。
|
||||
6. 新建作品入口可以正确创建 Agent session 并跳转到创作工作区。
|
||||
7. 页面在移动端首屏可用,信息层级清楚。
|
||||
8. 草稿与已发布作品都通过后端聚合接口返回,前端不自己拼数据来源。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -753,7 +753,7 @@ RPG 运行时链:
|
||||
|
||||
这些脚本不直接参与玩法,但直接支撑开发、发布、绑定和检查:
|
||||
|
||||
### `scripts/api-server-maincloud.mjs`
|
||||
### `scripts/api-server-dev.mjs`
|
||||
|
||||
职责:
|
||||
|
||||
|
||||
@@ -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. 后续扩展边界
|
||||
|
||||
|
||||
@@ -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. 认证快照同步失败会影响进程重启后的远端恢复完整性,需要在目标库恢复后重新完成一次成功同步。
|
||||
|
||||
@@ -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. 用户打开草稿页时碰到短暂断链,不再被立即判定成稳定的坏网关故障。
|
||||
|
||||
## 落地范围
|
||||
|
||||
@@ -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`。
|
||||
@@ -91,7 +91,7 @@ Genarrative-Database-Import
|
||||
|
||||
## 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`。
|
||||
@@ -107,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. 文件清单
|
||||
|
||||
|
||||
@@ -76,4 +76,4 @@ Responses 非流式解析优先读取 `output_text`,再兼容 `output[].conten
|
||||
3. `platform-llm` 单测覆盖 Responses 非流式、Responses SSE、Responses web_search tools 请求体。
|
||||
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:maincloud` 重新启动后端,并执行相应自动测试。
|
||||
6. 修改后按项目约束使用 `npm run api-server` 重新启动后端,并执行相应自动测试。
|
||||
|
||||
@@ -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. 文档目标
|
||||
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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。
|
||||
|
||||
@@ -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 联调链路单独排查。
|
||||
|
||||
@@ -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. 后续接入点
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# 新建作品入口配置说明 2026-05-01
|
||||
|
||||
## 背景
|
||||
|
||||
创作中心顶部“新建作品”入口和平台创作类型弹层都依赖同一组玩法模板。此前入口开放状态、隐藏状态和中文文案集中写在 `src/components/platform-entry/platformEntryCreationTypes.ts` 与入口组件中,后续切换玩法开放节奏时容易出现多个入口不一致。
|
||||
|
||||
## 落地规则
|
||||
|
||||
1. 新建作品入口配置统一放在 `src/config/newWorkEntryConfig.ts`。
|
||||
2. `visible` 控制玩法是否展示在新建作品入口和创作类型弹层中。
|
||||
3. `open` 控制玩法是否允许点击创建;`open: false` 时入口保持展示但禁用。
|
||||
4. `title`、`subtitle`、`badge` 控制玩法卡片文案。
|
||||
5. `startCard` 控制创作中心顶部新建作品模块的标题、辅助文案和移动端角标文案。
|
||||
6. `typeModal` 控制平台创作类型弹层标题和描述。
|
||||
7. 入口排序仍遵循“可创建玩法在前,未开放玩法在后”;同组内部沿用配置顺序。
|
||||
|
||||
## 当前状态
|
||||
|
||||
| 玩法 | 展示 | 开放 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| 角色扮演 | 是 | 是 | 点击后进入 RPG Agent 共创工作台 |
|
||||
| 大鱼吃小鱼 | 否 | 是 | 功能仍保留,不在新建作品入口展示 |
|
||||
| 拼图 | 是 | 是 | 点击后进入拼图 Agent 共创工作台 |
|
||||
| 抓大鹅 | 是 | 是 | 点击后进入抓大鹅 Agent 共创工作台 |
|
||||
| AIRP | 是 | 否 | 保留入口,显示敬请期待 |
|
||||
| 视觉小说 | 是 | 否 | 保留入口,显示敬请期待 |
|
||||
|
||||
## 验收
|
||||
|
||||
1. 修改 `src/config/newWorkEntryConfig.ts` 后,创作中心顶部卡带和平台创作类型弹层应同步变化。
|
||||
2. 隐藏玩法不触发入口预加载,也不出现在新建作品入口中。
|
||||
3. 未开放玩法点击态保持禁用,不应进入鉴权或创建会话链路。
|
||||
4. 已开放玩法点击后必须进入对应创建链路;若用户未登录,先走登录保护。
|
||||
@@ -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`。
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# 公开作品详情页自有作品编辑分流
|
||||
|
||||
更新时间:`2026-05-02`
|
||||
|
||||
## 背景
|
||||
|
||||
平台统一作品详情页左下角一直使用“作品改造”动作。这个动作适合打开其他作者作品时复制一份新草稿,但当详情页展示的是当前登录用户自己的作品时,继续复制会产生一份新的自己的作品,和用户预期的“编辑原作品”不一致。
|
||||
|
||||
## 落地规则
|
||||
|
||||
1. 作品详情页以 `ownerUserId === 当前登录用户 id` 判断作品归属。
|
||||
2. 非本人作品保持“作品改造”,点击后继续走现有 remix / 复制草稿链路。
|
||||
3. 本人作品把左下角按钮显示为“作品编辑”,点击后进入该作品绑定的原草稿或结果编辑页。
|
||||
4. 本人作品编辑不调用 remix 接口,不创建新的同款作品。
|
||||
5. 如果本人作品缺少可恢复的草稿会话,只展示可定位错误,不静默复制。
|
||||
|
||||
## 分玩法入口
|
||||
|
||||
1. RPG:复用已保存作品编辑入口,直接打开当前 profile 的结果编辑页。
|
||||
2. 拼图:优先使用当前详情项的 `sourceSessionId` 恢复原拼图草稿。
|
||||
3. 大鱼吃小鱼:使用公开作品的 `sourceSessionId` 恢复原玩法草稿。
|
||||
4. 抓大鹅:保留并传递 `sourceSessionId`,恢复原创作会话后进入结果页。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 登录用户打开自己的公开作品详情时,左下角按钮为“作品编辑”。
|
||||
2. 点击“作品编辑”不会调用对应玩法的 remix 接口。
|
||||
3. 登录用户打开他人公开作品详情时,左下角按钮仍为“作品改造”。
|
||||
4. 未登录用户点击“作品改造”仍先触发登录拦截。
|
||||
@@ -0,0 +1,75 @@
|
||||
# 拼图 APIMart 图片模型路由接入 2026-05-01
|
||||
|
||||
## 背景
|
||||
|
||||
拼图创作已收口为填表式流程,首图生成和结果页关卡重新生成都由 `server-rs/crates/api-server/src/puzzle.rs` 执行外部图片 I/O,再把正式图写入 OSS 与 SpacetimeDB。新的模型选择只影响图片生成上游,不改变 SpacetimeDB 表结构、拼图草稿结构或前端运行时规则。
|
||||
|
||||
本轮参考 APIMart 文档:
|
||||
|
||||
1. `https://docs.apimart.ai/cn/api-reference/images/gpt-image-2/generation`
|
||||
2. `https://docs.apimart.ai/cn/api-reference/images/gemini-3.1-flash/generation`
|
||||
|
||||
两条文档均指向 OpenAI 兼容风格的图片生成入口:`POST https://api.apimart.ai/v1/images/generations`,头部使用 `Authorization: Bearer {APIMART_API_KEY}`。请求体至少包含 `model`、`prompt`、`n`、`size`。返回体按 OpenAI images 兼容格式优先读取 `data[].url`,若供应商返回异步任务结构,则继续按 `task_id` / `tasks/{task_id}` 轮询并提取图片 URL。
|
||||
|
||||
## 模型选项
|
||||
|
||||
拼图图片生成支持两个选项:
|
||||
|
||||
| 前端显示 | 请求值 | 上游 |
|
||||
| --- | --- | --- |
|
||||
| `gpt-image-2` | `gpt-image-2` | APIMart `/v1/images/generations` |
|
||||
| `nanobanana2` | `gemini-3.1-flash-image-preview` | APIMart `/v1/images/generations` |
|
||||
|
||||
默认值为 `gpt-image-2`。前端只负责展示和传递所选模型,不能把模型路由逻辑、上游请求体拼装或 API Key 暴露到浏览器。历史草稿或旧请求中的空值、`original`、未知值统一按 `gpt-image-2` 处理,不再把拼图生图路由回 DashScope 原模型。
|
||||
|
||||
## 前端交互
|
||||
|
||||
1. 拼图创作表单的“画面描述”输入框左下角显示当前调用模型。
|
||||
2. 拼图结果页关卡详情的“画面描述”输入框左下角同样显示当前调用模型。
|
||||
3. 点击模型标识弹出轻量选择菜单,只支持 `gpt-image-2`、`nanobanana2` 两项。
|
||||
4. 菜单只是模型选择控件,不写入说明性规则文案。
|
||||
5. 参考图入口继续在画面描述输入框右下角,模型选择在左下角,两者不得遮挡文本。
|
||||
6. 表单创建 session、自动保存表单草稿、首图生成失败重试时都要保留当前模型选择。
|
||||
7. 结果页关卡重新生成时将当前模型随 `generate_puzzle_images` action 传给后端。
|
||||
8. “生成草稿”和关卡详情“生成画面 / 重新生成画面”按钮文本右侧展示 `消耗2光点`。
|
||||
9. 关卡详情点击“生成画面 / 重新生成画面”后先弹出确认消耗光点弹窗,确认后开始请求;按钮区域切换为 30 秒倒计时进度条,并展示预计剩余生成完成时间。
|
||||
|
||||
## 后端路由
|
||||
|
||||
1. `CreatePuzzleAgentSessionRequest` 与 `ExecutePuzzleAgentActionRequest` 增加可选 `imageModel` 字段;该字段不进入 SpacetimeDB reducer 输入结构。
|
||||
2. `compile_puzzle_draft_with_initial_cover` 与 `generate_puzzle_image_candidates` 增加图片模型参数。
|
||||
3. `imageModel` 归一化规则:
|
||||
- 空值、`original` 或未知值统一回落为 `gpt-image-2`;
|
||||
- `gpt-image-2` 走 APIMart;
|
||||
- `gemini-3.1-flash-image-preview` 走 APIMart,前端显示名为 `nanobanana2`。
|
||||
4. APIMart 文生图和图生图共用 `POST /v1/images/generations`。有参考图时,后端将参考图 Data URL 作为 `image_urls` 数组传入;若上游不接受该字段,错误按上游失败返回,不在前端降级伪造结果。
|
||||
5. APIMart 尺寸使用文档要求的比例写法 `1:1`。`gemini-3.1-flash-image-preview` 额外带 `resolution = "1K"`,对齐约 1024px 的拼图正方形素材。
|
||||
6. APIMart 生成成功后仍下载远程图片,沿用现有 OSS 私有对象、`asset_object` 和 `asset_entity_binding` 写入流程。若图片已成功上传 OSS,但 Maincloud / SpacetimeDB 短暂返回 `503 Service Unavailable`,资产索引写入允许降级跳过,并返回本次生成图片;日志必须记录 `拼图图片资产索引写入因 SpacetimeDB 连接不可用而降级跳过`。
|
||||
7. `save_puzzle_generated_images` 写回草稿时若遇到 Maincloud 连接级 `503` 或断线,API 层基于本次生成结果合成 session 快照返回给前端,避免 APIMart 已成功出图却被后置持久化误报成服务不可用。余额不足、参数错误、上游生图失败仍按原错误返回,不做伪成功。
|
||||
8. 结果页 `generate_puzzle_images` 会携带当前作品信息和 `levelsJson`。当 Maincloud / SpacetimeDB 在读取 session 阶段就返回连接级 `503` 或断线时,后端必须先用这份结果页快照构造最小内存 session,再继续调用 APIMart;外部图片已经生成后仍按第 6、7 条处理持久化降级。余额不足、参数错误、缺少草稿快照、关卡不存在等业务错误不走此降级。
|
||||
9. APIMart 异步任务轮询按文档口径在提交后先等待 `10s`,再调用 `GET /v1/tasks/{task_id}`;图片地址提取同时支持 `url: "..."` 与 `url: ["..."]` 两种结构。
|
||||
10. APIMart 错误统一映射为 `502 UPSTREAM_ERROR`,`details.provider = "apimart"`,保留上游状态码、业务 message 和截断后的 raw excerpt。
|
||||
11. 拼图首图生成 `compile_puzzle_draft` 与关卡图片生成 `generate_puzzle_images` 每次预扣 `2` 光点;余额不足仍返回 `409 CONFLICT`,Maincloud 连接级 503 仍按既有降级策略处理。
|
||||
|
||||
## 环境变量
|
||||
|
||||
新增服务端环境变量:
|
||||
|
||||
```text
|
||||
APIMART_BASE_URL="https://api.apimart.ai/v1"
|
||||
APIMART_API_KEY="YOUR_APIMART_API_KEY"
|
||||
APIMART_IMAGE_REQUEST_TIMEOUT_MS=180000
|
||||
```
|
||||
|
||||
`APIMART_API_KEY` 只能存在于本地或部署环境,不写入 Git 跟踪文件。若选择 APIMart 模型但缺少 key,后端返回服务不可用错误,前端展示现有错误面板。
|
||||
|
||||
## 验收
|
||||
|
||||
1. 创作表单和关卡详情的画面描述框左下角能切换 `gpt-image-2`、`nanobanana2`,默认显示 `gpt-image-2`。
|
||||
2. 点击“生成草稿”时,后端首图生成使用当前表单选择的模型。
|
||||
3. 点击“生成画面 / 重新生成画面”时,后端当前关卡图片生成使用关卡详情选择的模型。
|
||||
4. 历史 `original` 或空模型值不会再触发 DashScope,统一按 `gpt-image-2` 请求 APIMart。
|
||||
5. 选择 APIMart 模型时,请求 `POST {APIMART_BASE_URL}/images/generations`,使用 `Authorization: Bearer {APIMART_API_KEY}`,`model` 等于请求值,`size = 1:1`。
|
||||
6. “生成草稿”和关卡详情生图按钮展示 `消耗2光点`;关卡详情确认后展示 30 秒预计剩余进度条。
|
||||
7. 不改 SpacetimeDB 表结构,因此无需更新 `migration.rs` 或重新生成 bindings。
|
||||
8. 后端改动后运行对应 Rust 测试,并按项目约束用 `npm run api-server:maincloud` 重启验证。
|
||||
@@ -14,9 +14,9 @@
|
||||
4. 玩家在生成草稿前退出,再次从创作中心点击这条拼图草稿时,必须恢复到填表页,并回填之前自动保存的作品名称、作品描述和画面描述;只有执行 `compile_puzzle_draft` 且生成结果页草稿后,草稿入口才进入结果页。
|
||||
5. 表单自动保存走 `save_puzzle_form_draft` action,不消耗光点,不生成图片,不改变 `stage = collecting_anchors`;生成草稿按钮仍单独触发 `compile_puzzle_draft` 并进入进度页。
|
||||
6. 点击拼图入口始终创建新草稿,不复用上一次未完成 session;恢复旧草稿只通过“我的创作”中的草稿卡进入。
|
||||
7. 若 Maincloud 仍运行旧 wasm,缺少 `save_puzzle_form_draft` procedure,前端提交生成或生成失败页重试时不得继续复用空 `seedText` 的表单 session,必须用当前表单 payload 新建带真实 seed 的 session 再执行 `compile_puzzle_draft`。
|
||||
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。当前 Maincloud `xushi-p4wfr` 的迁移操作员表为空,但旧库引导密钥来自旧 wasm,本次临时生成的新引导密钥无法授权导出迁移,需使用已有迁移操作员 token 或数据库 owner 重新授权后发布;禁止为绕过冲突直接清库,除非明确接受数据丢失。
|
||||
9. 正式修复仍是发布最新 SpacetimeDB wasm。如果目标库的迁移操作员表为空,但旧库引导密钥来自旧 wasm,本次临时生成的新引导密钥无法授权导出迁移,需使用已有迁移操作员 token 或数据库 owner 重新授权后发布;禁止为绕过冲突直接清库,除非明确接受数据丢失。
|
||||
|
||||
1. 作品名称为必填字段,保存到 `workTitle`,兼容写入旧 `seedText`,同时作为作品级 `workTitle` 的真相源。
|
||||
2. 作品描述为必填字段,保存到 `workDescription`,作为作品详情页、作品列表和发布资料中的 `summary` 真相源。
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
|
||||
### 1. 图片生成
|
||||
|
||||
1. 拼图生成图固定使用 `1024*1024`。
|
||||
2. 文生图和参考图生图共用同一个尺寸常量,禁止一条链路仍生成竖屏或横版图。
|
||||
3. 拼图图片提示词明确写入 `1:1 正方形画布`,继续保留适配 `3x3 / 4x4 / 5x5 / 6x6 / 7x7` 拼图切块、主体清晰、层次明确、无文字水印等约束。
|
||||
4. 文生图正向 prompt 必须由后端压缩到 `500` 字符以内,优先保留玩家画面描述开头与固定拼图约束,避免 DashScope 旧 text2image 协议把超长 prompt 判为“请求参数不合法”。
|
||||
5. DashScope 上游失败时,api-server 必须在错误 details 中保留业务 message、`upstreamStatus` 和截断后的 `rawExcerpt`,日志也要记录同样的摘要,避免生成进度页只能看到通用 HTTP 文案。
|
||||
6. 图片生成仍由 `api-server` 执行。SpacetimeDB reducer 不做网络 I/O。
|
||||
7. 拼图文生图请求体按 DashScope Wan text2image 协议收口:`input` 放 `prompt` 与非空 `negative_prompt`,`parameters` 放 `n`、`size`、`prompt_extend`、`watermark`。不要在 `input` 与 `parameters` 里重复写入反向提示词,否则上游容易返回参数非法。
|
||||
1. 拼图默认使用 APIMart `gpt-image-2` 生成图,外部请求尺寸固定为 `1:1`;`nanobanana2` 仍映射为 `gemini-3.1-flash-image-preview`。
|
||||
2. 历史 `original` 或空模型值只做兼容输入,不再进入 DashScope 原模型链路,统一按 `gpt-image-2` 路由。
|
||||
3. 文生图和参考图生图共用同一个正方形尺寸口径,禁止一条链路仍生成竖屏或横版图。
|
||||
4. 拼图图片提示词明确写入 `1:1 正方形画布`,继续保留适配 `3x3 / 4x4 / 5x5 / 6x6 / 7x7` 拼图切块、主体清晰、层次明确、无文字水印等约束。
|
||||
5. 文生图正向 prompt 必须由后端压缩到 `500` 字符以内,优先保留玩家画面描述开头与固定拼图约束,避免上游把超长 prompt 判为“请求参数不合法”。
|
||||
6. APIMart 上游失败时,api-server 必须在错误 details 中保留业务 message、`upstreamStatus` 和截断后的 `rawExcerpt`,日志也要记录同样的摘要,避免生成进度页只能看到通用 HTTP 文案。
|
||||
7. 图片生成仍由 `api-server` 执行。SpacetimeDB reducer 不做网络 I/O。
|
||||
8. 光点预扣失败属于钱包或 SpacetimeDB 服务链路错误,不得映射成 `400 BAD_REQUEST`。除余额不足返回 `409 CONFLICT` 外,其余预扣异常统一按上游/服务错误暴露,避免生成页误提示“请求参数不合法”。
|
||||
|
||||
### 2. 前端规则裁决
|
||||
@@ -47,10 +47,10 @@
|
||||
|
||||
## 验收
|
||||
|
||||
1. 点击拼图草稿生成或重新生成画面时,后端请求 DashScope 的 `size` 为 `1024*1024`。
|
||||
1. 点击拼图草稿生成或重新生成画面时,后端请求 APIMart 的 `size` 为 `1:1`,默认模型为 `gpt-image-2`。
|
||||
2. 图片提示词包含 `1:1 正方形拼图关卡`。
|
||||
3. 图片提示词长度不超过 `500` 字符,超长画面描述会被截断,但适配 `3x3 / 4x4 / 5x5 / 6x6 / 7x7` 拼图切块、`避免文字、水印、边框和 UI 元素` 等玩法约束不能丢。
|
||||
4. DashScope 返回参数错误、任务失败或非 2xx 时,前端错误优先展示后端 details.message,后端日志能看到 `upstreamStatus` 和 `rawExcerpt`。
|
||||
4. APIMart 返回参数错误、任务失败或非 2xx 时,前端错误优先展示后端 details.message,后端日志能看到 `upstreamStatus` 和 `rawExcerpt`。
|
||||
5. 正式拼图 run 中拖动拼块后,前端立即更新棋盘、合并块和通关状态,不再等待 `/drag`。
|
||||
6. 移动端运行时棋盘为正方形,并尽量贴近屏幕两侧边缘。
|
||||
7. 基础单块和合并块都能看到圆角,合并块的外凸角与内凹角都不是直角,且图片不会溢出圆角裁剪。
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user