@shop-os/modelkit 0.1.2 → 0.1.4
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 +27 -21
- package/dist/index.cjs +408 -179
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +408 -179
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -83,7 +83,18 @@ var Catalog = class _Catalog {
|
|
|
83
83
|
|
|
84
84
|
// src/catalog/image.ts
|
|
85
85
|
var IMAGE_USAGE = { unit: "images", modality: "IMAGE" };
|
|
86
|
-
var GEMINI_RATIOS = [
|
|
86
|
+
var GEMINI_RATIOS = [
|
|
87
|
+
"1:1",
|
|
88
|
+
"2:3",
|
|
89
|
+
"3:2",
|
|
90
|
+
"16:9",
|
|
91
|
+
"9:16",
|
|
92
|
+
"4:3",
|
|
93
|
+
"3:4",
|
|
94
|
+
"21:9",
|
|
95
|
+
"4:5",
|
|
96
|
+
"5:4"
|
|
97
|
+
];
|
|
87
98
|
function geminiImage(id, label, aliases, sizes) {
|
|
88
99
|
const model = {
|
|
89
100
|
id,
|
|
@@ -106,7 +117,8 @@ var IMAGE_MODELS = [
|
|
|
106
117
|
"gemini-3.1-flash-image-preview",
|
|
107
118
|
"Nano Banana Flash",
|
|
108
119
|
["nb-2"],
|
|
109
|
-
|
|
120
|
+
// Flash 3.1 is the only Gemini image model with the 512 tier.
|
|
121
|
+
["512", "1K", "2K", "4K"]
|
|
110
122
|
),
|
|
111
123
|
geminiImage("gemini-3.1-flash-lite-image", "Nano Banana Lite", ["nb-lite"], ["1K"]),
|
|
112
124
|
// trigger-workflows validates 1K only; pricing seeds 2K/4K rows so allow all three.
|
|
@@ -210,7 +222,10 @@ var IMAGE_MODELS = [
|
|
|
210
222
|
constraints: {
|
|
211
223
|
aspectRatios: ["1:1", "4:3", "3:4", "16:9", "9:16", "3:2", "2:3", "21:9", "4:5", "5:4"],
|
|
212
224
|
sizes: ["1K", "2K"],
|
|
213
|
-
references: { images: 10 }
|
|
225
|
+
references: { images: 10 },
|
|
226
|
+
// Ark's Images API has no output-format, quality or count field; only
|
|
227
|
+
// the seed is forwarded, so anything else must warn, not vanish.
|
|
228
|
+
supports: ["seed"]
|
|
214
229
|
},
|
|
215
230
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
216
231
|
usage: { ...IMAGE_USAGE },
|
|
@@ -225,21 +240,12 @@ var IMAGE_MODELS = [
|
|
|
225
240
|
providerModelId: "seedream-4-5-251128",
|
|
226
241
|
lifecycle: "active",
|
|
227
242
|
constraints: {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
"3:2",
|
|
232
|
-
"4:3",
|
|
233
|
-
"3:4",
|
|
234
|
-
"4:5",
|
|
235
|
-
"5:4",
|
|
236
|
-
"9:16",
|
|
237
|
-
"16:9",
|
|
238
|
-
"21:9",
|
|
239
|
-
"97:30"
|
|
240
|
-
],
|
|
243
|
+
// 97:30 has no Ark size spelling; the A+ flow pads inputs to 97:30 and
|
|
244
|
+
// omits the ratio instead. Advertise only sizes the adapter can send.
|
|
245
|
+
aspectRatios: ["1:1", "2:3", "3:2", "4:3", "3:4", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
241
246
|
sizes: ["1K", "2K"],
|
|
242
|
-
references: { images: 10 }
|
|
247
|
+
references: { images: 10 },
|
|
248
|
+
supports: ["seed"]
|
|
243
249
|
},
|
|
244
250
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
245
251
|
usage: { ...IMAGE_USAGE },
|
|
@@ -263,6 +269,9 @@ var IMAGE_MODELS = [
|
|
|
263
269
|
pricingKind: "image_size"
|
|
264
270
|
},
|
|
265
271
|
{
|
|
272
|
+
// Prodia's gemini-3-pro jobs take aspect_ratio + resolution (1K/2K/4K), not
|
|
273
|
+
// width/height; 97:30 is outside its aspect_ratio enum.
|
|
274
|
+
// https://docs.prodia.com/models/gemini-3/
|
|
266
275
|
id: "prodia-nano-banana-pro",
|
|
267
276
|
aliases: [],
|
|
268
277
|
label: "Nano Banana Pro via Prodia",
|
|
@@ -271,19 +280,7 @@ var IMAGE_MODELS = [
|
|
|
271
280
|
providerModelId: "inference.gemini-3-pro.img2img.v1",
|
|
272
281
|
lifecycle: "active",
|
|
273
282
|
constraints: {
|
|
274
|
-
aspectRatios: [
|
|
275
|
-
"1:1",
|
|
276
|
-
"2:3",
|
|
277
|
-
"3:2",
|
|
278
|
-
"4:3",
|
|
279
|
-
"3:4",
|
|
280
|
-
"4:5",
|
|
281
|
-
"5:4",
|
|
282
|
-
"9:16",
|
|
283
|
-
"16:9",
|
|
284
|
-
"21:9",
|
|
285
|
-
"97:30"
|
|
286
|
-
],
|
|
283
|
+
aspectRatios: ["1:1", "2:3", "3:2", "4:3", "3:4", "4:5", "5:4", "9:16", "16:9", "21:9"],
|
|
287
284
|
sizes: ["1K", "2K", "4K"],
|
|
288
285
|
requires: ["references"]
|
|
289
286
|
},
|
|
@@ -292,6 +289,8 @@ var IMAGE_MODELS = [
|
|
|
292
289
|
pricingKind: "image_size"
|
|
293
290
|
},
|
|
294
291
|
{
|
|
292
|
+
// Nano Banana (img2img.v2) is flat-rate with aspect_ratio only; 3:2, 4:5,
|
|
293
|
+
// 5:4 and 97:30 are not in its enum. https://docs.prodia.com/models/nano-banana/
|
|
295
294
|
id: "prodia-nano-banana",
|
|
296
295
|
aliases: [],
|
|
297
296
|
label: "Nano Banana via Prodia",
|
|
@@ -300,19 +299,7 @@ var IMAGE_MODELS = [
|
|
|
300
299
|
providerModelId: "inference.nano-banana.img2img.v2",
|
|
301
300
|
lifecycle: "active",
|
|
302
301
|
constraints: {
|
|
303
|
-
aspectRatios: [
|
|
304
|
-
"1:1",
|
|
305
|
-
"2:3",
|
|
306
|
-
"3:2",
|
|
307
|
-
"4:3",
|
|
308
|
-
"3:4",
|
|
309
|
-
"4:5",
|
|
310
|
-
"5:4",
|
|
311
|
-
"9:16",
|
|
312
|
-
"16:9",
|
|
313
|
-
"21:9",
|
|
314
|
-
"97:30"
|
|
315
|
-
],
|
|
302
|
+
aspectRatios: ["1:1", "2:3", "3:4", "4:3", "9:16", "16:9", "21:9"],
|
|
316
303
|
sizes: ["1K"],
|
|
317
304
|
requires: ["references"]
|
|
318
305
|
},
|
|
@@ -321,6 +308,9 @@ var IMAGE_MODELS = [
|
|
|
321
308
|
pricingKind: "image_size"
|
|
322
309
|
},
|
|
323
310
|
{
|
|
311
|
+
// WAN 2.7 takes `images` (up to 9) and a `size` enum whose exact values
|
|
312
|
+
// cover 1:1/16:9/9:16/4:3/3:4 only; other ratios have no spelling.
|
|
313
|
+
// https://replicate.com/wan-video/wan-2.7-image-pro (input schema)
|
|
324
314
|
id: "wan-2.7-image-pro",
|
|
325
315
|
aliases: [],
|
|
326
316
|
label: "WAN 2.7 Image Pro",
|
|
@@ -329,19 +319,7 @@ var IMAGE_MODELS = [
|
|
|
329
319
|
providerModelId: "wan-video/wan-2.7-image-pro",
|
|
330
320
|
lifecycle: "active",
|
|
331
321
|
constraints: {
|
|
332
|
-
aspectRatios: [
|
|
333
|
-
"1:1",
|
|
334
|
-
"2:3",
|
|
335
|
-
"3:2",
|
|
336
|
-
"4:3",
|
|
337
|
-
"3:4",
|
|
338
|
-
"4:5",
|
|
339
|
-
"5:4",
|
|
340
|
-
"9:16",
|
|
341
|
-
"16:9",
|
|
342
|
-
"21:9",
|
|
343
|
-
"97:30"
|
|
344
|
-
],
|
|
322
|
+
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4"],
|
|
345
323
|
sizes: ["1K", "2K", "4K"],
|
|
346
324
|
references: { images: 9 }
|
|
347
325
|
},
|
|
@@ -350,6 +328,9 @@ var IMAGE_MODELS = [
|
|
|
350
328
|
pricingKind: "image_size"
|
|
351
329
|
},
|
|
352
330
|
{
|
|
331
|
+
// Qwen Image 2 Pro has aspect_ratio but no size input; resolution follows
|
|
332
|
+
// the reference image (match_input_image) or the provider default.
|
|
333
|
+
// https://replicate.com/qwen/qwen-image-2-pro (input schema)
|
|
353
334
|
id: "qwen-image-2-pro",
|
|
354
335
|
aliases: [],
|
|
355
336
|
label: "Qwen Image 2 Pro",
|
|
@@ -358,28 +339,19 @@ var IMAGE_MODELS = [
|
|
|
358
339
|
providerModelId: "qwen/qwen-image-2-pro",
|
|
359
340
|
lifecycle: "active",
|
|
360
341
|
constraints: {
|
|
361
|
-
aspectRatios: [
|
|
362
|
-
|
|
363
|
-
"2:3",
|
|
364
|
-
"3:2",
|
|
365
|
-
"4:3",
|
|
366
|
-
"3:4",
|
|
367
|
-
"4:5",
|
|
368
|
-
"5:4",
|
|
369
|
-
"9:16",
|
|
370
|
-
"16:9",
|
|
371
|
-
"21:9",
|
|
372
|
-
"97:30"
|
|
373
|
-
],
|
|
374
|
-
sizes: ["1K", "2K", "4K"],
|
|
342
|
+
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"],
|
|
343
|
+
sizes: [],
|
|
375
344
|
references: { images: 1 },
|
|
376
345
|
requires: ["references"]
|
|
377
346
|
},
|
|
378
|
-
defaults: {
|
|
347
|
+
defaults: { aspectRatio: "1:1" },
|
|
379
348
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
380
349
|
pricingKind: "image_size"
|
|
381
350
|
},
|
|
382
351
|
{
|
|
352
|
+
// Qwen Image Edit Plus takes aspect_ratio (or match_input_image) and
|
|
353
|
+
// output_format, but no size; no default ratio so edits keep following
|
|
354
|
+
// the input image. https://replicate.com/qwen-edit-apps/qwen-image-edit-plus-lora-skin
|
|
383
355
|
id: "qwen-image-edit-plus-lora-skin",
|
|
384
356
|
aliases: [],
|
|
385
357
|
label: "Qwen Image Edit Plus",
|
|
@@ -388,25 +360,13 @@ var IMAGE_MODELS = [
|
|
|
388
360
|
providerModelId: "qwen-edit-apps/qwen-image-edit-plus-lora-skin",
|
|
389
361
|
lifecycle: "active",
|
|
390
362
|
constraints: {
|
|
391
|
-
aspectRatios: [
|
|
392
|
-
|
|
393
|
-
"2:3",
|
|
394
|
-
"3:2",
|
|
395
|
-
"4:3",
|
|
396
|
-
"3:4",
|
|
397
|
-
"4:5",
|
|
398
|
-
"5:4",
|
|
399
|
-
"9:16",
|
|
400
|
-
"16:9",
|
|
401
|
-
"21:9",
|
|
402
|
-
"97:30"
|
|
403
|
-
],
|
|
404
|
-
sizes: ["1K", "2K", "4K"],
|
|
363
|
+
aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4"],
|
|
364
|
+
sizes: [],
|
|
405
365
|
references: { images: 1 },
|
|
406
366
|
requires: ["references"],
|
|
407
367
|
supports: ["outputFormat"]
|
|
408
368
|
},
|
|
409
|
-
defaults: {
|
|
369
|
+
defaults: { outputFormat: "png" },
|
|
410
370
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
411
371
|
pricingKind: "image_size"
|
|
412
372
|
}
|
|
@@ -503,8 +463,12 @@ var OTHER_MODELS = [
|
|
|
503
463
|
adapter: "replicate",
|
|
504
464
|
providerModelId: "topazlabs/image-upscale",
|
|
505
465
|
lifecycle: "active",
|
|
506
|
-
constraints: {
|
|
507
|
-
|
|
466
|
+
constraints: {
|
|
467
|
+
references: { images: 1 },
|
|
468
|
+
requires: ["references"],
|
|
469
|
+
supports: ["scaleFactor", "outputFormat"]
|
|
470
|
+
},
|
|
471
|
+
defaults: { scaleFactor: 2, outputFormat: "png" },
|
|
508
472
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
509
473
|
pricingKind: "flat"
|
|
510
474
|
},
|
|
@@ -560,7 +524,7 @@ var TEXT_MODELS = [
|
|
|
560
524
|
text("gpt-5.6-sol", "GPT-5.6 Sol", "gpt-5.6-sol"),
|
|
561
525
|
// Library key "claude-sonnet-4.5" maps to the SDK id "claude-sonnet-4-5".
|
|
562
526
|
text("claude-sonnet-4-5", "Claude Sonnet 4.5", "claude-sonnet-4-5", {
|
|
563
|
-
aliases: ["claude-sonnet-4.5"]
|
|
527
|
+
aliases: ["claude-sonnet-4.5", "claude-sonnet-4-5-20250929"]
|
|
564
528
|
}),
|
|
565
529
|
// Anthropic retired the dated 4.0 ids; callers that still send them get 4.6.
|
|
566
530
|
text("claude-sonnet-4-6", "Claude Sonnet 4.6", "claude-sonnet-4-6", {
|
|
@@ -576,7 +540,7 @@ var TEXT_MODELS = [
|
|
|
576
540
|
aliases: ["claude-opus-4.8", "claude-opus-4", "claude-opus-4.0", "claude-opus-4-20250514"]
|
|
577
541
|
}),
|
|
578
542
|
text("claude-haiku-4-5", "Claude Haiku 4.5", "claude-haiku-4-5", {
|
|
579
|
-
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001"]
|
|
543
|
+
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001", "claude-haiku-4"]
|
|
580
544
|
}),
|
|
581
545
|
text("claude-opus-5", "Claude Opus 5", "claude-opus-5", {
|
|
582
546
|
aliases: ["claude-opus-5.0"]
|
|
@@ -1059,7 +1023,7 @@ var MODELS = [
|
|
|
1059
1023
|
];
|
|
1060
1024
|
|
|
1061
1025
|
// src/resolve-options.ts
|
|
1062
|
-
var SIZE_ORDER = ["1K", "2K", "4K"];
|
|
1026
|
+
var SIZE_ORDER = ["512", "1K", "2K", "4K"];
|
|
1063
1027
|
var RESOLUTION_ORDER = ["360p", "480p", "720p", "768p", "1080p", "2k", "4k"];
|
|
1064
1028
|
function ratioValue(r) {
|
|
1065
1029
|
if (r === "adaptive") return 1;
|
|
@@ -1191,7 +1155,13 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1191
1155
|
model: model.id
|
|
1192
1156
|
});
|
|
1193
1157
|
}
|
|
1194
|
-
dropUnsupported(merged, model, warnings, [
|
|
1158
|
+
dropUnsupported(merged, model, warnings, [
|
|
1159
|
+
"seed",
|
|
1160
|
+
"quality",
|
|
1161
|
+
"count",
|
|
1162
|
+
"outputFormat",
|
|
1163
|
+
"scaleFactor"
|
|
1164
|
+
]);
|
|
1195
1165
|
return { request: merged, warnings };
|
|
1196
1166
|
}
|
|
1197
1167
|
function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
@@ -1823,7 +1793,11 @@ var aiSdkTextAdapter = {
|
|
|
1823
1793
|
function requiredKeys(model, config) {
|
|
1824
1794
|
if (model.adapter === "fal" && config.routing?.fal === "cloudflare-passthrough")
|
|
1825
1795
|
return ["cloudflare"];
|
|
1826
|
-
if (model.adapter === "ai-sdk-text")
|
|
1796
|
+
if (model.adapter === "ai-sdk-text") {
|
|
1797
|
+
const names = [textKeyName(model, config.routing ?? {})];
|
|
1798
|
+
if (config.routing?.text === "cloudflare") names.push("cloudflare");
|
|
1799
|
+
return names;
|
|
1800
|
+
}
|
|
1827
1801
|
return ADAPTER_KEYS[model.adapter];
|
|
1828
1802
|
}
|
|
1829
1803
|
var IMAGE_OUTPUT_TYPES = /* @__PURE__ */ new Set(["image", "upscale", "bg-remove"]);
|
|
@@ -1881,6 +1855,20 @@ function sdkAspectRatio(ratio) {
|
|
|
1881
1855
|
const parsed = sdkRatio.safeParse(ratio);
|
|
1882
1856
|
return parsed.success ? parsed.data : void 0;
|
|
1883
1857
|
}
|
|
1858
|
+
function sdkDataContent(ref) {
|
|
1859
|
+
return "url" in ref ? ref.url : ref.bytes;
|
|
1860
|
+
}
|
|
1861
|
+
function sdkReference(ref) {
|
|
1862
|
+
return "url" in ref ? ref.url : { data: ref.bytes, mediaType: ref.mime };
|
|
1863
|
+
}
|
|
1864
|
+
function pushIgnored(warnings, field, from, modelId) {
|
|
1865
|
+
warnings.push({
|
|
1866
|
+
code: "option_ignored",
|
|
1867
|
+
field,
|
|
1868
|
+
from,
|
|
1869
|
+
message: `${modelId} provider instance does not support ${field}; ignored`
|
|
1870
|
+
});
|
|
1871
|
+
}
|
|
1884
1872
|
function createModelKit(config, adapters) {
|
|
1885
1873
|
const catalog = new Catalog(MODELS).withOverrides(config.catalogOverride ?? []);
|
|
1886
1874
|
const logger = config.logger ?? console;
|
|
@@ -1903,6 +1891,7 @@ function createModelKit(config, adapters) {
|
|
|
1903
1891
|
call,
|
|
1904
1892
|
warnings
|
|
1905
1893
|
};
|
|
1894
|
+
if (config.endpoints) ctx.endpoints = config.endpoints;
|
|
1906
1895
|
if (call.signal) ctx.signal = call.signal;
|
|
1907
1896
|
return { adapter, ctx };
|
|
1908
1897
|
}
|
|
@@ -1942,16 +1931,45 @@ function createModelKit(config, adapters) {
|
|
|
1942
1931
|
};
|
|
1943
1932
|
}
|
|
1944
1933
|
async function passthroughImage(req, call) {
|
|
1945
|
-
const {
|
|
1934
|
+
const {
|
|
1935
|
+
model,
|
|
1936
|
+
prompt,
|
|
1937
|
+
n,
|
|
1938
|
+
count,
|
|
1939
|
+
size,
|
|
1940
|
+
aspectRatio,
|
|
1941
|
+
seed,
|
|
1942
|
+
providerOptions,
|
|
1943
|
+
references,
|
|
1944
|
+
exactSize: exactSizeField,
|
|
1945
|
+
scaleFactor,
|
|
1946
|
+
quality: _quality,
|
|
1947
|
+
outputFormat: _outputFormat
|
|
1948
|
+
} = req;
|
|
1946
1949
|
const options = { model, prompt };
|
|
1950
|
+
const warnings = [];
|
|
1947
1951
|
const quantity = n ?? count;
|
|
1948
1952
|
if (quantity !== void 0) options.n = quantity;
|
|
1949
|
-
|
|
1950
|
-
|
|
1953
|
+
if (references !== void 0 && references.length > 0)
|
|
1954
|
+
options.prompt = { images: references.map(sdkDataContent), text: prompt };
|
|
1955
|
+
const exact = exactSizeField === void 0 ? void 0 : exactSize.safeParse(exactSizeField);
|
|
1956
|
+
if (exact?.success) options.size = exact.data;
|
|
1957
|
+
else if (exactSizeField !== void 0)
|
|
1958
|
+
pushIgnored(warnings, "exactSize", exactSizeField, model.modelId);
|
|
1959
|
+
const requested = size === void 0 ? void 0 : exactSize.safeParse(size);
|
|
1960
|
+
if (requested?.success) options.size ??= requested.data;
|
|
1961
|
+
else if (size !== void 0) pushIgnored(warnings, "size", size, model.modelId);
|
|
1951
1962
|
const ratio = sdkAspectRatio(aspectRatio);
|
|
1952
1963
|
if (ratio) options.aspectRatio = ratio;
|
|
1964
|
+
else if (aspectRatio !== void 0)
|
|
1965
|
+
pushIgnored(warnings, "aspectRatio", aspectRatio, model.modelId);
|
|
1953
1966
|
if (seed !== void 0) options.seed = seed;
|
|
1954
1967
|
if (providerOptions) options.providerOptions = providerOptions;
|
|
1968
|
+
if (_quality !== void 0) pushIgnored(warnings, "quality", _quality, model.modelId);
|
|
1969
|
+
if (_outputFormat !== void 0)
|
|
1970
|
+
pushIgnored(warnings, "outputFormat", _outputFormat, model.modelId);
|
|
1971
|
+
if (scaleFactor !== void 0)
|
|
1972
|
+
pushIgnored(warnings, "scaleFactor", scaleFactor, model.modelId);
|
|
1955
1973
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
1956
1974
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
1957
1975
|
const result = await aiGenerateImage(options);
|
|
@@ -1966,17 +1984,73 @@ function createModelKit(config, adapters) {
|
|
|
1966
1984
|
quantity: images.length
|
|
1967
1985
|
};
|
|
1968
1986
|
await emit(usage2);
|
|
1969
|
-
return { image: images[0], images, usage: usage2, raw: result, warnings
|
|
1987
|
+
return { image: images[0], images, usage: usage2, raw: result, warnings };
|
|
1970
1988
|
}
|
|
1971
1989
|
function passthroughVideo(req, call) {
|
|
1972
|
-
const {
|
|
1990
|
+
const {
|
|
1991
|
+
model,
|
|
1992
|
+
prompt,
|
|
1993
|
+
aspectRatio,
|
|
1994
|
+
duration,
|
|
1995
|
+
durationSeconds,
|
|
1996
|
+
seed,
|
|
1997
|
+
providerOptions,
|
|
1998
|
+
firstFrame,
|
|
1999
|
+
lastFrame,
|
|
2000
|
+
sourceVideo,
|
|
2001
|
+
referenceImages,
|
|
2002
|
+
referenceVideos,
|
|
2003
|
+
referenceAudios,
|
|
2004
|
+
resolution,
|
|
2005
|
+
generateAudio: generateAudio2,
|
|
2006
|
+
negativePrompt: _negativePrompt,
|
|
2007
|
+
cfgScale: _cfgScale,
|
|
2008
|
+
promptExpansion: _promptExpansion,
|
|
2009
|
+
mode: _mode
|
|
2010
|
+
} = req;
|
|
1973
2011
|
const seconds = duration ?? durationSeconds;
|
|
1974
2012
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
1975
2013
|
const options = { model, prompt };
|
|
1976
|
-
const
|
|
2014
|
+
const warnings = [];
|
|
2015
|
+
const ratio = sdkAspectRatio(aspectRatio) ?? (aspectRatio === "adaptive" ? "adaptive" : void 0);
|
|
1977
2016
|
if (ratio) options.aspectRatio = ratio;
|
|
2017
|
+
else if (aspectRatio !== void 0)
|
|
2018
|
+
pushIgnored(warnings, "aspectRatio", aspectRatio, model.modelId);
|
|
1978
2019
|
if (seconds !== void 0) options.duration = seconds;
|
|
1979
2020
|
if (seed !== void 0) options.seed = seed;
|
|
2021
|
+
if (generateAudio2 !== void 0) options.generateAudio = generateAudio2;
|
|
2022
|
+
const frames = [
|
|
2023
|
+
...firstFrame ? [{ image: sdkDataContent(firstFrame), frameType: "first_frame" }] : [],
|
|
2024
|
+
...lastFrame ? [{ image: sdkDataContent(lastFrame), frameType: "last_frame" }] : []
|
|
2025
|
+
];
|
|
2026
|
+
if (frames.length > 0) options.frameImages = frames;
|
|
2027
|
+
const references = [
|
|
2028
|
+
...(referenceImages ?? []).map(sdkDataContent),
|
|
2029
|
+
...(referenceVideos ?? []).map(sdkReference)
|
|
2030
|
+
];
|
|
2031
|
+
if (references.length > 0) {
|
|
2032
|
+
if (frames.length > 0) {
|
|
2033
|
+
warnings.push({
|
|
2034
|
+
code: "option_ignored",
|
|
2035
|
+
field: "inputReferences",
|
|
2036
|
+
from: references.length,
|
|
2037
|
+
message: `${model.modelId} provider instance ignores references when frames are set`
|
|
2038
|
+
});
|
|
2039
|
+
} else {
|
|
2040
|
+
options.inputReferences = references;
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
if (sourceVideo) pushIgnored(warnings, "sourceVideo", void 0, model.modelId);
|
|
2044
|
+
if (referenceAudios?.length)
|
|
2045
|
+
pushIgnored(warnings, "referenceAudios", referenceAudios.length, model.modelId);
|
|
2046
|
+
if (resolution !== void 0)
|
|
2047
|
+
pushIgnored(warnings, "resolution", resolution, model.modelId);
|
|
2048
|
+
if (_negativePrompt !== void 0)
|
|
2049
|
+
pushIgnored(warnings, "negativePrompt", void 0, model.modelId);
|
|
2050
|
+
if (_cfgScale !== void 0) pushIgnored(warnings, "cfgScale", _cfgScale, model.modelId);
|
|
2051
|
+
if (_promptExpansion !== void 0)
|
|
2052
|
+
pushIgnored(warnings, "promptExpansion", _promptExpansion, model.modelId);
|
|
2053
|
+
if (_mode !== void 0) pushIgnored(warnings, "mode", _mode, model.modelId);
|
|
1980
2054
|
if (providerOptions) options.providerOptions = providerOptions;
|
|
1981
2055
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
1982
2056
|
const pending = aiGenerateVideo(options);
|
|
@@ -2004,7 +2078,7 @@ function createModelKit(config, adapters) {
|
|
|
2004
2078
|
});
|
|
2005
2079
|
return {
|
|
2006
2080
|
jobId: `ai-sdk:${model.provider}:${model.modelId}`,
|
|
2007
|
-
warnings
|
|
2081
|
+
warnings,
|
|
2008
2082
|
async poll() {
|
|
2009
2083
|
if (settled) return { status: "succeeded", raw: settled.raw };
|
|
2010
2084
|
if (failed) return { status: "failed" };
|
|
@@ -2228,6 +2302,9 @@ var SUBMIT_PATH = "/contents/generations/tasks";
|
|
|
2228
2302
|
var SEEDANCE_POLL_INTERVAL_MS = 15e3;
|
|
2229
2303
|
var RESULT_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
2230
2304
|
var VIDEO_URL_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2305
|
+
function arkBaseUrl(ctx) {
|
|
2306
|
+
return ctx.endpoints?.ark ?? ARK_BASE_URL;
|
|
2307
|
+
}
|
|
2231
2308
|
var SEEDREAM_SIZES = {
|
|
2232
2309
|
"1K": {
|
|
2233
2310
|
"1:1": "1024x1024",
|
|
@@ -2238,7 +2315,8 @@ var SEEDREAM_SIZES = {
|
|
|
2238
2315
|
"3:2": "1248x832",
|
|
2239
2316
|
"2:3": "832x1248",
|
|
2240
2317
|
"21:9": "1568x672",
|
|
2241
|
-
"4:5": "864x1080"
|
|
2318
|
+
"4:5": "864x1080",
|
|
2319
|
+
"5:4": "1080x864"
|
|
2242
2320
|
},
|
|
2243
2321
|
"2K": {
|
|
2244
2322
|
"1:1": "2048x2048",
|
|
@@ -2249,7 +2327,8 @@ var SEEDREAM_SIZES = {
|
|
|
2249
2327
|
"3:2": "2496x1664",
|
|
2250
2328
|
"2:3": "1664x2496",
|
|
2251
2329
|
"21:9": "3136x1344",
|
|
2252
|
-
"4:5": "1728x2160"
|
|
2330
|
+
"4:5": "1728x2160",
|
|
2331
|
+
"5:4": "2160x1728"
|
|
2253
2332
|
}
|
|
2254
2333
|
};
|
|
2255
2334
|
var arkAdapter = {
|
|
@@ -2296,9 +2375,11 @@ function seedreamSize(aspect, size) {
|
|
|
2296
2375
|
const table = SEEDREAM_SIZES[tier];
|
|
2297
2376
|
return table[aspect ?? ""] ?? table["1:1"] ?? "2048x2048";
|
|
2298
2377
|
}
|
|
2299
|
-
function
|
|
2300
|
-
if (
|
|
2301
|
-
|
|
2378
|
+
function sniffedImageMime(bytes) {
|
|
2379
|
+
if (bytes.length >= 4 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71)
|
|
2380
|
+
return "image/png";
|
|
2381
|
+
if (bytes.length >= 12 && bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80)
|
|
2382
|
+
return "image/webp";
|
|
2302
2383
|
return "image/jpeg";
|
|
2303
2384
|
}
|
|
2304
2385
|
function arkUrl(ref) {
|
|
@@ -2340,7 +2421,7 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2340
2421
|
else if (refs.length > 1) body.image = refs;
|
|
2341
2422
|
const data = await withRetry(async () => {
|
|
2342
2423
|
const res = await ctx.fetch(
|
|
2343
|
-
`${
|
|
2424
|
+
`${arkBaseUrl(ctx)}/images/generations`,
|
|
2344
2425
|
fetchInitFor(ctx, {
|
|
2345
2426
|
method: "POST",
|
|
2346
2427
|
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
@@ -2379,7 +2460,7 @@ async function generateSeedreamImage(req, ctx) {
|
|
|
2379
2460
|
};
|
|
2380
2461
|
if (req.size !== void 0) usage2.imageSize = req.size;
|
|
2381
2462
|
if (req.quality !== void 0) usage2.imageQuality = req.quality;
|
|
2382
|
-
return { images: [{ bytes, mime:
|
|
2463
|
+
return { images: [{ bytes, mime: sniffedImageMime(bytes) }], usage: usage2, raw: data };
|
|
2383
2464
|
}
|
|
2384
2465
|
var SeedanceResponseSchema = z4.object({
|
|
2385
2466
|
id: z4.string().optional(),
|
|
@@ -2467,7 +2548,7 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2467
2548
|
if (req.seed !== void 0) body.seed = req.seed;
|
|
2468
2549
|
const submit = await withRetry(async () => {
|
|
2469
2550
|
const res = await ctx.fetch(
|
|
2470
|
-
`${
|
|
2551
|
+
`${arkBaseUrl(ctx)}${SUBMIT_PATH}`,
|
|
2471
2552
|
fetchInitFor(ctx, {
|
|
2472
2553
|
method: "POST",
|
|
2473
2554
|
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
@@ -2487,7 +2568,7 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
2487
2568
|
const usage2 = seedanceUsage(ctx, req, duration);
|
|
2488
2569
|
const fetchStatus = async () => {
|
|
2489
2570
|
const res = await ctx.fetch(
|
|
2490
|
-
`${
|
|
2571
|
+
`${arkBaseUrl(ctx)}${SUBMIT_PATH}/${jobId}`,
|
|
2491
2572
|
fetchInitFor(ctx, {
|
|
2492
2573
|
headers: { Authorization: `Bearer ${key}` }
|
|
2493
2574
|
})
|
|
@@ -3548,60 +3629,6 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3548
3629
|
uploadedNames.push(file.fileName);
|
|
3549
3630
|
return file.fileUri;
|
|
3550
3631
|
};
|
|
3551
|
-
const parts = [];
|
|
3552
|
-
if (req.sourceVideo) {
|
|
3553
|
-
const media = await resolveMedia(
|
|
3554
|
-
req.sourceVideo,
|
|
3555
|
-
ctx.fetch,
|
|
3556
|
-
ctx.signal,
|
|
3557
|
-
"video/mp4",
|
|
3558
|
-
modelId
|
|
3559
|
-
);
|
|
3560
|
-
parts.push({
|
|
3561
|
-
type: "video",
|
|
3562
|
-
uri: await uploadOne("video", media.bytes, media.mime),
|
|
3563
|
-
mime_type: media.mime
|
|
3564
|
-
});
|
|
3565
|
-
}
|
|
3566
|
-
for (const ref of videos) {
|
|
3567
|
-
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "video/mp4", modelId);
|
|
3568
|
-
parts.push({
|
|
3569
|
-
type: "video",
|
|
3570
|
-
uri: await uploadOne("video", media.bytes, media.mime),
|
|
3571
|
-
mime_type: media.mime
|
|
3572
|
-
});
|
|
3573
|
-
}
|
|
3574
|
-
if (req.firstFrame) {
|
|
3575
|
-
const media = await resolveMedia(
|
|
3576
|
-
req.firstFrame,
|
|
3577
|
-
ctx.fetch,
|
|
3578
|
-
ctx.signal,
|
|
3579
|
-
"image/png",
|
|
3580
|
-
modelId
|
|
3581
|
-
);
|
|
3582
|
-
if (media.bytes.length > OMNI_INLINE_LIMIT_BYTES) {
|
|
3583
|
-
parts.push({
|
|
3584
|
-
type: "image",
|
|
3585
|
-
uri: await uploadOne("image", media.bytes, media.mime),
|
|
3586
|
-
mime_type: media.mime
|
|
3587
|
-
});
|
|
3588
|
-
} else {
|
|
3589
|
-
parts.push({ type: "image", data: toBase64(media.bytes), mime_type: media.mime });
|
|
3590
|
-
}
|
|
3591
|
-
}
|
|
3592
|
-
for (const ref of images) {
|
|
3593
|
-
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "image/png", modelId);
|
|
3594
|
-
if (media.bytes.length > OMNI_INLINE_LIMIT_BYTES) {
|
|
3595
|
-
parts.push({
|
|
3596
|
-
type: "image",
|
|
3597
|
-
uri: await uploadOne("image", media.bytes, media.mime),
|
|
3598
|
-
mime_type: media.mime
|
|
3599
|
-
});
|
|
3600
|
-
} else {
|
|
3601
|
-
parts.push({ type: "image", data: toBase64(media.bytes), mime_type: media.mime });
|
|
3602
|
-
}
|
|
3603
|
-
}
|
|
3604
|
-
parts.push({ type: "text", text: req.prompt });
|
|
3605
3632
|
const cleanupUploads = async () => {
|
|
3606
3633
|
for (const fileName of uploadedNames) await deleteGoogleFile(fileName, apiKey, ctx.fetch);
|
|
3607
3634
|
};
|
|
@@ -3615,6 +3642,60 @@ async function generateOmniVideo(req, ctx, createGenAIClient) {
|
|
|
3615
3642
|
if (ctx.signal !== void 0) createRetryOptions.signal = ctx.signal;
|
|
3616
3643
|
let interaction;
|
|
3617
3644
|
try {
|
|
3645
|
+
const parts = [];
|
|
3646
|
+
if (req.sourceVideo) {
|
|
3647
|
+
const media = await resolveMedia(
|
|
3648
|
+
req.sourceVideo,
|
|
3649
|
+
ctx.fetch,
|
|
3650
|
+
ctx.signal,
|
|
3651
|
+
"video/mp4",
|
|
3652
|
+
modelId
|
|
3653
|
+
);
|
|
3654
|
+
parts.push({
|
|
3655
|
+
type: "video",
|
|
3656
|
+
uri: await uploadOne("video", media.bytes, media.mime),
|
|
3657
|
+
mime_type: media.mime
|
|
3658
|
+
});
|
|
3659
|
+
}
|
|
3660
|
+
for (const ref of videos) {
|
|
3661
|
+
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "video/mp4", modelId);
|
|
3662
|
+
parts.push({
|
|
3663
|
+
type: "video",
|
|
3664
|
+
uri: await uploadOne("video", media.bytes, media.mime),
|
|
3665
|
+
mime_type: media.mime
|
|
3666
|
+
});
|
|
3667
|
+
}
|
|
3668
|
+
if (req.firstFrame) {
|
|
3669
|
+
const media = await resolveMedia(
|
|
3670
|
+
req.firstFrame,
|
|
3671
|
+
ctx.fetch,
|
|
3672
|
+
ctx.signal,
|
|
3673
|
+
"image/png",
|
|
3674
|
+
modelId
|
|
3675
|
+
);
|
|
3676
|
+
if (media.bytes.length > OMNI_INLINE_LIMIT_BYTES) {
|
|
3677
|
+
parts.push({
|
|
3678
|
+
type: "image",
|
|
3679
|
+
uri: await uploadOne("image", media.bytes, media.mime),
|
|
3680
|
+
mime_type: media.mime
|
|
3681
|
+
});
|
|
3682
|
+
} else {
|
|
3683
|
+
parts.push({ type: "image", data: toBase64(media.bytes), mime_type: media.mime });
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
for (const ref of images) {
|
|
3687
|
+
const media = await resolveMedia(ref, ctx.fetch, ctx.signal, "image/png", modelId);
|
|
3688
|
+
if (media.bytes.length > OMNI_INLINE_LIMIT_BYTES) {
|
|
3689
|
+
parts.push({
|
|
3690
|
+
type: "image",
|
|
3691
|
+
uri: await uploadOne("image", media.bytes, media.mime),
|
|
3692
|
+
mime_type: media.mime
|
|
3693
|
+
});
|
|
3694
|
+
} else {
|
|
3695
|
+
parts.push({ type: "image", data: toBase64(media.bytes), mime_type: media.mime });
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
parts.push({ type: "text", text: req.prompt });
|
|
3618
3699
|
try {
|
|
3619
3700
|
interaction = await withRetry(async () => {
|
|
3620
3701
|
try {
|
|
@@ -3948,6 +4029,10 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
3948
4029
|
imageQuality: "auto"
|
|
3949
4030
|
};
|
|
3950
4031
|
if (req.size !== void 0) usage2.imageSize = req.size;
|
|
4032
|
+
if (result.usage?.inputTokens !== void 0)
|
|
4033
|
+
usage2.inputTokens = result.usage.inputTokens;
|
|
4034
|
+
if (result.usage?.outputTokens !== void 0)
|
|
4035
|
+
usage2.outputTokens = result.usage.outputTokens;
|
|
3951
4036
|
return { images, usage: usage2, raw: result };
|
|
3952
4037
|
}
|
|
3953
4038
|
};
|
|
@@ -4479,7 +4564,7 @@ function aspectRatioToSize(ratio, tier) {
|
|
|
4479
4564
|
};
|
|
4480
4565
|
const MIN_PIXELS = 655360;
|
|
4481
4566
|
const MAX_PIXELS = 8294400;
|
|
4482
|
-
const maxLong = TIER_LONG_EDGE[tier];
|
|
4567
|
+
const maxLong = TIER_LONG_EDGE[tier] ?? 1024;
|
|
4483
4568
|
const RATIO_MAP = /* @__PURE__ */ new Map([
|
|
4484
4569
|
["1:1", [1, 1]],
|
|
4485
4570
|
["16:9", [16, 9]],
|
|
@@ -4680,7 +4765,8 @@ var RATIO_TO_DIMS = {
|
|
|
4680
4765
|
"9:16": { width: 768, height: 1360 },
|
|
4681
4766
|
"3:4": { width: 768, height: 1024 },
|
|
4682
4767
|
"2:3": { width: 768, height: 1152 },
|
|
4683
|
-
"4:5": { width: 896, height: 1120 }
|
|
4768
|
+
"4:5": { width: 896, height: 1120 },
|
|
4769
|
+
"5:4": { width: 1120, height: 896 }
|
|
4684
4770
|
};
|
|
4685
4771
|
function dimsFor(aspectRatio) {
|
|
4686
4772
|
if (aspectRatio !== void 0) {
|
|
@@ -4689,6 +4775,27 @@ function dimsFor(aspectRatio) {
|
|
|
4689
4775
|
}
|
|
4690
4776
|
return { width: 1024, height: 1024 };
|
|
4691
4777
|
}
|
|
4778
|
+
var GEMINI_JOB_RATIOS = /* @__PURE__ */ new Set([
|
|
4779
|
+
"1:1",
|
|
4780
|
+
"2:3",
|
|
4781
|
+
"3:2",
|
|
4782
|
+
"3:4",
|
|
4783
|
+
"4:3",
|
|
4784
|
+
"4:5",
|
|
4785
|
+
"5:4",
|
|
4786
|
+
"9:16",
|
|
4787
|
+
"16:9",
|
|
4788
|
+
"21:9"
|
|
4789
|
+
]);
|
|
4790
|
+
var NANO_BANANA_RATIOS = /* @__PURE__ */ new Set([
|
|
4791
|
+
"1:1",
|
|
4792
|
+
"2:3",
|
|
4793
|
+
"3:4",
|
|
4794
|
+
"4:3",
|
|
4795
|
+
"9:16",
|
|
4796
|
+
"16:9",
|
|
4797
|
+
"21:9"
|
|
4798
|
+
]);
|
|
4692
4799
|
async function refToBytes(ctx, ref) {
|
|
4693
4800
|
if ("bytes" in ref) return { bytes: ref.bytes, mime: ref.mime };
|
|
4694
4801
|
const res = await ctx.fetch(ref.url);
|
|
@@ -4788,7 +4895,7 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4788
4895
|
inputs = refs.length > 0 && firstRef !== void 0 ? [firstRef] : [];
|
|
4789
4896
|
accept = req.outputFormat === "png" ? "image/png" : "image/jpeg";
|
|
4790
4897
|
mime = accept;
|
|
4791
|
-
} else if (providerModelId === "flux-2-pro" || providerModelId === FLUX_2_PRO_JOB
|
|
4898
|
+
} else if (providerModelId === "flux-2-pro" || providerModelId === FLUX_2_PRO_JOB) {
|
|
4792
4899
|
const dims = dimsFor(req.aspectRatio);
|
|
4793
4900
|
const config = {
|
|
4794
4901
|
prompt: req.prompt,
|
|
@@ -4797,8 +4904,30 @@ async function generateProdiaImage(req, ctx) {
|
|
|
4797
4904
|
safety_tolerance: 5
|
|
4798
4905
|
};
|
|
4799
4906
|
if (req.seed !== void 0) config.seed = req.seed;
|
|
4800
|
-
|
|
4801
|
-
|
|
4907
|
+
job = { type: FLUX_2_PRO_JOB, config };
|
|
4908
|
+
inputs = refs;
|
|
4909
|
+
accept = "image/png";
|
|
4910
|
+
mime = "image/png";
|
|
4911
|
+
} else if (providerModelId === "inference.gemini-3-pro.img2img.v1" || providerModelId === "inference.nano-banana.img2img.v2") {
|
|
4912
|
+
const allowed = providerModelId === "inference.nano-banana.img2img.v2" ? NANO_BANANA_RATIOS : GEMINI_JOB_RATIOS;
|
|
4913
|
+
const config = {
|
|
4914
|
+
prompt: req.prompt,
|
|
4915
|
+
safety_tolerance: 5
|
|
4916
|
+
};
|
|
4917
|
+
if (req.aspectRatio !== void 0 && req.aspectRatio !== "adaptive") {
|
|
4918
|
+
if (allowed.has(req.aspectRatio)) config.aspect_ratio = req.aspectRatio;
|
|
4919
|
+
else
|
|
4920
|
+
ctx.warnings.push({
|
|
4921
|
+
code: "option_ignored",
|
|
4922
|
+
field: "aspectRatio",
|
|
4923
|
+
from: req.aspectRatio,
|
|
4924
|
+
message: `${providerModelId} has no ${req.aspectRatio} aspect_ratio; using the provider default`
|
|
4925
|
+
});
|
|
4926
|
+
}
|
|
4927
|
+
if (providerModelId === "inference.gemini-3-pro.img2img.v1")
|
|
4928
|
+
config.resolution = req.size ?? "1K";
|
|
4929
|
+
if (req.seed !== void 0) config.seed = req.seed;
|
|
4930
|
+
job = { type: providerModelId, config };
|
|
4802
4931
|
inputs = refs;
|
|
4803
4932
|
accept = "image/png";
|
|
4804
4933
|
mime = "image/png";
|
|
@@ -5069,13 +5198,88 @@ function isUpscaler(providerModelId) {
|
|
|
5069
5198
|
const id = isLower(providerModelId);
|
|
5070
5199
|
return id.includes("upscal") || id.includes("crystal") || id.includes("topaz");
|
|
5071
5200
|
}
|
|
5201
|
+
function isTopazUpscaler(providerModelId) {
|
|
5202
|
+
return isLower(providerModelId).includes("topazlabs/image-upscale");
|
|
5203
|
+
}
|
|
5072
5204
|
function isQwen(providerModelId) {
|
|
5073
5205
|
return isLower(providerModelId).includes("qwen");
|
|
5074
5206
|
}
|
|
5207
|
+
function isWanImage(providerModelId) {
|
|
5208
|
+
return isLower(providerModelId).includes("wan-2.7");
|
|
5209
|
+
}
|
|
5210
|
+
function isQwenEditPlus(providerModelId) {
|
|
5211
|
+
return isLower(providerModelId).includes("edit");
|
|
5212
|
+
}
|
|
5213
|
+
var QWEN_IMAGE_RATIOS = /* @__PURE__ */ new Set([
|
|
5214
|
+
"1:1",
|
|
5215
|
+
"16:9",
|
|
5216
|
+
"9:16",
|
|
5217
|
+
"4:3",
|
|
5218
|
+
"3:4",
|
|
5219
|
+
"3:2",
|
|
5220
|
+
"2:3"
|
|
5221
|
+
]);
|
|
5222
|
+
var QWEN_EDIT_RATIOS = /* @__PURE__ */ new Set(["1:1", "16:9", "9:16", "4:3", "3:4"]);
|
|
5223
|
+
var WAN_IMAGE_SIZES = {
|
|
5224
|
+
"1K": {
|
|
5225
|
+
"1:1": "1024*1024",
|
|
5226
|
+
"16:9": "1280*720",
|
|
5227
|
+
"9:16": "720*1280",
|
|
5228
|
+
"4:3": "1024*768",
|
|
5229
|
+
"3:4": "768*1024"
|
|
5230
|
+
},
|
|
5231
|
+
"2K": {
|
|
5232
|
+
"1:1": "2048*2048",
|
|
5233
|
+
"16:9": "2048*1152",
|
|
5234
|
+
"9:16": "1152*2048",
|
|
5235
|
+
"4:3": "2048*1536",
|
|
5236
|
+
"3:4": "1536*2048"
|
|
5237
|
+
},
|
|
5238
|
+
"4K": {
|
|
5239
|
+
"1:1": "4096*4096",
|
|
5240
|
+
"16:9": "4096*2304",
|
|
5241
|
+
"9:16": "2304*4096",
|
|
5242
|
+
"4:3": "4096*3072",
|
|
5243
|
+
"3:4": "3072*4096"
|
|
5244
|
+
}
|
|
5245
|
+
};
|
|
5246
|
+
function wanImageSize(aspectRatio, size) {
|
|
5247
|
+
const tier = size === "2K" || size === "4K" ? size : "1K";
|
|
5248
|
+
const table = WAN_IMAGE_SIZES[tier];
|
|
5249
|
+
return table[aspectRatio ?? ""] ?? table["1:1"] ?? "1024*1024";
|
|
5250
|
+
}
|
|
5075
5251
|
async function generateReplicateImage(req, ctx, deps) {
|
|
5076
5252
|
const id = ctx.model.providerModelId;
|
|
5077
|
-
|
|
5078
|
-
if (
|
|
5253
|
+
let input;
|
|
5254
|
+
if (isTopazUpscaler(id)) {
|
|
5255
|
+
const first = (req.references ?? [])[0];
|
|
5256
|
+
if (!first) {
|
|
5257
|
+
throw new ModelKitError({
|
|
5258
|
+
code: "missing_input",
|
|
5259
|
+
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5260
|
+
provider: "replicate",
|
|
5261
|
+
model: ctx.model.id,
|
|
5262
|
+
retryable: false
|
|
5263
|
+
});
|
|
5264
|
+
}
|
|
5265
|
+
let format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat ?? "png";
|
|
5266
|
+
if (format !== "png" && format !== "jpg") {
|
|
5267
|
+
ctx.warnings.push({
|
|
5268
|
+
code: "option_ignored",
|
|
5269
|
+
field: "outputFormat",
|
|
5270
|
+
from: format,
|
|
5271
|
+
message: "topazlabs/image-upscale supports only png and jpg; using png"
|
|
5272
|
+
});
|
|
5273
|
+
format = "png";
|
|
5274
|
+
}
|
|
5275
|
+
input = {
|
|
5276
|
+
image: refToUrl3(first),
|
|
5277
|
+
enhance_model: "Standard V2",
|
|
5278
|
+
output_format: format,
|
|
5279
|
+
upscale_factor: `${req.scaleFactor ?? 2}x`,
|
|
5280
|
+
face_enhancement: true
|
|
5281
|
+
};
|
|
5282
|
+
} else if (isUpscaler(id)) {
|
|
5079
5283
|
const refs = req.references ?? [];
|
|
5080
5284
|
const first = refs[0];
|
|
5081
5285
|
if (!first) {
|
|
@@ -5087,28 +5291,53 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
5087
5291
|
retryable: false
|
|
5088
5292
|
});
|
|
5089
5293
|
}
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5294
|
+
const imageInput = { prompt: req.prompt };
|
|
5295
|
+
imageInput.image = refToUrl3(first);
|
|
5296
|
+
imageInput.creativity = 0;
|
|
5297
|
+
imageInput.scale_factor = 2;
|
|
5298
|
+
imageInput.output_format = "png";
|
|
5299
|
+
input = imageInput;
|
|
5300
|
+
} else if (isWanImage(id)) {
|
|
5301
|
+
const refs = (req.references ?? []).map(refToUrl3);
|
|
5302
|
+
const imageInput = { prompt: req.prompt };
|
|
5303
|
+
if (refs.length > 0) imageInput.images = refs;
|
|
5304
|
+
imageInput.size = wanImageSize(req.aspectRatio, req.size);
|
|
5305
|
+
input = imageInput;
|
|
5094
5306
|
} else if (isQwen(id)) {
|
|
5095
5307
|
const refs = (req.references ?? []).map(refToUrl3);
|
|
5096
5308
|
const firstUrl = refs[0];
|
|
5309
|
+
const imageInput = { prompt: req.prompt };
|
|
5097
5310
|
if (firstUrl !== void 0) {
|
|
5098
|
-
|
|
5099
|
-
|
|
5311
|
+
imageInput.image = firstUrl;
|
|
5312
|
+
if (!isQwenEditPlus(id)) imageInput.match_input_image = true;
|
|
5313
|
+
}
|
|
5314
|
+
const ratios = isQwenEditPlus(id) ? QWEN_EDIT_RATIOS : QWEN_IMAGE_RATIOS;
|
|
5315
|
+
if (req.aspectRatio !== void 0) {
|
|
5316
|
+
if (ratios.has(req.aspectRatio)) imageInput.aspect_ratio = req.aspectRatio;
|
|
5317
|
+
else
|
|
5318
|
+
ctx.warnings.push({
|
|
5319
|
+
code: "option_ignored",
|
|
5320
|
+
field: "aspectRatio",
|
|
5321
|
+
from: req.aspectRatio,
|
|
5322
|
+
message: `${id} has no ${req.aspectRatio} aspect_ratio; using the provider default`
|
|
5323
|
+
});
|
|
5324
|
+
}
|
|
5325
|
+
if (isQwenEditPlus(id) && req.outputFormat !== void 0) {
|
|
5326
|
+
imageInput.output_format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat;
|
|
5100
5327
|
}
|
|
5101
|
-
|
|
5328
|
+
input = imageInput;
|
|
5102
5329
|
} else {
|
|
5103
5330
|
const refs = req.references ?? [];
|
|
5104
5331
|
const first = refs[0];
|
|
5105
|
-
|
|
5332
|
+
const imageInput = { prompt: req.prompt };
|
|
5333
|
+
if (first) imageInput.image = refToUrl3(first);
|
|
5334
|
+
input = imageInput;
|
|
5106
5335
|
}
|
|
5107
5336
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5108
5337
|
const file = await download(ctx, url);
|
|
5109
5338
|
const usage2 = imageUsage2(ctx, req);
|
|
5110
5339
|
usage2.quantity = predictTime;
|
|
5111
|
-
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage2, raw };
|
|
5340
|
+
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage2, raw, outputUrl: url };
|
|
5112
5341
|
}
|
|
5113
5342
|
function wanSize(aspectRatio) {
|
|
5114
5343
|
if (!aspectRatio || aspectRatio === "adaptive" || aspectRatio === "1:1") return "2K";
|