Skip to content

feat(images): Antigravity image edits accept multiple reference images - #16731

Open
diegosouzapw wants to merge 3 commits into
release/v3.8.53from
feat/port-pr-2769-antigravity-multi-reference-images
Open

diegosouzapw wants to merge 3 commits into
release/v3.8.53from
feat/port-pr-2769-antigravity-multi-reference-images

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Antigravity (Gemini image) edits now forward every reference image as its own inlineData part instead of only the first one; /v1/images/edits accepts up to 14 references for Antigravity (was 1).
  • /v1/images/generations bodies can carry image / images[] / image_url references as data URLs, raw base64, or public HTTP(S) URLs (fetched through the existing public-only, DNS-pinned fetchUntrustedRemoteImage guard).
  • Unusable references fail fast with a non-retryable 400 (no account rotation / cooldown), and a text-only Antigravity answer now returns a 502 with the sanitized model text instead of an empty 200.

Attribution

Thanks to @yheiakadylan for the original implementation.

Changes

  • open-sse/handlers/imageGeneration/providers/geminiInline.ts — new resolveGeminiReferenceParts (sources: referenceImages → imageBytes → string refs; cap GEMINI_IMAGE_MAX_REFERENCES = 14), buildGeminiImagePrompt (when references are attached, the prompt is prefixed with "Generate an image as the final response. Use all N attached reference image(s) in the result. Do not answer with text only."), buildGeminiImageUserParts, extractGeminiImageResults. geminiInlineImagePart is kept unchanged.
  • open-sse/handlers/imageGeneration.ts (handleGeminiImageGeneration) — uses the helpers; invalid refs → saveImageErrorResult(400, retryable:false); no image in the response → saveImageErrorResult(502) via sanitizeErrorMessage; the log line reports the reference count only (never bytes). File shrinks by 4 lines (frozen file-size cap respected).
  • src/app/api/v1/images/edits/route.ts — Antigravity branch passes referenceImages: images; its reference cap is 14 with a dedicated error message (Firefly / fal / single-reference messages unchanged).
  • tests/unit/antigravity-image-multi-reference.test.ts — new (9 cases).
  • tests/unit/gemini-antigravity-image-edits.test.ts — the 3 single-reference asserts now expect the reference preamble + prompt (exact assert.equal, same assert count). This is an intended contract change: with one reference attached the prompt is prefixed. Text-to-image without references keeps the prompt untouched (the existing deepEqual request test in image-generation-handler.test.ts still passes unchanged).

Out of scope (intentionally not ported): playground UI, per-account Antigravity runtime state (already covered by model lockout + imageCredentialRetry quota-exhausted rotation).

Test plan

  • Fail-before (base sources, new test file): node --import tsx/esm --test tests/unit/antigravity-image-multi-reference.test.ts → ℹ tests 9 ℹ pass 0 ℹ fail 9 (e.g. actual: 1, expected: 3 parts).
  • After the change, each run with an isolated DATA_DIR and env -u OMNIROUTE_API_KEY:
    • antigravity-image-multi-reference → ℹ tests 9 ℹ pass 9 ℹ fail 0
    • gemini-antigravity-image-edits → ℹ tests 3 ℹ pass 3 ℹ fail 0
    • image-generation-handler → ℹ tests 50 ℹ pass 50 ℹ fail 0
    • image-generation-route → ℹ tests 30 ℹ pass 30 ℹ fail 0
    • 10197-openrouter-image-edits-route 3/3, 8510-adobe-firefly-edits-route 4/4, image-combo-edits-fallback-12547 5/5, antigravity-image-credential-retry 4/4, image-credential-retry-429 4/4, image-generation-size-and-payload-guard 9/9, antigravity-image-quota-visibility 2/2, codex-images-dedicated-endpoint 6/6, guardrail-pipeline-wiring-characterization 10/10, hard-session-lease-bypass-inventory 3/3, issue-6686-quota-preflight-coverage 2/2 — all fail 0.
  • npm run typecheck:core → exit 0.
  • npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files> → no findings; npx prettier --check <changed files> → all formatted.
  • npm run check:file-size → [file-size] OK, [test-file-size] OK.
  • GITHUB_BASE_REF=release/v3.8.52 node scripts/check/check-pr-test-policy.mjs → Result: PASS; GITHUB_BASE_REF=release/v3.8.52 npm run check:test-masking → OK — 1 modificado(s) … sem enfraquecimento.

