434d721b99
- New leaf package `audio` (ADR-0017): SpeechModel/SpeechProvider and TranscriptionModel/TranscriptionProvider with imagegen conventions (zero value = backend default, functional options + Apply, bytes in/out, never URLs). Root re-exports added. - imagegen.Editor (ADR-0018): optional image-to-image interface — EditRequest carries the generation knobs plus Init image and denoising Strength; separate interface so existing Models keep compiling. - provider/llamaswap implements all of it: POST /v1/audio/speech (JSON, raw-audio response, MIME from Content-Type with format fallback), POST /v1/audio/transcriptions (multipart, response_format=json), ListVoices (GET /v1/audio/voices?model=, tolerant of string-list and object-list shapes), POST /sdapi/v1/img2img (txt2img wire + init_images/denoising_strength, shared image decode), and Health(ctx) (GET /health) — a cheap liveness probe for often-offline hosts. - Hermetic httptest coverage for every new wire shape and validation path; README sections + support-matrix footnote updated in the same commit (also corrects the stale /v1/images/generations claim — the image path has been SDAPI since the seed fix). First consumer: mort's llamaswap media tool cluster (status / image / TTS / STT agent tools against the netherstorm host). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AXQxVhXBw8PwFAtsVrXSmj
37 lines
1.7 KiB
Markdown
37 lines
1.7 KiB
Markdown
# 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: ["<b64>"]` + `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.
|