@shop-os/modelkit 0.2.26 → 0.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/CHANGELOG.md +24 -0
- package/README.md +20 -1
- package/dist/catalog.cjs +288 -14
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +158 -2
- package/dist/catalog.d.ts +158 -2
- package/dist/catalog.js +288 -14
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +688 -143
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +194 -2
- package/dist/index.d.ts +194 -2
- package/dist/index.js +683 -143
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1304,6 +1304,11 @@ var NEGATIVE_PROMPT = "blur, distort, and low quality";
|
|
|
1304
1304
|
var FRAMES_EXCLUDE_REFERENCES = { framesExcludeReferences: true };
|
|
1305
1305
|
var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
|
|
1306
1306
|
var SEEDANCE_PROMPT = { referenceSyntax: "numbered", maxChars: 3e4 };
|
|
1307
|
+
var SEEDANCE_2_AUDIO = {
|
|
1308
|
+
audioSeconds: { min: 2, max: 15, total: 15 },
|
|
1309
|
+
audioFormats: ["wav", "mp3"],
|
|
1310
|
+
audioMaxBytes: 15 * 1024 * 1024
|
|
1311
|
+
};
|
|
1307
1312
|
var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
|
|
1308
1313
|
var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
|
|
1309
1314
|
var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
|
|
@@ -1440,7 +1445,7 @@ var VIDEO_MODELS = [
|
|
|
1440
1445
|
description: "Google's conversational video model with native audio, human support, and natural language editing. Aspect ratio only \u2014 resolution and duration are model-determined.",
|
|
1441
1446
|
logo: GOOGLE_LOGO2
|
|
1442
1447
|
},
|
|
1443
|
-
capabilities: { acceptsSourceVideo: true }
|
|
1448
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: true }
|
|
1444
1449
|
},
|
|
1445
1450
|
{
|
|
1446
1451
|
id: "gemini-omni-1.1-flash",
|
|
@@ -1465,7 +1470,7 @@ var VIDEO_MODELS = [
|
|
|
1465
1470
|
// with a video task, so those calls carry the prompt alone).
|
|
1466
1471
|
// First-to-last-frame interpolation: `<LAST_FRAME>` goes with `<FIRST_FRAME>`.
|
|
1467
1472
|
supports: ["videoExtension", "lastFrame"],
|
|
1468
|
-
extension: { segmentSeconds: 10, maxTotalSeconds: 40 },
|
|
1473
|
+
extension: { segmentSeconds: 10, maxTotalSeconds: 40, returns: "joined" },
|
|
1469
1474
|
prompt: OMNI_PROMPT,
|
|
1470
1475
|
audio: "always"
|
|
1471
1476
|
},
|
|
@@ -1477,7 +1482,11 @@ var VIDEO_MODELS = [
|
|
|
1477
1482
|
logo: GOOGLE_LOGO2,
|
|
1478
1483
|
description: "Google Gemini Omni Flash 1.1 conversational video generation, editing and extension; text, image, and up to 10-second video input, 3-10 second output at up to 4K and 24 FPS, extendable to 40 seconds."
|
|
1479
1484
|
},
|
|
1480
|
-
capabilities: {
|
|
1485
|
+
capabilities: {
|
|
1486
|
+
acceptsSourceVideo: true,
|
|
1487
|
+
videoEdit: true,
|
|
1488
|
+
lastFrameRequiresFirstFrame: true
|
|
1489
|
+
}
|
|
1481
1490
|
},
|
|
1482
1491
|
{
|
|
1483
1492
|
// vibe-triggers and Space Builder drop the ratio when a frame is wired; Cowork always sends it.
|
|
@@ -1499,7 +1508,8 @@ var VIDEO_MODELS = [
|
|
|
1499
1508
|
videos: 3,
|
|
1500
1509
|
audios: 3,
|
|
1501
1510
|
audioOnly: false,
|
|
1502
|
-
videoSeconds: { min: 2, max: 15, total: 15 }
|
|
1511
|
+
videoSeconds: { min: 2, max: 15, total: 15 },
|
|
1512
|
+
...SEEDANCE_2_AUDIO
|
|
1503
1513
|
},
|
|
1504
1514
|
sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
|
|
1505
1515
|
ratioIgnoredWith: ["firstFrame", "sourceVideo"],
|
|
@@ -1521,7 +1531,7 @@ var VIDEO_MODELS = [
|
|
|
1521
1531
|
description: "High-quality AI video generation with reference image conditioning. Supports 4-15 second clips with human preprocessing.",
|
|
1522
1532
|
logo: BYTEDANCE_LOGO
|
|
1523
1533
|
},
|
|
1524
|
-
capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
|
|
1534
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: false, ...FRAMES_EXCLUDE_REFERENCES }
|
|
1525
1535
|
},
|
|
1526
1536
|
{
|
|
1527
1537
|
id: "seedance-2.0-fast",
|
|
@@ -1541,7 +1551,8 @@ var VIDEO_MODELS = [
|
|
|
1541
1551
|
videos: 3,
|
|
1542
1552
|
audios: 3,
|
|
1543
1553
|
audioOnly: false,
|
|
1544
|
-
videoSeconds: { min: 2, max: 15, total: 15 }
|
|
1554
|
+
videoSeconds: { min: 2, max: 15, total: 15 },
|
|
1555
|
+
...SEEDANCE_2_AUDIO
|
|
1545
1556
|
},
|
|
1546
1557
|
sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
|
|
1547
1558
|
ratioIgnoredWith: ["firstFrame", "sourceVideo"],
|
|
@@ -1563,7 +1574,7 @@ var VIDEO_MODELS = [
|
|
|
1563
1574
|
logo: BYTEDANCE_LOGO,
|
|
1564
1575
|
description: "Speed- and cost-optimized ByteDance Seedance 2.0 Fast; text plus image, video, and audio references to generate or edit 4-15 second clips."
|
|
1565
1576
|
},
|
|
1566
|
-
capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
|
|
1577
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: false, ...FRAMES_EXCLUDE_REFERENCES }
|
|
1567
1578
|
},
|
|
1568
1579
|
{
|
|
1569
1580
|
// omni_reference_task_type edit/extend: adaptive ratio, edit sends duration -1.
|
|
@@ -1583,12 +1594,20 @@ var VIDEO_MODELS = [
|
|
|
1583
1594
|
images: 30,
|
|
1584
1595
|
videos: 10,
|
|
1585
1596
|
audios: 10,
|
|
1586
|
-
videoSeconds: { min: 2, max: 30, total: 30, editMin: 4 }
|
|
1597
|
+
videoSeconds: { min: 2, max: 30, total: 30, editMin: 4 },
|
|
1598
|
+
// BytePlus: 2-30 s per clip, 30 s in all, wav/mp3, 15 MB each.
|
|
1599
|
+
audioSeconds: { min: 2, max: 30, total: 30 },
|
|
1600
|
+
audioFormats: ["wav", "mp3"],
|
|
1601
|
+
audioMaxBytes: 15 * 1024 * 1024
|
|
1587
1602
|
},
|
|
1588
1603
|
sourceVideoSeconds: { min: 2, max: 30, editMin: 4, inReferenceTotal: true },
|
|
1589
1604
|
ratioIgnoredWith: ["firstFrame", "sourceVideo"],
|
|
1590
1605
|
// No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
|
|
1591
|
-
supports: ["generateAudio", "lastFrame", "watermark", "taskType"],
|
|
1606
|
+
supports: ["generateAudio", "lastFrame", "watermark", "taskType", "videoExtension"],
|
|
1607
|
+
// Extend (probe 2026-10-02, 480p): returns ONLY the added footage, continuing from
|
|
1608
|
+
// the source's last frame at the source's framing and fps but at the requested
|
|
1609
|
+
// resolution, so the caller joins the clips. Forward only in practice.
|
|
1610
|
+
extension: { segmentSeconds: 30, maxTotalSeconds: 60, returns: "new" },
|
|
1592
1611
|
prompt: SEEDANCE_PROMPT,
|
|
1593
1612
|
audio: "optional"
|
|
1594
1613
|
},
|
|
@@ -1605,7 +1624,7 @@ var VIDEO_MODELS = [
|
|
|
1605
1624
|
logo: BYTEDANCE_LOGO,
|
|
1606
1625
|
description: "ByteDance Seedance 2.5 for long-form storytelling and omni-reference generation/editing; up to 50 reference assets and 4-30 second clips at up to 1080p."
|
|
1607
1626
|
},
|
|
1608
|
-
capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
|
|
1627
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: true, ...FRAMES_EXCLUDE_REFERENCES }
|
|
1609
1628
|
},
|
|
1610
1629
|
{
|
|
1611
1630
|
id: "grok-imagine",
|
|
@@ -1969,11 +1988,116 @@ var VIDEO_MODELS = [
|
|
|
1969
1988
|
}
|
|
1970
1989
|
];
|
|
1971
1990
|
|
|
1991
|
+
// src/catalog/video-tools.ts
|
|
1992
|
+
var TOPAZ_LOGO = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/topazlabs.png";
|
|
1993
|
+
var TOPAZ_SOURCE_SECONDS = { max: 300 };
|
|
1994
|
+
var TOPAZ_USAGE = { unit: "seconds" };
|
|
1995
|
+
var VIDEO_TOOL_MODELS = [
|
|
1996
|
+
{
|
|
1997
|
+
id: "topaz-precision",
|
|
1998
|
+
aliases: [],
|
|
1999
|
+
label: "Topaz Precision",
|
|
2000
|
+
type: "video-tool",
|
|
2001
|
+
adapter: "fal",
|
|
2002
|
+
providerModelId: "topaz/upscale/video/precision",
|
|
2003
|
+
lifecycle: "active",
|
|
2004
|
+
exposure: ["cowork"],
|
|
2005
|
+
constraints: {
|
|
2006
|
+
supports: [],
|
|
2007
|
+
sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
|
|
2008
|
+
tool: { kind: "upscale", upscaleFactor: { min: 1, max: 4 }, maxOutputLongEdge: 3840 }
|
|
2009
|
+
},
|
|
2010
|
+
defaults: {},
|
|
2011
|
+
providerOptions: { fal: { model: "Proteus" } },
|
|
2012
|
+
usage: TOPAZ_USAGE,
|
|
2013
|
+
pricingKind: "video_per_second",
|
|
2014
|
+
display: {
|
|
2015
|
+
provider: "topaz",
|
|
2016
|
+
logo: TOPAZ_LOGO,
|
|
2017
|
+
description: "Topaz Proteus upscaling: sharper, cleaner footage up to 4K while staying faithful to the source.",
|
|
2018
|
+
sortOrder: 20
|
|
2019
|
+
}
|
|
2020
|
+
},
|
|
2021
|
+
{
|
|
2022
|
+
id: "topaz-starlight",
|
|
2023
|
+
aliases: [],
|
|
2024
|
+
label: "Topaz Starlight",
|
|
2025
|
+
type: "video-tool",
|
|
2026
|
+
adapter: "fal",
|
|
2027
|
+
providerModelId: "topaz/upscale/video/generative",
|
|
2028
|
+
lifecycle: "active",
|
|
2029
|
+
exposure: ["cowork"],
|
|
2030
|
+
constraints: {
|
|
2031
|
+
supports: [],
|
|
2032
|
+
sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
|
|
2033
|
+
tool: { kind: "upscale", upscaleFactor: { min: 1, max: 4 }, maxOutputLongEdge: 3840 }
|
|
2034
|
+
},
|
|
2035
|
+
defaults: {},
|
|
2036
|
+
providerOptions: { fal: { model: "Starlight Precise 2.6" } },
|
|
2037
|
+
usage: TOPAZ_USAGE,
|
|
2038
|
+
pricingKind: "video_per_second",
|
|
2039
|
+
display: {
|
|
2040
|
+
provider: "topaz",
|
|
2041
|
+
logo: TOPAZ_LOGO,
|
|
2042
|
+
description: "Topaz Starlight Precise 2.6: generative upscaling that rebuilds fine detail, up to 4K. Slower and costlier than Precision.",
|
|
2043
|
+
sortOrder: 10
|
|
2044
|
+
}
|
|
2045
|
+
},
|
|
2046
|
+
{
|
|
2047
|
+
id: "topaz-apollo",
|
|
2048
|
+
aliases: [],
|
|
2049
|
+
label: "Topaz Apollo",
|
|
2050
|
+
type: "video-tool",
|
|
2051
|
+
adapter: "fal",
|
|
2052
|
+
providerModelId: "topaz/interpolate/video",
|
|
2053
|
+
lifecycle: "active",
|
|
2054
|
+
exposure: ["cowork"],
|
|
2055
|
+
constraints: {
|
|
2056
|
+
supports: [],
|
|
2057
|
+
sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
|
|
2058
|
+
tool: { kind: "interpolate", fps: { min: 16, max: 120 } }
|
|
2059
|
+
},
|
|
2060
|
+
defaults: {},
|
|
2061
|
+
providerOptions: { fal: { model: "Apollo" } },
|
|
2062
|
+
usage: TOPAZ_USAGE,
|
|
2063
|
+
pricingKind: "video_per_second",
|
|
2064
|
+
display: {
|
|
2065
|
+
provider: "topaz",
|
|
2066
|
+
logo: TOPAZ_LOGO,
|
|
2067
|
+
description: "Topaz Apollo frame interpolation: smoother motion at up to 120 fps, same length as the source."
|
|
2068
|
+
}
|
|
2069
|
+
},
|
|
2070
|
+
{
|
|
2071
|
+
id: "topaz-hyperion-2.5",
|
|
2072
|
+
aliases: [],
|
|
2073
|
+
label: "Topaz Hyperion 2.5",
|
|
2074
|
+
type: "video-tool",
|
|
2075
|
+
adapter: "fal",
|
|
2076
|
+
providerModelId: "topaz/sdr-to-hdr/video",
|
|
2077
|
+
lifecycle: "active",
|
|
2078
|
+
exposure: ["cowork"],
|
|
2079
|
+
constraints: {
|
|
2080
|
+
supports: [],
|
|
2081
|
+
sourceVideoSeconds: TOPAZ_SOURCE_SECONDS,
|
|
2082
|
+
tool: { kind: "hdr", outputFormats: ["h265", "prores"] }
|
|
2083
|
+
},
|
|
2084
|
+
defaults: {},
|
|
2085
|
+
usage: TOPAZ_USAGE,
|
|
2086
|
+
pricingKind: "video_per_second",
|
|
2087
|
+
display: {
|
|
2088
|
+
provider: "topaz",
|
|
2089
|
+
logo: TOPAZ_LOGO,
|
|
2090
|
+
description: "Topaz Hyperion 2.5 SDR to HDR: a 10-bit HDR master in H.265 (HDR10) or ProRes 422 HQ, at the source's size and frame rate."
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
];
|
|
2094
|
+
|
|
1972
2095
|
// src/catalog/models.ts
|
|
1973
2096
|
var MODELS = [
|
|
1974
2097
|
...TEXT_MODELS,
|
|
1975
2098
|
...IMAGE_MODELS,
|
|
1976
2099
|
...VIDEO_MODELS,
|
|
2100
|
+
...VIDEO_TOOL_MODELS,
|
|
1977
2101
|
...OTHER_MODELS
|
|
1978
2102
|
];
|
|
1979
2103
|
|
|
@@ -2270,7 +2394,15 @@ var ADAPTER_IDS = [
|
|
|
2270
2394
|
"higgsfield",
|
|
2271
2395
|
"xai-video"
|
|
2272
2396
|
];
|
|
2273
|
-
var ModelTypeSchema = z3.enum([
|
|
2397
|
+
var ModelTypeSchema = z3.enum([
|
|
2398
|
+
"text",
|
|
2399
|
+
"image",
|
|
2400
|
+
"video",
|
|
2401
|
+
"audio",
|
|
2402
|
+
"upscale",
|
|
2403
|
+
"bg-remove",
|
|
2404
|
+
"video-tool"
|
|
2405
|
+
]);
|
|
2274
2406
|
var LifecycleSchema = z3.enum(["active", "deprecated", "retired"]);
|
|
2275
2407
|
var SurfaceSchema = z3.enum(["cowork", "space_builder"]);
|
|
2276
2408
|
var SURFACES2 = SurfaceSchema.options;
|
|
@@ -2350,7 +2482,22 @@ var ReferenceLimitsSchema = z3.looseObject({
|
|
|
2350
2482
|
audios: z3.number().optional(),
|
|
2351
2483
|
total: z3.number().optional(),
|
|
2352
2484
|
audioOnly: z3.boolean().optional(),
|
|
2353
|
-
videoSeconds: VideoSecondsLimitsSchema.optional()
|
|
2485
|
+
videoSeconds: VideoSecondsLimitsSchema.optional(),
|
|
2486
|
+
audioSeconds: z3.looseObject({
|
|
2487
|
+
min: z3.number().optional(),
|
|
2488
|
+
max: z3.number().optional(),
|
|
2489
|
+
total: z3.number().optional()
|
|
2490
|
+
}).optional(),
|
|
2491
|
+
audioFormats: z3.array(z3.string()).optional(),
|
|
2492
|
+
audioMaxBytes: z3.number().positive().optional()
|
|
2493
|
+
});
|
|
2494
|
+
var RangeSchema = z3.looseObject({ min: z3.number(), max: z3.number() });
|
|
2495
|
+
var VideoToolConstraintsSchema = z3.looseObject({
|
|
2496
|
+
kind: z3.enum(["upscale", "interpolate", "hdr"]),
|
|
2497
|
+
upscaleFactor: RangeSchema.optional(),
|
|
2498
|
+
maxOutputLongEdge: z3.number().positive().optional(),
|
|
2499
|
+
fps: RangeSchema.optional(),
|
|
2500
|
+
outputFormats: z3.array(z3.enum(["h265", "prores"])).min(1).optional()
|
|
2354
2501
|
});
|
|
2355
2502
|
var ModelConstraintsSchema = z3.looseObject({
|
|
2356
2503
|
aspectRatios: z3.array(AspectRatioSchema).optional(),
|
|
@@ -2365,7 +2512,14 @@ var ModelConstraintsSchema = z3.looseObject({
|
|
|
2365
2512
|
supports: z3.array(SupportedOptionSchema).optional(),
|
|
2366
2513
|
ratioIgnoredWith: z3.array(z3.enum(["firstFrame", "sourceVideo"])).optional(),
|
|
2367
2514
|
sourceVideoSeconds: VideoSecondsLimitsSchema.omit({ total: true }).extend({ inReferenceTotal: z3.boolean().optional() }).optional(),
|
|
2368
|
-
|
|
2515
|
+
// segmentSeconds/maxTotalSeconds stay required: a kit before 0.3.0 drops a row whose
|
|
2516
|
+
// extension lacks them, so every extension block keeps them.
|
|
2517
|
+
extension: z3.looseObject({
|
|
2518
|
+
segmentSeconds: z3.number(),
|
|
2519
|
+
maxTotalSeconds: z3.number(),
|
|
2520
|
+
returns: z3.enum(["new", "joined"]).optional()
|
|
2521
|
+
}).optional(),
|
|
2522
|
+
tool: VideoToolConstraintsSchema.optional(),
|
|
2369
2523
|
// Loose on purpose: the read path keeps a row whose value is invalid (the accessors in
|
|
2370
2524
|
// conventions.ts read it as "not set"); CatalogModelSchema below rejects it on write.
|
|
2371
2525
|
audio: z3.unknown().optional(),
|
|
@@ -2437,6 +2591,7 @@ var CatalogDisplaySchema = z3.looseObject({
|
|
|
2437
2591
|
});
|
|
2438
2592
|
var CatalogCapabilitiesSchema = z3.looseObject({
|
|
2439
2593
|
acceptsSourceVideo: z3.boolean().optional(),
|
|
2594
|
+
videoEdit: z3.boolean().optional(),
|
|
2440
2595
|
framesExcludeReferences: z3.boolean().optional(),
|
|
2441
2596
|
lastFrameRequiresFirstFrame: z3.boolean().optional(),
|
|
2442
2597
|
reasoning: z3.boolean().optional(),
|
|
@@ -2479,6 +2634,13 @@ var CatalogModelSchemaBase = z3.looseObject({
|
|
|
2479
2634
|
message: "active text rows need contextWindow"
|
|
2480
2635
|
});
|
|
2481
2636
|
}
|
|
2637
|
+
if (row.type === "video-tool" && row.constraints.tool === void 0) {
|
|
2638
|
+
ctx.addIssue({
|
|
2639
|
+
code: "custom",
|
|
2640
|
+
path: ["constraints", "tool"],
|
|
2641
|
+
message: "video-tool rows need constraints.tool"
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2482
2644
|
if (row.replacedBy !== void 0 && row.replacedBy === row.id) {
|
|
2483
2645
|
ctx.addIssue({
|
|
2484
2646
|
code: "custom",
|
|
@@ -3485,7 +3647,7 @@ async function generateSeedanceVideo(req, ctx) {
|
|
|
3485
3647
|
}
|
|
3486
3648
|
|
|
3487
3649
|
// src/adapters/fal.ts
|
|
3488
|
-
import { z as
|
|
3650
|
+
import { z as z12 } from "zod";
|
|
3489
3651
|
import { createFalClient } from "@fal-ai/client";
|
|
3490
3652
|
|
|
3491
3653
|
// src/adapters/fal-http.ts
|
|
@@ -3573,6 +3735,364 @@ function createFalHttpClient(opts) {
|
|
|
3573
3735
|
};
|
|
3574
3736
|
}
|
|
3575
3737
|
|
|
3738
|
+
// src/adapters/fal-gateway.ts
|
|
3739
|
+
import { z as z9 } from "zod";
|
|
3740
|
+
var falDetailSchema = z9.object({ detail: JsonValueSchema });
|
|
3741
|
+
function liftDetail(body) {
|
|
3742
|
+
const parsed = falDetailSchema.safeParse(body);
|
|
3743
|
+
const detail = parsed.success ? parsed.data.detail : void 0;
|
|
3744
|
+
return detail ?? body;
|
|
3745
|
+
}
|
|
3746
|
+
function falError(status, body, model) {
|
|
3747
|
+
return classifyHttpError(status, liftDetail(body), "fal", model);
|
|
3748
|
+
}
|
|
3749
|
+
function gatewayConfig(ctx) {
|
|
3750
|
+
const cf = ctx.routing.cloudflare;
|
|
3751
|
+
const falKey = ctx.keys.fal;
|
|
3752
|
+
const cfToken = ctx.keys.cloudflare;
|
|
3753
|
+
if (!cf?.accountId || !cf?.gatewayId || !falKey && !cfToken) {
|
|
3754
|
+
throw new ModelKitError({
|
|
3755
|
+
code: "auth",
|
|
3756
|
+
message: "fal passthrough is not configured. Set routing.cloudflare and FAL_KEY or the gateway token (BYOK).",
|
|
3757
|
+
provider: "fal",
|
|
3758
|
+
model: ctx.model.id,
|
|
3759
|
+
retryable: false
|
|
3760
|
+
});
|
|
3761
|
+
}
|
|
3762
|
+
const config = {
|
|
3763
|
+
baseUrl: `https://gateway.ai.cloudflare.com/v1/${cf.accountId}/${cf.gatewayId}/fal`
|
|
3764
|
+
};
|
|
3765
|
+
if (falKey) config.falKey = falKey;
|
|
3766
|
+
if (cfToken) config.cfToken = cfToken;
|
|
3767
|
+
if (ctx.call.maxRetries !== void 0) config.singleAttempt = true;
|
|
3768
|
+
if (ctx.signal !== void 0) config.signal = ctx.signal;
|
|
3769
|
+
return config;
|
|
3770
|
+
}
|
|
3771
|
+
async function gatewayFetch(cfg, fetchImpl, targetUrl, init) {
|
|
3772
|
+
const headers2 = { "x-fal-target-url": targetUrl };
|
|
3773
|
+
if (cfg.falKey) headers2.Authorization = `Bearer ${cfg.falKey}`;
|
|
3774
|
+
if (init.body) headers2["Content-Type"] = "application/json";
|
|
3775
|
+
if (cfg.cfToken) headers2["cf-aig-authorization"] = `Bearer ${cfg.cfToken}`;
|
|
3776
|
+
if (cfg.singleAttempt) headers2["cf-aig-max-attempts"] = "1";
|
|
3777
|
+
const request = { method: init.method, headers: headers2 };
|
|
3778
|
+
if (cfg.signal !== void 0) request.signal = cfg.signal;
|
|
3779
|
+
if (init.body !== void 0) request.body = init.body;
|
|
3780
|
+
return fetchImpl(cfg.baseUrl, request);
|
|
3781
|
+
}
|
|
3782
|
+
|
|
3783
|
+
// src/adapters/fal-video-tools.ts
|
|
3784
|
+
import { z as z11 } from "zod";
|
|
3785
|
+
|
|
3786
|
+
// src/catalog/video-tools-spec.ts
|
|
3787
|
+
import { z as z10 } from "zod";
|
|
3788
|
+
var RangeSchema2 = z10.object({ min: z10.number(), max: z10.number() });
|
|
3789
|
+
var ToolSchema = z10.object({
|
|
3790
|
+
kind: z10.enum(["upscale", "interpolate", "hdr"]),
|
|
3791
|
+
upscaleFactor: RangeSchema2.optional(),
|
|
3792
|
+
maxOutputLongEdge: z10.number().positive().optional(),
|
|
3793
|
+
fps: RangeSchema2.optional(),
|
|
3794
|
+
outputFormats: z10.array(z10.enum(["h265", "prores"])).min(1).optional()
|
|
3795
|
+
});
|
|
3796
|
+
function videoToolConstraints(row) {
|
|
3797
|
+
if (row.type !== "video-tool") return void 0;
|
|
3798
|
+
const parsed = ToolSchema.safeParse(row.constraints.tool);
|
|
3799
|
+
if (!parsed.success) return void 0;
|
|
3800
|
+
const { kind, upscaleFactor, maxOutputLongEdge, fps, outputFormats } = parsed.data;
|
|
3801
|
+
return {
|
|
3802
|
+
kind,
|
|
3803
|
+
...upscaleFactor !== void 0 && { upscaleFactor },
|
|
3804
|
+
...maxOutputLongEdge !== void 0 && { maxOutputLongEdge },
|
|
3805
|
+
...fps !== void 0 && { fps },
|
|
3806
|
+
...outputFormats !== void 0 && { outputFormats }
|
|
3807
|
+
};
|
|
3808
|
+
}
|
|
3809
|
+
function resolutionTier(width, height) {
|
|
3810
|
+
const shortEdge = Math.min(width, height);
|
|
3811
|
+
if (shortEdge <= 360) return "360p";
|
|
3812
|
+
if (shortEdge <= 480) return "480p";
|
|
3813
|
+
if (shortEdge <= 720) return "720p";
|
|
3814
|
+
if (shortEdge <= 1080) return "1080p";
|
|
3815
|
+
if (shortEdge <= 1440) return "2k";
|
|
3816
|
+
return "4k";
|
|
3817
|
+
}
|
|
3818
|
+
function fail(error) {
|
|
3819
|
+
return { ok: false, error };
|
|
3820
|
+
}
|
|
3821
|
+
function planVideoTool(row, req) {
|
|
3822
|
+
const tool = videoToolConstraints(row);
|
|
3823
|
+
if (!tool) return fail(`${row.id} is not a video tool`);
|
|
3824
|
+
const { width, height, durationSeconds, fps } = req.source;
|
|
3825
|
+
if (!(width > 0 && height > 0 && durationSeconds > 0)) {
|
|
3826
|
+
return fail("The source video's width, height and duration are required");
|
|
3827
|
+
}
|
|
3828
|
+
const maxSeconds = row.constraints.sourceVideoSeconds?.max;
|
|
3829
|
+
if (maxSeconds !== void 0 && durationSeconds > maxSeconds) {
|
|
3830
|
+
return fail(`${row.label} takes source videos up to ${maxSeconds} seconds.`);
|
|
3831
|
+
}
|
|
3832
|
+
const base = {
|
|
3833
|
+
durationSeconds,
|
|
3834
|
+
...fps !== void 0 && { fps }
|
|
3835
|
+
};
|
|
3836
|
+
if (tool.kind === "upscale") {
|
|
3837
|
+
const factor = req.upscaleFactor;
|
|
3838
|
+
if (factor === void 0) return fail("An upscale factor is required");
|
|
3839
|
+
const range = tool.upscaleFactor;
|
|
3840
|
+
if (range && (factor < range.min || factor > range.max)) {
|
|
3841
|
+
return fail(`${row.label} upscales by ${range.min}x to ${range.max}x.`);
|
|
3842
|
+
}
|
|
3843
|
+
const outWidth = Math.round(width * factor);
|
|
3844
|
+
const outHeight = Math.round(height * factor);
|
|
3845
|
+
const limit = tool.maxOutputLongEdge;
|
|
3846
|
+
if (limit !== void 0 && Math.max(outWidth, outHeight) > limit) {
|
|
3847
|
+
return fail(
|
|
3848
|
+
`A ${factor}x upscale of a ${width}x${height} video passes the ${limit}px limit.`
|
|
3849
|
+
);
|
|
3850
|
+
}
|
|
3851
|
+
return {
|
|
3852
|
+
ok: true,
|
|
3853
|
+
output: {
|
|
3854
|
+
...base,
|
|
3855
|
+
width: outWidth,
|
|
3856
|
+
height: outHeight,
|
|
3857
|
+
resolution: resolutionTier(outWidth, outHeight),
|
|
3858
|
+
format: "h264"
|
|
3859
|
+
}
|
|
3860
|
+
};
|
|
3861
|
+
}
|
|
3862
|
+
if (tool.kind === "interpolate") {
|
|
3863
|
+
const target = req.targetFps;
|
|
3864
|
+
if (target === void 0 || !Number.isInteger(target)) {
|
|
3865
|
+
return fail("A whole-number target frame rate is required");
|
|
3866
|
+
}
|
|
3867
|
+
const range = tool.fps;
|
|
3868
|
+
if (range && (target < range.min || target > range.max)) {
|
|
3869
|
+
return fail(`${row.label} outputs ${range.min} to ${range.max} fps.`);
|
|
3870
|
+
}
|
|
3871
|
+
return {
|
|
3872
|
+
ok: true,
|
|
3873
|
+
output: {
|
|
3874
|
+
durationSeconds,
|
|
3875
|
+
fps: target,
|
|
3876
|
+
width,
|
|
3877
|
+
height,
|
|
3878
|
+
resolution: resolutionTier(width, height),
|
|
3879
|
+
format: "h264"
|
|
3880
|
+
}
|
|
3881
|
+
};
|
|
3882
|
+
}
|
|
3883
|
+
const formats = tool.outputFormats ?? ["h265"];
|
|
3884
|
+
const format = req.outputFormat ?? formats[0] ?? "h265";
|
|
3885
|
+
if (!formats.includes(format)) {
|
|
3886
|
+
return fail(`${row.label} writes ${formats.join(" or ")}.`);
|
|
3887
|
+
}
|
|
3888
|
+
return {
|
|
3889
|
+
ok: true,
|
|
3890
|
+
output: { ...base, width, height, resolution: resolutionTier(width, height), format }
|
|
3891
|
+
};
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
// src/adapters/fal-video-tools.ts
|
|
3895
|
+
var FAL_QUEUE_ORIGIN = "https://queue.fal.run";
|
|
3896
|
+
var queueUrlSchema = z11.url().refine((value) => new URL(value).origin === FAL_QUEUE_ORIGIN, {
|
|
3897
|
+
message: "not a fal queue URL"
|
|
3898
|
+
});
|
|
3899
|
+
var submitResponseSchema = z11.object({
|
|
3900
|
+
request_id: z11.string().min(1),
|
|
3901
|
+
status_url: queueUrlSchema,
|
|
3902
|
+
response_url: queueUrlSchema,
|
|
3903
|
+
cancel_url: queueUrlSchema
|
|
3904
|
+
});
|
|
3905
|
+
var statusResponseSchema = z11.object({ status: z11.string() });
|
|
3906
|
+
var videoFileSchema = z11.object({
|
|
3907
|
+
url: z11.url(),
|
|
3908
|
+
content_type: z11.string().nullish(),
|
|
3909
|
+
file_size: z11.number().nullish()
|
|
3910
|
+
});
|
|
3911
|
+
var toolOutputSchema = z11.object({ video: videoFileSchema });
|
|
3912
|
+
var falWebhookBodySchema = z11.object({
|
|
3913
|
+
request_id: z11.string().min(1),
|
|
3914
|
+
gateway_request_id: z11.string().nullish(),
|
|
3915
|
+
status: z11.enum(["OK", "ERROR"]),
|
|
3916
|
+
payload: JsonValueSchema.nullish(),
|
|
3917
|
+
error: z11.string().nullish(),
|
|
3918
|
+
payload_error: JsonValueSchema.nullish()
|
|
3919
|
+
});
|
|
3920
|
+
async function queueFetch(ctx, url, method, body) {
|
|
3921
|
+
const payload = body === void 0 ? void 0 : JSON.stringify(body);
|
|
3922
|
+
try {
|
|
3923
|
+
if (ctx.routing.fal === "cloudflare-passthrough") {
|
|
3924
|
+
return await gatewayFetch(gatewayConfig(ctx), ctx.fetch, url, {
|
|
3925
|
+
method,
|
|
3926
|
+
...payload !== void 0 && { body: payload }
|
|
3927
|
+
});
|
|
3928
|
+
}
|
|
3929
|
+
const falKey = ctx.keys.fal;
|
|
3930
|
+
if (!falKey) {
|
|
3931
|
+
throw new ModelKitError({
|
|
3932
|
+
code: "auth",
|
|
3933
|
+
message: "Missing API key for fal",
|
|
3934
|
+
provider: "fal",
|
|
3935
|
+
model: ctx.model.id,
|
|
3936
|
+
retryable: false
|
|
3937
|
+
});
|
|
3938
|
+
}
|
|
3939
|
+
return await ctx.fetch(url, {
|
|
3940
|
+
method,
|
|
3941
|
+
headers: {
|
|
3942
|
+
Authorization: `Key ${falKey}`,
|
|
3943
|
+
...payload !== void 0 && { "Content-Type": "application/json" }
|
|
3944
|
+
},
|
|
3945
|
+
...payload !== void 0 && { body: payload },
|
|
3946
|
+
...ctx.signal !== void 0 && { signal: ctx.signal }
|
|
3947
|
+
});
|
|
3948
|
+
} catch (cause) {
|
|
3949
|
+
if (cause instanceof ModelKitError) throw cause;
|
|
3950
|
+
throw classifyThrown("fal", cause, ctx.model.id);
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3953
|
+
async function readJson(ctx, res) {
|
|
3954
|
+
if (!res.ok) throw falError(res.status, await readBody(res), ctx.model.id);
|
|
3955
|
+
return JsonValueSchema.parse(await res.json());
|
|
3956
|
+
}
|
|
3957
|
+
function providerModelName(ctx) {
|
|
3958
|
+
return z11.string().safeParse(ctx.model.providerOptions?.["fal"]?.["model"]).data;
|
|
3959
|
+
}
|
|
3960
|
+
function toolInput(ctx, req, output) {
|
|
3961
|
+
const tool = videoToolConstraints(ctx.model);
|
|
3962
|
+
const model = providerModelName(ctx);
|
|
3963
|
+
const input = { video_url: req.source.url };
|
|
3964
|
+
if (tool?.kind === "upscale") {
|
|
3965
|
+
if (model !== void 0) input["model"] = model;
|
|
3966
|
+
input["upscale_factor"] = req.upscaleFactor ?? 1;
|
|
3967
|
+
input["H264_output"] = true;
|
|
3968
|
+
} else if (tool?.kind === "interpolate") {
|
|
3969
|
+
if (model !== void 0) input["model"] = model;
|
|
3970
|
+
input["target_fps"] = req.targetFps ?? 60;
|
|
3971
|
+
input["slowdown_factor"] = 1;
|
|
3972
|
+
input["H264_output"] = true;
|
|
3973
|
+
} else {
|
|
3974
|
+
input["output_format"] = output.format === "prores" ? "prores" : "mp4";
|
|
3975
|
+
}
|
|
3976
|
+
return input;
|
|
3977
|
+
}
|
|
3978
|
+
async function submitFalVideoTool(req, ctx, opts) {
|
|
3979
|
+
const plan = planVideoTool(ctx.model, req);
|
|
3980
|
+
if (!plan.ok) {
|
|
3981
|
+
throw new ModelKitError({
|
|
3982
|
+
code: "unsupported_option",
|
|
3983
|
+
message: plan.error,
|
|
3984
|
+
provider: "fal",
|
|
3985
|
+
model: ctx.model.id,
|
|
3986
|
+
retryable: false
|
|
3987
|
+
});
|
|
3988
|
+
}
|
|
3989
|
+
const target = new URL(`${FAL_QUEUE_ORIGIN}/${ctx.model.providerModelId}`);
|
|
3990
|
+
if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
|
|
3991
|
+
const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req, plan.output));
|
|
3992
|
+
const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
|
|
3993
|
+
if (!parsed.success) {
|
|
3994
|
+
throw new ModelKitError({
|
|
3995
|
+
code: "provider_rejected",
|
|
3996
|
+
message: `fal ${ctx.model.providerModelId} submit returned no queue URLs`,
|
|
3997
|
+
provider: "fal",
|
|
3998
|
+
model: ctx.model.id,
|
|
3999
|
+
retryable: false
|
|
4000
|
+
});
|
|
4001
|
+
}
|
|
4002
|
+
return {
|
|
4003
|
+
model: ctx.model.id,
|
|
4004
|
+
provider: "fal",
|
|
4005
|
+
requestId: parsed.data.request_id,
|
|
4006
|
+
statusUrl: parsed.data.status_url,
|
|
4007
|
+
responseUrl: parsed.data.response_url,
|
|
4008
|
+
cancelUrl: parsed.data.cancel_url,
|
|
4009
|
+
output: plan.output
|
|
4010
|
+
};
|
|
4011
|
+
}
|
|
4012
|
+
function checkedQueueUrl(ctx, url) {
|
|
4013
|
+
if (!queueUrlSchema.safeParse(url).success) {
|
|
4014
|
+
throw new ModelKitError({
|
|
4015
|
+
code: "provider_rejected",
|
|
4016
|
+
message: "Video-tool submission carries a URL outside fal's queue",
|
|
4017
|
+
provider: "fal",
|
|
4018
|
+
model: ctx.model.id,
|
|
4019
|
+
retryable: false
|
|
4020
|
+
});
|
|
4021
|
+
}
|
|
4022
|
+
return url;
|
|
4023
|
+
}
|
|
4024
|
+
async function falVideoToolStatus(sub, ctx) {
|
|
4025
|
+
const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl), "GET");
|
|
4026
|
+
const { status } = statusResponseSchema.parse(await readJson(ctx, res));
|
|
4027
|
+
if (status === "IN_QUEUE") return "queued";
|
|
4028
|
+
if (status === "COMPLETED") return "completed";
|
|
4029
|
+
return "running";
|
|
4030
|
+
}
|
|
4031
|
+
function usageOf(ctx, output) {
|
|
4032
|
+
return {
|
|
4033
|
+
model: ctx.model.id,
|
|
4034
|
+
provider: "fal",
|
|
4035
|
+
modality: "VIDEO",
|
|
4036
|
+
unit: "seconds",
|
|
4037
|
+
quantity: output.durationSeconds,
|
|
4038
|
+
durationSeconds: output.durationSeconds,
|
|
4039
|
+
resolution: output.resolution,
|
|
4040
|
+
...output.fps !== void 0 && { fps: output.fps }
|
|
4041
|
+
};
|
|
4042
|
+
}
|
|
4043
|
+
function resultOf(ctx, sub, payload) {
|
|
4044
|
+
const parsed = toolOutputSchema.safeParse(payload);
|
|
4045
|
+
if (!parsed.success) {
|
|
4046
|
+
throw new ModelKitError({
|
|
4047
|
+
code: "provider_rejected",
|
|
4048
|
+
message: `fal ${ctx.model.providerModelId} returned no video`,
|
|
4049
|
+
provider: "fal",
|
|
4050
|
+
model: ctx.model.id,
|
|
4051
|
+
retryable: false
|
|
4052
|
+
});
|
|
4053
|
+
}
|
|
4054
|
+
const file = parsed.data.video;
|
|
4055
|
+
return {
|
|
4056
|
+
video: {
|
|
4057
|
+
url: file.url,
|
|
4058
|
+
...file.content_type != null && { mime: file.content_type },
|
|
4059
|
+
...file.file_size != null && { bytes: file.file_size }
|
|
4060
|
+
},
|
|
4061
|
+
output: sub.output,
|
|
4062
|
+
usage: usageOf(ctx, sub.output),
|
|
4063
|
+
raw: payload
|
|
4064
|
+
};
|
|
4065
|
+
}
|
|
4066
|
+
async function falVideoToolResult(sub, ctx, webhook) {
|
|
4067
|
+
if (webhook !== void 0) {
|
|
4068
|
+
if (webhook.request_id !== sub.requestId) {
|
|
4069
|
+
throw new ModelKitError({
|
|
4070
|
+
code: "provider_rejected",
|
|
4071
|
+
message: "fal webhook is for a different request",
|
|
4072
|
+
provider: "fal",
|
|
4073
|
+
model: ctx.model.id,
|
|
4074
|
+
retryable: false
|
|
4075
|
+
});
|
|
4076
|
+
}
|
|
4077
|
+
if (webhook.status === "ERROR") {
|
|
4078
|
+
throw falError(
|
|
4079
|
+
void 0,
|
|
4080
|
+
webhook.payload ?? webhook.error ?? "fal job failed",
|
|
4081
|
+
ctx.model.id
|
|
4082
|
+
);
|
|
4083
|
+
}
|
|
4084
|
+
return resultOf(ctx, sub, webhook.payload);
|
|
4085
|
+
}
|
|
4086
|
+
const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl), "GET");
|
|
4087
|
+
return resultOf(ctx, sub, await readJson(ctx, res));
|
|
4088
|
+
}
|
|
4089
|
+
async function cancelFalVideoTool(sub, ctx) {
|
|
4090
|
+
const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl), "PUT");
|
|
4091
|
+
if (res.ok) return true;
|
|
4092
|
+
if (res.status === 400) return false;
|
|
4093
|
+
throw falError(res.status, await readBody(res), ctx.model.id);
|
|
4094
|
+
}
|
|
4095
|
+
|
|
3576
4096
|
// src/adapters/fal.ts
|
|
3577
4097
|
var MUSE_T2I_ENDPOINT = "meta/muse-image/text-to-image";
|
|
3578
4098
|
var MUSE_EDIT_ENDPOINT = "meta/muse-image/edit";
|
|
@@ -3580,7 +4100,7 @@ var KLING_O1_ENDPOINT = "fal-ai/kling-video/o1/video-to-video/reference";
|
|
|
3580
4100
|
var FAL_QUEUE_HOST = "https://queue.fal.run";
|
|
3581
4101
|
var PASSTHROUGH_POLL_MS = 2e3;
|
|
3582
4102
|
var PASSTHROUGH_MAX_WAIT_MS = 18e4;
|
|
3583
|
-
var falSubscribePayloadSchema =
|
|
4103
|
+
var falSubscribePayloadSchema = z12.object({ data: JsonValueSchema });
|
|
3584
4104
|
function defaultCreateFalClient(opts) {
|
|
3585
4105
|
if (opts.maxRetries !== void 0)
|
|
3586
4106
|
return createFalHttpClient({
|
|
@@ -3633,24 +4153,19 @@ function createFalAdapter(deps = defaultDeps) {
|
|
|
3633
4153
|
generateVideo: (req, ctx) => {
|
|
3634
4154
|
throwIfAborted(ctx.signal);
|
|
3635
4155
|
return generateFalVideo(req, ctx, deps);
|
|
3636
|
-
}
|
|
4156
|
+
},
|
|
4157
|
+
submitVideoTool: submitFalVideoTool,
|
|
4158
|
+
videoToolStatus: falVideoToolStatus,
|
|
4159
|
+
videoToolResult: falVideoToolResult,
|
|
4160
|
+
cancelVideoTool: cancelFalVideoTool
|
|
3637
4161
|
};
|
|
3638
4162
|
}
|
|
3639
4163
|
var falAdapter = createFalAdapter();
|
|
3640
|
-
var
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
const detail = parsed.success ? parsed.data.detail : void 0;
|
|
3644
|
-
return detail ?? body;
|
|
3645
|
-
}
|
|
3646
|
-
function falError(status, body, model) {
|
|
3647
|
-
return classifyHttpError(status, liftDetail(body), "fal", model);
|
|
3648
|
-
}
|
|
3649
|
-
var falSdkThrownSchema = z9.object({
|
|
3650
|
-
status: z9.number().optional(),
|
|
3651
|
-
statusCode: z9.number().optional(),
|
|
4164
|
+
var falSdkThrownSchema = z12.object({
|
|
4165
|
+
status: z12.number().optional(),
|
|
4166
|
+
statusCode: z12.number().optional(),
|
|
3652
4167
|
body: JsonValueSchema.optional(),
|
|
3653
|
-
message:
|
|
4168
|
+
message: z12.string().optional()
|
|
3654
4169
|
});
|
|
3655
4170
|
function falSdkError(cause, model) {
|
|
3656
4171
|
const parsed = falSdkThrownSchema.safeParse(cause);
|
|
@@ -3665,45 +4180,12 @@ function falSdkError(cause, model) {
|
|
|
3665
4180
|
body: liftDetail(info.body)
|
|
3666
4181
|
});
|
|
3667
4182
|
}
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
if (!cf?.accountId || !cf?.gatewayId || !falKey && !cfToken) {
|
|
3673
|
-
throw new ModelKitError({
|
|
3674
|
-
code: "auth",
|
|
3675
|
-
message: "fal passthrough is not configured. Set routing.cloudflare and FAL_KEY or the gateway token (BYOK).",
|
|
3676
|
-
provider: "fal",
|
|
3677
|
-
model: ctx.model.id,
|
|
3678
|
-
retryable: false
|
|
3679
|
-
});
|
|
3680
|
-
}
|
|
3681
|
-
const config = {
|
|
3682
|
-
baseUrl: `https://gateway.ai.cloudflare.com/v1/${cf.accountId}/${cf.gatewayId}/fal`
|
|
3683
|
-
};
|
|
3684
|
-
if (falKey) config.falKey = falKey;
|
|
3685
|
-
if (cfToken) config.cfToken = cfToken;
|
|
3686
|
-
if (ctx.call.maxRetries !== void 0) config.singleAttempt = true;
|
|
3687
|
-
if (ctx.signal !== void 0) config.signal = ctx.signal;
|
|
3688
|
-
return config;
|
|
3689
|
-
}
|
|
3690
|
-
async function gatewayFetch(cfg, fetchImpl, targetUrl, init) {
|
|
3691
|
-
const headers2 = { "x-fal-target-url": targetUrl };
|
|
3692
|
-
if (cfg.falKey) headers2.Authorization = `Bearer ${cfg.falKey}`;
|
|
3693
|
-
if (init.body) headers2["Content-Type"] = "application/json";
|
|
3694
|
-
if (cfg.cfToken) headers2["cf-aig-authorization"] = `Bearer ${cfg.cfToken}`;
|
|
3695
|
-
if (cfg.singleAttempt) headers2["cf-aig-max-attempts"] = "1";
|
|
3696
|
-
const request = { method: init.method, headers: headers2 };
|
|
3697
|
-
if (cfg.signal !== void 0) request.signal = cfg.signal;
|
|
3698
|
-
if (init.body !== void 0) request.body = init.body;
|
|
3699
|
-
return fetchImpl(cfg.baseUrl, request);
|
|
3700
|
-
}
|
|
3701
|
-
var falQueueSubmitSchema = z9.object({
|
|
3702
|
-
request_id: z9.string(),
|
|
3703
|
-
status_url: z9.string(),
|
|
3704
|
-
response_url: z9.string()
|
|
4183
|
+
var falQueueSubmitSchema = z12.object({
|
|
4184
|
+
request_id: z12.string(),
|
|
4185
|
+
status_url: z12.string(),
|
|
4186
|
+
response_url: z12.string()
|
|
3705
4187
|
});
|
|
3706
|
-
var falQueueStatusSchema =
|
|
4188
|
+
var falQueueStatusSchema = z12.object({ status: z12.string() });
|
|
3707
4189
|
async function passthroughRequest(ctx, endpoint, input) {
|
|
3708
4190
|
const cfg = gatewayConfig(ctx);
|
|
3709
4191
|
const submitRes = await gatewayFetch(cfg, ctx.fetch, `${FAL_QUEUE_HOST}/${endpoint}`, {
|
|
@@ -3836,11 +4318,11 @@ async function decodeImage(ctx, url, contentType) {
|
|
|
3836
4318
|
const mime = res.headers.get("content-type") ?? contentType ?? "image/png";
|
|
3837
4319
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
3838
4320
|
}
|
|
3839
|
-
var museImageResultSchema =
|
|
3840
|
-
images:
|
|
3841
|
-
|
|
3842
|
-
url:
|
|
3843
|
-
content_type:
|
|
4321
|
+
var museImageResultSchema = z12.object({
|
|
4322
|
+
images: z12.array(
|
|
4323
|
+
z12.object({
|
|
4324
|
+
url: z12.string().optional(),
|
|
4325
|
+
content_type: z12.string().nullable().optional()
|
|
3844
4326
|
})
|
|
3845
4327
|
).optional()
|
|
3846
4328
|
});
|
|
@@ -4010,8 +4492,8 @@ function klingO1Input(req) {
|
|
|
4010
4492
|
if (refs.length > 0) input.image_urls = refs;
|
|
4011
4493
|
return input;
|
|
4012
4494
|
}
|
|
4013
|
-
var falVideoResultSchema =
|
|
4014
|
-
video:
|
|
4495
|
+
var falVideoResultSchema = z12.object({
|
|
4496
|
+
video: z12.object({ url: z12.string().optional() }).optional()
|
|
4015
4497
|
});
|
|
4016
4498
|
function extractVideoUrl(result, endpoint, model) {
|
|
4017
4499
|
const parsed = falVideoResultSchema.safeParse(result);
|
|
@@ -4212,13 +4694,13 @@ async function passthroughVideoJob(ctx, req, endpoint, input) {
|
|
|
4212
4694
|
}
|
|
4213
4695
|
|
|
4214
4696
|
// src/adapters/google-genai.ts
|
|
4215
|
-
import { z as
|
|
4697
|
+
import { z as z14 } from "zod";
|
|
4216
4698
|
import {
|
|
4217
4699
|
GoogleGenAI
|
|
4218
4700
|
} from "@google/genai";
|
|
4219
4701
|
|
|
4220
4702
|
// src/adapters/google-files.ts
|
|
4221
|
-
import { z as
|
|
4703
|
+
import { z as z13 } from "zod";
|
|
4222
4704
|
var GOOGLE_FILES_BASE = "https://generativelanguage.googleapis.com";
|
|
4223
4705
|
var GOOGLE_FILES_POLL_INTERVAL_MS = 2e3;
|
|
4224
4706
|
var GOOGLE_FILES_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -4228,17 +4710,17 @@ var GENERIC_MEDIA_TYPES = /* @__PURE__ */ new Set([
|
|
|
4228
4710
|
"binary/octet-stream",
|
|
4229
4711
|
"application/binary"
|
|
4230
4712
|
]);
|
|
4231
|
-
var uploadedFileSchema =
|
|
4232
|
-
file:
|
|
4233
|
-
uri:
|
|
4234
|
-
name:
|
|
4235
|
-
state:
|
|
4236
|
-
mimeType:
|
|
4713
|
+
var uploadedFileSchema = z13.object({
|
|
4714
|
+
file: z13.object({
|
|
4715
|
+
uri: z13.string().optional(),
|
|
4716
|
+
name: z13.string().optional(),
|
|
4717
|
+
state: z13.string().optional(),
|
|
4718
|
+
mimeType: z13.string().optional()
|
|
4237
4719
|
}).optional()
|
|
4238
4720
|
});
|
|
4239
|
-
var fileStateSchema =
|
|
4240
|
-
state:
|
|
4241
|
-
error:
|
|
4721
|
+
var fileStateSchema = z13.object({
|
|
4722
|
+
state: z13.string().optional(),
|
|
4723
|
+
error: z13.object({ message: z13.string().optional() }).optional()
|
|
4242
4724
|
});
|
|
4243
4725
|
function resolveMime(declared, fallback) {
|
|
4244
4726
|
const clean = declared?.split(";")[0]?.trim().toLowerCase();
|
|
@@ -4455,7 +4937,7 @@ var OMNI_POLL_INTERVAL_MS = 1e4;
|
|
|
4455
4937
|
var RESULT_TIMEOUT_MS2 = 15 * 60 * 1e3;
|
|
4456
4938
|
var OMNI_INLINE_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
4457
4939
|
var MEDIA_PART_INLINE_LIMIT_BYTES = 20 * 1024 * 1024;
|
|
4458
|
-
var errorTextSchema =
|
|
4940
|
+
var errorTextSchema = z14.string();
|
|
4459
4941
|
function isGoogleGenaiVideoKnown(providerModelId) {
|
|
4460
4942
|
return providerModelId.startsWith("veo-") || providerModelId.startsWith("gemini-omni");
|
|
4461
4943
|
}
|
|
@@ -5061,15 +5543,15 @@ async function prepareGoogleMediaPart(ref, mediaType, ctx) {
|
|
|
5061
5543
|
// src/adapters/google-image.ts
|
|
5062
5544
|
import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
|
|
5063
5545
|
import { generateText } from "ai";
|
|
5064
|
-
import { z as
|
|
5546
|
+
import { z as z15 } from "zod";
|
|
5065
5547
|
var GEMINI_IMAGE_TIMEOUT_MS = 6e5;
|
|
5066
5548
|
var defaultGoogleImageDeps = {
|
|
5067
5549
|
createGoogleClient: (opts) => createGoogleGenerativeAI2(opts),
|
|
5068
5550
|
runTextGeneration: (opts) => generateText(opts)
|
|
5069
5551
|
};
|
|
5070
|
-
var causeChainNodeSchema =
|
|
5071
|
-
message:
|
|
5072
|
-
cause:
|
|
5552
|
+
var causeChainNodeSchema = z15.object({
|
|
5553
|
+
message: z15.string().optional(),
|
|
5554
|
+
cause: z15.unknown().optional()
|
|
5073
5555
|
});
|
|
5074
5556
|
function extractBlockReason(cause) {
|
|
5075
5557
|
let current = cause;
|
|
@@ -5189,7 +5671,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
5189
5671
|
var googleImageAdapter = createGoogleImageAdapter();
|
|
5190
5672
|
|
|
5191
5673
|
// src/adapters/higgsfield.ts
|
|
5192
|
-
import { z as
|
|
5674
|
+
import { z as z16 } from "zod";
|
|
5193
5675
|
|
|
5194
5676
|
// src/adapters/higgsfield-motions.ts
|
|
5195
5677
|
var MOTION_MAP = {
|
|
@@ -5408,14 +5890,14 @@ function klingEndpointFields(providerModelId) {
|
|
|
5408
5890
|
const path = (providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId).toLowerCase();
|
|
5409
5891
|
return KLING_ENDPOINT_FIELDS.get(path) ?? UNLISTED_KLING_FIELDS;
|
|
5410
5892
|
}
|
|
5411
|
-
var klingCreateSchema =
|
|
5412
|
-
var klingStatusSchema =
|
|
5413
|
-
status:
|
|
5414
|
-
video:
|
|
5893
|
+
var klingCreateSchema = z16.object({ status_url: z16.string() });
|
|
5894
|
+
var klingStatusSchema = z16.object({
|
|
5895
|
+
status: z16.string().optional(),
|
|
5896
|
+
video: z16.object({ url: z16.string().optional() }).optional(),
|
|
5415
5897
|
error: JsonValueSchema.optional()
|
|
5416
5898
|
});
|
|
5417
|
-
var errorMessageSchema =
|
|
5418
|
-
var textValueSchema =
|
|
5899
|
+
var errorMessageSchema = z16.object({ message: z16.string().optional() });
|
|
5900
|
+
var textValueSchema = z16.string();
|
|
5419
5901
|
function klingErrorDetail(error) {
|
|
5420
5902
|
if (error === void 0) return "unknown_error";
|
|
5421
5903
|
const asText = textValueSchema.safeParse(error);
|
|
@@ -5571,8 +6053,8 @@ async function generateKlingVideo(req, ctx) {
|
|
|
5571
6053
|
}
|
|
5572
6054
|
};
|
|
5573
6055
|
}
|
|
5574
|
-
var dopMotionOptionsSchema =
|
|
5575
|
-
modelkit:
|
|
6056
|
+
var dopMotionOptionsSchema = z16.object({
|
|
6057
|
+
modelkit: z16.object({ motion: z16.string().optional() }).optional()
|
|
5576
6058
|
});
|
|
5577
6059
|
function dopMotionId(ctx) {
|
|
5578
6060
|
const parsed = dopMotionOptionsSchema.safeParse(ctx.model.providerOptions);
|
|
@@ -5588,7 +6070,7 @@ function dopMotionId(ctx) {
|
|
|
5588
6070
|
});
|
|
5589
6071
|
return id;
|
|
5590
6072
|
}
|
|
5591
|
-
var jsonRecordSchema =
|
|
6073
|
+
var jsonRecordSchema = z16.record(z16.string(), JsonValueSchema);
|
|
5592
6074
|
var DOP_URL_KEYS = ["url", "video_url", "output_url", "result_url", "download_url"];
|
|
5593
6075
|
var DOP_NESTED_KEYS = ["video", "result", "results"];
|
|
5594
6076
|
function dopUrl(body) {
|
|
@@ -5616,8 +6098,8 @@ function dopUrl(body) {
|
|
|
5616
6098
|
}
|
|
5617
6099
|
return void 0;
|
|
5618
6100
|
}
|
|
5619
|
-
var dopCreateSchema =
|
|
5620
|
-
var dopStatusSchema =
|
|
6101
|
+
var dopCreateSchema = z16.object({ id: z16.string() });
|
|
6102
|
+
var dopStatusSchema = z16.object({ status: z16.string().optional() });
|
|
5621
6103
|
async function generateDopVideo(req, ctx) {
|
|
5622
6104
|
const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
|
|
5623
6105
|
if (!firstFrame) {
|
|
@@ -5745,7 +6227,7 @@ var higgsfieldAdapter = {
|
|
|
5745
6227
|
|
|
5746
6228
|
// src/adapters/openai-image.ts
|
|
5747
6229
|
import OpenAI from "openai";
|
|
5748
|
-
import { z as
|
|
6230
|
+
import { z as z17 } from "zod";
|
|
5749
6231
|
var MAX_EDIT_REFERENCES = 16;
|
|
5750
6232
|
function aspectRatioToSize(ratio, tier) {
|
|
5751
6233
|
const TIER_LONG_EDGE = {
|
|
@@ -5828,9 +6310,9 @@ function toProviderError2(cause, ctx) {
|
|
|
5828
6310
|
ctx.model.id
|
|
5829
6311
|
);
|
|
5830
6312
|
}
|
|
5831
|
-
var openaiUsageSchema =
|
|
5832
|
-
input_tokens:
|
|
5833
|
-
output_tokens:
|
|
6313
|
+
var openaiUsageSchema = z17.object({
|
|
6314
|
+
input_tokens: z17.number().optional(),
|
|
6315
|
+
output_tokens: z17.number().optional()
|
|
5834
6316
|
});
|
|
5835
6317
|
var openaiImageAdapter = {
|
|
5836
6318
|
id: "openai-image",
|
|
@@ -6241,13 +6723,13 @@ var prodiaAdapter = {
|
|
|
6241
6723
|
import Replicate from "replicate";
|
|
6242
6724
|
|
|
6243
6725
|
// src/adapters/replicate-http.ts
|
|
6244
|
-
import { z as
|
|
6245
|
-
var predictionSchema =
|
|
6246
|
-
id:
|
|
6247
|
-
status:
|
|
6726
|
+
import { z as z18 } from "zod";
|
|
6727
|
+
var predictionSchema = z18.object({
|
|
6728
|
+
id: z18.string(),
|
|
6729
|
+
status: z18.string(),
|
|
6248
6730
|
output: JsonValueSchema.optional(),
|
|
6249
6731
|
error: JsonValueSchema.optional(),
|
|
6250
|
-
metrics:
|
|
6732
|
+
metrics: z18.object({ predict_time: z18.number().optional() }).optional()
|
|
6251
6733
|
});
|
|
6252
6734
|
function createReplicateHttpClient(opts) {
|
|
6253
6735
|
async function request(path, body, signal) {
|
|
@@ -6298,7 +6780,7 @@ function createReplicateHttpClient(opts) {
|
|
|
6298
6780
|
}
|
|
6299
6781
|
|
|
6300
6782
|
// src/adapters/replicate.ts
|
|
6301
|
-
import { z as
|
|
6783
|
+
import { z as z19 } from "zod";
|
|
6302
6784
|
|
|
6303
6785
|
// src/adapters/input-spec-mapper.ts
|
|
6304
6786
|
function canonicalValue(req, key) {
|
|
@@ -6373,8 +6855,8 @@ function route(providerModelId) {
|
|
|
6373
6855
|
if (!providerModelId.includes("/")) return { version: providerModelId };
|
|
6374
6856
|
return { model: providerModelId };
|
|
6375
6857
|
}
|
|
6376
|
-
var replicateResponseStatusSchema =
|
|
6377
|
-
response:
|
|
6858
|
+
var replicateResponseStatusSchema = z19.object({
|
|
6859
|
+
response: z19.object({ status: z19.number() }).partial()
|
|
6378
6860
|
});
|
|
6379
6861
|
function replicateError(cause, ctx) {
|
|
6380
6862
|
if (isModelKitError(cause)) return cause;
|
|
@@ -6401,7 +6883,7 @@ function isUrlFn(value) {
|
|
|
6401
6883
|
function extractOutputUrl(output) {
|
|
6402
6884
|
const root = Array.isArray(output) ? output[0] : output;
|
|
6403
6885
|
if (root === void 0) throw noOutput();
|
|
6404
|
-
const asString =
|
|
6886
|
+
const asString = z19.string().safeParse(root);
|
|
6405
6887
|
if (asString.success && asString.data) return asString.data;
|
|
6406
6888
|
if (root instanceof URL) return root.href;
|
|
6407
6889
|
if (isObjectOutput(root)) {
|
|
@@ -6410,15 +6892,15 @@ function extractOutputUrl(output) {
|
|
|
6410
6892
|
if (urlValue !== void 0 && isUrlFn(urlValue)) {
|
|
6411
6893
|
const called = urlValue();
|
|
6412
6894
|
if (called instanceof URL) return called.href;
|
|
6413
|
-
const calledString =
|
|
6895
|
+
const calledString = z19.string().safeParse(called);
|
|
6414
6896
|
if (calledString.success && calledString.data) return calledString.data;
|
|
6415
6897
|
} else {
|
|
6416
|
-
const direct =
|
|
6898
|
+
const direct = z19.string().safeParse(urlValue);
|
|
6417
6899
|
if (direct.success && direct.data) return direct.data;
|
|
6418
6900
|
}
|
|
6419
6901
|
}
|
|
6420
6902
|
if ("default" in root) {
|
|
6421
|
-
const fallback =
|
|
6903
|
+
const fallback = z19.string().safeParse(root.default);
|
|
6422
6904
|
if (fallback.success && fallback.data) return fallback.data;
|
|
6423
6905
|
}
|
|
6424
6906
|
}
|
|
@@ -6479,7 +6961,7 @@ async function runPrediction(ctx, input, deps) {
|
|
|
6479
6961
|
}
|
|
6480
6962
|
return void 0;
|
|
6481
6963
|
}, pollOpts);
|
|
6482
|
-
const predictTime =
|
|
6964
|
+
const predictTime = z19.number().safeParse(done.metrics?.predict_time);
|
|
6483
6965
|
if (done.output === void 0) throw noOutput();
|
|
6484
6966
|
return {
|
|
6485
6967
|
url: extractOutputUrl(done.output),
|
|
@@ -6868,7 +7350,7 @@ async function generateReplicateVideo(req, ctx, deps) {
|
|
|
6868
7350
|
throw replicateError(cause, ctx);
|
|
6869
7351
|
}
|
|
6870
7352
|
if (current.status === "succeeded") {
|
|
6871
|
-
const predictTime =
|
|
7353
|
+
const predictTime = z19.number().safeParse(current.metrics?.predict_time);
|
|
6872
7354
|
if (current.output === void 0) throw noOutput();
|
|
6873
7355
|
return {
|
|
6874
7356
|
url: extractOutputUrl(current.output),
|
|
@@ -7009,7 +7491,7 @@ async function generateReplicateAudio(req, ctx, deps) {
|
|
|
7009
7491
|
// src/adapters/xai-video.ts
|
|
7010
7492
|
import { experimental_generateVideo } from "ai";
|
|
7011
7493
|
import { createXai as createXai2 } from "@ai-sdk/xai";
|
|
7012
|
-
import { z as
|
|
7494
|
+
import { z as z20 } from "zod";
|
|
7013
7495
|
var POLL_INTERVAL_MS2 = 1e4;
|
|
7014
7496
|
var POLL_TIMEOUT_MS2 = 15 * 6e4;
|
|
7015
7497
|
var defaultXaiDeps = {
|
|
@@ -7022,8 +7504,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
|
|
|
7022
7504
|
};
|
|
7023
7505
|
}
|
|
7024
7506
|
var xaiVideoAdapter = createXaiVideoAdapter();
|
|
7025
|
-
var xaiResponseStatusSchema =
|
|
7026
|
-
response:
|
|
7507
|
+
var xaiResponseStatusSchema = z20.object({
|
|
7508
|
+
response: z20.object({ status: z20.number() }).partial()
|
|
7027
7509
|
});
|
|
7028
7510
|
function xaiError(cause, ctx) {
|
|
7029
7511
|
const info = describeThrown(cause);
|
|
@@ -7031,12 +7513,12 @@ function xaiError(cause, ctx) {
|
|
|
7031
7513
|
const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
|
|
7032
7514
|
return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
|
|
7033
7515
|
}
|
|
7034
|
-
var xaiMetaSchema =
|
|
7516
|
+
var xaiMetaSchema = z20.object({
|
|
7035
7517
|
videoUrl: JsonValueSchema.optional(),
|
|
7036
7518
|
costInUsdTicks: JsonValueSchema.optional(),
|
|
7037
7519
|
duration: JsonValueSchema.optional()
|
|
7038
7520
|
});
|
|
7039
|
-
var xaiProviderMetadataSchema =
|
|
7521
|
+
var xaiProviderMetadataSchema = z20.object({ xai: xaiMetaSchema });
|
|
7040
7522
|
function metaOf(result) {
|
|
7041
7523
|
const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
|
|
7042
7524
|
if (!parsed.success) return {};
|
|
@@ -7144,7 +7626,7 @@ async function mapResult(ctx, req, result) {
|
|
|
7144
7626
|
};
|
|
7145
7627
|
}
|
|
7146
7628
|
const meta = metaOf(result);
|
|
7147
|
-
const videoUrl =
|
|
7629
|
+
const videoUrl = z20.string().safeParse(meta.videoUrl);
|
|
7148
7630
|
if (videoUrl.success && videoUrl.data) {
|
|
7149
7631
|
const res = await ctx.fetch(videoUrl.data);
|
|
7150
7632
|
if (!res.ok) {
|
|
@@ -7167,7 +7649,7 @@ async function mapResult(ctx, req, result) {
|
|
|
7167
7649
|
});
|
|
7168
7650
|
}
|
|
7169
7651
|
function usage(ctx, req, meta) {
|
|
7170
|
-
const costTicks =
|
|
7652
|
+
const costTicks = z20.number().safeParse(meta.costInUsdTicks);
|
|
7171
7653
|
const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
|
|
7172
7654
|
const event = {
|
|
7173
7655
|
model: ctx.model.id,
|
|
@@ -7300,22 +7782,22 @@ var liveState = store[KEY] ??= {
|
|
|
7300
7782
|
var liveCatalog = liveState.catalog;
|
|
7301
7783
|
|
|
7302
7784
|
// src/catalog/load.ts
|
|
7303
|
-
import { z as
|
|
7785
|
+
import { z as z21 } from "zod";
|
|
7304
7786
|
function rowCount() {
|
|
7305
7787
|
return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
|
|
7306
7788
|
}
|
|
7307
7789
|
function authHeaders(auth) {
|
|
7308
7790
|
return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
|
|
7309
7791
|
}
|
|
7310
|
-
var EnvelopeSchema =
|
|
7311
|
-
rows:
|
|
7312
|
-
revision:
|
|
7792
|
+
var EnvelopeSchema = z21.object({
|
|
7793
|
+
rows: z21.array(JsonValueSchema),
|
|
7794
|
+
revision: z21.string().optional()
|
|
7313
7795
|
});
|
|
7314
7796
|
function dropReason(path, message) {
|
|
7315
7797
|
return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
|
|
7316
7798
|
}
|
|
7317
7799
|
function rowId(raw) {
|
|
7318
|
-
const parsed =
|
|
7800
|
+
const parsed = z21.object({ id: z21.string().min(1) }).loose().safeParse(raw);
|
|
7319
7801
|
if (!parsed.success) return "?";
|
|
7320
7802
|
return parsed.data.id;
|
|
7321
7803
|
}
|
|
@@ -8179,7 +8661,7 @@ import {
|
|
|
8179
8661
|
streamObject as aiStreamObject2,
|
|
8180
8662
|
streamText as aiStreamText2
|
|
8181
8663
|
} from "ai";
|
|
8182
|
-
import { z as
|
|
8664
|
+
import { z as z22 } from "zod";
|
|
8183
8665
|
|
|
8184
8666
|
// src/generated-image.ts
|
|
8185
8667
|
function toGeneratedImage(image) {
|
|
@@ -8235,11 +8717,17 @@ function textUsageProvider(model, transport) {
|
|
|
8235
8717
|
}
|
|
8236
8718
|
|
|
8237
8719
|
// src/client.ts
|
|
8238
|
-
function
|
|
8239
|
-
|
|
8240
|
-
|
|
8720
|
+
function routingFor(config, tier) {
|
|
8721
|
+
const routing = config.routing ?? {};
|
|
8722
|
+
if (tier !== "sloosh") return routing;
|
|
8723
|
+
const direct = { ...routing };
|
|
8724
|
+
if (direct.text === "cloudflare") direct.text = "direct";
|
|
8725
|
+
if (direct.fal === "cloudflare-passthrough") direct.fal = "direct";
|
|
8726
|
+
return direct;
|
|
8727
|
+
}
|
|
8728
|
+
function requiredKeys(model, routing, transport) {
|
|
8729
|
+
if (model.adapter === "fal" && routing.fal === "cloudflare-passthrough") return ["cloudflare"];
|
|
8241
8730
|
if (model.adapter === "ai-sdk-text") {
|
|
8242
|
-
const routing = config.routing ?? {};
|
|
8243
8731
|
const names = [textKeyName(model, transport)];
|
|
8244
8732
|
if (textUsesCloudflareGateway(model, routing, transport)) names.push("cloudflare");
|
|
8245
8733
|
return names;
|
|
@@ -8255,10 +8743,10 @@ function textAbortOptions(sdk, context) {
|
|
|
8255
8743
|
if (abortSignal) return { abortSignal };
|
|
8256
8744
|
return {};
|
|
8257
8745
|
}
|
|
8258
|
-
var catalogId =
|
|
8259
|
-
var exactSize =
|
|
8260
|
-
var sdkRatio =
|
|
8261
|
-
var sizeTier =
|
|
8746
|
+
var catalogId = z22.string();
|
|
8747
|
+
var exactSize = z22.templateLiteral([z22.number(), "x", z22.number()]);
|
|
8748
|
+
var sdkRatio = z22.templateLiteral([z22.number(), ":", z22.number()]);
|
|
8749
|
+
var sizeTier = z22.enum(["512", "1K", "2K", "4K"]);
|
|
8262
8750
|
function isCatalogId(model) {
|
|
8263
8751
|
return catalogId.safeParse(model).success;
|
|
8264
8752
|
}
|
|
@@ -8343,7 +8831,8 @@ function createModelKit(config, adapters) {
|
|
|
8343
8831
|
model: model.id
|
|
8344
8832
|
});
|
|
8345
8833
|
const transport = resolveAnthropicTransport(model, config, call.tier, warnOnce);
|
|
8346
|
-
const
|
|
8834
|
+
const routing = routingFor(config, call.tier);
|
|
8835
|
+
const names = requiredKeys(model, routing, transport);
|
|
8347
8836
|
if (call.tier === "enterprise") {
|
|
8348
8837
|
const missing = missingEnterpriseKeys(config, names);
|
|
8349
8838
|
if (missing.length > 0)
|
|
@@ -8356,7 +8845,7 @@ function createModelKit(config, adapters) {
|
|
|
8356
8845
|
const ctx = {
|
|
8357
8846
|
model,
|
|
8358
8847
|
keys,
|
|
8359
|
-
routing
|
|
8848
|
+
routing,
|
|
8360
8849
|
fetch: fetchImpl,
|
|
8361
8850
|
logger,
|
|
8362
8851
|
call,
|
|
@@ -8367,6 +8856,24 @@ function createModelKit(config, adapters) {
|
|
|
8367
8856
|
if (call.signal) ctx.signal = call.signal;
|
|
8368
8857
|
return { adapter, ctx };
|
|
8369
8858
|
}
|
|
8859
|
+
function videoToolTarget(modelId, call) {
|
|
8860
|
+
mediaRetryOptions(call);
|
|
8861
|
+
const model = catalog.require(modelId);
|
|
8862
|
+
if (model.type !== "video-tool")
|
|
8863
|
+
throw new ModelKitError({
|
|
8864
|
+
code: "unsupported_option",
|
|
8865
|
+
message: `${model.id} is not a video tool`,
|
|
8866
|
+
model: model.id
|
|
8867
|
+
});
|
|
8868
|
+
return context(model, call, []);
|
|
8869
|
+
}
|
|
8870
|
+
function noVideoTools(adapter, model) {
|
|
8871
|
+
return new ModelKitError({
|
|
8872
|
+
code: "unsupported_option",
|
|
8873
|
+
message: `${adapter.id} has no video tools`,
|
|
8874
|
+
model: model.id
|
|
8875
|
+
});
|
|
8876
|
+
}
|
|
8370
8877
|
async function emit(event) {
|
|
8371
8878
|
try {
|
|
8372
8879
|
await config.onUsage?.(event);
|
|
@@ -8722,6 +9229,34 @@ function createModelKit(config, adapters) {
|
|
|
8722
9229
|
usageProvider: provider
|
|
8723
9230
|
};
|
|
8724
9231
|
},
|
|
9232
|
+
async submitVideoTool(req, call = {}) {
|
|
9233
|
+
const { webhookUrl, ...rest } = call;
|
|
9234
|
+
const { adapter, ctx } = videoToolTarget(req.model, rest);
|
|
9235
|
+
if (!adapter.submitVideoTool) throw noVideoTools(adapter, ctx.model);
|
|
9236
|
+
return adapter.submitVideoTool(
|
|
9237
|
+
req,
|
|
9238
|
+
ctx,
|
|
9239
|
+
webhookUrl !== void 0 ? { webhookUrl } : {}
|
|
9240
|
+
);
|
|
9241
|
+
},
|
|
9242
|
+
async videoToolStatus(sub, call = {}) {
|
|
9243
|
+
const { adapter, ctx } = videoToolTarget(sub.model, call);
|
|
9244
|
+
if (!adapter.videoToolStatus) throw noVideoTools(adapter, ctx.model);
|
|
9245
|
+
return adapter.videoToolStatus(sub, ctx);
|
|
9246
|
+
},
|
|
9247
|
+
async videoToolResult(sub, call = {}) {
|
|
9248
|
+
const { webhook, ...rest } = call;
|
|
9249
|
+
const { adapter, ctx } = videoToolTarget(sub.model, rest);
|
|
9250
|
+
if (!adapter.videoToolResult) throw noVideoTools(adapter, ctx.model);
|
|
9251
|
+
const result = await adapter.videoToolResult(sub, ctx, webhook);
|
|
9252
|
+
await emit({ ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit });
|
|
9253
|
+
return result;
|
|
9254
|
+
},
|
|
9255
|
+
async cancelVideoTool(sub, call = {}) {
|
|
9256
|
+
const { adapter, ctx } = videoToolTarget(sub.model, call);
|
|
9257
|
+
if (!adapter.cancelVideoTool) throw noVideoTools(adapter, ctx.model);
|
|
9258
|
+
return adapter.cancelVideoTool(sub, ctx);
|
|
9259
|
+
},
|
|
8725
9260
|
usageProvider(modelId, call = {}) {
|
|
8726
9261
|
const entry = catalog.require(modelId);
|
|
8727
9262
|
if (entry.type !== "text") return entry.adapter;
|
|
@@ -8847,6 +9382,7 @@ export {
|
|
|
8847
9382
|
SURFACES2 as SURFACES,
|
|
8848
9383
|
SurfaceSchema,
|
|
8849
9384
|
VIDEO_INPUT_SPEC_KEYS,
|
|
9385
|
+
VIDEO_TOOL_MODELS,
|
|
8850
9386
|
adapterServesType,
|
|
8851
9387
|
aiSdkTextAdapter,
|
|
8852
9388
|
arkAdapter,
|
|
@@ -8860,6 +9396,7 @@ export {
|
|
|
8860
9396
|
describeThrown,
|
|
8861
9397
|
generateImage as experimental_generateImage,
|
|
8862
9398
|
falAdapter,
|
|
9399
|
+
falWebhookBodySchema,
|
|
8863
9400
|
fileCatalogCache,
|
|
8864
9401
|
generateAudio,
|
|
8865
9402
|
generateImage,
|
|
@@ -8884,6 +9421,7 @@ export {
|
|
|
8884
9421
|
normalizeExposure,
|
|
8885
9422
|
openaiImageAdapter,
|
|
8886
9423
|
passthroughTextModel,
|
|
9424
|
+
planVideoTool,
|
|
8887
9425
|
pollUntil,
|
|
8888
9426
|
prepareMediaPart,
|
|
8889
9427
|
primeCatalog,
|
|
@@ -8891,6 +9429,7 @@ export {
|
|
|
8891
9429
|
readErrorBody,
|
|
8892
9430
|
replicateAdapter,
|
|
8893
9431
|
resetLiveCatalog,
|
|
9432
|
+
resolutionTier,
|
|
8894
9433
|
resolveAudioOptions,
|
|
8895
9434
|
resolveImageOptions,
|
|
8896
9435
|
resolveKeys,
|
|
@@ -8904,6 +9443,7 @@ export {
|
|
|
8904
9443
|
toGeneratedImage,
|
|
8905
9444
|
validateInputSpec,
|
|
8906
9445
|
videoLengthViolation,
|
|
9446
|
+
videoToolConstraints,
|
|
8907
9447
|
withRetry,
|
|
8908
9448
|
xaiVideoAdapter
|
|
8909
9449
|
};
|