@howells/motif-sdk 7.1.0 → 7.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/README.md +5 -3
- package/dist/image.d.ts +3 -10
- package/dist/image.js +118 -1711
- package/dist/index.cjs +6403 -5996
- package/dist/index.d.cts +132 -36
- package/dist/index.d.ts +132 -36
- package/dist/index.js +6401 -5997
- package/dist/registry.d.ts +253 -183
- package/dist/registry.js +151 -67
- package/package.json +1 -1
package/dist/image.js
CHANGED
|
@@ -4,14 +4,7 @@ import { createFal } from "@ai-sdk/fal";
|
|
|
4
4
|
import { createOpenAI } from "@ai-sdk/openai";
|
|
5
5
|
import { createReplicate } from "@ai-sdk/replicate";
|
|
6
6
|
// src/errors.ts
|
|
7
|
-
/**
|
|
8
|
-
* `MotifError` and its coercion helper.
|
|
9
|
-
*
|
|
10
|
-
* Extracted from `server.ts` so `server-tools.ts` can construct errors without
|
|
11
|
-
* importing back into `server.ts` — that import was a dependency cycle. Both
|
|
12
|
-
* `server.ts` and `server-tools.ts` import from here, and `server.ts`
|
|
13
|
-
* re-exports `MotifError` so the package's public surface is unchanged.
|
|
14
|
-
*/
|
|
7
|
+
/** `MotifError` and the fal HTTP error mapping. */
|
|
15
8
|
var MotifError = class extends Error {
|
|
16
9
|
status;
|
|
17
10
|
code;
|
|
@@ -49,6 +42,16 @@ function falHttpError(status, body, requestId) {
|
|
|
49
42
|
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
43
|
return new MotifError(`Request failed: ${status} ${body}`, status, void 0, requestId);
|
|
51
44
|
}
|
|
45
|
+
// src/fal-parse.ts
|
|
46
|
+
/**
|
|
47
|
+
* Boundary parsing for fal.ai HTTP responses.
|
|
48
|
+
*
|
|
49
|
+
* `Response.json()` yields `any`; these helpers narrow that untyped payload into
|
|
50
|
+
* the SDK's response types with runtime guards instead of unchecked assertions.
|
|
51
|
+
*/
|
|
52
|
+
function isRecord(value) {
|
|
53
|
+
return typeof value === "object" && value !== null;
|
|
54
|
+
}
|
|
52
55
|
// src/models.ts
|
|
53
56
|
const AA_IMAGE_LEADERBOARD_SNAPSHOT = "2026-10-07";
|
|
54
57
|
const AA_IMAGE_SOURCES = ["https://artificialanalysis.ai/image/leaderboard/text-to-image", "https://artificialanalysis.ai/image/leaderboard/editing"];
|
|
@@ -95,6 +98,8 @@ const MODELS = {
|
|
|
95
98
|
maskImageField: "mask_url",
|
|
96
99
|
supportsMarkupImage: true,
|
|
97
100
|
autoEditSize: true,
|
|
101
|
+
maxCount: 10,
|
|
102
|
+
singleImageFormats: ["svg"],
|
|
98
103
|
supportsNumImages: true,
|
|
99
104
|
supportsOutputFormat: true,
|
|
100
105
|
supportedOutputFormats: [
|
|
@@ -119,7 +124,7 @@ const MODELS = {
|
|
|
119
124
|
"xhigh",
|
|
120
125
|
"max"
|
|
121
126
|
],
|
|
122
|
-
supportsResolution:
|
|
127
|
+
supportsResolution: true,
|
|
123
128
|
supportsSyncMode: true,
|
|
124
129
|
type: "generation",
|
|
125
130
|
useQueue: true
|
|
@@ -162,6 +167,8 @@ const MODELS = {
|
|
|
162
167
|
maskImageField: "mask_url",
|
|
163
168
|
supportsMarkupImage: true,
|
|
164
169
|
autoEditSize: true,
|
|
170
|
+
maxCount: 10,
|
|
171
|
+
singleImageFormats: ["svg"],
|
|
165
172
|
supportsNumImages: true,
|
|
166
173
|
supportsOutputFormat: true,
|
|
167
174
|
supportedOutputFormats: [
|
|
@@ -186,7 +193,7 @@ const MODELS = {
|
|
|
186
193
|
"xhigh",
|
|
187
194
|
"max"
|
|
188
195
|
],
|
|
189
|
-
supportsResolution:
|
|
196
|
+
supportsResolution: true,
|
|
190
197
|
supportsSyncMode: true,
|
|
191
198
|
type: "generation",
|
|
192
199
|
useQueue: true
|
|
@@ -233,6 +240,12 @@ const MODELS = {
|
|
|
233
240
|
pricePerImageUsd: .133,
|
|
234
241
|
pricing: "$0.133",
|
|
235
242
|
sizeMode: "gpt_size",
|
|
243
|
+
supportedAspects: [
|
|
244
|
+
"auto",
|
|
245
|
+
"1:1",
|
|
246
|
+
"3:2",
|
|
247
|
+
"2:3"
|
|
248
|
+
],
|
|
236
249
|
supportsAspect: false,
|
|
237
250
|
supportsBackground: true,
|
|
238
251
|
streaming: {
|
|
@@ -241,6 +254,7 @@ const MODELS = {
|
|
|
241
254
|
},
|
|
242
255
|
supportsEdit: true,
|
|
243
256
|
supportsMaskImage: true,
|
|
257
|
+
maxCount: 4,
|
|
244
258
|
supportsNumImages: true,
|
|
245
259
|
supportsOutputFormat: true,
|
|
246
260
|
supportsQuality: true,
|
|
@@ -282,6 +296,7 @@ const MODELS = {
|
|
|
282
296
|
supportsAspect: true,
|
|
283
297
|
supportsEdit: true,
|
|
284
298
|
supportsLimitGenerations: true,
|
|
299
|
+
maxCount: 4,
|
|
285
300
|
supportsNumImages: true,
|
|
286
301
|
supportsOutputFormat: true,
|
|
287
302
|
supportsResolution: true,
|
|
@@ -327,6 +342,7 @@ const MODELS = {
|
|
|
327
342
|
],
|
|
328
343
|
supportsAspect: true,
|
|
329
344
|
supportsEdit: true,
|
|
345
|
+
maxCount: 4,
|
|
330
346
|
supportsNumImages: true,
|
|
331
347
|
supportsOutputFormat: true,
|
|
332
348
|
supportsResolution: false,
|
|
@@ -374,6 +390,7 @@ const MODELS = {
|
|
|
374
390
|
supportsEdit: true,
|
|
375
391
|
supportsGoogleSearch: true,
|
|
376
392
|
supportsLimitGenerations: true,
|
|
393
|
+
maxCount: 4,
|
|
377
394
|
supportsNumImages: true,
|
|
378
395
|
supportsOutputFormat: true,
|
|
379
396
|
supportsResolution: true,
|
|
@@ -448,6 +465,7 @@ const MODELS = {
|
|
|
448
465
|
supportsEdit: true,
|
|
449
466
|
supportsGoogleSearch: true,
|
|
450
467
|
supportsLimitGenerations: true,
|
|
468
|
+
maxCount: 4,
|
|
451
469
|
supportsNumImages: true,
|
|
452
470
|
supportsOutputFormat: true,
|
|
453
471
|
supportsResolution: true,
|
|
@@ -494,6 +512,7 @@ const MODELS = {
|
|
|
494
512
|
supportsAspect: true,
|
|
495
513
|
supportsResolution: false,
|
|
496
514
|
supportsEdit: true,
|
|
515
|
+
maxCount: 6,
|
|
497
516
|
supportsNumImages: true,
|
|
498
517
|
supportsSeed: true,
|
|
499
518
|
supportsSyncMode: true,
|
|
@@ -535,6 +554,7 @@ const MODELS = {
|
|
|
535
554
|
supportsAspect: true,
|
|
536
555
|
supportsResolution: false,
|
|
537
556
|
supportsEdit: true,
|
|
557
|
+
maxCount: 6,
|
|
538
558
|
supportsNumImages: true,
|
|
539
559
|
supportsSeed: true,
|
|
540
560
|
supportsSyncMode: true,
|
|
@@ -683,6 +703,7 @@ const MODELS = {
|
|
|
683
703
|
supportsAspect: true,
|
|
684
704
|
supportsEdit: false,
|
|
685
705
|
supportsGuidanceScale: true,
|
|
706
|
+
maxCount: 4,
|
|
686
707
|
supportsNumImages: true,
|
|
687
708
|
supportsOutputFormat: true,
|
|
688
709
|
supportsResolution: false,
|
|
@@ -723,6 +744,7 @@ const MODELS = {
|
|
|
723
744
|
supportsAspect: true,
|
|
724
745
|
supportsResolution: false,
|
|
725
746
|
supportsEdit: false,
|
|
747
|
+
maxCount: 4,
|
|
726
748
|
supportsNumImages: true,
|
|
727
749
|
supportsRenderingSpeed: true,
|
|
728
750
|
supportsSeed: true,
|
|
@@ -768,6 +790,7 @@ const MODELS = {
|
|
|
768
790
|
unit: "images",
|
|
769
791
|
unitPrice: .02
|
|
770
792
|
},
|
|
793
|
+
lowercaseResolution: true,
|
|
771
794
|
maxReferenceImages: 3,
|
|
772
795
|
name: "Grok Imagine Image",
|
|
773
796
|
pricePerImageUsd: .02,
|
|
@@ -785,6 +808,7 @@ const MODELS = {
|
|
|
785
808
|
supportedResolutions: ["1K", "2K"],
|
|
786
809
|
supportsAspect: true,
|
|
787
810
|
supportsEdit: true,
|
|
811
|
+
maxCount: 4,
|
|
788
812
|
supportsNumImages: true,
|
|
789
813
|
supportsOutputFormat: true,
|
|
790
814
|
supportsResolution: true,
|
|
@@ -835,6 +859,7 @@ const MODELS = {
|
|
|
835
859
|
supportsAspect: true,
|
|
836
860
|
supportsEdit: true,
|
|
837
861
|
supportsNegativePrompt: true,
|
|
862
|
+
maxCount: 6,
|
|
838
863
|
supportsNumImages: true,
|
|
839
864
|
supportsOutputFormat: true,
|
|
840
865
|
supportsResolution: false,
|
|
@@ -887,6 +912,7 @@ const MODELS = {
|
|
|
887
912
|
],
|
|
888
913
|
supportsAspect: true,
|
|
889
914
|
supportsEdit: true,
|
|
915
|
+
maxCount: 4,
|
|
890
916
|
supportsNumImages: true,
|
|
891
917
|
supportsOutputFormat: true,
|
|
892
918
|
supportsResolution: false,
|
|
@@ -916,6 +942,7 @@ const MODELS = {
|
|
|
916
942
|
supportsAspect: true,
|
|
917
943
|
supportsEdit: true,
|
|
918
944
|
supportsLimitGenerations: true,
|
|
945
|
+
maxCount: 4,
|
|
919
946
|
supportsNumImages: true,
|
|
920
947
|
supportsOutputFormat: true,
|
|
921
948
|
supportsResolution: false,
|
|
@@ -940,6 +967,7 @@ const MODELS = {
|
|
|
940
967
|
pricePerImageUsd: .06,
|
|
941
968
|
pricing: "$0.03 TURBO / $0.06 BALANCED / $0.09 QUALITY",
|
|
942
969
|
sizeMode: "aspect_ratio",
|
|
970
|
+
fixedOutputFormat: "png",
|
|
943
971
|
supportedAspects: [
|
|
944
972
|
"16:9",
|
|
945
973
|
"9:16",
|
|
@@ -955,6 +983,7 @@ const MODELS = {
|
|
|
955
983
|
supportsEdit: false,
|
|
956
984
|
supportsExpandPrompt: true,
|
|
957
985
|
supportsNegativePrompt: true,
|
|
986
|
+
maxCount: 8,
|
|
958
987
|
supportsNumImages: true,
|
|
959
988
|
supportsRenderingSpeed: true,
|
|
960
989
|
supportsResolution: false,
|
|
@@ -1013,6 +1042,7 @@ const MODELS = {
|
|
|
1013
1042
|
unit: "images",
|
|
1014
1043
|
unitPrice: .06
|
|
1015
1044
|
},
|
|
1045
|
+
lowercaseResolution: true,
|
|
1016
1046
|
maxReferenceImages: 3,
|
|
1017
1047
|
name: "Grok Imagine Image 2.0",
|
|
1018
1048
|
pricePerImageUsd: .06,
|
|
@@ -1030,6 +1060,7 @@ const MODELS = {
|
|
|
1030
1060
|
supportedResolutions: ["1K", "2K"],
|
|
1031
1061
|
supportsAspect: true,
|
|
1032
1062
|
supportsEdit: true,
|
|
1063
|
+
maxCount: 10,
|
|
1033
1064
|
supportsNumImages: true,
|
|
1034
1065
|
supportsOutputFormat: true,
|
|
1035
1066
|
supportsResolution: true,
|
|
@@ -1072,6 +1103,7 @@ const MODELS = {
|
|
|
1072
1103
|
],
|
|
1073
1104
|
supportsAspect: true,
|
|
1074
1105
|
supportsEdit: true,
|
|
1106
|
+
maxCount: 10,
|
|
1075
1107
|
supportsNumImages: true,
|
|
1076
1108
|
supportsOutputFormat: true,
|
|
1077
1109
|
supportsResolution: false,
|
|
@@ -1127,6 +1159,7 @@ const MODELS = {
|
|
|
1127
1159
|
unit: "images",
|
|
1128
1160
|
unitPrice: .05
|
|
1129
1161
|
},
|
|
1162
|
+
lowercaseResolution: true,
|
|
1130
1163
|
maxReferenceImages: 3,
|
|
1131
1164
|
name: "Grok Imagine Image Quality",
|
|
1132
1165
|
pricePerImageUsd: .05,
|
|
@@ -1144,6 +1177,7 @@ const MODELS = {
|
|
|
1144
1177
|
supportedResolutions: ["1K", "2K"],
|
|
1145
1178
|
supportsAspect: true,
|
|
1146
1179
|
supportsEdit: true,
|
|
1180
|
+
maxCount: 4,
|
|
1147
1181
|
supportsNumImages: true,
|
|
1148
1182
|
supportsOutputFormat: true,
|
|
1149
1183
|
supportsResolution: true,
|
|
@@ -1152,1708 +1186,87 @@ const MODELS = {
|
|
|
1152
1186
|
},
|
|
1153
1187
|
kling: {
|
|
1154
1188
|
endpoint: "fal-ai/kling-video/v3/pro/image-to-video",
|
|
1189
|
+
generatesAudio: true,
|
|
1155
1190
|
name: "Kling v3 Pro",
|
|
1191
|
+
outputKeys: ["video"],
|
|
1192
|
+
price: {
|
|
1193
|
+
audioUsd: .168,
|
|
1194
|
+
kind: "output-second",
|
|
1195
|
+
usd: .112
|
|
1196
|
+
},
|
|
1156
1197
|
pricing: "$0.11/sec",
|
|
1157
1198
|
sizeMode: "none",
|
|
1199
|
+
startFrameField: "start_image_url",
|
|
1158
1200
|
supportsAspect: false,
|
|
1159
1201
|
supportsEdit: false,
|
|
1160
1202
|
supportsNumImages: false,
|
|
1161
1203
|
supportsResolution: false,
|
|
1162
|
-
type: "video"
|
|
1204
|
+
type: "video",
|
|
1205
|
+
useQueue: true
|
|
1163
1206
|
},
|
|
1164
1207
|
"kling-turbo": {
|
|
1165
1208
|
endpoint: "fal-ai/kling-video/v3/turbo/pro/image-to-video",
|
|
1166
1209
|
name: "Kling v3 Turbo Pro",
|
|
1210
|
+
outputKeys: ["video"],
|
|
1211
|
+
price: {
|
|
1212
|
+
kind: "output-second",
|
|
1213
|
+
usd: .14
|
|
1214
|
+
},
|
|
1167
1215
|
pricing: "$0.14/sec",
|
|
1168
1216
|
sizeMode: "none",
|
|
1217
|
+
startFrameField: "image_url",
|
|
1169
1218
|
supportsAspect: false,
|
|
1170
1219
|
supportsEdit: false,
|
|
1171
1220
|
supportsNumImages: false,
|
|
1172
1221
|
supportsResolution: false,
|
|
1173
|
-
type: "video"
|
|
1222
|
+
type: "video",
|
|
1223
|
+
useQueue: true
|
|
1174
1224
|
},
|
|
1175
1225
|
clarity: {
|
|
1226
|
+
defaultScale: 2,
|
|
1176
1227
|
endpoint: "fal-ai/clarity-upscaler",
|
|
1177
1228
|
name: "Clarity Upscaler",
|
|
1229
|
+
outputKeys: ["image"],
|
|
1230
|
+
price: {
|
|
1231
|
+
kind: "megapixel",
|
|
1232
|
+
usd: .03
|
|
1233
|
+
},
|
|
1178
1234
|
pricing: "$0.03/MP",
|
|
1235
|
+
scaleField: "upscale_factor",
|
|
1236
|
+
scaleRange: {
|
|
1237
|
+
max: 4,
|
|
1238
|
+
min: 1
|
|
1239
|
+
},
|
|
1179
1240
|
supportsAspect: false,
|
|
1180
1241
|
supportsEdit: false,
|
|
1181
1242
|
supportsNumImages: false,
|
|
1243
|
+
supportsPrompt: true,
|
|
1182
1244
|
supportsResolution: false,
|
|
1183
1245
|
type: "utility"
|
|
1184
1246
|
},
|
|
1185
1247
|
crystal: {
|
|
1248
|
+
defaultScale: 2,
|
|
1186
1249
|
endpoint: "clarityai/crystal-upscaler",
|
|
1187
1250
|
name: "Crystal Upscaler",
|
|
1188
|
-
pricing: "$0.02",
|
|
1189
|
-
supportsAspect: false,
|
|
1190
|
-
supportsEdit: false,
|
|
1191
|
-
supportsNumImages: false,
|
|
1192
|
-
supportsResolution: false,
|
|
1193
|
-
type: "utility"
|
|
1194
|
-
}
|
|
1195
|
-
};
|
|
1196
|
-
[
|
|
1197
|
-
"sunburst",
|
|
1198
|
-
"flare",
|
|
1199
|
-
"gpt",
|
|
1200
|
-
"banana21",
|
|
1201
|
-
"banana2",
|
|
1202
|
-
"banana",
|
|
1203
|
-
"mai-image-2.5",
|
|
1204
|
-
"mai-image-2.5-pro",
|
|
1205
|
-
"seedream5",
|
|
1206
|
-
"qwen3",
|
|
1207
|
-
"banana2-lite",
|
|
1208
|
-
"grok-image-2",
|
|
1209
|
-
"grok-image-quality",
|
|
1210
|
-
"grok-image",
|
|
1211
|
-
"muse-image",
|
|
1212
|
-
"krea3",
|
|
1213
|
-
"flux2-flex",
|
|
1214
|
-
"flux2-pro",
|
|
1215
|
-
"flux2-turbo",
|
|
1216
|
-
"seedream5-lite",
|
|
1217
|
-
"ideogram4",
|
|
1218
|
-
"ideogram3-transparent",
|
|
1219
|
-
"recraft41"
|
|
1220
|
-
].filter((id) => MODELS[id]?.supportsEdit === true);
|
|
1221
|
-
// src/capabilities.ts
|
|
1222
|
-
/** Generation options a model can refuse, with the registry test for each. */
|
|
1223
|
-
const OPTION_CAPABILITIES = {
|
|
1224
|
-
aspect: (config) => (config.sizeMode ?? "aspect_ratio") !== "none",
|
|
1225
|
-
background: (config) => config.supportsBackground === true,
|
|
1226
|
-
enableGoogleSearch: (config) => config.supportsGoogleSearch === true,
|
|
1227
|
-
enableSafetyChecker: (config) => config.supportsSafetyChecker === true,
|
|
1228
|
-
enableWebSearch: (config) => config.supportsWebSearch === true,
|
|
1229
|
-
expandPrompt: (config) => config.supportsExpandPrompt === true,
|
|
1230
|
-
guidanceScale: (config) => config.supportsGuidanceScale === true,
|
|
1231
|
-
"image editing": (config) => config.supportsEdit,
|
|
1232
|
-
imageSize: (config) => config.sizeMode === "gpt_size" || config.sizeMode === "image_size_enum",
|
|
1233
|
-
inputFidelity: (config) => config.sizeMode === "gpt_size",
|
|
1234
|
-
limitGenerations: (config) => config.supportsLimitGenerations === true,
|
|
1235
|
-
markupImageUrl: (config) => config.supportsMarkupImage === true,
|
|
1236
|
-
maskImageUrl: (config) => config.supportsMaskImage === true,
|
|
1237
|
-
negativePrompt: (config) => config.supportsNegativePrompt === true,
|
|
1238
|
-
numImages: (config) => config.supportsNumImages,
|
|
1239
|
-
numInferenceSteps: (config) => config.supportsInferenceSteps === true,
|
|
1240
|
-
outputFormat: (config) => config.supportsOutputFormat === true,
|
|
1241
|
-
quality: (config) => config.supportsQuality === true,
|
|
1242
|
-
renderingSpeed: (config) => config.supportsRenderingSpeed === true,
|
|
1243
|
-
resolution: (config) => config.supportsResolution,
|
|
1244
|
-
safetyTolerance: (config) => config.supportsSafetyTolerance === true,
|
|
1245
|
-
seed: (config) => config.supportsSeed === true,
|
|
1246
|
-
syncMode: (config) => config.supportsSyncMode === true,
|
|
1247
|
-
thinkingLevel: (config) => config.supportsThinkingLevel === true,
|
|
1248
|
-
"transparent output": (config) => config.supportsBackground === true || config.transparentOutput === true
|
|
1249
|
-
};
|
|
1250
|
-
function isModelOption(key) {
|
|
1251
|
-
return Object.hasOwn(OPTION_CAPABILITIES, key);
|
|
1252
|
-
}
|
|
1253
|
-
Object.keys(OPTION_CAPABILITIES).filter(isModelOption);
|
|
1254
|
-
({
|
|
1255
|
-
look: [
|
|
1256
|
-
{
|
|
1257
|
-
acceptsMood: true,
|
|
1258
|
-
aspect: "1:1",
|
|
1259
|
-
clause: "Editorial photograph in the register of Atelier Ellis, Aman hotels, Kinfolk magazine and Aesop, pigment-rich mineral colour on named matte surfaces, quiet composition with generous negative space, shallow depth of field, shot on film with fine grain, restrained and materially rich. No text, no logos, no people",
|
|
1260
|
-
description: "Quiet, materially rich editorial photography for brand and mood imagery.",
|
|
1261
|
-
id: "editorial",
|
|
1262
|
-
label: "Quiet editorial",
|
|
1263
|
-
model: "flux2-pro"
|
|
1264
|
-
},
|
|
1265
|
-
{
|
|
1266
|
-
acceptsMood: true,
|
|
1267
|
-
aspect: "1:1",
|
|
1268
|
-
clause: "Editorial still life in the register of Aesop and Kinfolk, on a warm bone plaster ground, chalky unglazed surfaces in muted mineral colour, a long soft shadow, generous empty space, shot on film with fine grain, restrained and materially rich. No text, no logos, no people",
|
|
1269
|
-
description: "Objects and products on a plaster ground, for product and editorial still life.",
|
|
1270
|
-
id: "still-life",
|
|
1271
|
-
label: "Editorial still life",
|
|
1272
|
-
model: "flux2-pro"
|
|
1273
|
-
},
|
|
1274
|
-
{
|
|
1275
|
-
acceptsMood: true,
|
|
1276
|
-
aspect: "3:2",
|
|
1277
|
-
clause: "Interior photograph in the register of House & Garden and Kinfolk, shot square-on at eye level on a 35mm lens, warm off-white plaster, wide oak floorboards, linen, brass and a little pattern, light, bright and layered, collected rather than styled, lived-in rather than showroom-perfect, soft natural daylight, shot on film with fine grain. No text, no logos, no people",
|
|
1278
|
-
description: "Bright, collected rooms that feel lived in, for interior scenes.",
|
|
1279
|
-
id: "interior",
|
|
1280
|
-
label: "Interior",
|
|
1281
|
-
model: "flux2-pro"
|
|
1282
|
-
},
|
|
1283
|
-
{
|
|
1284
|
-
acceptsMood: true,
|
|
1285
|
-
aspect: "4:5",
|
|
1286
|
-
clause: "Architectural photograph in the register of House & Garden and Kinfolk, a considered house seen from outside at editorial distance with its garden and setting, pale render, stone or timber meeting precise detailing, clipped planting, soft warm daylight and long shadow, generous negative space, immaculate and calm, shot on film with fine grain. No text, no logos, no people",
|
|
1287
|
-
description: "Buildings and their settings from outside, for architecture, property and place.",
|
|
1288
|
-
id: "architectural",
|
|
1289
|
-
label: "Architectural exterior",
|
|
1290
|
-
model: "banana"
|
|
1291
|
-
},
|
|
1292
|
-
{
|
|
1293
|
-
acceptsMood: true,
|
|
1294
|
-
aspect: "1:1",
|
|
1295
|
-
clause: "Editorial documentary portrait in the register of Kinfolk, muted warm palette, waist-up and unposed against a plain plaster or linen ground, plain clothing with no logos, soft natural light, shot on film with fine grain. No text",
|
|
1296
|
-
description: "Natural, unposed documentary portraits of people. Pair with a mood for the light.",
|
|
1297
|
-
id: "portrait",
|
|
1298
|
-
label: "Documentary portrait",
|
|
1299
|
-
model: "seedream5"
|
|
1300
|
-
},
|
|
1301
|
-
{
|
|
1302
|
-
acceptsMood: false,
|
|
1303
|
-
aspect: "1:1",
|
|
1304
|
-
clause: "A single matte object centred with generous empty space, soft diffused studio light, minimal and quiet in the register of Aesop, one committed muted mineral colour on a plain ground. No text, no logos, no people",
|
|
1305
|
-
description: "One object in one colour on a clean ground, for icons and simple product shots.",
|
|
1306
|
-
id: "object",
|
|
1307
|
-
label: "Studio object",
|
|
1308
|
-
model: "flux2-pro"
|
|
1309
|
-
},
|
|
1310
|
-
{
|
|
1311
|
-
acceptsMood: false,
|
|
1312
|
-
aspect: "1:1",
|
|
1313
|
-
clause: "Straight-on orthographic photograph of the surface filling the entire frame edge to edge, even shadowless studio light, crisp macro texture, colour-accurate and quietly material. No text, no logos",
|
|
1314
|
-
description: "Flat, edge-to-edge surface photographs, for textures, backgrounds and material swatches.",
|
|
1315
|
-
id: "surface",
|
|
1316
|
-
label: "Flat surface",
|
|
1317
|
-
model: "flux2-pro"
|
|
1318
|
-
},
|
|
1319
|
-
{
|
|
1320
|
-
acceptsMood: false,
|
|
1321
|
-
aspect: "3:2",
|
|
1322
|
-
clause: "Painted abstraction filling the frame edge to edge, mineral pigment and chalk gesso on coarse natural linen, two or three confident gestures, warm ivory, oatmeal, putty and soft charcoal, flat diffuse reproduction light. No text",
|
|
1323
|
-
description: "Painted abstraction edge to edge, for wall art, heroes and calm backgrounds.",
|
|
1324
|
-
id: "abstract",
|
|
1325
|
-
label: "Painted abstract",
|
|
1326
|
-
model: "banana"
|
|
1327
|
-
},
|
|
1328
|
-
{
|
|
1329
|
-
acceptsMood: false,
|
|
1330
|
-
aspect: "1:1",
|
|
1331
|
-
clause: "Stylised editorial illustration in the register of Kinfolk, colour laid as flat planes in a warm muted palette of ivory, putty, sage and charcoal, fine hand-drawn line with a gentle gouache wash, generous empty space, clearly a drawing rather than a photograph. No text, no logos",
|
|
1332
|
-
description: "Line and gouache illustration of any subject, for drawn editorial imagery.",
|
|
1333
|
-
experimental: true,
|
|
1334
|
-
id: "illustration",
|
|
1335
|
-
label: "Editorial illustration",
|
|
1336
|
-
model: "flare"
|
|
1337
|
-
}
|
|
1338
|
-
],
|
|
1339
|
-
mood: [
|
|
1340
|
-
{
|
|
1341
|
-
clause: "soft natural daylight from a window out of frame, gentle falloff into the corners, low contrast, even diffused light with soft, held highlights",
|
|
1342
|
-
description: "Soft, even daylight from a window. The safe default.",
|
|
1343
|
-
id: "window",
|
|
1344
|
-
label: "Window light"
|
|
1345
|
-
},
|
|
1346
|
-
{
|
|
1347
|
-
clause: "early morning light through tall glazing, cool and clear",
|
|
1348
|
-
description: "Cool, clear early morning light.",
|
|
1349
|
-
id: "dawn",
|
|
1350
|
-
label: "Dawn"
|
|
1351
|
-
},
|
|
1352
|
-
{
|
|
1353
|
-
clause: "low raking daylight from the left, long soft shadows that reveal texture",
|
|
1354
|
-
description: "Low side light that brings out surface texture.",
|
|
1355
|
-
id: "raking",
|
|
1356
|
-
label: "Raking light"
|
|
1357
|
-
},
|
|
1358
|
-
{
|
|
1359
|
-
clause: "overcast afternoon with rain on a tall window, soft even grey light",
|
|
1360
|
-
description: "Soft grey light on a rainy afternoon.",
|
|
1361
|
-
id: "overcast",
|
|
1362
|
-
label: "Overcast"
|
|
1363
|
-
},
|
|
1364
|
-
{
|
|
1365
|
-
clause: "evening, warm practical lamps around 2400K, candles and a lit fire, cosy and warm, never gloomy",
|
|
1366
|
-
description: "Warm evening light from lamps, candles and a fire.",
|
|
1367
|
-
id: "lamplit",
|
|
1368
|
-
label: "Lamplit evening"
|
|
1369
|
-
},
|
|
1370
|
-
{
|
|
1371
|
-
clause: "night, one warm low practical light, deep shadow, candlelit",
|
|
1372
|
-
description: "Dark night scene lit by one warm low light.",
|
|
1373
|
-
id: "nocturne",
|
|
1374
|
-
label: "Nocturne"
|
|
1375
|
-
}
|
|
1376
|
-
]
|
|
1377
|
-
}).look;
|
|
1378
|
-
// src/tool-registry/analysis.ts
|
|
1379
|
-
const ANALYSIS_TOOLS = {
|
|
1380
|
-
"got-ocr": {
|
|
1381
|
-
category: "analysis",
|
|
1382
|
-
description: "Transcribe text from one or more images, optionally as formatted multi-page output.",
|
|
1383
|
-
endpoint: "fal-ai/got-ocr/v2",
|
|
1384
|
-
inputField: "input_image_urls",
|
|
1385
|
-
inputKind: "images",
|
|
1386
|
-
name: "GOT-OCR 2.0",
|
|
1387
|
-
outputKeys: ["outputs"],
|
|
1388
|
-
price: {
|
|
1389
|
-
kind: "call",
|
|
1390
|
-
per: ["input_image_urls"],
|
|
1391
|
-
usd: .05
|
|
1392
|
-
},
|
|
1393
|
-
pricing: "$0.05/image",
|
|
1394
|
-
queued: true,
|
|
1395
|
-
sourceUrl: "https://fal.ai/models/fal-ai/got-ocr/v2",
|
|
1396
|
-
task: "optical character recognition"
|
|
1397
|
-
},
|
|
1398
|
-
"moondream-caption": {
|
|
1399
|
-
category: "analysis",
|
|
1400
|
-
description: "Write a short, normal, or long caption for an image.",
|
|
1401
|
-
endpoint: "fal-ai/moondream3-preview/caption",
|
|
1402
|
-
inputField: "image_url",
|
|
1403
|
-
inputKind: "image",
|
|
1404
|
-
name: "Moondream 3 Caption",
|
|
1405
|
-
outputKeys: ["output"],
|
|
1406
|
-
price: {
|
|
1407
|
-
inputPerMillion: .4,
|
|
1408
|
-
inputTokens: 737,
|
|
1409
|
-
kind: "token",
|
|
1410
|
-
outputPerMillion: 3.5,
|
|
1411
|
-
outputTokens: 200
|
|
1412
|
-
},
|
|
1413
|
-
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1414
|
-
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/caption",
|
|
1415
|
-
task: "image captioning"
|
|
1416
|
-
},
|
|
1417
|
-
"moondream-detect": {
|
|
1418
|
-
category: "analysis",
|
|
1419
|
-
description: "Detect prompted objects and return their bounding boxes, with an optional preview.",
|
|
1420
|
-
endpoint: "fal-ai/moondream3-preview/detect",
|
|
1421
|
-
inputField: "image_url",
|
|
1422
|
-
inputKind: "image",
|
|
1423
|
-
name: "Moondream 3 Detect",
|
|
1424
|
-
outputKeys: ["objects", "image"],
|
|
1425
|
-
price: {
|
|
1426
|
-
inputPerMillion: .4,
|
|
1427
|
-
inputTokens: 737,
|
|
1428
|
-
kind: "token",
|
|
1429
|
-
outputPerMillion: 3.5,
|
|
1430
|
-
outputTokens: 100
|
|
1431
|
-
},
|
|
1432
|
-
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1433
|
-
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/detect",
|
|
1434
|
-
task: "object detection"
|
|
1435
|
-
},
|
|
1436
|
-
"moondream-point": {
|
|
1437
|
-
category: "analysis",
|
|
1438
|
-
description: "Return point coordinates for every instance of a prompted subject.",
|
|
1439
|
-
endpoint: "fal-ai/moondream3-preview/point",
|
|
1440
|
-
inputField: "image_url",
|
|
1441
|
-
inputKind: "image",
|
|
1442
|
-
name: "Moondream 3 Point",
|
|
1443
|
-
outputKeys: ["points", "image"],
|
|
1444
|
-
price: {
|
|
1445
|
-
inputPerMillion: .4,
|
|
1446
|
-
inputTokens: 737,
|
|
1447
|
-
kind: "token",
|
|
1448
|
-
outputPerMillion: 3.5,
|
|
1449
|
-
outputTokens: 100
|
|
1450
|
-
},
|
|
1451
|
-
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1452
|
-
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/point",
|
|
1453
|
-
task: "object pointing"
|
|
1454
|
-
},
|
|
1455
|
-
"moondream-query": {
|
|
1456
|
-
category: "analysis",
|
|
1457
|
-
description: "Answer a free-form question about an image, with reasoning.",
|
|
1458
|
-
endpoint: "fal-ai/moondream3-preview/query",
|
|
1459
|
-
inputField: "image_url",
|
|
1460
|
-
inputKind: "image",
|
|
1461
|
-
name: "Moondream 3 Query",
|
|
1462
|
-
outputKeys: ["output", "reasoning"],
|
|
1463
|
-
price: {
|
|
1464
|
-
inputPerMillion: .4,
|
|
1465
|
-
inputTokens: 737,
|
|
1466
|
-
kind: "token",
|
|
1467
|
-
outputPerMillion: 3.5,
|
|
1468
|
-
outputTokens: 500
|
|
1469
|
-
},
|
|
1470
|
-
pricing: "$0.40/M input tokens, $3.50/M output tokens",
|
|
1471
|
-
sourceUrl: "https://fal.ai/models/fal-ai/moondream3-preview/query",
|
|
1472
|
-
task: "visual question answering"
|
|
1473
|
-
},
|
|
1474
|
-
nsfw: {
|
|
1475
|
-
category: "moderation",
|
|
1476
|
-
description: "Predict whether one or more images contain NSFW concepts.",
|
|
1477
|
-
endpoint: "fal-ai/x-ailab/nsfw",
|
|
1478
|
-
inputField: "image_urls",
|
|
1479
|
-
inputKind: "images",
|
|
1480
|
-
name: "NSFW Checker",
|
|
1481
|
-
outputKeys: ["has_nsfw_concepts"],
|
|
1482
|
-
price: {
|
|
1483
|
-
kind: "call",
|
|
1484
|
-
per: ["image_urls"],
|
|
1485
|
-
usd: .001
|
|
1486
|
-
},
|
|
1487
|
-
pricing: "$0.001/image",
|
|
1488
|
-
sourceUrl: "https://fal.ai/models/fal-ai/x-ailab/nsfw",
|
|
1489
|
-
task: "vision moderation"
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1492
|
-
// src/tool-registry/assets.ts
|
|
1493
|
-
const ASSET_TOOLS = {
|
|
1494
|
-
"hunyuan3d-v3": {
|
|
1495
|
-
category: "3d",
|
|
1496
|
-
description: "Reconstruct a textured 3D mesh from a single image, with optional multi-view inputs.",
|
|
1497
|
-
endpoint: "fal-ai/hunyuan3d-v3/image-to-3d",
|
|
1498
|
-
inputField: "input_image_url",
|
|
1499
|
-
inputKind: "image",
|
|
1500
|
-
name: "Hunyuan3D v3 Image to 3D",
|
|
1501
|
-
outputKeys: [
|
|
1502
|
-
"model_glb",
|
|
1503
|
-
"model_urls",
|
|
1504
|
-
"thumbnail"
|
|
1505
|
-
],
|
|
1506
|
-
price: {
|
|
1507
|
-
kind: "call",
|
|
1508
|
-
usd: .375
|
|
1509
|
-
},
|
|
1510
|
-
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",
|
|
1511
|
-
queued: true,
|
|
1512
|
-
sourceUrl: "https://fal.ai/models/fal-ai/hunyuan3d-v3/image-to-3d",
|
|
1513
|
-
task: "single-image 3D reconstruction"
|
|
1514
|
-
},
|
|
1515
|
-
"ideogram-layerize-text": {
|
|
1516
|
-
category: "layers",
|
|
1517
|
-
description: "Split an image into background image layers plus editable HTML text containers.",
|
|
1518
|
-
endpoint: "fal-ai/ideogram/v3/layerize-text",
|
|
1519
|
-
inputField: "image_url",
|
|
1520
|
-
inputKind: "image",
|
|
1521
|
-
name: "Ideogram v3 Text Layerize",
|
|
1522
|
-
outputKeys: [
|
|
1523
|
-
"image_layers",
|
|
1524
|
-
"image",
|
|
1525
|
-
"text_html",
|
|
1526
|
-
"text_containers"
|
|
1527
|
-
],
|
|
1528
|
-
price: {
|
|
1529
|
-
kind: "call",
|
|
1530
|
-
usd: .09
|
|
1531
|
-
},
|
|
1532
|
-
pricing: "$0.09/image",
|
|
1533
|
-
queued: true,
|
|
1534
|
-
sourceUrl: "https://fal.ai/models/fal-ai/ideogram/v3/layerize-text",
|
|
1535
|
-
task: "text and image layer extraction"
|
|
1536
|
-
},
|
|
1537
|
-
"ideogram-tiling": {
|
|
1538
|
-
category: "material",
|
|
1539
|
-
description: "Generate a seamlessly tiling texture, optionally conditioned on a source image.",
|
|
1540
|
-
endpoint: "ideogram/v4/tiling",
|
|
1541
|
-
inputField: "image_url",
|
|
1542
|
-
inputKind: "image",
|
|
1543
|
-
name: "Ideogram v4 Tiling",
|
|
1544
|
-
outputKeys: ["images"],
|
|
1545
|
-
price: {
|
|
1546
|
-
kind: "megapixel",
|
|
1547
|
-
usd: .06
|
|
1548
|
-
},
|
|
1549
|
-
pricing: "$0.06/megapixel at the default BALANCED speed; $0.03 turbo, $0.10 quality",
|
|
1550
|
-
sourceUrl: "https://fal.ai/models/ideogram/v4/tiling",
|
|
1551
|
-
task: "seamless texture generation"
|
|
1552
|
-
},
|
|
1553
|
-
image2svg: {
|
|
1554
|
-
category: "vector",
|
|
1555
|
-
description: "Trace a raster image into layered SVG paths.",
|
|
1556
|
-
endpoint: "fal-ai/image2svg",
|
|
1557
|
-
inputField: "image_url",
|
|
1558
|
-
inputKind: "image",
|
|
1559
|
-
name: "Image to SVG",
|
|
1560
|
-
outputKeys: ["images"],
|
|
1561
|
-
price: {
|
|
1562
|
-
kind: "call",
|
|
1563
|
-
usd: .005
|
|
1564
|
-
},
|
|
1565
|
-
pricing: "$0.005/image",
|
|
1566
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image2svg",
|
|
1567
|
-
task: "raster to vector tracing"
|
|
1568
|
-
},
|
|
1569
|
-
"meshy-v7": {
|
|
1570
|
-
category: "3d",
|
|
1571
|
-
description: "Make a textured 3D mesh from one image, optionally rigged for animation.",
|
|
1572
|
-
endpoint: "meshy/v7/image-to-3d",
|
|
1573
|
-
inputField: "image_url",
|
|
1574
|
-
inputKind: "image",
|
|
1575
|
-
name: "Meshy v7 Image to 3D",
|
|
1576
|
-
outputKeys: [
|
|
1577
|
-
"model_glb",
|
|
1578
|
-
"model_urls",
|
|
1579
|
-
"thumbnail",
|
|
1580
|
-
"rigged_character_glb",
|
|
1581
|
-
"rigged_character_fbx"
|
|
1582
|
-
],
|
|
1583
|
-
price: {
|
|
1584
|
-
extras: {
|
|
1585
|
-
enable_animation: .12,
|
|
1586
|
-
enable_rigging: .2,
|
|
1587
|
-
ultra_mode: .2
|
|
1588
|
-
},
|
|
1589
|
-
kind: "call",
|
|
1590
|
-
usd: 1.2
|
|
1591
|
-
},
|
|
1592
|
-
pricing: "$1.20/generation at the default textured model; $0.80 untextured, $1.40 ultra, plus $0.20 for rigging and $0.12 for animation",
|
|
1593
|
-
queued: true,
|
|
1594
|
-
sourceUrl: "https://fal.ai/models/meshy/v7/image-to-3d",
|
|
1595
|
-
task: "single-image 3D reconstruction"
|
|
1596
|
-
},
|
|
1597
|
-
patina: {
|
|
1598
|
-
category: "material",
|
|
1599
|
-
description: "Decompose a surface photograph into PBR maps: basecolor, normal, roughness, metalness, height.",
|
|
1600
|
-
endpoint: "fal-ai/patina",
|
|
1601
|
-
inputField: "image_url",
|
|
1602
|
-
inputKind: "image",
|
|
1603
|
-
name: "Patina PBR Maps",
|
|
1604
|
-
outputKeys: ["images"],
|
|
1605
|
-
outputLabels: { images: {
|
|
1606
|
-
fallback: [
|
|
1607
|
-
"basecolor",
|
|
1608
|
-
"normal",
|
|
1609
|
-
"roughness",
|
|
1610
|
-
"metalness",
|
|
1611
|
-
"height"
|
|
1612
|
-
],
|
|
1613
|
-
fromOption: "maps"
|
|
1614
|
-
} },
|
|
1615
|
-
price: {
|
|
1616
|
-
base: .01,
|
|
1617
|
-
kind: "maps",
|
|
1618
|
-
perMapMegapixel: .01,
|
|
1619
|
-
perMegapixel: 0
|
|
1620
|
-
},
|
|
1621
|
-
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",
|
|
1622
|
-
queued: true,
|
|
1623
|
-
sourceUrl: "https://fal.ai/models/fal-ai/patina",
|
|
1624
|
-
task: "PBR material decomposition"
|
|
1625
|
-
},
|
|
1626
|
-
"patina-extract": {
|
|
1627
|
-
category: "material",
|
|
1628
|
-
description: "Extract a tiling PBR material from a prompted region of a photograph.",
|
|
1629
|
-
endpoint: "fal-ai/patina/material/extract",
|
|
1630
|
-
inputField: "image_url",
|
|
1631
|
-
inputKind: "image",
|
|
1632
|
-
name: "Patina Material Extract",
|
|
1633
|
-
outputKeys: ["images"],
|
|
1634
|
-
outputLabels: { images: {
|
|
1635
|
-
fallback: [
|
|
1636
|
-
"basecolor",
|
|
1637
|
-
"normal",
|
|
1638
|
-
"roughness",
|
|
1639
|
-
"metalness",
|
|
1640
|
-
"height"
|
|
1641
|
-
],
|
|
1642
|
-
fromOption: "maps"
|
|
1643
|
-
} },
|
|
1644
|
-
price: {
|
|
1645
|
-
base: .1,
|
|
1646
|
-
kind: "maps",
|
|
1647
|
-
perMapMegapixel: .01,
|
|
1648
|
-
perMegapixel: .02,
|
|
1649
|
-
upscale: {
|
|
1650
|
-
"2": .004,
|
|
1651
|
-
"4": .016
|
|
1652
|
-
}
|
|
1653
|
-
},
|
|
1654
|
-
pricing: "$0.10 plus $0.02/megapixel plus $0.01/megapixel per map, so 1MP with all 5 maps is $0.17; upscaling adds $0.004 (2x) or $0.016 (4x) per pre-upscale megapixel per map",
|
|
1655
|
-
queued: true,
|
|
1656
|
-
sourceUrl: "https://fal.ai/models/fal-ai/patina/material/extract",
|
|
1657
|
-
task: "tiling material extraction"
|
|
1658
|
-
},
|
|
1659
|
-
"qwen-layered": {
|
|
1660
|
-
category: "layers",
|
|
1661
|
-
description: "Split an image into a configurable number of stacked RGBA layers.",
|
|
1662
|
-
endpoint: "fal-ai/qwen-image-layered",
|
|
1663
|
-
inputField: "image_url",
|
|
1664
|
-
inputKind: "image",
|
|
1665
|
-
name: "Qwen Image Layered",
|
|
1666
|
-
outputKeys: ["images"],
|
|
1667
|
-
price: {
|
|
1668
|
-
kind: "call",
|
|
1669
|
-
usd: .05
|
|
1670
|
-
},
|
|
1671
|
-
pricing: "$0.05 per image, one input image a call",
|
|
1672
|
-
queued: true,
|
|
1673
|
-
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-layered",
|
|
1674
|
-
task: "image layer decomposition"
|
|
1675
|
-
},
|
|
1676
|
-
"recraft-vectorize": {
|
|
1677
|
-
category: "vector",
|
|
1678
|
-
description: "Convert a raster image into a clean SVG.",
|
|
1679
|
-
endpoint: "fal-ai/recraft/vectorize",
|
|
1680
|
-
inputField: "image_url",
|
|
1681
|
-
inputKind: "image",
|
|
1682
|
-
name: "Recraft Vectorize",
|
|
1683
|
-
outputKeys: ["image"],
|
|
1684
|
-
price: {
|
|
1685
|
-
kind: "call",
|
|
1686
|
-
usd: .04
|
|
1687
|
-
},
|
|
1688
|
-
pricing: "$0.04/image, $0.08 with a vector style",
|
|
1689
|
-
sourceUrl: "https://fal.ai/models/fal-ai/recraft/vectorize",
|
|
1690
|
-
task: "raster to vector conversion"
|
|
1691
|
-
},
|
|
1692
|
-
"sam3-3d-align": {
|
|
1693
|
-
category: "3d",
|
|
1694
|
-
description: "Align SAM 3D objects and bodies into a shared scene.",
|
|
1695
|
-
endpoint: "fal-ai/sam-3/3d-align",
|
|
1696
|
-
inputField: "image_url",
|
|
1697
|
-
inputKind: "image",
|
|
1698
|
-
name: "SAM 3D Align",
|
|
1699
|
-
outputKeys: [
|
|
1700
|
-
"scene_glb",
|
|
1701
|
-
"model_glb",
|
|
1702
|
-
"visualization",
|
|
1703
|
-
"body_mesh_ply",
|
|
1704
|
-
"metadata"
|
|
1705
|
-
],
|
|
1706
|
-
price: { kind: "metered" },
|
|
1707
|
-
pricing: "$0.02 per unit; fal does not define a unit, so no estimate is reported",
|
|
1708
|
-
queued: true,
|
|
1709
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-align",
|
|
1710
|
-
task: "3D scene alignment"
|
|
1711
|
-
},
|
|
1712
|
-
"sam3-3d-body": {
|
|
1713
|
-
category: "3d",
|
|
1714
|
-
defaultOptions: {
|
|
1715
|
-
export_meshes: true,
|
|
1716
|
-
include_3d_keypoints: true,
|
|
1717
|
-
include_mhr_params: true
|
|
1718
|
-
},
|
|
1719
|
-
description: "Reconstruct human body meshes and keypoints from a single image.",
|
|
1720
|
-
endpoint: "fal-ai/sam-3/3d-body",
|
|
1721
|
-
inputField: "image_url",
|
|
1722
|
-
inputKind: "image",
|
|
1723
|
-
name: "SAM 3D Body",
|
|
1724
|
-
outputKeys: [
|
|
1725
|
-
"model_glb",
|
|
1726
|
-
"visualization",
|
|
1727
|
-
"meshes",
|
|
1728
|
-
"metadata"
|
|
1729
|
-
],
|
|
1730
|
-
price: { kind: "metered" },
|
|
1731
|
-
pricing: "$0.02 per unit; fal does not define a unit, so no estimate is reported",
|
|
1732
|
-
queued: true,
|
|
1733
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-body",
|
|
1734
|
-
task: "single-image 3D body reconstruction"
|
|
1735
|
-
},
|
|
1736
|
-
"sam3-3d-objects": {
|
|
1737
|
-
category: "3d",
|
|
1738
|
-
description: "Reconstruct one or more 3D objects from an image and prompts.",
|
|
1739
|
-
endpoint: "fal-ai/sam-3/3d-objects",
|
|
1740
|
-
inputField: "image_url",
|
|
1741
|
-
inputKind: "image",
|
|
1742
|
-
name: "SAM 3D Objects",
|
|
1743
|
-
outputKeys: [
|
|
1744
|
-
"gaussian_splat",
|
|
1745
|
-
"model_glb",
|
|
1746
|
-
"metadata",
|
|
1747
|
-
"individual_splats",
|
|
1748
|
-
"individual_glbs",
|
|
1749
|
-
"artifacts_zip"
|
|
1750
|
-
],
|
|
1751
|
-
price: { kind: "metered" },
|
|
1752
|
-
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",
|
|
1753
|
-
queued: true,
|
|
1754
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-objects",
|
|
1755
|
-
task: "single-image 3D object reconstruction"
|
|
1756
|
-
},
|
|
1757
|
-
"seedream-layerize": {
|
|
1758
|
-
category: "layers",
|
|
1759
|
-
description: "Split an image into editable Seedream layers plus flattened previews.",
|
|
1760
|
-
endpoint: "bytedance/seedream/v5/pro/layerize",
|
|
1761
|
-
inputField: "image_url",
|
|
1762
|
-
inputKind: "image",
|
|
1763
|
-
name: "Seedream v5 Pro Layerize",
|
|
1764
|
-
outputKeys: ["layers", "images"],
|
|
1765
|
-
outputLabels: { layers: { fromItem: {
|
|
1766
|
-
nameField: "name",
|
|
1767
|
-
orderField: "z_index"
|
|
1768
|
-
} } },
|
|
1769
|
-
price: { kind: "metered" },
|
|
1770
|
-
pricing: "$0.03375 per generated layer below 1536x1536 total area, $0.0675 per layer above; the listed rate is per layer, not per call",
|
|
1771
|
-
queued: true,
|
|
1772
|
-
sourceUrl: "https://fal.ai/models/bytedance/seedream/v5/pro/layerize",
|
|
1773
|
-
task: "image layer decomposition"
|
|
1774
|
-
},
|
|
1775
|
-
"seedvr-seamless": {
|
|
1776
|
-
category: "material",
|
|
1777
|
-
description: "Upscale a tiling texture while keeping its edges seamless. ",
|
|
1778
|
-
endpoint: "fal-ai/seedvr/upscale/image/seamless",
|
|
1779
|
-
inputField: "image_url",
|
|
1780
|
-
inputKind: "image",
|
|
1781
|
-
name: "SeedVR Seamless Upscale",
|
|
1782
|
-
outputKeys: ["image"],
|
|
1783
|
-
price: {
|
|
1784
|
-
kind: "megapixel",
|
|
1785
|
-
usd: .0025
|
|
1786
|
-
},
|
|
1787
|
-
pricing: "$0.0025/megapixel",
|
|
1788
|
-
queued: true,
|
|
1789
|
-
sourceUrl: "https://fal.ai/models/fal-ai/seedvr/upscale/image/seamless",
|
|
1790
|
-
task: "seamless texture upscaling"
|
|
1791
|
-
},
|
|
1792
|
-
"trellis-2": {
|
|
1793
|
-
category: "3d",
|
|
1794
|
-
description: "Reconstruct a textured 3D mesh from a single image, with UV unwrapping.",
|
|
1795
|
-
endpoint: "fal-ai/trellis-2",
|
|
1796
|
-
inputField: "image_url",
|
|
1797
|
-
inputKind: "image",
|
|
1798
|
-
name: "TRELLIS 2",
|
|
1799
|
-
outputKeys: ["model_glb"],
|
|
1800
|
-
price: {
|
|
1801
|
-
kind: "call",
|
|
1802
|
-
usd: .3
|
|
1803
|
-
},
|
|
1804
|
-
pricing: "$0.30 at the default 1024p; $0.25 at 512p, $0.35 at 1536p",
|
|
1805
|
-
queued: true,
|
|
1806
|
-
sourceUrl: "https://fal.ai/models/fal-ai/trellis-2",
|
|
1807
|
-
task: "single-image 3D reconstruction"
|
|
1808
|
-
}
|
|
1809
|
-
};
|
|
1810
|
-
// src/tool-registry/background.ts
|
|
1811
|
-
const BACKGROUND_TOOLS = {
|
|
1812
|
-
"ben-v2": {
|
|
1813
|
-
category: "background",
|
|
1814
|
-
description: "Fast, high-quality background removal for images.",
|
|
1815
|
-
endpoint: "fal-ai/ben/v2/image",
|
|
1816
|
-
inputField: "image_url",
|
|
1817
|
-
inputKind: "image",
|
|
1818
|
-
name: "BEN v2 Background Removal",
|
|
1819
|
-
outputKeys: ["image"],
|
|
1820
|
-
price: {
|
|
1821
|
-
kind: "megapixel",
|
|
1822
|
-
usd: .025
|
|
1823
|
-
},
|
|
1824
|
-
pricing: "$0.025/megapixel",
|
|
1825
|
-
sourceUrl: "https://fal.ai/models/fal-ai/ben/v2/image",
|
|
1826
|
-
task: "image background removal"
|
|
1827
|
-
},
|
|
1828
|
-
birefnet: {
|
|
1829
|
-
category: "background",
|
|
1830
|
-
defaultOptions: {
|
|
1831
|
-
model: "General Use (Light)",
|
|
1832
|
-
operating_resolution: "1024x1024",
|
|
1833
|
-
output_format: "png",
|
|
1834
|
-
refine_foreground: true
|
|
1835
|
-
},
|
|
1836
|
-
description: "High-resolution dichotomous image segmentation and background removal.",
|
|
1837
|
-
endpoint: "fal-ai/birefnet/v2",
|
|
1838
|
-
inputField: "image_url",
|
|
1839
|
-
inputKind: "image",
|
|
1840
|
-
name: "BirefNet Background Removal",
|
|
1841
|
-
outputKeys: ["image", "mask_image"],
|
|
1842
|
-
price: {
|
|
1843
|
-
kind: "call",
|
|
1844
|
-
usd: 0
|
|
1845
|
-
},
|
|
1846
|
-
pricing: "$0/compute-second listed by fal",
|
|
1847
|
-
sourceUrl: "https://fal.ai/models/fal-ai/birefnet/v2",
|
|
1848
|
-
task: "image background removal"
|
|
1849
|
-
},
|
|
1850
|
-
"bria-rmbg": {
|
|
1851
|
-
category: "background",
|
|
1852
|
-
description: "Commercial-safe background removal for images.",
|
|
1853
|
-
endpoint: "fal-ai/bria/background/remove",
|
|
1854
|
-
inputField: "image_url",
|
|
1855
|
-
inputKind: "image",
|
|
1856
|
-
name: "Bria RMBG 2.0",
|
|
1857
|
-
outputKeys: ["image"],
|
|
1858
|
-
price: {
|
|
1859
|
-
kind: "call",
|
|
1860
|
-
usd: .018
|
|
1861
|
-
},
|
|
1862
|
-
pricing: "$0.018/generation",
|
|
1863
|
-
sourceUrl: "https://fal.ai/models/fal-ai/bria/background/remove",
|
|
1864
|
-
task: "image background removal"
|
|
1865
|
-
},
|
|
1866
|
-
"bria-video-rmbg": {
|
|
1867
|
-
category: "background",
|
|
1868
|
-
defaultOptions: {
|
|
1869
|
-
background_color: "Black",
|
|
1870
|
-
output_container_and_codec: "webm_vp9",
|
|
1871
|
-
preserve_audio: true
|
|
1872
|
-
},
|
|
1873
|
-
description: "Remove video backgrounds with configurable output container.",
|
|
1874
|
-
endpoint: "bria/video/background-removal",
|
|
1875
|
-
inputField: "video_url",
|
|
1876
|
-
inputKind: "video",
|
|
1877
|
-
name: "Bria Video Background Removal",
|
|
1878
|
-
outputKeys: ["video"],
|
|
1879
|
-
price: {
|
|
1880
|
-
kind: "second",
|
|
1881
|
-
usd: .14
|
|
1882
|
-
},
|
|
1883
|
-
pricing: "$0.14/sec",
|
|
1884
|
-
queued: true,
|
|
1885
|
-
sourceUrl: "https://fal.ai/models/bria/video/background-removal",
|
|
1886
|
-
task: "video background removal"
|
|
1887
|
-
},
|
|
1888
|
-
"bria-video-rmbg-v3": {
|
|
1889
|
-
category: "background",
|
|
1890
|
-
defaultOptions: {
|
|
1891
|
-
background_color: "Black",
|
|
1892
|
-
output_container_and_codec: "webm_vp9",
|
|
1893
|
-
preserve_audio: true
|
|
1894
|
-
},
|
|
1895
|
-
description: "Remove video backgrounds with Bria's VRMBG 3.0, with configurable output container.",
|
|
1896
|
-
endpoint: "bria/video/background-removal/v3",
|
|
1897
|
-
inputField: "video_url",
|
|
1898
|
-
inputKind: "video",
|
|
1899
|
-
name: "Bria Video Background Removal 3.0",
|
|
1900
|
-
outputKeys: ["video"],
|
|
1901
|
-
price: {
|
|
1902
|
-
kind: "second",
|
|
1903
|
-
usd: .05
|
|
1904
|
-
},
|
|
1905
|
-
pricing: "$0.05/sec",
|
|
1906
|
-
queued: true,
|
|
1907
|
-
sourceUrl: "https://fal.ai/models/bria/video/background-removal/v3",
|
|
1908
|
-
task: "video background removal"
|
|
1909
|
-
},
|
|
1910
|
-
"control-light": {
|
|
1911
|
-
category: "restoration",
|
|
1912
|
-
description: "Brighten a dark or underexposed photo, recovering detail while keeping its identity, geometry and colour.",
|
|
1913
|
-
endpoint: "fal-ai/control-light",
|
|
1914
|
-
inputField: "image_url",
|
|
1915
|
-
inputKind: "image",
|
|
1916
|
-
name: "Control Light",
|
|
1917
|
-
outputKeys: ["images"],
|
|
1918
|
-
price: {
|
|
1919
|
-
kind: "megapixel",
|
|
1920
|
-
usd: .03
|
|
1921
|
-
},
|
|
1922
|
-
pricing: "$0.03/megapixel",
|
|
1923
|
-
sourceUrl: "https://fal.ai/models/fal-ai/control-light",
|
|
1924
|
-
task: "low-light enhancement"
|
|
1925
|
-
},
|
|
1926
|
-
ddcolor: {
|
|
1927
|
-
category: "restoration",
|
|
1928
|
-
description: "Colourise black-and-white photographs.",
|
|
1929
|
-
endpoint: "fal-ai/ddcolor",
|
|
1930
|
-
inputField: "image_url",
|
|
1931
|
-
inputKind: "image",
|
|
1932
|
-
name: "DDColor Colourisation",
|
|
1933
|
-
outputKeys: ["image"],
|
|
1934
|
-
price: {
|
|
1935
|
-
kind: "megapixel",
|
|
1936
|
-
usd: .001
|
|
1937
|
-
},
|
|
1938
|
-
pricing: "$0.001/megapixel",
|
|
1939
|
-
sourceUrl: "https://fal.ai/models/fal-ai/ddcolor",
|
|
1940
|
-
task: "photo colourisation"
|
|
1941
|
-
},
|
|
1942
|
-
rembg: {
|
|
1943
|
-
category: "background",
|
|
1944
|
-
defaultOptions: { crop_to_bbox: false },
|
|
1945
|
-
description: "Generic image background removal utility.",
|
|
1946
|
-
endpoint: "fal-ai/imageutils/rembg",
|
|
1947
|
-
inputField: "image_url",
|
|
1948
|
-
inputKind: "image",
|
|
1949
|
-
name: "Remove Background",
|
|
1950
|
-
outputKeys: ["image"],
|
|
1951
|
-
price: {
|
|
1952
|
-
kind: "call",
|
|
1953
|
-
usd: 0
|
|
1954
|
-
},
|
|
1955
|
-
pricing: "$0/compute-second listed by fal",
|
|
1956
|
-
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/rembg",
|
|
1957
|
-
task: "image background removal"
|
|
1958
|
-
},
|
|
1959
|
-
"seedvr-upscale": {
|
|
1960
|
-
category: "restoration",
|
|
1961
|
-
defaultOptions: { output_format: "png" },
|
|
1962
|
-
description: "Diffusion image restoration and upscaling with SeedVR.",
|
|
1963
|
-
endpoint: "fal-ai/seedvr/upscale/image",
|
|
1964
|
-
inputField: "image_url",
|
|
1965
|
-
inputKind: "image",
|
|
1966
|
-
name: "SeedVR Image Upscale",
|
|
1967
|
-
outputKeys: ["image"],
|
|
1968
|
-
price: {
|
|
1969
|
-
kind: "megapixel",
|
|
1970
|
-
usd: .001
|
|
1971
|
-
},
|
|
1972
|
-
pricing: "$0.001/megapixel",
|
|
1973
|
-
queued: true,
|
|
1974
|
-
sourceUrl: "https://fal.ai/models/fal-ai/seedvr/upscale/image",
|
|
1975
|
-
task: "image restoration and upscaling"
|
|
1976
|
-
},
|
|
1977
|
-
"topaz-adjust": {
|
|
1978
|
-
category: "restoration",
|
|
1979
|
-
defaultOptions: { output_format: "png" },
|
|
1980
|
-
description: "Topaz exposure, white balance, and colour adjustment.",
|
|
1981
|
-
endpoint: "topaz/adjust/image",
|
|
1982
|
-
inputField: "image_url",
|
|
1983
|
-
inputKind: "image",
|
|
1984
|
-
name: "Topaz Adjust",
|
|
1985
|
-
outputKeys: ["image"],
|
|
1986
|
-
price: {
|
|
1987
|
-
kind: "megapixel-step",
|
|
1988
|
-
megapixels: 24,
|
|
1989
|
-
usd: .08
|
|
1990
|
-
},
|
|
1991
|
-
pricing: "$0.08 per 24 output megapixels",
|
|
1992
|
-
queued: true,
|
|
1993
|
-
sourceUrl: "https://fal.ai/models/topaz/adjust/image",
|
|
1994
|
-
task: "tonal adjustment"
|
|
1995
|
-
},
|
|
1996
|
-
"topaz-creative": {
|
|
1997
|
-
category: "restoration",
|
|
1998
|
-
defaultOptions: { output_format: "png" },
|
|
1999
|
-
description: "Topaz Bloom upscaling, which reimagines detail rather than preserving it.",
|
|
2000
|
-
endpoint: "topaz/upscale/image/creative",
|
|
2001
|
-
inputField: "image_url",
|
|
2002
|
-
inputKind: "image",
|
|
2003
|
-
name: "Topaz Creative Upscale",
|
|
2004
|
-
outputKeys: ["image"],
|
|
2005
|
-
price: {
|
|
2006
|
-
kind: "megapixel-step",
|
|
2007
|
-
megapixels: 2,
|
|
2008
|
-
usd: .08
|
|
2009
|
-
},
|
|
2010
|
-
pricing: "$0.08 per started 2 output megapixels, any Bloom model",
|
|
2011
|
-
queued: true,
|
|
2012
|
-
sourceUrl: "https://fal.ai/models/topaz/upscale/image/creative",
|
|
2013
|
-
task: "creative image upscaling"
|
|
2014
|
-
},
|
|
2015
|
-
"topaz-denoise": {
|
|
2016
|
-
category: "restoration",
|
|
2017
|
-
defaultOptions: { output_format: "png" },
|
|
2018
|
-
description: "Topaz noise reduction at source resolution.",
|
|
2019
|
-
endpoint: "topaz/denoise/image",
|
|
2020
|
-
inputField: "image_url",
|
|
2021
|
-
inputKind: "image",
|
|
2022
|
-
name: "Topaz Denoise",
|
|
2023
|
-
outputKeys: ["image"],
|
|
2024
|
-
price: {
|
|
2025
|
-
kind: "megapixel-step",
|
|
2026
|
-
megapixels: 24,
|
|
2027
|
-
usd: .08
|
|
2028
|
-
},
|
|
2029
|
-
pricing: "$0.08 per 24 output megapixels at the default Normal model; $0.16 with Denoise Max",
|
|
2030
|
-
queued: true,
|
|
2031
|
-
sourceUrl: "https://fal.ai/models/topaz/denoise/image",
|
|
2032
|
-
task: "image denoising"
|
|
2033
|
-
},
|
|
2034
|
-
"topaz-generative": {
|
|
2035
|
-
category: "restoration",
|
|
2036
|
-
defaultOptions: { output_format: "png" },
|
|
2037
|
-
description: "Topaz Wonder upscaling, which synthesises plausible detail as it enlarges.",
|
|
2038
|
-
endpoint: "topaz/upscale/image/generative",
|
|
2039
|
-
inputField: "image_url",
|
|
2040
|
-
inputKind: "image",
|
|
2041
|
-
name: "Topaz Generative Upscale",
|
|
2042
|
-
outputKeys: ["image"],
|
|
2043
|
-
price: {
|
|
2044
|
-
kind: "megapixel-step",
|
|
2045
|
-
megapixels: 8,
|
|
2046
|
-
usd: .08
|
|
2047
|
-
},
|
|
2048
|
-
pricing: "$0.08 per started 8 output megapixels at the default Wonder 3; per started 4 with Wonder, Wonder 2, Standard MAX, Redefine or Recover 3",
|
|
2049
|
-
queued: true,
|
|
2050
|
-
sourceUrl: "https://fal.ai/models/topaz/upscale/image/generative",
|
|
2051
|
-
task: "generative image upscaling"
|
|
2052
|
-
},
|
|
2053
|
-
"topaz-image": {
|
|
2054
|
-
category: "upscale",
|
|
2055
|
-
defaultOptions: {
|
|
2056
|
-
model: "Standard V2",
|
|
2057
|
-
output_format: "jpeg",
|
|
2058
|
-
upscale_factor: 2
|
|
2059
|
-
},
|
|
2060
|
-
description: "Professional Topaz image enhancement and upscaling.",
|
|
2061
|
-
endpoint: "fal-ai/topaz/upscale/image",
|
|
2062
|
-
inputField: "image_url",
|
|
2063
|
-
inputKind: "image",
|
|
2064
|
-
name: "Topaz Image Upscale",
|
|
2065
|
-
outputKeys: ["image"],
|
|
2066
|
-
price: {
|
|
2067
|
-
kind: "megapixel-step",
|
|
2068
|
-
megapixels: 24,
|
|
2069
|
-
usd: .08
|
|
2070
|
-
},
|
|
2071
|
-
pricing: "$0.08 for output up to 24MP; $0.16 to 48MP, $0.32 to 96MP, up to $1.36 at 512MP",
|
|
2072
|
-
queued: true,
|
|
2073
|
-
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/image",
|
|
2074
|
-
task: "image enhancement"
|
|
2075
|
-
},
|
|
2076
|
-
"topaz-precision": {
|
|
2077
|
-
category: "restoration",
|
|
2078
|
-
defaultOptions: { output_format: "png" },
|
|
2079
|
-
description: "Topaz upscaling that preserves the original detail rather than inventing it.",
|
|
2080
|
-
endpoint: "topaz/upscale/image/precision",
|
|
2081
|
-
inputField: "image_url",
|
|
2082
|
-
inputKind: "image",
|
|
2083
|
-
name: "Topaz Precision Upscale",
|
|
2084
|
-
outputKeys: ["image"],
|
|
2085
|
-
price: {
|
|
2086
|
-
kind: "megapixel-step",
|
|
2087
|
-
megapixels: 24,
|
|
2088
|
-
usd: .08
|
|
2089
|
-
},
|
|
2090
|
-
pricing: "$0.08 per 24 output megapixels, any precision model",
|
|
2091
|
-
queued: true,
|
|
2092
|
-
sourceUrl: "https://fal.ai/models/topaz/upscale/image/precision",
|
|
2093
|
-
task: "faithful image upscaling"
|
|
2094
|
-
},
|
|
2095
|
-
"topaz-restore": {
|
|
2096
|
-
category: "restoration",
|
|
2097
|
-
defaultOptions: { output_format: "png" },
|
|
2098
|
-
description: "Topaz restoration of damaged or degraded photographs at source resolution.",
|
|
2099
|
-
endpoint: "topaz/restore/image",
|
|
2100
|
-
inputField: "image_url",
|
|
2101
|
-
inputKind: "image",
|
|
2102
|
-
name: "Topaz Restore",
|
|
2103
|
-
outputKeys: ["image"],
|
|
2104
|
-
price: {
|
|
2105
|
-
kind: "megapixel-step",
|
|
2106
|
-
megapixels: 24,
|
|
2107
|
-
usd: .48
|
|
2108
|
-
},
|
|
2109
|
-
pricing: "$0.48 per 24 output megapixels at the default Recover 3; $0.08 with Dust-Scratch V2",
|
|
2110
|
-
queued: true,
|
|
2111
|
-
sourceUrl: "https://fal.ai/models/topaz/restore/image",
|
|
2112
|
-
task: "photo restoration"
|
|
2113
|
-
},
|
|
2114
|
-
"topaz-sharpen": {
|
|
2115
|
-
category: "restoration",
|
|
2116
|
-
defaultOptions: { output_format: "png" },
|
|
2117
|
-
description: "Topaz deblurring and sharpening at source resolution.",
|
|
2118
|
-
endpoint: "topaz/sharpen/image",
|
|
2119
|
-
inputField: "image_url",
|
|
2120
|
-
inputKind: "image",
|
|
2121
|
-
name: "Topaz Sharpen",
|
|
2122
|
-
outputKeys: ["image"],
|
|
2123
|
-
price: {
|
|
2124
|
-
kind: "megapixel-step",
|
|
2125
|
-
megapixels: 24,
|
|
2126
|
-
usd: .08
|
|
2127
|
-
},
|
|
2128
|
-
pricing: "$0.08 per 24 output megapixels at the default Standard model; $0.16 with Super Focus",
|
|
2129
|
-
queued: true,
|
|
2130
|
-
sourceUrl: "https://fal.ai/models/topaz/sharpen/image",
|
|
2131
|
-
task: "image sharpening"
|
|
2132
|
-
},
|
|
2133
|
-
"topaz-transparent": {
|
|
2134
|
-
category: "restoration",
|
|
2135
|
-
description: "Topaz upscaling that preserves the alpha channel end to end.",
|
|
2136
|
-
endpoint: "topaz/upscale/image/transparent",
|
|
2137
|
-
inputField: "image_url",
|
|
2138
|
-
inputKind: "image",
|
|
2139
|
-
name: "Topaz Transparent Upscale",
|
|
2140
1251
|
outputKeys: ["image"],
|
|
2141
|
-
price: {
|
|
2142
|
-
kind: "megapixel-step",
|
|
2143
|
-
megapixels: 24,
|
|
2144
|
-
usd: .08
|
|
2145
|
-
},
|
|
2146
|
-
pricing: "$0.08 per 24 output megapixels",
|
|
2147
|
-
queued: true,
|
|
2148
|
-
sourceUrl: "https://fal.ai/models/topaz/upscale/image/transparent",
|
|
2149
|
-
task: "transparent image upscaling"
|
|
2150
|
-
},
|
|
2151
|
-
"topaz-video": {
|
|
2152
|
-
category: "upscale",
|
|
2153
|
-
defaultOptions: {
|
|
2154
|
-
model: "Proteus",
|
|
2155
|
-
upscale_factor: 2
|
|
2156
|
-
},
|
|
2157
|
-
description: "Professional Topaz video enhancement and upscaling.",
|
|
2158
|
-
endpoint: "fal-ai/topaz/upscale/video",
|
|
2159
|
-
inputField: "video_url",
|
|
2160
|
-
inputKind: "video",
|
|
2161
|
-
name: "Topaz Video Upscale",
|
|
2162
|
-
outputKeys: ["video"],
|
|
2163
|
-
price: {
|
|
2164
|
-
doubleAtFps: 60,
|
|
2165
|
-
halfWithModel: "Gaia 2",
|
|
2166
|
-
kind: "video-second",
|
|
2167
|
-
tiers: [
|
|
2168
|
-
{
|
|
2169
|
-
upTo: 720,
|
|
2170
|
-
usd: .01
|
|
2171
|
-
},
|
|
2172
|
-
{
|
|
2173
|
-
upTo: 1080,
|
|
2174
|
-
usd: .02
|
|
2175
|
-
},
|
|
2176
|
-
{ usd: .08 }
|
|
2177
|
-
]
|
|
2178
|
-
},
|
|
2179
|
-
pricing: "$0.01/sec up to 720p output; $0.02 to 1080p, $0.08 above, doubled at 60fps, halved with Gaia 2",
|
|
2180
|
-
queued: true,
|
|
2181
|
-
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/video",
|
|
2182
|
-
task: "video enhancement"
|
|
2183
|
-
}
|
|
2184
|
-
};
|
|
2185
|
-
// src/tool-registry/editing.ts
|
|
2186
|
-
const EDITING_TOOLS = {
|
|
2187
|
-
"bria-eraser": {
|
|
2188
|
-
category: "erase",
|
|
2189
|
-
description: "Commercial-safe removal of a masked region, inpainted from surrounding context.",
|
|
2190
|
-
endpoint: "fal-ai/bria/eraser",
|
|
2191
|
-
inputField: "image_url",
|
|
2192
|
-
inputKind: "image",
|
|
2193
|
-
name: "Bria Eraser",
|
|
2194
|
-
outputKeys: ["image"],
|
|
2195
|
-
price: {
|
|
2196
|
-
kind: "call",
|
|
2197
|
-
usd: .04
|
|
2198
|
-
},
|
|
2199
|
-
pricing: "$0.04/generation",
|
|
2200
|
-
sourceUrl: "https://fal.ai/models/fal-ai/bria/eraser",
|
|
2201
|
-
task: "masked object erasure"
|
|
2202
|
-
},
|
|
2203
|
-
"bria-expand": {
|
|
2204
|
-
category: "reframe",
|
|
2205
|
-
description: "Expand an image onto a larger canvas, generating the new border area.",
|
|
2206
|
-
endpoint: "fal-ai/bria/expand",
|
|
2207
|
-
inputField: "image_url",
|
|
2208
|
-
inputKind: "image",
|
|
2209
|
-
name: "Bria Image Expansion",
|
|
2210
|
-
outputKeys: ["image"],
|
|
2211
|
-
price: {
|
|
2212
|
-
kind: "call",
|
|
2213
|
-
usd: .04
|
|
2214
|
-
},
|
|
2215
|
-
pricing: "$0.04/generation",
|
|
2216
|
-
sourceUrl: "https://fal.ai/models/fal-ai/bria/expand",
|
|
2217
|
-
task: "image outpainting"
|
|
2218
|
-
},
|
|
2219
|
-
"bria-genfill": {
|
|
2220
|
-
category: "erase",
|
|
2221
|
-
description: "Generative fill of a masked region from a prompt, commercial-safe.",
|
|
2222
|
-
endpoint: "fal-ai/bria/genfill",
|
|
2223
|
-
inputField: "image_url",
|
|
2224
|
-
inputKind: "image",
|
|
2225
|
-
name: "Bria GenFill",
|
|
2226
|
-
outputKeys: ["images"],
|
|
2227
|
-
price: {
|
|
2228
|
-
kind: "call",
|
|
2229
|
-
perImage: true,
|
|
2230
|
-
usd: .04
|
|
2231
|
-
},
|
|
2232
|
-
pricing: "$0.04/generation",
|
|
2233
|
-
sourceUrl: "https://fal.ai/models/fal-ai/bria/genfill",
|
|
2234
|
-
task: "masked generative fill"
|
|
2235
|
-
},
|
|
2236
|
-
"finegrain-eraser": {
|
|
2237
|
-
category: "erase",
|
|
2238
|
-
description: "Remove a prompted object and its shadows and reflections, filling the gap.",
|
|
2239
|
-
endpoint: "fal-ai/finegrain-eraser",
|
|
2240
|
-
inputField: "image_url",
|
|
2241
|
-
inputKind: "image",
|
|
2242
|
-
name: "Finegrain Object Eraser",
|
|
2243
|
-
outputKeys: ["image"],
|
|
2244
|
-
price: {
|
|
2245
|
-
kind: "call",
|
|
2246
|
-
usd: .27
|
|
2247
|
-
},
|
|
2248
|
-
pricing: "$0.27/image at the default standard mode; $0.18 express, $0.36 premium",
|
|
2249
|
-
sourceUrl: "https://fal.ai/models/fal-ai/finegrain-eraser",
|
|
2250
|
-
task: "prompted object erasure"
|
|
2251
|
-
},
|
|
2252
|
-
"flux-outpaint": {
|
|
2253
|
-
category: "reframe",
|
|
2254
|
-
description: "Outpaint an image by a per-edge pixel expansion with FLUX.2 pro.",
|
|
2255
|
-
endpoint: "fal-ai/flux-2-pro/outpaint",
|
|
2256
|
-
inputField: "image_url",
|
|
2257
|
-
inputKind: "image",
|
|
2258
|
-
name: "FLUX.2 Pro Outpaint",
|
|
2259
|
-
outputKeys: ["images"],
|
|
2260
|
-
price: {
|
|
2261
|
-
extra: .015,
|
|
2262
|
-
first: .03,
|
|
2263
|
-
kind: "megapixel-first"
|
|
2264
|
-
},
|
|
2265
|
-
pricing: "$0.03 for the first output megapixel, then $0.015 per extra megapixel of input and output, rounded up",
|
|
2266
|
-
sourceUrl: "https://fal.ai/models/fal-ai/flux-2-pro/outpaint",
|
|
2267
|
-
task: "image outpainting"
|
|
2268
|
-
},
|
|
2269
|
-
"iclight-v2": {
|
|
2270
|
-
category: "relight",
|
|
2271
|
-
description: "Relight a subject from a prompt, harmonising it with a new light direction.",
|
|
2272
|
-
endpoint: "fal-ai/iclight-v2",
|
|
2273
|
-
inputField: "image_url",
|
|
2274
|
-
inputKind: "image",
|
|
2275
|
-
name: "IC-Light v2",
|
|
2276
|
-
outputKeys: ["images"],
|
|
2277
|
-
price: {
|
|
2278
|
-
kind: "megapixel",
|
|
2279
|
-
usd: .1
|
|
2280
|
-
},
|
|
2281
|
-
pricing: "$0.10/megapixel",
|
|
2282
|
-
sourceUrl: "https://fal.ai/models/fal-ai/iclight-v2",
|
|
2283
|
-
task: "prompted relighting"
|
|
2284
|
-
},
|
|
2285
|
-
"ideogram-reframe": {
|
|
2286
|
-
category: "reframe",
|
|
2287
|
-
description: "Reframe an image to a new aspect ratio, generating the fill.",
|
|
2288
|
-
endpoint: "fal-ai/ideogram/v3/reframe",
|
|
2289
|
-
inputField: "image_url",
|
|
2290
|
-
inputKind: "image",
|
|
2291
|
-
name: "Ideogram v3 Reframe",
|
|
2292
|
-
outputKeys: ["images"],
|
|
2293
|
-
price: {
|
|
2294
|
-
kind: "call",
|
|
2295
|
-
perImage: true,
|
|
2296
|
-
usd: .06
|
|
2297
|
-
},
|
|
2298
|
-
pricing: "$0.06/image at the default BALANCED speed; $0.03 turbo, $0.09 quality",
|
|
2299
|
-
sourceUrl: "https://fal.ai/models/fal-ai/ideogram/v3/reframe",
|
|
2300
|
-
task: "aspect ratio reframing"
|
|
2301
|
-
},
|
|
2302
|
-
"lighting-restoration": {
|
|
2303
|
-
category: "relight",
|
|
2304
|
-
description: "Restore natural, even lighting across one or more input images.",
|
|
2305
|
-
endpoint: "fal-ai/qwen-image-edit-plus-lora-gallery/lighting-restoration",
|
|
2306
|
-
inputField: "image_urls",
|
|
2307
|
-
inputKind: "images",
|
|
2308
|
-
name: "Qwen Lighting Restoration",
|
|
2309
|
-
outputKeys: ["images"],
|
|
2310
|
-
price: {
|
|
2311
|
-
kind: "megapixel",
|
|
2312
|
-
usd: .035
|
|
2313
|
-
},
|
|
2314
|
-
pricing: "$0.035/megapixel",
|
|
2315
|
-
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-edit-plus-lora-gallery/lighting-restoration",
|
|
2316
|
-
task: "lighting restoration"
|
|
2317
|
-
},
|
|
2318
|
-
"object-removal": {
|
|
2319
|
-
category: "erase",
|
|
2320
|
-
description: "Remove a prompted object from an image and fill the gap.",
|
|
2321
|
-
endpoint: "fal-ai/object-removal",
|
|
2322
|
-
inputField: "image_url",
|
|
2323
|
-
inputKind: "image",
|
|
2324
|
-
name: "Object Removal",
|
|
2325
|
-
outputKeys: ["images"],
|
|
2326
|
-
price: {
|
|
2327
|
-
kind: "call",
|
|
2328
|
-
usd: .024
|
|
2329
|
-
},
|
|
2330
|
-
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
2331
|
-
sourceUrl: "https://fal.ai/models/fal-ai/object-removal",
|
|
2332
|
-
task: "prompted object removal"
|
|
2333
|
-
},
|
|
2334
|
-
"object-removal-bbox": {
|
|
2335
|
-
category: "erase",
|
|
2336
|
-
description: "Remove whatever falls inside supplied bounding boxes.",
|
|
2337
|
-
endpoint: "fal-ai/object-removal/bbox",
|
|
2338
|
-
inputField: "image_url",
|
|
2339
|
-
inputKind: "image",
|
|
2340
|
-
name: "Object Removal by Box",
|
|
2341
|
-
outputKeys: ["images"],
|
|
2342
|
-
price: {
|
|
2343
|
-
kind: "call",
|
|
2344
|
-
usd: .024
|
|
2345
|
-
},
|
|
2346
|
-
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
2347
|
-
sourceUrl: "https://fal.ai/models/fal-ai/object-removal/bbox",
|
|
2348
|
-
task: "bounding box object removal"
|
|
2349
|
-
},
|
|
2350
|
-
"object-removal-mask": {
|
|
2351
|
-
category: "erase",
|
|
2352
|
-
description: "Remove the masked region of an image and fill the gap.",
|
|
2353
|
-
endpoint: "fal-ai/object-removal/mask",
|
|
2354
|
-
inputField: "image_url",
|
|
2355
|
-
inputKind: "image",
|
|
2356
|
-
name: "Object Removal by Mask",
|
|
2357
|
-
outputKeys: ["images"],
|
|
2358
|
-
price: {
|
|
2359
|
-
kind: "call",
|
|
2360
|
-
usd: .024
|
|
2361
|
-
},
|
|
2362
|
-
pricing: "$0.024/image at the default best quality; $0.006 low, $0.012 medium, $0.018 high",
|
|
2363
|
-
sourceUrl: "https://fal.ai/models/fal-ai/object-removal/mask",
|
|
2364
|
-
task: "masked object removal"
|
|
2365
|
-
},
|
|
2366
|
-
"remove-lighting": {
|
|
2367
|
-
category: "relight",
|
|
2368
|
-
description: "Strip baked-in lighting and shadows to leave a flat, neutral surface.",
|
|
2369
|
-
endpoint: "fal-ai/qwen-image-edit-plus-lora-gallery/remove-lighting",
|
|
2370
|
-
inputField: "image_urls",
|
|
2371
|
-
inputKind: "images",
|
|
2372
|
-
name: "Qwen Remove Lighting",
|
|
2373
|
-
outputKeys: ["images"],
|
|
2374
|
-
price: {
|
|
2375
|
-
kind: "megapixel",
|
|
2376
|
-
usd: .035
|
|
2377
|
-
},
|
|
2378
|
-
pricing: "$0.035/megapixel",
|
|
2379
|
-
sourceUrl: "https://fal.ai/models/fal-ai/qwen-image-edit-plus-lora-gallery/remove-lighting",
|
|
2380
|
-
task: "lighting removal"
|
|
2381
|
-
},
|
|
2382
|
-
"smart-resize": {
|
|
2383
|
-
category: "reframe",
|
|
2384
|
-
description: "Resize one image to several target sizes, recomposing rather than cropping.",
|
|
2385
|
-
endpoint: "fal-ai/smart-resize",
|
|
2386
|
-
inputField: "image_url",
|
|
2387
|
-
inputKind: "image",
|
|
2388
|
-
name: "Smart Resize",
|
|
2389
|
-
outputKeys: ["images", "results"],
|
|
2390
|
-
price: {
|
|
2391
|
-
fee: .05,
|
|
2392
|
-
kind: "call",
|
|
2393
|
-
multipliers: { resolution: { "4K": 2 } },
|
|
2394
|
-
per: ["target_sizes", "num_images_per_size"],
|
|
2395
|
-
usd: .15
|
|
2396
|
-
},
|
|
2397
|
-
pricing: "$0.15 per output image, doubled at 4K, plus a $0.05 vision analysis fee per request",
|
|
2398
|
-
queued: true,
|
|
2399
|
-
sourceUrl: "https://fal.ai/models/fal-ai/smart-resize",
|
|
2400
|
-
task: "multi-size recomposition"
|
|
2401
|
-
},
|
|
2402
|
-
"telestyle-v2": {
|
|
2403
|
-
category: "restyle",
|
|
2404
|
-
description: "Redraw a content image in the style of a second, style image.",
|
|
2405
|
-
endpoint: "fal-ai/telestyle-v2",
|
|
2406
|
-
inputField: "content_image_url",
|
|
2407
|
-
inputKind: "image",
|
|
2408
|
-
name: "TeleStyle v2",
|
|
2409
|
-
outputKeys: ["images"],
|
|
2410
1252
|
price: {
|
|
2411
1253
|
kind: "megapixel",
|
|
2412
|
-
usd: .
|
|
2413
|
-
},
|
|
2414
|
-
pricing: "$0.035/megapixel",
|
|
2415
|
-
referenceField: "style_image_url",
|
|
2416
|
-
sourceUrl: "https://fal.ai/models/fal-ai/telestyle-v2",
|
|
2417
|
-
task: "style transfer from a reference image"
|
|
2418
|
-
},
|
|
2419
|
-
"text-removal": {
|
|
2420
|
-
category: "erase",
|
|
2421
|
-
defaultOptions: { output_format: "png" },
|
|
2422
|
-
description: "Remove all rendered text from an image, rebuilding what sat behind it.",
|
|
2423
|
-
endpoint: "fal-ai/image-editing/text-removal",
|
|
2424
|
-
inputField: "image_url",
|
|
2425
|
-
inputKind: "image",
|
|
2426
|
-
name: "Text Removal",
|
|
2427
|
-
outputKeys: ["images"],
|
|
2428
|
-
price: {
|
|
2429
|
-
kind: "call",
|
|
2430
|
-
usd: .04
|
|
1254
|
+
usd: .016
|
|
2431
1255
|
},
|
|
2432
|
-
pricing: "$0.
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
category: "try-on",
|
|
2438
|
-
description: "Dress the person in one image in the garment shown in another.",
|
|
2439
|
-
endpoint: "google/virtual-try-on",
|
|
2440
|
-
inputField: "person_image_url",
|
|
2441
|
-
inputKind: "image",
|
|
2442
|
-
name: "Google Virtual Try-On",
|
|
2443
|
-
outputKeys: ["images"],
|
|
2444
|
-
price: {
|
|
2445
|
-
kind: "call",
|
|
2446
|
-
perImage: true,
|
|
2447
|
-
usd: .075
|
|
2448
|
-
},
|
|
2449
|
-
pricing: "$0.075/image",
|
|
2450
|
-
queued: true,
|
|
2451
|
-
referenceField: "product_image_url",
|
|
2452
|
-
sourceUrl: "https://fal.ai/models/google/virtual-try-on",
|
|
2453
|
-
task: "virtual garment try-on"
|
|
2454
|
-
}
|
|
2455
|
-
};
|
|
2456
|
-
// src/tool-registry/structure.ts
|
|
2457
|
-
const STRUCTURE_TOOLS = {
|
|
2458
|
-
"depth-anything": {
|
|
2459
|
-
category: "preprocess",
|
|
2460
|
-
description: "Generate Depth Anything v2 depth maps from input images.",
|
|
2461
|
-
endpoint: "fal-ai/image-preprocessors/depth-anything/v2",
|
|
2462
|
-
inputField: "image_url",
|
|
2463
|
-
inputKind: "image",
|
|
2464
|
-
name: "Depth Anything v2 Preprocessor",
|
|
2465
|
-
outputKeys: ["image"],
|
|
2466
|
-
price: {
|
|
2467
|
-
kind: "call",
|
|
2468
|
-
usd: 0
|
|
2469
|
-
},
|
|
2470
|
-
pricing: "$0/compute-second listed by fal",
|
|
2471
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/depth-anything/v2",
|
|
2472
|
-
task: "depth preprocessing"
|
|
2473
|
-
},
|
|
2474
|
-
dwpose: {
|
|
2475
|
-
category: "preprocess",
|
|
2476
|
-
description: "Extract body, hand, and face pose skeletons from an image.",
|
|
2477
|
-
endpoint: "fal-ai/dwpose",
|
|
2478
|
-
inputField: "image_url",
|
|
2479
|
-
inputKind: "image",
|
|
2480
|
-
name: "DWPose Estimation",
|
|
2481
|
-
outputKeys: ["image"],
|
|
2482
|
-
price: {
|
|
2483
|
-
kind: "second",
|
|
2484
|
-
usd: 6e-4
|
|
1256
|
+
pricing: "$0.016/MP of output",
|
|
1257
|
+
scaleField: "scale_factor",
|
|
1258
|
+
scaleRange: {
|
|
1259
|
+
max: 200,
|
|
1260
|
+
min: 1
|
|
2485
1261
|
},
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
category: "preprocess",
|
|
2492
|
-
description: "Generate HED soft edge maps for ControlNet-style workflows.",
|
|
2493
|
-
endpoint: "fal-ai/image-preprocessors/hed",
|
|
2494
|
-
inputField: "image_url",
|
|
2495
|
-
inputKind: "image",
|
|
2496
|
-
name: "HED Edge Preprocessor",
|
|
2497
|
-
outputKeys: ["image"],
|
|
2498
|
-
price: {
|
|
2499
|
-
kind: "call",
|
|
2500
|
-
usd: 0
|
|
2501
|
-
},
|
|
2502
|
-
pricing: "$0/compute-second listed by fal",
|
|
2503
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/hed",
|
|
2504
|
-
task: "edge preprocessing"
|
|
2505
|
-
},
|
|
2506
|
-
lineart: {
|
|
2507
|
-
category: "preprocess",
|
|
2508
|
-
defaultOptions: { coarse: false },
|
|
2509
|
-
description: "Generate line art/control-style edges from an input image.",
|
|
2510
|
-
endpoint: "fal-ai/image-preprocessors/lineart",
|
|
2511
|
-
inputField: "image_url",
|
|
2512
|
-
inputKind: "image",
|
|
2513
|
-
name: "Line Art Preprocessor",
|
|
2514
|
-
outputKeys: ["image"],
|
|
2515
|
-
price: {
|
|
2516
|
-
kind: "call",
|
|
2517
|
-
usd: 0
|
|
2518
|
-
},
|
|
2519
|
-
pricing: "$0/compute-second listed by fal",
|
|
2520
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/lineart",
|
|
2521
|
-
task: "image preprocessing"
|
|
2522
|
-
},
|
|
2523
|
-
"marigold-depth": {
|
|
2524
|
-
category: "depth",
|
|
2525
|
-
defaultOptions: {
|
|
2526
|
-
ensemble_size: 10,
|
|
2527
|
-
num_inference_steps: 10
|
|
2528
|
-
},
|
|
2529
|
-
description: "Create depth maps using Marigold depth estimation.",
|
|
2530
|
-
endpoint: "fal-ai/imageutils/marigold-depth",
|
|
2531
|
-
inputField: "image_url",
|
|
2532
|
-
inputKind: "image",
|
|
2533
|
-
name: "Marigold Depth Estimation",
|
|
2534
|
-
outputKeys: ["image"],
|
|
2535
|
-
price: {
|
|
2536
|
-
kind: "call",
|
|
2537
|
-
usd: 0
|
|
2538
|
-
},
|
|
2539
|
-
pricing: "$0/compute-second listed by fal",
|
|
2540
|
-
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/marigold-depth",
|
|
2541
|
-
task: "depth map"
|
|
2542
|
-
},
|
|
2543
|
-
"midas-depth": {
|
|
2544
|
-
category: "depth",
|
|
2545
|
-
defaultOptions: {
|
|
2546
|
-
a: Math.PI * 2,
|
|
2547
|
-
bg_th: .1
|
|
2548
|
-
},
|
|
2549
|
-
description: "Create MiDaS depth maps from input images.",
|
|
2550
|
-
endpoint: "fal-ai/imageutils/depth",
|
|
2551
|
-
inputField: "image_url",
|
|
2552
|
-
inputKind: "image",
|
|
2553
|
-
name: "MiDaS Depth Estimation",
|
|
2554
|
-
outputKeys: ["image"],
|
|
2555
|
-
price: {
|
|
2556
|
-
kind: "call",
|
|
2557
|
-
usd: 0
|
|
2558
|
-
},
|
|
2559
|
-
pricing: "$0/compute-second listed by fal",
|
|
2560
|
-
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/depth",
|
|
2561
|
-
task: "depth map"
|
|
2562
|
-
},
|
|
2563
|
-
"midas-preprocessor": {
|
|
2564
|
-
category: "preprocess",
|
|
2565
|
-
description: "Generate MiDaS depth and normal maps for image workflows.",
|
|
2566
|
-
endpoint: "fal-ai/image-preprocessors/midas",
|
|
2567
|
-
inputField: "image_url",
|
|
2568
|
-
inputKind: "image",
|
|
2569
|
-
name: "MiDaS Preprocessor",
|
|
2570
|
-
outputKeys: ["depth_map", "normal_map"],
|
|
2571
|
-
price: {
|
|
2572
|
-
kind: "call",
|
|
2573
|
-
usd: 0
|
|
2574
|
-
},
|
|
2575
|
-
pricing: "$0/compute-second listed by fal",
|
|
2576
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/midas",
|
|
2577
|
-
task: "depth and normal preprocessing"
|
|
2578
|
-
},
|
|
2579
|
-
mlsd: {
|
|
2580
|
-
category: "preprocess",
|
|
2581
|
-
description: "Detect straight line segments for architectural and interior control maps.",
|
|
2582
|
-
endpoint: "fal-ai/image-preprocessors/mlsd",
|
|
2583
|
-
inputField: "image_url",
|
|
2584
|
-
inputKind: "image",
|
|
2585
|
-
name: "M-LSD Line Preprocessor",
|
|
2586
|
-
outputKeys: ["image"],
|
|
2587
|
-
price: {
|
|
2588
|
-
kind: "call",
|
|
2589
|
-
usd: 0
|
|
2590
|
-
},
|
|
2591
|
-
pricing: "$0/compute-second listed by fal",
|
|
2592
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/mlsd",
|
|
2593
|
-
task: "line segment preprocessing"
|
|
2594
|
-
},
|
|
2595
|
-
pidi: {
|
|
2596
|
-
category: "preprocess",
|
|
2597
|
-
description: "Generate PiDiNet soft edge maps from an input image.",
|
|
2598
|
-
endpoint: "fal-ai/image-preprocessors/pidi",
|
|
2599
|
-
inputField: "image_url",
|
|
2600
|
-
inputKind: "image",
|
|
2601
|
-
name: "PiDiNet Edge Preprocessor",
|
|
2602
|
-
outputKeys: ["image"],
|
|
2603
|
-
price: {
|
|
2604
|
-
kind: "call",
|
|
2605
|
-
usd: 0
|
|
2606
|
-
},
|
|
2607
|
-
pricing: "$0/compute-second listed by fal",
|
|
2608
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/pidi",
|
|
2609
|
-
task: "edge preprocessing"
|
|
2610
|
-
},
|
|
2611
|
-
"sam-preprocessor": {
|
|
2612
|
-
category: "preprocess",
|
|
2613
|
-
description: "Generate a SAM segmentation map for ControlNet-style workflows.",
|
|
2614
|
-
endpoint: "fal-ai/image-preprocessors/sam",
|
|
2615
|
-
inputField: "image_url",
|
|
2616
|
-
inputKind: "image",
|
|
2617
|
-
name: "SAM Preprocessor",
|
|
2618
|
-
outputKeys: ["image"],
|
|
2619
|
-
price: {
|
|
2620
|
-
kind: "call",
|
|
2621
|
-
usd: 0
|
|
2622
|
-
},
|
|
2623
|
-
pricing: "$0/compute-second listed by fal",
|
|
2624
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/sam",
|
|
2625
|
-
task: "segmentation preprocessing"
|
|
2626
|
-
},
|
|
2627
|
-
"sam2-auto": {
|
|
2628
|
-
category: "segmentation",
|
|
2629
|
-
defaultOptions: {
|
|
2630
|
-
min_mask_region_area: 100,
|
|
2631
|
-
output_format: "png",
|
|
2632
|
-
points_per_side: 32,
|
|
2633
|
-
pred_iou_thresh: .88,
|
|
2634
|
-
stability_score_thresh: .95
|
|
2635
|
-
},
|
|
2636
|
-
description: "Automatically segment an image into combined and individual masks.",
|
|
2637
|
-
endpoint: "fal-ai/sam2/auto-segment",
|
|
2638
|
-
inputField: "image_url",
|
|
2639
|
-
inputKind: "image",
|
|
2640
|
-
name: "SAM 2 Auto Segment",
|
|
2641
|
-
outputKeys: ["combined_mask", "individual_masks"],
|
|
2642
|
-
price: {
|
|
2643
|
-
kind: "call",
|
|
2644
|
-
usd: 0
|
|
2645
|
-
},
|
|
2646
|
-
pricing: "$0/compute-second listed by fal",
|
|
2647
|
-
queued: true,
|
|
2648
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam2/auto-segment",
|
|
2649
|
-
task: "automatic image segmentation"
|
|
2650
|
-
},
|
|
2651
|
-
"sam3-1-image": {
|
|
2652
|
-
category: "segmentation",
|
|
2653
|
-
defaultOptions: {
|
|
2654
|
-
apply_mask: true,
|
|
2655
|
-
max_masks: 3,
|
|
2656
|
-
output_format: "png"
|
|
2657
|
-
},
|
|
2658
|
-
description: "Segment image objects with text, point, or box prompts. SAM 3.1 adds Object Multiplex for faster multi-object tracking.",
|
|
2659
|
-
endpoint: "fal-ai/sam-3-1/image",
|
|
2660
|
-
inputField: "image_url",
|
|
2661
|
-
inputKind: "image",
|
|
2662
|
-
name: "SAM 3.1 Image",
|
|
2663
|
-
outputKeys: [
|
|
2664
|
-
"image",
|
|
2665
|
-
"masks",
|
|
2666
|
-
"metadata",
|
|
2667
|
-
"scores",
|
|
2668
|
-
"boxes"
|
|
2669
|
-
],
|
|
2670
|
-
price: {
|
|
2671
|
-
kind: "call",
|
|
2672
|
-
usd: .01
|
|
2673
|
-
},
|
|
2674
|
-
pricing: "$0.01/request",
|
|
2675
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/image",
|
|
2676
|
-
task: "promptable image segmentation"
|
|
2677
|
-
},
|
|
2678
|
-
"sam3-1-video": {
|
|
2679
|
-
category: "segmentation",
|
|
2680
|
-
defaultOptions: {
|
|
2681
|
-
apply_mask: true,
|
|
2682
|
-
prompt: "person"
|
|
2683
|
-
},
|
|
2684
|
-
description: "SAM 3.1 video segmentation with Object Multiplex tracking for multiple objects.",
|
|
2685
|
-
endpoint: "fal-ai/sam-3-1/video",
|
|
2686
|
-
inputField: "video_url",
|
|
2687
|
-
inputKind: "video",
|
|
2688
|
-
name: "SAM 3.1 Video",
|
|
2689
|
-
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2690
|
-
price: {
|
|
2691
|
-
frames: 16,
|
|
2692
|
-
kind: "frames",
|
|
2693
|
-
usd: .01
|
|
2694
|
-
},
|
|
2695
|
-
pricing: "$0.01/16 frames of video input",
|
|
2696
|
-
queued: true,
|
|
2697
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/video",
|
|
2698
|
-
task: "multi-object video segmentation"
|
|
2699
|
-
},
|
|
2700
|
-
"sam3-image": {
|
|
2701
|
-
category: "segmentation",
|
|
2702
|
-
defaultOptions: {
|
|
2703
|
-
apply_mask: true,
|
|
2704
|
-
max_masks: 3,
|
|
2705
|
-
output_format: "png"
|
|
2706
|
-
},
|
|
2707
|
-
description: "Segment image objects with text, point, or box prompts.",
|
|
2708
|
-
endpoint: "fal-ai/sam-3/image",
|
|
2709
|
-
inputField: "image_url",
|
|
2710
|
-
inputKind: "image",
|
|
2711
|
-
name: "SAM 3 Image",
|
|
2712
|
-
outputKeys: [
|
|
2713
|
-
"image",
|
|
2714
|
-
"masks",
|
|
2715
|
-
"metadata",
|
|
2716
|
-
"scores",
|
|
2717
|
-
"boxes"
|
|
2718
|
-
],
|
|
2719
|
-
price: {
|
|
2720
|
-
kind: "call",
|
|
2721
|
-
usd: .005
|
|
2722
|
-
},
|
|
2723
|
-
pricing: "$0.005/request",
|
|
2724
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image",
|
|
2725
|
-
task: "promptable image segmentation"
|
|
2726
|
-
},
|
|
2727
|
-
"sam3-image-rle": {
|
|
2728
|
-
category: "segmentation",
|
|
2729
|
-
defaultOptions: {
|
|
2730
|
-
apply_mask: true,
|
|
2731
|
-
max_masks: 3
|
|
2732
|
-
},
|
|
2733
|
-
description: "Segment image objects and return run-length encoded masks.",
|
|
2734
|
-
endpoint: "fal-ai/sam-3/image-rle",
|
|
2735
|
-
inputField: "image_url",
|
|
2736
|
-
inputKind: "image",
|
|
2737
|
-
name: "SAM 3 Image RLE",
|
|
2738
|
-
outputKeys: [
|
|
2739
|
-
"rle",
|
|
2740
|
-
"scores",
|
|
2741
|
-
"boxes",
|
|
2742
|
-
"metadata"
|
|
2743
|
-
],
|
|
2744
|
-
price: {
|
|
2745
|
-
kind: "call",
|
|
2746
|
-
usd: .005
|
|
2747
|
-
},
|
|
2748
|
-
pricing: "$0.005/request",
|
|
2749
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image-rle",
|
|
2750
|
-
task: "promptable image segmentation to RLE"
|
|
2751
|
-
},
|
|
2752
|
-
"sam3-video": {
|
|
2753
|
-
category: "segmentation",
|
|
2754
|
-
defaultOptions: {
|
|
2755
|
-
apply_mask: true,
|
|
2756
|
-
detection_threshold: .5,
|
|
2757
|
-
prompt: "person",
|
|
2758
|
-
video_output_type: "X264 (.mp4)"
|
|
2759
|
-
},
|
|
2760
|
-
description: "Segment and track prompted objects across video frames.",
|
|
2761
|
-
endpoint: "fal-ai/sam-3/video",
|
|
2762
|
-
inputField: "video_url",
|
|
2763
|
-
inputKind: "video",
|
|
2764
|
-
name: "SAM 3 Video",
|
|
2765
|
-
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2766
|
-
price: {
|
|
2767
|
-
frames: 16,
|
|
2768
|
-
kind: "frames",
|
|
2769
|
-
usd: .005
|
|
2770
|
-
},
|
|
2771
|
-
pricing: "$0.005/16 frames of video input",
|
|
2772
|
-
queued: true,
|
|
2773
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video",
|
|
2774
|
-
task: "promptable video segmentation"
|
|
2775
|
-
},
|
|
2776
|
-
"sam3-video-rle": {
|
|
2777
|
-
category: "segmentation",
|
|
2778
|
-
defaultOptions: {
|
|
2779
|
-
apply_mask: true,
|
|
2780
|
-
detection_threshold: .5,
|
|
2781
|
-
prompt: "person"
|
|
2782
|
-
},
|
|
2783
|
-
description: "Track prompted video objects and return RLE mask data.",
|
|
2784
|
-
endpoint: "fal-ai/sam-3/video-rle",
|
|
2785
|
-
inputField: "video_url",
|
|
2786
|
-
inputKind: "video",
|
|
2787
|
-
name: "SAM 3 Video RLE",
|
|
2788
|
-
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2789
|
-
price: {
|
|
2790
|
-
frames: 16,
|
|
2791
|
-
kind: "frames",
|
|
2792
|
-
usd: .005
|
|
2793
|
-
},
|
|
2794
|
-
pricing: "$0.005/16 frames of video",
|
|
2795
|
-
queued: true,
|
|
2796
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video-rle",
|
|
2797
|
-
task: "promptable video segmentation to RLE"
|
|
2798
|
-
},
|
|
2799
|
-
scribble: {
|
|
2800
|
-
category: "preprocess",
|
|
2801
|
-
description: "Turn an image into a scribble-style control map.",
|
|
2802
|
-
endpoint: "fal-ai/image-preprocessors/scribble",
|
|
2803
|
-
inputField: "image_url",
|
|
2804
|
-
inputKind: "image",
|
|
2805
|
-
name: "Scribble Preprocessor",
|
|
2806
|
-
outputKeys: ["image"],
|
|
2807
|
-
price: {
|
|
2808
|
-
kind: "call",
|
|
2809
|
-
usd: 0
|
|
2810
|
-
},
|
|
2811
|
-
pricing: "$0/compute-second listed by fal",
|
|
2812
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/scribble",
|
|
2813
|
-
task: "scribble preprocessing"
|
|
2814
|
-
},
|
|
2815
|
-
teed: {
|
|
2816
|
-
category: "preprocess",
|
|
2817
|
-
description: "Generate TEED edge maps from an input image.",
|
|
2818
|
-
endpoint: "fal-ai/image-preprocessors/teed",
|
|
2819
|
-
inputField: "image_url",
|
|
2820
|
-
inputKind: "image",
|
|
2821
|
-
name: "TEED Edge Preprocessor",
|
|
2822
|
-
outputKeys: ["image"],
|
|
2823
|
-
price: {
|
|
2824
|
-
kind: "call",
|
|
2825
|
-
usd: 0
|
|
2826
|
-
},
|
|
2827
|
-
pricing: "$0/compute-second listed by fal",
|
|
2828
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/teed",
|
|
2829
|
-
task: "edge preprocessing"
|
|
2830
|
-
},
|
|
2831
|
-
"zoe-depth": {
|
|
2832
|
-
category: "preprocess",
|
|
2833
|
-
description: "Generate ZoeDepth metric depth maps from an input image.",
|
|
2834
|
-
endpoint: "fal-ai/image-preprocessors/zoe",
|
|
2835
|
-
inputField: "image_url",
|
|
2836
|
-
inputKind: "image",
|
|
2837
|
-
name: "ZoeDepth Preprocessor",
|
|
2838
|
-
outputKeys: ["image"],
|
|
2839
|
-
price: {
|
|
2840
|
-
kind: "call",
|
|
2841
|
-
usd: 0
|
|
2842
|
-
},
|
|
2843
|
-
pricing: "$0/compute-second listed by fal",
|
|
2844
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/zoe",
|
|
2845
|
-
task: "depth preprocessing"
|
|
1262
|
+
supportsAspect: false,
|
|
1263
|
+
supportsEdit: false,
|
|
1264
|
+
supportsNumImages: false,
|
|
1265
|
+
supportsResolution: false,
|
|
1266
|
+
type: "utility"
|
|
2846
1267
|
}
|
|
2847
1268
|
};
|
|
2848
|
-
|
|
2849
|
-
const FAL_TOOLS = {
|
|
2850
|
-
...ANALYSIS_TOOLS,
|
|
2851
|
-
...ASSET_TOOLS,
|
|
2852
|
-
...BACKGROUND_TOOLS,
|
|
2853
|
-
...EDITING_TOOLS,
|
|
2854
|
-
...STRUCTURE_TOOLS
|
|
2855
|
-
};
|
|
2856
|
-
Object.keys(FAL_TOOLS);
|
|
1269
|
+
Object.keys(MODELS).filter((id) => MODELS[id]?.type === "generation");
|
|
2857
1270
|
// src/image/fetch.ts
|
|
2858
1271
|
function urlOf(input) {
|
|
2859
1272
|
if (typeof input === "string") return input;
|
|
@@ -2871,7 +1284,7 @@ function toProviderFetch(fetch) {
|
|
|
2871
1284
|
* Builds a Vercel AI SDK `ImageModel` from `@ai-sdk/fal`. Building a model
|
|
2872
1285
|
* performs no network I/O — the request only happens when `generateImage`
|
|
2873
1286
|
* invokes `model.doGenerate`. This is the lightweight fal *image* adapter; the
|
|
2874
|
-
*
|
|
1287
|
+
* Task client (`createMotif`) runs fal's queue, upload and tools.
|
|
2875
1288
|
*
|
|
2876
1289
|
* ENDPOINT QUIRK (Phase 0): fal's gpt-image endpoint wants `image_size` as a
|
|
2877
1290
|
* STRING enum (e.g. "1024x1024"), passed at generate time via
|
|
@@ -2889,35 +1302,38 @@ function toProviderFetch(fetch) {
|
|
|
2889
1302
|
const FAL_GPT_IMAGE_MODEL = "fal-ai/gpt-image-1.5";
|
|
2890
1303
|
/** Env var read for the fal key when `apiKey` is not supplied in config. */
|
|
2891
1304
|
const FAL_API_KEY_ENV = "FAL_KEY";
|
|
1305
|
+
function registryPrice(modelId) {
|
|
1306
|
+
const price = MODELS[modelId]?.pricePerImageUsd;
|
|
1307
|
+
if (typeof price !== "number") throw new MotifError(`Registry Model ${modelId} has no per-image price`, 0);
|
|
1308
|
+
return price;
|
|
1309
|
+
}
|
|
2892
1310
|
/**
|
|
2893
1311
|
* Static fal USD/image, keyed by the fal ENDPOINT id. Cost tracking must price
|
|
2894
1312
|
* the endpoints consumers actually pass. Every price is
|
|
2895
1313
|
* sourced from the fal registry snapshot in `../models`
|
|
2896
1314
|
* (`MODELS[...].pricePerImageUsd`) so this table stays in sync rather than
|
|
2897
|
-
* drifting to a second hand-maintained copy;
|
|
2898
|
-
*
|
|
2899
|
-
* price. Each key is `MODELS[x].endpoint`; the trailing comment cites the
|
|
2900
|
-
* `MODELS` key it comes from. Covers the flux2 family, banana, seedream, and
|
|
1315
|
+
* drifting to a second hand-maintained copy; a registry entry without a price throws at
|
|
1316
|
+
* load. Each key is `MODELS[x].endpoint`. Covers the flux2 family, banana, seedream, and
|
|
2901
1317
|
* the other priced fal generation endpoints.
|
|
2902
1318
|
*/
|
|
2903
1319
|
const FAL_IMAGE_PRICE_USD = {
|
|
2904
|
-
"fal-ai/flux-2-pro":
|
|
2905
|
-
"fal-ai/flux-2-flex":
|
|
2906
|
-
"fal-ai/flux-2/turbo":
|
|
2907
|
-
[FAL_GPT_IMAGE_MODEL]:
|
|
2908
|
-
"fal-ai/nano-banana-2":
|
|
2909
|
-
"fal-ai/nano-banana-pro":
|
|
2910
|
-
"bytedance/seedream/v5/pro/text-to-image":
|
|
2911
|
-
"bytedance/seedream/v5/lite/text-to-image":
|
|
2912
|
-
"fal-ai/recraft/v4.1/text-to-image":
|
|
2913
|
-
"ideogram/v4":
|
|
2914
|
-
"xai/grok-imagine-image":
|
|
2915
|
-
"xai/grok-imagine-image/v2.0/text-to-image":
|
|
2916
|
-
"xai/grok-imagine-image/quality/text-to-image":
|
|
2917
|
-
"meta/muse-image/text-to-image":
|
|
2918
|
-
"microsoft/mai-image-2.5-pro":
|
|
2919
|
-
"fal-ai/ideogram/v3/generate-transparent":
|
|
2920
|
-
"alibaba/qwen-image-3/text-to-image":
|
|
1320
|
+
"fal-ai/flux-2-pro": registryPrice("flux2-pro"),
|
|
1321
|
+
"fal-ai/flux-2-flex": registryPrice("flux2-flex"),
|
|
1322
|
+
"fal-ai/flux-2/turbo": registryPrice("flux2-turbo"),
|
|
1323
|
+
[FAL_GPT_IMAGE_MODEL]: registryPrice("gpt"),
|
|
1324
|
+
"fal-ai/nano-banana-2": registryPrice("banana2"),
|
|
1325
|
+
"fal-ai/nano-banana-pro": registryPrice("banana"),
|
|
1326
|
+
"bytedance/seedream/v5/pro/text-to-image": registryPrice("seedream5"),
|
|
1327
|
+
"bytedance/seedream/v5/lite/text-to-image": registryPrice("seedream5-lite"),
|
|
1328
|
+
"fal-ai/recraft/v4.1/text-to-image": registryPrice("recraft41"),
|
|
1329
|
+
"ideogram/v4": registryPrice("ideogram4"),
|
|
1330
|
+
"xai/grok-imagine-image": registryPrice("grok-image"),
|
|
1331
|
+
"xai/grok-imagine-image/v2.0/text-to-image": registryPrice("grok-image-2"),
|
|
1332
|
+
"xai/grok-imagine-image/quality/text-to-image": registryPrice("grok-image-quality"),
|
|
1333
|
+
"meta/muse-image/text-to-image": registryPrice("muse-image"),
|
|
1334
|
+
"microsoft/mai-image-2.5-pro": registryPrice("mai-image-2.5-pro"),
|
|
1335
|
+
"fal-ai/ideogram/v3/generate-transparent": registryPrice("ideogram3-transparent"),
|
|
1336
|
+
"alibaba/qwen-image-3/text-to-image": registryPrice("qwen3")
|
|
2921
1337
|
};
|
|
2922
1338
|
/**
|
|
2923
1339
|
* Build a fal `ImageModel`. Prefers the passed `apiKey`, else the `FAL_KEY` env
|
|
@@ -3046,9 +1462,6 @@ function openRouterModelSlug(modelId) {
|
|
|
3046
1462
|
if (slug === void 0) throw new MotifError(`No OpenRouter image model for "${modelId}". Known: ${Object.keys(OPENROUTER_GEMINI_IMAGE_MODELS).join(", ")}; or pass an OpenRouter slug such as google/gemini-3.1-flash-image.`, 0);
|
|
3047
1463
|
return slug;
|
|
3048
1464
|
}
|
|
3049
|
-
function isRecord$2(value) {
|
|
3050
|
-
return typeof value === "object" && value !== null;
|
|
3051
|
-
}
|
|
3052
1465
|
function toDataUrl(mediaType, data) {
|
|
3053
1466
|
return `data:${mediaType};base64,${typeof data === "string" ? data : Buffer.from(data).toString("base64")}`;
|
|
3054
1467
|
}
|
|
@@ -3071,20 +1484,20 @@ function buildBody(slug, options) {
|
|
|
3071
1484
|
};
|
|
3072
1485
|
}
|
|
3073
1486
|
function errorMessage(body, fallback) {
|
|
3074
|
-
if (isRecord
|
|
1487
|
+
if (isRecord(body) && isRecord(body.error)) {
|
|
3075
1488
|
const { message } = body.error;
|
|
3076
1489
|
if (typeof message === "string" && message !== "") return message;
|
|
3077
1490
|
}
|
|
3078
1491
|
return fallback;
|
|
3079
1492
|
}
|
|
3080
1493
|
function parseResponse(body) {
|
|
3081
|
-
if (!isRecord
|
|
1494
|
+
if (!isRecord(body) || !Array.isArray(body.data)) throw new MotifError("OpenRouter image response had no data array", 502);
|
|
3082
1495
|
const images = [];
|
|
3083
|
-
for (const entry of body.data) if (isRecord
|
|
1496
|
+
for (const entry of body.data) if (isRecord(entry) && typeof entry.b64_json === "string") images.push(entry.b64_json);
|
|
3084
1497
|
if (images.length === 0) throw new MotifError("OpenRouter returned no images", 502);
|
|
3085
1498
|
return {
|
|
3086
1499
|
images,
|
|
3087
|
-
cost: isRecord
|
|
1500
|
+
cost: isRecord(body.usage) && typeof body.usage.cost === "number" ? body.usage.cost : void 0
|
|
3088
1501
|
};
|
|
3089
1502
|
}
|
|
3090
1503
|
function buildModel(modelId, apiKey, doFetch) {
|
|
@@ -3231,17 +1644,14 @@ function getProviderAdapter(provider) {
|
|
|
3231
1644
|
* from the provider registry (see sources in each adapter).
|
|
3232
1645
|
* 3. Unknown → `{ usd: 0, source: "unknown" }`.
|
|
3233
1646
|
*/
|
|
3234
|
-
function isRecord$1(value) {
|
|
3235
|
-
return typeof value === "object" && value !== null;
|
|
3236
|
-
}
|
|
3237
1647
|
/**
|
|
3238
1648
|
* Extract a provider-reported total cost from a `generateImage` result's
|
|
3239
1649
|
* `providerMetadata`, if the provider surfaces a numeric `cost`. The shape is
|
|
3240
1650
|
* `{ [provider]: { ...; cost?: number } }`. Returns undefined otherwise.
|
|
3241
1651
|
*/
|
|
3242
1652
|
function costFromProviderMetadata(providerMetadata) {
|
|
3243
|
-
if (!isRecord
|
|
3244
|
-
for (const value of Object.values(providerMetadata)) if (isRecord
|
|
1653
|
+
if (!isRecord(providerMetadata)) return;
|
|
1654
|
+
for (const value of Object.values(providerMetadata)) if (isRecord(value)) {
|
|
3245
1655
|
const cost = value.cost;
|
|
3246
1656
|
if (typeof cost === "number" && Number.isFinite(cost)) return cost;
|
|
3247
1657
|
}
|
|
@@ -3493,9 +1903,6 @@ function renderWarning(warning) {
|
|
|
3493
1903
|
if (warning.type === "deprecated") return `deprecated setting "${warning.setting}": ${warning.message}`;
|
|
3494
1904
|
return warning.message;
|
|
3495
1905
|
}
|
|
3496
|
-
function isRecord(value) {
|
|
3497
|
-
return typeof value === "object" && value !== null;
|
|
3498
|
-
}
|
|
3499
1906
|
/** Look for a provider correlation id in providerMetadata, then response headers. */
|
|
3500
1907
|
function extractRequestId(result) {
|
|
3501
1908
|
for (const call of result.calls) {
|