diff --git a/apps/ai-game-creator-shell/src-tauri/src/process_session/lifecycle.rs b/apps/ai-game-creator-shell/src-tauri/src/process_session/lifecycle.rs index 8f259dad5..d5e5f166d 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/process_session/lifecycle.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/process_session/lifecycle.rs @@ -1435,11 +1435,13 @@ fn finalize_live_process_session( output.needs_reconciliation = true; } let needs_reconciliation = output.needs_reconciliation; - live.output_changed.notify_all(); - drop(output); + // 只有 live registry 已收束后才能发布可信终态。等待 `output_changed` 的调用方 + // 可能立即执行 run 级取消清理,而 registry 中的任何 live 条目都会被视为未完成会话。 if record_persisted && !needs_reconciliation { if let Ok(mut registry) = process_session_registry().lock() { registry.sessions.remove(&live.process_id); } } + live.output_changed.notify_all(); + drop(output); } diff --git a/server-rs/crates/api-server/src/editor_project.rs b/server-rs/crates/api-server/src/editor_project.rs index ecd8ef4b8..83b3dd00b 100644 --- a/server-rs/crates/api-server/src/editor_project.rs +++ b/server-rs/crates/api-server/src/editor_project.rs @@ -6650,6 +6650,7 @@ async fn resolve_editor_pixel_art_source_for_owner( )?; let generation_input_reference = if let Some(source_resource) = source_resource { Some(json!({ + "id": "source", "title": "原图", "label": source_resource .label diff --git a/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx b/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx index 04e6af030..7f2ef9a4c 100644 --- a/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx +++ b/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx @@ -2241,9 +2241,20 @@ describe('ImageCanvasEditorView generation integration', () => { projectId: 'editor-project-default', assetFolderId: 'project', generationInputs: { + version: 2, + action: 'spec.generate', fields: [ - { title: '玩法设定', value: '消除类派对玩法' }, - { title: '美术风格', value: '糖果玻璃拟物' }, + { id: 'specType', title: '规范类型', value: 'icon' }, + { + id: 'playSetting', + title: '玩法设定', + value: '消除类派对玩法', + }, + { + id: 'artStyle', + title: '美术风格', + value: '糖果玻璃拟物', + }, ], references: [], }, @@ -3165,9 +3176,16 @@ describe('ImageCanvasEditorView generation integration', () => { projectId: 'editor-project-default', assetFolderId: 'project', generationInputs: { + version: 2, + action: 'spec.generate', fields: [ - { title: '玩法设定', value: '背包整理玩法' }, - { title: '美术风格', value: '清爽卡通' }, + { id: 'specType', title: '规范类型', value: 'icon' }, + { + id: 'playSetting', + title: '玩法设定', + value: '背包整理玩法', + }, + { id: 'artStyle', title: '美术风格', value: '清爽卡通' }, ], references: [], }, diff --git a/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts b/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts index 7cd0757be..235b3f282 100644 --- a/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts +++ b/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts @@ -1206,6 +1206,38 @@ describe('ImageCanvasGenerationDialogModel', () => { }); }); + it('maps legacy ui spec.generate inputs to the unified icon spec composer', () => { + expect( + createSameSourceGenerationDialogDraft({ + sourceLayer: createLayer({ + sourceType: 'generated', + assetKind: 'icon-spec', + generationInputs: { + version: 2, + action: 'spec.generate', + fields: [ + { id: 'specType', title: '规范类型', value: 'ui' }, + { id: 'playSetting', title: '玩法设定', value: '消除玩法' }, + { id: 'artStyle', title: '美术风格', value: '糖果玻璃' }, + ], + references: [], + }, + }), + availableLayers: [], + canvasSize: { width: 960, height: 720 }, + viewport: { x: 0, y: 0, scale: 1 }, + mode: 'redraw', + }), + ).toMatchObject({ + mode: 'spec', + specType: 'icon', + specValues: { + playSetting: '消除玩法', + artStyle: '糖果玻璃', + }, + }); + }); + it('restores the narrowly scoped legacy scene recipe into the scene composer', () => { expect( createSameSourceGenerationDialogDraft({