Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fixes/8863-firefly-gpt-image-detail-level.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Adobe Firefly**: `gpt-image` requests now default `detailLevel` to maximal (5) instead of leaving the upstream default, so generations come back at the quality the model is capable of
5 changes: 3 additions & 2 deletions config/quality/file-size-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@
"open-sse/mcp-server/server.ts": 1407,
"open-sse/mcp-server/tools/advancedTools.ts": 1120,
"open-sse/services/accountFallback.ts": 1966,
"open-sse/services/adobeFireflyClient.ts": 2317,
"open-sse/services/adobeFireflyClient.ts": 2322,
"open-sse/services/claudeCodeCompatible.ts": 1202,
"open-sse/services/combo.ts": 3648,
"open-sse/services/compression/strategySelector.ts": 1060,
Expand Down Expand Up @@ -411,5 +411,6 @@
"_rebaseline_2026_07_28_8842_antigravity_projectid_refresh": "PR #8842 (fix/antigravity-projectid-refresh) own growth: open-sse/executors/antigravity.ts 1493->1528 (+35 = projectId discovery in refreshCredentials: import ensureAntigravityProjectAssigned + trim projectId + call ensureAntigravityProjectAssigned with 8s timeout + persistDiscoveredAntigravityProjectId + log success/failure). Irreducible wiring at the existing credential-refresh chokepoint. Covered by tests/unit/executor-antigravity.test.ts (4 new test cases).",
"_rebaseline_2026_07_28_8842_antigravity_test": "PR #8842 test growth: tests/unit/executor-antigravity.test.ts new testFrozen 1098 (4 new test cases for projectId discovery during refresh: discovers when empty, skips when set, handles failure, skips when access_token not a string). All above cap 1000 on day one.",
"_rebaseline_2026_07_28_8860_tokenrefresh_projectid": "PR #8860 (fix/antigravity-projectid-centralized) own test growth: tests/unit/token-refresh-service.test.ts 1311->1378 (+67 = 4 cases covering projectId discovery on the tokenRefresh.ts path — the Dashboard/health-check refresh route, which #8842 did not reach since that fixed the executor path). Covered by the same file.",
"_rebaseline_2026_07_28_8861_xiaomi_token_plan": "PR #8861 (feat/xiaomi-token-plan-protocol-selector) own growth: EditConnectionModal.tsx 1283->1316 (+33 = the per-connection API-protocol selector field) and open-sse/executors/base.ts 1540->1562 (+22 = alternate-format resolution at the existing buildUrl/headers chokepoint). Both are irreducible wiring at existing call sites."
"_rebaseline_2026_07_28_8861_xiaomi_token_plan": "PR #8861 (feat/xiaomi-token-plan-protocol-selector) own growth: EditConnectionModal.tsx 1283->1316 (+33 = the per-connection API-protocol selector field) and open-sse/executors/base.ts 1540->1562 (+22 = alternate-format resolution at the existing buildUrl/headers chokepoint). Both are irreducible wiring at existing call sites.",
"_rebaseline_2026_07_28_8863_firefly_detail_level": "PR #8863 (fix/adobe-firefly-gpt-detail-level-max) own growth: adobeFireflyClient.ts 2317->2322 (+5 = gpt-image detailLevel defaulting to maximal at the existing payload-build site). Covered by tests/unit/adobe-firefly.test.ts."
}
17 changes: 11 additions & 6 deletions open-sse/services/adobeFireflyClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -660,13 +660,18 @@ export function resolveAdobeVideoModel(model: string): {
return { id: "sora-2", spec: ADOBE_FIREFLY_VIDEO_MODELS["sora-2"] };
}

/**
* Map OpenAI/VibeProxy quality tiers onto Firefly gpt-image `generationSettings.detailLevel`.
* Wire range is integer 1–5 (discovery schema). Default is **maximal (5)** —
* the SPA often defaults to 3, but detail is critical for GPT Image 2 output quality.
* Explicit low/medium still honor the caller's choice.
*/
function gptDetailLevel(quality: unknown): number {
// Live firefly.adobe.com default for gpt-image is detailLevel 3 (medium).
const q = String(quality ?? "medium").trim().toLowerCase();
if (q === "high" || q === "4k" || q === "ultra") return 5;
if (q === "low" || q === "1k") return 1;
if (q === "medium" || q === "2k" || q === "standard" || q === "hd" || q === "auto") return 3;
return 3;
const q = String(quality ?? "high").trim().toLowerCase();
if (q === "low" || q === "1k" || q === "1") return 1;
if (q === "medium" || q === "2k" || q === "standard" || q === "hd" || q === "3") return 3;
// high / 4k / ultra / auto / empty / unknown → max detail
return 5;
}

export function buildAdobeImagePayload(opts: {
Expand Down
42 changes: 42 additions & 0 deletions tests/unit/adobe-firefly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,48 @@ test("buildAdobeImagePayload produces nano and gpt-image shapes", () => {
assert.equal((gpt.modelSpecificPayload as Record<string, unknown>).size, "auto");
assert.equal(gpt.size, undefined);
assert.equal(gpt.outputResolution, undefined);

// Missing / auto quality → maximal detail (5). Explicit low/medium still honored.
const gptDefault = buildAdobeImagePayload({
prompt: "a dog",
aspectRatio: "1:1",
outputResolution: "1K",
modelSpec: ADOBE_FIREFLY_IMAGE_MODELS["gpt-image-2"],
});
assert.equal((gptDefault.generationSettings as Record<string, unknown>).detailLevel, 5);
const gptAuto = buildAdobeImagePayload({
prompt: "a dog",
aspectRatio: "1:1",
outputResolution: "1K",
modelSpec: ADOBE_FIREFLY_IMAGE_MODELS["gpt-image"],
quality: "auto",
});
assert.equal((gptAuto.generationSettings as Record<string, unknown>).detailLevel, 5);
const gptLow = buildAdobeImagePayload({
prompt: "a dog",
aspectRatio: "1:1",
outputResolution: "1K",
modelSpec: ADOBE_FIREFLY_IMAGE_MODELS["gpt-image"],
quality: "low",
});
assert.equal((gptLow.generationSettings as Record<string, unknown>).detailLevel, 1);
const gptMedium = buildAdobeImagePayload({
prompt: "a dog",
aspectRatio: "1:1",
outputResolution: "1K",
modelSpec: ADOBE_FIREFLY_IMAGE_MODELS["gpt-image"],
quality: "medium",
});
assert.equal((gptMedium.generationSettings as Record<string, unknown>).detailLevel, 3);
// Firefly UI resolution tiers map onto the same detailLevel scale.
const gpt4k = buildAdobeImagePayload({
prompt: "a dog",
aspectRatio: "1:1",
outputResolution: "1K",
modelSpec: ADOBE_FIREFLY_IMAGE_MODELS["gpt-image"],
quality: "4k",
});
assert.equal((gpt4k.generationSettings as Record<string, unknown>).detailLevel, 5);
});

test("buildAdobeImagePayload attaches referenceBlobs like live adobe_atach_images capture", () => {
Expand Down
Loading