Let each image model carry its own request parameters - #198
Merged
Merged
Conversation
Image generation could only send the six named size presets, translated
per model by a hard-coded list of size dialects. A model that wants
something else (exact pixels such as {"width": 1600, "height": 900}, a
resolution tier, step counts) couldn't be used that way without a code
change.
Settings -> AI Services -> Images now has a "Model parameters (JSON)"
editor per model. The JSON is merged into the fal request for that model,
for every generation path (editor dialog and the assistant's
generate_image action). Stored per user alongside the other image
settings, so curated and custom models both work and no migration is
needed.
Merge rules (build_fal_image_body):
- If the JSON sets image_size or aspect_ratio it replaces the size the
dropdown would send, so the two can never conflict. Other keys such as
resolution or seed go out alongside the dropdown size.
- prompt, num_images and sync_mode are managed by the app and refused on
save (and stripped again at send time): cost accounting and the
download path assume exactly one fetchable image.
The editor explains itself: example chips (exact pixels, aspect ratio,
resolution, quality, PNG), a link to the model's schema on fal.ai, and a
short "What can I put here?" note. The Size dropdown in the Generate
image dialog is disabled with an explanation when a model's parameters
set the size.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MDpGog3zexuU9KNPpP3jEM
test_a_beating_job_survives_the_sweeper started a heartbeat thread, slept 100 ms and asserted the sweeper left the job alone. That only holds if the thread completes a beat inside that window; under load it may not, and then the sweeper is judging a job that simply hasn't beaten yet. The result moved with whatever else was in the suite: in this checkout it failed on every full run once two new tests were added elsewhere, and passed again with either one deselected, with no change to the code under test. Poll for the first beat (up to 5 s) before asserting. A heartbeat that never beats still fails the test, after the wait, with the job still stale. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MDpGog3zexuU9KNPpP3jEM
davior
marked this pull request as ready for review
October 1, 2026 11:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Image generation could only send the six named size presets, translated per model by a hard-coded list of size dialects. A model that wants something else (exact pixels such as
{"width": 1600, "height": 900}, a resolution tier, step counts) couldn't be used that way without a code change.Settings → AI Services → Images now has a Model parameters (JSON) editor per model. The JSON is merged into the fal request for that model, on every generation path (the editor's Generate image dialog and the assistant's
generate_imageaction).How it works
image_gen_configsetting. Curated and custom models both work. No migration: old blobs just lack the key.build_fal_image_bodyinrouters/settings.py):image_sizeoraspect_ratio, it replaces the size the dropdown would send, so the two can't conflict. Other keys (resolution,seed,output_format, ...) go out alongside the dropdown size.prompt,num_imagesandsync_modeare managed by the app. They're refused on save with a clear message, and stripped again at send time. Cost accounting and the download path assume exactly one fetchable image.PUT /settings/imagestakesmodel_paramsas a per-model patch: an object sets that model's params,null/{}clears them, and models not mentioned are left alone.I did not change the preset list or the existing dialect mapping. The code comment says FLUX.1/.2 accept presets verbatim, so I can't tell from the code which models were misbehaving. The override works whatever fal says a model accepts.
Second commit: unrelated flaky test
test_a_beating_job_survives_the_sweeperslept a fixed 100 ms and then asserted. In this checkout it failed on every full run once the new tests were added (and passed again with either new wiring test deselected, or with a diagnostic plugin loaded), with no change to the code it tests. It now polls up to 5 s for the first beat. A heartbeat that never beats still fails it; I checked that by breakingrunner.heartbeattemporarily. It's a separate commit (Wait for the first heartbeat...) so it's easy to drop if you'd rather handle it separately.Verification
pytest -q→ 1116 passed, 5 consecutive full runs (30 new tests intests/test_image_params.py). Mutation check: droppingmodel_paramsfrom the persisted blob makes 6 of them fail.npm test→ 190 passed (newutils/imageParams.test.ts),npm run build(tsc + vite) clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01MDpGog3zexuU9KNPpP3jEM
Generated by Claude Code