添加maincloud发布

This commit is contained in:
2026-04-24 22:07:02 +08:00
parent 0708fd0547
commit f6604ea3b4
16 changed files with 563 additions and 23 deletions

View File

@@ -203,6 +203,8 @@ spacetime server ping <server>
```bash
# Clear data and republish
spacetime publish my-db --clear-database --yes
# Clear data and republish only when conflict
spacetime publish my-db --clear-database=on-conflict --yes
```
### "Build failed"

View File

@@ -52,3 +52,7 @@ ALIYUN_OSS_ACCESS_KEY_SECRET="XblWGE6CO1WLnSBdMRVpL6lut4GSoS"
GENARRATIVE_BACKEND_STACK="rust"
RUST_SERVER_TARGET="http://127.0.0.1:3100"
GENARRATIVE_API_TARGET="http://127.0.0.1:3100"
GENARRATIVE_SPACETIME_MAINCLOUD_SERVER_URL="https://maincloud.spacetimedb.com"
GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE="xushi-p4wfr"
GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN="eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIwMUsyN05YUjBaQkRUVEVCNlFQQjFXNzU2MiIsImlzcyI6Imh0dHBzOi8vYXV0aC5zcGFjZXRpbWVkYi5jb20iLCJhdWQiOiJzcGFjZXRpbWVkYiIsImlhdCI6MTc3NzAzNjI2MSwiZXhwIjoxODQwMTA4MjYxfQ.XosLKR-y85dv4yRN-INJMNSWhz4VtXaDvypvyzNAwFdmLMC3IKG6HfmSBHwLOjO3JVkQBTKodivYe6_sDOFNsCMGdP5nwMubYlmxWaOk41WBldd3JFA7ag8OpikYBkWp-4n59c8wLn-LWiOUWBw_g5vaCbzZs3pP51amw9o-DUEog53fGjoS3ij8oVIg_8AZDxoSmqVvT6K-2wIpstj7bM674nks-qbhMuAjdM9l1HURw_uip5iWEIB4hQZtzlOtHe49wvhN3lvgoM9r4YJS7emDDBwFTopQF-cSPKyh_tFfpH7jUIb3RiqGutQV37c3veNnUVxmYNvqB561eR4mQw"

View File

