@howells/motif-sdk 6.0.0 → 7.1.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.js CHANGED
@@ -3,7 +3,7 @@ import { err, ok } from "neverthrow";
3
3
  import { createFal } from "@ai-sdk/fal";
4
4
  import { createOpenAI } from "@ai-sdk/openai";
5
5
  import { createReplicate } from "@ai-sdk/replicate";
6
- //#region src/errors.ts
6
+ // src/errors.ts
7
7
  /**
8
8
  * `MotifError` and its coercion helper.
9
9
  *
@@ -49,13 +49,11 @@ function falHttpError(status, body, requestId) {
49
49
  if (isFalAccountLocked(status, body)) return new MotifError(`fal account is locked because it is out of credit (fal said: ${body})`, status, ACCOUNT_LOCKED, requestId);
50
50
  return new MotifError(`Request failed: ${status} ${body}`, status, void 0, requestId);
51
51
  }
52
- //#endregion
53
- //#region src/models.ts
52
+ // src/models.ts
54
53
  const AA_IMAGE_LEADERBOARD_SNAPSHOT = "2026-10-07";
55
54
  const AA_IMAGE_SOURCES = ["https://artificialanalysis.ai/image/leaderboard/text-to-image", "https://artificialanalysis.ai/image/leaderboard/editing"];
56
55
  const FAL_PRICING_CHECKED_AT = "2026-05-12";
57
56
  const FAL_PRICING_CHECKED_JUL_2026 = "2026-07-11";
58
- const FAL_PRICING_CHECKED_AUG_2026 = "2026-08-23";
59
57
  const FAL_PRICING_CHECKED_SEP_2026 = "2026-09-16";
60
58
  const FAL_PRICING_CHECKED_OCT_2026 = "2026-10-29";
61
59
  const MODELS = {
@@ -354,7 +352,7 @@ const MODELS = {
354
352
  quality: "frontier",
355
353
  speed: "unknown"
356
354
  },
357
- useCase: "Previous-generation Gemini workhorse; retains 0.5K output"
355
+ useCase: "Gemini workhorse with 0.5K output"
358
356
  },
359
357
  editEndpoint: "fal-ai/nano-banana-2/edit",
360
358
  endpoint: "fal-ai/nano-banana-2",
@@ -459,211 +457,6 @@ const MODELS = {
459
457
  supportsWebSearch: true,
460
458
  type: "generation"
461
459
  },
462
- gemini: {
463
- benchmark: { artificialAnalysis: {
464
- editing: {
465
- elo: 987,
466
- rank: 50
467
- },
468
- snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
469
- sourceUrls: AA_IMAGE_SOURCES,
470
- textToImage: {
471
- elo: 985,
472
- rank: 60
473
- }
474
- } },
475
- editEndpoint: "fal-ai/gemini-25-flash-image/edit",
476
- endpoint: "fal-ai/gemini-25-flash-image",
477
- falPricing: {
478
- checkedAt: FAL_PRICING_CHECKED_AT,
479
- currency: "USD",
480
- endpointId: "fal-ai/gemini-25-flash-image",
481
- estimatedCostPerImageUsd: .0398,
482
- source: "fal-pricing-api",
483
- unit: "images",
484
- unitPrice: .0398
485
- },
486
- maxReferenceImages: 4,
487
- name: "Gemini 2.5 Flash",
488
- pricePerImageUsd: .0398,
489
- pricing: "$0.04",
490
- sizeMode: "aspect_ratio",
491
- supportedAspects: [
492
- "21:9",
493
- "16:9",
494
- "3:2",
495
- "4:3",
496
- "5:4",
497
- "1:1",
498
- "4:5",
499
- "3:4",
500
- "2:3",
501
- "9:16"
502
- ],
503
- supportsAspect: true,
504
- supportsEdit: true,
505
- supportsNumImages: true,
506
- supportsOutputFormat: true,
507
- supportsResolution: false,
508
- supportsSafetyTolerance: true,
509
- supportsSeed: true,
510
- supportsSyncMode: true,
511
- type: "generation"
512
- },
513
- gemini3: {
514
- editEndpoint: "fal-ai/gemini-3-pro-image-preview/edit",
515
- endpoint: "fal-ai/gemini-3-pro-image-preview",
516
- falPricing: {
517
- checkedAt: FAL_PRICING_CHECKED_AT,
518
- currency: "USD",
519
- endpointId: "fal-ai/gemini-3-pro-image-preview",
520
- estimatedCostPerImageUsd: .15,
521
- source: "fal-pricing-api",
522
- unit: "images",
523
- unitPrice: .15
524
- },
525
- maxReferenceImages: 4,
526
- name: "Gemini 3 Pro",
527
- pricePerImageUsd: .15,
528
- pricing: "$0.15",
529
- sizeMode: "aspect_ratio",
530
- supportedAspects: [
531
- "auto",
532
- "21:9",
533
- "16:9",
534
- "3:2",
535
- "4:3",
536
- "5:4",
537
- "1:1",
538
- "4:5",
539
- "3:4",
540
- "2:3",
541
- "9:16"
542
- ],
543
- supportedResolutions: [
544
- "1K",
545
- "2K",
546
- "4K"
547
- ],
548
- supportsAspect: true,
549
- supportsEdit: true,
550
- supportsNumImages: true,
551
- supportsOutputFormat: true,
552
- supportsResolution: true,
553
- supportsSafetyTolerance: true,
554
- supportsSeed: true,
555
- supportsSyncMode: true,
556
- supportsWebSearch: true,
557
- type: "generation"
558
- },
559
- seedream4: {
560
- benchmark: {
561
- artificialAnalysis: {
562
- editing: {
563
- elo: 1015,
564
- rank: 36
565
- },
566
- snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
567
- sourceUrls: AA_IMAGE_SOURCES,
568
- textToImage: {
569
- elo: 1030,
570
- rank: 21
571
- }
572
- },
573
- speed: {
574
- medianSeconds: 14.3,
575
- p95Seconds: 21,
576
- source: "artificial-analysis-models"
577
- },
578
- tiers: {
579
- price: "budget",
580
- quality: "best",
581
- speed: "balanced"
582
- },
583
- useCase: "Legacy budget generation and large multi-reference edits"
584
- },
585
- customImageSize: {
586
- maxPixels: 16777216,
587
- minPixels: 921600
588
- },
589
- editEndpoint: "fal-ai/bytedance/seedream/v4/edit",
590
- endpoint: "fal-ai/bytedance/seedream/v4/text-to-image",
591
- falPricing: {
592
- checkedAt: FAL_PRICING_CHECKED_AT,
593
- currency: "USD",
594
- endpointId: "fal-ai/bytedance/seedream/v4/text-to-image",
595
- estimatedCostPerImageUsd: .03,
596
- source: "fal-pricing-api",
597
- unit: "images",
598
- unitPrice: .03
599
- },
600
- maxReferenceImages: 10,
601
- name: "Seedream 4.0",
602
- pricePerImageUsd: .03,
603
- pricing: "$0.03",
604
- sizeMode: "image_size_enum",
605
- supportsAspect: true,
606
- supportsEdit: true,
607
- supportsNumImages: true,
608
- supportsResolution: false,
609
- supportsSeed: true,
610
- supportsSyncMode: true,
611
- type: "generation"
612
- },
613
- seedream45: {
614
- benchmark: {
615
- artificialAnalysis: {
616
- editing: {
617
- elo: 1037,
618
- rank: 32
619
- },
620
- snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
621
- sourceUrls: AA_IMAGE_SOURCES,
622
- textToImage: {
623
- elo: 1022,
624
- rank: 26
625
- }
626
- },
627
- speed: {
628
- medianSeconds: 18.2,
629
- p95Seconds: 43.3,
630
- source: "artificial-analysis-models"
631
- },
632
- tiers: {
633
- price: "standard",
634
- quality: "better",
635
- speed: "balanced"
636
- },
637
- useCase: "Cheap current Seedream model with good animation/art scores"
638
- },
639
- customImageSize: {
640
- maxPixels: 16777216,
641
- minPixels: 3686400
642
- },
643
- editEndpoint: "fal-ai/bytedance/seedream/v4.5/edit",
644
- endpoint: "fal-ai/bytedance/seedream/v4.5/text-to-image",
645
- falPricing: {
646
- checkedAt: FAL_PRICING_CHECKED_AT,
647
- currency: "USD",
648
- endpointId: "fal-ai/bytedance/seedream/v4.5/text-to-image",
649
- estimatedCostPerImageUsd: .04,
650
- source: "fal-pricing-api",
651
- unit: "images",
652
- unitPrice: .04
653
- },
654
- maxReferenceImages: 10,
655
- name: "Seedream 4.5",
656
- pricePerImageUsd: .04,
657
- pricing: "$0.04",
658
- sizeMode: "image_size_enum",
659
- supportsAspect: true,
660
- supportsEdit: true,
661
- supportsNumImages: true,
662
- supportsResolution: false,
663
- supportsSeed: true,
664
- supportsSyncMode: true,
665
- type: "generation"
666
- },
667
460
  seedream5: {
668
461
  benchmark: { artificialAnalysis: {
669
462
  editing: {
@@ -747,65 +540,6 @@ const MODELS = {
747
540
  supportsSyncMode: true,
748
541
  maxReferenceImages: 10
749
542
  },
750
- "flux2-max": {
751
- benchmark: {
752
- artificialAnalysis: {
753
- editing: {
754
- elo: 997,
755
- rank: 49
756
- },
757
- snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
758
- sourceUrls: AA_IMAGE_SOURCES,
759
- textToImage: {
760
- elo: 1020,
761
- rank: 28
762
- }
763
- },
764
- speed: {
765
- medianSeconds: 31.6,
766
- p95Seconds: 41,
767
- source: "artificial-analysis-models"
768
- },
769
- tiers: {
770
- price: "premium",
771
- quality: "best",
772
- speed: "slow"
773
- },
774
- useCase: "Best FLUX quality and high-end editing"
775
- },
776
- customImageSize: {
777
- maxEdge: 2560,
778
- maxPixels: 4194304,
779
- minEdge: 256,
780
- multipleOf: 16
781
- },
782
- editEndpoint: "fal-ai/flux-2-max/edit",
783
- endpoint: "fal-ai/flux-2-max",
784
- falPricing: {
785
- checkedAt: FAL_PRICING_CHECKED_AT,
786
- currency: "USD",
787
- endpointId: "fal-ai/flux-2-max",
788
- estimatedCostPerImageUsd: .07,
789
- source: "fal-pricing-api",
790
- unit: "megapixels",
791
- unitPrice: .07
792
- },
793
- maxReferenceImages: 10,
794
- name: "FLUX.2 Max",
795
- pricePerImageUsd: .07,
796
- pricing: "$0.07/MP",
797
- sizeMode: "image_size_enum",
798
- supportsAspect: true,
799
- supportsEdit: true,
800
- supportsNumImages: false,
801
- supportsOutputFormat: true,
802
- supportsResolution: false,
803
- supportsSafetyChecker: true,
804
- supportsSafetyTolerance: true,
805
- supportsSeed: true,
806
- supportsSyncMode: true,
807
- type: "generation"
808
- },
809
543
  "flux2-pro": {
810
544
  benchmark: {
811
545
  artificialAnalysis: {
@@ -927,69 +661,6 @@ const MODELS = {
927
661
  supportsSyncMode: true,
928
662
  type: "generation"
929
663
  },
930
- "flux2-dev": {
931
- benchmark: {
932
- artificialAnalysis: {
933
- editing: {
934
- elo: 1e3,
935
- rank: 45
936
- },
937
- snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
938
- sourceUrls: AA_IMAGE_SOURCES,
939
- textToImage: {
940
- elo: 1e3,
941
- rank: 42
942
- }
943
- },
944
- speed: {
945
- medianSeconds: 4.6,
946
- p95Seconds: 69.6,
947
- source: "artificial-analysis-models"
948
- },
949
- tiers: {
950
- price: "variable",
951
- quality: "better",
952
- speed: "fast"
953
- },
954
- useCase: "Open FLUX.2 quality with low average cost"
955
- },
956
- customImageSize: {
957
- maxEdge: 2048,
958
- minEdge: 512
959
- },
960
- editEndpoint: "fal-ai/flux-2/edit",
961
- endpoint: "fal-ai/flux-2",
962
- falPricing: {
963
- checkedAt: FAL_PRICING_CHECKED_AT,
964
- currency: "USD",
965
- endpointId: "fal-ai/flux-2",
966
- estimatedCostPerImageUsd: .012,
967
- source: "fal-pricing-api",
968
- unit: "compute seconds",
969
- unitPrice: .00167
970
- },
971
- maxReferenceImages: 4,
972
- name: "FLUX.2 [dev]",
973
- pricePerImageUsd: .012,
974
- pricing: "$0.00167/sec",
975
- sizeMode: "image_size_enum",
976
- supportsAspect: true,
977
- streaming: {
978
- generation: true,
979
- edit: true
980
- },
981
- supportsEdit: true,
982
- supportsGuidanceScale: true,
983
- supportsInferenceSteps: true,
984
- supportsNumImages: true,
985
- supportsOutputFormat: true,
986
- supportsResolution: false,
987
- supportsSafetyChecker: true,
988
- supportsSafetyTolerance: true,
989
- supportsSeed: true,
990
- supportsSyncMode: true,
991
- type: "generation"
992
- },
993
664
  "flux2-turbo": {
994
665
  customImageSize: {
995
666
  maxEdge: 2048,
@@ -1020,188 +691,6 @@ const MODELS = {
1020
691
  supportsSyncMode: true,
1021
692
  type: "generation"
1022
693
  },
1023
- flux: {
1024
- endpoint: "fal-ai/flux-pro/v1.1-ultra",
1025
- falPricing: {
1026
- checkedAt: FAL_PRICING_CHECKED_AT,
1027
- currency: "USD",
1028
- endpointId: "fal-ai/flux-pro/v1.1-ultra",
1029
- estimatedCostPerImageUsd: .06,
1030
- source: "fal-pricing-api",
1031
- unit: "images",
1032
- unitPrice: .06
1033
- },
1034
- maxReferenceImages: 1,
1035
- name: "FLUX Pro Ultra",
1036
- pricePerImageUsd: .06,
1037
- pricing: "$0.06",
1038
- sizeMode: "aspect_ratio",
1039
- supportsAspect: true,
1040
- supportsEdit: true,
1041
- supportsEnhancePrompt: true,
1042
- supportsImagePromptStrength: true,
1043
- supportsNumImages: true,
1044
- supportsOutputFormat: true,
1045
- supportsRaw: true,
1046
- supportsResolution: false,
1047
- supportsSafetyTolerance: true,
1048
- supportsSeed: true,
1049
- supportsSyncMode: true,
1050
- type: "generation"
1051
- },
1052
- "flux-fast": {
1053
- customImageSize: {},
1054
- endpoint: "fal-ai/flux/schnell",
1055
- falPricing: {
1056
- checkedAt: FAL_PRICING_CHECKED_AT,
1057
- currency: "USD",
1058
- endpointId: "fal-ai/flux/schnell",
1059
- estimatedCostPerImageUsd: .003,
1060
- source: "fal-pricing-api",
1061
- unit: "megapixels",
1062
- unitPrice: .003
1063
- },
1064
- name: "FLUX Schnell",
1065
- pricePerImageUsd: .003,
1066
- pricing: "$0.003",
1067
- sizeMode: "image_size_enum",
1068
- supportsAspect: true,
1069
- supportsEdit: false,
1070
- supportsGuidanceScale: true,
1071
- supportsInferenceSteps: true,
1072
- supportsNumImages: true,
1073
- supportsOutputFormat: true,
1074
- supportsResolution: false,
1075
- supportsSeed: true,
1076
- supportsSyncMode: true,
1077
- type: "generation"
1078
- },
1079
- recraft: {
1080
- customImageSize: {},
1081
- endpoint: "fal-ai/recraft/v3/text-to-image",
1082
- falPricing: {
1083
- checkedAt: FAL_PRICING_CHECKED_AT,
1084
- currency: "USD",
1085
- endpointId: "fal-ai/recraft/v3/text-to-image",
1086
- estimatedCostPerImageUsd: .04,
1087
- source: "fal-pricing-api",
1088
- unit: "images",
1089
- unitPrice: .04
1090
- },
1091
- name: "Recraft V3",
1092
- pricePerImageUsd: .04,
1093
- pricing: "$0.04",
1094
- sizeMode: "image_size_enum",
1095
- supportsAspect: true,
1096
- supportsEdit: false,
1097
- supportsNumImages: false,
1098
- supportsResolution: false,
1099
- supportsStyle: true,
1100
- supportsSyncMode: true,
1101
- type: "generation"
1102
- },
1103
- reve: {
1104
- benchmark: {
1105
- tiers: {
1106
- price: "premium",
1107
- quality: "frontier",
1108
- speed: "unknown"
1109
- },
1110
- useCase: "Historical Reve route; not currently verified on fal"
1111
- },
1112
- editEndpoint: "fal-ai/reve/edit",
1113
- endpoint: "fal-ai/reve/text-to-image",
1114
- falPricing: {
1115
- checkedAt: FAL_PRICING_CHECKED_AUG_2026,
1116
- currency: "USD",
1117
- endpointId: "fal-ai/reve/text-to-image",
1118
- estimatedCostPerImageUsd: .04,
1119
- source: "fal-pricing-api",
1120
- unit: "images",
1121
- unitPrice: .04
1122
- },
1123
- maxReferenceImages: 1,
1124
- name: "Reve 2.1",
1125
- pricePerImageUsd: .04,
1126
- pricing: "$0.04",
1127
- sizeMode: "aspect_ratio",
1128
- supportedAspects: [
1129
- "16:9",
1130
- "9:16",
1131
- "3:2",
1132
- "2:3",
1133
- "4:3",
1134
- "3:4",
1135
- "1:1"
1136
- ],
1137
- supportsAspect: true,
1138
- supportsEdit: true,
1139
- supportsNumImages: true,
1140
- supportsOutputFormat: true,
1141
- supportsResolution: false,
1142
- supportsSeed: false,
1143
- supportsSyncMode: true,
1144
- type: "generation"
1145
- },
1146
- recraft4: {
1147
- benchmark: { artificialAnalysis: {
1148
- snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
1149
- sourceUrls: AA_IMAGE_SOURCES,
1150
- textToImage: {
1151
- elo: 984,
1152
- rank: 62
1153
- }
1154
- } },
1155
- customImageSize: {},
1156
- endpoint: "fal-ai/recraft/v4/text-to-image",
1157
- falPricing: {
1158
- checkedAt: FAL_PRICING_CHECKED_JUL_2026,
1159
- currency: "USD",
1160
- endpointId: "fal-ai/recraft/v4/text-to-image",
1161
- estimatedCostPerImageUsd: .04,
1162
- source: "fal-pricing-api",
1163
- unit: "images",
1164
- unitPrice: .04
1165
- },
1166
- name: "Recraft V4",
1167
- pricePerImageUsd: .04,
1168
- pricing: "$0.04",
1169
- sizeMode: "image_size_enum",
1170
- supportsAspect: true,
1171
- supportsEdit: false,
1172
- supportsNumImages: false,
1173
- supportsResolution: false,
1174
- supportsSyncMode: true,
1175
- type: "generation"
1176
- },
1177
- ideogram: {
1178
- customImageSize: {},
1179
- endpoint: "fal-ai/ideogram/v3",
1180
- falPricing: {
1181
- checkedAt: FAL_PRICING_CHECKED_AT,
1182
- currency: "USD",
1183
- endpointId: "fal-ai/ideogram/v3",
1184
- estimatedCostPerImageUsd: .03,
1185
- source: "fal-pricing-api",
1186
- unit: "images",
1187
- unitPrice: .03
1188
- },
1189
- name: "Ideogram V3",
1190
- pricePerImageUsd: .03,
1191
- pricing: "$0.03",
1192
- sizeMode: "image_size_enum",
1193
- supportsAspect: true,
1194
- supportsEdit: false,
1195
- supportsExpandPrompt: true,
1196
- supportsNegativePrompt: true,
1197
- supportsNumImages: true,
1198
- supportsRenderingSpeed: true,
1199
- supportsResolution: false,
1200
- supportsSeed: true,
1201
- supportsStyle: true,
1202
- supportsSyncMode: true,
1203
- type: "generation"
1204
- },
1205
694
  ideogram4: {
1206
695
  benchmark: { artificialAnalysis: {
1207
696
  snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
@@ -1302,52 +791,6 @@ const MODELS = {
1302
791
  supportsSyncMode: true,
1303
792
  type: "generation"
1304
793
  },
1305
- qwen: {
1306
- benchmark: {
1307
- artificialAnalysis: {
1308
- snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
1309
- sourceUrls: AA_IMAGE_SOURCES,
1310
- textToImage: {
1311
- elo: 890,
1312
- rank: 106
1313
- }
1314
- },
1315
- speed: {
1316
- medianSeconds: 23.3,
1317
- p95Seconds: 491,
1318
- source: "artificial-analysis-models"
1319
- },
1320
- tiers: {
1321
- price: "budget",
1322
- quality: "better",
1323
- speed: "slow"
1324
- },
1325
- useCase: "Low-cost open-weight text and design generation"
1326
- },
1327
- customImageSize: {},
1328
- endpoint: "fal-ai/qwen-image",
1329
- falPricing: {
1330
- checkedAt: FAL_PRICING_CHECKED_AT,
1331
- currency: "USD",
1332
- endpointId: "fal-ai/qwen-image",
1333
- estimatedCostPerImageUsd: .02,
1334
- source: "fal-pricing-api",
1335
- unit: "megapixels",
1336
- unitPrice: .02
1337
- },
1338
- name: "Qwen Image",
1339
- pricePerImageUsd: .02,
1340
- pricing: "$0.02/MP",
1341
- sizeMode: "image_size_enum",
1342
- supportsAspect: true,
1343
- supportsEdit: false,
1344
- supportsNumImages: true,
1345
- supportsOutputFormat: true,
1346
- supportsResolution: false,
1347
- supportsSeed: true,
1348
- supportsSyncMode: true,
1349
- type: "generation"
1350
- },
1351
794
  qwen3: {
1352
795
  benchmark: {
1353
796
  artificialAnalysis: {
@@ -1748,26 +1191,6 @@ const MODELS = {
1748
1191
  supportsNumImages: false,
1749
1192
  supportsResolution: false,
1750
1193
  type: "utility"
1751
- },
1752
- rmbg: {
1753
- endpoint: "fal-ai/birefnet",
1754
- name: "BiRefNet (Background Removal)",
1755
- pricing: "$0.02",
1756
- supportsAspect: false,
1757
- supportsEdit: false,
1758
- supportsNumImages: false,
1759
- supportsResolution: false,
1760
- type: "utility"
1761
- },
1762
- bria: {
1763
- endpoint: "fal-ai/bria/background/remove",
1764
- name: "Bria RMBG 2.0",
1765
- pricing: "$0.02",
1766
- supportsAspect: false,
1767
- supportsEdit: false,
1768
- supportsNumImages: false,
1769
- supportsResolution: false,
1770
- type: "utility"
1771
1194
  }
1772
1195
  };
1773
1196
  [
@@ -1795,8 +1218,7 @@ const MODELS = {
1795
1218
  "ideogram3-transparent",
1796
1219
  "recraft41"
1797
1220
  ].filter((id) => MODELS[id]?.supportsEdit === true);
1798
- //#endregion
1799
- //#region src/capabilities.ts
1221
+ // src/capabilities.ts
1800
1222
  /** Generation options a model can refuse, with the registry test for each. */
