Fix FAL.AI models list endpoint (#4236) The FAL.AI endpoint seems to have switched to a paginated format where the results are nested under an `items` key. This updates the endpoint handler to fetch all pages and extract the model options correctly.

b45477578ffd3c135a9a4745fa3cf38af0db76f1

Jenner La Fave <jenner@jfave.com>

Signed
1 files changed, +32 -16Ignore whitespace
src/endpoints/stable-diffusion.js+32 -16
@@ -1160,28 +1160,44 @@ const falai = express.Router();
11601160falai.post('/models', async (_request, response) => {
11611161 try {
11621162 const modelsUrl = new URL('https://fal.ai/api/models?categories=text-to-image');
11631163 constlet resultpage = await fetch(modelsUrl)1;
1164+ let modelsResponse;
1165+ let models = [];
11641166
1165- if (!result.ok) {
1167+ do {
1166- console.warn('FAL.AI returned an error.', result.status, result.statusText);
1168+ modelsUrl.searchParams.set('page', page.toString());
1167- throw new Error('FAL.AI request failed.');
1169+ const result = await fetch(modelsUrl);
1168- }
11691170
1170- const data = await result.json();
1171+ if (!result.ok) {
1172+ console.warn('FAL.AI returned an error.', result.status, result.statusText);
1173+ throw new Error('FAL.AI request failed.');
1174+ }
11711175
1172- if (!Array.isArray(data)) {
1173- console.warn('FAL.AI returned invalid data.');
1174- throw new Error('FAL.AI request failed.');
1175- }
11761176
1177- const models = data
1177+ modelsResponse = await result.json();
1178- .filter(x => !x.title.toLowerCase().includes('inpainting') &&
1178+ if (!('items' in modelsResponse) || !Array.isArray(modelsResponse.items)) {
1179- !x.title.toLowerCase().includes('control') &&
1179+ console.warn('FAL.AI returned invalid data.');
1180- !x.title.toLowerCase().includes('upscale') &&
1180+ throw new Error('FAL.AI request failed.');
1181- !x.title.toLowerCase().includes('lora'))
1181+ }
1182+
1183+ models = models.concat(
1184+ modelsResponse.items.filter(
1185+ x => (
1186+ !x.title.toLowerCase().includes('inpainting') &&
1187+ !x.title.toLowerCase().includes('control') &&
1188+ !x.title.toLowerCase().includes('upscale') &&
1189+ !x.title.toLowerCase().includes('lora')
1190+ ),
1191+ ),
1192+ );
1193+
1194+ page = modelsResponse.page + 1;
1195+ } while (modelsResponse != null && page < modelsResponse.pages);
1196+
1197+ const modelOptions = models
11821198 .sort((a, b) => a.title.localeCompare(b.title))
11831199 .map(x => ({ value: x.modelUrl.split('fal-ai/')[1], text: x.title }));
11841200 return response.send(modelsmodelOptions);
11851201 } catch (error) {
11861202 console.error(error);
11871203 return response.sendStatus(500);