@@ -83,3 +83,27 @@ cargo test -p api-server custom_world_foundation_draft -- --nocapture
```
结果:后端检查通过;`custom_world_foundation_draft` 相关测试 `3 passed`
## 2026-04-24 `spacetime-client` facade 补齐
合并 `draft_foundation` 进度链路后,`spacetime-module` 和生成绑定中已经存在 `upsert_custom_world_agent_operation_progress` procedure但手写 `spacetime-client` facade 尚未导出对应 record input 与调用方法,导致 `api-server` 编译时报:
1. `CustomWorldAgentOperationProgressRecordInput` 未导出。
2. `SpacetimeClient::upsert_custom_world_agent_operation_progress` 不存在。
本次补齐边界:
1. `spacetime-client::mapper` 新增 `CustomWorldAgentOperationProgressRecordInput`
2. `spacetime-client::custom_world` 新增 `upsert_custom_world_agent_operation_progress(...)`,负责把字符串形式的 operation type/status 翻译为 SpacetimeDB 生成枚举后调用 procedure。
3. `spacetime-client::module_bindings::mod` 补入已生成的 progress input/procedure 索引,避免 procedure 文件存在但 `RemoteProcedures` 扩展 trait 未进入作用域。
4. `api-server` 只依赖 facade不直接碰生成绑定保持 HTTP 层与 SpacetimeDB 生成类型隔离。
补充验证:
```bash
cargo fmt -p spacetime-client -p api-server
cargo check -p api-server --bin api-server
npm run check:encoding
```
结果:`api-server` 编译通过,编码检查通过;剩余 warning 为既有 dead code。

View File

@@ -0,0 +1,68 @@
# 拼图玩法单机运行态与真实图片生成方案 2026-04-24
## 1. 本次收口目标
这次收口只做两件事:
1. 拼图结果页中的候选图生成不再返回本地 SVG 占位图,而是接入 Rust `api-server` 现有的真实外部生图链。
2. 拼图第一版运行态改为单机本地运行,不再把交换、拖动、通关进度和下一关状态保存到后端。
## 2. 第一版单机范围
第一版“单机版本”的准确定义如下:
1. 玩家从拼图广场或作品详情进入玩法时,前端基于作品详情在本地构造一次 `PuzzleRunSnapshot`
2. 交换拼图块、拖动拼图块、关卡是否拼完,全部由前端本地计算。
3. 本地运行态不调用 `/api/runtime/puzzle/runs/*` 写回当前过程状态。
4. 关闭玩法后,这次运行态直接失效,不做断点续玩,不做跨端同步。
5. 后端仍然负责:
- Agent 会话
- 结果页草稿编译
- 正式候选图生成
- 封面确认
- 作品发布
- 作品列表 / 详情 / 广场读取
这意味着第一版拼图玩法是“创作后端化、游玩本地化”的结构,而不是“所有状态都走后端”的结构。
## 3. 真实图片生成链
拼图正式候选图统一复用当前仓库已经跑通的 Rust 资产主链:
1. `api-server` 根据拼图草稿的关卡名和结果页 prompt 组装正式文生图 prompt。
2. 调用 DashScope 文生图接口创建异步任务。
3. 轮询任务直到拿到正式图片地址。
4. 下载图片二进制。
5. 上传到私有 OSS。
6.`module-assets` / `spacetime-client` 的资产真相链中确认对象并绑定到拼图实体。
7. 对前端返回 `/generated-puzzle-assets/*` 兼容路径,而不是本地 `svg` 占位路径。
## 4. 路径与边界
### 4.1 候选图输出路径
拼图正式候选图统一使用:
`/generated-puzzle-assets/*`
不能继续写到仓库本地 `public/generated-puzzle-covers/*`
### 4.2 运行态边界
第一版单机运行态保留现有 DTO 结构,目的是不重做界面层。
但 DTO 的来源变化为:
1. 进入玩法时从作品详情构造本地 `run`
2. 交换 / 拖动 / 通关时由前端工具函数返回新的 `run`
3. 当前不依赖后端 `start/swap/drag/next-level` 接口完成主链
## 5. 当前实现判断标准
当下面结果成立时,视为这一轮目标达成:
1. `generate_puzzle_images` 返回的 `imageSrc` 不再是本地 `svg` 占位图。
2. 返回路径切到 `/generated-puzzle-assets/*`
3. 未配置 DashScope 或 OSS 时,接口明确返回 provider 级错误,而不是静默回退占位图。
4. 玩家进入拼图玩法后,即使后端运行态接口不可用,也能在本地完成交换与拖动。
5. 关闭玩法后不保留当前 run 进度。

View File

@@ -0,0 +1,59 @@
# 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. 输出 `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. 启动 `cargo run -p api-server --manifest-path server-rs/Cargo.toml`
## 设计约束
- Maincloud 数据库名必须显式配置,不能默认读取本地 `spacetime.local.json`
- 发布脚本只处理 SpacetimeDB 模块发布,不启动本地 SpacetimeDB。
- `api-server` 继续通过 `SpacetimeClientConfig``server_url / database / token` 连接数据库,不在前端增加逻辑。

View File

@@ -7,8 +7,10 @@
"dev": "node scripts/dev-node.mjs",
"dev:rust": "node scripts/run-bash-script.mjs scripts/dev-rust-stack.sh",
"dev:rust:logs": "node scripts/run-bash-script.mjs scripts/spacetime-logs-local.sh",
"dev:web": "node scripts/vite-cli.mjs --port=3000 --host=0.0.0.0",
"dev:web": "node scripts/dev-web-rust.mjs",
"dev:node": "node scripts/dev-node.mjs",
"spacetime:publish:maincloud": "node scripts/run-bash-script.mjs scripts/spacetime-publish-maincloud.sh",
"api-server:maincloud": "node scripts/api-server-maincloud.mjs",
"deploy:rust:remote": "node scripts/run-bash-script.mjs scripts/deploy-rust-remote.sh",
"build:rust:ubuntu": "node scripts/run-bash-script.mjs scripts/deploy-rust-remote.sh",
"serve:caddy": "node scripts/run-caddy-dev.mjs",

View File

@@ -0,0 +1,86 @@
import {spawn} from 'node:child_process';
import {existsSync, readFileSync} from 'node:fs';
import {resolve} from 'node:path';
const repoRoot = process.cwd();
function loadEnvFile(path, target) {
if (!existsSync(path)) {
return;
}
const rawText = readFileSync(path, 'utf8');
for (const rawLine of rawText.split(/\r?\n/u)) {
const line = rawLine.trim();
if (!line || line.startsWith('#')) {
continue;
}
const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/u);
if (!match) {
continue;
}
const [, key, rawValue] = match;
if (target[key] !== undefined) {
continue;
}
target[key] = rawValue.replace(/^['"]|['"]$/gu, '');
}
}
const mergedEnv = {...process.env};
loadEnvFile(resolve(repoRoot, '.env'), mergedEnv);
loadEnvFile(resolve(repoRoot, '.env.local'), mergedEnv);
mergedEnv.GENARRATIVE_API_HOST = mergedEnv.GENARRATIVE_API_HOST || '127.0.0.1';
mergedEnv.GENARRATIVE_API_PORT = mergedEnv.GENARRATIVE_API_PORT || '3100';
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL =
mergedEnv.GENARRATIVE_SPACETIME_MAINCLOUD_SERVER_URL ||
mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL ||
'https://maincloud.spacetimedb.com';
mergedEnv.GENARRATIVE_SPACETIME_DATABASE =
mergedEnv.GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE ||
mergedEnv.GENARRATIVE_SPACETIME_DATABASE ||
'';
mergedEnv.GENARRATIVE_SPACETIME_TOKEN =
mergedEnv.GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN ||
mergedEnv.GENARRATIVE_SPACETIME_TOKEN ||
'';
if (!mergedEnv.GENARRATIVE_SPACETIME_DATABASE) {
console.error(
'[api-server:maincloud] 缺少 GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE 或 GENARRATIVE_SPACETIME_DATABASE。',
);
process.exit(1);
}
console.log(
`[api-server:maincloud] SpacetimeDB ${mergedEnv.GENARRATIVE_SPACETIME_DATABASE} @ ${mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL}`,
);
const child = spawn(
'cargo',
['run', '-p', 'api-server', '--manifest-path', 'server-rs/Cargo.toml'],
{
cwd: repoRoot,
env: mergedEnv,
stdio: 'inherit',
shell: process.platform === 'win32',
},
);
child.on('error', (error) => {
console.error(`[api-server:maincloud] 启动 cargo 失败: ${error.message}`);
process.exit(1);
});
child.on('exit', (code, signal) => {
if (signal) {
console.error(`[api-server:maincloud] api-server 被信号终止: ${signal}`);
process.exit(1);
}
process.exit(code ?? 0);
});

40
scripts/dev-web-rust.mjs Normal file
View File

@@ -0,0 +1,40 @@
import {spawn} from 'node:child_process';
const mergedEnv = {
...process.env,
GENARRATIVE_BACKEND_STACK: process.env.GENARRATIVE_BACKEND_STACK || 'rust',
RUST_SERVER_TARGET:
process.env.RUST_SERVER_TARGET ||
process.env.GENARRATIVE_API_TARGET ||
`http://127.0.0.1:${process.env.GENARRATIVE_API_PORT || '3100'}`,
};
mergedEnv.GENARRATIVE_RUNTIME_SERVER_TARGET =
process.env.GENARRATIVE_RUNTIME_SERVER_TARGET || mergedEnv.RUST_SERVER_TARGET;
console.log(`[dev:web] backend=rust target=${mergedEnv.GENARRATIVE_RUNTIME_SERVER_TARGET}`);
const child = spawn(
'node',
['scripts/vite-cli.mjs', '--port=3000', '--host=0.0.0.0'],
{
cwd: process.cwd(),
env: mergedEnv,
stdio: 'inherit',
shell: process.platform === 'win32',
},
);
child.on('error', (error) => {
console.error(`[dev:web] 启动 Vite 失败: ${error.message}`);
process.exit(1);
});
child.on('exit', (code, signal) => {
if (signal) {
console.error(`[dev:web] Vite 被信号终止: ${signal}`);
process.exit(1);
}
process.exit(code ?? 0);
});

View File

@@ -0,0 +1,125 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
SERVER_RS_DIR="${REPO_ROOT}/server-rs"
MODULE_PATH="${SERVER_RS_DIR}/target/wasm32-unknown-unknown/release/spacetime_module.wasm"
SPACETIME_SERVER_ALIAS="maincloud"
CLEAR_DATABASE=0
load_env_file() {
local env_file="$1"
local line key value
if [[ ! -f "${env_file}" ]]; then
return
fi
while IFS= read -r line || [[ -n "${line}" ]]; do
line="${line%$'\r'}"
line="${line#$'\xef\xbb\xbf'}"
[[ -z "${line}" || "${line}" == \#* ]] && continue
[[ "${line}" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]] || continue
key="${BASH_REMATCH[1]}"
value="${BASH_REMATCH[2]}"
value="${value%\"}"
value="${value#\"}"
value="${value%\'}"
value="${value#\'}"
if [[ -z "${!key+x}" ]]; then
export "${key}=${value}"
fi
done <"${env_file}"
}
usage() {
cat <<'EOF'
用法:
npm run spacetime:publish:maincloud
npm run spacetime:publish:maincloud -- --database <database>
npm run spacetime:publish:maincloud -- --clear-database
说明:
发布 server-rs/crates/spacetime-module 到 SpacetimeDB Maincloud。
数据库名优先读取 --database其次读取 GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE。
EOF
}
load_env_file "${REPO_ROOT}/.env"
load_env_file "${REPO_ROOT}/.env.local"
SPACETIME_DATABASE="${GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE:-}"
SPACETIME_SERVER_URL="${GENARRATIVE_SPACETIME_MAINCLOUD_SERVER_URL:-https://maincloud.spacetimedb.com}"
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
--database)
SPACETIME_DATABASE="${2:?缺少 --database 的值}"
shift 2
;;
--server-url)
SPACETIME_SERVER_URL="${2:?缺少 --server-url 的值}"
shift 2
;;
--clear-database)
CLEAR_DATABASE=1
shift
;;
*)
echo "[spacetime:maincloud] 未知参数: $1" >&2
usage >&2
exit 1
;;
esac
done
if [[ -z "${SPACETIME_DATABASE}" ]]; then
echo "[spacetime:maincloud] 缺少 GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE。" >&2
echo "[spacetime:maincloud] 请在 .env.local 中配置,或通过 --database <database> 传入。" >&2
exit 1
fi
if ! command -v cargo >/dev/null 2>&1; then
echo "[spacetime:maincloud] 缺少 cargo 命令。" >&2
exit 1
fi
if ! command -v spacetime >/dev/null 2>&1; then
echo "[spacetime:maincloud] 缺少 spacetime CLI请先安装并登录 Maincloud。" >&2
exit 1
fi
echo "[spacetime:maincloud] 构建 spacetime-module wasm"
cargo build \
--manifest-path "${SERVER_RS_DIR}/Cargo.toml" \
-p spacetime-module \
--target wasm32-unknown-unknown \
--release
PUBLISH_ARGS=(
publish
"${SPACETIME_DATABASE}"
--server "${SPACETIME_SERVER_ALIAS}"
--bin-path "${MODULE_PATH}"
--yes
)
if [[ "${CLEAR_DATABASE}" -eq 1 ]]; then
# Maincloud 清库只在 schema 冲突时触发,避免无冲突升级误删线上数据。
PUBLISH_ARGS+=(-c=on-conflict)
fi
echo "[spacetime:maincloud] 发布 SpacetimeDB wasm: ${SPACETIME_DATABASE} -> ${SPACETIME_SERVER_ALIAS}"
spacetime "${PUBLISH_ARGS[@]}"
cat <<EOF
[spacetime:maincloud] 发布完成。api-server 可使用以下环境:
GENARRATIVE_SPACETIME_SERVER_URL=${SPACETIME_SERVER_URL}
GENARRATIVE_SPACETIME_DATABASE=${SPACETIME_DATABASE}
GENARRATIVE_SPACETIME_TOKEN=
EOF

View File

@@ -394,19 +394,26 @@ impl AppConfig {
config.oss_success_action_status = oss_success_action_status;
}
if let Some(spacetime_server_url) =
read_first_non_empty_env(&["GENARRATIVE_SPACETIME_SERVER_URL"])
if let Some(spacetime_server_url) = read_first_non_empty_env(&[
"GENARRATIVE_SPACETIME_SERVER_URL",
"GENARRATIVE_SPACETIME_MAINCLOUD_SERVER_URL",
])
{
config.spacetime_server_url = spacetime_server_url;
}
if let Some(spacetime_database) =
read_first_non_empty_env(&["GENARRATIVE_SPACETIME_DATABASE"])
if let Some(spacetime_database) = read_first_non_empty_env(&[
"GENARRATIVE_SPACETIME_DATABASE",
"GENARRATIVE_SPACETIME_MAINCLOUD_DATABASE",
])
{
config.spacetime_database = spacetime_database;
}
config.spacetime_token = read_first_non_empty_env(&["GENARRATIVE_SPACETIME_TOKEN"]);
config.spacetime_token = read_first_non_empty_env(&[
"GENARRATIVE_SPACETIME_TOKEN",
"GENARRATIVE_SPACETIME_MAINCLOUD_TOKEN",
]);
if let Some(spacetime_pool_size) =
read_first_positive_u32_env(&["GENARRATIVE_SPACETIME_POOL_SIZE"])
{

View File

@@ -1,5 +1,5 @@
use platform_llm::{LlmClient, LlmMessage, LlmTextRequest};
use serde_json::{Map as JsonMap, Value as JsonValue, json};
use serde_json::{Map as JsonMap, Value as JsonValue};
use shared_contracts::runtime::ExecuteCustomWorldAgentActionRequest;
use spacetime_client::CustomWorldAgentSessionRecord;
@@ -488,6 +488,7 @@ fn create_stable_id(prefix: &str, name: &str, index: usize) -> String {
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn character_expansion_prompt_keeps_node_contract_text() {

View File

@@ -16,6 +16,7 @@ use module_assets::{
AssetObjectAccessPolicy, AssetObjectFieldError, build_asset_entity_binding_input,
build_asset_object_upsert_input, generate_asset_binding_id, generate_asset_object_id,
};
use module_puzzle::PuzzleGeneratedImageCandidate;
use platform_oss::{LegacyAssetPrefix, OssHeadObjectRequest, OssObjectAccess, OssPutObjectRequest};
use serde_json::{Map, Value, json};
use shared_contracts::{
@@ -1463,21 +1464,6 @@ struct PuzzleDownloadedImage {
bytes: Vec<u8>,
}
fn to_puzzle_generated_image_candidate(
candidate: &PuzzleGeneratedImageCandidateRecord,
) -> PuzzleGeneratedImageCandidate {
// SpacetimeDB ???????? module-puzzle ??????????? snake_case ????HTTP ????????? camelCase?
PuzzleGeneratedImageCandidate {
candidate_id: candidate.candidate_id.clone(),
image_src: candidate.image_src.clone(),
asset_id: candidate.asset_id.clone(),
prompt: candidate.prompt.clone(),
actual_prompt: candidate.actual_prompt.clone(),
source_type: candidate.source_type.clone(),
selected: candidate.selected,
}
}
struct GeneratedPuzzleAssetResponse {
image_src: String,
asset_id: String,
@@ -1526,6 +1512,21 @@ fn build_puzzle_dashscope_http_client(
})
}
fn to_puzzle_generated_image_candidate(
candidate: &PuzzleGeneratedImageCandidateRecord,
) -> PuzzleGeneratedImageCandidate {
// SpacetimeDB 模块反序列化的是 module-puzzle 的持久化结构,必须保留 snake_case 字段名HTTP 响应层再单独映射为 camelCase。
PuzzleGeneratedImageCandidate {
candidate_id: candidate.candidate_id.clone(),
image_src: candidate.image_src.clone(),
asset_id: candidate.asset_id.clone(),
prompt: candidate.prompt.clone(),
actual_prompt: candidate.actual_prompt.clone(),
source_type: candidate.source_type.clone(),
selected: candidate.selected,
}
}
async fn create_puzzle_text_to_image_generation(
http_client: &reqwest::Client,
settings: &PuzzleDashScopeSettings,

View File

@@ -436,6 +436,41 @@ impl SpacetimeClient {
.await
}
pub async fn upsert_custom_world_agent_operation_progress(
&self,
input: CustomWorldAgentOperationProgressRecordInput,
) -> Result<CustomWorldAgentOperationRecord, SpacetimeClientError> {
let procedure_input = CustomWorldAgentOperationProgressInput {
session_id: input.session_id,
owner_user_id: input.owner_user_id,
operation_id: input.operation_id,
operation_type: parse_rpg_agent_operation_type_record(input.operation_type.as_str())?,
operation_status: parse_rpg_agent_operation_status_record(
input.operation_status.as_str(),
)?,
phase_label: input.phase_label,
phase_detail: input.phase_detail,
operation_progress: input.operation_progress,
error_message: input.error_message,
updated_at_micros: input.updated_at_micros,
};
self.call_after_connect(move |connection, sender| {
connection
.procedures()
.upsert_custom_world_agent_operation_progress_then(
procedure_input,
move |_, result| {
let mapped = result
.map_err(|error| SpacetimeClientError::Procedure(error.to_string()))
.and_then(map_custom_world_agent_operation_procedure_result);
send_once(&sender, mapped);
},
);
})
.await
}
pub async fn get_custom_world_agent_operation(
&self,
session_id: String,

View File

@@ -4,7 +4,40 @@ pub mod module_bindings;
mod mapper;
pub(crate) use mapper::*;
pub use mapper::{BattleStateRecord, ResolveCombatActionRecord, CustomWorldLibraryEntryRecord, CustomWorldGalleryEntryRecord, CustomWorldLibraryMutationRecord, CustomWorldPublishedProfileCompileRecord, CustomWorldPublishWorldRecord, CustomWorldAgentMessageRecord, CustomWorldAgentOperationRecord, CustomWorldDraftCardRecord, CustomWorldSupportedActionRecord, CustomWorldCheckpointRecord, CustomWorldAgentCheckpointRecord, CustomWorldResultPreviewBlockerRecord, CustomWorldPublishGateRecord, CustomWorldWorkSummaryRecord, CustomWorldDraftCardDetailSectionRecord, CustomWorldDraftCardDetailRecord, CustomWorldAgentSessionRecord, CustomWorldProfileUpsertRecordInput, CustomWorldPublishWorldRecordInput, CustomWorldAgentSessionCreateRecordInput, CustomWorldAgentMessageSubmitRecordInput, CustomWorldAgentMessageFinalizeRecordInput, CustomWorldAgentActionExecuteRecordInput, CustomWorldAgentActionExecuteRecord, PuzzleAgentSessionCreateRecordInput, PuzzleAgentMessageSubmitRecordInput, PuzzleAgentMessageFinalizeRecordInput, PuzzleGeneratedImagesSaveRecordInput, PuzzleSelectCoverImageRecordInput, PuzzlePublishRecordInput, PuzzleWorkUpsertRecordInput, PuzzleRunStartRecordInput, PuzzleRunSwapRecordInput, PuzzleRunDragRecordInput, PuzzleRunNextLevelRecordInput, PuzzleAnchorItemRecord, PuzzleAnchorPackRecord, PuzzleCreatorIntentRecord, PuzzleGeneratedImageCandidateRecord, PuzzleResultDraftRecord, PuzzleAgentMessageRecord, PuzzleAgentSuggestedActionRecord, PuzzleResultPreviewBlockerRecord, PuzzleResultPreviewFindingRecord, PuzzleResultPreviewRecord, PuzzleAgentSessionRecord, PuzzleWorkProfileRecord, PuzzleCellPositionRecord, PuzzlePieceStateRecord, PuzzleMergedGroupRecord, PuzzleBoardRecord, PuzzleRuntimeLevelRecord, PuzzleRunRecord, BigFishSessionCreateRecordInput, BigFishMessageSubmitRecordInput, BigFishMessageFinalizeRecordInput, BigFishAssetGenerateRecordInput, BigFishRunStartRecordInput, BigFishRunInputSubmitRecordInput, BigFishAnchorItemRecord, BigFishAnchorPackRecord, BigFishLevelBlueprintRecord, BigFishBackgroundBlueprintRecord, BigFishRuntimeParamsRecord, BigFishGameDraftRecord, BigFishAgentMessageRecord, BigFishAssetSlotRecord, BigFishAssetCoverageRecord, BigFishSessionRecord, BigFishWorkSummaryRecord, BigFishVector2Record, BigFishRuntimeEntityRecord, BigFishRuntimeRecord, ResolveNpcBattleInteractionInput, AiTaskStageRecord, AiResultReferenceRecord, AiTextChunkRecord, AiTaskRecord, AiTaskMutationRecord, NpcStateRecord, NpcInteractionRecord, NpcBattleInteractionRecord};
pub use mapper::{
AiResultReferenceRecord, AiTaskMutationRecord, AiTaskRecord, AiTaskStageRecord,
AiTextChunkRecord, BattleStateRecord, BigFishAgentMessageRecord, BigFishAnchorItemRecord,
BigFishAnchorPackRecord, BigFishAssetCoverageRecord, BigFishAssetGenerateRecordInput,
BigFishAssetSlotRecord, BigFishBackgroundBlueprintRecord, BigFishGameDraftRecord,
BigFishLevelBlueprintRecord, BigFishMessageFinalizeRecordInput,
BigFishMessageSubmitRecordInput, BigFishRunInputSubmitRecordInput, BigFishRunStartRecordInput,
BigFishRuntimeEntityRecord, BigFishRuntimeParamsRecord, BigFishRuntimeRecord,
BigFishSessionCreateRecordInput, BigFishSessionRecord, BigFishVector2Record,
BigFishWorkSummaryRecord, CustomWorldAgentActionExecuteRecord,
CustomWorldAgentActionExecuteRecordInput, CustomWorldAgentCheckpointRecord,
CustomWorldAgentMessageFinalizeRecordInput, CustomWorldAgentMessageRecord,
CustomWorldAgentMessageSubmitRecordInput, CustomWorldAgentOperationProgressRecordInput,
CustomWorldAgentOperationRecord, CustomWorldAgentSessionCreateRecordInput,
CustomWorldAgentSessionRecord, CustomWorldCheckpointRecord, CustomWorldDraftCardDetailRecord,
CustomWorldDraftCardDetailSectionRecord, CustomWorldDraftCardRecord,
CustomWorldGalleryEntryRecord, CustomWorldLibraryEntryRecord, CustomWorldLibraryMutationRecord,
CustomWorldProfileUpsertRecordInput, CustomWorldPublishGateRecord,
CustomWorldPublishWorldRecord, CustomWorldPublishWorldRecordInput,
CustomWorldPublishedProfileCompileRecord, CustomWorldResultPreviewBlockerRecord,
CustomWorldSupportedActionRecord, CustomWorldWorkSummaryRecord, NpcBattleInteractionRecord,
NpcInteractionRecord, NpcStateRecord, PuzzleAgentMessageFinalizeRecordInput,
PuzzleAgentMessageRecord, PuzzleAgentMessageSubmitRecordInput,
PuzzleAgentSessionCreateRecordInput, PuzzleAgentSessionRecord,
PuzzleAgentSuggestedActionRecord, PuzzleAnchorItemRecord, PuzzleAnchorPackRecord,
PuzzleBoardRecord, PuzzleCellPositionRecord, PuzzleCreatorIntentRecord,
PuzzleGeneratedImageCandidateRecord, PuzzleGeneratedImagesSaveRecordInput,
PuzzleMergedGroupRecord, PuzzlePieceStateRecord, PuzzlePublishRecordInput,
PuzzleResultDraftRecord, PuzzleResultPreviewBlockerRecord, PuzzleResultPreviewFindingRecord,
PuzzleResultPreviewRecord, PuzzleRunDragRecordInput, PuzzleRunNextLevelRecordInput,
PuzzleRunRecord, PuzzleRunStartRecordInput, PuzzleRunSwapRecordInput, PuzzleRuntimeLevelRecord,
PuzzleSelectCoverImageRecordInput, PuzzleWorkProfileRecord, PuzzleWorkUpsertRecordInput,
ResolveCombatActionRecord, ResolveNpcBattleInteractionInput,
};
pub mod ai;
pub mod assets;

View File

@@ -2737,6 +2737,41 @@ pub(crate) fn format_rpg_agent_operation_status(
}
}
pub(crate) fn parse_rpg_agent_operation_type_record(
value: &str,
) -> Result<crate::module_bindings::RpgAgentOperationType, SpacetimeClientError> {
match value.trim() {
"process_message" => Ok(crate::module_bindings::RpgAgentOperationType::ProcessMessage),
"draft_foundation" => Ok(crate::module_bindings::RpgAgentOperationType::DraftFoundation),
"update_draft_card" => Ok(crate::module_bindings::RpgAgentOperationType::UpdateDraftCard),
"sync_result_profile" => {
Ok(crate::module_bindings::RpgAgentOperationType::SyncResultProfile)
}
"generate_characters" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateCharacters)
}
"generate_landmarks" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateLandmarks)
}
"generate_role_assets" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateRoleAssets)
}
"sync_role_assets" => Ok(crate::module_bindings::RpgAgentOperationType::SyncRoleAssets),
"generate_scene_assets" => {
Ok(crate::module_bindings::RpgAgentOperationType::GenerateSceneAssets)
}
"sync_scene_assets" => Ok(crate::module_bindings::RpgAgentOperationType::SyncSceneAssets),
"expand_long_tail" => Ok(crate::module_bindings::RpgAgentOperationType::ExpandLongTail),
"publish_world" => Ok(crate::module_bindings::RpgAgentOperationType::PublishWorld),
"revert_checkpoint" => Ok(crate::module_bindings::RpgAgentOperationType::RevertCheckpoint),
"delete_characters" => Ok(crate::module_bindings::RpgAgentOperationType::DeleteCharacters),
"delete_landmarks" => Ok(crate::module_bindings::RpgAgentOperationType::DeleteLandmarks),
other => Err(SpacetimeClientError::Runtime(format!(
"未知 rpg agent operation type: {other}"
))),
}
}
pub(crate) fn parse_rpg_agent_operation_status_record(
value: &str,
) -> Result<crate::module_bindings::RpgAgentOperationStatus, SpacetimeClientError> {
@@ -3686,6 +3721,20 @@ pub struct CustomWorldAgentMessageFinalizeRecordInput {
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldAgentOperationProgressRecordInput {
pub session_id: String,
pub owner_user_id: String,
pub operation_id: String,
pub operation_type: String,
pub operation_status: String,
pub phase_label: String,
pub phase_detail: String,
pub operation_progress: u32,
pub error_message: Option<String>,
pub updated_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CustomWorldAgentActionExecuteRecordInput {
pub session_id: String,

View File

@@ -114,6 +114,7 @@ pub mod custom_world_agent_message_snapshot_type;
pub mod custom_world_agent_message_submit_input_type;
pub mod custom_world_agent_operation_type;
pub mod custom_world_agent_operation_get_input_type;
pub mod custom_world_agent_operation_progress_input_type;
pub mod custom_world_agent_operation_procedure_result_type;
pub mod custom_world_agent_operation_snapshot_type;
pub mod custom_world_agent_session_type;
@@ -339,6 +340,7 @@ pub mod start_ai_task_reducer;
pub mod start_ai_task_stage_reducer;
pub mod turn_in_quest_reducer;
pub mod unpublish_custom_world_profile_reducer;
pub mod upsert_custom_world_agent_operation_progress_procedure;
pub mod upsert_chapter_progression_reducer;
pub mod upsert_custom_world_profile_reducer;
pub mod upsert_npc_state_reducer;
@@ -579,6 +581,7 @@ pub use custom_world_agent_message_snapshot_type::CustomWorldAgentMessageSnapsho
pub use custom_world_agent_message_submit_input_type::CustomWorldAgentMessageSubmitInput;
pub use custom_world_agent_operation_type::CustomWorldAgentOperation;
pub use custom_world_agent_operation_get_input_type::CustomWorldAgentOperationGetInput;
pub use custom_world_agent_operation_progress_input_type::CustomWorldAgentOperationProgressInput;
pub use custom_world_agent_operation_procedure_result_type::CustomWorldAgentOperationProcedureResult;
pub use custom_world_agent_operation_snapshot_type::CustomWorldAgentOperationSnapshot;
pub use custom_world_agent_session_type::CustomWorldAgentSession;
@@ -846,6 +849,7 @@ pub use start_ai_task_reducer::start_ai_task;
pub use start_ai_task_stage_reducer::start_ai_task_stage;
pub use turn_in_quest_reducer::turn_in_quest;
pub use unpublish_custom_world_profile_reducer::unpublish_custom_world_profile;
pub use upsert_custom_world_agent_operation_progress_procedure::upsert_custom_world_agent_operation_progress;
pub use upsert_chapter_progression_reducer::upsert_chapter_progression;
pub use upsert_custom_world_profile_reducer::upsert_custom_world_profile;
pub use upsert_npc_state_reducer::upsert_npc_state;