1801
1223
  const OPTION_CAPABILITIES = {
1802
1224
  aspect: (config) => (config.sizeMode ?? "aspect_ratio") !== "none",
@@ -1804,11 +1226,9 @@ const OPTION_CAPABILITIES = {
1804
1226
  enableGoogleSearch: (config) => config.supportsGoogleSearch === true,
1805
1227
  enableSafetyChecker: (config) => config.supportsSafetyChecker === true,
1806
1228
  enableWebSearch: (config) => config.supportsWebSearch === true,
1807
- enhancePrompt: (config) => config.supportsEnhancePrompt === true,
1808
1229
  expandPrompt: (config) => config.supportsExpandPrompt === true,
1809
1230
  guidanceScale: (config) => config.supportsGuidanceScale === true,
1810
1231
  "image editing": (config) => config.supportsEdit,
1811
- imagePromptStrength: (config) => config.supportsImagePromptStrength === true,
1812
1232
  imageSize: (config) => config.sizeMode === "gpt_size" || config.sizeMode === "image_size_enum",
1813
1233
  inputFidelity: (config) => config.sizeMode === "gpt_size",
1814
1234
  limitGenerations: (config) => config.supportsLimitGenerations === true,
@@ -1819,12 +1239,10 @@ const OPTION_CAPABILITIES = {
1819
1239
  numInferenceSteps: (config) => config.supportsInferenceSteps === true,
1820
1240
  outputFormat: (config) => config.supportsOutputFormat === true,
1821
1241
  quality: (config) => config.supportsQuality === true,
1822
- raw: (config) => config.supportsRaw === true,
1823
1242
  renderingSpeed: (config) => config.supportsRenderingSpeed === true,
1824
1243
  resolution: (config) => config.supportsResolution,
1825
1244
  safetyTolerance: (config) => config.supportsSafetyTolerance === true,
1826
1245
  seed: (config) => config.supportsSeed === true,
1827
- style: (config) => config.supportsStyle === true,
1828
1246
  syncMode: (config) => config.supportsSyncMode === true,
1829
1247
  thinkingLevel: (config) => config.supportsThinkingLevel === true,
1830
1248
  "transparent output": (config) => config.supportsBackground === true || config.transparentOutput === true
@@ -1878,7 +1296,7 @@ Object.keys(OPTION_CAPABILITIES).filter(isModelOption);
1878
1296
  description: "Natural, unposed documentary portraits of people. Pair with a mood for the light.",
1879
1297
  id: "portrait",
1880
1298
  label: "Documentary portrait",
1881
- model: "seedream45"
1299
+ model: "seedream5"
1882
1300
  },
1883
1301
  {
1884
1302
  acceptsMood: false,
@@ -1957,8 +1375,7 @@ Object.keys(OPTION_CAPABILITIES).filter(isModelOption);
1957
1375
  }
1958
1376
  ]
1959
1377
  }).look;
