Files
TrueGrowth/openspec/changes/archive/2026-04-29-add-gpt-image-edit-support/design.md

2.7 KiB

Context

The first GPT Image compatibility phase added profile-level image API compatibility and a dedicated official generation schema:

  • openai.image.gpt-generation-json -> /images/generations
  • openai.image.basic-json -> existing default compatibility adapter

The second phase needs /images/edits, but the project still has only one image task surface and one image adapter method. A broad image operation abstraction would be cleaner long-term, but too large for this step.

Goals / Non-Goals

  • Goals:
    • Support official GPT Image image-to-image/edit requests.
    • Reuse existing TaskType.IMAGE queue/history/canvas flows.
    • Keep basic Tuzi/OpenAI-compatible behavior unchanged.
    • Avoid routing by model ID alone.
  • Non-Goals:
    • No new task type.
    • No new public MCP tool name.
    • No full mask drawing UI in this phase.

Decisions

  • Decision: Add an edit request schema instead of a new task type.

    The schema is the existing adapter handoff point. It lets the routing layer choose official generation vs official edit while keeping task plumbing stable.

  • Decision: Add planner-level schema preference.

    The same model/profile can have both generation and edit bindings. Runtime request shape, not model ID, decides which binding is appropriate.

  • Decision: Use multipart edit requests for the official GPT Image adapter.

    The official /images/edits examples use file-style form fields such as image[]=@.... The adapter converts the existing canvas data URLs or fetchable image references to Blobs, appends them as image[], and lets fetch set the multipart boundary.

Runtime Flow

Image task
  -> extract reference images
  -> decide preferred schema:
       no references -> openai.image.gpt-generation-json
       references/mask/edit mode -> openai.image.gpt-edit-form
  -> resolve invocation plan with preferred schema
  -> resolve adapter from binding
  -> gpt-image-adapter sends /images/generations or /images/edits

If the preferred edit schema is unavailable, planning falls back to the highest-priority image binding. That preserves Tuzi/basic compatibility.

Request Fields

Extend ImageGenerationRequest with lightweight edit semantics:

type ImageGenerationMode = 'text_to_image' | 'image_to_image' | 'image_edit';

interface ImageGenerationRequest {
  generationMode?: ImageGenerationMode;
  referenceImages?: string[];
  maskImage?: string;
  inputFidelity?: 'high' | 'low';
}

Official edit multipart fields:

model=gpt-image-1.5
prompt=...
image[]=@image-1.png
mask=@mask.png
input_fidelity=high
size=1024x1024

Rollback

Switching a profile from openai-gpt-image to tuzi-compatible or openai-compatible-basic returns reference-image requests to the default adapter compatibility path.