@howells/motif-sdk 1.1.0 → 1.3.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 +1071 -199
- package/dist/index.cjs +2054 -417
- package/dist/index.d.cts +2461 -402
- package/dist/index.d.ts +2461 -402
- package/dist/index.js +2043 -416
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { err as
|
|
2
|
+
import { err as err3, ok as ok3 } from "neverthrow";
|
|
3
3
|
|
|
4
4
|
// src/aspects.ts
|
|
5
5
|
var ASPECT_RATIOS = [
|
|
@@ -99,22 +99,23 @@ var FORMAT_PRESETS = {
|
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
// src/models.ts
|
|
102
|
-
var AA_IMAGE_LEADERBOARD_SNAPSHOT = "2026-
|
|
102
|
+
var AA_IMAGE_LEADERBOARD_SNAPSHOT = "2026-08-23";
|
|
103
103
|
var AA_IMAGE_SOURCES = [
|
|
104
104
|
"https://artificialanalysis.ai/image/leaderboard/text-to-image",
|
|
105
105
|
"https://artificialanalysis.ai/image/leaderboard/editing"
|
|
106
106
|
];
|
|
107
107
|
var FAL_PRICING_CHECKED_AT = "2026-05-12";
|
|
108
108
|
var FAL_PRICING_CHECKED_JUL_2026 = "2026-07-11";
|
|
109
|
+
var FAL_PRICING_CHECKED_AUG_2026 = "2026-08-23";
|
|
109
110
|
var MODELS = {
|
|
110
111
|
// ─── Generation Models ────────────────────────────────────────
|
|
111
112
|
gpt2: {
|
|
112
113
|
benchmark: {
|
|
113
114
|
artificialAnalysis: {
|
|
114
|
-
editing: { elo:
|
|
115
|
+
editing: { elo: 1256, rank: 3 },
|
|
115
116
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
116
117
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
117
|
-
textToImage: { elo:
|
|
118
|
+
textToImage: { elo: 1369, rank: 1 }
|
|
118
119
|
},
|
|
119
120
|
speed: {
|
|
120
121
|
medianSeconds: 200.7,
|
|
@@ -154,10 +155,10 @@ var MODELS = {
|
|
|
154
155
|
gpt: {
|
|
155
156
|
benchmark: {
|
|
156
157
|
artificialAnalysis: {
|
|
157
|
-
editing: { elo:
|
|
158
|
+
editing: { elo: 1250, rank: 5 },
|
|
158
159
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
159
160
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
160
|
-
textToImage: { elo:
|
|
161
|
+
textToImage: { elo: 1310, rank: 4 }
|
|
161
162
|
},
|
|
162
163
|
speed: {
|
|
163
164
|
medianSeconds: 34.6,
|
|
@@ -197,10 +198,10 @@ var MODELS = {
|
|
|
197
198
|
banana2: {
|
|
198
199
|
benchmark: {
|
|
199
200
|
artificialAnalysis: {
|
|
200
|
-
editing: { elo:
|
|
201
|
+
editing: { elo: 1249, rank: 7 },
|
|
201
202
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
202
203
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
203
|
-
textToImage: { elo:
|
|
204
|
+
textToImage: { elo: 1320, rank: 3 }
|
|
204
205
|
},
|
|
205
206
|
tiers: { price: "premium", quality: "frontier", speed: "unknown" },
|
|
206
207
|
useCase: "Best balance of quality, edit support, web search, and cost"
|
|
@@ -238,10 +239,10 @@ var MODELS = {
|
|
|
238
239
|
banana: {
|
|
239
240
|
benchmark: {
|
|
240
241
|
artificialAnalysis: {
|
|
241
|
-
editing: { elo:
|
|
242
|
+
editing: { elo: 1245, rank: 9 },
|
|
242
243
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
243
244
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
244
|
-
textToImage: { elo:
|
|
245
|
+
textToImage: { elo: 1297, rank: 6 }
|
|
245
246
|
},
|
|
246
247
|
speed: {
|
|
247
248
|
medianSeconds: 19.2,
|
|
@@ -281,6 +282,13 @@ var MODELS = {
|
|
|
281
282
|
type: "generation"
|
|
282
283
|
},
|
|
283
284
|
gemini: {
|
|
285
|
+
benchmark: {
|
|
286
|
+
artificialAnalysis: {
|
|
287
|
+
editing: { elo: 1180, rank: 29 },
|
|
288
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
289
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
290
|
+
}
|
|
291
|
+
},
|
|
284
292
|
editEndpoint: "fal-ai/gemini-25-flash-image/edit",
|
|
285
293
|
endpoint: "fal-ai/gemini-25-flash-image",
|
|
286
294
|
falPricing: {
|
|
@@ -308,6 +316,14 @@ var MODELS = {
|
|
|
308
316
|
type: "generation"
|
|
309
317
|
},
|
|
310
318
|
gemini3: {
|
|
319
|
+
benchmark: {
|
|
320
|
+
artificialAnalysis: {
|
|
321
|
+
editing: { elo: 1245, rank: 9 },
|
|
322
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
323
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
324
|
+
textToImage: { elo: 1297, rank: 6 }
|
|
325
|
+
}
|
|
326
|
+
},
|
|
311
327
|
editEndpoint: "fal-ai/gemini-3-pro-image-preview/edit",
|
|
312
328
|
endpoint: "fal-ai/gemini-3-pro-image-preview",
|
|
313
329
|
falPricing: {
|
|
@@ -338,10 +354,10 @@ var MODELS = {
|
|
|
338
354
|
seedream4: {
|
|
339
355
|
benchmark: {
|
|
340
356
|
artificialAnalysis: {
|
|
341
|
-
editing: { elo:
|
|
357
|
+
editing: { elo: 1185, rank: 28 },
|
|
342
358
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
343
359
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
344
|
-
textToImage: { elo:
|
|
360
|
+
textToImage: { elo: 1226, rank: 16 }
|
|
345
361
|
},
|
|
346
362
|
speed: {
|
|
347
363
|
medianSeconds: 14.3,
|
|
@@ -378,10 +394,10 @@ var MODELS = {
|
|
|
378
394
|
seedream45: {
|
|
379
395
|
benchmark: {
|
|
380
396
|
artificialAnalysis: {
|
|
381
|
-
editing: { elo:
|
|
397
|
+
editing: { elo: 1186, rank: 26 },
|
|
382
398
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
383
399
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
384
|
-
textToImage: { elo:
|
|
400
|
+
textToImage: { elo: 1203, rank: 32 }
|
|
385
401
|
},
|
|
386
402
|
speed: {
|
|
387
403
|
medianSeconds: 18.2,
|
|
@@ -416,6 +432,14 @@ var MODELS = {
|
|
|
416
432
|
type: "generation"
|
|
417
433
|
},
|
|
418
434
|
seedream5: {
|
|
435
|
+
benchmark: {
|
|
436
|
+
artificialAnalysis: {
|
|
437
|
+
editing: { elo: 1248, rank: 8 },
|
|
438
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
439
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
440
|
+
textToImage: { elo: 1279, rank: 10 }
|
|
441
|
+
}
|
|
442
|
+
},
|
|
419
443
|
name: "Seedream 5.0 Pro",
|
|
420
444
|
endpoint: "bytedance/seedream/v5/pro/text-to-image",
|
|
421
445
|
editEndpoint: "bytedance/seedream/v5/pro/edit",
|
|
@@ -442,6 +466,13 @@ var MODELS = {
|
|
|
442
466
|
maxReferenceImages: 10
|
|
443
467
|
},
|
|
444
468
|
"seedream5-lite": {
|
|
469
|
+
benchmark: {
|
|
470
|
+
artificialAnalysis: {
|
|
471
|
+
editing: { elo: 1169, rank: 32 },
|
|
472
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
473
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
474
|
+
}
|
|
475
|
+
},
|
|
445
476
|
name: "Seedream 5.0 Lite",
|
|
446
477
|
endpoint: "fal-ai/bytedance/seedream/v5/lite/text-to-image",
|
|
447
478
|
editEndpoint: "fal-ai/bytedance/seedream/v5/lite/edit",
|
|
@@ -470,10 +501,10 @@ var MODELS = {
|
|
|
470
501
|
"flux2-max": {
|
|
471
502
|
benchmark: {
|
|
472
503
|
artificialAnalysis: {
|
|
473
|
-
editing: { elo:
|
|
504
|
+
editing: { elo: 1201, rank: 19 },
|
|
474
505
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
475
506
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
476
|
-
textToImage: { elo:
|
|
507
|
+
textToImage: { elo: 1225, rank: 17 }
|
|
477
508
|
},
|
|
478
509
|
speed: {
|
|
479
510
|
medianSeconds: 31.6,
|
|
@@ -513,10 +544,10 @@ var MODELS = {
|
|
|
513
544
|
"flux2-pro": {
|
|
514
545
|
benchmark: {
|
|
515
546
|
artificialAnalysis: {
|
|
516
|
-
editing: { elo: 1170,
|
|
547
|
+
editing: { elo: 1170, rank: 31 },
|
|
517
548
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
518
549
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
519
|
-
textToImage: { elo:
|
|
550
|
+
textToImage: { elo: 1207, rank: 30 }
|
|
520
551
|
},
|
|
521
552
|
speed: {
|
|
522
553
|
medianSeconds: 16.1,
|
|
@@ -556,10 +587,9 @@ var MODELS = {
|
|
|
556
587
|
"flux2-flex": {
|
|
557
588
|
benchmark: {
|
|
558
589
|
artificialAnalysis: {
|
|
559
|
-
editing: { elo: 1161, pricePer1k: 60, rank: 22 },
|
|
560
590
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
561
591
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
562
|
-
textToImage: { elo:
|
|
592
|
+
textToImage: { elo: 1223, rank: 18 }
|
|
563
593
|
},
|
|
564
594
|
speed: {
|
|
565
595
|
medianSeconds: 15.3,
|
|
@@ -603,8 +633,7 @@ var MODELS = {
|
|
|
603
633
|
benchmark: {
|
|
604
634
|
artificialAnalysis: {
|
|
605
635
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
606
|
-
sourceUrls: AA_IMAGE_SOURCES
|
|
607
|
-
textToImage: { elo: 1160, pricePer1k: 12, rank: 19, winRate: 0.57 }
|
|
636
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
608
637
|
},
|
|
609
638
|
speed: {
|
|
610
639
|
medianSeconds: 4.6,
|
|
@@ -747,7 +776,55 @@ var MODELS = {
|
|
|
747
776
|
supportsSyncMode: true,
|
|
748
777
|
type: "generation"
|
|
749
778
|
},
|
|
779
|
+
reve: {
|
|
780
|
+
benchmark: {
|
|
781
|
+
artificialAnalysis: {
|
|
782
|
+
// #2 on BOTH boards, which almost nothing else manages - the top text-to-image model
|
|
783
|
+
// (GPT Image 2) drops to 3rd for editing, and the top editor (MAI-Image-2.5-Pro) is not
|
|
784
|
+
// on fal at all. Reve is the best editor motif can actually reach.
|
|
785
|
+
editing: { elo: 1263, rank: 2 },
|
|
786
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
787
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
788
|
+
textToImage: { elo: 1322, rank: 2 }
|
|
789
|
+
},
|
|
790
|
+
tiers: { price: "premium", quality: "frontier", speed: "unknown" },
|
|
791
|
+
useCase: "Highest-ranked editor reachable on fal; strong prompt adherence and text rendering"
|
|
792
|
+
},
|
|
793
|
+
editEndpoint: "fal-ai/reve/edit",
|
|
794
|
+
endpoint: "fal-ai/reve/text-to-image",
|
|
795
|
+
falPricing: {
|
|
796
|
+
checkedAt: FAL_PRICING_CHECKED_AUG_2026,
|
|
797
|
+
currency: "USD",
|
|
798
|
+
endpointId: "fal-ai/reve/text-to-image",
|
|
799
|
+
estimatedCostPerImageUsd: 0.04,
|
|
800
|
+
source: "fal-pricing-api",
|
|
801
|
+
unit: "images",
|
|
802
|
+
unitPrice: 0.04
|
|
803
|
+
},
|
|
804
|
+
maxReferenceImages: 1,
|
|
805
|
+
name: "Reve 2.1",
|
|
806
|
+
pricePerImageUsd: 0.04,
|
|
807
|
+
pricing: "$0.04",
|
|
808
|
+
// fal's schema takes aspect_ratio from a fixed set and has no width/height or resolution
|
|
809
|
+
// parameter, so aspect is supported and resolution is not.
|
|
810
|
+
sizeMode: "aspect_ratio",
|
|
811
|
+
supportsAspect: true,
|
|
812
|
+
supportsEdit: true,
|
|
813
|
+
supportsNumImages: true,
|
|
814
|
+
supportsOutputFormat: true,
|
|
815
|
+
supportsResolution: false,
|
|
816
|
+
supportsSeed: false,
|
|
817
|
+
supportsSyncMode: true,
|
|
818
|
+
type: "generation"
|
|
819
|
+
},
|
|
750
820
|
recraft4: {
|
|
821
|
+
benchmark: {
|
|
822
|
+
artificialAnalysis: {
|
|
823
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
824
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
825
|
+
textToImage: { elo: 1215, rank: 25 }
|
|
826
|
+
}
|
|
827
|
+
},
|
|
751
828
|
endpoint: "fal-ai/recraft/v4/text-to-image",
|
|
752
829
|
falPricing: {
|
|
753
830
|
checkedAt: FAL_PRICING_CHECKED_JUL_2026,
|
|
@@ -798,6 +875,13 @@ var MODELS = {
|
|
|
798
875
|
type: "generation"
|
|
799
876
|
},
|
|
800
877
|
ideogram4: {
|
|
878
|
+
benchmark: {
|
|
879
|
+
artificialAnalysis: {
|
|
880
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
881
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
882
|
+
textToImage: { elo: 1220, rank: 19 }
|
|
883
|
+
}
|
|
884
|
+
},
|
|
801
885
|
name: "Ideogram V4",
|
|
802
886
|
endpoint: "ideogram/v4",
|
|
803
887
|
type: "generation",
|
|
@@ -830,10 +914,10 @@ var MODELS = {
|
|
|
830
914
|
"grok-image": {
|
|
831
915
|
benchmark: {
|
|
832
916
|
artificialAnalysis: {
|
|
833
|
-
editing: { elo:
|
|
917
|
+
editing: { elo: 1214, rank: 16 },
|
|
834
918
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
835
919
|
sourceUrls: AA_IMAGE_SOURCES,
|
|
836
|
-
textToImage: { elo:
|
|
920
|
+
textToImage: { elo: 1216, rank: 23 }
|
|
837
921
|
},
|
|
838
922
|
speed: {
|
|
839
923
|
medianSeconds: 5.1,
|
|
@@ -871,8 +955,7 @@ var MODELS = {
|
|
|
871
955
|
benchmark: {
|
|
872
956
|
artificialAnalysis: {
|
|
873
957
|
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
874
|
-
sourceUrls: AA_IMAGE_SOURCES
|
|
875
|
-
textToImage: { elo: 1158, pricePer1k: 20, rank: 20, winRate: 0.6 }
|
|
958
|
+
sourceUrls: AA_IMAGE_SOURCES
|
|
876
959
|
},
|
|
877
960
|
speed: {
|
|
878
961
|
medianSeconds: 23.3,
|
|
@@ -907,8 +990,14 @@ var MODELS = {
|
|
|
907
990
|
},
|
|
908
991
|
qwen3: {
|
|
909
992
|
benchmark: {
|
|
993
|
+
artificialAnalysis: {
|
|
994
|
+
editing: { elo: 1218, rank: 15 },
|
|
995
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
996
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
997
|
+
textToImage: { elo: 1272, rank: 11 }
|
|
998
|
+
},
|
|
910
999
|
tiers: { price: "budget", quality: "better", speed: "unknown" },
|
|
911
|
-
useCase: "
|
|
1000
|
+
useCase: "Strong quality per dollar - 11th on text-to-image at $30/1k"
|
|
912
1001
|
},
|
|
913
1002
|
endpoint: "fal-ai/qwen-image-3/text-to-image",
|
|
914
1003
|
falPricing: {
|
|
@@ -1333,7 +1422,7 @@ function validateGenerateOptions(options, config, sizeMode, hasEditImages) {
|
|
|
1333
1422
|
if (options.background !== void 0 && config.supportsBackground !== true) {
|
|
1334
1423
|
unsupported(config, "background");
|
|
1335
1424
|
}
|
|
1336
|
-
if (options.transparent === true &&
|
|
1425
|
+
if (options.transparent === true && config.supportsBackground !== true) {
|
|
1337
1426
|
unsupported(config, "transparent output");
|
|
1338
1427
|
}
|
|
1339
1428
|
if (options.inputFidelity !== void 0) {
|
|
@@ -1615,353 +1704,351 @@ function buildGenerateBody(options) {
|
|
|
1615
1704
|
|
|
1616
1705
|
// src/leaderboards.ts
|
|
1617
1706
|
var IMAGE_TEXT_TO_IMAGE_TOP_20 = {
|
|
1618
|
-
capturedAt: "2026-
|
|
1707
|
+
capturedAt: "2026-08-23",
|
|
1619
1708
|
entries: [
|
|
1620
1709
|
{
|
|
1621
1710
|
apiPricing: "$211/1k images",
|
|
1622
1711
|
creator: "OpenAI",
|
|
1623
|
-
elo:
|
|
1712
|
+
elo: 1369,
|
|
1624
1713
|
isCurrent: true,
|
|
1625
1714
|
model: "GPT Image 2 (high)",
|
|
1626
1715
|
rank: 1,
|
|
1627
1716
|
routableModelId: "gpt2"
|
|
1628
1717
|
},
|
|
1629
1718
|
{
|
|
1630
|
-
apiPricing: "$
|
|
1631
|
-
creator: "
|
|
1632
|
-
elo:
|
|
1719
|
+
apiPricing: "$200/1k images",
|
|
1720
|
+
creator: "Reve",
|
|
1721
|
+
elo: 1322,
|
|
1633
1722
|
isCurrent: true,
|
|
1634
|
-
model: "
|
|
1723
|
+
model: "Reve 2.1",
|
|
1635
1724
|
rank: 2,
|
|
1636
|
-
routableModelId: "
|
|
1725
|
+
routableModelId: "reve"
|
|
1637
1726
|
},
|
|
1638
1727
|
{
|
|
1639
1728
|
apiPricing: "$67/1k images",
|
|
1640
1729
|
creator: "Google",
|
|
1641
|
-
elo:
|
|
1730
|
+
elo: 1320,
|
|
1642
1731
|
isCurrent: true,
|
|
1643
1732
|
model: "Nano Banana 2 (Gemini 3.1 Flash Image Preview)",
|
|
1644
1733
|
rank: 3,
|
|
1645
1734
|
routableModelId: "banana2"
|
|
1646
1735
|
},
|
|
1647
1736
|
{
|
|
1648
|
-
apiPricing: "$
|
|
1649
|
-
creator: "
|
|
1650
|
-
elo:
|
|
1737
|
+
apiPricing: "$133/1k images",
|
|
1738
|
+
creator: "OpenAI",
|
|
1739
|
+
elo: 1310,
|
|
1651
1740
|
isCurrent: true,
|
|
1652
|
-
model: "
|
|
1653
|
-
rank: 4
|
|
1741
|
+
model: "GPT Image 1.5 (high)",
|
|
1742
|
+
rank: 4,
|
|
1743
|
+
routableModelId: "gpt"
|
|
1654
1744
|
},
|
|
1655
1745
|
{
|
|
1656
|
-
apiPricing: "$
|
|
1657
|
-
creator: "
|
|
1658
|
-
elo:
|
|
1746
|
+
apiPricing: "$48/1k images",
|
|
1747
|
+
creator: "Microsoft AI",
|
|
1748
|
+
elo: 1305,
|
|
1659
1749
|
isCurrent: true,
|
|
1660
|
-
model: "
|
|
1661
|
-
rank: 5
|
|
1662
|
-
routableModelId: "banana"
|
|
1750
|
+
model: "MAI-Image-2.5",
|
|
1751
|
+
rank: 5
|
|
1663
1752
|
},
|
|
1664
1753
|
{
|
|
1665
|
-
apiPricing: "$
|
|
1666
|
-
creator: "
|
|
1667
|
-
elo:
|
|
1754
|
+
apiPricing: "$134/1k images",
|
|
1755
|
+
creator: "Google",
|
|
1756
|
+
elo: 1297,
|
|
1668
1757
|
isCurrent: true,
|
|
1669
|
-
model: "
|
|
1758
|
+
model: "Nano Banana Pro (Gemini 3 Pro Image)",
|
|
1670
1759
|
rank: 6,
|
|
1671
|
-
routableModelId: "
|
|
1760
|
+
routableModelId: "banana"
|
|
1672
1761
|
},
|
|
1673
1762
|
{
|
|
1674
|
-
apiPricing: "$
|
|
1675
|
-
creator: "Microsoft",
|
|
1676
|
-
elo:
|
|
1763
|
+
apiPricing: "$109/1k images",
|
|
1764
|
+
creator: "Microsoft AI",
|
|
1765
|
+
elo: 1293,
|
|
1677
1766
|
isCurrent: true,
|
|
1678
|
-
model: "MAI-Image-2",
|
|
1767
|
+
model: "MAI-Image-2.5-Pro",
|
|
1679
1768
|
rank: 7
|
|
1680
1769
|
},
|
|
1681
1770
|
{
|
|
1682
|
-
apiPricing: "$
|
|
1683
|
-
creator: "
|
|
1684
|
-
elo:
|
|
1771
|
+
apiPricing: "$34/1k images",
|
|
1772
|
+
creator: "Google",
|
|
1773
|
+
elo: 1289,
|
|
1685
1774
|
isCurrent: true,
|
|
1686
|
-
model: "
|
|
1687
|
-
rank: 8
|
|
1688
|
-
routableModelId: "flux2-max"
|
|
1775
|
+
model: "Nano Banana 2 Lite (Gemini 3.1 Flash Lite Image)",
|
|
1776
|
+
rank: 8
|
|
1689
1777
|
},
|
|
1690
1778
|
{
|
|
1691
|
-
apiPricing: "
|
|
1692
|
-
creator: "
|
|
1693
|
-
elo:
|
|
1779
|
+
apiPricing: "$43/1k images",
|
|
1780
|
+
creator: "Alibaba",
|
|
1781
|
+
elo: 1282,
|
|
1694
1782
|
isCurrent: true,
|
|
1695
|
-
model: "
|
|
1783
|
+
model: "Qwen-Image-3.0-Pro",
|
|
1696
1784
|
rank: 9
|
|
1697
1785
|
},
|
|
1698
1786
|
{
|
|
1699
|
-
apiPricing: "$
|
|
1700
|
-
creator: "
|
|
1701
|
-
elo:
|
|
1787
|
+
apiPricing: "$90/1k images",
|
|
1788
|
+
creator: "Bytedance",
|
|
1789
|
+
elo: 1279,
|
|
1702
1790
|
isCurrent: true,
|
|
1703
|
-
model: "
|
|
1791
|
+
model: "Seedream 5.0 Pro",
|
|
1704
1792
|
rank: 10,
|
|
1705
|
-
routableModelId: "
|
|
1793
|
+
routableModelId: "seedream5"
|
|
1706
1794
|
},
|
|
1707
1795
|
{
|
|
1708
|
-
apiPricing: "$
|
|
1709
|
-
creator: "
|
|
1710
|
-
elo:
|
|
1711
|
-
isCurrent:
|
|
1712
|
-
model: "
|
|
1713
|
-
rank: 11
|
|
1796
|
+
apiPricing: "$30/1k images",
|
|
1797
|
+
creator: "Alibaba",
|
|
1798
|
+
elo: 1272,
|
|
1799
|
+
isCurrent: true,
|
|
1800
|
+
model: "Qwen-Image-3.0",
|
|
1801
|
+
rank: 11,
|
|
1802
|
+
routableModelId: "qwen3"
|
|
1714
1803
|
},
|
|
1715
1804
|
{
|
|
1716
|
-
apiPricing: "$
|
|
1717
|
-
creator: "
|
|
1718
|
-
elo:
|
|
1805
|
+
apiPricing: "$75/1k images",
|
|
1806
|
+
creator: "Alibaba",
|
|
1807
|
+
elo: 1237,
|
|
1719
1808
|
isCurrent: true,
|
|
1720
|
-
model: "
|
|
1721
|
-
rank: 12
|
|
1722
|
-
routableModelId: "grok-image"
|
|
1809
|
+
model: "Qwen Image 2.0 Pro",
|
|
1810
|
+
rank: 12
|
|
1723
1811
|
},
|
|
1724
1812
|
{
|
|
1725
|
-
apiPricing: "$
|
|
1726
|
-
creator: "
|
|
1727
|
-
elo:
|
|
1813
|
+
apiPricing: "$50/1k images",
|
|
1814
|
+
creator: "SpaceXAI",
|
|
1815
|
+
elo: 1234,
|
|
1728
1816
|
isCurrent: true,
|
|
1729
|
-
model: "
|
|
1730
|
-
rank: 13
|
|
1731
|
-
routableModelId: "flux2-flex"
|
|
1817
|
+
model: "grok-imagine-image-quality",
|
|
1818
|
+
rank: 13
|
|
1732
1819
|
},
|
|
1733
1820
|
{
|
|
1734
|
-
apiPricing: "$
|
|
1735
|
-
creator: "
|
|
1736
|
-
elo:
|
|
1821
|
+
apiPricing: "$20/1k images",
|
|
1822
|
+
creator: "Microsoft AI",
|
|
1823
|
+
elo: 1228,
|
|
1737
1824
|
isCurrent: true,
|
|
1738
|
-
model: "
|
|
1825
|
+
model: "MAI-Image-2.5-Flash",
|
|
1739
1826
|
rank: 14
|
|
1740
1827
|
},
|
|
1741
1828
|
{
|
|
1742
|
-
apiPricing: "$
|
|
1743
|
-
creator: "
|
|
1744
|
-
elo:
|
|
1829
|
+
apiPricing: "$80/1k images",
|
|
1830
|
+
creator: "HiDream",
|
|
1831
|
+
elo: 1228,
|
|
1745
1832
|
isCurrent: true,
|
|
1746
|
-
model: "
|
|
1833
|
+
model: "HiDream-O1-Image-1.5",
|
|
1747
1834
|
rank: 15
|
|
1748
1835
|
},
|
|
1749
1836
|
{
|
|
1750
|
-
apiPricing: "$
|
|
1751
|
-
creator: "
|
|
1752
|
-
elo:
|
|
1753
|
-
isCurrent:
|
|
1754
|
-
model: "
|
|
1755
|
-
rank: 16
|
|
1837
|
+
apiPricing: "$30/1k images",
|
|
1838
|
+
creator: "ByteDance Seed",
|
|
1839
|
+
elo: 1226,
|
|
1840
|
+
isCurrent: true,
|
|
1841
|
+
model: "Seedream 4.0",
|
|
1842
|
+
rank: 16,
|
|
1843
|
+
routableModelId: "seedream4"
|
|
1756
1844
|
},
|
|
1757
1845
|
{
|
|
1758
|
-
apiPricing: "$
|
|
1759
|
-
creator: "
|
|
1760
|
-
elo:
|
|
1846
|
+
apiPricing: "$70/1k images",
|
|
1847
|
+
creator: "Black Forest Labs",
|
|
1848
|
+
elo: 1225,
|
|
1761
1849
|
isCurrent: true,
|
|
1762
|
-
model: "
|
|
1850
|
+
model: "FLUX.2 [max]",
|
|
1763
1851
|
rank: 17,
|
|
1764
|
-
routableModelId: "
|
|
1852
|
+
routableModelId: "flux2-max"
|
|
1765
1853
|
},
|
|
1766
1854
|
{
|
|
1767
|
-
apiPricing: "$
|
|
1768
|
-
creator: "
|
|
1769
|
-
elo:
|
|
1855
|
+
apiPricing: "$60/1k images",
|
|
1856
|
+
creator: "Black Forest Labs",
|
|
1857
|
+
elo: 1223,
|
|
1770
1858
|
isCurrent: true,
|
|
1771
|
-
model: "FLUX.2 [
|
|
1772
|
-
rank: 18
|
|
1859
|
+
model: "FLUX.2 [flex]",
|
|
1860
|
+
rank: 18,
|
|
1861
|
+
routableModelId: "flux2-flex"
|
|
1773
1862
|
},
|
|
1774
1863
|
{
|
|
1775
|
-
apiPricing: "$
|
|
1776
|
-
creator: "
|
|
1777
|
-
elo:
|
|
1864
|
+
apiPricing: "$60/1k images",
|
|
1865
|
+
creator: "Ideogram",
|
|
1866
|
+
elo: 1220,
|
|
1778
1867
|
isCurrent: true,
|
|
1779
|
-
model: "
|
|
1868
|
+
model: "Ideogram 4.0",
|
|
1780
1869
|
rank: 19,
|
|
1781
|
-
routableModelId: "
|
|
1870
|
+
routableModelId: "ideogram4"
|
|
1782
1871
|
},
|
|
1783
1872
|
{
|
|
1784
|
-
apiPricing: "$
|
|
1785
|
-
creator: "
|
|
1786
|
-
elo:
|
|
1873
|
+
apiPricing: "$60/1k images",
|
|
1874
|
+
creator: "Krea",
|
|
1875
|
+
elo: 1220,
|
|
1787
1876
|
isCurrent: true,
|
|
1788
|
-
model: "
|
|
1789
|
-
rank: 20
|
|
1790
|
-
routableModelId: "qwen"
|
|
1877
|
+
model: "Krea 2 Large",
|
|
1878
|
+
rank: 20
|
|
1791
1879
|
}
|
|
1792
1880
|
],
|
|
1793
1881
|
source: "https://artificialanalysis.ai/image/leaderboard/text-to-image"
|
|
1794
1882
|
};
|
|
1795
1883
|
var IMAGE_EDITING_TOP_20 = {
|
|
1796
|
-
capturedAt: "2026-
|
|
1884
|
+
capturedAt: "2026-08-23",
|
|
1797
1885
|
entries: [
|
|
1798
1886
|
{
|
|
1799
|
-
apiPricing: "$
|
|
1800
|
-
creator: "
|
|
1801
|
-
elo:
|
|
1887
|
+
apiPricing: "$109/1k images",
|
|
1888
|
+
creator: "Microsoft AI",
|
|
1889
|
+
elo: 1272,
|
|
1802
1890
|
isCurrent: true,
|
|
1803
|
-
model: "
|
|
1891
|
+
model: "MAI-Image-2.5-Pro",
|
|
1804
1892
|
rank: 1
|
|
1805
1893
|
},
|
|
1806
1894
|
{
|
|
1807
|
-
apiPricing: "$
|
|
1808
|
-
creator: "
|
|
1809
|
-
elo:
|
|
1895
|
+
apiPricing: "$200/1k images",
|
|
1896
|
+
creator: "Reve",
|
|
1897
|
+
elo: 1263,
|
|
1810
1898
|
isCurrent: true,
|
|
1811
|
-
model: "
|
|
1899
|
+
model: "Reve 2.1",
|
|
1812
1900
|
rank: 2,
|
|
1813
|
-
routableModelId: "
|
|
1901
|
+
routableModelId: "reve"
|
|
1814
1902
|
},
|
|
1815
1903
|
{
|
|
1816
1904
|
apiPricing: "$211/1k images",
|
|
1817
1905
|
creator: "OpenAI",
|
|
1818
|
-
elo:
|
|
1906
|
+
elo: 1256,
|
|
1819
1907
|
isCurrent: true,
|
|
1820
1908
|
model: "GPT Image 2 (high)",
|
|
1821
1909
|
rank: 3,
|
|
1822
1910
|
routableModelId: "gpt2"
|
|
1823
1911
|
},
|
|
1824
1912
|
{
|
|
1825
|
-
apiPricing: "$
|
|
1826
|
-
creator: "
|
|
1827
|
-
elo:
|
|
1913
|
+
apiPricing: "$48/1k images",
|
|
1914
|
+
creator: "Microsoft AI",
|
|
1915
|
+
elo: 1256,
|
|
1828
1916
|
isCurrent: true,
|
|
1829
|
-
model: "
|
|
1830
|
-
rank: 4
|
|
1831
|
-
routableModelId: "banana"
|
|
1917
|
+
model: "MAI-Image-2.5",
|
|
1918
|
+
rank: 4
|
|
1832
1919
|
},
|
|
1833
1920
|
{
|
|
1834
|
-
apiPricing: "$
|
|
1835
|
-
creator: "
|
|
1836
|
-
elo:
|
|
1921
|
+
apiPricing: "$133/1k images",
|
|
1922
|
+
creator: "OpenAI",
|
|
1923
|
+
elo: 1250,
|
|
1837
1924
|
isCurrent: true,
|
|
1838
|
-
model: "
|
|
1925
|
+
model: "GPT Image 1.5 (high)",
|
|
1839
1926
|
rank: 5,
|
|
1840
|
-
routableModelId: "
|
|
1927
|
+
routableModelId: "gpt"
|
|
1841
1928
|
},
|
|
1842
1929
|
{
|
|
1843
|
-
apiPricing: "$
|
|
1844
|
-
creator: "
|
|
1845
|
-
elo:
|
|
1930
|
+
apiPricing: "$43/1k images",
|
|
1931
|
+
creator: "Alibaba",
|
|
1932
|
+
elo: 1250,
|
|
1846
1933
|
isCurrent: true,
|
|
1847
|
-
model: "
|
|
1934
|
+
model: "Qwen-Image-3.0-Pro",
|
|
1848
1935
|
rank: 6
|
|
1849
1936
|
},
|
|
1850
1937
|
{
|
|
1851
|
-
apiPricing: "$
|
|
1852
|
-
creator: "
|
|
1853
|
-
elo:
|
|
1938
|
+
apiPricing: "$67/1k images",
|
|
1939
|
+
creator: "Google",
|
|
1940
|
+
elo: 1249,
|
|
1854
1941
|
isCurrent: true,
|
|
1855
|
-
model: "
|
|
1942
|
+
model: "Nano Banana 2 (Gemini 3.1 Flash Image Preview)",
|
|
1856
1943
|
rank: 7,
|
|
1857
|
-
routableModelId: "
|
|
1944
|
+
routableModelId: "banana2"
|
|
1858
1945
|
},
|
|
1859
1946
|
{
|
|
1860
|
-
apiPricing: "$
|
|
1861
|
-
creator: "
|
|
1862
|
-
elo:
|
|
1947
|
+
apiPricing: "$90/1k images",
|
|
1948
|
+
creator: "Bytedance",
|
|
1949
|
+
elo: 1248,
|
|
1863
1950
|
isCurrent: true,
|
|
1864
|
-
model: "
|
|
1865
|
-
rank: 8
|
|
1951
|
+
model: "Seedream 5.0 Pro",
|
|
1952
|
+
rank: 8,
|
|
1953
|
+
routableModelId: "seedream5"
|
|
1866
1954
|
},
|
|
1867
1955
|
{
|
|
1868
|
-
apiPricing: "
|
|
1869
|
-
creator: "
|
|
1870
|
-
elo:
|
|
1956
|
+
apiPricing: "$134/1k images",
|
|
1957
|
+
creator: "Google",
|
|
1958
|
+
elo: 1245,
|
|
1871
1959
|
isCurrent: true,
|
|
1872
|
-
model: "
|
|
1873
|
-
rank: 9
|
|
1960
|
+
model: "Nano Banana Pro (Gemini 3 Pro Image)",
|
|
1961
|
+
rank: 9,
|
|
1962
|
+
routableModelId: "banana"
|
|
1874
1963
|
},
|
|
1875
1964
|
{
|
|
1876
|
-
apiPricing: "$
|
|
1877
|
-
creator: "
|
|
1878
|
-
elo:
|
|
1965
|
+
apiPricing: "$20/1k images",
|
|
1966
|
+
creator: "Microsoft AI",
|
|
1967
|
+
elo: 1236,
|
|
1879
1968
|
isCurrent: true,
|
|
1880
|
-
model: "
|
|
1881
|
-
rank: 10
|
|
1882
|
-
routableModelId: "flux2-max"
|
|
1969
|
+
model: "MAI-Image-2.5-Flash",
|
|
1970
|
+
rank: 10
|
|
1883
1971
|
},
|
|
1884
1972
|
{
|
|
1885
|
-
apiPricing: "
|
|
1886
|
-
creator: "
|
|
1887
|
-
elo:
|
|
1973
|
+
apiPricing: "$50/1k images",
|
|
1974
|
+
creator: "SpaceXAI",
|
|
1975
|
+
elo: 1226,
|
|
1888
1976
|
isCurrent: true,
|
|
1889
|
-
model: "
|
|
1977
|
+
model: "grok-imagine-image-quality",
|
|
1890
1978
|
rank: 11
|
|
1891
1979
|
},
|
|
1892
1980
|
{
|
|
1893
|
-
apiPricing: "$
|
|
1894
|
-
creator: "
|
|
1895
|
-
elo:
|
|
1981
|
+
apiPricing: "$90/1k images",
|
|
1982
|
+
creator: "Tencent",
|
|
1983
|
+
elo: 1222,
|
|
1896
1984
|
isCurrent: true,
|
|
1897
|
-
model: "
|
|
1985
|
+
model: "HunyuanImage 3.0 Instruct",
|
|
1898
1986
|
rank: 12
|
|
1899
1987
|
},
|
|
1900
1988
|
{
|
|
1901
|
-
apiPricing: "$
|
|
1902
|
-
creator: "
|
|
1903
|
-
elo:
|
|
1989
|
+
apiPricing: "$80/1k images",
|
|
1990
|
+
creator: "Newport AI",
|
|
1991
|
+
elo: 1220,
|
|
1904
1992
|
isCurrent: true,
|
|
1905
|
-
model: "
|
|
1993
|
+
model: "DreamImage 2.0",
|
|
1906
1994
|
rank: 13
|
|
1907
1995
|
},
|
|
1908
1996
|
{
|
|
1909
|
-
apiPricing: "$
|
|
1910
|
-
creator: "
|
|
1911
|
-
elo:
|
|
1997
|
+
apiPricing: "$100/1k images",
|
|
1998
|
+
creator: "Luma Labs",
|
|
1999
|
+
elo: 1219,
|
|
1912
2000
|
isCurrent: true,
|
|
1913
|
-
model: "
|
|
2001
|
+
model: "Luma UNI 1 Max",
|
|
1914
2002
|
rank: 14
|
|
1915
2003
|
},
|
|
1916
2004
|
{
|
|
1917
|
-
apiPricing: "$
|
|
1918
|
-
creator: "
|
|
1919
|
-
elo:
|
|
2005
|
+
apiPricing: "$33/1k images",
|
|
2006
|
+
creator: "Alibaba",
|
|
2007
|
+
elo: 1218,
|
|
1920
2008
|
isCurrent: true,
|
|
1921
|
-
model: "
|
|
1922
|
-
rank: 15
|
|
2009
|
+
model: "Qwen-Image-3.0",
|
|
2010
|
+
rank: 15,
|
|
2011
|
+
routableModelId: "qwen3"
|
|
1923
2012
|
},
|
|
1924
2013
|
{
|
|
1925
|
-
apiPricing: "$
|
|
1926
|
-
creator: "
|
|
1927
|
-
elo:
|
|
2014
|
+
apiPricing: "$20/1k images",
|
|
2015
|
+
creator: "SpaceXAI",
|
|
2016
|
+
elo: 1214,
|
|
1928
2017
|
isCurrent: true,
|
|
1929
|
-
model: "
|
|
2018
|
+
model: "grok-imagine-image",
|
|
1930
2019
|
rank: 16,
|
|
1931
|
-
routableModelId: "
|
|
2020
|
+
routableModelId: "grok-image"
|
|
1932
2021
|
},
|
|
1933
2022
|
{
|
|
1934
|
-
apiPricing: "$
|
|
1935
|
-
creator: "
|
|
1936
|
-
elo:
|
|
2023
|
+
apiPricing: "$28/1k images",
|
|
2024
|
+
creator: "KlingAI",
|
|
2025
|
+
elo: 1208,
|
|
1937
2026
|
isCurrent: true,
|
|
1938
|
-
model: "
|
|
1939
|
-
rank: 17
|
|
1940
|
-
routableModelId: "seedream45"
|
|
2027
|
+
model: "Kling Image 3.0 Omni",
|
|
2028
|
+
rank: 17
|
|
1941
2029
|
},
|
|
1942
2030
|
{
|
|
1943
|
-
apiPricing: "$
|
|
1944
|
-
creator: "
|
|
1945
|
-
elo:
|
|
2031
|
+
apiPricing: "$34/1k images",
|
|
2032
|
+
creator: "Google",
|
|
2033
|
+
elo: 1202,
|
|
1946
2034
|
isCurrent: true,
|
|
1947
|
-
model: "
|
|
2035
|
+
model: "Nano Banana 2 Lite",
|
|
1948
2036
|
rank: 18
|
|
1949
2037
|
},
|
|
1950
2038
|
{
|
|
1951
|
-
apiPricing: "$
|
|
1952
|
-
creator: "
|
|
1953
|
-
elo:
|
|
2039
|
+
apiPricing: "$140/1k images",
|
|
2040
|
+
creator: "Black Forest Labs",
|
|
2041
|
+
elo: 1201,
|
|
1954
2042
|
isCurrent: true,
|
|
1955
|
-
model: "
|
|
2043
|
+
model: "FLUX.2 [max]",
|
|
1956
2044
|
rank: 19,
|
|
1957
|
-
routableModelId: "
|
|
2045
|
+
routableModelId: "flux2-max"
|
|
1958
2046
|
},
|
|
1959
2047
|
{
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
elo: 1172,
|
|
2048
|
+
creator: "Alibaba",
|
|
2049
|
+
elo: 1200,
|
|
1963
2050
|
isCurrent: true,
|
|
1964
|
-
model: "
|
|
2051
|
+
model: "Wan 2.7 Pro",
|
|
1965
2052
|
rank: 20
|
|
1966
2053
|
}
|
|
1967
2054
|
],
|
|
@@ -2191,7 +2278,31 @@ var VIDEO_IMAGE_TO_VIDEO_TOP_15 = {
|
|
|
2191
2278
|
};
|
|
2192
2279
|
|
|
2193
2280
|
// src/server.ts
|
|
2194
|
-
import { err, ok } from "neverthrow";
|
|
2281
|
+
import { err as err2, ok as ok2 } from "neverthrow";
|
|
2282
|
+
|
|
2283
|
+
// src/errors.ts
|
|
2284
|
+
var MotifError = class extends Error {
|
|
2285
|
+
status;
|
|
2286
|
+
code;
|
|
2287
|
+
/** fal's request-correlation id (from the `x-fal-request-id` header or the
|
|
2288
|
+
* error body). Ties a failure back to fal's dashboard/support. */
|
|
2289
|
+
requestId;
|
|
2290
|
+
constructor(message, status, code, requestId) {
|
|
2291
|
+
super(message);
|
|
2292
|
+
this.name = "MotifError";
|
|
2293
|
+
this.status = status;
|
|
2294
|
+
this.code = code;
|
|
2295
|
+
this.requestId = requestId;
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
function toMotifError(error) {
|
|
2299
|
+
if (error instanceof MotifError) {
|
|
2300
|
+
return error;
|
|
2301
|
+
}
|
|
2302
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2303
|
+
const code = error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
2304
|
+
return new MotifError(message, 0, code);
|
|
2305
|
+
}
|
|
2195
2306
|
|
|
2196
2307
|
// src/fal-parse.ts
|
|
2197
2308
|
function isRecord(value) {
|
|
@@ -2289,9 +2400,369 @@ function requestIdFromBody(text) {
|
|
|
2289
2400
|
return asString(parsed.request_id) ?? asString(parsed.requestId) ?? asString(parsed.trace_id);
|
|
2290
2401
|
}
|
|
2291
2402
|
|
|
2292
|
-
// src/tools.ts
|
|
2293
|
-
|
|
2294
|
-
|
|
2403
|
+
// src/server-tools.ts
|
|
2404
|
+
import { err, ok } from "neverthrow";
|
|
2405
|
+
|
|
2406
|
+
// src/tool-registry/analysis.ts
|
|
2407
|
+
var ANALYSIS_TOOLS = {
|
|
2408
|
+
"got-ocr": {
|
|
2409
|
+
category: "analysis",
|
|
2410
|
+
description: "Transcribe text from one or more images, optionally as formatted multi-page output.",
|
|
2411
|
+
endpoint: "fal-ai/got-ocr/v2",
|
|
2412
|
+
inputField: "input_image_urls",
|
|
2413
|
+
inputKind: "images",
|
|
2414
|
+
name: "GOT-OCR 2.0",
|
|
2415
|
+
outputKeys: ["outputs"],
|
|
2416
|
+
price: { kind: "metered" },
|
|
2417
|
+
pricing: "$0.05/image",
|
|
2418
|
+
queued: true,
|
|
2419
|
+
sourceUrl: "https://fal.ai/models/fal-ai/got-ocr/v2",
|
|
2420
|
+
task: "optical character recognition"
|
|
2421
|
+
},
|
|
2422
|
+
"moondream-caption": {
|
|
2423
|
+
category: "analysis",
|
|
2424
|
+
description: "Write a short, normal, or long caption for an image.",
|
|
2425
|
+
endpoint: "fal-ai/moondream3-preview/caption",
|
|
2426
|
+
inputField: "image_url",
|
|
2427
|
+
inputKind: "image",
|
|
2428
|
+
name: "Moondream 3 Caption",
|
|
2429
|
+
outputKeys: ["output"],
|
|
2430
|
+
price: { kind: "metered" },
|
|
2431
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
2432
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/caption",
|
|
2433
|
+
task: "image captioning"
|
|
2434
|
+
},
|
|
2435
|
+
"moondream-detect": {
|
|
2436
|
+
category: "analysis",
|
|
2437
|
+
description: "Detect prompted objects and return their bounding boxes, with an optional preview.",
|
|
2438
|
+
endpoint: "fal-ai/moondream3-preview/detect",
|
|
2439
|
+
inputField: "image_url",
|
|
2440
|
+
inputKind: "image",
|
|
2441
|
+
name: "Moondream 3 Detect",
|
|
2442
|
+
outputKeys: ["objects", "image"],
|
|
2443
|
+
price: { kind: "metered" },
|
|
2444
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
2445
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/detect",
|
|
2446
|
+
task: "object detection"
|
|
2447
|
+
},
|
|
2448
|
+
"moondream-point": {
|
|
2449
|
+
category: "analysis",
|
|
2450
|
+
description: "Return point coordinates for every instance of a prompted subject.",
|
|
2451
|
+
endpoint: "fal-ai/moondream3-preview/point",
|
|
2452
|
+
inputField: "image_url",
|
|
2453
|
+
inputKind: "image",
|
|
2454
|
+
name: "Moondream 3 Point",
|
|
2455
|
+
outputKeys: ["points", "image"],
|
|
2456
|
+
price: { kind: "metered" },
|
|
2457
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
2458
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/point",
|
|
2459
|
+
task: "object pointing"
|
|
2460
|
+
},
|
|
2461
|
+
"moondream-query": {
|
|
2462
|
+
category: "analysis",
|
|
2463
|
+
description: "Answer a free-form question about an image, with reasoning.",
|
|
2464
|
+
endpoint: "fal-ai/moondream3-preview/query",
|
|
2465
|
+
inputField: "image_url",
|
|
2466
|
+
inputKind: "image",
|
|
2467
|
+
name: "Moondream 3 Query",
|
|
2468
|
+
outputKeys: ["output", "reasoning"],
|
|
2469
|
+
price: { kind: "metered" },
|
|
2470
|
+
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
2471
|
+
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/query",
|
|
2472
|
+
task: "visual question answering"
|
|
2473
|
+
},
|
|
2474
|
+
nsfw: {
|
|
2475
|
+
category: "moderation",
|
|
2476
|
+
description: "Predict whether one or more images contain NSFW concepts.",
|
|
2477
|
+
endpoint: "fal-ai/x-ailab/nsfw",
|
|
2478
|
+
inputField: "image_urls",
|
|
2479
|
+
inputKind: "images",
|
|
2480
|
+
name: "NSFW Checker",
|
|
2481
|
+
outputKeys: ["has_nsfw_concepts"],
|
|
2482
|
+
price: { kind: "metered" },
|
|
2483
|
+
pricing: "$0.001/image",
|
|
2484
|
+
sourceUrl: "https://fal.ai/models/fal-ai/x-ailab/nsfw",
|
|
2485
|
+
task: "vision moderation"
|
|
2486
|
+
}
|
|
2487
|
+
};
|
|
2488
|
+
|
|
2489
|
+
// src/tool-registry/assets.ts
|
|
2490
|
+
var ASSET_TOOLS = {
|
|
2491
|
+
"hunyuan3d-v3": {
|
|
2492
|
+
category: "3d",
|
|
2493
|
+
description: "Reconstruct a textured 3D mesh from a single image, with optional multi-view inputs.",
|
|
2494
|
+
endpoint: "fal-ai/hunyuan3d-v3/image-to-3d",
|
|
2495
|
+
inputField: "input_image_url",
|
|
2496
|
+
inputKind: "image",
|
|
2497
|
+
name: "Hunyuan3D v3 Image to 3D",
|
|
2498
|
+
outputKeys: ["model_glb", "model_urls", "thumbnail"],
|
|
2499
|
+
price: { kind: "call", usd: 0.375 },
|
|
2500
|
+
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",
|
|
2501
|
+
queued: true,
|
|
2502
|
+
sourceUrl: "https://fal.ai/models/fal-ai/hunyuan3d-v3/image-to-3d",
|
|
2503
|
+
task: "single-image 3D reconstruction"
|
|
2504
|
+
},
|
|
2505
|
+
"ideogram-layerize-text": {
|
|
2506
|
+
category: "layers",
|
|
2507
|
+
description: "Split an image into background image layers plus editable HTML text containers.",
|
|
2508
|
+
endpoint: "fal-ai/ideogram/v3/layerize-text",
|
|
2509
|
+
inputField: "image_url",
|
|
2510
|
+
inputKind: "image",
|
|
2511
|
+
name: "Ideogram v3 Text Layerize",
|
|
2512
|
+
outputKeys: ["image_layers", "image", "text_html", "text_containers"],
|
|
2513
|
+
price: { kind: "call", usd: 0.09 },
|
|
2514
|
+
pricing: "$0.09/image",
|
|
2515
|
+
queued: true,
|
|
2516
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ideogram/v3/layerize-text",
|
|
2517
|
+
task: "text and image layer extraction"
|
|
2518
|
+
},
|
|
2519
|
+
"ideogram-tiling": {
|
|
2520
|
+
category: "material",
|
|
2521
|
+
description: "Generate a seamlessly tiling texture, optionally conditioned on a source image.",
|
|
2522
|
+
endpoint: "ideogram/v4/tiling",
|
|
2523
|
+
inputField: "image_url",
|
|
2524
|
+
inputKind: "image",
|
|
2525
|
+
name: "Ideogram v4 Tiling",
|
|
2526
|
+
outputKeys: ["images"],
|
|
2527
|
+
price: { kind: "megapixel", usd: 0.06 },
|
|
2528
|
+
pricing: "$0.06/megapixel at the default BALANCED speed; $0.03 turbo, $0.10 quality",
|
|
2529
|
+
sourceUrl: "https://fal.ai/models/ideogram/v4/tiling",
|
|
2530
|
+
task: "seamless texture generation"
|
|
2531
|
+
},
|
|
2532
|
+
image2svg: {
|
|
2533
|
+
category: "vector",
|
|
2534
|
+
description: "Trace a raster image into layered SVG paths.",
|
|
2535
|
+
endpoint: "fal-ai/image2svg",
|
|
2536
|
+
inputField: "image_url",
|
|
2537
|
+
inputKind: "image",
|
|
2538
|
+
name: "Image to SVG",
|
|
2539
|
+
outputKeys: ["images"],
|
|
2540
|
+
price: { kind: "call", usd: 5e-3 },
|
|
2541
|
+
pricing: "$0.005/image",
|
|
2542
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image2svg",
|
|
2543
|
+
task: "raster to vector tracing"
|
|
2544
|
+
},
|
|
2545
|
+
patina: {
|
|
2546
|
+
category: "material",
|
|
2547
|
+
description: "Decompose a surface photograph into PBR maps: basecolor, normal, roughness, metalness, height.",
|
|
2548
|
+
endpoint: "fal-ai/patina",
|
|
2549
|
+
inputField: "image_url",
|
|
2550
|
+
inputKind: "image",
|
|
2551
|
+
name: "Patina PBR Maps",
|
|
2552
|
+
outputKeys: ["images"],
|
|
2553
|
+
// Output order follows the request's `maps` array, so read that first;
|
|
2554
|
+
// the fallback is the endpoint's own schema default.
|
|
2555
|
+
outputLabels: {
|
|
2556
|
+
images: {
|
|
2557
|
+
fallback: ["basecolor", "normal", "roughness", "metalness", "height"],
|
|
2558
|
+
fromOption: "maps"
|
|
2559
|
+
}
|
|
2560
|
+
},
|
|
2561
|
+
price: { kind: "metered" },
|
|
2562
|
+
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",
|
|
2563
|
+
queued: true,
|
|
2564
|
+
sourceUrl: "https://fal.ai/models/fal-ai/patina",
|
|
2565
|
+
task: "PBR material decomposition"
|
|
2566
|
+
},
|
|
2567
|
+
"patina-extract": {
|
|
2568
|
+
category: "material",
|
|
2569
|
+
description: "Extract a tiling PBR material from a prompted region of a photograph.",
|
|
2570
|
+
endpoint: "fal-ai/patina/material/extract",
|
|
2571
|
+
inputField: "image_url",
|
|
2572
|
+
inputKind: "image",
|
|
2573
|
+
name: "Patina Material Extract",
|
|
2574
|
+
outputKeys: ["images"],
|
|
2575
|
+
// Same `maps` option and schema default as fal-ai/patina, both verified.
|
|
2576
|
+
// `num_images` above 1 multiplies the array and breaks the mapping, which
|
|
2577
|
+
// the count check catches.
|
|
2578
|
+
outputLabels: {
|
|
2579
|
+
images: {
|
|
2580
|
+
fallback: ["basecolor", "normal", "roughness", "metalness", "height"],
|
|
2581
|
+
fromOption: "maps"
|
|
2582
|
+
}
|
|
2583
|
+
},
|
|
2584
|
+
price: { kind: "metered" },
|
|
2585
|
+
pricing: "$0.10 base only; add $0.02/megapixel plus $0.01/megapixel per map, so 1MP with all 5 maps is $0.17",
|
|
2586
|
+
queued: true,
|
|
2587
|
+
sourceUrl: "https://fal.ai/models/fal-ai/patina/material/extract",
|
|
2588
|
+
task: "tiling material extraction"
|
|
2589
|
+
},
|
|
2590
|
+
"qwen-layered": {
|
|
2591
|
+
category: "layers",
|
|
2592
|
+
description: "Split an image into a configurable number of stacked RGBA layers.",
|
|
2593
|
+
endpoint: "fal-ai/qwen-image-layered",
|
|
2594
|
+
inputField: "image_url",
|
|
2595
|
+
inputKind: "image",
|
|
2596
|
+
name: "Qwen Image Layered",
|
|
2597
|
+
outputKeys: ["images"],
|
|
2598
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
2599
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
2600
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
2601
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
2602
|
+
// rather than a number that is right only on one reading.
|
|
2603
|
+
price: { kind: "metered" },
|
|
2604
|
+
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",
|
|
2605
|
+
queued: true,
|
|
2606
|
+
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-layered",
|
|
2607
|
+
task: "image layer decomposition"
|
|
2608
|
+
},
|
|
2609
|
+
"recraft-vectorize": {
|
|
2610
|
+
category: "vector",
|
|
2611
|
+
description: "Convert a raster image into a clean SVG.",
|
|
2612
|
+
endpoint: "fal-ai/recraft/vectorize",
|
|
2613
|
+
inputField: "image_url",
|
|
2614
|
+
inputKind: "image",
|
|
2615
|
+
name: "Recraft Vectorize",
|
|
2616
|
+
outputKeys: ["image"],
|
|
2617
|
+
price: { kind: "call", usd: 0.04 },
|
|
2618
|
+
pricing: "$0.04/image, $0.08 with a vector style",
|
|
2619
|
+
sourceUrl: "https://fal.ai/models/fal-ai/recraft/vectorize",
|
|
2620
|
+
task: "raster to vector conversion"
|
|
2621
|
+
},
|
|
2622
|
+
"sam3-3d-align": {
|
|
2623
|
+
category: "3d",
|
|
2624
|
+
description: "Align SAM 3D objects and bodies into a shared scene.",
|
|
2625
|
+
endpoint: "fal-ai/sam-3/3d-align",
|
|
2626
|
+
inputField: "image_url",
|
|
2627
|
+
inputKind: "image",
|
|
2628
|
+
name: "SAM 3D Align",
|
|
2629
|
+
outputKeys: [
|
|
2630
|
+
"scene_glb",
|
|
2631
|
+
"model_glb",
|
|
2632
|
+
"visualization",
|
|
2633
|
+
"body_mesh_ply",
|
|
2634
|
+
"metadata"
|
|
2635
|
+
],
|
|
2636
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
2637
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
2638
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
2639
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
2640
|
+
// rather than a number that is right only on one reading.
|
|
2641
|
+
price: { kind: "metered" },
|
|
2642
|
+
pricing: "$0.02 per unit; fal does not define a unit, so no estimate is reported",
|
|
2643
|
+
queued: true,
|
|
2644
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-align",
|
|
2645
|
+
task: "3D scene alignment"
|
|
2646
|
+
},
|
|
2647
|
+
"sam3-3d-body": {
|
|
2648
|
+
category: "3d",
|
|
2649
|
+
defaultOptions: {
|
|
2650
|
+
export_meshes: true,
|
|
2651
|
+
include_3d_keypoints: true,
|
|
2652
|
+
include_mhr_params: true
|
|
2653
|
+
},
|
|
2654
|
+
description: "Reconstruct human body meshes and keypoints from a single image.",
|
|
2655
|
+
endpoint: "fal-ai/sam-3/3d-body",
|
|
2656
|
+
inputField: "image_url",
|
|
2657
|
+
inputKind: "image",
|
|
2658
|
+
name: "SAM 3D Body",
|
|
2659
|
+
outputKeys: ["model_glb", "visualization", "meshes", "metadata"],
|
|
2660
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
2661
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
2662
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
2663
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
2664
|
+
// rather than a number that is right only on one reading.
|
|
2665
|
+
price: { kind: "metered" },
|
|
2666
|
+
pricing: "$0.02 per unit; fal does not define a unit, so no estimate is reported",
|
|
2667
|
+
queued: true,
|
|
2668
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-body",
|
|
2669
|
+
task: "single-image 3D body reconstruction"
|
|
2670
|
+
},
|
|
2671
|
+
"sam3-3d-objects": {
|
|
2672
|
+
category: "3d",
|
|
2673
|
+
defaultOptions: {
|
|
2674
|
+
prompt: "car"
|
|
2675
|
+
},
|
|
2676
|
+
description: "Reconstruct one or more 3D objects from an image and prompts.",
|
|
2677
|
+
endpoint: "fal-ai/sam-3/3d-objects",
|
|
2678
|
+
inputField: "image_url",
|
|
2679
|
+
inputKind: "image",
|
|
2680
|
+
name: "SAM 3D Objects",
|
|
2681
|
+
outputKeys: [
|
|
2682
|
+
"gaussian_splat",
|
|
2683
|
+
"model_glb",
|
|
2684
|
+
"metadata",
|
|
2685
|
+
"individual_splats",
|
|
2686
|
+
"individual_glbs",
|
|
2687
|
+
"artifacts_zip"
|
|
2688
|
+
],
|
|
2689
|
+
// fal publishes a figure but not what it counts. Encoding it as `call`
|
|
2690
|
+
// would assert a per-request price we cannot support, and this endpoint
|
|
2691
|
+
// returns several outputs — the same shape that made `seedream-layerize`
|
|
2692
|
+
// under-report by a factor of its layer count. `metered` reports null
|
|
2693
|
+
// rather than a number that is right only on one reading.
|
|
2694
|
+
price: { kind: "metered" },
|
|
2695
|
+
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",
|
|
2696
|
+
queued: true,
|
|
2697
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-objects",
|
|
2698
|
+
task: "single-image 3D object reconstruction"
|
|
2699
|
+
},
|
|
2700
|
+
"seedream-layerize": {
|
|
2701
|
+
category: "layers",
|
|
2702
|
+
description: "Split an image into editable Seedream layers plus flattened previews.",
|
|
2703
|
+
endpoint: "bytedance/seedream/v5/pro/layerize",
|
|
2704
|
+
inputField: "image_url",
|
|
2705
|
+
inputKind: "image",
|
|
2706
|
+
name: "Seedream v5 Pro Layerize",
|
|
2707
|
+
outputKeys: ["layers", "images"],
|
|
2708
|
+
// Every element of `layers` carries its own `name` ("Left amber glass
|
|
2709
|
+
// bottle") and a `z_index` that orders the stack, verified live. Without
|
|
2710
|
+
// this the stack lands as layers.png … layers-5.png and the only way to
|
|
2711
|
+
// tell the reconstructed background plate from an object is to open them.
|
|
2712
|
+
outputLabels: {
|
|
2713
|
+
layers: { fromItem: { nameField: "name", orderField: "z_index" } }
|
|
2714
|
+
},
|
|
2715
|
+
price: { kind: "metered" },
|
|
2716
|
+
pricing: "$0.03375 per generated layer below 1536x1536 total area, $0.0675 per layer above; the listed rate is per layer, not per call",
|
|
2717
|
+
queued: true,
|
|
2718
|
+
sourceUrl: "https://fal.ai/models/bytedance/seedream/v5/pro/layerize",
|
|
2719
|
+
task: "image layer decomposition"
|
|
2720
|
+
},
|
|
2721
|
+
"seedvr-seamless": {
|
|
2722
|
+
category: "material",
|
|
2723
|
+
description: "Upscale a tiling texture while keeping its edges seamless. ",
|
|
2724
|
+
endpoint: "fal-ai/seedvr/upscale/image/seamless",
|
|
2725
|
+
inputField: "image_url",
|
|
2726
|
+
inputKind: "image",
|
|
2727
|
+
name: "SeedVR Seamless Upscale",
|
|
2728
|
+
outputKeys: ["image"],
|
|
2729
|
+
price: { kind: "megapixel", usd: 25e-4 },
|
|
2730
|
+
pricing: "$0.0025/megapixel",
|
|
2731
|
+
queued: true,
|
|
2732
|
+
sourceUrl: "https://fal.ai/models/fal-ai/seedvr/upscale/image/seamless",
|
|
2733
|
+
task: "seamless texture upscaling"
|
|
2734
|
+
},
|
|
2735
|
+
"trellis-2": {
|
|
2736
|
+
category: "3d",
|
|
2737
|
+
description: "Reconstruct a textured 3D mesh from a single image, with UV unwrapping.",
|
|
2738
|
+
endpoint: "fal-ai/trellis-2",
|
|
2739
|
+
inputField: "image_url",
|
|
2740
|
+
inputKind: "image",
|
|
2741
|
+
name: "TRELLIS 2",
|
|
2742
|
+
outputKeys: ["model_glb"],
|
|
2743
|
+
price: { kind: "call", usd: 0.3 },
|
|
2744
|
+
pricing: "$0.30 at the default 1024p; $0.25 at 512p, $0.35 at 1536p",
|
|
2745
|
+
queued: true,
|
|
2746
|
+
sourceUrl: "https://fal.ai/models/fal-ai/trellis-2",
|
|
2747
|
+
task: "single-image 3D reconstruction"
|
|
2748
|
+
}
|
|
2749
|
+
};
|
|
2750
|
+
|
|
2751
|
+
// src/tool-registry/background.ts
|
|
2752
|
+
var BACKGROUND_TOOLS = {
|
|
2753
|
+
"ben-v2": {
|
|
2754
|
+
category: "background",
|
|
2755
|
+
description: "Fast, high-quality background removal for images.",
|
|
2756
|
+
endpoint: "fal-ai/ben/v2/image",
|
|
2757
|
+
inputField: "image_url",
|
|
2758
|
+
inputKind: "image",
|
|
2759
|
+
name: "BEN v2 Background Removal",
|
|
2760
|
+
outputKeys: ["image"],
|
|
2761
|
+
price: { kind: "megapixel", usd: 0.025 },
|
|
2762
|
+
pricing: "$0.025/megapixel",
|
|
2763
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ben/v2/image",
|
|
2764
|
+
task: "image background removal"
|
|
2765
|
+
},
|
|
2295
2766
|
birefnet: {
|
|
2296
2767
|
category: "background",
|
|
2297
2768
|
defaultOptions: {
|
|
@@ -2306,6 +2777,7 @@ var FAL_TOOLS = {
|
|
|
2306
2777
|
inputKind: "image",
|
|
2307
2778
|
name: "BirefNet Background Removal",
|
|
2308
2779
|
outputKeys: ["image", "mask_image"],
|
|
2780
|
+
price: { kind: "metered" },
|
|
2309
2781
|
pricing: "$0/compute-second listed by fal",
|
|
2310
2782
|
sourceUrl: "https://fal.ai/models/fal-ai/birefnet/v2",
|
|
2311
2783
|
task: "image background removal"
|
|
@@ -2318,7 +2790,8 @@ var FAL_TOOLS = {
|
|
|
2318
2790
|
inputKind: "image",
|
|
2319
2791
|
name: "Bria RMBG 2.0",
|
|
2320
2792
|
outputKeys: ["image"],
|
|
2321
|
-
|
|
2793
|
+
price: { kind: "call", usd: 0.018 },
|
|
2794
|
+
pricing: "$0.018/generation",
|
|
2322
2795
|
sourceUrl: "https://fal.ai/models/fal-ai/bria/background/remove",
|
|
2323
2796
|
task: "image background removal"
|
|
2324
2797
|
},
|
|
@@ -2335,10 +2808,422 @@ var FAL_TOOLS = {
|
|
|
2335
2808
|
inputKind: "video",
|
|
2336
2809
|
name: "Bria Video Background Removal",
|
|
2337
2810
|
outputKeys: ["video"],
|
|
2338
|
-
|
|
2811
|
+
price: { kind: "second", usd: 425e-5 },
|
|
2812
|
+
pricing: "$0.00425/sec",
|
|
2813
|
+
queued: true,
|
|
2339
2814
|
sourceUrl: "https://fal.ai/models/bria/video/background-removal",
|
|
2340
2815
|
task: "video background removal"
|
|
2341
2816
|
},
|
|
2817
|
+
ddcolor: {
|
|
2818
|
+
category: "restoration",
|
|
2819
|
+
description: "Colourise black-and-white photographs.",
|
|
2820
|
+
endpoint: "fal-ai/ddcolor",
|
|
2821
|
+
inputField: "image_url",
|
|
2822
|
+
inputKind: "image",
|
|
2823
|
+
name: "DDColor Colourisation",
|
|
2824
|
+
outputKeys: ["image"],
|
|
2825
|
+
price: { kind: "megapixel", usd: 1e-3 },
|
|
2826
|
+
pricing: "$0.001/megapixel",
|
|
2827
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ddcolor",
|
|
2828
|
+
task: "photo colourisation"
|
|
2829
|
+
},
|
|
2830
|
+
rembg: {
|
|
2831
|
+
category: "background",
|
|
2832
|
+
defaultOptions: {
|
|
2833
|
+
crop_to_bbox: false
|
|
2834
|
+
},
|
|
2835
|
+
description: "Generic image background removal utility.",
|
|
2836
|
+
endpoint: "fal-ai/imageutils/rembg",
|
|
2837
|
+
inputField: "image_url",
|
|
2838
|
+
inputKind: "image",
|
|
2839
|
+
name: "Remove Background",
|
|
2840
|
+
outputKeys: ["image"],
|
|
2841
|
+
price: { kind: "metered" },
|
|
2842
|
+
pricing: "$0/compute-second listed by fal",
|
|
2843
|
+
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/rembg",
|
|
2844
|
+
task: "image background removal"
|
|
2845
|
+
},
|
|
2846
|
+
"seedvr-upscale": {
|
|
2847
|
+
category: "restoration",
|
|
2848
|
+
defaultOptions: {
|
|
2849
|
+
output_format: "png"
|
|
2850
|
+
},
|
|
2851
|
+
description: "Diffusion image restoration and upscaling with SeedVR.",
|
|
2852
|
+
endpoint: "fal-ai/seedvr/upscale/image",
|
|
2853
|
+
inputField: "image_url",
|
|
2854
|
+
inputKind: "image",
|
|
2855
|
+
name: "SeedVR Image Upscale",
|
|
2856
|
+
outputKeys: ["image"],
|
|
2857
|
+
price: { kind: "megapixel", usd: 1e-3 },
|
|
2858
|
+
pricing: "$0.001/megapixel",
|
|
2859
|
+
queued: true,
|
|
2860
|
+
sourceUrl: "https://fal.ai/models/fal-ai/seedvr/upscale/image",
|
|
2861
|
+
task: "image restoration and upscaling"
|
|
2862
|
+
},
|
|
2863
|
+
"topaz-adjust": {
|
|
2864
|
+
category: "restoration",
|
|
2865
|
+
defaultOptions: {
|
|
2866
|
+
output_format: "png"
|
|
2867
|
+
},
|
|
2868
|
+
description: "Topaz exposure, white balance, and colour adjustment.",
|
|
2869
|
+
endpoint: "topaz/adjust/image",
|
|
2870
|
+
inputField: "image_url",
|
|
2871
|
+
inputKind: "image",
|
|
2872
|
+
name: "Topaz Adjust",
|
|
2873
|
+
outputKeys: ["image"],
|
|
2874
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
2875
|
+
pricing: "$0.08 per 24 output megapixels",
|
|
2876
|
+
queued: true,
|
|
2877
|
+
sourceUrl: "https://fal.ai/models/topaz/adjust/image",
|
|
2878
|
+
task: "tonal adjustment"
|
|
2879
|
+
},
|
|
2880
|
+
"topaz-creative": {
|
|
2881
|
+
category: "restoration",
|
|
2882
|
+
defaultOptions: {
|
|
2883
|
+
output_format: "png"
|
|
2884
|
+
},
|
|
2885
|
+
description: "Topaz Bloom upscaling, which reimagines detail rather than preserving it.",
|
|
2886
|
+
endpoint: "topaz/upscale/image/creative",
|
|
2887
|
+
inputField: "image_url",
|
|
2888
|
+
inputKind: "image",
|
|
2889
|
+
name: "Topaz Creative Upscale",
|
|
2890
|
+
outputKeys: ["image"],
|
|
2891
|
+
price: { kind: "megapixel", usd: 0.96 / 24 },
|
|
2892
|
+
pricing: "$0.96 per 24 output megapixels",
|
|
2893
|
+
queued: true,
|
|
2894
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/creative",
|
|
2895
|
+
task: "creative image upscaling"
|
|
2896
|
+
},
|
|
2897
|
+
"topaz-denoise": {
|
|
2898
|
+
category: "restoration",
|
|
2899
|
+
defaultOptions: {
|
|
2900
|
+
output_format: "png"
|
|
2901
|
+
},
|
|
2902
|
+
description: "Topaz noise reduction at source resolution.",
|
|
2903
|
+
endpoint: "topaz/denoise/image",
|
|
2904
|
+
inputField: "image_url",
|
|
2905
|
+
inputKind: "image",
|
|
2906
|
+
name: "Topaz Denoise",
|
|
2907
|
+
outputKeys: ["image"],
|
|
2908
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
2909
|
+
pricing: "$0.08 per 24 output megapixels at the default Normal model; $0.16 with Denoise Max",
|
|
2910
|
+
queued: true,
|
|
2911
|
+
sourceUrl: "https://fal.ai/models/topaz/denoise/image",
|
|
2912
|
+
task: "image denoising"
|
|
2913
|
+
},
|
|
2914
|
+
"topaz-generative": {
|
|
2915
|
+
category: "restoration",
|
|
2916
|
+
defaultOptions: {
|
|
2917
|
+
output_format: "png"
|
|
2918
|
+
},
|
|
2919
|
+
description: "Topaz Wonder upscaling, which synthesises plausible detail as it enlarges.",
|
|
2920
|
+
endpoint: "topaz/upscale/image/generative",
|
|
2921
|
+
inputField: "image_url",
|
|
2922
|
+
inputKind: "image",
|
|
2923
|
+
name: "Topaz Generative Upscale",
|
|
2924
|
+
outputKeys: ["image"],
|
|
2925
|
+
price: { kind: "megapixel", usd: 0.24 / 24 },
|
|
2926
|
+
pricing: "$0.24 per 24 output megapixels at the default Wonder 3; $0.48 with Wonder, Wonder 2, Standard MAX, Redefine or Recover 3",
|
|
2927
|
+
queued: true,
|
|
2928
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/generative",
|
|
2929
|
+
task: "generative image upscaling"
|
|
2930
|
+
},
|
|
2931
|
+
"topaz-image": {
|
|
2932
|
+
category: "upscale",
|
|
2933
|
+
defaultOptions: {
|
|
2934
|
+
model: "Standard V2",
|
|
2935
|
+
output_format: "jpeg",
|
|
2936
|
+
upscale_factor: 2
|
|
2937
|
+
},
|
|
2938
|
+
description: "Professional Topaz image enhancement and upscaling.",
|
|
2939
|
+
endpoint: "fal-ai/topaz/upscale/image",
|
|
2940
|
+
inputField: "image_url",
|
|
2941
|
+
inputKind: "image",
|
|
2942
|
+
name: "Topaz Image Upscale",
|
|
2943
|
+
outputKeys: ["image"],
|
|
2944
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
2945
|
+
pricing: "$0.08 for output up to 24MP; $0.16 to 48MP, $0.32 to 96MP, up to $1.36 at 512MP",
|
|
2946
|
+
queued: true,
|
|
2947
|
+
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/image",
|
|
2948
|
+
task: "image enhancement"
|
|
2949
|
+
},
|
|
2950
|
+
"topaz-precision": {
|
|
2951
|
+
category: "restoration",
|
|
2952
|
+
defaultOptions: {
|
|
2953
|
+
output_format: "png"
|
|
2954
|
+
},
|
|
2955
|
+
description: "Topaz upscaling that preserves the original detail rather than inventing it.",
|
|
2956
|
+
endpoint: "topaz/upscale/image/precision",
|
|
2957
|
+
inputField: "image_url",
|
|
2958
|
+
inputKind: "image",
|
|
2959
|
+
name: "Topaz Precision Upscale",
|
|
2960
|
+
outputKeys: ["image"],
|
|
2961
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
2962
|
+
pricing: "$0.08 per 24 output megapixels, any precision model",
|
|
2963
|
+
queued: true,
|
|
2964
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/precision",
|
|
2965
|
+
task: "faithful image upscaling"
|
|
2966
|
+
},
|
|
2967
|
+
"topaz-restore": {
|
|
2968
|
+
category: "restoration",
|
|
2969
|
+
defaultOptions: {
|
|
2970
|
+
output_format: "png"
|
|
2971
|
+
},
|
|
2972
|
+
description: "Topaz restoration of damaged or degraded photographs at source resolution.",
|
|
2973
|
+
endpoint: "topaz/restore/image",
|
|
2974
|
+
inputField: "image_url",
|
|
2975
|
+
inputKind: "image",
|
|
2976
|
+
name: "Topaz Restore",
|
|
2977
|
+
outputKeys: ["image"],
|
|
2978
|
+
price: { kind: "megapixel", usd: 0.48 / 24 },
|
|
2979
|
+
pricing: "$0.48 per 24 output megapixels at the default Recover 3; $0.08 with Dust-Scratch V2",
|
|
2980
|
+
queued: true,
|
|
2981
|
+
sourceUrl: "https://fal.ai/models/topaz/restore/image",
|
|
2982
|
+
task: "photo restoration"
|
|
2983
|
+
},
|
|
2984
|
+
"topaz-sharpen": {
|
|
2985
|
+
category: "restoration",
|
|
2986
|
+
defaultOptions: {
|
|
2987
|
+
output_format: "png"
|
|
2988
|
+
},
|
|
2989
|
+
description: "Topaz deblurring and sharpening at source resolution.",
|
|
2990
|
+
endpoint: "topaz/sharpen/image",
|
|
2991
|
+
inputField: "image_url",
|
|
2992
|
+
inputKind: "image",
|
|
2993
|
+
name: "Topaz Sharpen",
|
|
2994
|
+
outputKeys: ["image"],
|
|
2995
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
2996
|
+
pricing: "$0.08 per 24 output megapixels at the default Standard model; $0.16 with Super Focus",
|
|
2997
|
+
queued: true,
|
|
2998
|
+
sourceUrl: "https://fal.ai/models/topaz/sharpen/image",
|
|
2999
|
+
task: "image sharpening"
|
|
3000
|
+
},
|
|
3001
|
+
"topaz-transparent": {
|
|
3002
|
+
category: "restoration",
|
|
3003
|
+
description: "Topaz upscaling that preserves the alpha channel end to end.",
|
|
3004
|
+
endpoint: "topaz/upscale/image/transparent",
|
|
3005
|
+
inputField: "image_url",
|
|
3006
|
+
inputKind: "image",
|
|
3007
|
+
name: "Topaz Transparent Upscale",
|
|
3008
|
+
outputKeys: ["image"],
|
|
3009
|
+
price: { kind: "megapixel", usd: 0.08 / 24 },
|
|
3010
|
+
pricing: "$0.08 per 24 output megapixels",
|
|
3011
|
+
queued: true,
|
|
3012
|
+
sourceUrl: "https://fal.ai/models/topaz/upscale/image/transparent",
|
|
3013
|
+
task: "transparent image upscaling"
|
|
3014
|
+
},
|
|
3015
|
+
"topaz-video": {
|
|
3016
|
+
category: "upscale",
|
|
3017
|
+
defaultOptions: {
|
|
3018
|
+
model: "Proteus",
|
|
3019
|
+
upscale_factor: 2
|
|
3020
|
+
},
|
|
3021
|
+
description: "Professional Topaz video enhancement and upscaling.",
|
|
3022
|
+
endpoint: "fal-ai/topaz/upscale/video",
|
|
3023
|
+
inputField: "video_url",
|
|
3024
|
+
inputKind: "video",
|
|
3025
|
+
name: "Topaz Video Upscale",
|
|
3026
|
+
outputKeys: ["video"],
|
|
3027
|
+
price: { kind: "second", usd: 0.01 },
|
|
3028
|
+
pricing: "$0.01/sec up to 720p; $0.02 to 1080p, $0.08 above, doubled at 60fps, halved with Gaia 2",
|
|
3029
|
+
queued: true,
|
|
3030
|
+
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/video",
|
|
3031
|
+
task: "video enhancement"
|
|
3032
|
+
}
|
|
3033
|
+
};
|
|
3034
|
+
|
|
3035
|
+
// src/tool-registry/editing.ts
|
|
3036
|
+
var EDITING_TOOLS = {
|
|
3037
|
+
"bria-eraser": {
|
|
3038
|
+
category: "erase",
|
|
3039
|
+
description: "Commercial-safe removal of a masked region, inpainted from surrounding context.",
|
|
3040
|
+
endpoint: "fal-ai/bria/eraser",
|
|
3041
|
+
inputField: "image_url",
|
|
3042
|
+
inputKind: "image",
|
|
3043
|
+
name: "Bria Eraser",
|
|
3044
|
+
outputKeys: ["image"],
|
|
3045
|
+
price: { kind: "call", usd: 0.04 },
|
|
3046
|
+
pricing: "$0.04/generation",
|
|
3047
|
+
sourceUrl: "https://fal.ai/models/fal-ai/bria/eraser",
|
|
3048
|
+
task: "masked object erasure"
|
|
3049
|
+
},
|
|
3050
|
+
"bria-expand": {
|
|
3051
|
+
category: "reframe",
|
|
3052
|
+
description: "Expand an image onto a larger canvas, generating the new border area.",
|
|
3053
|
+
endpoint: "fal-ai/bria/expand",
|
|
3054
|
+
inputField: "image_url",
|
|
3055
|
+
inputKind: "image",
|
|
3056
|
+
name: "Bria Image Expansion",
|
|
3057
|
+
outputKeys: ["image"],
|
|
3058
|
+
price: { kind: "call", usd: 0.04 },
|
|
3059
|
+
pricing: "$0.04/generation",
|
|
3060
|
+
sourceUrl: "https://fal.ai/models/fal-ai/bria/expand",
|
|
3061
|
+
task: "image outpainting"
|
|
3062
|
+
},
|
|
3063
|
+
"bria-genfill": {
|
|
3064
|
+
category: "erase",
|
|
3065
|
+
description: "Generative fill of a masked region from a prompt, commercial-safe.",
|
|
3066
|
+
endpoint: "fal-ai/bria/genfill",
|
|
3067
|
+
inputField: "image_url",
|
|
3068
|
+
inputKind: "image",
|
|
3069
|
+
name: "Bria GenFill",
|
|
3070
|
+
outputKeys: ["images"],
|
|
3071
|
+
price: { kind: "call", usd: 0.04 },
|
|
3072
|
+
pricing: "$0.04/generation",
|
|
3073
|
+
sourceUrl: "https://fal.ai/models/fal-ai/bria/genfill",
|
|
3074
|
+
task: "masked generative fill"
|
|
3075
|
+
},
|
|
3076
|
+
"finegrain-eraser": {
|
|
3077
|
+
category: "erase",
|
|
3078
|
+
description: "Remove a prompted object and its shadows and reflections, filling the gap.",
|
|
3079
|
+
endpoint: "fal-ai/finegrain-eraser",
|
|
3080
|
+
inputField: "image_url",
|
|
3081
|
+
inputKind: "image",
|
|
3082
|
+
name: "Finegrain Object Eraser",
|
|
3083
|
+
outputKeys: ["image"],
|
|
3084
|
+
price: { kind: "call", usd: 0.27 },
|
|
3085
|
+
pricing: "$0.27/image at the default standard mode; $0.18 express, $0.36 premium",
|
|
3086
|
+
sourceUrl: "https://fal.ai/models/fal-ai/finegrain-eraser",
|
|
3087
|
+
task: "prompted object erasure"
|
|
3088
|
+
},
|
|
3089
|
+
"flux-outpaint": {
|
|
3090
|
+
category: "reframe",
|
|
3091
|
+
description: "Outpaint an image by a per-edge pixel expansion with FLUX.2 pro.",
|
|
3092
|
+
endpoint: "fal-ai/flux-2-pro/outpaint",
|
|
3093
|
+
inputField: "image_url",
|
|
3094
|
+
inputKind: "image",
|
|
3095
|
+
name: "FLUX.2 Pro Outpaint",
|
|
3096
|
+
outputKeys: ["images"],
|
|
3097
|
+
price: { kind: "metered" },
|
|
3098
|
+
pricing: "$0.03 for the first output megapixel, then $0.015 per extra megapixel of input and output, rounded up",
|
|
3099
|
+
sourceUrl: "https://fal.ai/models/fal-ai/flux-2-pro/outpaint",
|
|
3100
|
+
task: "image outpainting"
|
|
3101
|
+
},
|
|
3102
|
+
"iclight-v2": {
|
|
3103
|
+
category: "relight",
|
|
3104
|
+
description: "Relight a subject from a prompt, harmonising it with a new light direction.",
|
|
3105
|
+
endpoint: "fal-ai/iclight-v2",
|
|
3106
|
+
inputField: "image_url",
|
|
3107
|
+
inputKind: "image",
|
|
3108
|
+
name: "IC-Light v2",
|
|
3109
|
+
outputKeys: ["images"],
|
|
3110
|
+
price: { kind: "megapixel", usd: 0.1 },
|
|
3111
|
+
pricing: "$0.10/megapixel",
|
|
3112
|
+
sourceUrl: "https://fal.ai/models/fal-ai/iclight-v2",
|
|
3113
|
+
task: "prompted relighting"
|
|
3114
|
+
},
|
|
3115
|
+
"ideogram-reframe": {
|
|
3116
|
+
category: "reframe",
|
|
3117
|
+
description: "Reframe an image to a new aspect ratio, generating the fill.",
|
|
3118
|
+
endpoint: "fal-ai/ideogram/v3/reframe",
|
|
3119
|
+
inputField: "image_url",
|
|
3120
|
+
inputKind: "image",
|
|
3121
|
+
name: "Ideogram v3 Reframe",
|
|
3122
|
+
outputKeys: ["images"],
|
|
3123
|
+
price: { kind: "call", usd: 0.06 },
|
|
3124
|
+
pricing: "$0.06/image at the default BALANCED speed; $0.03 turbo, $0.09 quality",
|
|
3125
|
+
sourceUrl: "https://fal.ai/models/fal-ai/ideogram/v3/reframe",
|
|
3126
|
+
task: "aspect ratio reframing"
|
|
3127
|
+
},
|
|
3128
|
+
"lighting-restoration": {
|
|
3129
|
+
category: "relight",
|
|
3130
|
+
description: "Restore natural, even lighting across one or more input images.",
|
|
3131
|
+
endpoint: "fal-ai/qwen-image-edit-plus-lora-gallery/lighting-restoration",
|
|
3132
|
+
inputField: "image_urls",
|
|
3133
|
+
inputKind: "images",
|
|
3134
|
+
name: "Qwen Lighting Restoration",
|
|
3135
|
+
outputKeys: ["images"],
|
|
3136
|
+
price: { kind: "megapixel", usd: 0.035 },
|
|
3137
|
+
pricing: "$0.035/megapixel",
|
|
3138
|
+
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-edit-plus-lora-gallery/lighting-restoration",
|
|
3139
|
+
task: "lighting restoration"
|
|
3140
|
+
},
|
|
3141
|
+
"object-removal": {
|
|
3142
|
+
category: "erase",
|
|
3143
|
+
description: "Remove a prompted object from an image and fill the gap.",
|
|
3144
|
+
endpoint: "fal-ai/object-removal",
|
|
3145
|
+
inputField: "image_url",
|
|
3146
|
+
inputKind: "image",
|
|
3147
|
+
name: "Object Removal",
|
|
3148
|
+
outputKeys: ["images"],
|
|
3149
|
+
price: { kind: "call", usd: 0.024 },
|
|
3150
|
+
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
3151
|
+
sourceUrl: "https://fal.ai/models/fal-ai/object-removal",
|
|
3152
|
+
task: "prompted object removal"
|
|
3153
|
+
},
|
|
3154
|
+
"object-removal-bbox": {
|
|
3155
|
+
category: "erase",
|
|
3156
|
+
description: "Remove whatever falls inside supplied bounding boxes.",
|
|
3157
|
+
endpoint: "fal-ai/object-removal/bbox",
|
|
3158
|
+
inputField: "image_url",
|
|
3159
|
+
inputKind: "image",
|
|
3160
|
+
name: "Object Removal by Box",
|
|
3161
|
+
outputKeys: ["images"],
|
|
3162
|
+
price: { kind: "call", usd: 0.024 },
|
|
3163
|
+
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
3164
|
+
sourceUrl: "https://fal.ai/models/fal-ai/object-removal/bbox",
|
|
3165
|
+
task: "bounding box object removal"
|
|
3166
|
+
},
|
|
3167
|
+
"object-removal-mask": {
|
|
3168
|
+
category: "erase",
|
|
3169
|
+
description: "Remove the masked region of an image and fill the gap.",
|
|
3170
|
+
endpoint: "fal-ai/object-removal/mask",
|
|
3171
|
+
inputField: "image_url",
|
|
3172
|
+
inputKind: "image",
|
|
3173
|
+
name: "Object Removal by Mask",
|
|
3174
|
+
outputKeys: ["images"],
|
|
3175
|
+
price: { kind: "call", usd: 0.024 },
|
|
3176
|
+
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
3177
|
+
sourceUrl: "https://fal.ai/models/fal-ai/object-removal/mask",
|
|
3178
|
+
task: "masked object removal"
|
|
3179
|
+
},
|
|
3180
|
+
"remove-lighting": {
|
|
3181
|
+
category: "relight",
|
|
3182
|
+
description: "Strip baked-in lighting and shadows to leave a flat, neutral surface.",
|
|
3183
|
+
endpoint: "fal-ai/qwen-image-edit-plus-lora-gallery/remove-lighting",
|
|
3184
|
+
inputField: "image_urls",
|
|
3185
|
+
inputKind: "images",
|
|
3186
|
+
name: "Qwen Remove Lighting",
|
|
3187
|
+
outputKeys: ["images"],
|
|
3188
|
+
price: { kind: "megapixel", usd: 0.035 },
|
|
3189
|
+
pricing: "$0.035/megapixel",
|
|
3190
|
+
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-edit-plus-lora-gallery/remove-lighting",
|
|
3191
|
+
task: "lighting removal"
|
|
3192
|
+
},
|
|
3193
|
+
"smart-resize": {
|
|
3194
|
+
category: "reframe",
|
|
3195
|
+
description: "Resize one image to several target sizes, recomposing rather than cropping.",
|
|
3196
|
+
endpoint: "fal-ai/smart-resize",
|
|
3197
|
+
inputField: "image_url",
|
|
3198
|
+
inputKind: "image",
|
|
3199
|
+
name: "Smart Resize",
|
|
3200
|
+
outputKeys: ["images", "results"],
|
|
3201
|
+
price: { kind: "metered" },
|
|
3202
|
+
pricing: "$0.15 per output image, doubled at 4K, plus a $0.05 vision analysis fee per request",
|
|
3203
|
+
queued: true,
|
|
3204
|
+
sourceUrl: "https://fal.ai/models/fal-ai/smart-resize",
|
|
3205
|
+
task: "multi-size recomposition"
|
|
3206
|
+
},
|
|
3207
|
+
"text-removal": {
|
|
3208
|
+
category: "erase",
|
|
3209
|
+
defaultOptions: {
|
|
3210
|
+
output_format: "png"
|
|
3211
|
+
},
|
|
3212
|
+
description: "Remove all rendered text from an image, rebuilding what sat behind it.",
|
|
3213
|
+
endpoint: "fal-ai/image-editing/text-removal",
|
|
3214
|
+
inputField: "image_url",
|
|
3215
|
+
inputKind: "image",
|
|
3216
|
+
name: "Text Removal",
|
|
3217
|
+
outputKeys: ["images"],
|
|
3218
|
+
price: { kind: "call", usd: 0.04 },
|
|
3219
|
+
pricing: "$0.04/image",
|
|
3220
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-editing/text-removal",
|
|
3221
|
+
task: "text removal"
|
|
3222
|
+
}
|
|
3223
|
+
};
|
|
3224
|
+
|
|
3225
|
+
// src/tool-registry/structure.ts
|
|
3226
|
+
var STRUCTURE_TOOLS = {
|
|
2342
3227
|
"depth-anything": {
|
|
2343
3228
|
category: "preprocess",
|
|
2344
3229
|
description: "Generate Depth Anything v2 depth maps from input images.",
|
|
@@ -2347,10 +3232,37 @@ var FAL_TOOLS = {
|
|
|
2347
3232
|
inputKind: "image",
|
|
2348
3233
|
name: "Depth Anything v2 Preprocessor",
|
|
2349
3234
|
outputKeys: ["image"],
|
|
3235
|
+
price: { kind: "metered" },
|
|
2350
3236
|
pricing: "$0/compute-second listed by fal",
|
|
2351
3237
|
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/depth-anything/v2",
|
|
2352
3238
|
task: "depth preprocessing"
|
|
2353
3239
|
},
|
|
3240
|
+
dwpose: {
|
|
3241
|
+
category: "preprocess",
|
|
3242
|
+
description: "Extract body, hand, and face pose skeletons from an image.",
|
|
3243
|
+
endpoint: "fal-ai/dwpose",
|
|
3244
|
+
inputField: "image_url",
|
|
3245
|
+
inputKind: "image",
|
|
3246
|
+
name: "DWPose Estimation",
|
|
3247
|
+
outputKeys: ["image"],
|
|
3248
|
+
price: { kind: "second", usd: 6e-4 },
|
|
3249
|
+
pricing: "$0.0006/compute-second",
|
|
3250
|
+
sourceUrl: "https://fal.ai/models/fal-ai/dwpose",
|
|
3251
|
+
task: "pose preprocessing"
|
|
3252
|
+
},
|
|
3253
|
+
hed: {
|
|
3254
|
+
category: "preprocess",
|
|
3255
|
+
description: "Generate HED soft edge maps for ControlNet-style workflows.",
|
|
3256
|
+
endpoint: "fal-ai/image-preprocessors/hed",
|
|
3257
|
+
inputField: "image_url",
|
|
3258
|
+
inputKind: "image",
|
|
3259
|
+
name: "HED Edge Preprocessor",
|
|
3260
|
+
outputKeys: ["image"],
|
|
3261
|
+
price: { kind: "metered" },
|
|
3262
|
+
pricing: "$0/compute-second listed by fal",
|
|
3263
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/hed",
|
|
3264
|
+
task: "edge preprocessing"
|
|
3265
|
+
},
|
|
2354
3266
|
lineart: {
|
|
2355
3267
|
category: "preprocess",
|
|
2356
3268
|
defaultOptions: {
|
|
@@ -2362,6 +3274,7 @@ var FAL_TOOLS = {
|
|
|
2362
3274
|
inputKind: "image",
|
|
2363
3275
|
name: "Line Art Preprocessor",
|
|
2364
3276
|
outputKeys: ["image"],
|
|
3277
|
+
price: { kind: "metered" },
|
|
2365
3278
|
pricing: "$0/compute-second listed by fal",
|
|
2366
3279
|
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/lineart",
|
|
2367
3280
|
task: "image preprocessing"
|
|
@@ -2378,6 +3291,7 @@ var FAL_TOOLS = {
|
|
|
2378
3291
|
inputKind: "image",
|
|
2379
3292
|
name: "Marigold Depth Estimation",
|
|
2380
3293
|
outputKeys: ["image"],
|
|
3294
|
+
price: { kind: "metered" },
|
|
2381
3295
|
pricing: "$0/compute-second listed by fal",
|
|
2382
3296
|
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/marigold-depth",
|
|
2383
3297
|
task: "depth map"
|
|
@@ -2394,6 +3308,7 @@ var FAL_TOOLS = {
|
|
|
2394
3308
|
inputKind: "image",
|
|
2395
3309
|
name: "MiDaS Depth Estimation",
|
|
2396
3310
|
outputKeys: ["image"],
|
|
3311
|
+
price: { kind: "metered" },
|
|
2397
3312
|
pricing: "$0/compute-second listed by fal",
|
|
2398
3313
|
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/depth",
|
|
2399
3314
|
task: "depth map"
|
|
@@ -2406,36 +3321,36 @@ var FAL_TOOLS = {
|
|
|
2406
3321
|
inputKind: "image",
|
|
2407
3322
|
name: "MiDaS Preprocessor",
|
|
2408
3323
|
outputKeys: ["depth_map", "normal_map"],
|
|
3324
|
+
price: { kind: "metered" },
|
|
2409
3325
|
pricing: "$0/compute-second listed by fal",
|
|
2410
3326
|
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/midas",
|
|
2411
3327
|
task: "depth and normal preprocessing"
|
|
2412
3328
|
},
|
|
2413
|
-
|
|
2414
|
-
category: "
|
|
2415
|
-
description: "
|
|
2416
|
-
endpoint: "fal-ai/
|
|
2417
|
-
inputField: "
|
|
2418
|
-
inputKind: "
|
|
2419
|
-
name: "
|
|
2420
|
-
outputKeys: ["
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
3329
|
+
mlsd: {
|
|
3330
|
+
category: "preprocess",
|
|
3331
|
+
description: "Detect straight line segments for architectural and interior control maps.",
|
|
3332
|
+
endpoint: "fal-ai/image-preprocessors/mlsd",
|
|
3333
|
+
inputField: "image_url",
|
|
3334
|
+
inputKind: "image",
|
|
3335
|
+
name: "M-LSD Line Preprocessor",
|
|
3336
|
+
outputKeys: ["image"],
|
|
3337
|
+
price: { kind: "metered" },
|
|
3338
|
+
pricing: "$0/compute-second listed by fal",
|
|
3339
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/mlsd",
|
|
3340
|
+
task: "line segment preprocessing"
|
|
2424
3341
|
},
|
|
2425
|
-
|
|
2426
|
-
category: "
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
},
|
|
2430
|
-
description: "Generic image background removal utility.",
|
|
2431
|
-
endpoint: "fal-ai/imageutils/rembg",
|
|
3342
|
+
pidi: {
|
|
3343
|
+
category: "preprocess",
|
|
3344
|
+
description: "Generate PiDiNet soft edge maps from an input image.",
|
|
3345
|
+
endpoint: "fal-ai/image-preprocessors/pidi",
|
|
2432
3346
|
inputField: "image_url",
|
|
2433
3347
|
inputKind: "image",
|
|
2434
|
-
name: "
|
|
3348
|
+
name: "PiDiNet Edge Preprocessor",
|
|
2435
3349
|
outputKeys: ["image"],
|
|
3350
|
+
price: { kind: "metered" },
|
|
2436
3351
|
pricing: "$0/compute-second listed by fal",
|
|
2437
|
-
sourceUrl: "https://fal.ai/models/fal-ai/
|
|
2438
|
-
task: "
|
|
3352
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/pidi",
|
|
3353
|
+
task: "edge preprocessing"
|
|
2439
3354
|
},
|
|
2440
3355
|
"sam-preprocessor": {
|
|
2441
3356
|
category: "preprocess",
|
|
@@ -2445,6 +3360,7 @@ var FAL_TOOLS = {
|
|
|
2445
3360
|
inputKind: "image",
|
|
2446
3361
|
name: "SAM Preprocessor",
|
|
2447
3362
|
outputKeys: ["image"],
|
|
3363
|
+
price: { kind: "metered" },
|
|
2448
3364
|
pricing: "$0/compute-second listed by fal",
|
|
2449
3365
|
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/sam",
|
|
2450
3366
|
task: "segmentation preprocessing"
|
|
@@ -2464,7 +3380,9 @@ var FAL_TOOLS = {
|
|
|
2464
3380
|
inputKind: "image",
|
|
2465
3381
|
name: "SAM 2 Auto Segment",
|
|
2466
3382
|
outputKeys: ["combined_mask", "individual_masks"],
|
|
3383
|
+
price: { kind: "metered" },
|
|
2467
3384
|
pricing: "$0/compute-second listed by fal",
|
|
3385
|
+
queued: true,
|
|
2468
3386
|
sourceUrl: "https://fal.ai/models/fal-ai/sam2/auto-segment",
|
|
2469
3387
|
task: "automatic image segmentation"
|
|
2470
3388
|
},
|
|
@@ -2481,7 +3399,8 @@ var FAL_TOOLS = {
|
|
|
2481
3399
|
inputKind: "image",
|
|
2482
3400
|
name: "SAM 3.1 Image",
|
|
2483
3401
|
outputKeys: ["image", "masks", "metadata", "scores", "boxes"],
|
|
2484
|
-
|
|
3402
|
+
price: { kind: "call", usd: 0.01 },
|
|
3403
|
+
pricing: "$0.01/request",
|
|
2485
3404
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/image",
|
|
2486
3405
|
task: "promptable image segmentation"
|
|
2487
3406
|
},
|
|
@@ -2497,61 +3416,12 @@ var FAL_TOOLS = {
|
|
|
2497
3416
|
inputKind: "video",
|
|
2498
3417
|
name: "SAM 3.1 Video",
|
|
2499
3418
|
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2500
|
-
|
|
3419
|
+
price: { kind: "metered" },
|
|
3420
|
+
pricing: "$0.01/16 frames of video input",
|
|
3421
|
+
queued: true,
|
|
2501
3422
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/video",
|
|
2502
3423
|
task: "multi-object video segmentation"
|
|
2503
3424
|
},
|
|
2504
|
-
"sam3-3d-align": {
|
|
2505
|
-
category: "3d",
|
|
2506
|
-
description: "Align SAM 3D objects and bodies into a shared scene.",
|
|
2507
|
-
endpoint: "fal-ai/sam-3/3d-align",
|
|
2508
|
-
inputField: "image_url",
|
|
2509
|
-
inputKind: "image",
|
|
2510
|
-
name: "SAM 3D Align",
|
|
2511
|
-
outputKeys: ["scene_glb", "metadata", "artifacts_zip"],
|
|
2512
|
-
pricing: "fal pricing varies by scene",
|
|
2513
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-align",
|
|
2514
|
-
task: "3D scene alignment"
|
|
2515
|
-
},
|
|
2516
|
-
"sam3-3d-body": {
|
|
2517
|
-
category: "3d",
|
|
2518
|
-
defaultOptions: {
|
|
2519
|
-
export_meshes: true,
|
|
2520
|
-
include_3d_keypoints: true,
|
|
2521
|
-
include_mhr_params: true
|
|
2522
|
-
},
|
|
2523
|
-
description: "Reconstruct human body meshes and keypoints from a single image.",
|
|
2524
|
-
endpoint: "fal-ai/sam-3/3d-body",
|
|
2525
|
-
inputField: "image_url",
|
|
2526
|
-
inputKind: "image",
|
|
2527
|
-
name: "SAM 3D Body",
|
|
2528
|
-
outputKeys: ["model_glb", "visualization", "meshes", "metadata"],
|
|
2529
|
-
pricing: "$0.015/inference",
|
|
2530
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-body",
|
|
2531
|
-
task: "single-image 3D body reconstruction"
|
|
2532
|
-
},
|
|
2533
|
-
"sam3-3d-objects": {
|
|
2534
|
-
category: "3d",
|
|
2535
|
-
defaultOptions: {
|
|
2536
|
-
prompt: "car"
|
|
2537
|
-
},
|
|
2538
|
-
description: "Reconstruct one or more 3D objects from an image and prompts.",
|
|
2539
|
-
endpoint: "fal-ai/sam-3/3d-objects",
|
|
2540
|
-
inputField: "image_url",
|
|
2541
|
-
inputKind: "image",
|
|
2542
|
-
name: "SAM 3D Objects",
|
|
2543
|
-
outputKeys: [
|
|
2544
|
-
"gaussian_splat",
|
|
2545
|
-
"model_glb",
|
|
2546
|
-
"metadata",
|
|
2547
|
-
"individual_splats",
|
|
2548
|
-
"individual_glbs",
|
|
2549
|
-
"artifacts_zip"
|
|
2550
|
-
],
|
|
2551
|
-
pricing: "$0.02/generation",
|
|
2552
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-objects",
|
|
2553
|
-
task: "single-image 3D object reconstruction"
|
|
2554
|
-
},
|
|
2555
3425
|
"sam3-image": {
|
|
2556
3426
|
category: "segmentation",
|
|
2557
3427
|
defaultOptions: {
|
|
@@ -2565,6 +3435,7 @@ var FAL_TOOLS = {
|
|
|
2565
3435
|
inputKind: "image",
|
|
2566
3436
|
name: "SAM 3 Image",
|
|
2567
3437
|
outputKeys: ["image", "masks", "metadata", "scores", "boxes"],
|
|
3438
|
+
price: { kind: "call", usd: 5e-3 },
|
|
2568
3439
|
pricing: "$0.005/request",
|
|
2569
3440
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image",
|
|
2570
3441
|
task: "promptable image segmentation"
|
|
@@ -2580,7 +3451,8 @@ var FAL_TOOLS = {
|
|
|
2580
3451
|
inputField: "image_url",
|
|
2581
3452
|
inputKind: "image",
|
|
2582
3453
|
name: "SAM 3 Image RLE",
|
|
2583
|
-
outputKeys: ["
|
|
3454
|
+
outputKeys: ["rle", "scores", "boxes", "metadata"],
|
|
3455
|
+
price: { kind: "call", usd: 5e-3 },
|
|
2584
3456
|
pricing: "$0.005/request",
|
|
2585
3457
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image-rle",
|
|
2586
3458
|
task: "promptable image segmentation to RLE"
|
|
@@ -2599,7 +3471,9 @@ var FAL_TOOLS = {
|
|
|
2599
3471
|
inputKind: "video",
|
|
2600
3472
|
name: "SAM 3 Video",
|
|
2601
3473
|
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2602
|
-
|
|
3474
|
+
price: { kind: "metered" },
|
|
3475
|
+
pricing: "$0.005/16 frames of video input",
|
|
3476
|
+
queued: true,
|
|
2603
3477
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video",
|
|
2604
3478
|
task: "promptable video segmentation"
|
|
2605
3479
|
},
|
|
@@ -2615,45 +3489,65 @@ var FAL_TOOLS = {
|
|
|
2615
3489
|
inputField: "video_url",
|
|
2616
3490
|
inputKind: "video",
|
|
2617
3491
|
name: "SAM 3 Video RLE",
|
|
2618
|
-
|
|
2619
|
-
|
|
3492
|
+
// fal's video-rle endpoint no longer returns RLE data: its Output schema is
|
|
3493
|
+
// now identical to sam3-video's, so this entry differs only by endpoint.
|
|
3494
|
+
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
3495
|
+
price: { kind: "metered" },
|
|
3496
|
+
pricing: "$0.005/16 frames of video",
|
|
3497
|
+
queued: true,
|
|
2620
3498
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video-rle",
|
|
2621
3499
|
task: "promptable video segmentation to RLE"
|
|
2622
3500
|
},
|
|
2623
|
-
|
|
2624
|
-
category: "
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
output_format: "jpeg",
|
|
2628
|
-
upscale_factor: 2
|
|
2629
|
-
},
|
|
2630
|
-
description: "Professional Topaz image enhancement and upscaling.",
|
|
2631
|
-
endpoint: "fal-ai/topaz/upscale/image",
|
|
3501
|
+
scribble: {
|
|
3502
|
+
category: "preprocess",
|
|
3503
|
+
description: "Turn an image into a scribble-style control map.",
|
|
3504
|
+
endpoint: "fal-ai/image-preprocessors/scribble",
|
|
2632
3505
|
inputField: "image_url",
|
|
2633
3506
|
inputKind: "image",
|
|
2634
|
-
name: "
|
|
3507
|
+
name: "Scribble Preprocessor",
|
|
2635
3508
|
outputKeys: ["image"],
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
3509
|
+
price: { kind: "metered" },
|
|
3510
|
+
pricing: "$0/compute-second listed by fal",
|
|
3511
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/scribble",
|
|
3512
|
+
task: "scribble preprocessing"
|
|
2639
3513
|
},
|
|
2640
|
-
|
|
2641
|
-
category: "
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
3514
|
+
teed: {
|
|
3515
|
+
category: "preprocess",
|
|
3516
|
+
description: "Generate TEED edge maps from an input image.",
|
|
3517
|
+
endpoint: "fal-ai/image-preprocessors/teed",
|
|
3518
|
+
inputField: "image_url",
|
|
3519
|
+
inputKind: "image",
|
|
3520
|
+
name: "TEED Edge Preprocessor",
|
|
3521
|
+
outputKeys: ["image"],
|
|
3522
|
+
price: { kind: "metered" },
|
|
3523
|
+
pricing: "$0/compute-second listed by fal",
|
|
3524
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/teed",
|
|
3525
|
+
task: "edge preprocessing"
|
|
3526
|
+
},
|
|
3527
|
+
"zoe-depth": {
|
|
3528
|
+
category: "preprocess",
|
|
3529
|
+
description: "Generate ZoeDepth metric depth maps from an input image.",
|
|
3530
|
+
endpoint: "fal-ai/image-preprocessors/zoe",
|
|
3531
|
+
inputField: "image_url",
|
|
3532
|
+
inputKind: "image",
|
|
3533
|
+
name: "ZoeDepth Preprocessor",
|
|
3534
|
+
outputKeys: ["image"],
|
|
3535
|
+
price: { kind: "metered" },
|
|
3536
|
+
pricing: "$0/compute-second listed by fal",
|
|
3537
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/zoe",
|
|
3538
|
+
task: "depth preprocessing"
|
|
2655
3539
|
}
|
|
2656
3540
|
};
|
|
3541
|
+
|
|
3542
|
+
// src/tools.ts
|
|
3543
|
+
var FAL_EXPLORE_CHECKED_AT = "2026-08-23";
|
|
3544
|
+
var FAL_TOOLS = {
|
|
3545
|
+
...ANALYSIS_TOOLS,
|
|
3546
|
+
...ASSET_TOOLS,
|
|
3547
|
+
...BACKGROUND_TOOLS,
|
|
3548
|
+
...EDITING_TOOLS,
|
|
3549
|
+
...STRUCTURE_TOOLS
|
|
3550
|
+
};
|
|
2657
3551
|
var FAL_TOOLS_CHECKED_AT = FAL_EXPLORE_CHECKED_AT;
|
|
2658
3552
|
var FAL_TOOL_IDS = Object.keys(
|
|
2659
3553
|
FAL_TOOLS
|
|
@@ -2680,9 +3574,110 @@ function buildFalToolRequest(options) {
|
|
|
2680
3574
|
return { body, endpoint: tool.endpoint, tool };
|
|
2681
3575
|
}
|
|
2682
3576
|
|
|
2683
|
-
// src/server.ts
|
|
3577
|
+
// src/server-tools.ts
|
|
2684
3578
|
var FAL_BASE_URL = "https://fal.run";
|
|
2685
3579
|
var FAL_QUEUE_URL = "https://queue.fal.run";
|
|
3580
|
+
var POLL_INTERVAL_MS = 3e3;
|
|
3581
|
+
var MAX_POLL_ATTEMPTS = 160;
|
|
3582
|
+
function buildToolRequest(options) {
|
|
3583
|
+
try {
|
|
3584
|
+
return ok(buildFalToolRequest(options));
|
|
3585
|
+
} catch (error) {
|
|
3586
|
+
return err(
|
|
3587
|
+
new MotifError(error instanceof Error ? error.message : String(error), 0)
|
|
3588
|
+
);
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
async function runTool(exec, options) {
|
|
3592
|
+
const request = buildToolRequest(options);
|
|
3593
|
+
if (request.isErr()) {
|
|
3594
|
+
return err(request.error);
|
|
3595
|
+
}
|
|
3596
|
+
const response = await exec.request(
|
|
3597
|
+
`${FAL_BASE_URL}/${request.value.endpoint}`,
|
|
3598
|
+
{
|
|
3599
|
+
body: JSON.stringify(request.value.body),
|
|
3600
|
+
method: "POST"
|
|
3601
|
+
}
|
|
3602
|
+
);
|
|
3603
|
+
if (response.isErr()) {
|
|
3604
|
+
return err(response.error);
|
|
3605
|
+
}
|
|
3606
|
+
const data = await response.value.json();
|
|
3607
|
+
return ok(isRecord(data) ? data : {});
|
|
3608
|
+
}
|
|
3609
|
+
async function submitTool(exec, options) {
|
|
3610
|
+
const request = buildToolRequest(options);
|
|
3611
|
+
if (request.isErr()) {
|
|
3612
|
+
return err(request.error);
|
|
3613
|
+
}
|
|
3614
|
+
const response = await exec.request(
|
|
3615
|
+
`${FAL_QUEUE_URL}/${request.value.endpoint}`,
|
|
3616
|
+
{
|
|
3617
|
+
body: JSON.stringify(request.value.body),
|
|
3618
|
+
method: "POST"
|
|
3619
|
+
}
|
|
3620
|
+
);
|
|
3621
|
+
if (response.isErr()) {
|
|
3622
|
+
return err(response.error);
|
|
3623
|
+
}
|
|
3624
|
+
const data = await response.value.json();
|
|
3625
|
+
const submission = parseQueueSubmission(data);
|
|
3626
|
+
return ok({
|
|
3627
|
+
endpoint: endpointFromQueueUrl(
|
|
3628
|
+
submission.responseUrl,
|
|
3629
|
+
request.value.endpoint
|
|
3630
|
+
),
|
|
3631
|
+
requestId: submission.requestId
|
|
3632
|
+
});
|
|
3633
|
+
}
|
|
3634
|
+
async function checkToolStatus(exec, job) {
|
|
3635
|
+
return await exec.getJobStatus(job.endpoint, job.requestId);
|
|
3636
|
+
}
|
|
3637
|
+
async function getToolResult(exec, job) {
|
|
3638
|
+
const url = `${FAL_QUEUE_URL}/${job.endpoint}/requests/${job.requestId}`;
|
|
3639
|
+
const response = await exec.request(url);
|
|
3640
|
+
if (response.isErr()) {
|
|
3641
|
+
return err(response.error);
|
|
3642
|
+
}
|
|
3643
|
+
const data = await response.value.json();
|
|
3644
|
+
return ok(isRecord(data) ? data : {});
|
|
3645
|
+
}
|
|
3646
|
+
async function runToolQueued(exec, options, onProgress) {
|
|
3647
|
+
const job = await submitTool(exec, options);
|
|
3648
|
+
if (job.isErr()) {
|
|
3649
|
+
return err(job.error);
|
|
3650
|
+
}
|
|
3651
|
+
for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {
|
|
3652
|
+
const status = await checkToolStatus(exec, job.value);
|
|
3653
|
+
if (status.isErr()) {
|
|
3654
|
+
return err(status.error);
|
|
3655
|
+
}
|
|
3656
|
+
onProgress?.(status.value.status, status.value.queuePosition);
|
|
3657
|
+
if (status.value.status === "completed") {
|
|
3658
|
+
return await getToolResult(exec, job.value);
|
|
3659
|
+
}
|
|
3660
|
+
if (status.value.status === "failed") {
|
|
3661
|
+
const message = status.value.error ?? "Queued tool run failed";
|
|
3662
|
+
return err(new MotifError(message, 0, void 0, job.value.requestId));
|
|
3663
|
+
}
|
|
3664
|
+
await new Promise((resolve) => {
|
|
3665
|
+
setTimeout(resolve, POLL_INTERVAL_MS);
|
|
3666
|
+
});
|
|
3667
|
+
}
|
|
3668
|
+
return err(
|
|
3669
|
+
new MotifError(
|
|
3670
|
+
"Queued tool run timed out",
|
|
3671
|
+
0,
|
|
3672
|
+
void 0,
|
|
3673
|
+
job.value.requestId
|
|
3674
|
+
)
|
|
3675
|
+
);
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3678
|
+
// src/server.ts
|
|
3679
|
+
var FAL_BASE_URL2 = "https://fal.run";
|
|
3680
|
+
var FAL_QUEUE_URL2 = "https://queue.fal.run";
|
|
2686
3681
|
var FAL_API_URL = "https://api.fal.ai";
|
|
2687
3682
|
var FAL_REST_URL = "https://rest.alpha.fal.ai";
|
|
2688
3683
|
var FalClient = class {
|
|
@@ -2714,16 +3709,16 @@ var FalClient = class {
|
|
|
2714
3709
|
try {
|
|
2715
3710
|
built = buildGenerateBody(options);
|
|
2716
3711
|
} catch (error) {
|
|
2717
|
-
return
|
|
3712
|
+
return err2(toMotifError(error));
|
|
2718
3713
|
}
|
|
2719
3714
|
const { endpoint, body } = built;
|
|
2720
|
-
const response = await this.request(`${
|
|
3715
|
+
const response = await this.request(`${FAL_BASE_URL2}/${endpoint}`, {
|
|
2721
3716
|
body: JSON.stringify(body),
|
|
2722
3717
|
headers: this.ephemeralHeaders(options),
|
|
2723
3718
|
method: "POST"
|
|
2724
3719
|
});
|
|
2725
3720
|
if (response.isErr()) {
|
|
2726
|
-
return
|
|
3721
|
+
return err2(response.error);
|
|
2727
3722
|
}
|
|
2728
3723
|
const data = await response.value.json();
|
|
2729
3724
|
return this.normalizeResponse(data);
|
|
@@ -2731,7 +3726,7 @@ var FalClient = class {
|
|
|
2731
3726
|
async generateQueued(options) {
|
|
2732
3727
|
const job = await this.submitGeneration(options);
|
|
2733
3728
|
if (job.isErr()) {
|
|
2734
|
-
return
|
|
3729
|
+
return err2(job.error);
|
|
2735
3730
|
}
|
|
2736
3731
|
const pollIntervalMs = 3e3;
|
|
2737
3732
|
const maxAttempts = 160;
|
|
@@ -2741,20 +3736,20 @@ var FalClient = class {
|
|
|
2741
3736
|
job.value.requestId
|
|
2742
3737
|
);
|
|
2743
3738
|
if (status.isErr()) {
|
|
2744
|
-
return
|
|
3739
|
+
return err2(status.error);
|
|
2745
3740
|
}
|
|
2746
3741
|
if (status.value.status === "completed") {
|
|
2747
3742
|
return await this.getJobResult(job.value.endpoint, job.value.requestId);
|
|
2748
3743
|
}
|
|
2749
3744
|
if (status.value.status === "failed") {
|
|
2750
3745
|
const message = status.value.error ?? "Queued generation failed";
|
|
2751
|
-
return
|
|
3746
|
+
return err2(new MotifError(message, 0, void 0, job.value.requestId));
|
|
2752
3747
|
}
|
|
2753
3748
|
await new Promise((resolve) => {
|
|
2754
3749
|
setTimeout(resolve, pollIntervalMs);
|
|
2755
3750
|
});
|
|
2756
3751
|
}
|
|
2757
|
-
return
|
|
3752
|
+
return err2(new MotifError("Queued generation timed out", 0));
|
|
2758
3753
|
}
|
|
2759
3754
|
/** ─── Queue-Based Generation ──────────────────────────────── */
|
|
2760
3755
|
/** Submit a generation to the fal.ai queue (returns immediately). */
|
|
@@ -2763,20 +3758,20 @@ var FalClient = class {
|
|
|
2763
3758
|
try {
|
|
2764
3759
|
built = buildGenerateBody(options);
|
|
2765
3760
|
} catch (error) {
|
|
2766
|
-
return
|
|
3761
|
+
return err2(toMotifError(error));
|
|
2767
3762
|
}
|
|
2768
3763
|
const { endpoint, body } = built;
|
|
2769
|
-
const response = await this.request(`${
|
|
3764
|
+
const response = await this.request(`${FAL_QUEUE_URL2}/${endpoint}`, {
|
|
2770
3765
|
body: JSON.stringify(body),
|
|
2771
3766
|
headers: this.ephemeralHeaders(options),
|
|
2772
3767
|
method: "POST"
|
|
2773
3768
|
});
|
|
2774
3769
|
if (response.isErr()) {
|
|
2775
|
-
return
|
|
3770
|
+
return err2(response.error);
|
|
2776
3771
|
}
|
|
2777
3772
|
const data = await response.value.json();
|
|
2778
3773
|
const submission = parseQueueSubmission(data);
|
|
2779
|
-
return
|
|
3774
|
+
return ok2({
|
|
2780
3775
|
endpoint: endpointFromQueueUrl(submission.responseUrl, endpoint),
|
|
2781
3776
|
estimatedCost: estimateCost(
|
|
2782
3777
|
options.model,
|
|
@@ -2788,10 +3783,10 @@ var FalClient = class {
|
|
|
2788
3783
|
}
|
|
2789
3784
|
/** Check the status of a queued generation. */
|
|
2790
3785
|
async getJobStatus(endpoint, requestId) {
|
|
2791
|
-
const url = `${
|
|
3786
|
+
const url = `${FAL_QUEUE_URL2}/${endpoint}/requests/${requestId}/status?logs=1`;
|
|
2792
3787
|
const response = await this.request(url);
|
|
2793
3788
|
if (response.isErr()) {
|
|
2794
|
-
return
|
|
3789
|
+
return err2(response.error);
|
|
2795
3790
|
}
|
|
2796
3791
|
const data = await response.value.json();
|
|
2797
3792
|
const record = isRecord(data) ? data : {};
|
|
@@ -2806,9 +3801,9 @@ var FalClient = class {
|
|
|
2806
3801
|
} else if (rawStatus === "FAILED" || rawStatus === "ERROR" || rawStatus === "CANCELED") {
|
|
2807
3802
|
status = "failed";
|
|
2808
3803
|
} else {
|
|
2809
|
-
return
|
|
3804
|
+
return err2(new MotifError(`Unknown job status: ${rawStatus}`, 0));
|
|
2810
3805
|
}
|
|
2811
|
-
return
|
|
3806
|
+
return ok2({
|
|
2812
3807
|
error: asString(record.error) ?? asString(record.detail),
|
|
2813
3808
|
logs: parseLogs(record.logs),
|
|
2814
3809
|
queuePosition: asNumber(record.queue_position),
|
|
@@ -2817,10 +3812,10 @@ var FalClient = class {
|
|
|
2817
3812
|
}
|
|
2818
3813
|
/** Fetch the completed result from the queue. */
|
|
2819
3814
|
async getJobResult(endpoint, requestId) {
|
|
2820
|
-
const url = `${
|
|
3815
|
+
const url = `${FAL_QUEUE_URL2}/${endpoint}/requests/${requestId}`;
|
|
2821
3816
|
const response = await this.request(url);
|
|
2822
3817
|
if (response.isErr()) {
|
|
2823
|
-
return
|
|
3818
|
+
return err2(response.error);
|
|
2824
3819
|
}
|
|
2825
3820
|
const data = await response.value.json();
|
|
2826
3821
|
return this.normalizeResponse(data, requestId);
|
|
@@ -2841,7 +3836,7 @@ var FalClient = class {
|
|
|
2841
3836
|
} = options;
|
|
2842
3837
|
const config = MODELS[model];
|
|
2843
3838
|
if (!config || config.type !== "utility") {
|
|
2844
|
-
return
|
|
3839
|
+
return err2(new MotifError(`Invalid upscale model: ${model}`, 0));
|
|
2845
3840
|
}
|
|
2846
3841
|
const body = { image_url: imageUrl };
|
|
2847
3842
|
if (model === "crystal") {
|
|
@@ -2874,12 +3869,12 @@ var FalClient = class {
|
|
|
2874
3869
|
body.guidance_scale = guidanceScale;
|
|
2875
3870
|
}
|
|
2876
3871
|
}
|
|
2877
|
-
const response = await this.request(`${
|
|
3872
|
+
const response = await this.request(`${FAL_BASE_URL2}/${config.endpoint}`, {
|
|
2878
3873
|
body: JSON.stringify(body),
|
|
2879
3874
|
method: "POST"
|
|
2880
3875
|
});
|
|
2881
3876
|
if (response.isErr()) {
|
|
2882
|
-
return
|
|
3877
|
+
return err2(response.error);
|
|
2883
3878
|
}
|
|
2884
3879
|
const data = await response.value.json();
|
|
2885
3880
|
return this.normalizeResponse(data);
|
|
@@ -2897,7 +3892,7 @@ var FalClient = class {
|
|
|
2897
3892
|
} = options;
|
|
2898
3893
|
const config = MODELS[model];
|
|
2899
3894
|
if (!config) {
|
|
2900
|
-
return
|
|
3895
|
+
return err2(
|
|
2901
3896
|
new MotifError(`Invalid background removal model: ${model}`, 0)
|
|
2902
3897
|
);
|
|
2903
3898
|
}
|
|
@@ -2919,12 +3914,12 @@ var FalClient = class {
|
|
|
2919
3914
|
rbBody.output_mask = outputMask;
|
|
2920
3915
|
}
|
|
2921
3916
|
}
|
|
2922
|
-
const response = await this.request(`${
|
|
3917
|
+
const response = await this.request(`${FAL_BASE_URL2}/${config.endpoint}`, {
|
|
2923
3918
|
body: JSON.stringify(rbBody),
|
|
2924
3919
|
method: "POST"
|
|
2925
3920
|
});
|
|
2926
3921
|
if (response.isErr()) {
|
|
2927
|
-
return
|
|
3922
|
+
return err2(response.error);
|
|
2928
3923
|
}
|
|
2929
3924
|
const data = await response.value.json();
|
|
2930
3925
|
return this.normalizeResponse(data);
|
|
@@ -2947,7 +3942,7 @@ var FalClient = class {
|
|
|
2947
3942
|
} = options;
|
|
2948
3943
|
const config = MODELS.kling;
|
|
2949
3944
|
if (!config) {
|
|
2950
|
-
return
|
|
3945
|
+
return err2(new MotifError("Kling video model not found", 0));
|
|
2951
3946
|
}
|
|
2952
3947
|
const body = {
|
|
2953
3948
|
duration: String(duration),
|
|
@@ -2964,16 +3959,16 @@ var FalClient = class {
|
|
|
2964
3959
|
if (cfgScale !== void 0) {
|
|
2965
3960
|
body.cfg_scale = cfgScale;
|
|
2966
3961
|
}
|
|
2967
|
-
const response = await this.request(`${
|
|
3962
|
+
const response = await this.request(`${FAL_QUEUE_URL2}/${config.endpoint}`, {
|
|
2968
3963
|
body: JSON.stringify(body),
|
|
2969
3964
|
method: "POST"
|
|
2970
3965
|
});
|
|
2971
3966
|
if (response.isErr()) {
|
|
2972
|
-
return
|
|
3967
|
+
return err2(response.error);
|
|
2973
3968
|
}
|
|
2974
3969
|
const data = await response.value.json();
|
|
2975
3970
|
const submission = parseQueueSubmission(data);
|
|
2976
|
-
return
|
|
3971
|
+
return ok2({
|
|
2977
3972
|
endpoint: endpointFromQueueUrl(submission.responseUrl, config.endpoint),
|
|
2978
3973
|
estimatedCost: estimateVideoCost(duration, generateAudio),
|
|
2979
3974
|
requestId: submission.requestId
|
|
@@ -2981,17 +3976,17 @@ var FalClient = class {
|
|
|
2981
3976
|
}
|
|
2982
3977
|
/** Fetch the completed video result from the queue. */
|
|
2983
3978
|
async getVideoResult(endpoint, requestId) {
|
|
2984
|
-
const url = `${
|
|
3979
|
+
const url = `${FAL_QUEUE_URL2}/${endpoint}/requests/${requestId}`;
|
|
2985
3980
|
const response = await this.request(url);
|
|
2986
3981
|
if (response.isErr()) {
|
|
2987
|
-
return
|
|
3982
|
+
return err2(response.error);
|
|
2988
3983
|
}
|
|
2989
3984
|
const data = await response.value.json();
|
|
2990
3985
|
const video = isRecord(data) && isRecord(data.video) ? data.video : void 0;
|
|
2991
3986
|
if (video === void 0) {
|
|
2992
|
-
return
|
|
3987
|
+
return err2(new MotifError("No video in response", 0));
|
|
2993
3988
|
}
|
|
2994
|
-
return
|
|
3989
|
+
return ok2({
|
|
2995
3990
|
contentType: asString(video.content_type) ?? "",
|
|
2996
3991
|
fileName: asString(video.file_name) ?? "",
|
|
2997
3992
|
fileSize: asNumber(video.file_size) ?? 0,
|
|
@@ -3015,13 +4010,13 @@ var FalClient = class {
|
|
|
3015
4010
|
}
|
|
3016
4011
|
);
|
|
3017
4012
|
if (initiateResponse.isErr()) {
|
|
3018
|
-
return
|
|
4013
|
+
return err2(initiateResponse.error);
|
|
3019
4014
|
}
|
|
3020
4015
|
const initiateData = await initiateResponse.value.json();
|
|
3021
4016
|
const fileUrl = isRecord(initiateData) ? asString(initiateData.file_url) ?? "" : "";
|
|
3022
4017
|
const uploadUrl = isRecord(initiateData) ? asString(initiateData.upload_url) : void 0;
|
|
3023
4018
|
if (uploadUrl === void 0 || uploadUrl === "") {
|
|
3024
|
-
return
|
|
4019
|
+
return err2(
|
|
3025
4020
|
new MotifError("Upload initiate response missing upload_url", 0)
|
|
3026
4021
|
);
|
|
3027
4022
|
}
|
|
@@ -3036,7 +4031,7 @@ var FalClient = class {
|
|
|
3036
4031
|
method: "PUT"
|
|
3037
4032
|
});
|
|
3038
4033
|
} catch (error) {
|
|
3039
|
-
return
|
|
4034
|
+
return err2(
|
|
3040
4035
|
new MotifError(
|
|
3041
4036
|
`Upload PUT failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3042
4037
|
0
|
|
@@ -3044,38 +4039,45 @@ var FalClient = class {
|
|
|
3044
4039
|
);
|
|
3045
4040
|
}
|
|
3046
4041
|
if (!putResponse.ok) {
|
|
3047
|
-
return
|
|
4042
|
+
return err2(
|
|
3048
4043
|
new MotifError(
|
|
3049
4044
|
`Upload PUT failed: ${putResponse.status}`,
|
|
3050
4045
|
putResponse.status
|
|
3051
4046
|
)
|
|
3052
4047
|
);
|
|
3053
4048
|
}
|
|
3054
|
-
return
|
|
4049
|
+
return ok2(fileUrl);
|
|
3055
4050
|
}
|
|
3056
4051
|
/** ─── Utilities ───────────────────────────────────────────── */
|
|
3057
4052
|
/** Run a registered fal utility/tool endpoint. */
|
|
3058
4053
|
async runTool(options) {
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
return
|
|
4054
|
+
return await runTool(this.toolExecutor, options);
|
|
4055
|
+
}
|
|
4056
|
+
/** ─── Queue-Based Tools ───────────────────────────────────── */
|
|
4057
|
+
/**
|
|
4058
|
+
* Submit a tool run to the fal queue. Returns as soon as fal accepts it.
|
|
4059
|
+
*
|
|
4060
|
+
* The queued counterpart to `runTool`, for endpoints that outrun the
|
|
4061
|
+
* synchronous request timeout. Callers choose the path — neither one falls
|
|
4062
|
+
* back to the other.
|
|
4063
|
+
*/
|
|
4064
|
+
async submitTool(options) {
|
|
4065
|
+
return await submitTool(this.toolExecutor, options);
|
|
4066
|
+
}
|
|
4067
|
+
/** Poll one queued tool run. */
|
|
4068
|
+
async checkToolStatus(job) {
|
|
4069
|
+
return await checkToolStatus(this.toolExecutor, job);
|
|
4070
|
+
}
|
|
4071
|
+
/** Fetch the finished payload for a queued tool run. */
|
|
4072
|
+
async getToolResult(job) {
|
|
4073
|
+
return await getToolResult(this.toolExecutor, job);
|
|
4074
|
+
}
|
|
4075
|
+
/**
|
|
4076
|
+
* Submit, poll to completion, and return the result. The convenience path
|
|
4077
|
+
* for tools whose registry entry sets `queued`.
|
|
4078
|
+
*/
|
|
4079
|
+
async runToolQueued(options, onProgress) {
|
|
4080
|
+
return await runToolQueued(this.toolExecutor, options, onProgress);
|
|
3079
4081
|
}
|
|
3080
4082
|
/**
|
|
3081
4083
|
* Delete fal's stored IO payloads for a completed request.
|
|
@@ -3090,9 +4092,9 @@ var FalClient = class {
|
|
|
3090
4092
|
{ method: "DELETE" }
|
|
3091
4093
|
);
|
|
3092
4094
|
if (response.isErr()) {
|
|
3093
|
-
return
|
|
4095
|
+
return err2(response.error);
|
|
3094
4096
|
}
|
|
3095
|
-
return
|
|
4097
|
+
return ok2();
|
|
3096
4098
|
}
|
|
3097
4099
|
/** Estimate cost for a generation (no API call). */
|
|
3098
4100
|
estimateCost(model, resolution, numImages) {
|
|
@@ -3118,6 +4120,16 @@ var FalClient = class {
|
|
|
3118
4120
|
get tools() {
|
|
3119
4121
|
return FAL_TOOLS;
|
|
3120
4122
|
}
|
|
4123
|
+
/**
|
|
4124
|
+
* The seam `server-tools.ts` runs against — the client's authenticated fetch
|
|
4125
|
+
* and its queue status parser, exposed without widening the public surface.
|
|
4126
|
+
*/
|
|
4127
|
+
get toolExecutor() {
|
|
4128
|
+
return {
|
|
4129
|
+
getJobStatus: async (endpoint, requestId) => await this.getJobStatus(endpoint, requestId),
|
|
4130
|
+
request: async (url, init) => await this.request(url, init)
|
|
4131
|
+
};
|
|
4132
|
+
}
|
|
3121
4133
|
/** ─── Private ─────────────────────────────────────────────── */
|
|
3122
4134
|
/** Authenticated fetch to fal.ai APIs with retry logic. */
|
|
3123
4135
|
async request(url, options = {}) {
|
|
@@ -3149,15 +4161,15 @@ var FalClient = class {
|
|
|
3149
4161
|
const text = await response.text();
|
|
3150
4162
|
const message = `Request failed: ${response.status} ${text}`;
|
|
3151
4163
|
const requestId = response.headers.get("x-fal-request-id") ?? requestIdFromBody(text);
|
|
3152
|
-
return
|
|
4164
|
+
return err2(
|
|
3153
4165
|
new MotifError(message, response.status, void 0, requestId)
|
|
3154
4166
|
);
|
|
3155
4167
|
}
|
|
3156
|
-
return
|
|
4168
|
+
return ok2(response);
|
|
3157
4169
|
} catch (error) {
|
|
3158
4170
|
clearTimeout(timeoutId);
|
|
3159
4171
|
if (error instanceof MotifError) {
|
|
3160
|
-
return
|
|
4172
|
+
return err2(error);
|
|
3161
4173
|
}
|
|
3162
4174
|
lastError = new MotifError(
|
|
3163
4175
|
error instanceof Error ? error.message : String(error),
|
|
@@ -3171,7 +4183,7 @@ var FalClient = class {
|
|
|
3171
4183
|
}
|
|
3172
4184
|
}
|
|
3173
4185
|
}
|
|
3174
|
-
return
|
|
4186
|
+
return err2(lastError ?? new MotifError("Request failed after retries", 0));
|
|
3175
4187
|
}
|
|
3176
4188
|
ephemeralHeaders(options) {
|
|
3177
4189
|
return options.ephemeral === true ? { "X-Fal-Store-IO": "0" } : {};
|
|
@@ -3182,24 +4194,24 @@ var FalClient = class {
|
|
|
3182
4194
|
*/
|
|
3183
4195
|
normalizeResponse(data, fallbackRequestId) {
|
|
3184
4196
|
if (!isRecord(data)) {
|
|
3185
|
-
return
|
|
4197
|
+
return err2(
|
|
3186
4198
|
new MotifError("Unexpected fal response shape", 0, "FAL_ERROR")
|
|
3187
4199
|
);
|
|
3188
4200
|
}
|
|
3189
4201
|
const obj = data;
|
|
3190
4202
|
const requestId = asString(obj.request_id) ?? asString(obj.requestId) ?? fallbackRequestId;
|
|
3191
4203
|
if ("detail" in obj) {
|
|
3192
|
-
return
|
|
4204
|
+
return err2(new MotifError(asString(obj.detail) ?? "", 0, "FAL_ERROR"));
|
|
3193
4205
|
}
|
|
3194
4206
|
if ("image" in obj && !("images" in obj)) {
|
|
3195
|
-
return
|
|
4207
|
+
return ok2({
|
|
3196
4208
|
images: [toMotifImage(obj.image)],
|
|
3197
4209
|
prompt: asString(obj.prompt),
|
|
3198
4210
|
requestId,
|
|
3199
4211
|
seed: asNumber(obj.seed)
|
|
3200
4212
|
});
|
|
3201
4213
|
}
|
|
3202
|
-
return
|
|
4214
|
+
return ok2({
|
|
3203
4215
|
images: parseImages(obj.images),
|
|
3204
4216
|
prompt: asString(obj.prompt),
|
|
3205
4217
|
requestId,
|
|
@@ -3207,27 +4219,632 @@ var FalClient = class {
|
|
|
3207
4219
|
});
|
|
3208
4220
|
}
|
|
3209
4221
|
};
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
4222
|
+
|
|
4223
|
+
// src/tool-cost.ts
|
|
4224
|
+
var UNKNOWN = { basis: "unknown", usd: null };
|
|
4225
|
+
function totalMegapixels(outputs) {
|
|
4226
|
+
let pixels = 0;
|
|
4227
|
+
let measured = 0;
|
|
4228
|
+
for (const output of outputs) {
|
|
4229
|
+
if (output.width !== void 0 && output.height !== void 0) {
|
|
4230
|
+
pixels += output.width * output.height;
|
|
4231
|
+
measured += 1;
|
|
4232
|
+
}
|
|
4233
|
+
}
|
|
4234
|
+
return measured === 0 ? null : pixels / 1e6;
|
|
4235
|
+
}
|
|
4236
|
+
function projectedToolCost(price) {
|
|
4237
|
+
return price.kind === "call" ? { basis: "projected", usd: price.usd } : UNKNOWN;
|
|
4238
|
+
}
|
|
4239
|
+
function measuredToolCost(price, outputs) {
|
|
4240
|
+
if (price.kind === "call") {
|
|
4241
|
+
return { basis: "measured", usd: price.usd };
|
|
4242
|
+
}
|
|
4243
|
+
if (price.kind === "megapixel") {
|
|
4244
|
+
const megapixels = totalMegapixels(outputs);
|
|
4245
|
+
return megapixels === null ? UNKNOWN : { basis: "measured", usd: price.usd * megapixels };
|
|
4246
|
+
}
|
|
4247
|
+
return UNKNOWN;
|
|
4248
|
+
}
|
|
4249
|
+
function formatCost(usd) {
|
|
4250
|
+
return usd === null ? "metered" : `$${usd.toFixed(3)}`;
|
|
4251
|
+
}
|
|
4252
|
+
function sumCosts(costs) {
|
|
4253
|
+
let known = 0;
|
|
4254
|
+
let unknown = 0;
|
|
4255
|
+
for (const cost of costs) {
|
|
4256
|
+
if (cost === null) {
|
|
4257
|
+
unknown += 1;
|
|
4258
|
+
} else {
|
|
4259
|
+
known += cost;
|
|
4260
|
+
}
|
|
3222
4261
|
}
|
|
4262
|
+
return { known, unknown };
|
|
4263
|
+
}
|
|
4264
|
+
|
|
4265
|
+
// src/tool-parameters.generated.ts
|
|
4266
|
+
var FAL_TOOL_PARAMETERS = {
|
|
4267
|
+
"ben-v2": [
|
|
4268
|
+
{ key: "seed", type: "integer" }
|
|
4269
|
+
],
|
|
4270
|
+
"birefnet": [
|
|
4271
|
+
{ key: "mask_only", type: "boolean", fallback: false },
|
|
4272
|
+
{ key: "model", type: "enum(General Use (Light)|General Use (Light 2K)|General Use (Heavy)|Matting|Portrait|General Use (Dynamic))", fallback: "General Use (Light)" },
|
|
4273
|
+
{ key: "operating_resolution", type: "enum(1024x1024|2048x2048|2304x2304)", fallback: "1024x1024" },
|
|
4274
|
+
{ key: "output_format", type: "enum(webp|png|gif)", fallback: "png" },
|
|
4275
|
+
{ key: "output_mask", type: "boolean", fallback: false },
|
|
4276
|
+
{ key: "refine_foreground", type: "boolean", fallback: true }
|
|
4277
|
+
],
|
|
4278
|
+
"bria-eraser": [
|
|
4279
|
+
{ key: "mask_type", type: "enum(manual|automatic)", fallback: "manual" },
|
|
4280
|
+
{ key: "preserve_alpha", type: "boolean", fallback: false }
|
|
4281
|
+
],
|
|
4282
|
+
"bria-expand": [
|
|
4283
|
+
{ key: "aspect_ratio", type: "enum(1:1|2:3|3:2|3:4|4:3|4:5|5:4|9:16|16:9)" },
|
|
4284
|
+
{ key: "canvas_size", type: "list[integer]", required: true },
|
|
4285
|
+
{ key: "negative_prompt", type: "string", fallback: "" },
|
|
4286
|
+
{ key: "original_image_location", type: "list[integer]" },
|
|
4287
|
+
{ key: "original_image_size", type: "list[integer]" },
|
|
4288
|
+
{ key: "prompt", type: "string", fallback: "" },
|
|
4289
|
+
{ key: "seed", type: "integer" }
|
|
4290
|
+
],
|
|
4291
|
+
"bria-genfill": [
|
|
4292
|
+
{ key: "negative_prompt", type: "string", fallback: "" },
|
|
4293
|
+
{ key: "num_images", type: "integer", fallback: 1 },
|
|
4294
|
+
{ key: "prompt", type: "string", required: true },
|
|
4295
|
+
{ key: "seed", type: "integer" }
|
|
4296
|
+
],
|
|
4297
|
+
"bria-rmbg": [],
|
|
4298
|
+
"bria-video-rmbg": [
|
|
4299
|
+
{ key: "background_color", type: "enum(Transparent|Black|White|Gray|Red|Green|Blue|Yellow|Cyan|Magenta|Orange)", fallback: "Black" },
|
|
4300
|
+
{ key: "output_container_and_codec", type: "enum(mp4_h265|mp4_h264|webm_vp9|mov_h265|mov_proresks|mkv_h265|mkv_h264|mkv_vp9|gif)", fallback: "webm_vp9" },
|
|
4301
|
+
{ key: "preserve_audio", type: "boolean", fallback: true }
|
|
4302
|
+
],
|
|
4303
|
+
"ddcolor": [
|
|
4304
|
+
{ key: "seed", type: "integer" }
|
|
4305
|
+
],
|
|
4306
|
+
"depth-anything": [],
|
|
4307
|
+
"dwpose": [
|
|
4308
|
+
{ key: "draw_mode", type: "enum(full-pose|body-pose|face-pose|hand-pose|face-hand-mask|face-mask|hand-mask)", fallback: "body-pose" }
|
|
4309
|
+
],
|
|
4310
|
+
"finegrain-eraser": [
|
|
4311
|
+
{ key: "mode", type: "enum(express|standard|premium)", fallback: "standard" },
|
|
4312
|
+
{ key: "prompt", type: "string", required: true },
|
|
4313
|
+
{ key: "seed", type: "integer" }
|
|
4314
|
+
],
|
|
4315
|
+
"flux-outpaint": [
|
|
4316
|
+
{ key: "auto_crop", type: "boolean", fallback: false },
|
|
4317
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4318
|
+
{ key: "expand_bottom", type: "integer", fallback: 0 },
|
|
4319
|
+
{ key: "expand_left", type: "integer", fallback: 0 },
|
|
4320
|
+
{ key: "expand_right", type: "integer", fallback: 0 },
|
|
4321
|
+
{ key: "expand_top", type: "integer", fallback: 0 },
|
|
4322
|
+
{ key: "mode", type: "enum(high|fast)", fallback: "high" },
|
|
4323
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" }
|
|
4324
|
+
],
|
|
4325
|
+
"got-ocr": [
|
|
4326
|
+
{ key: "do_format", type: "boolean", fallback: false },
|
|
4327
|
+
{ key: "multi_page", type: "boolean", fallback: false }
|
|
4328
|
+
],
|
|
4329
|
+
"hed": [
|
|
4330
|
+
{ key: "safe", type: "boolean", fallback: false },
|
|
4331
|
+
{ key: "scribble", type: "boolean", fallback: false }
|
|
4332
|
+
],
|
|
4333
|
+
"hunyuan3d-v3": [
|
|
4334
|
+
{ key: "back_image_url", type: "string" },
|
|
4335
|
+
{ key: "enable_pbr", type: "boolean", fallback: false },
|
|
4336
|
+
{ key: "face_count", type: "integer", fallback: 5e5 },
|
|
4337
|
+
{ key: "generate_type", type: "enum(Normal|LowPoly|Geometry)", fallback: "Normal" },
|
|
4338
|
+
{ key: "left_image_url", type: "string" },
|
|
4339
|
+
{ key: "polygon_type", type: "enum(triangle|quadrilateral)", fallback: "triangle" },
|
|
4340
|
+
{ key: "right_image_url", type: "string" }
|
|
4341
|
+
],
|
|
4342
|
+
"iclight-v2": [
|
|
4343
|
+
{ key: "background_threshold", type: "number", fallback: 0.67 },
|
|
4344
|
+
{ key: "cfg", type: "number", fallback: 1 },
|
|
4345
|
+
{ key: "enable_hr_fix", type: "boolean", fallback: false },
|
|
4346
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4347
|
+
{ key: "guidance_scale", type: "number", fallback: 5 },
|
|
4348
|
+
{ key: "highres_denoise", type: "number", fallback: 0.95 },
|
|
4349
|
+
{ key: "hr_downscale", type: "number", fallback: 0.5 },
|
|
4350
|
+
{ key: "image_size", type: "object|enum(square_hd|square|portrait_4_3|portrait_16_9|landscape_4_3|landscape_16_9)" },
|
|
4351
|
+
{ key: "initial_latent", type: "enum(None|Left|Right|Top|Bottom)", fallback: "None" },
|
|
4352
|
+
{ key: "lowres_denoise", type: "number", fallback: 0.98 },
|
|
4353
|
+
{ key: "mask_image_url", type: "string" },
|
|
4354
|
+
{ key: "negative_prompt", type: "string", fallback: "" },
|
|
4355
|
+
{ key: "num_images", type: "integer", fallback: 1 },
|
|
4356
|
+
{ key: "num_inference_steps", type: "integer", fallback: 28 },
|
|
4357
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" },
|
|
4358
|
+
{ key: "prompt", type: "string", required: true },
|
|
4359
|
+
{ key: "seed", type: "integer" }
|
|
4360
|
+
],
|
|
4361
|
+
"ideogram-layerize-text": [
|
|
4362
|
+
{ key: "font_file_body_url", type: "string" },
|
|
4363
|
+
{ key: "font_file_h1_url", type: "string" },
|
|
4364
|
+
{ key: "font_file_h2_url", type: "string" },
|
|
4365
|
+
{ key: "font_file_small_url", type: "string" },
|
|
4366
|
+
{ key: "font_name_body", type: "string" },
|
|
4367
|
+
{ key: "font_name_h1", type: "string" },
|
|
4368
|
+
{ key: "font_name_h2", type: "string" },
|
|
4369
|
+
{ key: "font_name_small", type: "string" },
|
|
4370
|
+
{ key: "prompt", type: "string" },
|
|
4371
|
+
{ key: "seed", type: "integer" }
|
|
4372
|
+
],
|
|
4373
|
+
"ideogram-reframe": [
|
|
4374
|
+
{ key: "color_palette", type: "object" },
|
|
4375
|
+
{ key: "image_size", type: "object|enum(square_hd|square|portrait_4_3|portrait_16_9|landscape_4_3|landscape_16_9)", required: true },
|
|
4376
|
+
{ key: "num_images", type: "integer", fallback: 1 },
|
|
4377
|
+
{ key: "rendering_speed", type: "enum(TURBO|BALANCED|QUALITY)", fallback: "BALANCED" },
|
|
4378
|
+
{ key: "seed", type: "integer" },
|
|
4379
|
+
{ key: "style", type: "enum(AUTO|GENERAL|REALISTIC|DESIGN)" },
|
|
4380
|
+
{ key: "style_codes", type: "list[string]" },
|
|
4381
|
+
{ key: "style_preset", type: "enum(80S_ILLUSTRATION|90S_NOSTALGIA|ABSTRACT_ORGANIC|ANALOG_NOSTALGIA|ART_BRUT|ART_DECO|ART_POSTER|AURA|AVANT_GARDE|BAUHAUS|BLUEPRINT|BLURRY_MOTION|BRIGHT_ART|C4D_CARTOON|CHILDRENS_BOOK|COLLAGE|COLORING_BOOK_I|COLORING_BOOK_II|CUBISM|DARK_AURA|DOODLE|DOUBLE_EXPOSURE|DRAMATIC_CINEMA|EDITORIAL|EMOTIONAL_MINIMAL|ETHEREAL_PARTY|EXPIRED_FILM|FLAT_ART|FLAT_VECTOR|FOREST_REVERIE|GEO_MINIMALIST|GLASS_PRISM|GOLDEN_HOUR|GRAFFITI_I|GRAFFITI_II|HALFTONE_PRINT|HIGH_CONTRAST|HIPPIE_ERA|ICONIC|JAPANDI_FUSION|JAZZY|LONG_EXPOSURE|MAGAZINE_EDITORIAL|MINIMAL_ILLUSTRATION|MIXED_MEDIA|MONOCHROME|NIGHTLIFE|OIL_PAINTING|OLD_CARTOONS|PAINT_GESTURE|POP_ART|RETRO_ETCHING|RIVIERA_POP|SPOTLIGHT_80S|STYLIZED_RED|SURREAL_COLLAGE|TRAVEL_POSTER|VINTAGE_GEO|VINTAGE_POSTER|WATERCOLOR|WEIRD|WOODBLOCK_PRINT)" }
|
|
4382
|
+
],
|
|
4383
|
+
"ideogram-tiling": [
|
|
4384
|
+
{ key: "acceleration", type: "enum(none|low|regular|high)", fallback: "none" },
|
|
4385
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4386
|
+
{ key: "expansion_model", type: "enum(None|Medium|Large)", fallback: "Medium" },
|
|
4387
|
+
{ key: "image_size", type: "object|enum(square_hd|square|portrait_4_3|portrait_16_9|landscape_4_3|landscape_16_9)", fallback: "square_hd" },
|
|
4388
|
+
{ key: "num_images", type: "integer", fallback: 1 },
|
|
4389
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" },
|
|
4390
|
+
{ key: "prompt", type: "string", required: true },
|
|
4391
|
+
{ key: "rendering_speed", type: "enum(TURBO|BALANCED|QUALITY)", fallback: "BALANCED" },
|
|
4392
|
+
{ key: "seed", type: "integer" },
|
|
4393
|
+
{ key: "strength", type: "number", fallback: 0.8 },
|
|
4394
|
+
{ key: "tiling_mode", type: "enum(both|horizontal|vertical)", fallback: "both" }
|
|
4395
|
+
],
|
|
4396
|
+
"image2svg": [
|
|
4397
|
+
{ key: "color_precision", type: "integer", fallback: 6 },
|
|
4398
|
+
{ key: "colormode", type: "enum(color|binary)", fallback: "color" },
|
|
4399
|
+
{ key: "corner_threshold", type: "integer", fallback: 60 },
|
|
4400
|
+
{ key: "filter_speckle", type: "integer", fallback: 4 },
|
|
4401
|
+
{ key: "hierarchical", type: "enum(stacked|cutout)", fallback: "stacked" },
|
|
4402
|
+
{ key: "layer_difference", type: "integer", fallback: 16 },
|
|
4403
|
+
{ key: "length_threshold", type: "number", fallback: 4 },
|
|
4404
|
+
{ key: "max_iterations", type: "integer", fallback: 10 },
|
|
4405
|
+
{ key: "mode", type: "enum(spline|polygon)", fallback: "spline" },
|
|
4406
|
+
{ key: "path_precision", type: "integer", fallback: 3 },
|
|
4407
|
+
{ key: "splice_threshold", type: "integer", fallback: 45 }
|
|
4408
|
+
],
|
|
4409
|
+
"lighting-restoration": [
|
|
4410
|
+
{ key: "acceleration", type: "enum(none|regular)", fallback: "regular" },
|
|
4411
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4412
|
+
{ key: "guidance_scale", type: "number", fallback: 1 },
|
|
4413
|
+
{ key: "image_size", type: "object|enum(square_hd|square|portrait_4_3|portrait_16_9|landscape_4_3|landscape_16_9)" },
|
|
4414
|
+
{ key: "negative_prompt", type: "string", fallback: " " },
|
|
4415
|
+
{ key: "num_images", type: "integer", fallback: 1 },
|
|
4416
|
+
{ key: "num_inference_steps", type: "integer", fallback: 6 },
|
|
4417
|
+
{ key: "output_format", type: "enum(png|jpeg|webp)", fallback: "png" },
|
|
4418
|
+
{ key: "seed", type: "integer" }
|
|
4419
|
+
],
|
|
4420
|
+
"lineart": [
|
|
4421
|
+
{ key: "coarse", type: "boolean", fallback: false }
|
|
4422
|
+
],
|
|
4423
|
+
"marigold-depth": [
|
|
4424
|
+
{ key: "ensemble_size", type: "integer", fallback: 10 },
|
|
4425
|
+
{ key: "num_inference_steps", type: "integer", fallback: 10 },
|
|
4426
|
+
{ key: "processing_res", type: "integer", fallback: 0 }
|
|
4427
|
+
],
|
|
4428
|
+
"midas-depth": [
|
|
4429
|
+
{ key: "a", type: "number", fallback: 6.283185307179586 },
|
|
4430
|
+
{ key: "bg_th", type: "number", fallback: 0.1 },
|
|
4431
|
+
{ key: "depth_and_normal", type: "boolean", fallback: false }
|
|
4432
|
+
],
|
|
4433
|
+
"midas-preprocessor": [
|
|
4434
|
+
{ key: "a", type: "number", fallback: 6.283185307179586 },
|
|
4435
|
+
{ key: "background_threshold", type: "number", fallback: 0.1 }
|
|
4436
|
+
],
|
|
4437
|
+
"mlsd": [
|
|
4438
|
+
{ key: "distance_threshold", type: "number", fallback: 0.1 },
|
|
4439
|
+
{ key: "score_threshold", type: "number", fallback: 0.1 }
|
|
4440
|
+
],
|
|
4441
|
+
"moondream-caption": [
|
|
4442
|
+
{ key: "length", type: "enum(short|normal|long)", fallback: "normal" },
|
|
4443
|
+
{ key: "temperature", type: "number" },
|
|
4444
|
+
{ key: "top_p", type: "number" }
|
|
4445
|
+
],
|
|
4446
|
+
"moondream-detect": [
|
|
4447
|
+
{ key: "preview", type: "boolean", fallback: false },
|
|
4448
|
+
{ key: "prompt", type: "string", required: true }
|
|
4449
|
+
],
|
|
4450
|
+
"moondream-point": [
|
|
4451
|
+
{ key: "preview", type: "boolean", fallback: false },
|
|
4452
|
+
{ key: "prompt", type: "string", required: true }
|
|
4453
|
+
],
|
|
4454
|
+
"moondream-query": [
|
|
4455
|
+
{ key: "prompt", type: "string", required: true },
|
|
4456
|
+
{ key: "reasoning", type: "boolean", fallback: true },
|
|
4457
|
+
{ key: "temperature", type: "number" },
|
|
4458
|
+
{ key: "top_p", type: "number" }
|
|
4459
|
+
],
|
|
4460
|
+
"nsfw": [],
|
|
4461
|
+
"object-removal": [
|
|
4462
|
+
{ key: "mask_expansion", type: "integer", fallback: 15 },
|
|
4463
|
+
{ key: "model", type: "enum(low_quality|medium_quality|high_quality|best_quality)", fallback: "best_quality" },
|
|
4464
|
+
{ key: "prompt", type: "string", required: true }
|
|
4465
|
+
],
|
|
4466
|
+
"object-removal-bbox": [
|
|
4467
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4468
|
+
{ key: "mask_expansion", type: "integer", fallback: 15 },
|
|
4469
|
+
{ key: "model", type: "enum(low_quality|medium_quality|high_quality|best_quality)", fallback: "best_quality" }
|
|
4470
|
+
],
|
|
4471
|
+
"object-removal-mask": [
|
|
4472
|
+
{ key: "mask_expansion", type: "integer", fallback: 15 },
|
|
4473
|
+
{ key: "model", type: "enum(low_quality|medium_quality|high_quality|best_quality)", fallback: "best_quality" }
|
|
4474
|
+
],
|
|
4475
|
+
"patina": [
|
|
4476
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4477
|
+
{ key: "maps", type: "list[enum(basecolor|normal|roughness|metalness|height)]", fallback: ["basecolor", "normal", "roughness", "metalness", "height"] },
|
|
4478
|
+
{ key: "output_format", type: "enum(jpeg|png|webp)", fallback: "png" },
|
|
4479
|
+
{ key: "seed", type: "integer" }
|
|
4480
|
+
],
|
|
4481
|
+
"patina-extract": [
|
|
4482
|
+
{ key: "enable_prompt_expansion", type: "boolean", fallback: true },
|
|
4483
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4484
|
+
{ key: "image_size", type: "object|enum(square_hd|square|portrait_4_3|portrait_16_9|landscape_4_3|landscape_16_9)", fallback: "square_hd" },
|
|
4485
|
+
{ key: "maps", type: "list[enum(basecolor|normal|roughness|metalness|height)]", fallback: ["basecolor", "normal", "roughness", "metalness", "height"] },
|
|
4486
|
+
{ key: "num_images", type: "integer", fallback: 1 },
|
|
4487
|
+
{ key: "num_inference_steps", type: "integer", fallback: 8 },
|
|
4488
|
+
{ key: "output_format", type: "enum(jpeg|png|webp)", fallback: "png" },
|
|
4489
|
+
{ key: "prompt", type: "string", required: true },
|
|
4490
|
+
{ key: "seed", type: "integer" },
|
|
4491
|
+
{ key: "strength", type: "number", fallback: 0.6 },
|
|
4492
|
+
{ key: "tile_size", type: "integer", fallback: 128 },
|
|
4493
|
+
{ key: "tile_stride", type: "integer", fallback: 64 },
|
|
4494
|
+
{ key: "tiling_mode", type: "enum(both|horizontal|vertical)", fallback: "both" },
|
|
4495
|
+
{ key: "upscale_factor", type: "enum(0|2|4)", fallback: 0 }
|
|
4496
|
+
],
|
|
4497
|
+
"pidi": [
|
|
4498
|
+
{ key: "apply_filter", type: "boolean", fallback: false },
|
|
4499
|
+
{ key: "safe", type: "boolean", fallback: false },
|
|
4500
|
+
{ key: "scribble", type: "boolean", fallback: false }
|
|
4501
|
+
],
|
|
4502
|
+
"qwen-layered": [
|
|
4503
|
+
{ key: "acceleration", type: "enum(none|regular|high)", fallback: "regular" },
|
|
4504
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4505
|
+
{ key: "guidance_scale", type: "number", fallback: 5 },
|
|
4506
|
+
{ key: "negative_prompt", type: "string", fallback: "" },
|
|
4507
|
+
{ key: "num_inference_steps", type: "integer", fallback: 28 },
|
|
4508
|
+
{ key: "num_layers", type: "integer", fallback: 4 },
|
|
4509
|
+
{ key: "output_format", type: "enum(png|webp)", fallback: "png" },
|
|
4510
|
+
{ key: "prompt", type: "string" },
|
|
4511
|
+
{ key: "seed", type: "integer" }
|
|
4512
|
+
],
|
|
4513
|
+
"recraft-vectorize": [],
|
|
4514
|
+
"rembg": [
|
|
4515
|
+
{ key: "crop_to_bbox", type: "boolean", fallback: false }
|
|
4516
|
+
],
|
|
4517
|
+
"remove-lighting": [
|
|
4518
|
+
{ key: "acceleration", type: "enum(none|regular)", fallback: "regular" },
|
|
4519
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4520
|
+
{ key: "guidance_scale", type: "number", fallback: 1 },
|
|
4521
|
+
{ key: "image_size", type: "object|enum(square_hd|square|portrait_4_3|portrait_16_9|landscape_4_3|landscape_16_9)" },
|
|
4522
|
+
{ key: "negative_prompt", type: "string", fallback: " " },
|
|
4523
|
+
{ key: "num_images", type: "integer", fallback: 1 },
|
|
4524
|
+
{ key: "num_inference_steps", type: "integer", fallback: 6 },
|
|
4525
|
+
{ key: "output_format", type: "enum(png|jpeg|webp)", fallback: "png" },
|
|
4526
|
+
{ key: "seed", type: "integer" }
|
|
4527
|
+
],
|
|
4528
|
+
"sam-preprocessor": [],
|
|
4529
|
+
"sam2-auto": [
|
|
4530
|
+
{ key: "min_mask_region_area", type: "integer", fallback: 100 },
|
|
4531
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "png" },
|
|
4532
|
+
{ key: "points_per_side", type: "integer", fallback: 32 },
|
|
4533
|
+
{ key: "pred_iou_thresh", type: "number", fallback: 0.88 },
|
|
4534
|
+
{ key: "stability_score_thresh", type: "number", fallback: 0.95 }
|
|
4535
|
+
],
|
|
4536
|
+
"sam3-1-image": [
|
|
4537
|
+
{ key: "apply_mask", type: "boolean", fallback: true },
|
|
4538
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4539
|
+
{ key: "include_boxes", type: "boolean", fallback: false },
|
|
4540
|
+
{ key: "include_scores", type: "boolean", fallback: false },
|
|
4541
|
+
{ key: "max_masks", type: "integer", fallback: 3 },
|
|
4542
|
+
{ key: "output_format", type: "enum(jpeg|png|webp)", fallback: "png" },
|
|
4543
|
+
{ key: "point_prompts", type: "list[object]", fallback: [] },
|
|
4544
|
+
{ key: "prompt", type: "string", fallback: "wheel" },
|
|
4545
|
+
{ key: "return_multiple_masks", type: "boolean", fallback: false }
|
|
4546
|
+
],
|
|
4547
|
+
"sam3-1-video": [
|
|
4548
|
+
{ key: "apply_mask", type: "boolean", fallback: true },
|
|
4549
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4550
|
+
{ key: "detection_threshold", type: "number", fallback: 0.5 },
|
|
4551
|
+
{ key: "max_num_objects", type: "integer", fallback: 16 },
|
|
4552
|
+
{ key: "point_prompts", type: "list[object]", fallback: [] },
|
|
4553
|
+
{ key: "prompt", type: "string", fallback: "" },
|
|
4554
|
+
{ key: "video_output_type", type: "enum(X264 (.mp4)|VP9 (.webm))", fallback: "X264 (.mp4)" }
|
|
4555
|
+
],
|
|
4556
|
+
"sam3-3d-align": [
|
|
4557
|
+
{ key: "body_mask_url", type: "string" },
|
|
4558
|
+
{ key: "body_mesh_url", type: "string", required: true },
|
|
4559
|
+
{ key: "focal_length", type: "number" },
|
|
4560
|
+
{ key: "object_mesh_url", type: "string" }
|
|
4561
|
+
],
|
|
4562
|
+
"sam3-3d-body": [
|
|
4563
|
+
{ key: "export_meshes", type: "boolean", fallback: true },
|
|
4564
|
+
{ key: "include_3d_keypoints", type: "boolean", fallback: true },
|
|
4565
|
+
{ key: "include_mhr_params", type: "boolean", fallback: true }
|
|
4566
|
+
],
|
|
4567
|
+
"sam3-3d-objects": [
|
|
4568
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4569
|
+
{ key: "detection_threshold", type: "number" },
|
|
4570
|
+
{ key: "export_textured_glb", type: "boolean", fallback: false },
|
|
4571
|
+
{ key: "mask_urls", type: "list[string]" },
|
|
4572
|
+
{ key: "point_prompts", type: "list[object]", fallback: [] },
|
|
4573
|
+
{ key: "pointmap_url", type: "string" },
|
|
4574
|
+
{ key: "prompt", type: "string", fallback: "car" },
|
|
4575
|
+
{ key: "seed", type: "integer" }
|
|
4576
|
+
],
|
|
4577
|
+
"sam3-image": [
|
|
4578
|
+
{ key: "apply_mask", type: "boolean", fallback: true },
|
|
4579
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4580
|
+
{ key: "include_boxes", type: "boolean", fallback: false },
|
|
4581
|
+
{ key: "include_scores", type: "boolean", fallback: false },
|
|
4582
|
+
{ key: "max_masks", type: "integer", fallback: 3 },
|
|
4583
|
+
{ key: "output_format", type: "enum(jpeg|png|webp)", fallback: "png" },
|
|
4584
|
+
{ key: "point_prompts", type: "list[object]", fallback: [] },
|
|
4585
|
+
{ key: "prompt", type: "string", fallback: "wheel" },
|
|
4586
|
+
{ key: "return_multiple_masks", type: "boolean", fallback: false },
|
|
4587
|
+
{ key: "text_prompt", type: "string" }
|
|
4588
|
+
],
|
|
4589
|
+
"sam3-image-rle": [
|
|
4590
|
+
{ key: "apply_mask", type: "boolean", fallback: true },
|
|
4591
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4592
|
+
{ key: "include_boxes", type: "boolean", fallback: false },
|
|
4593
|
+
{ key: "include_scores", type: "boolean", fallback: false },
|
|
4594
|
+
{ key: "max_masks", type: "integer", fallback: 3 },
|
|
4595
|
+
{ key: "output_format", type: "enum(jpeg|png|webp)", fallback: "png" },
|
|
4596
|
+
{ key: "point_prompts", type: "list[object]", fallback: [] },
|
|
4597
|
+
{ key: "prompt", type: "string", fallback: "wheel" },
|
|
4598
|
+
{ key: "return_multiple_masks", type: "boolean", fallback: false },
|
|
4599
|
+
{ key: "text_prompt", type: "string" }
|
|
4600
|
+
],
|
|
4601
|
+
"sam3-video": [
|
|
4602
|
+
{ key: "apply_mask", type: "boolean", fallback: true },
|
|
4603
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4604
|
+
{ key: "detection_threshold", type: "number", fallback: 0.5 },
|
|
4605
|
+
{ key: "point_prompts", type: "list[object]", fallback: [] },
|
|
4606
|
+
{ key: "prompt", type: "string", fallback: "" },
|
|
4607
|
+
{ key: "text_prompt", type: "string" },
|
|
4608
|
+
{ key: "video_output_type", type: "enum(X264 (.mp4)|VP9 (.webm))", fallback: "X264 (.mp4)" }
|
|
4609
|
+
],
|
|
4610
|
+
"sam3-video-rle": [
|
|
4611
|
+
{ key: "apply_mask", type: "boolean", fallback: false },
|
|
4612
|
+
{ key: "boundingbox_zip", type: "boolean", fallback: false },
|
|
4613
|
+
{ key: "box_prompts", type: "list[object]", fallback: [] },
|
|
4614
|
+
{ key: "detection_threshold", type: "number", fallback: 0.5 },
|
|
4615
|
+
{ key: "frame_index", type: "integer", fallback: 0 },
|
|
4616
|
+
{ key: "point_prompts", type: "list[object]", fallback: [] },
|
|
4617
|
+
{ key: "prompt", type: "string", fallback: "" }
|
|
4618
|
+
],
|
|
4619
|
+
"scribble": [
|
|
4620
|
+
{ key: "model", type: "enum(HED|PiDi)", fallback: "HED" },
|
|
4621
|
+
{ key: "safe", type: "boolean", fallback: false }
|
|
4622
|
+
],
|
|
4623
|
+
"seedream-layerize": [
|
|
4624
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4625
|
+
{ key: "enhance_prompt_mode", type: "enum(standard|fast)", fallback: "standard" },
|
|
4626
|
+
{ key: "image_size", type: "enum(auto|auto_1K|auto_1.5K|auto_2K)", fallback: "auto" },
|
|
4627
|
+
{ key: "prompt", type: "string", fallback: "" }
|
|
4628
|
+
],
|
|
4629
|
+
"seedvr-seamless": [
|
|
4630
|
+
{ key: "enable_safety_checker", type: "boolean", fallback: true },
|
|
4631
|
+
{ key: "noise_scale", type: "number", fallback: 0.1 },
|
|
4632
|
+
{ key: "output_format", type: "enum(png|jpeg|webp)", fallback: "png" },
|
|
4633
|
+
{ key: "seed", type: "integer" },
|
|
4634
|
+
{ key: "target_resolution", type: "enum(720p|1080p|1440p|2160p)", fallback: "1080p" },
|
|
4635
|
+
{ key: "upscale_factor", type: "number", fallback: 2 },
|
|
4636
|
+
{ key: "upscale_mode", type: "enum(target|factor)", fallback: "factor" }
|
|
4637
|
+
],
|
|
4638
|
+
"seedvr-upscale": [
|
|
4639
|
+
{ key: "noise_scale", type: "number", fallback: 0.1 },
|
|
4640
|
+
{ key: "output_format", type: "enum(png|jpg|webp)", fallback: "jpg" },
|
|
4641
|
+
{ key: "seed", type: "integer" },
|
|
4642
|
+
{ key: "target_resolution", type: "enum(720p|1080p|1440p|2160p)", fallback: "1080p" },
|
|
4643
|
+
{ key: "upscale_factor", type: "number", fallback: 2 },
|
|
4644
|
+
{ key: "upscale_mode", type: "enum(target|factor)", fallback: "factor" }
|
|
4645
|
+
],
|
|
4646
|
+
"smart-resize": [
|
|
4647
|
+
{ key: "num_images_per_size", type: "integer", fallback: 1 },
|
|
4648
|
+
{ key: "output_format", type: "enum(jpeg|png|webp)", fallback: "png" },
|
|
4649
|
+
{ key: "prompt", type: "string", fallback: "" },
|
|
4650
|
+
{ key: "resolution", type: "enum(1K|2K|4K)", fallback: "1K" },
|
|
4651
|
+
{ key: "safety_tolerance", type: "enum(1|2|3|4|5|6)", fallback: "4" },
|
|
4652
|
+
{ key: "seed", type: "integer" },
|
|
4653
|
+
{ key: "target_sizes", type: "list[string]", required: true }
|
|
4654
|
+
],
|
|
4655
|
+
"teed": [],
|
|
4656
|
+
"text-removal": [
|
|
4657
|
+
{ key: "aspect_ratio", type: "enum(21:9|16:9|4:3|3:2|1:1|2:3|3:4|9:16|9:21)" },
|
|
4658
|
+
{ key: "guidance_scale", type: "number", fallback: 3.5 },
|
|
4659
|
+
{ key: "num_inference_steps", type: "integer", fallback: 30 },
|
|
4660
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" },
|
|
4661
|
+
{ key: "safety_tolerance", type: "enum(1|2|3|4|5|6)", fallback: "2" },
|
|
4662
|
+
{ key: "seed", type: "integer" }
|
|
4663
|
+
],
|
|
4664
|
+
"topaz-adjust": [
|
|
4665
|
+
{ key: "model", type: "enum(Adjust V2|White Balance|Colorize)", fallback: "Adjust V2" },
|
|
4666
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" }
|
|
4667
|
+
],
|
|
4668
|
+
"topaz-creative": [
|
|
4669
|
+
{ key: "autoprompt", type: "boolean" },
|
|
4670
|
+
{ key: "color_preservation", type: "boolean" },
|
|
4671
|
+
{ key: "creativity", type: "integer" },
|
|
4672
|
+
{ key: "crop_to_fill", type: "boolean", fallback: false },
|
|
4673
|
+
{ key: "model", type: "enum(Bloom 2|Bloom|Bloom Realism)", fallback: "Bloom 2" },
|
|
4674
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" },
|
|
4675
|
+
{ key: "upscale_factor", type: "number", fallback: 2 }
|
|
4676
|
+
],
|
|
4677
|
+
"topaz-denoise": [
|
|
4678
|
+
{ key: "model", type: "enum(Normal|Strong|Extreme|Denoise Max)", fallback: "Normal" },
|
|
4679
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" }
|
|
4680
|
+
],
|
|
4681
|
+
"topaz-generative": [
|
|
4682
|
+
{ key: "autoprompt", type: "boolean" },
|
|
4683
|
+
{ key: "creativity", type: "integer" },
|
|
4684
|
+
{ key: "crop_to_fill", type: "boolean", fallback: false },
|
|
4685
|
+
{ key: "denoise", type: "number" },
|
|
4686
|
+
{ key: "detail", type: "number" },
|
|
4687
|
+
{ key: "enhancement_strength", type: "enum(low|medium|high)" },
|
|
4688
|
+
{ key: "face_enhancement", type: "boolean", fallback: true },
|
|
4689
|
+
{ key: "face_enhancement_creativity", type: "number", fallback: 0 },
|
|
4690
|
+
{ key: "face_enhancement_strength", type: "number", fallback: 0.8 },
|
|
4691
|
+
{ key: "model", type: "enum(Wonder 3.5|Wonder 3|Wonder 2|Wonder|Recover 3|Standard MAX|Redefine|Recovery V2|Recovery)", fallback: "Wonder 3" },
|
|
4692
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" },
|
|
4693
|
+
{ key: "prompt", type: "string" },
|
|
4694
|
+
{ key: "sharpen", type: "number" },
|
|
4695
|
+
{ key: "subject_detection", type: "enum(All|Foreground|Background)", fallback: "All" },
|
|
4696
|
+
{ key: "texture", type: "integer" },
|
|
4697
|
+
{ key: "upscale_factor", type: "number", fallback: 2 }
|
|
4698
|
+
],
|
|
4699
|
+
"topaz-image": [
|
|
4700
|
+
{ key: "autoprompt", type: "boolean" },
|
|
4701
|
+
{ key: "creativity", type: "integer" },
|
|
4702
|
+
{ key: "crop_to_fill", type: "boolean", fallback: false },
|
|
4703
|
+
{ key: "denoise", type: "number" },
|
|
4704
|
+
{ key: "detail", type: "number" },
|
|
4705
|
+
{ key: "enhancement_strength", type: "enum(low|medium|high)" },
|
|
4706
|
+
{ key: "face_enhancement", type: "boolean", fallback: true },
|
|
4707
|
+
{ key: "face_enhancement_creativity", type: "number", fallback: 0 },
|
|
4708
|
+
{ key: "face_enhancement_strength", type: "number", fallback: 0.8 },
|
|
4709
|
+
{ key: "fix_compression", type: "number" },
|
|
4710
|
+
{ key: "model", type: "enum(Standard V2|High Fidelity V2|Low Resolution V2|CGI|Text Refine|Wonder 3|Wonder|Standard MAX|Redefine|Recovery V2|Recovery)", fallback: "Standard V2" },
|
|
4711
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" },
|
|
4712
|
+
{ key: "prompt", type: "string" },
|
|
4713
|
+
{ key: "sharpen", type: "number" },
|
|
4714
|
+
{ key: "strength", type: "number" },
|
|
4715
|
+
{ key: "subject_detection", type: "enum(All|Foreground|Background)", fallback: "All" },
|
|
4716
|
+
{ key: "texture", type: "integer" },
|
|
4717
|
+
{ key: "upscale_factor", type: "number", fallback: 2 }
|
|
4718
|
+
],
|
|
4719
|
+
"topaz-precision": [
|
|
4720
|
+
{ key: "crop_to_fill", type: "boolean", fallback: false },
|
|
4721
|
+
{ key: "denoise", type: "number" },
|
|
4722
|
+
{ key: "face_enhancement", type: "boolean", fallback: true },
|
|
4723
|
+
{ key: "face_enhancement_creativity", type: "number", fallback: 0 },
|
|
4724
|
+
{ key: "face_enhancement_strength", type: "number", fallback: 0.8 },
|
|
4725
|
+
{ key: "fix_compression", type: "number" },
|
|
4726
|
+
{ key: "model", type: "enum(Standard V2|High Fidelity V3|High Fidelity V2|Low Resolution V2|CGI|Text Refine)", fallback: "Standard V2" },
|
|
4727
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" },
|
|
4728
|
+
{ key: "sharpen", type: "number" },
|
|
4729
|
+
{ key: "strength", type: "number" },
|
|
4730
|
+
{ key: "subject_detection", type: "enum(All|Foreground|Background)", fallback: "All" },
|
|
4731
|
+
{ key: "upscale_factor", type: "number", fallback: 2 }
|
|
4732
|
+
],
|
|
4733
|
+
"topaz-restore": [
|
|
4734
|
+
{ key: "model", type: "enum(Recover 3|Dust-Scratch V2)", fallback: "Recover 3" },
|
|
4735
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" }
|
|
4736
|
+
],
|
|
4737
|
+
"topaz-sharpen": [
|
|
4738
|
+
{ key: "model", type: "enum(Standard|Strong|Lens Blur V2|Motion Blur|Natural|Refocus|Wildlife|Portrait|Auto Sharpen|Super Focus V3|Super Focus V2)", fallback: "Standard" },
|
|
4739
|
+
{ key: "output_format", type: "enum(jpeg|png)", fallback: "jpeg" }
|
|
4740
|
+
],
|
|
4741
|
+
"topaz-transparent": [
|
|
4742
|
+
{ key: "output_format", type: "string", fallback: "png" },
|
|
4743
|
+
{ key: "upscale_factor", type: "number", fallback: 2 }
|
|
4744
|
+
],
|
|
4745
|
+
"topaz-video": [
|
|
4746
|
+
{ key: "compression", type: "number" },
|
|
4747
|
+
{ key: "grain", type: "number" },
|
|
4748
|
+
{ key: "H264_output", type: "boolean", fallback: false },
|
|
4749
|
+
{ key: "halo", type: "number" },
|
|
4750
|
+
{ key: "model", type: "enum(Proteus|Artemis HQ|Artemis MQ|Artemis LQ|Gaia HQ|Gaia CG|Gaia 2|Nyx|Nyx Fast|Nyx XL|Nyx HF|Starlight Precise 2.5|Starlight HQ|Starlight Mini|Starlight Sharp|Starlight Fast 2|Starlight Precise 1|Starlight Precise 2|Starlight Fast 1)", fallback: "Proteus" },
|
|
4751
|
+
{ key: "noise", type: "number" },
|
|
4752
|
+
{ key: "recover_detail", type: "number" },
|
|
4753
|
+
{ key: "target_fps", type: "integer" },
|
|
4754
|
+
{ key: "upscale_factor", type: "number", fallback: 2 }
|
|
4755
|
+
],
|
|
4756
|
+
"trellis-2": [
|
|
4757
|
+
{ key: "decimation_target", type: "integer", fallback: 5e5 },
|
|
4758
|
+
{ key: "remesh", type: "boolean", fallback: true },
|
|
4759
|
+
{ key: "remesh_band", type: "number", fallback: 1 },
|
|
4760
|
+
{ key: "remesh_project", type: "number", fallback: 0 },
|
|
4761
|
+
{ key: "resolution", type: "enum(512|1024|1536)", fallback: 1024 },
|
|
4762
|
+
{ key: "seed", type: "integer" },
|
|
4763
|
+
{ key: "shape_slat_guidance_interval_end", type: "number", fallback: 1 },
|
|
4764
|
+
{ key: "shape_slat_guidance_interval_start", type: "number", fallback: 0.6 },
|
|
4765
|
+
{ key: "shape_slat_guidance_rescale", type: "number", fallback: 0.5 },
|
|
4766
|
+
{ key: "shape_slat_guidance_strength", type: "number", fallback: 7.5 },
|
|
4767
|
+
{ key: "shape_slat_rescale_t", type: "number", fallback: 3 },
|
|
4768
|
+
{ key: "shape_slat_sampling_steps", type: "integer", fallback: 12 },
|
|
4769
|
+
{ key: "ss_guidance_interval_end", type: "number", fallback: 1 },
|
|
4770
|
+
{ key: "ss_guidance_interval_start", type: "number", fallback: 0.6 },
|
|
4771
|
+
{ key: "ss_guidance_rescale", type: "number", fallback: 0.7 },
|
|
4772
|
+
{ key: "ss_guidance_strength", type: "number", fallback: 7.5 },
|
|
4773
|
+
{ key: "ss_rescale_t", type: "number", fallback: 5 },
|
|
4774
|
+
{ key: "ss_sampling_steps", type: "integer", fallback: 12 },
|
|
4775
|
+
{ key: "tex_slat_guidance_interval_end", type: "number", fallback: 0.9 },
|
|
4776
|
+
{ key: "tex_slat_guidance_interval_start", type: "number", fallback: 0.6 },
|
|
4777
|
+
{ key: "tex_slat_guidance_rescale", type: "number", fallback: 0 },
|
|
4778
|
+
{ key: "tex_slat_guidance_strength", type: "number", fallback: 1 },
|
|
4779
|
+
{ key: "tex_slat_rescale_t", type: "number", fallback: 3 },
|
|
4780
|
+
{ key: "tex_slat_sampling_steps", type: "integer", fallback: 12 },
|
|
4781
|
+
{ key: "texture_size", type: "enum(1024|2048|4096)", fallback: 2048 },
|
|
4782
|
+
{ key: "uv_unwrap_angle_threshold_deg", type: "number", fallback: 90 },
|
|
4783
|
+
{ key: "uv_unwrap_global_iterations", type: "integer", fallback: 1 },
|
|
4784
|
+
{ key: "uv_unwrap_refine_iterations", type: "integer", fallback: 0 },
|
|
4785
|
+
{ key: "uv_unwrap_smooth_strength", type: "number", fallback: 1 }
|
|
4786
|
+
],
|
|
4787
|
+
"zoe-depth": []
|
|
3223
4788
|
};
|
|
3224
|
-
function
|
|
3225
|
-
|
|
3226
|
-
|
|
4789
|
+
function falToolParameters(tool) {
|
|
4790
|
+
return FAL_TOOL_PARAMETERS[tool] ?? [];
|
|
4791
|
+
}
|
|
4792
|
+
|
|
4793
|
+
// src/model-output.generated.ts
|
|
4794
|
+
var MODEL_OUTPUT = {
|
|
4795
|
+
"banana": { container: "png", lossless: true, bitDepth: 8 },
|
|
4796
|
+
"banana2": { container: "png", lossless: true, bitDepth: 8 },
|
|
4797
|
+
"flux": { container: "jpeg", subsampling: "4:4:4", lossless: false, bitDepth: 8 },
|
|
4798
|
+
"flux-fast": { container: "jpeg", subsampling: "4:4:4", lossless: false, bitDepth: 8 },
|
|
4799
|
+
"flux2-dev": { container: "png", lossless: true, bitDepth: 8 },
|
|
4800
|
+
"flux2-flex": { container: "jpeg", subsampling: "4:4:4", lossless: false, bitDepth: 8 },
|
|
4801
|
+
"flux2-max": { container: "jpeg", subsampling: "4:4:4", lossless: false, bitDepth: 8 },
|
|
4802
|
+
"flux2-pro": { container: "jpeg", subsampling: "4:4:4", lossless: false, bitDepth: 8 },
|
|
4803
|
+
"flux2-turbo": { container: "png", lossless: true, bitDepth: 8 },
|
|
4804
|
+
"gemini": { container: "png", lossless: true, bitDepth: 8 },
|
|
4805
|
+
"gemini3": { container: "png", lossless: true, bitDepth: 8 },
|
|
4806
|
+
"gpt": { container: "png", lossless: true, bitDepth: 8 },
|
|
4807
|
+
"gpt2": { container: "png", lossless: true, bitDepth: 8 },
|
|
4808
|
+
"grok-image": { container: "png", lossless: true, bitDepth: 8 },
|
|
4809
|
+
"ideogram": { container: "png", lossless: true, bitDepth: 8 },
|
|
4810
|
+
"ideogram4": { container: "jpeg", subsampling: "4:4:4", lossless: false, bitDepth: 8 },
|
|
4811
|
+
"qwen": { container: "png", lossless: true, bitDepth: 8 },
|
|
4812
|
+
"qwen3": { container: "png", lossless: true, bitDepth: 8 },
|
|
4813
|
+
"recraft": { container: "webp (lossless)", lossless: true, hasAlpha: true, bitDepth: 8 },
|
|
4814
|
+
"recraft4": { container: "webp (lossless)", lossless: true, hasAlpha: true, bitDepth: 8 },
|
|
4815
|
+
"seedream4": { container: "jpeg", subsampling: "4:4:4", lossless: false, bitDepth: 8 },
|
|
4816
|
+
"seedream45": { container: "jpeg", subsampling: "4:2:0", lossless: false, bitDepth: 8 },
|
|
4817
|
+
"seedream5": { container: "jpeg", subsampling: "4:2:0", lossless: false, bitDepth: 8 },
|
|
4818
|
+
"seedream5-lite": { container: "jpeg", subsampling: "4:2:0", lossless: false, bitDepth: 8 }
|
|
4819
|
+
};
|
|
4820
|
+
|
|
4821
|
+
// src/model-output.ts
|
|
4822
|
+
function modelOutput(model) {
|
|
4823
|
+
return MODEL_OUTPUT[model];
|
|
4824
|
+
}
|
|
4825
|
+
function losslessAvailability(model) {
|
|
4826
|
+
const shape = MODEL_OUTPUT[model];
|
|
4827
|
+
if (shape === void 0) {
|
|
4828
|
+
return "unknown";
|
|
3227
4829
|
}
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
4830
|
+
if (shape.lossless) {
|
|
4831
|
+
return "default";
|
|
4832
|
+
}
|
|
4833
|
+
return MODELS[model]?.supportsOutputFormat === true ? "on-request" : "unavailable";
|
|
4834
|
+
}
|
|
4835
|
+
function describeModelOutput(model) {
|
|
4836
|
+
const shape = MODEL_OUTPUT[model];
|
|
4837
|
+
if (shape === void 0) {
|
|
4838
|
+
return "not measured";
|
|
4839
|
+
}
|
|
4840
|
+
const base = shape.subsampling === void 0 || shape.subsampling === "" ? shape.container : `${shape.container} ${shape.subsampling}`;
|
|
4841
|
+
const suffix = {
|
|
4842
|
+
default: "lossless",
|
|
4843
|
+
"on-request": "lossless on request",
|
|
4844
|
+
unavailable: "no lossless route",
|
|
4845
|
+
unknown: "lossless route not measured"
|
|
4846
|
+
};
|
|
4847
|
+
return `${base}, ${suffix[losslessAvailability(model)]}`;
|
|
3231
4848
|
}
|
|
3232
4849
|
export {
|
|
3233
4850
|
ASPECT_RATIOS,
|
|
@@ -3238,6 +4855,7 @@ export {
|
|
|
3238
4855
|
FAL_TOOLS,
|
|
3239
4856
|
FAL_TOOLS_CHECKED_AT,
|
|
3240
4857
|
FAL_TOOL_IDS,
|
|
4858
|
+
FAL_TOOL_PARAMETERS,
|
|
3241
4859
|
FORMAT_PRESETS,
|
|
3242
4860
|
FalClient,
|
|
3243
4861
|
GENERATION_MODELS,
|
|
@@ -3245,6 +4863,7 @@ export {
|
|
|
3245
4863
|
IMAGE_EDITING_TOP_20,
|
|
3246
4864
|
IMAGE_TEXT_TO_IMAGE_TOP_20,
|
|
3247
4865
|
MODELS,
|
|
4866
|
+
MODEL_OUTPUT,
|
|
3248
4867
|
MotifError,
|
|
3249
4868
|
RECRAFT_STYLES,
|
|
3250
4869
|
RESOLUTIONS,
|
|
@@ -3256,14 +4875,22 @@ export {
|
|
|
3256
4875
|
aspectToGptSize,
|
|
3257
4876
|
buildFalToolRequest,
|
|
3258
4877
|
buildGenerateBody,
|
|
4878
|
+
describeModelOutput,
|
|
3259
4879
|
enrichPrompt,
|
|
3260
|
-
|
|
4880
|
+
err3 as err,
|
|
3261
4881
|
estimateCost,
|
|
3262
4882
|
estimateVideoCost,
|
|
4883
|
+
falToolParameters,
|
|
4884
|
+
formatCost,
|
|
3263
4885
|
getFalKeyFromEnv,
|
|
3264
4886
|
isFalToolId,
|
|
4887
|
+
losslessAvailability,
|
|
4888
|
+
measuredToolCost,
|
|
4889
|
+
modelOutput,
|
|
3265
4890
|
motifEnvSchema,
|
|
3266
|
-
|
|
4891
|
+
ok3 as ok,
|
|
3267
4892
|
parseMotifEnv,
|
|
3268
|
-
|
|
4893
|
+
projectedToolCost,
|
|
4894
|
+
sanitizePrompt,
|
|
4895
|
+
sumCosts
|
|
3269
4896
|
};
|