1960
- //#endregion
1961
- //#region src/tool-registry/analysis.ts
1378
+ // src/tool-registry/analysis.ts
1962
1379
  const ANALYSIS_TOOLS = {
1963
1380
  "got-ocr": {
1964
1381
  category: "analysis",
@@ -2072,8 +1489,7 @@ const ANALYSIS_TOOLS = {
2072
1489
  task: "vision moderation"
2073
1490
  }
2074
1491
  };
2075
- //#endregion
2076
- //#region src/tool-registry/assets.ts
1492
+ // src/tool-registry/assets.ts
2077
1493
  const ASSET_TOOLS = {
2078
1494
  "hunyuan3d-v3": {
2079
1495
  category: "3d",
@@ -2391,8 +1807,7 @@ const ASSET_TOOLS = {
2391
1807
  task: "single-image 3D reconstruction"
2392
1808
  }
2393
1809
  };
2394
- //#endregion
2395
- //#region src/tool-registry/background.ts
1810
+ // src/tool-registry/background.ts
2396
1811
  const BACKGROUND_TOOLS = {
2397
1812
  "ben-v2": {
2398
1813
  category: "background",
@@ -2767,8 +2182,7 @@ const BACKGROUND_TOOLS = {
2767
2182
  task: "video enhancement"
2768
2183
  }
2769
2184
  };
2770
- //#endregion
2771
- //#region src/tool-registry/editing.ts
2185
+ // src/tool-registry/editing.ts
2772
2186
  const EDITING_TOOLS = {
2773
2187
  "bria-eraser": {
2774
2188
  category: "erase",
@@ -3039,8 +2453,7 @@ const EDITING_TOOLS = {
3039
2453
  task: "virtual garment try-on"
3040
2454
  }
3041
2455
  };
3042
- //#endregion
3043
- //#region src/tool-registry/structure.ts
2456
+ // src/tool-registry/structure.ts
3044
2457
  const STRUCTURE_TOOLS = {
3045
2458
  "depth-anything": {
3046
2459
  category: "preprocess",
@@ -3432,8 +2845,7 @@ const STRUCTURE_TOOLS = {
3432
2845
  task: "depth preprocessing"
3433
2846
  }
3434
2847
  };
3435
- //#endregion
3436
- //#region src/tools.ts
2848
+ // src/tools.ts
3437
2849
  const FAL_TOOLS = {
3438
2850
  ...ANALYSIS_TOOLS,
3439
2851
  ...ASSET_TOOLS,
@@ -3442,8 +2854,7 @@ const FAL_TOOLS = {
3442
2854
  ...STRUCTURE_TOOLS
3443
2855
  };
3444
2856
  Object.keys(FAL_TOOLS);
3445
- //#endregion
3446
- //#region src/image/fetch.ts
2857
+ // src/image/fetch.ts
3447
2858
  function urlOf(input) {
3448
2859
  if (typeof input === "string") return input;
3449
2860
  return input instanceof URL ? input.href : input.url;
@@ -3453,16 +2864,14 @@ function toProviderFetch(fetch) {
3453
2864
  if (fetch === void 0) return {};
3454
2865
  return { fetch: async (input, init) => await fetch(urlOf(input), init ?? {}) };
3455
2866
  }
3456
- //#endregion
3457
- //#region src/image/fal.ts
2867
+ // src/image/fal.ts
3458
2868
  /**
3459
2869
  * fal provider adapter.
3460
2870
  *
3461
2871
  * Builds a Vercel AI SDK `ImageModel` from `@ai-sdk/fal`. Building a model
3462
2872
  * performs no network I/O — the request only happens when `generateImage`
3463
2873
  * invokes `model.doGenerate`. This is the lightweight fal *image* adapter; the
3464
- * richer `FalClient` fal client (queue, upload, upscale, rmbg, video, tools)
3465
- * is a separate, later fold (design doc §8, phase 1d).
2874
+ * richer `FalClient` fal client (queue, upload, tools) is separate.
3466
2875
  *
3467
2876
  * ENDPOINT QUIRK (Phase 0): fal's gpt-image endpoint wants `image_size` as a
3468
2877
  * STRING enum (e.g. "1024x1024"), passed at generate time via
@@ -3476,47 +2885,31 @@ function toProviderFetch(fetch) {
3476
2885
  * providerOptions: { fal: { image_size: "1024x1024" } },
3477
2886
  * });
3478
2887
  */
3479
- /**
3480
- * fal endpoint ids proven to work with this adapter and priced in
3481
- * {@link FAL_IMAGE_PRICE_USD} below (FLUX Pro Ultra + gpt-image).
3482
- */
3483
- const FAL_FLUX_MODEL = "fal-ai/flux-pro/v1.1-ultra";
2888
+ /** The gpt-image endpoint id priced in {@link FAL_IMAGE_PRICE_USD} below. */
3484
2889
  const FAL_GPT_IMAGE_MODEL = "fal-ai/gpt-image-1.5";
3485
2890
  /** Env var read for the fal key when `apiKey` is not supplied in config. */
3486
2891
  const FAL_API_KEY_ENV = "FAL_KEY";
3487
2892
  /**
3488
2893
  * Static fal USD/image, keyed by the fal ENDPOINT id. Cost tracking must price
3489
- * the endpoints consumers actually pass — kiln uses
3490
- * `fal-ai/flux/schnell`, `fal-ai/flux-2-pro`, `fal-ai/flux-2-max`. Every price is
2894
+ * the endpoints consumers actually pass. Every price is
3491
2895
  * sourced from the fal registry snapshot in `../models`
3492
2896
  * (`MODELS[...].pricePerImageUsd`) so this table stays in sync rather than
3493
2897
  * drifting to a second hand-maintained copy; the `??` fallbacks are the registry
3494
2898
  * values at time of writing, used only if a registry entry loses its optional
3495
2899
  * price. Each key is `MODELS[x].endpoint`; the trailing comment cites the
3496
- * `MODELS` key it comes from. Covers the flux/flux2 family, banana, seedream, and
2900
+ * `MODELS` key it comes from. Covers the flux2 family, banana, seedream, and
3497
2901
  * the other priced fal generation endpoints.
3498
2902
  */
3499
2903
  const FAL_IMAGE_PRICE_USD = {
3500
- [FAL_FLUX_MODEL]: MODELS.flux?.pricePerImageUsd ?? .06,
3501
- "fal-ai/flux/schnell": MODELS["flux-fast"]?.pricePerImageUsd ?? .003,
3502
- "fal-ai/flux-2-max": MODELS["flux2-max"]?.pricePerImageUsd ?? .07,
3503
2904
  "fal-ai/flux-2-pro": MODELS["flux2-pro"]?.pricePerImageUsd ?? .03,
3504
2905
  "fal-ai/flux-2-flex": MODELS["flux2-flex"]?.pricePerImageUsd ?? .05,
3505
- "fal-ai/flux-2": MODELS["flux2-dev"]?.pricePerImageUsd ?? .012,
3506
2906
  "fal-ai/flux-2/turbo": MODELS["flux2-turbo"]?.pricePerImageUsd ?? .008,
3507
2907
  [FAL_GPT_IMAGE_MODEL]: MODELS.gpt?.pricePerImageUsd ?? .133,
3508
2908
  "fal-ai/nano-banana-2": MODELS.banana2?.pricePerImageUsd ?? .08,
3509
2909
  "fal-ai/nano-banana-pro": MODELS.banana?.pricePerImageUsd ?? .15,
3510
- "fal-ai/gemini-25-flash-image": MODELS.gemini?.pricePerImageUsd ?? .0398,
3511
- "fal-ai/gemini-3-pro-image-preview": MODELS.gemini3?.pricePerImageUsd ?? .15,
3512
- "fal-ai/bytedance/seedream/v4/text-to-image": MODELS.seedream4?.pricePerImageUsd ?? .03,
3513
- "fal-ai/bytedance/seedream/v4.5/text-to-image": MODELS.seedream45?.pricePerImageUsd ?? .04,
3514
2910
  "bytedance/seedream/v5/pro/text-to-image": MODELS.seedream5?.pricePerImageUsd ?? .0675,
3515
2911
  "bytedance/seedream/v5/lite/text-to-image": MODELS["seedream5-lite"]?.pricePerImageUsd ?? .035,
3516
- "fal-ai/recraft/v3/text-to-image": MODELS.recraft?.pricePerImageUsd ?? .04,
3517
- "fal-ai/recraft/v4/text-to-image": MODELS.recraft4?.pricePerImageUsd ?? .04,
3518
2912
  "fal-ai/recraft/v4.1/text-to-image": MODELS.recraft41?.pricePerImageUsd ?? .035,
3519
- "fal-ai/ideogram/v3": MODELS.ideogram?.pricePerImageUsd ?? .03,
3520
2913
  "ideogram/v4": MODELS.ideogram4?.pricePerImageUsd ?? .03,
3521
2914
  "xai/grok-imagine-image": MODELS["grok-image"]?.pricePerImageUsd ?? .02,
3522
2915
  "xai/grok-imagine-image/v2.0/text-to-image": MODELS["grok-image-2"]?.pricePerImageUsd ?? .06,
@@ -3524,8 +2917,7 @@ const FAL_IMAGE_PRICE_USD = {
3524
2917
  "meta/muse-image/text-to-image": MODELS["muse-image"]?.pricePerImageUsd ?? .01,
3525
2918
  "microsoft/mai-image-2.5-pro": MODELS["mai-image-2.5-pro"]?.pricePerImageUsd ?? .17,
3526
2919
  "fal-ai/ideogram/v3/generate-transparent": MODELS["ideogram3-transparent"]?.pricePerImageUsd ?? .06,
3527
- "alibaba/qwen-image-3/text-to-image": MODELS.qwen3?.pricePerImageUsd ?? .04,
3528
- "fal-ai/qwen-image": MODELS.qwen?.pricePerImageUsd ?? .02
2920
+ "alibaba/qwen-image-3/text-to-image": MODELS.qwen3?.pricePerImageUsd ?? .04
3529
2921
  };
3530
2922
  /**
3531
2923
  * Build a fal `ImageModel`. Prefers the passed `apiKey`, else the `FAL_KEY` env
@@ -3558,8 +2950,7 @@ const falAdapter = {
3558
2950
  resolveModel: resolveModel$3,
3559
2951
  priceUsdByModel: FAL_IMAGE_PRICE_USD
3560
2952
  };
3561
- //#endregion
3562
- //#region src/image/openai.ts
2953
+ // src/image/openai.ts
3563
2954
  /**
3564
2955
  * OpenAI (gpt-image) provider adapter.
3565
2956
  *
@@ -3605,8 +2996,7 @@ const openaiAdapter = {
3605
2996
  resolveModel: resolveModel$2,
3606
2997
  priceUsdByModel: OPENAI_IMAGE_PRICE_USD
3607
2998
  };
3608
- //#endregion
3609
- //#region src/image/openrouter.ts
2999
+ // src/image/openrouter.ts
3610
3000
  /** Env var read for the OpenRouter API key when `apiKey` is not supplied in config. */
3611
3001
  const OPENROUTER_API_KEY_ENV = "OPENROUTER_API_KEY";
3612
3002
  const OPENROUTER_IMAGES_URL = "https://openrouter.ai/api/v1/images";
@@ -3769,8 +3159,7 @@ const openrouterAdapter = {
3769
3159
  resolveModel: resolveModel$1,
3770
3160
  priceUsdByModel: OPENROUTER_IMAGE_PRICE_USD
3771
3161
  };
3772
- //#endregion
3773
- //#region src/image/replicate.ts
3162
+ // src/image/replicate.ts
3774
3163
  /**
3775
3164
  * Replicate provider adapter.
3776
3165
  *
@@ -3805,8 +3194,7 @@ function resolveModel(modelId, apiKey, fetch) {
3805
3194
  ...toProviderFetch(fetch)
3806
3195
  }).image(modelId);
3807
3196
  }
3808
- //#endregion
3809
- //#region src/image/provider.ts
3197
+ // src/image/provider.ts
3810
3198
  /**
3811
3199
  * The provider registry. Every id in {@link ImageProviderId}'s closed part maps
3812
3200
  * to its adapter; the open union tail means a lookup can still miss, so access
@@ -3832,8 +3220,7 @@ function getProviderAdapter(provider) {
3832
3220
  if (adapter === void 0) throw new MotifError(`Unsupported image provider: ${provider}`, 0);
3833
3221
  return adapter;
3834
3222
  }
3835
- //#endregion
3836
- //#region src/image/cost.ts
3223
+ // src/image/cost.ts
3837
3224
  /**
3838
3225
  * Per-call cost tracking for the image layer.
3839
3226
  *
@@ -3903,8 +3290,7 @@ function costForCalls(provider, modelId, callMetadata, imageCount) {
3903
3290
  source: "unknown"
3904
3291
  };
3905
3292
  }
3906
- //#endregion
3907
- //#region src/image/index.ts
3293
+ // src/image/index.ts
3908
3294
  /**
3909
3295
  * `@howells/motif-sdk/image` — provider-agnostic image generation + editing.
3910
3296
  *
@@ -4176,5 +3562,4 @@ function toMotifError(error) {
4176
3562
  if (isFalAccountLocked(status, body)) return falHttpError(status, body);
4177
3563
  return new MotifError(message, status, code);
4178
3564
  }
4179
- //#endregion
4180
3565
  export { FAL_API_KEY_ENV, OPENAI_API_KEY_ENV, OPENROUTER_API_KEY_ENV, PROVIDERS, REPLICATE_API_KEY_ENV, costForImages, costFromProviderMetadata, createMotifImage, getProviderAdapter, providerPricePerImageUsd };