Merge branch 'master' into codex/rust-agent
Project CI / Repository checks (pull_request) Successful in 2m29s
Project CI / Frontend tests (pull_request) Successful in 3m13s
Project CI / Backend tests (pull_request) Failing after 5m1s
Project CI / Native shell tests (pull_request) Failing after 8m23s

This commit is contained in:
2026-08-31 10:50:50 +08:00
73 changed files with 3504 additions and 873 deletions
+17
View File
@@ -1096,6 +1096,11 @@ fn admin_editor_showcase_asset_payload_from_record(
model: record.model,
provider: record.provider,
task_id: record.task_id,
source_resource_id: record.source_resource_id,
source_image_src: record.source_image_src,
source_object_key: record.source_object_key,
source_asset_object_id: record.source_asset_object_id,
source_label: record.source_label,
asset_kind,
generation_inputs: sanitize_editor_generation_inputs(record.generation_inputs),
thumbnail_src: record.thumbnail_src,
@@ -1250,6 +1255,10 @@ fn admin_editor_asset_payload_from_record(
asset_kind,
generation_inputs: sanitize_editor_generation_inputs(record.generation_inputs),
source_resource_id: record.source_resource_id,
source_image_src: record.source_image_src,
source_object_key: record.source_object_key,
source_asset_object_id: record.source_asset_object_id,
source_label: record.source_label,
thumbnail_src: record.thumbnail_src,
generation_cost_mud_points: record.generation_cost_mud_points,
created_at: record.created_at,
@@ -4136,6 +4145,10 @@ mod tests {
provider: None,
task_id: None,
source_resource_id: None,
source_image_src: None,
source_object_key: None,
source_asset_object_id: None,
source_label: None,
asset_kind: Some("character".to_string()),
generation_inputs: None,
thumbnail_src: None,
@@ -4187,6 +4200,10 @@ mod tests {
asset_kind: Some("character".to_string()),
generation_inputs: None,
source_resource_id: None,
source_image_src: None,
source_object_key: None,
source_asset_object_id: None,
source_label: None,
thumbnail_src: None,
generation_cost_mud_points,
created_at: "2026-07-04T10:00:00Z".to_string(),
@@ -14612,6 +14612,10 @@ mod tests {
provider: None,
task_id: None,
source_resource_id: None,
source_image_src: None,
source_object_key: None,
source_asset_object_id: None,
source_label: None,
asset_kind: None,
generation_inputs: None,
thumbnail_src: None,
@@ -965,7 +965,7 @@ pub fn build_game_creation_seed_task_graph(
"预览并试玩验收",
GameCreationAgentGroup::Code,
"Playtest",
["preview-readiness"],
["publish-package"],
[".agent/logs/preview.log"],
["预览不是空白页,主循环和基础输入可用"],
),
@@ -974,7 +974,7 @@ pub fn build_game_creation_seed_task_graph(
"整理运营定位",
GameCreationAgentGroup::Publishing,
"Director",
["preview-playtest"],
["preview-readiness"],
[".agent/passes/pass-*/groups/publishing/director.md"],
["标题、卖点、标签和封面方向明确"],
),
@@ -247,6 +247,10 @@ pub struct AdminEditorAssetPayload {
pub asset_kind: Option<String>,
pub generation_inputs: Option<Value>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub thumbnail_src: Option<String>,
pub generation_cost_mud_points: u64,
pub created_at: String,
@@ -295,6 +299,11 @@ pub struct AdminEditorShowcaseAssetPayload {
pub model: Option<String>,
pub provider: Option<String>,
pub task_id: Option<String>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub asset_kind: Option<String>,
pub generation_inputs: Option<Value>,
pub thumbnail_src: Option<String>,
@@ -367,12 +367,7 @@ pub fn new_game_creation_app_seed_tasks() -> Vec<GameCreationAppTaskState> {
"生成可运行原型",
GameCreationAppAgentGroup::Code,
"Code",
[
"code-director",
"balance-seed",
"art-polish",
"audio-asset-plan",
],
["code-director", "balance-seed", "audio-asset-plan"],
["game/"],
["本地 Web 游戏项目可以通过 HTTP server 打开"],
),
@@ -399,7 +394,7 @@ pub fn new_game_creation_app_seed_tasks() -> Vec<GameCreationAppTaskState> {
"预览并试玩验收",
GameCreationAppAgentGroup::Code,
"Playtest",
["preview-readiness"],
["publish-package"],
[".agent/logs/preview.log"],
["预览不是空白页,主循环和基础输入可用"],
),
@@ -408,7 +403,7 @@ pub fn new_game_creation_app_seed_tasks() -> Vec<GameCreationAppTaskState> {
"整理运营定位",
GameCreationAppAgentGroup::Publishing,
"Director",
["preview-playtest"],
["preview-readiness"],
[".agent/passes/pass-*/groups/publishing/director.md"],
["标题、卖点、标签和封面方向明确"],
),
@@ -1609,12 +1604,7 @@ mod tests {
.expect("code prototype task");
assert_eq!(
code_prototype.dependencies,
[
"code-director",
"balance-seed",
"art-polish",
"audio-asset-plan"
]
["code-director", "balance-seed", "audio-asset-plan"]
);
}
@@ -1662,7 +1652,7 @@ mod tests {
vec!["balance-director", "art-asset-plan", "audio-director"]
);
for task_id in ["balance-director", "art-asset-plan", "audio-director"] {
for task_id in ["balance-director", "audio-director"] {
manifest
.tasks
.iter_mut()
@@ -1675,24 +1665,48 @@ mod tests {
.iter()
.map(|task| task.id.as_str())
.collect::<Vec<_>>(),
vec!["balance-seed", "art-polish", "audio-asset-plan"]
vec!["balance-seed", "art-asset-plan", "audio-asset-plan"]
);
manifest
.tasks
.iter_mut()
.find(|task| task.id == "balance-seed")
.unwrap()
.status = GameCreationAppTaskStatus::Completed;
for task_id in ["balance-seed", "audio-asset-plan"] {
manifest
.tasks
.iter_mut()
.find(|task| task.id == task_id)
.unwrap()
.status = GameCreationAppTaskStatus::Completed;
}
assert_eq!(
select_game_creation_app_ready_tasks(&manifest)
.iter()
.map(|task| task.id.as_str())
.collect::<Vec<_>>(),
vec!["art-polish", "audio-asset-plan"]
vec!["art-asset-plan", "code-prototype"]
);
for task_id in ["art-polish", "audio-asset-plan"] {
// code-prototype is ready even while both the art asset and polish
// tasks are still pending; the final completion gate checks the real
// art resources later.
assert_eq!(
manifest
.tasks
.iter()
.find(|task| task.id == "art-asset-plan")
.unwrap()
.status,
GameCreationAppTaskStatus::Pending
);
assert_eq!(
manifest
.tasks
.iter()
.find(|task| task.id == "art-polish")
.unwrap()
.status,
GameCreationAppTaskStatus::Pending
);
for task_id in ["art-asset-plan", "art-polish"] {
manifest
.tasks
.iter_mut()
@@ -166,6 +166,10 @@ pub struct AdminEditorAssetRecord {
pub asset_kind: Option<String>,
pub generation_inputs: Option<serde_json::Value>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub thumbnail_src: Option<String>,
pub generation_cost_mud_points: u64,
pub created_at: String,
@@ -198,6 +202,10 @@ pub struct EditorShowcaseAssetRecord {
pub provider: Option<String>,
pub task_id: Option<String>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub asset_kind: Option<String>,
pub generation_inputs: Option<serde_json::Value>,
pub thumbnail_src: Option<String>,
@@ -1496,6 +1504,10 @@ fn map_admin_editor_asset_snapshot(
asset_kind: snapshot.asset_kind,
generation_inputs,
source_resource_id: snapshot.source_resource_id,
source_image_src: snapshot.source_image_src,
source_object_key: snapshot.source_object_key,
source_asset_object_id: snapshot.source_asset_object_id,
source_label: snapshot.source_label,
thumbnail_src: snapshot.thumbnail_src,
generation_cost_mud_points: snapshot.generation_cost_mud_points,
created_at: format_timestamp_micros(snapshot.created_at_micros),
@@ -1533,6 +1545,10 @@ fn map_editor_showcase_asset_snapshot(
provider: snapshot.provider,
task_id: snapshot.task_id,
source_resource_id: snapshot.source_resource_id,
source_image_src: snapshot.source_image_src,
source_object_key: snapshot.source_object_key,
source_asset_object_id: snapshot.source_asset_object_id,
source_label: snapshot.source_label,
asset_kind: snapshot.asset_kind,
generation_inputs,
thumbnail_src: snapshot.thumbnail_src,
@@ -165,6 +165,10 @@ pub struct AdminEditorAssetRecord {
pub asset_kind: Option<String>,
pub generation_inputs: Option<serde_json::Value>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub thumbnail_src: Option<String>,
pub generation_cost_mud_points: u64,
pub created_at: String,
@@ -197,6 +201,10 @@ pub struct EditorShowcaseAssetRecord {
pub provider: Option<String>,
pub task_id: Option<String>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub asset_kind: Option<String>,
pub generation_inputs: Option<serde_json::Value>,
pub thumbnail_src: Option<String>,
@@ -1380,6 +1388,10 @@ fn map_editor_project_resource_snapshot(
provider: snapshot.provider,
task_id: snapshot.task_id,
source_resource_id: snapshot.source_resource_id,
source_image_src: snapshot.source_image_src,
source_object_key: snapshot.source_object_key,
source_asset_object_id: snapshot.source_asset_object_id,
source_label: snapshot.source_label,
asset_kind: snapshot.asset_kind,
generation_inputs,
public_showcase_enabled: snapshot.public_showcase_enabled,
@@ -1532,6 +1544,10 @@ fn map_editor_showcase_asset_snapshot(
provider: snapshot.provider,
task_id: snapshot.task_id,
source_resource_id: snapshot.source_resource_id,
source_image_src: snapshot.source_image_src,
source_object_key: snapshot.source_object_key,
source_asset_object_id: snapshot.source_asset_object_id,
source_label: snapshot.source_label,
asset_kind: snapshot.asset_kind,
generation_inputs,
thumbnail_src: snapshot.thumbnail_src,
@@ -25,6 +25,10 @@ pub struct AdminEditorAssetSnapshot {
pub asset_kind: Option<String>,
pub generation_inputs_json: Option<String>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub thumbnail_src: Option<String>,
pub generation_cost_mud_points: u64,
pub created_at_micros: i64,
@@ -23,6 +23,10 @@ pub struct EditorShowcaseAssetSnapshot {
pub provider: Option<String>,
pub task_id: Option<String>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub asset_kind: Option<String>,
pub generation_inputs_json: Option<String>,
pub thumbnail_src: Option<String>,
@@ -879,6 +879,10 @@ pub struct AdminEditorAssetSnapshot {
pub asset_kind: Option<String>,
pub generation_inputs_json: Option<String>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub thumbnail_src: Option<String>,
pub generation_cost_mud_points: u64,
pub created_at_micros: i64,
@@ -912,6 +916,10 @@ pub struct EditorShowcaseAssetSnapshot {
pub provider: Option<String>,
pub task_id: Option<String>,
pub source_resource_id: Option<String>,
pub source_image_src: Option<String>,
pub source_object_key: Option<String>,
pub source_asset_object_id: Option<String>,
pub source_label: Option<String>,
pub asset_kind: Option<String>,
pub generation_inputs_json: Option<String>,
pub thumbnail_src: Option<String>,
@@ -3217,9 +3225,13 @@ fn admin_list_editor_assets(
Ok(groups
.into_iter()
.flat_map(|(_, group_task_id, assets)| {
assets
.into_iter()
.map(move |row| admin_asset_snapshot_from_row(row, group_task_id.clone()))
assets.into_iter().map(move |row| {
let source = row
.source_resource_id
.as_ref()
.and_then(|id| ctx.db.editor_project_resource().resource_id().find(id));
admin_asset_snapshot_from_row(row, group_task_id.clone(), source.as_ref())
})
})
.collect())
}
@@ -6405,7 +6417,7 @@ fn admin_list_editor_showcase_assets(
cursor.as_ref(),
)
})
.map(showcase_snapshot_from_row)
.map(|asset| showcase_snapshot_from_row_with_ctx(Some(ctx), asset))
.collect::<Vec<_>>();
assets.sort_by(|left, right| {
@@ -6436,7 +6448,7 @@ fn admin_review_editor_showcase_asset(
if asset.review_status == EDITOR_SHOWCASE_STATUS_APPROVED
&& review_status == EDITOR_SHOWCASE_STATUS_APPROVED
{
return Ok(showcase_snapshot_from_row(asset));
return Ok(showcase_snapshot_from_row_with_ctx(Some(ctx), asset));
}
return Err("只有待审核素材可以审核".to_string());
}
@@ -7835,6 +7847,16 @@ fn asset_folder_snapshot_from_row(row: EditorAssetFolder) -> EditorAssetFolderSn
}
fn showcase_snapshot_from_row(row: EditorShowcaseAsset) -> EditorShowcaseAssetSnapshot {
showcase_snapshot_from_row_with_ctx(None, row)
}
fn showcase_snapshot_from_row_with_ctx(
ctx: Option<&ReducerContext>,
row: EditorShowcaseAsset,
) -> EditorShowcaseAssetSnapshot {
let source = row.source_resource_id.as_ref().and_then(|id| {
ctx.and_then(|value| value.db.editor_project_resource().resource_id().find(id))
});
EditorShowcaseAssetSnapshot {
showcase_id: row.showcase_id,
asset_id: row.asset_id,
@@ -7852,6 +7874,12 @@ fn showcase_snapshot_from_row(row: EditorShowcaseAsset) -> EditorShowcaseAssetSn
provider: row.provider,
task_id: row.task_id,
source_resource_id: row.source_resource_id,
source_image_src: source.as_ref().map(|value| value.image_src.clone()),
source_object_key: source.as_ref().and_then(|value| value.object_key.clone()),
source_asset_object_id: source
.as_ref()
.and_then(|value| value.asset_object_id.clone()),
source_label: source.as_ref().and_then(|value| value.prompt.clone()),
asset_kind: row.asset_kind,
generation_inputs_json: row.generation_inputs_json,
thumbnail_src: row.thumbnail_src,
@@ -8362,6 +8390,7 @@ fn asset_snapshot_from_row(ctx: &ReducerContext, row: EditorAsset) -> EditorAsse
fn admin_asset_snapshot_from_row(
row: EditorAsset,
group_task_id: Option<String>,
source: Option<&EditorProjectResource>,
) -> AdminEditorAssetSnapshot {
AdminEditorAssetSnapshot {
asset_id: row.asset_id,
@@ -8382,6 +8411,10 @@ fn admin_asset_snapshot_from_row(
asset_kind: row.asset_kind,
generation_inputs_json: row.generation_inputs_json,
source_resource_id: row.source_resource_id,
source_image_src: source.map(|value| value.image_src.clone()),
source_object_key: source.and_then(|value| value.object_key.clone()),
source_asset_object_id: source.and_then(|value| value.asset_object_id.clone()),
source_label: source.and_then(|value| value.prompt.clone()),
thumbnail_src: row.thumbnail_src,
generation_cost_mud_points: row.generation_cost_mud_points,
created_at_micros: row.created_at.to_micros_since_unix_epoch(),
@@ -20685,7 +20718,7 @@ mod tests {
admin_editor_asset_group_task_id_with(&slice, &mut task_id_aliases, |_, _| {
panic!("persisted group must not depend on project resources")
});
let snapshot = admin_asset_snapshot_from_row(slice, group_task_id);
let snapshot = admin_asset_snapshot_from_row(slice, group_task_id, None);
assert_eq!(snapshot.task_id.as_deref(), Some(split_task_id));
assert_eq!(snapshot.group_task_id.as_deref(), Some(source_task_id));