Feat/gpt-image-2.5 集成 #422
Open
k88936
wants to merge 88 commits from
feat/gptimage2to2.5 into master
pull from: feat/gptimage2to2.5
merge into: GenarrativeAI:master
GenarrativeAI:master
GenarrativeAI:feat/external-scene-generation
GenarrativeAI:feat/tribo3d-integeration
GenarrativeAI:fix/mobile-style
GenarrativeAI:feat/msg-queue-to-rust
GenarrativeAI:opt/test-compile-warning
GenarrativeAI:fix/api-timeout
GenarrativeAI:codex/admin-gray-game-publish
GenarrativeAI:codex/remove-agc-codex-restrictions
GenarrativeAI:backup/agc-macos-dualarch-node-runtime
GenarrativeAI:feat/Crt_Ws
GenarrativeAI:codex/preview-llm-router-config
GenarrativeAI:fix/stroke-width-regression-from-285
GenarrativeAI:agent-organize
GenarrativeAI:feat/game-agent-canvas-resource-workbench-v2
GenarrativeAI:feat/agc-new-workflow
GenarrativeAI:fix/agc-release-version-sync
GenarrativeAI:codex/shared-components-followup
GenarrativeAI:codex/game-agent-runtime-interaction-design
GenarrativeAI:feat/spine-sequence-export-v2
GenarrativeAI:codex/game-agent-run
GenarrativeAI:codex/ui-spritesheet-durable-transaction-latest
GenarrativeAI:feat/art-agent-more-tools
GenarrativeAI:codex/editor-canvas-null-source-repair
GenarrativeAI:hotfix/editor-layout-2mib
GenarrativeAI:codex/showcase
Labels
Clear labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Breaking change that won't be backward compatible
Something is not working
Documentation changes
Improve existing functionality
New functionality
This is security issue
Issue or pull request related to testing
Priority
Critical
1
The priority is critical
Priority
High
2
The priority is high
Priority
Low
4
The priority is low
Priority
Medium
3
The priority is medium
Reviewed
Confirmed
1
Issue has been confirmed
Reviewed
Duplicate
2
This issue or pull request already exists
Reviewed
Invalid
3
Invalid issue
Reviewed
Won't Fix
3
This issue won't be fixed
Status
Abandoned
3
Somebody has started to work on this but abandoned work
Status
Blocked
1
Something is blocking this issue or pull request
Status
Need More Info
2
Feedback is required to reproduce issue or to continue work
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: GenarrativeAI/Genarrative#422
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "feat/gptimage2to2.5"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
手动实现 Debug 并在其中把 api_key 渲染为 <redacted> settings() 公开返回该结构体,默认 derive 会让 {:?} 直接打印 provider 凭据1
server-rs/crates/platform-image/src/raw_image_edit/mod.rs:151ImageProviderSettings,并在函数入口取provider_label = settings.provider.as_str(),错误变体、审计与 tracing 统一用它。PlatformImageError、build_failure_audit、日志都硬编码VECTOR_ENGINE_PROVIDER,而本函数用的是GPT_IMAGE_2_5_EDIT_MODEL(Tiantoken),失败会被错误归因到 vector-engine。89587c9e9修正 raw image edit 的 provider 归属。2
server-rs/crates/platform-image/src/image_provider/transport/curl.rs:198map_curl_error(provider: ImageProvider, ...),日志与PlatformImageError::Request都用参数化 provider。map_curl_error仍硬编码VECTOR_ENGINE_PROVIDER,Tiantoken 的 libcurl 传输失败被误标。5cba2dbeb修正 libcurl 传输错误的 provider 归属。3
server-rs/crates/platform-image/src/image_provider/transport/client.rs:14build_image_http_client保留.pool_max_idle_per_host(0),即关闭 idle keep-alive。08577b66c「fix: stabilize puzzle vector engine asset generation」加入,属针对上游网关的稳定性规避;且图片生成本身是 30–120 秒级的长请求,建连开销占比很低(评审自己也标performance · low)。若要恢复连接复用,建议单独做生产实测与对比,不要顺手改。4
server-rs/crates/platform-image/src/image_provider/transport/mod.rs:1mod client;/mod curl;普通模块声明。#[path = "client.rs"]这类属性冗余,且暗示非标准布局。99081455e移除 image_provider transport 冗余 path 属性。5
server-rs/crates/platform-image/tests/image_provider.rs:533-534format!("\"model\":\"{GPT_IMAGE_2_5_GENERATION_MODEL}\""),并导入GPT_IMAGE_2_5_EDIT_MODEL覆盖编辑体断言。345c9c3a9收敛 ImageProvider 集成测试的模型断言。6
server-rs/crates/platform-image/tests/image_provider.rs:539image_generation_uses_default_generation_model_on_success。gpt_image_2/without_fallback,与实际断言的 2.5 + 无跨模型回退不符。fa2b36654修正 ImageProvider 生成测试的错误命名。7
server-rs/crates/platform-image/src/image_provider/protocol/response.rs:15handle_image_response(..., provider: ImageProvider, ...),Upstream/ResponseParse/MissingImage与 tracing 字段都用provider.as_str()。PlatformImageError::provider() == "vector-engine",污染重试/审计/预算判定。90b77d6bd修正共享响应处理的 provider 归属。8
server-rs/crates/platform-image/src/image_provider/protocol/request.rs:20normalize_image_model把空/空白输入归一到GPT_IMAGE_2_5_GENERATION_MODEL,与build_image_request_body的默认值一致;显式传入的模型(含历史gpt-image-2)原样保留,交给resolve_image_provider路由。build_image_request_body_with_model("")会悄悄用旧gpt-image-2,与新的默认生成模型不一致。939c35a9b统一缺省图片模型的归一化结果(并补测试断言两者产出同一请求体)。9
server-rs/crates/platform-image/src/image_provider/protocol/request.rs:107resolve_image_provider用NANOBANANA_2_MODEL常量匹配 nanobanana 分支。874d061cb统一 ImageProvider 模型路由使用的 nanobanana 常量。10
server-rs/crates/platform-editor-agent/src/agent/tools/generate_ui_design.rs:37GPT_IMAGE_2_5_BUSINESS_NAME;api-server 适配层在反序列化前把gpt-image-2/gpt-image-2-c归一为gpt-image-2.5。validate_args判InvalidModel,并带崩 3 个 api-server 测试。bd0a06e3d兼容图片工具的历史 gpt-image-2 模型别名(新增normalize_legacy_image_model_args并接入图片类工具的校验与计价入口)。11
server-rs/crates/platform-editor-agent/src/agent/tools/image_generation_options.rs:78supported_image_sizes只认 nanobanana2 / gpt-image-2.5;generate-image的历史gpt-image-2参数由 api-server 边界先归一。generate-image会直接拒绝gpt-image-2(dyn_pricing_uses_the_supplied_runtime_snapshot因此失败)。bd0a06e3d。12
server-rs/crates/platform-image/src/image_provider/runtime/executor.rs:70-76ensure_provider_matches_model:先resolve_image_provider,再与settings.provider比对,不一致直接返回InvalidRequest(含中文原因)。resolve_image_provider结果,会把属于另一个 provider 的模型配上当前 provider 的base_url/api_key发出去(用错密钥打错端点);编辑入口下方的参考图数量错误分支还硬编码VECTOR_ENGINE_PROVIDER。42fdb57ef校验图片请求模型与 provider 绑定一致(含新增单测,并把 GPT 模型相关集成测试的 settings provider 调整为 tiantoken);参考图数量分支的 provider 归属由e393a803f一并修掉。13
server-rs/crates/platform-image/src/image_provider/runtime/executor.rs:855-858record_image_model_fallback及为它服务的“先解析响应/下载图片”预计算都已删除,重试只保留同模型重试。1c950df11删除已失效的跨模型回退分支。14
server-rs/crates/platform-image/src/image_provider/runtime/budget.rs:89request_budget_exhausted_error(provider: ImageProvider, ...),tracing 与错误字段都用该 provider;image_source.rs的参考图下载错误同样带上 provider。d3407e891修正预算与图片下载错误的 provider 归属。15
server-rs/crates/platform-image/src/image_provider/runtime/types.rs:18-22ImageProviderSettings手写Debug,api_key固定输出<redacted>。Debug配合公开的settings()访问器会打印凭据。6c33459b9为 ImageProviderSettings 增加脱敏 Debug 实现。16
server-rs/crates/api-server/src/editor_project.rs:3191-3195provider_model按分支选择——nanobanana2 用自身;无参考图用GPT_IMAGE_2_5_GENERATION_MODEL;有参考图(走images/edits)用GPT_IMAGE_2_5_EDIT_MODEL。flare-c打编辑端点。ae257a6ff按端点选择编辑器生成的 provider_model。17
server-rs/crates/api-server/src/editor_project.rs:8517GPT_IMAGE_2_5_EDIT_MODEL。8924bf335修正 UI 设计素材提取的编辑模型。18
server-rs/crates/api-server/src/character_visual_assets.rs:952reference_images是否为空在GPT_IMAGE_2_5_GENERATION_MODEL/GPT_IMAGE_2_5_EDIT_MODEL间选择。5ce267ae8按参考图选择角色主形象的 provider 模型。19
server-rs/crates/api-server/src/openai_image_generation.rs:410-420client_for_model之前先做本地空参考图校验,直接返回 400「缺少参考图」;client_for_model仍保留expect(依赖启动期必然初始化客户端这一前提)。expect出客户端,再走参考图校验,缺参考图的请求会 panic。1a2e60bf0修复图片编辑缺少参考图时的 panic(vector_engine_multi_reference_edit_rejects_empty_references恢复 400 + 缺少参考图)。残留可选优化:client_for_model的expect仍是硬失败,若要彻底改成Result属于接口级调整,未在本次范围。20
server-rs/crates/api-server/src/editor_project.rs:4007gpt-image-2,与实现不符。ff4f42d2f修正编辑器生成模型归一化注释。21
src/components/image-editor/ImageCanvasGenerationModel.ts:395-398EDITOR_MODEL_MUD_POINT_CONFIG里是[IMAGE_MODEL_GPT_IMAGE_2_5];normalizeEditorImageModel会把gpt-image-2/gpt-image-2-c映射为gpt-image-2.5;calculateEditorImageModelPrice先归一再查价;EDITOR_IMAGE_MODEL_MUD_POINT_CONFIG仍保留历史gpt-image-2档位供测试与对读。normalizeEditorImageModel仍原样返回gpt-image-2,导致回落到 nanobanana 价(12/24)」。该前提在当前代码已不成立(属过期结论)。normalizeEditorImageModel的映射解决,无需再改。现有用例「支持用后端下发的模型定价覆盖按钮泥点」只下发gpt-image-2.5的价格,仍断言calculateEditorImageModelPrice('gpt-image-2','1K') === 29,当前通过。22
server-rs/crates/api-server/src/editor_generation_config.rs:164spec_model_mud_points对None/ 空模型显式回退EDITOR_IMAGE_MODEL_GPT_IMAGE_2_5_GENERATION,只有非空才走normalize_editor_image_model。normalize_editor_image_model(None)会落到 nanobanana 档,生成规范计价会从 5 意外变成 24。0c54cca81修正生成规范缺省模型的计价档。23
server-rs/crates/platform-image/src/image_provider/protocol/payload.rs:3parse_json_payload(..., provider: ImageProvider),ResponseParse用provider.as_str()。4888a0eb0修正响应解析错误的 provider 归属。24
server-rs/crates/platform-editor-agent/src/agent/tools/edit_image.rs:158EditImageTool::validate_args只接受GPT_IMAGE_2_5_BUSINESS_NAME;api-server 适配层在进入校验前归一历史别名,EditImageTool::pricing也已从GPT_IMAGE_2_MODEL改为GPT_IMAGE_2_5_BUSINESS_NAME。edit-image调用model: "gpt-image-2"会判InvalidModel;pricing 仍引旧常量。bd0a06e3d。25
server-rs/crates/platform-image/src/image_provider/runtime/executor.rs:840auditable_image_model覆盖gpt-image-2、gpt-image-2-c、gpt-image-2.5、gpt-image-2.5-flare-c、gpt-image-2.5-sunburst-c、gemini-3.1-flash-image-preview。image_model丢字段。0817ea815补齐审计模型白名单的 GPT Image 2.5 与 nanobanana 模型。26
server-rs/crates/platform-image/src/image_provider/tests.rs:9image_provider/mod.rs声明了#[cfg(test)] mod tests;,extract_image_urls/extract_b64_images提升为pub(crate),测试模块补齐导入与base64::Engine用法。cargo test会静默跳过其中所有用例。c86ac0422恢复 image_provider 单元测试模块(cargo test -p platform-image现在会真正执行这些用例)。27
src/components/image-editor/ImageCanvasGenerationModel.ts:137EDITOR_IMAGE_MODEL_OPTIONS只剩 nanobanana2 与 gpt-image-2.5;decodeCanvasGenerationInputs的normalizeStringOption会先跑normalizeEditorImageModel(历史值 →gpt-image-2.5)再判断是否在选项内,并对历史值追加model回退告警。gpt-image-2会因不在选项里被重写成DEFAULT_IMAGE_MODEL(nanobanana2)。当前代码已不会这样:归一发生在选项校验之前,历史值稳定迁移到gpt-image-2.5。5b1b0ddb9已补回归用例「restores the concrete legacy GPT image value to GPT Image 2.5 with a warning」,当前通过)。无需再改。28
server-rs/crates/api-server/src/editor_generation_config.rs:271-276—— 下面先把背景讲透A. 这套「泥点定价配置」是什么
models: { "<模型 key>": { unit: "perGeneration" | "perSecond", price: 数字 } 或 { prices: { "1K": 数字, "2K": 数字 } } }。EditorGenerationPricingConfig+EditorGenerationPricingStore(editor_generation_config.rs)。crates/api-server/config/editor-generation-pricing.default.json(include_str!)。/var/lib/genarrative/editor-generation-pricing/editor-generation-pricing.override.json(或仓库里的.app/editor-generation-pricing.override.json)。state.rs::editor_generation_pricing())会先拉 SpacetimeDB record,成功就用它;失败则warn!后回退到本地缓存/override/default 快照。B. 本次迁移对 key 做了什么
gpt-image-2。gpt-image-2.5-flare-c(生成,含带参考图的普通生成)与gpt-image-2.5-sunburst-c(编辑 / 快速编辑 / 原位修改 / raw edit)。validate()现在把这两个 key 连同尺寸档位(各需 1K、2K)列为必填,和其它模型(nanobanana、视频、音效、音乐)一起校验。C. 为什么会出现 backfill(这就是你问的那个函数)
gpt-image-2。backfill_legacy_gpt_image_2_5_pricing(editor_generation_config.rs:396-430)就是针对这件事的一次性兼容垫片,逻辑只有四步:gpt-image-2,取不到就退回默认 JSON 里的gpt-image-2;or_insert到gpt-image-2.5-flare-c与gpt-image-2.5-sunburst-c(只补缺失的 key,绝不覆盖已有值);docs/adr/【ADR】GPT Image 2.5模型路由与历史值兼容-2026-09-18.md)明确写了「旧单 key 配置只允许受控 backfill,并留下兼容 TODO」「不执行数据库历史迁移」,就是这个意思。D. 问题(成立)
load_editor_generation_pricing_from_candidates里读完 override JSON 后调用)。crates/api-server/src/state.rs::editor_generation_pricing_from_record()(从第 444 行起)。它把 record 里的 models 拼成EditorGenerationPricingConfig,只补了音效模型(ElevenLabs),然后直接config.validate()—— 没有调用 GPT 图片的 backfill。gpt-image-2)读回来时校验失败。E. 影响有多大(说清楚,不用慌)
editor_generation_pricing()的Err(error)分支 →warn!后返回本地快照。所以不会 500,也不会算成 0 泥点。F. 建议修法(很小,但会碰到线上已持久化数据,所以留给你点头)
backfill_legacy_gpt_image_2_5_pricing由fn改为pub(crate) fn;state.rs::editor_generation_pricing_from_record里,let config = EditorGenerationPricingConfig { models };之后、config.validate()?;之前插入一行crate::editor_generation_config::backfill_legacy_gpt_image_2_5_pricing(&mut config, legacy_fallback, "SpacetimeDB 模型定价配置")?;(
legacy_fallback已经是该函数的入参、就是本地快照,正好当兜底来源);# TODO:注释改成「record 与 override 两条路径都已回填」,等线上数据全部重存过一轮后再删掉这块兼容。validate()里塞兼容(把兼容逻辑散进校验)、或做一次性数据迁移(ADR 明确不迁移历史记录)。045910989按上面 1 / 2 / 3 落地(backfill_legacy_gpt_image_2_5_pricing改pub(crate)、editor_generation_pricing_from_record在validate()前先回填、TODO 注释改成覆盖 override 与 record 两条路径),并补两条用例:旧 record 自动补齐两个 2.5 key、显式 2.5 key 不被回填覆盖。29
server-rs/crates/api-server/src/editor_generation_config.rs:168(实际是editor_generation_config.rs:1103的用例)editor_generation_pricing_rejects_missing_required_image_size构造一份 JSON,GPT 图片只有"gpt-image-2": { "1K": 20 }(故意缺 2K),想验证「缺尺寸档位要报错」,末尾断言错误文案包含gpt-image-2 缺少 2K。validate()的顺序是 nanobanana →gpt-image-2.5-flare-c→gpt-image-2.5-sunburst-c→ 视频……。这份 JSON 里两个新 key 根本不存在,所以第一个报错是models 缺少模型 gpt-image-2.5-flare-c 的泥点配置,走不到「缺 2K」那一步。用例的意图(缺档位要拦下来)依然有效,只是夹具和断言过期了。gpt-image-2.5-flare-c给{ "1K": 20 }(缺 2K),gpt-image-2.5-sunburst-c给{ "1K": 3, "2K": 5 },断言改成包含models.gpt-image-2.5-flare-c 缺少 2K 的泥点配置。既保留原意又对齐新 key。缺少模型 gpt-image-2.5-flare-c:不推荐,容易被误读成「校验只看新 key」,也测不到缺档位分支。cargo test -p api-server editor_generation_config一起收口最省事;我不想在你的迁移决策落地前先把测试改成只反映当前(可能还会变)的实现。6318baf7c按 (a) 落地:夹具换成两个新 key(gpt-image-2.5-flare-c只给1K缺2K,gpt-image-2.5-sunburst-c给1K/2K),断言改为包含models.gpt-image-2.5-flare-c 缺少 2K 的泥点配置,用例仍覆盖「缺档位必须拦下来」。30
server-rs/crates/api-server/src/editor_project.rs:380editor_project_icon.rs的EditorImageProviderRequest构造点已补provider_model,且因该路径始终带参考图,取值是GPT_IMAGE_2_5_EDIT_MODEL。E0063: missing field provider_model编译失败(critical)。2e2ed47be补齐图标 spritesheet 请求的 provider_model。(另:dedc58cce顺带修掉同批遗留的GPT_IMAGE_2_C_MODEL未重导出编译错误。)附:原 review 之外的当前失败项
A
crates/api-server/src/editor_project.rs::publication_material_generation_is_locked_to_gpt_image_2generate_editor_image_for_owner的源码文本,要求出现Some(GPT_IMAGE_2_MODEL)。Some(GPT_IMAGE_2_5_BUSINESS_NAME),文本断言过期,用例失败。fa84a364d修正宣发素材生成锁定的模型断言(顺带把用例改名为..._gpt_image_2_5)。B
crates/api-server/src/app.rs::public_editor_generation_pricing_route_returns_default_configpayload["models"]["gpt-image-2"]["prices"]["1K"] == 3。public_projection()现在会删除gpt-image-2、把gpt-image-2.5-flare-c投影成业务名gpt-image-2.5,所以旧 key 读出来是Null,用例失败。4415723f7同步公开定价路由用例到 GPT Image 2.5 公开投影(断言gpt-image-2.5的 3 / 5,并断言gpt-image-2、gpt-image-2.5-flare-c、gpt-image-2.5-sunburst-c都不公开)。C
crates/api-server/src/app.rs::admin_editor_generation_pricing_route_saves_config_and_updates_public_routegpt-image-2的定价 JSON,期望 200。validate()新增两个必填 2.5 档位后该 JSON 非法,接口返回 400(save_editor_generation_pricing→store.replace→validate→Invalid),用例失败。28e6e67e9补齐后台定价保存用例的 GPT Image 2.5 档位(payload 换成gpt-image-2.5-flare-c31/62 与gpt-image-2.5-sunburst-c41/82;公开断言按生成档 62 校验并确认不透出具体 key;新增 admin 读回具体 key 的断言,覆盖 ADR 里「admin 定价接口是 concrete key 的例外」)。D 环境/外部依赖类失败(原判断为「与本次改动无关」,复核后为可修复的代码/夹具错配)
editor_background_music_prompt_assist::tests::*(16 项)、editor_sound_effect_prompt_assist::tests::*(4 项)、vector_engine_audio_generation::sound_effect_translation::tests::*(8 项)、state::tests::app_state_builds_editor_agent_llm_client_from_vector_engine_settings(1 项)。editor agent LLM client should exist)。b294cbc3d把 Tiantoken 凭据改成只从进程环境变量TIANTOKEN_*现读之后,这 3 组 mock 夹具仍用AppConfig.vector_engine_base_url/vector_engine_api_key构造AppState,state.vector_engine_llm_client()于是全是None,路由统一回 503editor_llm_unavailable;state那条同源,断言里的 base URL 与配置来源都已过期。1c1deff73把读取点从AppState::new前移到AppConfig::from_env,新增AppConfig.tiantoken_base_url/AppConfig.tiantoken_api_key(只读TIANTOKEN_*,仍不回退 VectorEngine 凭据),删除现读环境变量的config::tiantoken_*访问器;三处 mock 夹具与state用例改用 config 字段,避免在并行用例里set_var互相踩TIANTOKEN_*。cargo test -p api-server现为 1060 passed / 0 failed / 6 ignored。─── 1. 【已修复 3d498e280】 .codex/skills/gpt-image-2-apimart/scripts/generate-anthro-cat-illustrations.mjs:259 ───
现状:requestImagePayload 里是
for (const model of [preferredImageModel])包住整个请求,内部还有catch (error) { throw error; },循环之后跟一条不可达的 throw。问题:跨模型回退删除后,单元素循环和无操作 catch 都是死代码,会让人误以为仍保留 fallback。
建议修复:直接用
const model = preferredImageModel;,去掉单元素循环、无操作 catch 与不可达 throw。本次处理:已按上述方式改写;请求体、超时、vectorEngineResponseParse/vectorEngineBody 等错误语义不变。已跑
node --check。─── 2. 【已修复 13b40fd6a】 .codex/skills/gpt-image-2-apimart/scripts/generate-template-samples.mjs:229 ───
现状/问题:与第 1 项同形的单元素模型循环 + 无操作 catch。
建议修复:同样改为直接用 preferredImageModel,删除循环与 no-op catch。
本次处理:已修复;请求与错误语义不变。已跑
node --check。─── 3. 【已修复 fc55bec48】 .codex/skills/gpt-image-2-apimart/scripts/generate-anthro-cat-illustrations.mjs:372 ───
现状:dry-run 输出里每个 request 都带
fallbackModel: null。问题:该字段恒为 null,会让读取 dry-run 结果的人以为还存在跨模型回退。
建议修复:删除该字段,requests 只保留真实请求信息(id/title/body)。
本次处理:已删除。已跑
node --check。─── 4. 【已修复 cf6b855c9】 .codex/skills/gpt-image-2-apimart/scripts/generate-template-samples.mjs:348 ───
现状/问题:与第 3 项相同的恒为 null 的 fallbackModel 字段。
建议修复:删除该字段。
本次处理:已删除。已跑
node --check。─── 5. 【已修复 e7319dea5】 server-rs/crates/api-server/src/editor_agent/tool.rs:233-239 ───
现状:normalize_legacy_image_model_args 返回 owned Value,未命中别名时
value.clone();随后 parse_invalid_args / parse_internal 内部再value.clone()交给 null_tool_args_as_missing。validate / pricing / display / prepare 都会经过这里。问题:常见「无需归一」路径要深拷贝两份 JSON 树。
建议修复:改用
Cow<'_, Value>——未改写返回 Borrowed、改写返回 Owned;包装函数先绑定let normalized = ...再传&normalized,让常见路径从两次深拷贝降为一次。本次处理:已按上述方式实现;非图片工具仍保留原来的
&Value接口,未扩大改动面。已跑cargo check -p api-server与cargo test -p api-server editor_agent::tool::tests(13 项通过,含dyn_validation_normalizes_legacy_gpt_image_2_alias)。─── 6. 【保留给你】 server-rs/crates/api-server/src/state.rs:638-650 ───
现状:
AppState::new启动时无条件构造 VectorEngine 与 Tiantoken 两个图片 provider client;任一 base URL / API key 缺失就直接AppStateInitError,api-server 起不来。两个 client 还共用config.vector_engine_image_request_timeout_ms同一个超时字段(TIANTOKEN_IMAGE_REQUEST_TIMEOUT_MS会写进该字段并覆盖它)。问题:这是有意的失败关闭,能保证运行期不缺配置;代价是每次部署都要同时备齐两套凭据——只跑玩法 / nanobanana 的环境也得配
TIANTOKEN_*,只用编辑器 GPT Image 2.5 的环境也得配VECTOR_ENGINE_*。建议修复(需你拍板):若是有意的运维收口,保持现状,并把两套 env 在
deploy/env/api-server.env.example与运维文档里标成必需项;若要放宽,改成按已启用模型集合校验必需凭据,或首次使用懒加载 + 缓存。未改原因:这是启动期行为与部署契约变更,会影响现网 compose 与环境变量,必须由你确认。
─── 7. 【保留给你】 server-rs/crates/api-server/src/editor_project.rs:3192-3198 ───
现状:带参考图的非 nanobanana 生成,provider_model 取 GPT_IMAGE_2_5_EDIT_MODEL(gpt-image-2.5-sunburst-c)走编辑端点;但预扣费仍走
image_generation_mud_points(normalized_kind, model, size)。问题:生成档与编辑档价格不同(默认编辑档更贵),带参考图的生成会「按生成档收费、实际调用编辑模型/端点」。
建议修复(需你确认产品口径):若参考图存在时本就该按编辑档计费,就把计费切到
image_edit_model_mud_points;若是有意吸收编辑成本,需要写明并保证展示价、预扣价、结算价一致。未改原因:这是计费语义变更,必须由你拍板。
─── 8. 【已修复 ee7e6728e】 server-rs/crates/platform-image/src/image_provider/protocol/request.rs:105-115 ───
现状:resolve_image_provider 把 GPT_IMAGE_2_5_BUSINESS_NAME(gpt-image-2.5)与 gpt-image-2.5-flare-c / -sunburst-c 一起判为 Tiantoken;build_image_request_body_with_model 会把 model 原样发给 provider(normalize_image_model 只处理空值,preferred_image_upstream_model 是恒等函数),所以业务名一旦漏到这一层就会原样发给 provider。
问题:调用方若把业务名当 model 传入,provider 会收到可能不被支持的 gpt-image-2.5。核实结论:当前仓库调用链一律传具体 provider_model,业务名只参与计价/展示与路由判断,所以此前没有实际触发,是公开 API 的潜在陷阱。
建议修复:按你选的 (a) —— 在 resolve_image_provider 里拒绝业务名,收紧白名单,业务名必须先在任务边界解析成具体 key。
本次处理:已移除白名单里的 GPT_IMAGE_2_5_BUSINESS_NAME;新增
resolve_image_provider_rejects_business_model_and_accepts_concrete_models。cargo test -p platform-image22 项通过,cargo test -p api-server1115 项通过。─── 9. 【已修复 9922704ae】 server-rs/crates/platform-image/src/image_provider/protocol/request.rs:284 ───
现状:nanobanana_generate_content_url 用 normalize_image_model(model) 拼路径,而该函数空值会回落到 GPT_IMAGE_2_5_GENERATION_MODEL(gpt-image-2.5-flare-c)。
问题:对 nanobanana 端点,空模型会拼出
.../v1beta/models/gpt-image-2.5-flare-c:generateContent,语义错误。执行器每次都会先归一,所以此前只影响这个公开 helper 的语义。建议修复:空/空白模型在本地回落到 NANOBANANA_2_MODEL,并补一条单测。
本次处理:已修复并新增
nanobanana_generate_content_url_blank_model_falls_back_to_nanobanana_model;cargo test -p platform-image21 项全通过。─── 10. 【已修复 ee3a8c12d】 server-rs/crates/api-server/src/config.rs:1324-1326 ───
现状:Tiantoken 只读 TIANTOKEN_BASE_URL / TIANTOKEN_API_KEY,不再从 VECTOR_ENGINE_* 回退(源码注释写明「有意为之」);build_required_image_provider_client 缺 base_url 时只报“tiantoken 图片 provider 缺少 BASE_URL 配置”,没点名变量名。
问题:这是明确的 breaking 配置变更,新增报错文案不足以让运维直接定位到该配哪个变量;构造成功后也没有日志能确认实际生效的 provider 配置。
建议修复:保持「不回退、缺失即启动失败」,但把缺失配置的报错点名具体环境变量,并在启动成功时记录已启用的 provider。
本次处理:按你说的「ok,log 里给更多信息」——报错补上
VECTOR_ENGINE_BASE_URL/VECTOR_ENGINE_API_KEY或TIANTOKEN_BASE_URL/TIANTOKEN_API_KEY,并启动info!记录 provider、base_url、超时与对应 env 变量。cargo check -p api-server通过,全量 1115 项测试 0 失败。─── 11. 【已修复 75c286d5d】 server-rs/crates/api-server/src/editor_generation_config.rs:114-116 ───
现状:public_projection 移除了 gpt-image-2.5-flare-c / -sunburst-c / gpt-image-2,却保留了历史别名 gpt-image-2-c。
问题:normalize_editor_image_model 仍识别 gpt-image-2-c,validate 又允许额外模型键,若配置里存在该键,就会经公开定价接口把 provider 历史别名暴露出去,与该函数「隐藏 provider 专用键」的目的冲突。
建议修复:在 public_projection 里一并
models.remove(EDITOR_IMAGE_MODEL_GPT_IMAGE_2_C)。本次处理:已按建议修复。
─── 12. 【已修复 ba32ab015】 server-rs/crates/platform-image/src/image_provider/runtime/executor.rs:307-311 ───
现状:create_nanobanana_generate_content 在 request_budget_exhausted_error、retry_image_upstream_status_after_delay、retry_image_send_after_delay、map_curl_error、handle_image_response 五处写死 ImageProvider::VectorEngine,而同函数的 InvalidRequest 与 tracing 用的是 settings.provider。
问题:今天结果正确(nanobanana 目前只路由到 VectorEngine),但审计/错误标签存在两处真相,未来若增加 provider 会静默不一致。
建议修复:这些位置统一改用 settings.provider。
本次处理:已按建议修复,语义不变。
cargo test -p platform-image通过。─── 13. 【已修复 43191eaec】 server-rs/crates/api-server/src/openai_image_generation.rs:150 ───
现状:create_openai_image_generation(非 _with_model)在迁移到 create_openai_image_generation_with_model 后已无调用方,且把 model 写死为 GPT_IMAGE_2_5_GENERATION_MODEL、忽略 reference_images。
问题:pub(crate) 无调用方会触发 dead_code,也会误导后续调用者。
建议修复:按退役对象直接删除该函数,并同步移除不再使用的 create_image_generation 导入。
本次处理:已确认全仓库无其它调用方(含测试)后删除。
cargo check -p api-server通过。─── 14. 【已修复 407a1bece】 server-rs/crates/api-server/src/openai_image_generation.rs:386-397 ───
现状:create_openai_image_edit_with_references_and_model 在参考图为空时用 missing_reference_images_error(ImageProvider::Tiantoken, ...),但非空路径用 client_for_model(model) 选 provider。
问题:若 model 是 vector-engine 模型走到该分支,错误归属(及派生失败审计)会标成 tiantoken。
建议修复:该分支按模型解析 provider,与非空路径保持一致。
本次处理:已改为
resolve_image_provider(model)(解析失败回落 Tiantoken 以保持旧行为)。注意这里不能直接用 client_for_model,否则会重新引入「provider 未配置即在参考图校验前 panic」的问题——原注释刻意避免这一点。cargo check -p api-server通过。─── 15. 【已修复 45295f55a】 src/components/image-editor/ImageCanvasGenerationModel.ts:651-657 ───
现状:normalizeEditorImageModel 与 isLegacyEditorImageModel 各自维护同一组 gpt-image-2 / gpt-image-2-c 判定。
问题:两处判断会随新别名漂移。
建议修复:抽取单一来源并复用。
本次处理:新增
LEGACY_EDITOR_IMAGE_MODELS集合并让两处复用(normalize 复用它做归一、isLegacy 复用它做判定)。已跑npx eslint、npx prettier --check与npx vitest run src/components/image-editor/ImageCanvasGenerationModel.test.ts(当时 35 项通过;第 16 项删掉 gpt-image-2-c 恢复用例后为 34 项通过)。─── 16. 【已修复 9327eb628】 platform-image / api-server / 主站前端全链路(你指出的 gpt-image-2-c 退役;先 eae6ee6fd 只做白名单拒绝,后 9327eb628 整体删除) ───
现状:
gpt-image-2-c是 2026-07-21「首选 gpt-image-2、失败兜底 gpt-image-2-c」那版里的兜底 provider model。跨模型兜底在 GPT Image 2.5 迁移里已经删掉,但这个字符串仍残留在 6 个地方:platform-image的GPT_IMAGE_2_C_MODEL常量与 re-export、is_gpt_image_2_family_model的尺寸语义、auditable_image_model的审计标签、api-server 的 3 处提交边界解析(画布参数 / Agent 工具参数 / 定价归一与 public_projection)、主站前端的常量与历史布局恢复分支、以及 External v1 与 ADR 的描述。问题:这些残留让一个「从未进入业务模型、持久化
model字段或前端契约」的历史值继续享有现役路由、兼容解析、尺寸语义、审计标签和文档承诺,读代码的人会以为它还受支持;is_gpt_image_2_family_model命中它还会套用 GPT Image 2 的像素预算,语义上把一个已删除的模型当成现役模型处理。核实结论(先按「不轻信原 review」重查过):api-server 持久化的模型一律取自
generation_options.model(业务值),前端在 2.5 迁移前只写gpt-image-2,全仓库除测试与文档外没有任何写入gpt-image-2-c的路径;因此不存在需要读回它的持久化数据或客户端契约,可以整体删除而不是只加拒绝。建议修复:整体删除——常量、re-export、尺寸语义、审计标签、api-server 三处解析分支、前端常量与历史恢复分支、External v1 / ADR / 共享记忆描述;数据库里既有的审计字符串保持原样。
本次处理:已按整体删除落地,单独提交
9327eb628(20 个文件)。platform-image常量与 re-export 删除;is_gpt_image_2_family_model、auditable_image_model去掉该分支;api-servereditor_project/editor_generation_config/editor_agent::tool/openai_image_generation去掉解析与 re-export;前端删IMAGE_MODEL_GPT_IMAGE_2_C与对应恢复用例;同步 External v1 OpenAPI 描述、ADR、decision-log、CONTEXT、pitfalls、后端架构与运维文档里「gpt-image-2 / gpt-image-2-c 仍按兼容规则解析」「切兜底模型 gpt-image-2-c」的过期表述。resolve_image_provider("gpt-image-2-c")仍返回 err,但现在走的是「未知值」分支而非专门拒绝分支。待你确认的相邻问题:provider 白名单里仍保留
gpt-image-2(见第 8 项)。它同样只是「提交边界解析」的历史值,但它同时是玩法图片链路和默认定价 JSON 的现役 key;要不要把 provider 边界收紧到只剩gpt-image-2.5-flare-c/gpt-image-2.5-sunburst-c/ nanobanana,需要你定,我没擅自改。验证:
cargo test -p platform-image全绿(64 + 14 + 22 项);cargo test -p api-server1111 通过 / 4 失败,失败全部是editor_sound_effect_prompt_assist的 mock LLM TCP 用例(并发负载下 5s 连接超时),单独跑该模块 10 项全通过,与本次改动无关;npx vitest run ...ImageCanvasGenerationModel.test.ts34 项通过;eslint / prettier /check:encoding(5133 文件)/check:doc-index/git diff --check全部通过。暂时不要合并, 因为需要等待购买服务, 配置环境变量
代码评审(PR #422 GPT Image 2.5 集成)
整体方向正确:provider-neutral 重构干净、Tiantoken 凭据零回退、双 client 启动期强制构造、legacy 值只在提交边界归一且不回写历史、公开投影不泄露 concrete key、凭据脱敏到位,测试对「不跨模型」语义覆盖扎实。但存在 2 个阻塞项、4 个严重项,建议修复后再合并。
阻塞(合并前必须处理)
生成入口按「是否带参考图」而非任务类型选择 concrete model,与本 PR 自己的 ADR/里程碑/decision-log 直接矛盾,且计价 key 与执行 key 分裂
server-rs/crates/api-server/src/editor_project.rs:3294-3300、editor_project_icon.rs:1777-1786、character_visual_assets.rs:949-955:只要生成任务带参考图,provider_model就选gpt-image-2.5-sunburst-c。cargo test -p platform-image整包运行本地必红server-rs/crates/platform-image/tests/image_provider.rs:422-432:mock server 只读到\r\n\r\n(响应头结束)就断言请求体内容(aspectRatio/imageSize),TCP 分段下 body 未必随 header 同包到达。本机整包跑与单跑均复现失败(断言 panic → mock 不写响应 → 客户端超时)。tests/vector_engine.rs同名测试中已存在,但本 PR 整体迁移重写了该文件,建议顺手修复:复用同文件已有的read_http_request(按 Content-Length 读完整 body)再断言。严重
Agent 编辑工具(EditImageTool)计价打到生成档:
editor_agent/tool.rs:692-704用GPT_IMAGE_2_5_BUSINESS_NAME走image_generation_mud_points(归一后命中 flare-c 档),但该工具执行时固定 dispatch sunburst-c;直连快速编辑与 raw edit 都已改用image_edit_model_mud_points。Agent 编辑是唯一仍按生成档计价的编辑入口,admin 调价后即错价,应统一改走编辑档。.codex/skills/gpt-image-2-apimart两个现役脚本直连 provider 却发送业务模型值:scripts/generate-template-samples.mjs:21,73-87、generate-anthro-cat-illustrations.mjs:12读VECTOR_ENGINE_BASE_URL/API_KEY直连images/generations|edits,请求体model: "gpt-image-2.5"。按 ADR,业务模型值只存在于 api-server 提交边界,provider 端只认 concrete model,且 GPT Image 2.5 走 Tiantoken 而非 VectorEngine——实盘运行必然被 provider 拒绝。请改用 concrete model + Tiantoken 凭据,或明确标注脚本已退役。platform-image 路由层放行 legacy/业务名并原样透传上游:
image_provider/protocol/request.rs:105-115把gpt-image-2/gpt-image-2-c/gpt-image-2.5也路由到 Tiantoken,runtime/executor.rs:722-727恒等透传 model 字符串。一旦有绕过 api-server dispatch 的调用方,provider 将收到字面的业务/历史值。与 ADR「严格白名单、未知 model 直接拒绝」表述不符,建议白名单只保留两个 concrete 2.5 模型 + nanobanana;若是有意兼容,需补钉死该行为的测试并更新 ADR。create_raw_image_edit绕过 provider 白名单校验:raw_image_edit/mod.rs:119-153硬编码 sunburst-c 但不校验settings.provider,误传 VectorEngine 配置会把 Tiantoken 专有模型名连同 API key 发到 VectorEngine 网关。共享 executor 有ensure_provider_matches_model防线,raw 路径没有,建议入口加 provider 校验(当前唯一调用方硬编码 Tiantoken,属纵深防御缺失)。次要
openai_image_generation.rs:132create_openai_image_generation、:266create_openai_image_edit、:305create_openai_image_edit_with_references(仅测试使用)在全 crate 无调用方,cargo check已报 dead_code 警告;所有create_*的_http_client参数被忽略。建议删除死函数、收敛签名。genarrative-external-v1.openapi.jsonUI 设计端点(约 3488 行)写default: gemini-3.1-flash-image-preview+「未传时默认使用 nanobanana」,但editor_project.rs:2876-2877对 ui-design kind 强制gpt-image-2.5。该矛盾 master 已存在,但本 PR 恰好改到这几行,按仓库规范 Rust 与 OpenAPI 不一致不应视为完成,建议顺手修正。state.rs:2521-2531的#[cfg(test)]兜底使「Tiantoken 配置缺失阻止启动」这条 ADR 硬性要求没有任何测试保护,建议把必填校验拆成纯函数并补参数化单测。raw_image.rs:167,190tracking 仍传VECTOR_ENGINE_PROVIDER;editor_project.rs:6155-6165错误消息仍写"provider": "vector-engine"(该分支现为 Tiantoken sunburst-c)。VECTOR_ENGINE_IMAGE_EDIT_MAX_REFERENCE_IMAGES = 5原是 VectorEngine 约束,现沿用到 Tiantoken 编辑路径(constants.rs:10、executor.rs:494、image_source.rs:145),5 张是否为 Tiantoken 真实上限未见确认,常量名也与用途不符。editor_project.rs:4102-4103concrete key 使用字符串字面量而非已 import 的GPT_IMAGE_2_5_GENERATION_MODEL/GPT_IMAGE_2_5_EDIT_MODEL常量。executor.rs:232/422/673handle_image_response的task_prefix硬编码"vector-engine",Tiantoken 任务 fallback task_id 会以错误前缀进入持久化与审计。建议(不阻塞合并)
apps/ai-game-creator-shell/)与主站src/services/apiClient.ts、editorProjectClient.ts的改动经逐行核对为纯 prettier 格式化 churn,与本 PR 主题无关;其中generated/DirectThreadRequestKind.ts是绑定生成产物,手工格式化会在下次重新生成时被打回。建议拆出或在 PR 描述中说明来源。error.rs的FallbackFailed/with_recovered_failure_audits/into_final_error、executor.rs:729finish_image_model_fallback_error等已无任何 push 点,crate 列表恒空(api-server 仍在消费公开 API,删除需跨 crate 跟进)。openai_image_generation.rs:440-452client_for_model用expectpanic 保证启动期不变量,建议改为返回Result变成可审计的 503。image_generation_options.rs:111gpt_image_2_size_parameter_schema、prompt 文件gpt-image-2-size.txt(内容已是 2.5 语义)。request.rs:96-99空模型默认值在编辑上下文会落到生成模型 flare-c,严格白名单语义下空值应报错或按任务类型取默认。已核实无问题的方面
tiantoken_credentials_never_fall_back_to_vector_engine_env;非 test 构建下任一 provider 缺配置即启动失败。src/、apps/、OpenAPI 零命中 flare/sunburst);normalizeEditorImageModel兼容解析仅在使用端、命中 legacy 触发既有回退警告、历史 fixture 不回写且有断言保护;nanobanana 默认行为未变。public_projection()只暴露业务名,admin 例外有测试固定。ImageProviderSettings/OpenAiImageSettingsDebug 脱敏,日志不含 key 与图片字节。本地验证结果
cargo check -p api-server通过(有本 PR 新增的 dead_code 警告,见次要项 7)cargo test -p platform-image:1 个失败(见阻塞项 2),其余 19 个通过npm run typecheck通过;image-editor 三个核心 model 定向测试 115 个全部通过npm run check:encoding、npm run check:doc-index、git diff --check均通过结论:阻塞项 1(代码与 ADR 矛盾 + 计价分裂)和阻塞项 2(测试门禁红)解决前不建议合并;严重项 3-6 建议同 PR 修复。
已过时,重审
复审(a6f99c887..f3c362b1e,16 个新提交)
上轮问题的处理情况
已解决:
resolve_image_provider现在拒绝业务名gpt-image-2.5与已退役的gpt-image-2-c,新增resolve_image_provider_rejects_business_model_and_accepts_concrete_models单测钉死(上轮严重项 5 的主体已解决)。gpt-image-2-c整体删除:常量、re-export、尺寸语义、审计标签、三处提交边界解析、前端常量与恢复分支全部移除,ADR / CONTEXT / OpenAPI / api-operations / pitfalls / decision-log 同步一致。数据库历史审计字符串不回写的策略表述清晰。nanobanana_generate_content_url_blank_model_falls_back_to_nanobanana_model)。TIANTOKEN_BASE_URL等),client 构造成功后有 info 启动日志,ADR Consequences 已同步。VectorEngine改为settings.provider透传。create_openai_image_generation已删除;空参考图错误的 provider 改为按模型解析(openai_image_generation.rs:341)。LEGACY_EDITOR_IMAGE_MODELS集合,ImageCanvasGenerationModel.test.ts34 项本地通过。仍未解决(沿用上轮意见):
editor_project.rs:3294-3300、editor_project_icon.rs:1777-1786、character_visual_assets.rs:949-955本轮未改动,而 ADR 中「普通生成即使因参考图使用 edits multipart,仍按生成 concrete model」的表述也保留原样。代码与文档的矛盾依然存在,且计价(flare-c 档)与执行/审计(sunburst-c)分裂的问题仍在。请明确二选一:改代码按任务类型分流,或修订三处文档并把生成带参考图的计价切到编辑档。cargo test -p platform-image本地仍必红——tests/image_provider.rs的nanobanana_generate_content_posts_native_body_and_reads_inline_datamock 竞态未修复(mock 只读到\r\n\r\n就断言请求体),本机连续复现(21 passed / 1 failed)。decision-log 记录的「cargo test -p platform-image 全绿」与本机(Windows)结果不符,说明该 race 与平台/网络栈行为相关,CI 上同样有失败风险。建议用同文件已有的按 Content-Length 完整读 body 的 helper 重写该断言。editor_agent/tool.rs:698-703依旧用image_generation_mud_points+GPT_IMAGE_2_5_BUSINESS_NAME(命中 flare-c 档),与直连快速编辑 / raw edit 已改用的image_edit_model_mud_points(sunburst-c 档)不一致,admin 分开调价即错价。.codex两个脚本仍发送业务名直连 provider:本轮只清理了单模型循环与fallbackModel字段,generate-template-samples.mjs:21仍是preferredImageModel = 'gpt-image-2.5'直连VECTOR_ENGINE_BASE_URL。按新白名单,provider 端只认 concrete model 且 GPT Image 2.5 走 Tiantoken,实盘必败。请改用 concrete model + Tiantoken 凭据,或在 SKILL.md 标注脚本已退役。create_raw_image_edit仍无 provider 校验:raw_image_edit/mod.rs本轮未动,硬编码 sunburst-c 但不校验settings.provider,与共享 executor 的ensure_provider_matches_model防线不一致。其他遗留(次要,不阻塞):
openai_image_generation.rs的create_openai_image_edit与create_openai_image_edit_with_references仍是 dead_code(cargo check 有警告),建议一并删除。executor.rs:231/421/672的task_prefix仍硬编码"vector-engine",Tiantoken 任务 fallback task_id 会带错误前缀进入持久化与审计。resolve_image_provider仍接受gpt-image-2→ Tiantoken,且 executorpreferred_image_upstream_model恒等透传——legacy 字符串若绕过 api-server 边界会原样发往上游。ADR 已记录「gpt-image-2 继续作为历史可读值接受」为有意行为,建议在新增的白名单单测里补一条gpt-image-2 → Tiantoken的断言把该意图钉死,或让 executor 也拒绝。gpt-image-2.5的矛盾仍在(本轮该行又被改到但仍未修正)。editor_project.rs:4101-4102concrete key 仍是字符串字面量而非已 import 的常量。gpt-image-2-c在后端normalize_editor_generation_options走_ => nanobanana未知值分支静默回落,与 decision-log「走既有未知值分支」的表述一致,无异议。本轮本地验证
cargo test -p platform-image:21 通过 / 1 失败(阻塞项 2 的既有竞态)cargo check -p api-server:通过,仍有上述两个 dead_code 警告npx vitest run src/components/image-editor/ImageCanvasGenerationModel.test.ts:34 项全部通过结论:本轮更新质量高,白名单收紧与
gpt-image-2-c清理做得干净彻底、文档同步完整。但上轮的 2 个阻塞项(参考图分流与 ADR 矛盾、平台相关测试竞态)与 3 个严重项(编辑工具计价、.codex 脚本、raw edit 防线)均未处理,维持「修复后再合并」的结论。- resolve_image_provider 错误类型从 &'static str 改为 String,未知模型返回「不支持的图片模型:{model}」 - ensure_provider_matches_model 去掉重复拼接的模型名,避免错误信息出现两遍输入 - openai_image_generation 缺少参考图的本地校验改用显式 match,不再用 unwrap_or 静默假定 Tiantoken - 补充断言:业务模型名与 unknown-model 的拒绝原因里必须包含被拒绝的模型值留给你处理的 Review 剩余项(未自动修改)
说明:以下是从上一版 ./review.txt 中保留下来的、会影响生产行为 / 计费或需要基础设施判断的项,我没有自动改,等你确认。可机械替换、纯文档或跨 crate 死代码清理类的问题已逐项修复并单独提交(见文末「已修复」)。
GenerateIconSpritesheetTool::pricing用!args.reference_image_ids.is_empty()判断has_reference_images,但reference_image_id(图标规范图)是必填参数,执行时始终把它作为参考图提交,GPT Image 2.5 固定落到/v1/images/edits+gpt-image-2.5-sunburst-c;直连入口resolve_editor_icon_spritesheet_price(editor_project_icon.rs:236-252)已经硬编码传true。reference_image_ids为空时按生成档gpt-image-2.5-flare-c计价,实际按编辑档执行,属于少收费;admin 单独调整编辑档价格后偏差会放大。与 2026-09-21 决策「图标素材图集(固定参考图)… 全部同规则」不一致。true;顺带确认build_display_args展示价同步变化,并跑cargo test -p api-server editor_agent::tool。gpt-image-2补齐而不是从同级的新档位推导backfill_legacy_gpt_image_2_5_pricing)gpt-image-2.5-flare-c/gpt-image-2.5-sunburst-c任一缺失,就整体从gpt-image-2(先查持久化 override,再查受控默认配置)克隆出两个 key,分别or_insert。gpt-image-2.5-flare-c、但缺gpt-image-2.5-sunburst-c时,sunburst-c 会拿到gpt-image-2的历史价格,而不是「同级那份已经存在的新档位」或受控默认里的 sunburst-c 价;admin 单独调过生成档价格时,编辑档会被静默回溯成旧值,且没有任何日志/标记说明这是补齐值。gpt-image-2或受控默认;每次实际写入补齐值时记tracing::warn!(带 source / 模型 / 价格);补editor_generation_config的部分迁移用例。.timeout(...).http1_only().pool_max_idle_per_host(0);该 client 实际只用于下载参考图 / provider 回图(runtime/image_source.rs:13-85,生成请求本身走 curl),而 api-server/src/state.rs 里其它长生命周期 client 用的是pool_max_idle_per_host(8/64/128)。pool_max_idle_per_host(0)等于禁用 keep-alive,每次下载都要重新做 TCP + TLS 握手;批量下载参考图(最多 5 张)和 provider 回图都会多付这部分延迟。pool_max_idle_per_host(0)调到与其它 client 一致的量级(如 8),http1_only()仅在确实需要时保留;改动后跑cargo test -p platform-image与一次真实图片下载冒烟。http1_only/ 禁长连接取决于网关与 provider 侧约束,仓库代码里没有依据可判断。已修复(按你的选择追加)
b0bb71a79让 resolve_image_provider 的拒绝原因带上模型名 —— 上一版第 2 条(错误类型改String并携带模型名;ensure_provider_matches_model去掉重复拼接;openai_image_generation.rs的unwrap_or(Tiantoken)改为显式 match;补拒绝原因含模型名的断言)c0d4e76a0解耦 Tiantoken 与 VectorEngine 的图片请求超时 —— 上一版第 3 条(新增tiantoken_image_request_timeout_ms,VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS只作用于 VectorEngine;state / OpenAiImageSettings 各取自己的字段;deploy env 示例与运维文档同步)ff89951a9删除失效的图片模型兜底审计链路 —— 上一版第 6 条(删除FallbackFailed、recovered_failure_audits、with_recovered_failure_audits、into_final_error、GeneratedImages字段、executor 包装层、api-serverrecoveredFailureCount与两处落库循环;同步运维文档与 decision-log)已修复(上一轮)
0b1caf728修正图片脚本中误导性的首选模型变量名 —— 原 review 第 1、3 条827164ed7为图片素材脚本补回同模型瞬时错误重试 —— 原 review 第 2、4、5、6 条(重试用providerStatus,删掉只写不读的providerBody/providerResponseParse)d95a01cf0同步图片技能文档的同模型重试说明 —— 上述脚本改动的 SKILL.md 文档同步e901937bb修正图片解析去重测试名与真实覆盖范围 —— 原 review 第 7 条a4be08d51修正 nanobanana 空模型被误归一为 GPT 生成模型 —— 原 review 第 9、13 条fb6e00c96消除前端 legacy gpt-image-2 档位的重复字面量 —— 原 review 第 12 条(保留 legacy key 兼容持久化值,改为复用同一常量消除漂移,并修正注释)d3822a9a1补齐图片生成重试测试的同模型断言 —— 原 review 第 17 条8e92bd295修正带参考图的便捷生成入口模型选择 —— 原 review 第 19 条4f2591b50说明 GPT Image 2 尺寸族与 provider 白名单的口径差异 —— 原 review 第 14 条(判定为有意设计,仅补注释)1低优不管了 2I will都给默认值了, 不留处理代码 3这是原行为
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.