修复图标规范参考图超限预检

后端在调用 LLM 前按模型上限拒绝超限参考图。
前端在请求发送前限制图标规范参考图数量。
补充超限零请求回归测试与预检顺序断言。
This commit is contained in:
2026-08-06 11:25:48 +08:00
parent c932f5e8fb
commit 3550f046e4
3 changed files with 38 additions and 11 deletions
@@ -1808,18 +1808,19 @@ pub(crate) async fn validate_editor_image_generation_parameters_for_owner(
payload.image_size.as_deref(),
);
let reference_limit = if matches!(normalized_kind, Some("quick-edit")) {
9
EDITOR_QUICK_EDIT_REFERENCE_LIMIT
.min(editor_provider_reference_limit(generation_options.model))
} else {
5
EDITOR_IMAGE_GENERATION_REFERENCE_LIMIT
};
for source in payload
.reference_image_srcs
.as_deref()
.unwrap_or_default()
.iter()
.map(|source| source.trim())
.filter(|source| !source.is_empty())
.take(reference_limit)
ensure_editor_reference_image_source_limit(
payload.reference_image_srcs.as_deref(),
reference_limit,
"editor-image-generation",
"referenceImageSrcs",
"生成参考图",
)?;
for source in normalize_editor_reference_image_sources(payload.reference_image_srcs.as_deref())
{
parse_editor_reference_image(state, caller.owner_user_id.as_str(), source).await?;
}
@@ -14784,18 +14785,25 @@ mod tests {
fn image_generation_preflight_checks_references_provider_and_pricing() {
let source = include_str!("editor_project.rs");
assert_function_contains(
assert_function_contains_in_order(
source,
"pub(crate) async fn validate_editor_image_generation_parameters_for_owner",
"pub(crate) async fn generate_editor_image_for_owner",
&[
"ensure_editor_reference_image_sources_are_stable(",
"ensure_editor_reference_image_source_limit(",
"parse_editor_reference_image(",
"require_openai_image_settings(",
"build_openai_image_http_client(",
".editor_generation_pricing()",
],
);
assert_function_not_contains(
source,
"pub(crate) async fn validate_editor_image_generation_parameters_for_owner",
"pub(crate) async fn generate_editor_image_for_owner",
&[".take(reference_limit)"],
);
}
#[test]
@@ -1452,6 +1452,20 @@ describe('editorProjectClient', () => {
expect(requestJsonMock).not.toHaveBeenCalled();
});
it('rejects excess icon spec references before dispatch', async () => {
await expect(
generateEditorIconSpec({
playSetting: '回合制占点',
artStyle: '低多边形',
referenceImageSrcs: Array.from(
{ length: 6 },
(_, index) => `resource-reference-${index + 1}`,
),
}),
).rejects.toThrow('图标规范参考图最多允许 5 张,当前选择 6 张');
expect(requestJsonMock).not.toHaveBeenCalled();
});
it('submits icon spec business fields without a client prompt or image kind', async () => {
requestJsonMock.mockResolvedValueOnce({
imageSrc: 'data:image/png;base64,spec',
@@ -1106,6 +1106,11 @@ export async function generateEditorIconSpec(
'美术风格',
);
assertStableEditorMediaReferences(input.referenceImageSrcs, '图标规范参考图');
assertEditorReferenceLimit(
input.referenceImageSrcs,
EDITOR_IMAGE_REFERENCE_LIMIT,
'图标规范参考图',
);
return requestJson<EditorImageGenerationResponse>(
EDITOR_ICON_SPEC_GENERATION_API,
jsonRequest('POST', {