diff --git a/src/routes/generatedImages.js b/src/routes/generatedImages.js index 2c27f39c..ad24dff7 100644 --- a/src/routes/generatedImages.js +++ b/src/routes/generatedImages.js @@ -167,6 +167,17 @@ router.put('/admin/image-settings/:workflow', adminMiddleware, async (req, res) if (!IMAGE_WORKFLOWS.includes(workflow)) throw images.failure(404, 'Workflow not found'); const budget = images.budgetLimit(req.body.budget); + // The primary model — the field this endpoint used to accept and drop, so a + // saved selection never survived a refresh. Blank is a real value for + // my_resources ("use the Clinical Assistant's model"), so an empty string is + // written rather than skipped, and only an absent field leaves it alone. + let model = null; + if (req.body.model !== undefined) { + const id = String(req.body.model || '').trim(); + if (id && !MODEL_ID.test(id)) throw images.failure(400, 'Not a model ID: ' + id.slice(0, 60)); + model = id; + } + // Fallbacks are optional, and only sent when the caller means to change // them: an absent field leaves the saved chain alone rather than clearing it. let fallbacks = null; @@ -178,8 +189,10 @@ router.put('/admin/image-settings/:workflow', adminMiddleware, async (req, res) if (!MODEL_ID.test(id)) throw images.failure(400, 'Not a model ID: ' + id.slice(0, 60)); } // The primary counts toward the cap, and naming it again would pay twice - // for the same refusal. - const primary = String(await db.getSetting(workflow + '.image_model') || ''); + // for the same refusal. Compare against the model this request is setting, + // not the one it replaces, or a model promoted to primary in the same save + // survives as its own fallback. + const primary = model !== null ? model : String(await db.getSetting(workflow + '.image_model') || ''); fallbacks = fallbacks.filter((id, i) => id !== primary && fallbacks.indexOf(id) === i); if (fallbacks.length > images.MAX_IMAGE_MODELS - 1) { throw images.failure(400, 'At most ' + (images.MAX_IMAGE_MODELS - 1) + @@ -191,6 +204,7 @@ router.put('/admin/image-settings/:workflow', adminMiddleware, async (req, res) try { await client.query('BEGIN'); const changes = { image_budget: budget }; + if (model !== null) changes.image_model = model; if (fallbacks !== null) changes.fallback_image_models = fallbacks.join(','); for (const [key, value] of Object.entries(changes)) { await client.query('INSERT INTO app_settings(key,value) VALUES($1,$2) ON CONFLICT(key) DO UPDATE SET value=$2,updated_at=NOW()', [workflow + '.' + key, String(value)]);