# Editor Image Model Options Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 让图片画布的“生成角色形象”和“生成图标素材”支持 `nanobanana2` 与 `gpt-image-2`,并按模型提供合法的尺寸比例与大小尺寸选项。 **Architecture:** 前端抽出编辑器图片模型配置,生成面板只保存模型、比例、大小三个轻量状态;后端集中归一模型和尺寸组合,角色图与图标 spritesheet 继续走现有 VectorEngine、去背、OSS 和拆分链路。用户模型偏好用 localStorage 记住,默认 `nanobanana2`。 **Tech Stack:** React + TypeScript + Vitest;Rust Axum api-server;platform-image VectorEngine provider;Markdown 项目文档。 --- ## File Structure - Modify `C:\Genarrative\src\services\image-editor\editorProjectClient.ts` - 扩展图片生成和图标 spritesheet 请求类型,加入 `aspectRatio` 与 `imageSize`。 - 默认图标模型改为 `gemini-3.1-flash-image-preview` 对应的 `nanobanana2`。 - Modify `C:\Genarrative\src\services\image-editor\editorProjectClient.test.ts` - 先补失败测试:角色 / 图标请求会带模型、比例、大小。 - Modify `C:\Genarrative\src\components\image-editor\ImageCanvasEditorView.tsx` - 增加模型配置、选项归一、localStorage 偏好、角色 / 图标面板字段和提交 payload。 - Modify `C:\Genarrative\src\components\image-editor\ImageCanvasEditorView.test.tsx` - 先补失败测试:默认显示 nanobanana2,切换模型后比例 / 大小选项变更,并在请求中传递。 - Modify `C:\Genarrative\server-rs\crates\platform-image\src\vector_engine\request.rs` - 让 `512` 不被 normalize 成非法尺寸,并保留 gpt-image-2 尺寸。 - Modify `C:\Genarrative\server-rs\crates\platform-image\tests\vector_engine.rs` - 先补失败测试:nanobanana2 0.5K 请求 body 保留 `512`。 - Modify `C:\Genarrative\server-rs\crates\api-server\src\editor_project.rs` - 扩展请求 DTO,集中校验 `nanobanana2 / gpt-image-2` 与尺寸组合。 - 角色生成按模型走 with_model 调用;图标生成按模型和组合选择尺寸。 - Modify docs: - `C:\Genarrative\docs\【编辑器】画板角色形象生成入口设计-2026-06-15.md` - `C:\Genarrative\docs\【编辑器】画板图标素材生成入口设计-2026-06-15.md` - `C:\Genarrative\docs\technical\【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md` --- ### Task 1: Client request contract **Files:** - Modify: `C:\Genarrative\src\services\image-editor\editorProjectClient.ts` - Test: `C:\Genarrative\src\services\image-editor\editorProjectClient.test.ts` - [ ] **Step 1: Write failing tests** Add tests asserting `generateEditorImage` and `generateEditorIconSpritesheet` serialize `model`, `aspectRatio`, and `imageSize` when supplied. - [ ] **Step 2: Run test to verify failure** Run: `npm run test -- src/services/image-editor/editorProjectClient.test.ts -t "image model options"` Expected: FAIL because payloads do not include `aspectRatio` / `imageSize`. - [ ] **Step 3: Minimal implementation** Extend input types and JSON body builders to include optional `aspectRatio` and `imageSize`; change icon default model constant to `gemini-3.1-flash-image-preview` if not already. - [ ] **Step 4: Verify green** Run same test command. Expected: PASS. ### Task 2: Frontend panel state and local preference **Files:** - Modify: `C:\Genarrative\src\components\image-editor\ImageCanvasEditorView.tsx` - Test: `C:\Genarrative\src\components\image-editor\ImageCanvasEditorView.test.tsx` - [ ] **Step 1: Write failing tests** Add tests for: 1. opening `生成角色形象` defaults to model `nanobanana2` and shows `尺寸比例` / `大小尺寸`; 2. switching to `gpt-image-2` limits visible combinations and submits model + mapped size metadata; 3. icon spritesheet defaults to `nanobanana2` and submits the chosen model. - [ ] **Step 2: Run test to verify failure** Run: `npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx -t "模型|尺寸比例|大小尺寸"` Expected: FAIL because current UI has placeholder model button only. - [ ] **Step 3: Minimal implementation** Add model option config, dialog fields `imageModel/aspectRatio/imageSize`, localStorage helpers, option buttons/selects, and submit payload wiring. - [ ] **Step 4: Verify green** Run same test command. Expected: PASS. ### Task 3: Backend model and dimension normalization **Files:** - Modify: `C:\Genarrative\server-rs\crates\platform-image\src\vector_engine\request.rs` - Modify: `C:\Genarrative\server-rs\crates\api-server\src\editor_project.rs` - Test: `C:\Genarrative\server-rs\crates\platform-image\tests\vector_engine.rs` - Test: existing unit tests inside `editor_project.rs` - [ ] **Step 1: Write failing tests** Add tests covering: 1. `build_vector_engine_image_request_body_with_model("gemini-3.1-flash-image-preview", ..., "512", ...)` keeps `size = "512"`. 2. editor character model normalization defaults to nanobanana2 and maps `gpt-image-2 + 2:3 + 1K` to `1024x1536`. 3. icon spritesheet model normalization accepts both models. - [ ] **Step 2: Run backend tests to verify failure** Run: `cargo test -p platform-image --manifest-path server-rs/Cargo.toml vector_engine_request_body_can_use_nanobanana2_half_k -- --nocapture` `cargo test -p api-server --manifest-path server-rs/Cargo.toml editor_project -- --nocapture` Expected: FAIL until normalization functions exist. - [ ] **Step 3: Minimal implementation** Add constants and helpers: - `EDITOR_IMAGE_MODEL_NANOBANANA2 = "gemini-3.1-flash-image-preview"` - `EDITOR_IMAGE_MODEL_GPT_IMAGE_2 = "gpt-image-2"` - `normalize_editor_image_model` - `normalize_editor_generation_dimensions` Use with_model calls for character and icon generation responses. - [ ] **Step 4: Verify green** Run the same backend tests. Expected: PASS. ### Task 4: Documentation and final checks **Files:** - Modify docs listed above. - [ ] **Step 1: Update docs** Document defaults, user preference, model-specific options, and Apifox source URLs. - [ ] **Step 2: Run focused verification** Run: `npm run test -- src/services/image-editor/editorProjectClient.test.ts src/components/image-editor/ImageCanvasEditorView.test.tsx` `cargo test -p platform-image --manifest-path server-rs/Cargo.toml vector_engine_request_body_can_use_nanobanana2_half_k -- --nocapture` `cargo test -p api-server --manifest-path server-rs/Cargo.toml editor_project -- --nocapture` `npm run typecheck -- --pretty false` `npm run check:encoding` --- ## Self-Review - Spec coverage: covers role generation, icon spritesheet generation, default model, user preference, model-specific dimensions, docs. - Placeholder scan: no unresolved placeholders. - Type consistency: frontend uses `model/aspectRatio/imageSize`; backend DTO mirrors camelCase fields.