⚠️ base-red inherited: #15306 — unit/vitest/integration/package-artifact gates on release/v3.8.52

live_check (hold-vps)

POST /v1/images/edits to antigravity/gemini-3.1-flash-image with two multipart reference images and confirm the upstream accepts more than one reference and the result uses both; also confirm the 14-reference cap against Google's documented limit.

diegosouzapw and others added 2 commits October 15, 2026 13:12
Antigravity (Gemini image) edits only ever forwarded the first reference
image. Every reference now becomes its own inlineData part:

- /v1/images/edits forwards all multipart/JSON references to Antigravity
  (cap raised from 1 to 14, the Gemini 3 image reference limit).
- /v1/images/generations bodies may carry image / images[] / image_url as
  data URLs, raw base64 or public HTTP(S) URLs; URLs go through the
  public-only, DNS-pinned fetchUntrustedRemoteImage guard.
- An unusable reference fails with a non-retryable 400 before dispatch,
  so the account is not rotated or cooled down.
- When references are attached, the prompt is prefixed with an explicit
  "use all N attached reference images; do not answer with text only"
  instruction.
- A response with no image (text-only refusal) now returns a 502 carrying
  the sanitized model text instead of an empty 200.

The reference resolution, prompt and response extraction live in
providers/geminiInline.ts so imageGeneration.ts shrinks by 4 lines.

Co-authored-by: Hai Trinh <haitrinh2605204@gmail.com>
Inspired-by: decolua/9router#2769
@diegosouzapw diegosouzapw added the hold-vps PR verde, merge aguardando validação live (release-drain) label Oct 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

CI Coverage Report

  • Coverage job: skipped
  • PR test policy: success

Coverage artifact was not available for this run.

@diegosouzapw diegosouzapw added the deferred-v3.8.53 Feat PRs held for v3.8.53. Keep open. Do not merge into v3.8.52. label Oct 16, 2026
@diegosouzapw diegosouzapw changed the title feat(images): Antigravity image edits accept multiple reference images [defer] feat(images): Antigravity image edits accept multiple reference images Oct 16, 2026
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.52 to release/v3.8.53 October 19, 2026 13:26
@diegosouzapw

Copy link
Copy Markdown
Collaborator Author

Re-homed to release/v3.8.53: v3.8.52 entered its release freeze, so the branch now belongs to the release captain and development continues on the next cycle. Nothing is wrong with this PR — it just needed a live base. No action needed from you; CI will re-run against the new base.

@diegosouzapw diegosouzapw removed the deferred-v3.8.53 Feat PRs held for v3.8.53. Keep open. Do not merge into v3.8.52. label Oct 20, 2026
@diegosouzapw diegosouzapw changed the title [defer] feat(images): Antigravity image edits accept multiple reference images feat(images): Antigravity image edits accept multiple reference images Oct 20, 2026
…-reference-images

Resolve the overlap with #18148 (reject unusable Gemini reference images):
keep the base's no-remote-fetch policy for Gemini image models and reapply the
multi-reference delta on top of it. HTTP(S) references are rejected with the
base's message instead of being fetched; data URLs, raw base64 and multipart
uploads keep working as multiple inline parts. The edits route keeps the base's
muse-image branch alongside the PR's isGeminiImageEdit reference cap.
@diegosouzapw diegosouzapw added the deferred-v3.8.54 Feat PRs held for v3.8.54. Keep open. Do not merge into v3.8.53. label Nov 2, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deferred-v3.8.54 Feat PRs held for v3.8.54. Keep open. Do not merge into v3.8.53. hold-vps PR verde, merge aguardando validação live (release-drain)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant