Switch to VectorEngine gpt-image-2 and edits

Replace uses of the legacy `gpt-image-2-all` model with `gpt-image-2` and standardize image workflows: no-reference generation uses POST /v1/images/generations, any-reference flows use POST /v1/images/edits with multipart `image` parts. Update SKILLs, generation scripts, decision logs, and docs to reflect the contract change and edits-vs-generations guidance. Apply corresponding changes across backend (api-server match3d/puzzle modules, openai image adapter, mappers, telemetry, spacetime client/module), frontend components and services (Match3D, Puzzle, CreativeImageInputPanel, runtime shells), and add new spritesheet/parser files and tests. Also add media/logo.png. These changes align repository code and documentation with the VectorEngine image API contract and update generation/upload handling (green-screen -> alpha processing, spritesheet handling, and related tests).
This commit is contained in:
2026-05-22 03:06:41 +08:00
parent 321e1ea33a
commit ae014ac881
90 changed files with 7078 additions and 3389 deletions

View File

@@ -71,10 +71,12 @@ use crate::{
},
auth::AuthenticatedAccessToken,
config::AppConfig,
generated_asset_sheets::apply_generated_asset_sheet_green_screen_alpha,
http_error::AppError,
openai_image_generation::{
DownloadedOpenAiImage, OpenAiGeneratedImages, OpenAiReferenceImage,
build_openai_image_http_client, create_openai_image_edit, create_openai_image_generation,
build_openai_image_http_client, create_openai_image_edit,
create_openai_image_edit_with_references, create_openai_image_generation,
require_openai_image_settings,
},
platform_errors::map_oss_error,
@@ -95,10 +97,10 @@ const MATCH3D_DEFAULT_DIFFICULTY: u32 = 4;
const MATCH3D_DRAFT_GENERATION_POINTS_COST: u64 = 10;
const MATCH3D_BACKGROUND_IMAGE_POINTS_COST: u64 = 2;
const MATCH3D_ITEM_ASSETS_POINTS_PER_BATCH: u64 = 2;
const MATCH3D_MATERIAL_ITEM_BATCH_SIZE: usize = 5;
const MATCH3D_MATERIAL_ITEM_BATCH_SIZE: usize = 20;
const MATCH3D_ITEM_VIEW_COUNT: usize = 5;
const MATCH3D_MATERIAL_GRID_SIZE: u32 = 5;
const MATCH3D_MAX_GENERATED_ITEM_COUNT: usize = 25;
const MATCH3D_MATERIAL_GRID_SIZE: u32 = 10;
const MATCH3D_MAX_GENERATED_ITEM_COUNT: usize = 20;
const MATCH3D_MATERIAL_VECTOR_ENGINE_GEMINI_MODEL: &str = "gemini-3-pro-image-preview";
const MATCH3D_MATERIAL_VECTOR_ENGINE_GEMINI_ASPECT_RATIO: &str = "1:1";
const MATCH3D_LEGACY_MODEL_DOWNLOAD_TIMEOUT_MS: u64 = 3 * 60_000;
@@ -118,7 +120,7 @@ const MATCH3D_QUESTION_DIFFICULTY: &str = "如果难度是从1-10你要创作
const MATCH3D_CLICK_SOUND_ASSET_KIND: &str = "match3d_click_sound";
const MATCH3D_PIXEL_RETRO_STYLE_PROMPT: &str = "真正复古像素 2D 游戏道具 sprite 风格,先以约 64x64 低分辨率像素块绘制再按整数倍放大,硬边方块像素清晰可见,有限色板 12-24 色,禁止抗锯齿、柔焦、平滑渐变、真实 3D 渲染、PBR 材质和摄影光照。";
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DConfigJson {
theme_text: String,
@@ -170,15 +172,33 @@ struct Match3DGeneratedItemImageView {
image_object_key: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Match3DGeneratedBackgroundAsset {
prompt: String,
#[serde(default)]
level_scene_prompt: Option<String>,
#[serde(default)]
level_scene_image_src: Option<String>,
#[serde(default)]
level_scene_image_object_key: Option<String>,
#[serde(default)]
image_src: Option<String>,
#[serde(default)]
image_object_key: Option<String>,
#[serde(default)]
ui_spritesheet_prompt: Option<String>,
#[serde(default)]
ui_spritesheet_image_src: Option<String>,
#[serde(default)]
ui_spritesheet_image_object_key: Option<String>,
#[serde(default)]
item_spritesheet_prompt: Option<String>,
#[serde(default)]
item_spritesheet_image_src: Option<String>,
#[serde(default)]
item_spritesheet_image_object_key: Option<String>,
#[serde(default)]
container_prompt: Option<String>,
#[serde(default)]
container_image_src: Option<String>,
@@ -445,8 +465,17 @@ impl From<shared_contracts::match3d_works::Match3DGeneratedItemAssetResponse>
.background_asset
.map(|asset| Match3DGeneratedBackgroundAsset {
prompt: asset.prompt,
level_scene_prompt: asset.level_scene_prompt,
level_scene_image_src: asset.level_scene_image_src,
level_scene_image_object_key: asset.level_scene_image_object_key,
image_src: asset.image_src,
image_object_key: asset.image_object_key,
ui_spritesheet_prompt: asset.ui_spritesheet_prompt,
ui_spritesheet_image_src: asset.ui_spritesheet_image_src,
ui_spritesheet_image_object_key: asset.ui_spritesheet_image_object_key,
item_spritesheet_prompt: asset.item_spritesheet_prompt,
item_spritesheet_image_src: asset.item_spritesheet_image_src,
item_spritesheet_image_object_key: asset.item_spritesheet_image_object_key,
container_prompt: asset.container_prompt,
container_image_src: asset.container_image_src,
container_image_object_key: asset.container_image_object_key,