# ADR-0018: imagegen.Editor — image-to-image as a separate optional interface **Status:** Accepted — 2026-07-11 ## Context ADR-0016 shipped text-to-image and explicitly deferred img2img. mort's new llama-swap media tools need "edit this image under this prompt" (image-to-image with a denoising strength). Two shape questions: does Edit belong on `imagegen.Model`, and which llama-swap endpoint carries it — OpenAI-style `/v1/images/edits` (multipart) or A1111-style `/sdapi/v1/img2img` (JSON)? ## Decision - **`Editor` is a separate, optional interface** (`Edit(ctx, EditRequest, ...EditOption) (*Result, error)`), not a new method on `Model`. Existing `Model` implementations keep compiling; callers type-assert (`m.(imagegen.Editor)`) or require the capability explicitly. - `EditRequest` = the generation knobs (prompt, N, size, steps, cfg, negative prompt, sampler, seed) plus `Init Image` (required) and `Strength *float64` (denoising strength in [0,1]; nil = backend default). Same option/Apply conventions; result type is the shared `Result`. - llama-swap implements it via **`/sdapi/v1/img2img`**, not `/v1/images/edits`: the same sd-server build that ignores `seed` on the OpenAI images route (the reason txt2img went SDAPI in ADR-0016's implementation) applies; the JSON shape is txt2img's plus `init_images: [""]` + `denoising_strength`, so it reuses `doJSON` verbatim, where the OpenAI route is multipart. ## Consequences - Backends that can't edit simply don't implement `Editor`; no stub methods. - The init image travels base64-inline in JSON (~33% overhead) — acceptable at chat-image sizes; a future backend needing multipart can still satisfy the same interface.