Let generate_image work from reference images, with an image editing model

generate_image takes reference images: files the run reaches as
[file:ID] refs, or the user's uploads by media id, up to four, each
checked like a picture source and limited to raster images.

Calls with references go to a new Image editing harness (no automatic
picks). While it has no model or is off, image generation takes them;
with its fallback on, image generation steps in after its pick fails.
Only models that take image input are tried with references, so none
drops them unseen. OpenRouter gets them on /images as input_references;
other providers as a multipart upload to /images/edits.

The Models pages show image editing's unset state as "Same as image
generation", and the models cache version is bumped so it shows at once.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-28 18:43:10 +01:00
co-authored by Claude Opus 5.5
parent 243c19e0c5
commit de28d4d9f7
22 changed files with 564 additions and 47 deletions
@@ -13,6 +13,7 @@ type Props = {
model_id: number | null;
provider_name?: string;
automatic: boolean;
falls_back_title?: string;
onChange: (model_id: number | null) => void;
};
@@ -26,6 +27,7 @@ export default function HarnessModelSelect({
model_id,
provider_name,
automatic,
falls_back_title,
onChange,
}: Props) {
return (
@@ -35,7 +37,13 @@ export default function HarnessModelSelect({
label="Model"
showLabel
placeholder="Search models"
options={harnessModelSelectOptions({ models, model_id, provider_name, automatic })}
options={harnessModelSelectOptions({
models,
model_id,
provider_name,
automatic,
falls_back_title,
})}
defaultValues={[model_id ? String(model_id) : AutoModelValue]}
changeHandler={(value) => {
const picked = Array.isArray(value) ? value[0] : value;