@howells/motif-sdk 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/image.d.ts +8 -0
- package/dist/image.js +1078 -183
- package/dist/index.cjs +1460 -447
- package/dist/index.d.cts +2288 -410
- package/dist/index.d.ts +2288 -410
- package/dist/index.js +1460 -447
- package/package.json +1 -1
package/dist/image.js
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
// src/image/index.ts
|
|
2
2
|
import { generateImage } from "ai";
|
|
3
|
-
import { err as
|
|
3
|
+
import { err as err3, ok as ok3 } from "neverthrow";
|
|
4
4
|
|
|
5
5
|
// src/server.ts
|
|
6
|
-
import { err, ok } from "neverthrow";
|
|
6
|
+
import { err as err2, ok as ok2 } from "neverthrow";
|
|
7
7
|
|
|
8
8
|
// src/models.ts
|
|
9
|
-
var AA_IMAGE_LEADERBOARD_SNAPSHOT = "2026-
|
|
9
|
+
var AA_IMAGE_LEADERBOARD_SNAPSHOT = "2026-08-23";
|
|
10
10
|
var AA_IMAGE_SOURCES = [
|
|
11
11
|
"https://artificialanalysis.ai/image/leaderboard/text-to-image",
|
|
12
12
|
"https://artificialanalysis.ai/image/leaderboard/editing"
|
|
13
13
|
];
|
|
14
14
|
var FAL_PRICING_CHECKED_AT = "2026-05-12";
|
|
15
15
|
var FAL_PRICING_CHECKED_JUL_2026 = "2026-07-11";
|
|
16
|
+
var FAL_PRICING_CHECKED_AUG_2026 = "2026-08-23";
|
|
16
17
|
var MODELS = {
|
|
17
18
|
// ─── Generation Models ────────────────────────────────────────
|
|
18
19
|
gpt2: {
|
|
19
20
|
benchmark: {
|
|
20
21
|
artificialAnalysis: {
|
|
21
|
-
editing: { elo:
|
|
22
|
+
editing: { elo: 1256, pricePer1k: 211, rank: 3 },
|
|
22
23
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
23
24
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
24
|
-
textToImage: { elo:
|
|
25
|
+
textToImage: { elo: 1369, pricePer1k: 211, rank: 1 }
|
|
25
26
|
},
|
|
26
27
|
speed: {
|
|
27
28
|
medianSeconds: 200.7,
|
|
@@ -61,10 +62,10 @@ var MODELS = {
|
|
|
61
62
|
gpt: {
|
|
62
63
|
benchmark: {
|
|
63
64
|
artificialAnalysis: {
|
|
64
|
-
editing: { elo:
|
|
65
|
+
editing: { elo: 1250, pricePer1k: 133, rank: 5 },
|
|
65
66
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
66
67
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
67
|
-
textToImage: { elo:
|
|
68
|
+
textToImage: { elo: 1310, pricePer1k: 133, rank: 4 }
|
|
68
69
|
},
|
|
69
70
|
speed: {
|
|
70
71
|
medianSeconds: 34.6,
|
|
@@ -104,10 +105,10 @@ var MODELS = {
|
|
|
104
105
|
banana2: {
|
|
105
106
|
benchmark: {
|
|
106
107
|
artificialAnalysis: {
|
|
107
|
-
editing: { elo:
|
|
108
|
+
editing: { elo: 1249, pricePer1k: 67, rank: 7 },
|
|
108
109
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
109
110
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
110
|
-
textToImage: { elo:
|
|
111
|
+
textToImage: { elo: 1320, pricePer1k: 67, rank: 3 }
|
|
111
112
|
},
|
|
112
113
|
tiers: { price: "premium", quality: "frontier", speed: "unknown" },
|
|
113
114
|
useCase: "Best balance of quality, edit support, web search, and cost"
|
|
@@ -145,10 +146,10 @@ var MODELS = {
|
|
|
145
146
|
banana: {
|
|
146
147
|
benchmark: {
|
|
147
148
|
artificialAnalysis: {
|
|
148
|
-
editing: { elo:
|
|
149
|
+
editing: { elo: 1245, pricePer1k: 134, rank: 9 },
|
|
149
150
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
150
151
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
151
|
-
textToImage: { elo:
|
|
152
|
+
textToImage: { elo: 1297, pricePer1k: 134, rank: 6 }
|
|
152
153
|
},
|
|
153
154
|
speed: {
|
|
154
155
|
medianSeconds: 19.2,
|
|
@@ -188,6 +189,13 @@ var MODELS = {
|
|
|
188
189
|
type: "generation"
|
|
189
190
|
},
|
|
190
191
|
gemini: {
|
|
192
|
+
benchmark: {
|
|
193
|
+
artificialAnalysis: {
|
|
194
|
+
editing: { elo: 1180, pricePer1k: 39, rank: 29 },
|
|
195
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
196
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
197
|
+
}
|
|
198
|
+
},
|
|
191
199
|
editEndpoint: "fal-ai/gemini-25-flash-image/edit",
|
|
192
200
|
endpoint: "fal-ai/gemini-25-flash-image",
|
|
193
201
|
falPricing: {
|
|
@@ -215,6 +223,14 @@ var MODELS = {
|
|
|
215
223
|
type: "generation"
|
|
216
224
|
},
|
|
217
225
|
gemini3: {
|
|
226
|
+
benchmark: {
|
|
227
|
+
artificialAnalysis: {
|
|
228
|
+
editing: { elo: 1245, pricePer1k: 134, rank: 9 },
|
|
229
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
230
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
231
|
+
textToImage: { elo: 1297, pricePer1k: 134, rank: 6 }
|
|
232
|
+
}
|
|
233
|
+
},
|
|
218
234
|
editEndpoint: "fal-ai/gemini-3-pro-image-preview/edit",
|
|
219
235
|
endpoint: "fal-ai/gemini-3-pro-image-preview",
|
|
220
236
|
falPricing: {
|
|
@@ -245,10 +261,10 @@ var MODELS = {
|
|
|
245
261
|
seedream4: {
|
|
246
262
|
benchmark: {
|
|
247
263
|
artificialAnalysis: {
|
|
248
|
-
editing: { elo:
|
|
264
|
+
editing: { elo: 1185, pricePer1k: 30, rank: 28 },
|
|
249
265
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
250
266
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
251
|
-
textToImage: { elo:
|
|
267
|
+
textToImage: { elo: 1226, pricePer1k: 30, rank: 16 }
|
|
252
268
|
},
|
|
253
269
|
speed: {
|
|
254
270
|
medianSeconds: 14.3,
|
|
@@ -285,10 +301,10 @@ var MODELS = {
|
|
|
285
301
|
seedream45: {
|
|
286
302
|
benchmark: {
|
|
287
303
|
artificialAnalysis: {
|
|
288
|
-
editing: { elo:
|
|
304
|
+
editing: { elo: 1186, pricePer1k: 40, rank: 26 },
|
|
289
305
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
290
306
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
291
|
-
textToImage: { elo:
|
|
307
|
+
textToImage: { elo: 1203, pricePer1k: 40, rank: 32 }
|
|
292
308
|
},
|
|
293
309
|
speed: {
|
|
294
310
|
medianSeconds: 18.2,
|
|
@@ -323,6 +339,14 @@ var MODELS = {
|
|
|
323
339
|
type: "generation"
|
|
324
340
|
},
|
|
325
341
|
seedream5: {
|
|
342
|
+
benchmark: {
|
|
343
|
+
artificialAnalysis: {
|
|
344
|
+
editing: { elo: 1248, pricePer1k: 90, rank: 8 },
|
|
345
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
346
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
347
|
+
textToImage: { elo: 1279, pricePer1k: 90, rank: 10 }
|
|
348
|
+
}
|
|
349
|
+
},
|
|
326
350
|
name: "Seedream 5.0 Pro",
|
|
327
351
|
endpoint: "bytedance/seedream/v5/pro/text-to-image",
|
|
328
352
|
editEndpoint: "bytedance/seedream/v5/pro/edit",
|
|
@@ -349,6 +373,13 @@ var MODELS = {
|
|
|
349
373
|
maxReferenceImages: 10
|
|
350
374
|
},
|
|
351
375
|
"seedream5-lite": {
|
|
376
|
+
benchmark: {
|
|
377
|
+
artificialAnalysis: {
|
|
378
|
+
editing: { elo: 1169, pricePer1k: 35, rank: 32 },
|
|
379
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
380
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
381
|
+
}
|
|
382
|
+
},
|
|
352
383
|
name: "Seedream 5.0 Lite",
|
|
353
384
|
endpoint: "fal-ai/bytedance/seedream/v5/lite/text-to-image",
|
|
354
385
|
editEndpoint: "fal-ai/bytedance/seedream/v5/lite/edit",
|
|
@@ -377,10 +408,10 @@ var MODELS = {
|
|
|
377
408
|
"flux2-max": {
|
|
378
409
|
benchmark: {
|
|
379
410
|
artificialAnalysis: {
|
|
380
|
-
editing: { elo:
|
|
411
|
+
editing: { elo: 1201, pricePer1k: 140, rank: 19 },
|
|
381
412
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
382
413
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
383
|
-
textToImage: { elo:
|
|
414
|
+
textToImage: { elo: 1225, pricePer1k: 70, rank: 17 }
|
|
384
415
|
},
|
|
385
416
|
speed: {
|
|
386
417
|
medianSeconds: 31.6,
|
|
@@ -420,10 +451,10 @@ var MODELS = {
|
|
|
420
451
|
"flux2-pro": {
|
|
421
452
|
benchmark: {
|
|
422
453
|
artificialAnalysis: {
|
|
423
|
-
editing: { elo: 1170, pricePer1k:
|
|
454
|
+
editing: { elo: 1170, pricePer1k: 45, rank: 31 },
|
|
424
455
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
425
456
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
426
|
-
textToImage: { elo:
|
|
457
|
+
textToImage: { elo: 1207, pricePer1k: 30, rank: 30 }
|
|
427
458
|
},
|
|
428
459
|
speed: {
|
|
429
460
|
medianSeconds: 16.1,
|
|
@@ -463,10 +494,9 @@ var MODELS = {
|
|
|
463
494
|
"flux2-flex": {
|
|
464
495
|
benchmark: {
|
|
465
496
|
artificialAnalysis: {
|
|
466
|
-
editing: { elo: 1161, pricePer1k: 60, rank: 22 },
|
|
467
497
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
468
498
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
469
|
-
textToImage: { elo:
|
|
499
|
+
textToImage: { elo: 1223, pricePer1k: 60, rank: 18 }
|
|
470
500
|
},
|
|
471
501
|
speed: {
|
|
472
502
|
medianSeconds: 15.3,
|
|
@@ -510,8 +540,7 @@ var MODELS = {
|
|
|
510
540
|
benchmark: {
|
|
511
541
|
artificialAnalysis: {
|
|
512
542
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
513
|
-
sourceUrls: AA_IMAGE_SOURCES
|
|
514
|
-
textToImage: { elo: 1160, pricePer1k: 12, rank: 19, winRate: 0.57 }
|
|
543
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
515
544
|
},
|
|
516
545
|
speed: {
|
|
517
546
|
medianSeconds: 4.6,
|
|
@@ -654,7 +683,55 @@ var MODELS = {
|
|
|
654
683
|
supportsSyncMode: true,
|
|
655
684
|
type: "generation"
|
|
656
685
|
},
|
|
686
|
+
reve: {
|
|
687
|
+
benchmark: {
|
|
688
|
+
artificialAnalysis: {
|
|
689
|
+
// #2 on BOTH boards, which almost nothing else manages - the top text-to-image model
|
|
690
|
+
// (GPT Image 2) drops to 3rd for editing, and the top editor (MAI-Image-2.5-Pro) is not
|
|
691
|
+
// on fal at all. Reve is the best editor motif can actually reach.
|
|
692
|
+
editing: { elo: 1263, pricePer1k: 200, rank: 2 },
|
|
693
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
694
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
695
|
+
textToImage: { elo: 1322, pricePer1k: 200, rank: 2 }
|
|
696
|
+
},
|
|
697
|
+
tiers: { price: "premium", quality: "frontier", speed: "unknown" },
|
|
698
|
+
useCase: "Highest-ranked editor reachable on fal; strong prompt adherence and text rendering"
|
|
699
|
+
},
|
|
700
|
+
editEndpoint: "fal-ai/reve/edit",
|
|
701
|
+
endpoint: "fal-ai/reve/text-to-image",
|
|
702
|
+
falPricing: {
|
|
703
|
+
checkedAt: FAL_PRICING_CHECKED_AUG_2026,
|
|
704
|
+
currency: "USD",
|
|
705
|
+
endpointId: "fal-ai/reve/text-to-image",
|
|
706
|
+
estimatedCostPerImageUsd: 0.04,
|
|
707
|
+
source: "fal-pricing-api",
|
|
708
|
+
unit: "images",
|
|
709
|
+
unitPrice: 0.04
|
|
710
|
+
},
|
|
711
|
+
maxReferenceImages: 1,
|
|
712
|
+
name: "Reve 2.1",
|
|
713
|
+
pricePerImageUsd: 0.04,
|
|
714
|
+
pricing: "$0.04",
|
|
715
|
+
// fal's schema takes aspect_ratio from a fixed set and has no width/height or resolution
|
|
716
|
+
// parameter, so aspect is supported and resolution is not.
|
|
717
|
+
sizeMode: "aspect_ratio",
|
|
718
|
+
supportsAspect: true,
|
|
719
|
+
supportsEdit: true,
|
|
720
|
+
supportsNumImages: true,
|
|
721
|
+
supportsOutputFormat: true,
|
|
722
|
+
supportsResolution: false,
|
|
723
|
+
supportsSeed: false,
|
|
724
|
+
supportsSyncMode: true,
|
|
725
|
+
type: "generation"
|
|
726
|
+
},
|
|
657
727
|
recraft4: {
|
|
728
|
+
benchmark: {
|
|
729
|
+
artificialAnalysis: {
|
|
730
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
731
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
732
|
+
textToImage: { elo: 1215, pricePer1k: 35, rank: 25 }
|
|
733
|
+
}
|
|
734
|
+
},
|
|
658
735
|
endpoint: "fal-ai/recraft/v4/text-to-image",
|
|
659
736
|
falPricing: {
|
|
660
737
|
checkedAt: FAL_PRICING_CHECKED_JUL_2026,
|
|
@@ -705,6 +782,13 @@ var MODELS = {
|
|
|
705
782
|
type: "generation"
|
|
706
783
|
},
|
|
707
784
|
ideogram4: {
|
|
785
|
+
benchmark: {
|
|
786
|
+
artificialAnalysis: {
|
|
787
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
788
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
789
|
+
textToImage: { elo: 1220, pricePer1k: 60, rank: 19 }
|
|
790
|
+
}
|
|
791
|
+
},
|
|
708
792
|
name: "Ideogram V4",
|
|
709
793
|
endpoint: "ideogram/v4",
|
|
710
794
|
type: "generation",
|
|
@@ -737,10 +821,10 @@ var MODELS = {
|
|
|
737
821
|
"grok-image": {
|
|
738
822
|
benchmark: {
|
|
739
823
|
artificialAnalysis: {
|
|
740
|
-
editing: { elo:
|
|
824
|
+
editing: { elo: 1214, pricePer1k: 20, rank: 16 },
|
|
741
825
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
742
826
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
743
|
-
textToImage: { elo:
|
|
827
|
+
textToImage: { elo: 1216, pricePer1k: 20, rank: 23 }
|
|
744
828
|
},
|
|
745
829
|
speed: {
|
|
746
830
|
medianSeconds: 5.1,
|
|
@@ -778,8 +862,7 @@ var MODELS = {
|
|
|
778
862
|
benchmark: {
|
|
779
863
|
artificialAnalysis: {
|
|
780
864
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
781
|
-
sourceUrls: AA_IMAGE_SOURCES
|
|
782
|
-
textToImage: { elo: 1158, pricePer1k: 20, rank: 20, winRate: 0.6 }
|
|
865
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
783
866
|
},
|
|
784
867
|
speed: {
|
|
785
868
|
medianSeconds: 23.3,
|
|
@@ -812,6 +895,41 @@ var MODELS = {
|
|
|
812
895
|
supportsSyncMode: true,
|
|
813
896
|
type: "generation"
|
|
814
897
|
},
|
|
898
|
+
qwen3: {
|
|
899
|
+
benchmark: {
|
|
900
|
+
artificialAnalysis: {
|
|
901
|
+
editing: { elo: 1218, pricePer1k: 33, rank: 15 },
|
|
902
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
903
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
904
|
+
textToImage: { elo: 1272, pricePer1k: 30, rank: 11 }
|
|
905
|
+
},
|
|
906
|
+
tiers: { price: "budget", quality: "better", speed: "unknown" },
|
|
907
|
+
useCase: "Strong quality per dollar - 11th on text-to-image at $30/1k"
|
|
908
|
+
},
|
|
909
|
+
endpoint: "fal-ai/qwen-image-3/text-to-image",
|
|
910
|
+
falPricing: {
|
|
911
|
+
checkedAt: "2026-08-05",
|
|
912
|
+
currency: "USD",
|
|
913
|
+
endpointId: "fal-ai/qwen-image-3/text-to-image",
|
|
914
|
+
estimatedCostPerImageUsd: 0.02,
|
|
915
|
+
source: "fal-pricing-api",
|
|
916
|
+
unit: "megapixels",
|
|
917
|
+
unitPrice: 0.02
|
|
918
|
+
},
|
|
919
|
+
name: "Qwen Image 3",
|
|
920
|
+
pricePerImageUsd: 0.02,
|
|
921
|
+
pricing: "$0.02/MP (assumed from qwen v1; fal pricing page bot-gated at check time)",
|
|
922
|
+
sizeMode: "image_size_enum",
|
|
923
|
+
supportsAspect: true,
|
|
924
|
+
supportsEdit: false,
|
|
925
|
+
supportsNegativePrompt: true,
|
|
926
|
+
supportsNumImages: true,
|
|
927
|
+
supportsOutputFormat: true,
|
|
928
|
+
supportsResolution: false,
|
|
929
|
+
supportsSafetyChecker: true,
|
|
930
|
+
supportsSeed: true,
|
|
931
|
+
type: "generation"
|
|
932
|
+
},
|
|
815
933
|
// ─── Video Models ─────────────────────────────────────────────
|
|
816
934
|
kling: {
|
|
817
935
|
endpoint: "fal-ai/kling-video/v3/pro/image-to-video",
|
|
@@ -889,14 +1007,385 @@ var GENERATION_MODELS = [
|
|
|
889
1007
|
"ideogram",
|
|
890
1008
|
"ideogram4",
|
|
891
1009
|
"grok-image",
|
|
892
|
-
"qwen"
|
|
1010
|
+
"qwen",
|
|
1011
|
+
"qwen3"
|
|
893
1012
|
];
|
|
894
1013
|
var EDIT_CAPABLE_MODELS = GENERATION_MODELS.filter(
|
|
895
1014
|
(id) => MODELS[id]?.supportsEdit === true
|
|
896
1015
|
);
|
|
897
1016
|
|
|
898
|
-
// src/
|
|
899
|
-
var
|
|
1017
|
+
// src/errors.ts
|
|
1018
|
+
var MotifError = class extends Error {
|
|
1019
|
+
status;
|
|
1020
|
+
code;
|
|
1021
|
+
/** fal's request-correlation id (from the `x-fal-request-id` header or the
|
|
1022
|
+
* error body). Ties a failure back to fal's dashboard/support. */
|
|
1023
|
+
requestId;
|
|
1024
|
+
constructor(message, status, code, requestId) {
|
|
1025
|
+
super(message);
|
|
1026
|
+
this.name = "MotifError";
|
|
1027
|
+
this.status = status;
|
|
1028
|
+
this.code = code;
|
|
1029
|
+
this.requestId = requestId;
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
|
|
1033
|
+
// src/server-tools.ts
|
|
1034
|
+
import { err, ok } from "neverthrow";
|
|
1035
|
+
|
|
1036
|
+
// src/tool-registry/analysis.ts
|
|
1037
|
+
var ANALYSIS_TOOLS = {
|
|
1038
|
+
"got-ocr": {
|
|
1039
|
+
category: "analysis",
|
|
1040
|
+
description: "Transcribe text from one or more images, optionally as formatted multi-page output.",
|
|
1041
|
+
endpoint: "fal-ai/got-ocr/v2",
|
|
1042
|
+
inputField: "input_image_urls",
|
|
1043
|
+
inputKind: "images",
|
|
1044
|
+
name: "GOT-OCR 2.0",
|
|
1045
|
+
outputKeys: ["outputs"],
|
|
1046
|
+
price: { kind: "metered" },
|
|
1047
|
+
pricing: "$0.05/image",
|
|
1048
|
+
queued: true,
|
|
1049
|
+
sourceUrl: "https://fal.ai/models/fal-ai/got-ocr/v2",
|
|
1050
|
+
task: "optical character recognition"
|
|
1051
|
+
},
|
|
1052
|
+
"moondream-caption": {
|
|
1053
|
+
category: "analysis",
|
|
1054
|
+
description: "Write a short, normal, or long caption for an image.",
|
|
1055
|
+
endpoint: "fal-ai/moondream3-preview/caption",
|
|
1056
|
+
inputField: "image_url",
|
|
1057
|
+
inputKind: "image",
|
|
1058
|
+
name: "Moondream 3 Caption",
|
|
1059
|
+
outputKeys: ["output"],
|
|
1060
|
+
price: { kind: "metered" },
|
|
1061
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1062
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/caption",
|
|
1063
|
+
task: "image captioning"
|
|
1064
|
+
},
|
|
1065
|
+
"moondream-detect": {
|
|
1066
|
+
category: "analysis",
|
|
1067
|
+
description: "Detect prompted objects and return their bounding boxes, with an optional preview.",
|
|
1068
|
+
endpoint: "fal-ai/moondream3-preview/detect",
|
|
1069
|
+
inputField: "image_url",
|
|
1070
|
+
inputKind: "image",
|
|
1071
|
+
name: "Moondream 3 Detect",
|
|
1072
|
+
outputKeys: ["objects", "image"],
|
|
1073
|
+
price: { kind: "metered" },
|
|
1074
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1075
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/detect",
|
|
1076
|
+
task: "object detection"
|
|
1077
|
+
},
|
|
1078
|
+
"moondream-point": {
|
|
1079
|
+
category: "analysis",
|
|
1080
|
+
description: "Return point coordinates for every instance of a prompted subject.",
|
|
1081
|
+
endpoint: "fal-ai/moondream3-preview/point",
|
|
1082
|
+
inputField: "image_url",
|
|
1083
|
+
inputKind: "image",
|
|
1084
|
+
name: "Moondream 3 Point",
|
|
1085
|
+
outputKeys: ["points", "image"],
|
|
1086
|
+
price: { kind: "metered" },
|
|
1087
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1088
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/point",
|
|
1089
|
+
task: "object pointing"
|
|
1090
|
+
},
|
|
1091
|
+
"moondream-query": {
|
|
1092
|
+
category: "analysis",
|
|
1093
|
+
description: "Answer a free-form question about an image, with reasoning.",
|
|
1094
|
+
endpoint: "fal-ai/moondream3-preview/query",
|
|
1095
|
+
inputField: "image_url",
|
|
1096
|
+
inputKind: "image",
|
|
1097
|
+
name: "Moondream 3 Query",
|
|
1098
|
+
outputKeys: ["output", "reasoning"],
|
|
1099
|
+
price: { kind: "metered" },
|
|
1100
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1101
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/query",
|
|
1102
|
+
task: "visual question answering"
|
|
1103
|
+
},
|
|
1104
|
+
nsfw: {
|
|
1105
|
+
category: "moderation",
|
|
1106
|
+
description: "Predict whether one or more images contain NSFW concepts.",
|
|
1107
|
+
endpoint: "fal-ai/x-ailab/nsfw",
|
|
1108
|
+
inputField: "image_urls",
|
|
1109
|
+
inputKind: "images",
|
|
1110
|
+
name: "NSFW Checker",
|
|
1111
|
+
outputKeys: ["has_nsfw_concepts"],
|
|
1112
|
+
price: { kind: "metered" },
|
|
1113
|
+
pricing: "$0.001/image",
|
|
1114
|
+
sourceUrl: "https://fal.ai/models/fal-ai/x-ailab/nsfw",
|
|
1115
|
+
task: "vision moderation"
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
|
|
1119
|
+
// src/tool-registry/assets.ts
|
|
1120
|
+
var ASSET_TOOLS = {
|
|
1121
|
+
"hunyuan3d-v3": {
|
|
1122
|
+
category: "3d",
|
|
1123
|
+
description: "Reconstruct a textured 3D mesh from a single image, with optional multi-view inputs.",
|
|
1124
|
+
endpoint: "fal-ai/hunyuan3d-v3/image-to-3d",
|
|
1125
|
+
inputField: "input_image_url",
|
|
1126
|
+
inputKind: "image",
|
|
1127
|
+
name: "Hunyuan3D v3 Image to 3D",
|
|
1128
|
+
outputKeys: ["model_glb", "model_urls", "thumbnail"],
|
|
1129
|
+
price: { kind: "call", usd: 0.375 },
|
|
1130
|
+
pricing: "$0.375/generation at the default Normal type; $0.45 low poly, $0.225 geometry only, and $0.15 each for PBR, multi-view, or a custom face count",
|
|
1131
|
+
queued: true,
|
|
1132
|
+
sourceUrl: "https://fal.ai/models/fal-ai/hunyuan3d-v3/image-to-3d",
|
|
1133
|
+
task: "single-image 3D reconstruction"
|
|
1134
|
+
},
|
|
1135
|
+
"ideogram-layerize-text": {
|
|
1136
|
+
category: "layers",
|
|
1137
|
+
description: "Split an image into background image layers plus editable HTML text containers.",
|
|
1138
|
+
endpoint: "fal-ai/ideogram/v3/layerize-text",
|
|
1139
|
+
inputField: "image_url",
|
|
1140
|
+
inputKind: "image",
|
|
1141
|
+
name: "Ideogram v3 Text Layerize",
|
|
1142
|
+
outputKeys: ["image_layers", "image", "text_html", "text_containers"],
|
|
1143
|
+
price: { kind: "call", usd: 0.09 },
|
|
1144
|
+
pricing: "$0.09/image",
|
|
1145
|
+
queued: true,
|
|
1146
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ideogram/v3/layerize-text",
|
|
1147
|
+
task: "text and image layer extraction"
|
|
1148
|
+
},
|
|
1149
|
+
"ideogram-tiling": {
|
|
1150
|
+
category: "material",
|
|
1151
|
+
description: "Generate a seamlessly tiling texture, optionally conditioned on a source image.",
|
|
1152
|
+
endpoint: "ideogram/v4/tiling",
|
|
1153
|
+
inputField: "image_url",
|
|
1154
|
+
inputKind: "image",
|
|
1155
|
+
name: "Ideogram v4 Tiling",
|
|
1156
|
+
outputKeys: ["images"],
|
|
1157
|
+
price: { kind: "megapixel", usd: 0.06 },
|
|
1158
|
+
pricing: "$0.06/megapixel at the default BALANCED speed; $0.03 turbo, $0.10 quality",
|
|
1159
|
+
sourceUrl: "https://fal.ai/models/ideogram/v4/tiling",
|
|
1160
|
+
task: "seamless texture generation"
|
|
1161
|
+
},
|
|
1162
|
+
image2svg: {
|
|
1163
|
+
category: "vector",
|
|
1164
|
+
description: "Trace a raster image into layered SVG paths.",
|
|
1165
|
+
endpoint: "fal-ai/image2svg",
|
|
1166
|
+
inputField: "image_url",
|
|
1167
|
+
inputKind: "image",
|
|
1168
|
+
name: "Image to SVG",
|
|
1169
|
+
outputKeys: ["images"],
|
|
1170
|
+
price: { kind: "call", usd: 5e-3 },
|
|
1171
|
+
pricing: "$0.005/image",
|
|
1172
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image2svg",
|
|
1173
|
+
task: "raster to vector tracing"
|
|
1174
|
+
},
|
|
1175
|
+
patina: {
|
|
1176
|
+
category: "material",
|
|
1177
|
+
description: "Decompose a surface photograph into PBR maps: basecolor, normal, roughness, metalness, height.",
|
|
1178
|
+
endpoint: "fal-ai/patina",
|
|
1179
|
+
inputField: "image_url",
|
|
1180
|
+
inputKind: "image",
|
|
1181
|
+
name: "Patina PBR Maps",
|
|
1182
|
+
outputKeys: ["images"],
|
|
1183
|
+
// Output order follows the request's `maps` array, so read that first;
|
|
1184
|
+
// the fallback is the endpoint's own schema default.
|
|
1185
|
+
outputLabels: {
|
|
1186
|
+
images: {
|
|
1187
|
+
fallback: ["basecolor", "normal", "roughness", "metalness", "height"],
|
|
1188
|
+
fromOption: "maps"
|
|
1189
|
+
}
|
|
1190
|
+
},
|
|
1191
|
+
price: { kind: "metered" },
|
|
1192
|
+
pricing: "$0.01 base plus $0.01/megapixel per output map, so all 5 maps on a 1MP image cost $0.06; the listed rate is per map",
|
|
1193
|
+
queued: true,
|
|
1194
|
+
sourceUrl: "https://fal.ai/models/fal-ai/patina",
|
|
1195
|
+
task: "PBR material decomposition"
|
|
1196
|
+
},
|
|
1197
|
+
"patina-extract": {
|
|
1198
|
+
category: "material",
|
|
1199
|
+
description: "Extract a tiling PBR material from a prompted region of a photograph.",
|
|
1200
|
+
endpoint: "fal-ai/patina/material/extract",
|
|
1201
|
+
inputField: "image_url",
|
|
1202
|
+
inputKind: "image",
|
|
1203
|
+
name: "Patina Material Extract",
|
|
1204
|
+
outputKeys: ["images"],
|
|
1205
|
+
// Same `maps` option and schema default as fal-ai/patina, both verified.
|
|
1206
|
+
// `num_images` above 1 multiplies the array and breaks the mapping, which
|
|
1207
|
+
// the count check catches.
|
|
1208
|
+
outputLabels: {
|
|
1209
|
+
images: {
|
|
1210
|
+
fallback: ["basecolor", "normal", "roughness", "metalness", "height"],
|
|
1211
|
+
fromOption: "maps"
|
|
1212
|
+
}
|
|
1213
|
+
},
|
|
1214
|
+
price: { kind: "metered" },
|
|
1215
|
+
pricing: "$0.10 base only; add $0.02/megapixel plus $0.01/megapixel per map, so 1MP with all 5 maps is $0.17",
|
|
1216
|
+
queued: true,
|
|
1217
|
+
sourceUrl: "https://fal.ai/models/fal-ai/patina/material/extract",
|
|
1218
|
+
task: "tiling material extraction"
|
|
1219
|
+
},
|
|
1220
|
+
"qwen-layered": {
|
|
1221
|
+
category: "layers",
|
|
1222
|
+
description: "Split an image into a configurable number of stacked RGBA layers.",
|
|
1223
|
+
endpoint: "fal-ai/qwen-image-layered",
|
|
1224
|
+
inputField: "image_url",
|
|
1225
|
+
inputKind: "image",
|
|
1226
|
+
name: "Qwen Image Layered",
|
|
1227
|
+
outputKeys: ["images"],
|
|
1228
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
1229
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
1230
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
1231
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
1232
|
+
// rather than a number that is right only on one reading.
|
|
1233
|
+
price: { kind: "metered" },
|
|
1234
|
+
pricing: "$0.05 per image; fal does not say whether that counts the input image or each of the generated layers, so no estimate is reported",
|
|
1235
|
+
queued: true,
|
|
1236
|
+
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-layered",
|
|
1237
|
+
task: "image layer decomposition"
|
|
1238
|
+
},
|
|
1239
|
+
"recraft-vectorize": {
|
|
1240
|
+
category: "vector",
|
|
1241
|
+
description: "Convert a raster image into a clean SVG.",
|
|
1242
|
+
endpoint: "fal-ai/recraft/vectorize",
|
|
1243
|
+
inputField: "image_url",
|
|
1244
|
+
inputKind: "image",
|
|
1245
|
+
name: "Recraft Vectorize",
|
|
1246
|
+
outputKeys: ["image"],
|
|
1247
|
+
price: { kind: "call", usd: 0.04 },
|
|
1248
|
+
pricing: "$0.04/image, $0.08 with a vector style",
|
|
1249
|
+
sourceUrl: "https://fal.ai/models/fal-ai/recraft/vectorize",
|
|
1250
|
+
task: "raster to vector conversion"
|
|
1251
|
+
},
|
|
1252
|
+
"sam3-3d-align": {
|
|
1253
|
+
category: "3d",
|
|
1254
|
+
description: "Align SAM 3D objects and bodies into a shared scene.",
|
|
1255
|
+
endpoint: "fal-ai/sam-3/3d-align",
|
|
1256
|
+
inputField: "image_url",
|
|
1257
|
+
inputKind: "image",
|
|
1258
|
+
name: "SAM 3D Align",
|
|
1259
|
+
outputKeys: [
|
|
1260
|
+
"scene_glb",
|
|
1261
|
+
"model_glb",
|
|
1262
|
+
"visualization",
|
|
1263
|
+
"body_mesh_ply",
|
|
1264
|
+
"metadata"
|
|
1265
|
+
],
|
|
1266
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
1267
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
1268
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
1269
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
1270
|
+
// rather than a number that is right only on one reading.
|
|
1271
|
+
price: { kind: "metered" },
|
|
1272
|
+
pricing: "$0.02 per unit; fal does not define a unit, so no estimate is reported",
|
|
1273
|
+
queued: true,
|
|
1274
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-align",
|
|
1275
|
+
task: "3D scene alignment"
|
|
1276
|
+
},
|
|
1277
|
+
"sam3-3d-body": {
|
|
1278
|
+
category: "3d",
|
|
1279
|
+
defaultOptions: {
|
|
1280
|
+
export_meshes: true,
|
|
1281
|
+
include_3d_keypoints: true,
|
|
1282
|
+
include_mhr_params: true
|
|
1283
|
+
},
|
|
1284
|
+
description: "Reconstruct human body meshes and keypoints from a single image.",
|
|
1285
|
+
endpoint: "fal-ai/sam-3/3d-body",
|
|
1286
|
+
inputField: "image_url",
|
|
1287
|
+
inputKind: "image",
|
|
1288
|
+
name: "SAM 3D Body",
|
|
1289
|
+
outputKeys: ["model_glb", "visualization", "meshes", "metadata"],
|
|
1290
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
1291
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
1292
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
1293
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
1294
|
+
// rather than a number that is right only on one reading.
|
|
1295
|
+
price: { kind: "metered" },
|
|
1296
|
+
pricing: "$0.02 per unit; fal does not define a unit, so no estimate is reported",
|
|
1297
|
+
queued: true,
|
|
1298
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-body",
|
|
1299
|
+
task: "single-image 3D body reconstruction"
|
|
1300
|
+
},
|
|
1301
|
+
"sam3-3d-objects": {
|
|
1302
|
+
category: "3d",
|
|
1303
|
+
defaultOptions: {
|
|
1304
|
+
prompt: "car"
|
|
1305
|
+
},
|
|
1306
|
+
description: "Reconstruct one or more 3D objects from an image and prompts.",
|
|
1307
|
+
endpoint: "fal-ai/sam-3/3d-objects",
|
|
1308
|
+
inputField: "image_url",
|
|
1309
|
+
inputKind: "image",
|
|
1310
|
+
name: "SAM 3D Objects",
|
|
1311
|
+
outputKeys: [
|
|
1312
|
+
"gaussian_splat",
|
|
1313
|
+
"model_glb",
|
|
1314
|
+
"metadata",
|
|
1315
|
+
"individual_splats",
|
|
1316
|
+
"individual_glbs",
|
|
1317
|
+
"artifacts_zip"
|
|
1318
|
+
],
|
|
1319
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
1320
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
1321
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
1322
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
1323
|
+
// rather than a number that is right only on one reading.
|
|
1324
|
+
price: { kind: "metered" },
|
|
1325
|
+
pricing: "$0.02 per unit; fal does not define a unit, and this endpoint returns one mesh per detected object, so no estimate is reported",
|
|
1326
|
+
queued: true,
|
|
1327
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-objects",
|
|
1328
|
+
task: "single-image 3D object reconstruction"
|
|
1329
|
+
},
|
|
1330
|
+
"seedream-layerize": {
|
|
1331
|
+
category: "layers",
|
|
1332
|
+
description: "Split an image into editable Seedream layers plus flattened previews.",
|
|
1333
|
+
endpoint: "bytedance/seedream/v5/pro/layerize",
|
|
1334
|
+
inputField: "image_url",
|
|
1335
|
+
inputKind: "image",
|
|
1336
|
+
name: "Seedream v5 Pro Layerize",
|
|
1337
|
+
outputKeys: ["layers", "images"],
|
|
1338
|
+
price: { kind: "metered" },
|
|
1339
|
+
pricing: "$0.03375 per generated layer below 1536x1536 total area, $0.0675 per layer above; the listed rate is per layer, not per call",
|
|
1340
|
+
queued: true,
|
|
1341
|
+
sourceUrl: "https://fal.ai/models/bytedance/seedream/v5/pro/layerize",
|
|
1342
|
+
task: "image layer decomposition"
|
|
1343
|
+
},
|
|
1344
|
+
"seedvr-seamless": {
|
|
1345
|
+
category: "material",
|
|
1346
|
+
description: "Upscale a tiling texture while keeping its edges seamless. ",
|
|
1347
|
+
endpoint: "fal-ai/seedvr/upscale/image/seamless",
|
|
1348
|
+
inputField: "image_url",
|
|
1349
|
+
inputKind: "image",
|
|
1350
|
+
name: "SeedVR Seamless Upscale",
|
|
1351
|
+
outputKeys: ["image"],
|
|
1352
|
+
price: { kind: "megapixel", usd: 25e-4 },
|
|
1353
|
+
pricing: "$0.0025/megapixel",
|
|
1354
|
+
queued: true,
|
|
1355
|
+
sourceUrl: "https://fal.ai/models/fal-ai/seedvr/upscale/image/seamless",
|
|
1356
|
+
task: "seamless texture upscaling"
|
|
1357
|
+
},
|
|
1358
|
+
"trellis-2": {
|
|
1359
|
+
category: "3d",
|
|
1360
|
+
description: "Reconstruct a textured 3D mesh from a single image, with UV unwrapping.",
|
|
1361
|
+
endpoint: "fal-ai/trellis-2",
|
|
1362
|
+
inputField: "image_url",
|
|
1363
|
+
inputKind: "image",
|
|
1364
|
+
name: "TRELLIS 2",
|
|
1365
|
+
outputKeys: ["model_glb"],
|
|
1366
|
+
price: { kind: "call", usd: 0.3 },
|
|
1367
|
+
pricing: "$0.30 at the default 1024p; $0.25 at 512p, $0.35 at 1536p",
|
|
1368
|
+
queued: true,
|
|
1369
|
+
sourceUrl: "https://fal.ai/models/fal-ai/trellis-2",
|
|
1370
|
+
task: "single-image 3D reconstruction"
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
1373
|
+
|
|
1374
|
+
// src/tool-registry/background.ts
|
|
1375
|
+
var BACKGROUND_TOOLS = {
|
|
1376
|
+
"ben-v2": {
|
|
1377
|
+
category: "background",
|
|
1378
|
+
description: "Fast, high-quality background removal for images.",
|
|
1379
|
+
endpoint: "fal-ai/ben/v2/image",
|
|
1380
|
+
inputField: "image_url",
|
|
1381
|
+
inputKind: "image",
|
|
1382
|
+
name: "BEN v2 Background Removal",
|
|
1383
|
+
outputKeys: ["image"],
|
|
1384
|
+
price: { kind: "megapixel", usd: 0.025 },
|
|
1385
|
+
pricing: "$0.025/megapixel",
|
|
1386
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ben/v2/image",
|
|
1387
|
+
task: "image background removal"
|
|
1388
|
+
},
|
|
900
1389
|
birefnet: {
|
|
901
1390
|
category: "background",
|
|
902
1391
|
defaultOptions: {
|
|
@@ -911,6 +1400,7 @@ var FAL_TOOLS = {
|
|
|
911
1400
|
inputKind: "image",
|
|
912
1401
|
name: "BirefNet Background Removal",
|
|
913
1402
|
outputKeys: ["image", "mask_image"],
|
|
1403
|
+
price: { kind: "metered" },
|
|
914
1404
|
pricing: "$0/compute-second listed by fal",
|
|
915
1405
|
sourceUrl: "https://fal.ai/models/fal-ai/birefnet/v2",
|
|
916
1406
|
task: "image background removal"
|
|
@@ -923,7 +1413,8 @@ var FAL_TOOLS = {
|
|
|
923
1413
|
inputKind: "image",
|
|
924
1414
|
name: "Bria RMBG 2.0",
|
|
925
1415
|
outputKeys: ["image"],
|
|
926
|
-
|
|
1416
|
+
price: { kind: "call", usd: 0.018 },
|
|
1417
|
+
pricing: "$0.018/generation",
|
|
927
1418
|
sourceUrl: "https://fal.ai/models/fal-ai/bria/background/remove",
|
|
928
1419
|
task: "image background removal"
|
|
929
1420
|
},
|
|
@@ -940,35 +1431,475 @@ var FAL_TOOLS = {
|
|
|
940
1431
|
inputKind: "video",
|
|
941
1432
|
name: "Bria Video Background Removal",
|
|
942
1433
|
outputKeys: ["video"],
|
|
943
|
-
|
|
1434
|
+
price: { kind: "second", usd: 425e-5 },
|
|
1435
|
+
pricing: "$0.00425/sec",
|
|
1436
|
+
queued: true,
|
|
944
1437
|
sourceUrl: "https://fal.ai/models/bria/video/background-removal",
|
|
945
1438
|
task: "video background removal"
|
|
946
1439
|
},
|
|
947
|
-
|
|
948
|
-
category: "
|
|
949
|
-
description: "
|
|
950
|
-
endpoint: "fal-ai/
|
|
1440
|
+
ddcolor: {
|
|
1441
|
+
category: "restoration",
|
|
1442
|
+
description: "Colourise black-and-white photographs.",
|
|
1443
|
+
endpoint: "fal-ai/ddcolor",
|
|
951
1444
|
inputField: "image_url",
|
|
952
1445
|
inputKind: "image",
|
|
953
|
-
name: "
|
|
1446
|
+
name: "DDColor Colourisation",
|
|
954
1447
|
outputKeys: ["image"],
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1448
|
+
price: { kind: "megapixel", usd: 1e-3 },
|
|
1449
|
+
pricing: "$0.001/megapixel",
|
|
1450
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ddcolor",
|
|
1451
|
+
task: "photo colourisation"
|
|
958
1452
|
},
|
|
959
|
-
|
|
960
|
-
category: "
|
|
1453
|
+
rembg: {
|
|
1454
|
+
category: "background",
|
|
961
1455
|
defaultOptions: {
|
|
962
|
-
|
|
1456
|
+
crop_to_bbox: false
|
|
963
1457
|
},
|
|
964
|
-
description: "
|
|
965
|
-
endpoint: "fal-ai/
|
|
1458
|
+
description: "Generic image background removal utility.",
|
|
1459
|
+
endpoint: "fal-ai/imageutils/rembg",
|
|
966
1460
|
inputField: "image_url",
|
|
967
1461
|
inputKind: "image",
|
|
968
|
-
name: "
|
|
1462
|
+
name: "Remove Background",
|
|
969
1463
|
outputKeys: ["image"],
|
|
1464
|
+
price: { kind: "metered" },
|
|
970
1465
|
pricing: "$0/compute-second listed by fal",
|
|
971
|
-
sourceUrl: "https://fal.ai/models/fal-ai/
|
|
1466
|
+
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/rembg",
|
|
1467
|
+
task: "image background removal"
|
|
1468
|
+
},
|
|
1469
|
+
"seedvr-upscale": {
|
|
1470
|
+
category: "restoration",
|
|
1471
|
+
defaultOptions: {
|
|
1472
|
+
output_format: "png"
|
|
1473
|
+
},
|
|
1474
|
+
description: "Diffusion image restoration and upscaling with SeedVR.",
|
|
1475
|
+
endpoint: "fal-ai/seedvr/upscale/image",
|
|
1476
|
+
inputField: "image_url",
|
|
1477
|
+
inputKind: "image",
|
|
1478
|
+
name: "SeedVR Image Upscale",
|
|
1479
|
+
outputKeys: ["image"],
|
|
1480
|
+
price: { kind: "megapixel", usd: 1e-3 },
|
|
1481
|
+
pricing: "$0.001/megapixel",
|
|
1482
|
+
queued: true,
|
|
1483
|
+
sourceUrl: "https://fal.ai/models/fal-ai/seedvr/upscale/image",
|
|
1484
|
+
task: "image restoration and upscaling"
|
|
1485
|
+
},
|
|
1486
|
+
"topaz-adjust": {
|
|
1487
|
+
category: "restoration",
|
|
1488
|
+
defaultOptions: {
|
|
1489
|
+
output_format: "png"
|
|
1490
|
+
},
|
|
1491
|
+
description: "Topaz exposure, white balance, and colour adjustment.",
|
|
1492
|
+
endpoint: "topaz/adjust/image",
|
|
1493
|
+
inputField: "image_url",
|
|
1494
|
+
inputKind: "image",
|
|
1495
|
+
name: "Topaz Adjust",
|
|
1496
|
+
outputKeys: ["image"],
|
|
1497
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
1498
|
+
pricing: "$0.08 per 24 output megapixels",
|
|
1499
|
+
queued: true,
|
|
1500
|
+
sourceUrl: "https://fal.ai/models/topaz/adjust/image",
|
|
1501
|
+
task: "tonal adjustment"
|
|
1502
|
+
},
|
|
1503
|
+
"topaz-creative": {
|
|
1504
|
+
category: "restoration",
|
|
1505
|
+
defaultOptions: {
|
|
1506
|
+
output_format: "png"
|
|
1507
|
+
},
|
|
1508
|
+
description: "Topaz Bloom upscaling, which reimagines detail rather than preserving it.",
|
|
1509
|
+
endpoint: "topaz/upscale/image/creative",
|
|
1510
|
+
inputField: "image_url",
|
|
1511
|
+
inputKind: "image",
|
|
1512
|
+
name: "Topaz Creative Upscale",
|
|
1513
|
+
outputKeys: ["image"],
|
|
1514
|
+
price: { kind: "megapixel", usd: 0.96 / 24 },
|
|
1515
|
+
pricing: "$0.96 per 24 output megapixels",
|
|
1516
|
+
queued: true,
|
|
1517
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/creative",
|
|
1518
|
+
task: "creative image upscaling"
|
|
1519
|
+
},
|
|
1520
|
+
"topaz-denoise": {
|
|
1521
|
+
category: "restoration",
|
|
1522
|
+
defaultOptions: {
|
|
1523
|
+
output_format: "png"
|
|
1524
|
+
},
|
|
1525
|
+
description: "Topaz noise reduction at source resolution.",
|
|
1526
|
+
endpoint: "topaz/denoise/image",
|
|
1527
|
+
inputField: "image_url",
|
|
1528
|
+
inputKind: "image",
|
|
1529
|
+
name: "Topaz Denoise",
|
|
1530
|
+
outputKeys: ["image"],
|
|
1531
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
1532
|
+
pricing: "$0.08 per 24 output megapixels at the default Normal model; $0.16 with Denoise Max",
|
|
1533
|
+
queued: true,
|
|
1534
|
+
sourceUrl: "https://fal.ai/models/topaz/denoise/image",
|
|
1535
|
+
task: "image denoising"
|
|
1536
|
+
},
|
|
1537
|
+
"topaz-generative": {
|
|
1538
|
+
category: "restoration",
|
|
1539
|
+
defaultOptions: {
|
|
1540
|
+
output_format: "png"
|
|
1541
|
+
},
|
|
1542
|
+
description: "Topaz Wonder upscaling, which synthesises plausible detail as it enlarges.",
|
|
1543
|
+
endpoint: "topaz/upscale/image/generative",
|
|
1544
|
+
inputField: "image_url",
|
|
1545
|
+
inputKind: "image",
|
|
1546
|
+
name: "Topaz Generative Upscale",
|
|
1547
|
+
outputKeys: ["image"],
|
|
1548
|
+
price: { kind: "megapixel", usd: 0.24 / 24 },
|
|
1549
|
+
pricing: "$0.24 per 24 output megapixels at the default Wonder 3; $0.48 with Wonder, Wonder 2, Standard MAX, Redefine or Recover 3",
|
|
1550
|
+
queued: true,
|
|
1551
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/generative",
|
|
1552
|
+
task: "generative image upscaling"
|
|
1553
|
+
},
|
|
1554
|
+
"topaz-image": {
|
|
1555
|
+
category: "upscale",
|
|
1556
|
+
defaultOptions: {
|
|
1557
|
+
model: "Standard V2",
|
|
1558
|
+
output_format: "jpeg",
|
|
1559
|
+
upscale_factor: 2
|
|
1560
|
+
},
|
|
1561
|
+
description: "Professional Topaz image enhancement and upscaling.",
|
|
1562
|
+
endpoint: "fal-ai/topaz/upscale/image",
|
|
1563
|
+
inputField: "image_url",
|
|
1564
|
+
inputKind: "image",
|
|
1565
|
+
name: "Topaz Image Upscale",
|
|
1566
|
+
outputKeys: ["image"],
|
|
1567
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
1568
|
+
pricing: "$0.08 for output up to 24MP; $0.16 to 48MP, $0.32 to 96MP, up to $1.36 at 512MP",
|
|
1569
|
+
queued: true,
|
|
1570
|
+
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/image",
|
|
1571
|
+
task: "image enhancement"
|
|
1572
|
+
},
|
|
1573
|
+
"topaz-precision": {
|
|
1574
|
+
category: "restoration",
|
|
1575
|
+
defaultOptions: {
|
|
1576
|
+
output_format: "png"
|
|
1577
|
+
},
|
|
1578
|
+
description: "Topaz upscaling that preserves the original detail rather than inventing it.",
|
|
1579
|
+
endpoint: "topaz/upscale/image/precision",
|
|
1580
|
+
inputField: "image_url",
|
|
1581
|
+
inputKind: "image",
|
|
1582
|
+
name: "Topaz Precision Upscale",
|
|
1583
|
+
outputKeys: ["image"],
|
|
1584
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
1585
|
+
pricing: "$0.08 per 24 output megapixels, any precision model",
|
|
1586
|
+
queued: true,
|
|
1587
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/precision",
|
|
1588
|
+
task: "faithful image upscaling"
|
|
1589
|
+
},
|
|
1590
|
+
"topaz-restore": {
|
|
1591
|
+
category: "restoration",
|
|
1592
|
+
defaultOptions: {
|
|
1593
|
+
output_format: "png"
|
|
1594
|
+
},
|
|
1595
|
+
description: "Topaz restoration of damaged or degraded photographs at source resolution.",
|
|
1596
|
+
endpoint: "topaz/restore/image",
|
|
1597
|
+
inputField: "image_url",
|
|
1598
|
+
inputKind: "image",
|
|
1599
|
+
name: "Topaz Restore",
|
|
1600
|
+
outputKeys: ["image"],
|
|
1601
|
+
price: { kind: "megapixel", usd: 0.48 / 24 },
|
|
1602
|
+
pricing: "$0.48 per 24 output megapixels at the default Recover 3; $0.08 with Dust-Scratch V2",
|
|
1603
|
+
queued: true,
|
|
1604
|
+
sourceUrl: "https://fal.ai/models/topaz/restore/image",
|
|
1605
|
+
task: "photo restoration"
|
|
1606
|
+
},
|
|
1607
|
+
"topaz-sharpen": {
|
|
1608
|
+
category: "restoration",
|
|
1609
|
+
defaultOptions: {
|
|
1610
|
+
output_format: "png"
|
|
1611
|
+
},
|
|
1612
|
+
description: "Topaz deblurring and sharpening at source resolution.",
|
|
1613
|
+
endpoint: "topaz/sharpen/image",
|
|
1614
|
+
inputField: "image_url",
|
|
1615
|
+
inputKind: "image",
|
|
1616
|
+
name: "Topaz Sharpen",
|
|
1617
|
+
outputKeys: ["image"],
|
|
1618
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
1619
|
+
pricing: "$0.08 per 24 output megapixels at the default Standard model; $0.16 with Super Focus",
|
|
1620
|
+
queued: true,
|
|
1621
|
+
sourceUrl: "https://fal.ai/models/topaz/sharpen/image",
|
|
1622
|
+
task: "image sharpening"
|
|
1623
|
+
},
|
|
1624
|
+
"topaz-transparent": {
|
|
1625
|
+
category: "restoration",
|
|
1626
|
+
description: "Topaz upscaling that preserves the alpha channel end to end.",
|
|
1627
|
+
endpoint: "topaz/upscale/image/transparent",
|
|
1628
|
+
inputField: "image_url",
|
|
1629
|
+
inputKind: "image",
|
|
1630
|
+
name: "Topaz Transparent Upscale",
|
|
1631
|
+
outputKeys: ["image"],
|
|
1632
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
1633
|
+
pricing: "$0.08 per 24 output megapixels",
|
|
1634
|
+
queued: true,
|
|
1635
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/transparent",
|
|
1636
|
+
task: "transparent image upscaling"
|
|
1637
|
+
},
|
|
1638
|
+
"topaz-video": {
|
|
1639
|
+
category: "upscale",
|
|
1640
|
+
defaultOptions: {
|
|
1641
|
+
model: "Proteus",
|
|
1642
|
+
upscale_factor: 2
|
|
1643
|
+
},
|
|
1644
|
+
description: "Professional Topaz video enhancement and upscaling.",
|
|
1645
|
+
endpoint: "fal-ai/topaz/upscale/video",
|
|
1646
|
+
inputField: "video_url",
|
|
1647
|
+
inputKind: "video",
|
|
1648
|
+
name: "Topaz Video Upscale",
|
|
1649
|
+
outputKeys: ["video"],
|
|
1650
|
+
price: { kind: "second", usd: 0.01 },
|
|
1651
|
+
pricing: "$0.01/sec up to 720p; $0.02 to 1080p, $0.08 above, doubled at 60fps, halved with Gaia 2",
|
|
1652
|
+
queued: true,
|
|
1653
|
+
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/video",
|
|
1654
|
+
task: "video enhancement"
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1657
|
+
|
|
1658
|
+
// src/tool-registry/editing.ts
|
|
1659
|
+
var EDITING_TOOLS = {
|
|
1660
|
+
"bria-eraser": {
|
|
1661
|
+
category: "erase",
|
|
1662
|
+
description: "Commercial-safe removal of a masked region, inpainted from surrounding context.",
|
|
1663
|
+
endpoint: "fal-ai/bria/eraser",
|
|
1664
|
+
inputField: "image_url",
|
|
1665
|
+
inputKind: "image",
|
|
1666
|
+
name: "Bria Eraser",
|
|
1667
|
+
outputKeys: ["image"],
|
|
1668
|
+
price: { kind: "call", usd: 0.04 },
|
|
1669
|
+
pricing: "$0.04/generation",
|
|
1670
|
+
sourceUrl: "https://fal.ai/models/fal-ai/bria/eraser",
|
|
1671
|
+
task: "masked object erasure"
|
|
1672
|
+
},
|
|
1673
|
+
"bria-expand": {
|
|
1674
|
+
category: "reframe",
|
|
1675
|
+
description: "Expand an image onto a larger canvas, generating the new border area.",
|
|
1676
|
+
endpoint: "fal-ai/bria/expand",
|
|
1677
|
+
inputField: "image_url",
|
|
1678
|
+
inputKind: "image",
|
|
1679
|
+
name: "Bria Image Expansion",
|
|
1680
|
+
outputKeys: ["image"],
|
|
1681
|
+
price: { kind: "call", usd: 0.04 },
|
|
1682
|
+
pricing: "$0.04/generation",
|
|
1683
|
+
sourceUrl: "https://fal.ai/models/fal-ai/bria/expand",
|
|
1684
|
+
task: "image outpainting"
|
|
1685
|
+
},
|
|
1686
|
+
"bria-genfill": {
|
|
1687
|
+
category: "erase",
|
|
1688
|
+
description: "Generative fill of a masked region from a prompt, commercial-safe.",
|
|
1689
|
+
endpoint: "fal-ai/bria/genfill",
|
|
1690
|
+
inputField: "image_url",
|
|
1691
|
+
inputKind: "image",
|
|
1692
|
+
name: "Bria GenFill",
|
|
1693
|
+
outputKeys: ["images"],
|
|
1694
|
+
price: { kind: "call", usd: 0.04 },
|
|
1695
|
+
pricing: "$0.04/generation",
|
|
1696
|
+
sourceUrl: "https://fal.ai/models/fal-ai/bria/genfill",
|
|
1697
|
+
task: "masked generative fill"
|
|
1698
|
+
},
|
|
1699
|
+
"finegrain-eraser": {
|
|
1700
|
+
category: "erase",
|
|
1701
|
+
description: "Remove a prompted object and its shadows and reflections, filling the gap.",
|
|
1702
|
+
endpoint: "fal-ai/finegrain-eraser",
|
|
1703
|
+
inputField: "image_url",
|
|
1704
|
+
inputKind: "image",
|
|
1705
|
+
name: "Finegrain Object Eraser",
|
|
1706
|
+
outputKeys: ["image"],
|
|
1707
|
+
price: { kind: "call", usd: 0.27 },
|
|
1708
|
+
pricing: "$0.27/image at the default standard mode; $0.18 express, $0.36 premium",
|
|
1709
|
+
sourceUrl: "https://fal.ai/models/fal-ai/finegrain-eraser",
|
|
1710
|
+
task: "prompted object erasure"
|
|
1711
|
+
},
|
|
1712
|
+
"flux-outpaint": {
|
|
1713
|
+
category: "reframe",
|
|
1714
|
+
description: "Outpaint an image by a per-edge pixel expansion with FLUX.2 pro.",
|
|
1715
|
+
endpoint: "fal-ai/flux-2-pro/outpaint",
|
|
1716
|
+
inputField: "image_url",
|
|
1717
|
+
inputKind: "image",
|
|
1718
|
+
name: "FLUX.2 Pro Outpaint",
|
|
1719
|
+
outputKeys: ["images"],
|
|
1720
|
+
price: { kind: "metered" },
|
|
1721
|
+
pricing: "$0.03 for the first output megapixel, then $0.015 per extra megapixel of input and output, rounded up",
|
|
1722
|
+
sourceUrl: "https://fal.ai/models/fal-ai/flux-2-pro/outpaint",
|
|
1723
|
+
task: "image outpainting"
|
|
1724
|
+
},
|
|
1725
|
+
"iclight-v2": {
|
|
1726
|
+
category: "relight",
|
|
1727
|
+
description: "Relight a subject from a prompt, harmonising it with a new light direction.",
|
|
1728
|
+
endpoint: "fal-ai/iclight-v2",
|
|
1729
|
+
inputField: "image_url",
|
|
1730
|
+
inputKind: "image",
|
|
1731
|
+
name: "IC-Light v2",
|
|
1732
|
+
outputKeys: ["images"],
|
|
1733
|
+
price: { kind: "megapixel", usd: 0.1 },
|
|
1734
|
+
pricing: "$0.10/megapixel",
|
|
1735
|
+
sourceUrl: "https://fal.ai/models/fal-ai/iclight-v2",
|
|
1736
|
+
task: "prompted relighting"
|
|
1737
|
+
},
|
|
1738
|
+
"ideogram-reframe": {
|
|
1739
|
+
category: "reframe",
|
|
1740
|
+
description: "Reframe an image to a new aspect ratio, generating the fill.",
|
|
1741
|
+
endpoint: "fal-ai/ideogram/v3/reframe",
|
|
1742
|
+
inputField: "image_url",
|
|
1743
|
+
inputKind: "image",
|
|
1744
|
+
name: "Ideogram v3 Reframe",
|
|
1745
|
+
outputKeys: ["images"],
|
|
1746
|
+
price: { kind: "call", usd: 0.06 },
|
|
1747
|
+
pricing: "$0.06/image at the default BALANCED speed; $0.03 turbo, $0.09 quality",
|
|
1748
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ideogram/v3/reframe",
|
|
1749
|
+
task: "aspect ratio reframing"
|
|
1750
|
+
},
|
|
1751
|
+
"lighting-restoration": {
|
|
1752
|
+
category: "relight",
|
|
1753
|
+
description: "Restore natural, even lighting across one or more input images.",
|
|
1754
|
+
endpoint: "fal-ai/qwen-image-edit-plus-lora-gallery/lighting-restoration",
|
|
1755
|
+
inputField: "image_urls",
|
|
1756
|
+
inputKind: "images",
|
|
1757
|
+
name: "Qwen Lighting Restoration",
|
|
1758
|
+
outputKeys: ["images"],
|
|
1759
|
+
price: { kind: "megapixel", usd: 0.035 },
|
|
1760
|
+
pricing: "$0.035/megapixel",
|
|
1761
|
+
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-edit-plus-lora-gallery/lighting-restoration",
|
|
1762
|
+
task: "lighting restoration"
|
|
1763
|
+
},
|
|
1764
|
+
"object-removal": {
|
|
1765
|
+
category: "erase",
|
|
1766
|
+
description: "Remove a prompted object from an image and fill the gap.",
|
|
1767
|
+
endpoint: "fal-ai/object-removal",
|
|
1768
|
+
inputField: "image_url",
|
|
1769
|
+
inputKind: "image",
|
|
1770
|
+
name: "Object Removal",
|
|
1771
|
+
outputKeys: ["images"],
|
|
1772
|
+
price: { kind: "call", usd: 0.024 },
|
|
1773
|
+
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
1774
|
+
sourceUrl: "https://fal.ai/models/fal-ai/object-removal",
|
|
1775
|
+
task: "prompted object removal"
|
|
1776
|
+
},
|
|
1777
|
+
"object-removal-bbox": {
|
|
1778
|
+
category: "erase",
|
|
1779
|
+
description: "Remove whatever falls inside supplied bounding boxes.",
|
|
1780
|
+
endpoint: "fal-ai/object-removal/bbox",
|
|
1781
|
+
inputField: "image_url",
|
|
1782
|
+
inputKind: "image",
|
|
1783
|
+
name: "Object Removal by Box",
|
|
1784
|
+
outputKeys: ["images"],
|
|
1785
|
+
price: { kind: "call", usd: 0.024 },
|
|
1786
|
+
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
1787
|
+
sourceUrl: "https://fal.ai/models/fal-ai/object-removal/bbox",
|
|
1788
|
+
task: "bounding box object removal"
|
|
1789
|
+
},
|
|
1790
|
+
"object-removal-mask": {
|
|
1791
|
+
category: "erase",
|
|
1792
|
+
description: "Remove the masked region of an image and fill the gap.",
|
|
1793
|
+
endpoint: "fal-ai/object-removal/mask",
|
|
1794
|
+
inputField: "image_url",
|
|
1795
|
+
inputKind: "image",
|
|
1796
|
+
name: "Object Removal by Mask",
|
|
1797
|
+
outputKeys: ["images"],
|
|
1798
|
+
price: { kind: "call", usd: 0.024 },
|
|
1799
|
+
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
1800
|
+
sourceUrl: "https://fal.ai/models/fal-ai/object-removal/mask",
|
|
1801
|
+
task: "masked object removal"
|
|
1802
|
+
},
|
|
1803
|
+
"remove-lighting": {
|
|
1804
|
+
category: "relight",
|
|
1805
|
+
description: "Strip baked-in lighting and shadows to leave a flat, neutral surface.",
|
|
1806
|
+
endpoint: "fal-ai/qwen-image-edit-plus-lora-gallery/remove-lighting",
|
|
1807
|
+
inputField: "image_urls",
|
|
1808
|
+
inputKind: "images",
|
|
1809
|
+
name: "Qwen Remove Lighting",
|
|
1810
|
+
outputKeys: ["images"],
|
|
1811
|
+
price: { kind: "megapixel", usd: 0.035 },
|
|
1812
|
+
pricing: "$0.035/megapixel",
|
|
1813
|
+
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-edit-plus-lora-gallery/remove-lighting",
|
|
1814
|
+
task: "lighting removal"
|
|
1815
|
+
},
|
|
1816
|
+
"smart-resize": {
|
|
1817
|
+
category: "reframe",
|
|
1818
|
+
description: "Resize one image to several target sizes, recomposing rather than cropping.",
|
|
1819
|
+
endpoint: "fal-ai/smart-resize",
|
|
1820
|
+
inputField: "image_url",
|
|
1821
|
+
inputKind: "image",
|
|
1822
|
+
name: "Smart Resize",
|
|
1823
|
+
outputKeys: ["images", "results"],
|
|
1824
|
+
price: { kind: "metered" },
|
|
1825
|
+
pricing: "$0.15 per output image, doubled at 4K, plus a $0.05 vision analysis fee per request",
|
|
1826
|
+
queued: true,
|
|
1827
|
+
sourceUrl: "https://fal.ai/models/fal-ai/smart-resize",
|
|
1828
|
+
task: "multi-size recomposition"
|
|
1829
|
+
},
|
|
1830
|
+
"text-removal": {
|
|
1831
|
+
category: "erase",
|
|
1832
|
+
defaultOptions: {
|
|
1833
|
+
output_format: "png"
|
|
1834
|
+
},
|
|
1835
|
+
description: "Remove all rendered text from an image, rebuilding what sat behind it.",
|
|
1836
|
+
endpoint: "fal-ai/image-editing/text-removal",
|
|
1837
|
+
inputField: "image_url",
|
|
1838
|
+
inputKind: "image",
|
|
1839
|
+
name: "Text Removal",
|
|
1840
|
+
outputKeys: ["images"],
|
|
1841
|
+
price: { kind: "call", usd: 0.04 },
|
|
1842
|
+
pricing: "$0.04/image",
|
|
1843
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-editing/text-removal",
|
|
1844
|
+
task: "text removal"
|
|
1845
|
+
}
|
|
1846
|
+
};
|
|
1847
|
+
|
|
1848
|
+
// src/tool-registry/structure.ts
|
|
1849
|
+
var STRUCTURE_TOOLS = {
|
|
1850
|
+
"depth-anything": {
|
|
1851
|
+
category: "preprocess",
|
|
1852
|
+
description: "Generate Depth Anything v2 depth maps from input images.",
|
|
1853
|
+
endpoint: "fal-ai/image-preprocessors/depth-anything/v2",
|
|
1854
|
+
inputField: "image_url",
|
|
1855
|
+
inputKind: "image",
|
|
1856
|
+
name: "Depth Anything v2 Preprocessor",
|
|
1857
|
+
outputKeys: ["image"],
|
|
1858
|
+
price: { kind: "metered" },
|
|
1859
|
+
pricing: "$0/compute-second listed by fal",
|
|
1860
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/depth-anything/v2",
|
|
1861
|
+
task: "depth preprocessing"
|
|
1862
|
+
},
|
|
1863
|
+
dwpose: {
|
|
1864
|
+
category: "preprocess",
|
|
1865
|
+
description: "Extract body, hand, and face pose skeletons from an image.",
|
|
1866
|
+
endpoint: "fal-ai/dwpose",
|
|
1867
|
+
inputField: "image_url",
|
|
1868
|
+
inputKind: "image",
|
|
1869
|
+
name: "DWPose Estimation",
|
|
1870
|
+
outputKeys: ["image"],
|
|
1871
|
+
price: { kind: "second", usd: 6e-4 },
|
|
1872
|
+
pricing: "$0.0006/compute-second",
|
|
1873
|
+
sourceUrl: "https://fal.ai/models/fal-ai/dwpose",
|
|
1874
|
+
task: "pose preprocessing"
|
|
1875
|
+
},
|
|
1876
|
+
hed: {
|
|
1877
|
+
category: "preprocess",
|
|
1878
|
+
description: "Generate HED soft edge maps for ControlNet-style workflows.",
|
|
1879
|
+
endpoint: "fal-ai/image-preprocessors/hed",
|
|
1880
|
+
inputField: "image_url",
|
|
1881
|
+
inputKind: "image",
|
|
1882
|
+
name: "HED Edge Preprocessor",
|
|
1883
|
+
outputKeys: ["image"],
|
|
1884
|
+
price: { kind: "metered" },
|
|
1885
|
+
pricing: "$0/compute-second listed by fal",
|
|
1886
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/hed",
|
|
1887
|
+
task: "edge preprocessing"
|
|
1888
|
+
},
|
|
1889
|
+
lineart: {
|
|
1890
|
+
category: "preprocess",
|
|
1891
|
+
defaultOptions: {
|
|
1892
|
+
coarse: false
|
|
1893
|
+
},
|
|
1894
|
+
description: "Generate line art/control-style edges from an input image.",
|
|
1895
|
+
endpoint: "fal-ai/image-preprocessors/lineart",
|
|
1896
|
+
inputField: "image_url",
|
|
1897
|
+
inputKind: "image",
|
|
1898
|
+
name: "Line Art Preprocessor",
|
|
1899
|
+
outputKeys: ["image"],
|
|
1900
|
+
price: { kind: "metered" },
|
|
1901
|
+
pricing: "$0/compute-second listed by fal",
|
|
1902
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/lineart",
|
|
972
1903
|
task: "image preprocessing"
|
|
973
1904
|
},
|
|
974
1905
|
"marigold-depth": {
|
|
@@ -983,6 +1914,7 @@ var FAL_TOOLS = {
|
|
|
983
1914
|
inputKind: "image",
|
|
984
1915
|
name: "Marigold Depth Estimation",
|
|
985
1916
|
outputKeys: ["image"],
|
|
1917
|
+
price: { kind: "metered" },
|
|
986
1918
|
pricing: "$0/compute-second listed by fal",
|
|
987
1919
|
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/marigold-depth",
|
|
988
1920
|
task: "depth map"
|
|
@@ -999,6 +1931,7 @@ var FAL_TOOLS = {
|
|
|
999
1931
|
inputKind: "image",
|
|
1000
1932
|
name: "MiDaS Depth Estimation",
|
|
1001
1933
|
outputKeys: ["image"],
|
|
1934
|
+
price: { kind: "metered" },
|
|
1002
1935
|
pricing: "$0/compute-second listed by fal",
|
|
1003
1936
|
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/depth",
|
|
1004
1937
|
task: "depth map"
|
|
@@ -1011,36 +1944,36 @@ var FAL_TOOLS = {
|
|
|
1011
1944
|
inputKind: "image",
|
|
1012
1945
|
name: "MiDaS Preprocessor",
|
|
1013
1946
|
outputKeys: ["depth_map", "normal_map"],
|
|
1947
|
+
price: { kind: "metered" },
|
|
1014
1948
|
pricing: "$0/compute-second listed by fal",
|
|
1015
1949
|
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/midas",
|
|
1016
1950
|
task: "depth and normal preprocessing"
|
|
1017
1951
|
},
|
|
1018
|
-
|
|
1019
|
-
category: "
|
|
1020
|
-
description: "
|
|
1021
|
-
endpoint: "fal-ai/
|
|
1022
|
-
inputField: "
|
|
1023
|
-
inputKind: "
|
|
1024
|
-
name: "
|
|
1025
|
-
outputKeys: ["
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1952
|
+
mlsd: {
|
|
1953
|
+
category: "preprocess",
|
|
1954
|
+
description: "Detect straight line segments for architectural and interior control maps.",
|
|
1955
|
+
endpoint: "fal-ai/image-preprocessors/mlsd",
|
|
1956
|
+
inputField: "image_url",
|
|
1957
|
+
inputKind: "image",
|
|
1958
|
+
name: "M-LSD Line Preprocessor",
|
|
1959
|
+
outputKeys: ["image"],
|
|
1960
|
+
price: { kind: "metered" },
|
|
1961
|
+
pricing: "$0/compute-second listed by fal",
|
|
1962
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/mlsd",
|
|
1963
|
+
task: "line segment preprocessing"
|
|
1029
1964
|
},
|
|
1030
|
-
|
|
1031
|
-
category: "
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
},
|
|
1035
|
-
description: "Generic image background removal utility.",
|
|
1036
|
-
endpoint: "fal-ai/imageutils/rembg",
|
|
1965
|
+
pidi: {
|
|
1966
|
+
category: "preprocess",
|
|
1967
|
+
description: "Generate PiDiNet soft edge maps from an input image.",
|
|
1968
|
+
endpoint: "fal-ai/image-preprocessors/pidi",
|
|
1037
1969
|
inputField: "image_url",
|
|
1038
1970
|
inputKind: "image",
|
|
1039
|
-
name: "
|
|
1971
|
+
name: "PiDiNet Edge Preprocessor",
|
|
1040
1972
|
outputKeys: ["image"],
|
|
1973
|
+
price: { kind: "metered" },
|
|
1041
1974
|
pricing: "$0/compute-second listed by fal",
|
|
1042
|
-
sourceUrl: "https://fal.ai/models/fal-ai/
|
|
1043
|
-
task: "
|
|
1975
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/pidi",
|
|
1976
|
+
task: "edge preprocessing"
|
|
1044
1977
|
},
|
|
1045
1978
|
"sam-preprocessor": {
|
|
1046
1979
|
category: "preprocess",
|
|
@@ -1050,6 +1983,7 @@ var FAL_TOOLS = {
|
|
|
1050
1983
|
inputKind: "image",
|
|
1051
1984
|
name: "SAM Preprocessor",
|
|
1052
1985
|
outputKeys: ["image"],
|
|
1986
|
+
price: { kind: "metered" },
|
|
1053
1987
|
pricing: "$0/compute-second listed by fal",
|
|
1054
1988
|
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/sam",
|
|
1055
1989
|
task: "segmentation preprocessing"
|
|
@@ -1069,7 +2003,9 @@ var FAL_TOOLS = {
|
|
|
1069
2003
|
inputKind: "image",
|
|
1070
2004
|
name: "SAM 2 Auto Segment",
|
|
1071
2005
|
outputKeys: ["combined_mask", "individual_masks"],
|
|
2006
|
+
price: { kind: "metered" },
|
|
1072
2007
|
pricing: "$0/compute-second listed by fal",
|
|
2008
|
+
queued: true,
|
|
1073
2009
|
sourceUrl: "https://fal.ai/models/fal-ai/sam2/auto-segment",
|
|
1074
2010
|
task: "automatic image segmentation"
|
|
1075
2011
|
},
|
|
@@ -1086,7 +2022,8 @@ var FAL_TOOLS = {
|
|
|
1086
2022
|
inputKind: "image",
|
|
1087
2023
|
name: "SAM 3.1 Image",
|
|
1088
2024
|
outputKeys: ["image", "masks", "metadata", "scores", "boxes"],
|
|
1089
|
-
|
|
2025
|
+
price: { kind: "call", usd: 0.01 },
|
|
2026
|
+
pricing: "$0.01/request",
|
|
1090
2027
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/image",
|
|
1091
2028
|
task: "promptable image segmentation"
|
|
1092
2029
|
},
|
|
@@ -1102,61 +2039,12 @@ var FAL_TOOLS = {
|
|
|
1102
2039
|
inputKind: "video",
|
|
1103
2040
|
name: "SAM 3.1 Video",
|
|
1104
2041
|
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
1105
|
-
|
|
2042
|
+
price: { kind: "metered" },
|
|
2043
|
+
pricing: "$0.01/16 frames of video input",
|
|
2044
|
+
queued: true,
|
|
1106
2045
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/video",
|
|
1107
2046
|
task: "multi-object video segmentation"
|
|
1108
2047
|
},
|
|
1109
|
-
"sam3-3d-align": {
|
|
1110
|
-
category: "3d",
|
|
1111
|
-
description: "Align SAM 3D objects and bodies into a shared scene.",
|
|
1112
|
-
endpoint: "fal-ai/sam-3/3d-align",
|
|
1113
|
-
inputField: "image_url",
|
|
1114
|
-
inputKind: "image",
|
|
1115
|
-
name: "SAM 3D Align",
|
|
1116
|
-
outputKeys: ["scene_glb", "metadata", "artifacts_zip"],
|
|
1117
|
-
pricing: "fal pricing varies by scene",
|
|
1118
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-align",
|
|
1119
|
-
task: "3D scene alignment"
|
|
1120
|
-
},
|
|
1121
|
-
"sam3-3d-body": {
|
|
1122
|
-
category: "3d",
|
|
1123
|
-
defaultOptions: {
|
|
1124
|
-
export_meshes: true,
|
|
1125
|
-
include_3d_keypoints: true,
|
|
1126
|
-
include_mhr_params: true
|
|
1127
|
-
},
|
|
1128
|
-
description: "Reconstruct human body meshes and keypoints from a single image.",
|
|
1129
|
-
endpoint: "fal-ai/sam-3/3d-body",
|
|
1130
|
-
inputField: "image_url",
|
|
1131
|
-
inputKind: "image",
|
|
1132
|
-
name: "SAM 3D Body",
|
|
1133
|
-
outputKeys: ["model_glb", "visualization", "meshes", "metadata"],
|
|
1134
|
-
pricing: "$0.015/inference",
|
|
1135
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-body",
|
|
1136
|
-
task: "single-image 3D body reconstruction"
|
|
1137
|
-
},
|
|
1138
|
-
"sam3-3d-objects": {
|
|
1139
|
-
category: "3d",
|
|
1140
|
-
defaultOptions: {
|
|
1141
|
-
prompt: "car"
|
|
1142
|
-
},
|
|
1143
|
-
description: "Reconstruct one or more 3D objects from an image and prompts.",
|
|
1144
|
-
endpoint: "fal-ai/sam-3/3d-objects",
|
|
1145
|
-
inputField: "image_url",
|
|
1146
|
-
inputKind: "image",
|
|
1147
|
-
name: "SAM 3D Objects",
|
|
1148
|
-
outputKeys: [
|
|
1149
|
-
"gaussian_splat",
|
|
1150
|
-
"model_glb",
|
|
1151
|
-
"metadata",
|
|
1152
|
-
"individual_splats",
|
|
1153
|
-
"individual_glbs",
|
|
1154
|
-
"artifacts_zip"
|
|
1155
|
-
],
|
|
1156
|
-
pricing: "$0.02/generation",
|
|
1157
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-objects",
|
|
1158
|
-
task: "single-image 3D object reconstruction"
|
|
1159
|
-
},
|
|
1160
2048
|
"sam3-image": {
|
|
1161
2049
|
category: "segmentation",
|
|
1162
2050
|
defaultOptions: {
|
|
@@ -1170,6 +2058,7 @@ var FAL_TOOLS = {
|
|
|
1170
2058
|
inputKind: "image",
|
|
1171
2059
|
name: "SAM 3 Image",
|
|
1172
2060
|
outputKeys: ["image", "masks", "metadata", "scores", "boxes"],
|
|
2061
|
+
price: { kind: "call", usd: 5e-3 },
|
|
1173
2062
|
pricing: "$0.005/request",
|
|
1174
2063
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image",
|
|
1175
2064
|
task: "promptable image segmentation"
|
|
@@ -1185,7 +2074,8 @@ var FAL_TOOLS = {
|
|
|
1185
2074
|
inputField: "image_url",
|
|
1186
2075
|
inputKind: "image",
|
|
1187
2076
|
name: "SAM 3 Image RLE",
|
|
1188
|
-
outputKeys: ["
|
|
2077
|
+
outputKeys: ["rle", "scores", "boxes", "metadata"],
|
|
2078
|
+
price: { kind: "call", usd: 5e-3 },
|
|
1189
2079
|
pricing: "$0.005/request",
|
|
1190
2080
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image-rle",
|
|
1191
2081
|
task: "promptable image segmentation to RLE"
|
|
@@ -1204,7 +2094,9 @@ var FAL_TOOLS = {
|
|
|
1204
2094
|
inputKind: "video",
|
|
1205
2095
|
name: "SAM 3 Video",
|
|
1206
2096
|
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
1207
|
-
|
|
2097
|
+
price: { kind: "metered" },
|
|
2098
|
+
pricing: "$0.005/16 frames of video input",
|
|
2099
|
+
queued: true,
|
|
1208
2100
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video",
|
|
1209
2101
|
task: "promptable video segmentation"
|
|
1210
2102
|
},
|
|
@@ -1220,65 +2112,68 @@ var FAL_TOOLS = {
|
|
|
1220
2112
|
inputField: "video_url",
|
|
1221
2113
|
inputKind: "video",
|
|
1222
2114
|
name: "SAM 3 Video RLE",
|
|
1223
|
-
|
|
1224
|
-
|
|
2115
|
+
// fal's video-rle endpoint no longer returns RLE data: its Output schema is
|
|
2116
|
+
// now identical to sam3-video's, so this entry differs only by endpoint.
|
|
2117
|
+
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2118
|
+
price: { kind: "metered" },
|
|
2119
|
+
pricing: "$0.005/16 frames of video",
|
|
2120
|
+
queued: true,
|
|
1225
2121
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video-rle",
|
|
1226
2122
|
task: "promptable video segmentation to RLE"
|
|
1227
2123
|
},
|
|
1228
|
-
|
|
1229
|
-
category: "
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
output_format: "jpeg",
|
|
1233
|
-
upscale_factor: 2
|
|
1234
|
-
},
|
|
1235
|
-
description: "Professional Topaz image enhancement and upscaling.",
|
|
1236
|
-
endpoint: "fal-ai/topaz/upscale/image",
|
|
2124
|
+
scribble: {
|
|
2125
|
+
category: "preprocess",
|
|
2126
|
+
description: "Turn an image into a scribble-style control map.",
|
|
2127
|
+
endpoint: "fal-ai/image-preprocessors/scribble",
|
|
1237
2128
|
inputField: "image_url",
|
|
1238
2129
|
inputKind: "image",
|
|
1239
|
-
name: "
|
|
2130
|
+
name: "Scribble Preprocessor",
|
|
1240
2131
|
outputKeys: ["image"],
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
2132
|
+
price: { kind: "metered" },
|
|
2133
|
+
pricing: "$0/compute-second listed by fal",
|
|
2134
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/scribble",
|
|
2135
|
+
task: "scribble preprocessing"
|
|
1244
2136
|
},
|
|
1245
|
-
|
|
1246
|
-
category: "
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
2137
|
+
teed: {
|
|
2138
|
+
category: "preprocess",
|
|
2139
|
+
description: "Generate TEED edge maps from an input image.",
|
|
2140
|
+
endpoint: "fal-ai/image-preprocessors/teed",
|
|
2141
|
+
inputField: "image_url",
|
|
2142
|
+
inputKind: "image",
|
|
2143
|
+
name: "TEED Edge Preprocessor",
|
|
2144
|
+
outputKeys: ["image"],
|
|
2145
|
+
price: { kind: "metered" },
|
|
2146
|
+
pricing: "$0/compute-second listed by fal",
|
|
2147
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/teed",
|
|
2148
|
+
task: "edge preprocessing"
|
|
2149
|
+
},
|
|
2150
|
+
"zoe-depth": {
|
|
2151
|
+
category: "preprocess",
|
|
2152
|
+
description: "Generate ZoeDepth metric depth maps from an input image.",
|
|
2153
|
+
endpoint: "fal-ai/image-preprocessors/zoe",
|
|
2154
|
+
inputField: "image_url",
|
|
2155
|
+
inputKind: "image",
|
|
2156
|
+
name: "ZoeDepth Preprocessor",
|
|
2157
|
+
outputKeys: ["image"],
|
|
2158
|
+
price: { kind: "metered" },
|
|
2159
|
+
pricing: "$0/compute-second listed by fal",
|
|
2160
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/zoe",
|
|
2161
|
+
task: "depth preprocessing"
|
|
1260
2162
|
}
|
|
1261
2163
|
};
|
|
2164
|
+
|
|
2165
|
+
// src/tools.ts
|
|
2166
|
+
var FAL_TOOLS = {
|
|
2167
|
+
...ANALYSIS_TOOLS,
|
|
2168
|
+
...ASSET_TOOLS,
|
|
2169
|
+
...BACKGROUND_TOOLS,
|
|
2170
|
+
...EDITING_TOOLS,
|
|
2171
|
+
...STRUCTURE_TOOLS
|
|
2172
|
+
};
|
|
1262
2173
|
var FAL_TOOL_IDS = Object.keys(
|
|
1263
2174
|
FAL_TOOLS
|
|
1264
2175
|
);
|
|
1265
2176
|
|
|
1266
|
-
// src/server.ts
|
|
1267
|
-
var MotifError = class extends Error {
|
|
1268
|
-
status;
|
|
1269
|
-
code;
|
|
1270
|
-
/** fal's request-correlation id (from the `x-fal-request-id` header or the
|
|
1271
|
-
* error body). Ties a failure back to fal's dashboard/support. */
|
|
1272
|
-
requestId;
|
|
1273
|
-
constructor(message, status, code, requestId) {
|
|
1274
|
-
super(message);
|
|
1275
|
-
this.name = "MotifError";
|
|
1276
|
-
this.status = status;
|
|
1277
|
-
this.code = code;
|
|
1278
|
-
this.requestId = requestId;
|
|
1279
|
-
}
|
|
1280
|
-
};
|
|
1281
|
-
|
|
1282
2177
|
// src/image/fal.ts
|
|
1283
2178
|
import { createFal } from "@ai-sdk/fal";
|
|
1284
2179
|
var FAL_FLUX_MODEL = "fal-ai/flux-pro/v1.1-ultra";
|
|
@@ -1558,9 +2453,9 @@ function createMotifImage(config = {}, deps = {}) {
|
|
|
1558
2453
|
...opts.headers === void 0 ? {} : { headers: opts.headers },
|
|
1559
2454
|
...opts.providerOptions === void 0 ? {} : { providerOptions: toProviderOptions(opts.providerOptions) }
|
|
1560
2455
|
});
|
|
1561
|
-
return
|
|
2456
|
+
return ok3(toMotifImageResult(result, provider, modelId));
|
|
1562
2457
|
} catch (error) {
|
|
1563
|
-
return
|
|
2458
|
+
return err3(toMotifError2(error));
|
|
1564
2459
|
}
|
|
1565
2460
|
}
|
|
1566
2461
|
async function edit(opts) {
|
|
@@ -1581,9 +2476,9 @@ function createMotifImage(config = {}, deps = {}) {
|
|
|
1581
2476
|
...opts.headers === void 0 ? {} : { headers: opts.headers },
|
|
1582
2477
|
...opts.providerOptions === void 0 ? {} : { providerOptions: toProviderOptions(opts.providerOptions) }
|
|
1583
2478
|
});
|
|
1584
|
-
return
|
|
2479
|
+
return ok3(toMotifImageResult(result, provider, modelId));
|
|
1585
2480
|
} catch (error) {
|
|
1586
|
-
return
|
|
2481
|
+
return err3(toMotifError2(error));
|
|
1587
2482
|
}
|
|
1588
2483
|
}
|
|
1589
2484
|
async function bestOfN(opts) {
|
|
@@ -1605,19 +2500,19 @@ async function runCandidate(opts, index, generate, edit) {
|
|
|
1605
2500
|
async function selectWinner(opts, candidates) {
|
|
1606
2501
|
const { judge } = opts;
|
|
1607
2502
|
if (judge === void 0) {
|
|
1608
|
-
return
|
|
2503
|
+
return ok3({ chosenIndex: 0 });
|
|
1609
2504
|
}
|
|
1610
2505
|
const context = "images" in opts ? { instruction: opts.instruction } : { prompt: opts.prompt };
|
|
1611
2506
|
const decision = await judge(candidates, context);
|
|
1612
2507
|
if (!Number.isInteger(decision.index) || decision.index < 0 || decision.index >= candidates.length) {
|
|
1613
|
-
return
|
|
2508
|
+
return err3(
|
|
1614
2509
|
new MotifError(
|
|
1615
2510
|
`bestOfN judge returned an out-of-range index ${decision.index} (expected 0..${candidates.length - 1})`,
|
|
1616
2511
|
0
|
|
1617
2512
|
)
|
|
1618
2513
|
);
|
|
1619
2514
|
}
|
|
1620
|
-
return
|
|
2515
|
+
return ok3({
|
|
1621
2516
|
chosenIndex: decision.index,
|
|
1622
2517
|
...decision.reason === void 0 ? {} : { reason: decision.reason }
|
|
1623
2518
|
});
|
|
@@ -1626,7 +2521,7 @@ async function runBestOfN(opts, generate, edit) {
|
|
|
1626
2521
|
try {
|
|
1627
2522
|
const { n } = opts;
|
|
1628
2523
|
if (!Number.isInteger(n) || n < 1) {
|
|
1629
|
-
return
|
|
2524
|
+
return err3(
|
|
1630
2525
|
new MotifError(`bestOfN requires an integer n >= 1 (got ${n})`, 0)
|
|
1631
2526
|
);
|
|
1632
2527
|
}
|
|
@@ -1645,23 +2540,23 @@ async function runBestOfN(opts, generate, edit) {
|
|
|
1645
2540
|
}
|
|
1646
2541
|
}
|
|
1647
2542
|
if (candidates.length === 0) {
|
|
1648
|
-
return
|
|
2543
|
+
return err3(
|
|
1649
2544
|
firstError ?? new MotifError(`all ${n} bestOfN candidates failed`, 0)
|
|
1650
2545
|
);
|
|
1651
2546
|
}
|
|
1652
2547
|
const winner = await selectWinner(opts, candidates);
|
|
1653
2548
|
if (winner.isErr()) {
|
|
1654
|
-
return
|
|
2549
|
+
return err3(winner.error);
|
|
1655
2550
|
}
|
|
1656
2551
|
const { chosenIndex, reason } = winner.value;
|
|
1657
2552
|
const best = candidates[chosenIndex];
|
|
1658
2553
|
if (best === void 0) {
|
|
1659
|
-
return
|
|
2554
|
+
return err3(new MotifError("bestOfN failed to resolve a winner", 0));
|
|
1660
2555
|
}
|
|
1661
2556
|
const totalCostUsd = Number(
|
|
1662
2557
|
candidates.reduce((sum, candidate) => sum + candidate.cost.usd, 0).toFixed(6)
|
|
1663
2558
|
);
|
|
1664
|
-
return
|
|
2559
|
+
return ok3({
|
|
1665
2560
|
best,
|
|
1666
2561
|
chosenIndex,
|
|
1667
2562
|
...reason === void 0 ? {} : { reason },
|
|
@@ -1669,7 +2564,7 @@ async function runBestOfN(opts, generate, edit) {
|
|
|
1669
2564
|
totalCostUsd
|
|
1670
2565
|
});
|
|
1671
2566
|
} catch (error) {
|
|
1672
|
-
return
|
|
2567
|
+
return err3(toMotifError2(error));
|
|
1673
2568
|
}
|
|
1674
2569
|
}
|
|
1675
2570
|
function defaultResolveModel(provider, modelId, apiKey) {
|
|
@@ -1785,7 +2680,7 @@ function toJsonValue(value, path) {
|
|
|
1785
2680
|
0
|
|
1786
2681
|
);
|
|
1787
2682
|
}
|
|
1788
|
-
function
|
|
2683
|
+
function toMotifError2(error) {
|
|
1789
2684
|
if (error instanceof MotifError) {
|
|
1790
2685
|
return error;
|
|
1791
2686
|
}
|